Display object can return ndc coordinates from a pixel coordinate box
This commit is contained in:
parent
03d179eed4
commit
54cf01246b
56
src/Box.cpp
56
src/Box.cpp
|
@ -1,6 +1,6 @@
|
|||
/* /\ +--------------------------------------------------------------+
|
||||
____/ \____ /| - zlib/MIT/Unlicenced game framework licensed to freely use, |
|
||||
\ / / | copy, modify and sell without restriction |
|
||||
\ / / | copy, and modify without restriction |
|
||||
+--\ ^__^ /--+ | |
|
||||
| ~/ \~ | | - originally created at [http://nugget.fun] |
|
||||
| ~~~~~~~~~~~~ | +--------------------------------------------------------------+
|
||||
|
@ -10,33 +10,37 @@
|
|||
|
||||
#include "Box.hpp"
|
||||
|
||||
/* Construct a Box by giving a corner coordinate (top left in SDL coordinates, bottom left in GL coordinates)
|
||||
* and size (as width, height). The gl argument indicates that the Y-coordinate increases from the bottom of
|
||||
/* Construct a Box by giving a corner coordinate (top left if Y-axis is not inverted, bottom left otherwise) and
|
||||
* size (as width, height). The invert_y argument indicates that the Y-coordinate increases from the bottom of
|
||||
* the screen to the top rather than the default case where it increases from the top to the bottom. */
|
||||
Box::Box(const glm::vec2& corner, const glm::vec2& size, bool use_gl_coordinates)
|
||||
Box::Box(const glm::vec2& corner, const glm::vec2& size, bool invert_y)
|
||||
{
|
||||
x = corner.x;
|
||||
y = corner.y;
|
||||
w = size.x;
|
||||
h = size.y;
|
||||
gl(use_gl_coordinates);
|
||||
this->invert_y(invert_y);
|
||||
}
|
||||
|
||||
/* Construct a Box by passing an SDL_Rect struct, which is of the form {x, y, w, h} and limited to int arguments */
|
||||
Box::Box(const SDL_Rect& rect, bool use_gl_coordinates) : Box({rect.x, rect.y}, {rect.w, rect.h}, use_gl_coordinates) {}
|
||||
/* Construct a Box from float arguments: x, y, width, height. If invert_y is set, the Y-axis increases from bottom to
|
||||
* top instead of top to bottom. */
|
||||
Box::Box(float x, float y, float width, float height, bool invert_y) : Box({x, y}, {width, height}, invert_y) {}
|
||||
|
||||
/* Set GL mode to true, meaning the Y-coordinate increases from the bottom of the screen to the top, or false,
|
||||
* meaning SDL mode where the Y-coordinate increases from the top of the screen to the bottom. */
|
||||
void Box::gl(bool use_gl_coordinates)
|
||||
/* Construct a Box by passing an SDL_Rect struct, which is of the form {x, y, w, h} and limited to int arguments. */
|
||||
Box::Box(const SDL_Rect& rect, bool invert_y) : Box({rect.x, rect.y}, {rect.w, rect.h}, invert_y) {}
|
||||
|
||||
/* Set inverted Y mode to true, meaning the Y-coordinate increases from the bottom to the top, or false, meaning the
|
||||
* Y-coordinate increases from the top to the bottom. */
|
||||
void Box::invert_y(bool invert)
|
||||
{
|
||||
this->use_gl_coordinates = use_gl_coordinates;
|
||||
invert_y_state = invert;
|
||||
}
|
||||
|
||||
/* Returns true if GL coordinate mode was set, meaning the Y-coordinate increases from the bottom of the screen to
|
||||
* the top, or false, meaning SDL mode where the Y-coordinate increases from the top of the screen to the bottom. */
|
||||
bool Box::gl() const
|
||||
/* Returns true if Y-axis was set to inverted, meaning the Y-coordinate increases from the bottom to the top, or false,
|
||||
* meaning Y-coordinate increases from the top to the bottom. */
|
||||
bool Box::inverted_y() const
|
||||
{
|
||||
return use_gl_coordinates;
|
||||
return invert_y_state;
|
||||
}
|
||||
|
||||
/* Return the width */
|
||||
|
@ -98,7 +102,7 @@ float Box::area() const
|
|||
float Box::top() const
|
||||
{
|
||||
/* if Y-coordinate increases from bottom to top, use the bottom to determine this value */
|
||||
if (gl())
|
||||
if (inverted_y())
|
||||
{
|
||||
return bottom() + height();
|
||||
}
|
||||
|
@ -119,7 +123,7 @@ float Box::right() const
|
|||
float Box::bottom() const
|
||||
{
|
||||
/* if Y-coordinate increases from bottom to top, use the stored Y-coordinate */
|
||||
if (gl())
|
||||
if (inverted_y())
|
||||
{
|
||||
return y;
|
||||
}
|
||||
|
@ -146,7 +150,7 @@ float Box::cx() const
|
|||
float Box::cy() const
|
||||
{
|
||||
/* if Y-coordinate increases from bottom to top, add from the bottom */
|
||||
if (gl())
|
||||
if (inverted_y())
|
||||
{
|
||||
return bottom() + height() / 2.0f;
|
||||
}
|
||||
|
@ -179,7 +183,7 @@ void Box::drag_top(float delta)
|
|||
{
|
||||
float new_location = top() + delta;
|
||||
height(std::abs(bottom() - new_location));
|
||||
if ((gl() && new_location < bottom()) || (!gl() && new_location > bottom()))
|
||||
if ((inverted_y() && new_location < bottom()) || (!inverted_y() && new_location > bottom()))
|
||||
{
|
||||
bottom(new_location);
|
||||
}
|
||||
|
@ -239,7 +243,7 @@ void Box::drag_bottom(float delta)
|
|||
{
|
||||
float new_location = bottom() + delta;
|
||||
height(std::abs(top() - new_location));
|
||||
if ((gl() && new_location > top()) || (!gl() && new_location < bottom()))
|
||||
if ((inverted_y() && new_location > top()) || (!inverted_y() && new_location < bottom()))
|
||||
{
|
||||
top(new_location);
|
||||
}
|
||||
|
@ -477,9 +481,9 @@ bool Box::fits(const Box& container) const
|
|||
{
|
||||
return
|
||||
!(
|
||||
((gl() && top() > container.top()) || (!gl() && top() < container.top())) ||
|
||||
((inverted_y() && top() > container.top()) || (!inverted_y() && top() < container.top())) ||
|
||||
right() > container.right() ||
|
||||
((gl() && bottom() < container.bottom()) || (!gl() && bottom() > container.bottom())) ||
|
||||
((inverted_y() && bottom() < container.bottom()) || (!inverted_y() && bottom() > container.bottom())) ||
|
||||
left() < container.left()
|
||||
);
|
||||
}
|
||||
|
@ -487,7 +491,7 @@ bool Box::fits(const Box& container) const
|
|||
/* Removes any part of the box that is not inside the passed crop area box */
|
||||
void Box::crop(const Box& area)
|
||||
{
|
||||
if ((gl() && top() > area.top()) || (!gl() && top() < area.top()))
|
||||
if ((inverted_y() && top() > area.top()) || (!inverted_y() && top() < area.top()))
|
||||
{
|
||||
top(area.top(), true);
|
||||
}
|
||||
|
@ -495,7 +499,7 @@ void Box::crop(const Box& area)
|
|||
{
|
||||
right(area.right(), true);
|
||||
}
|
||||
if ((gl() && bottom() < area.bottom()) || (!gl() && bottom() > area.bottom()))
|
||||
if ((inverted_y() && bottom() < area.bottom()) || (!inverted_y() && bottom() > area.bottom()))
|
||||
{
|
||||
bottom(area.bottom(), true);
|
||||
}
|
||||
|
@ -509,7 +513,7 @@ void Box::crop(const Box& area)
|
|||
* will return true. */
|
||||
bool Box::collide(const glm::vec2& point) const
|
||||
{
|
||||
return point.x >= left() && point.x <= right() && point.y >= (gl() ? bottom() : top()) && point.y <= (gl() ? top() : bottom());
|
||||
return point.x >= left() && point.x <= right() && point.y >= (inverted_y() ? bottom() : top()) && point.y <= (inverted_y() ? top() : bottom());
|
||||
}
|
||||
|
||||
/* Returns true if the line segment intersects the box, false otherwise. If intersection is passed and there is a
|
||||
|
@ -557,7 +561,7 @@ bool Box::collide(const Segment& segment, glm::vec2& intersection) const
|
|||
bool Box::collide(const Box& box, Box* overlap) const
|
||||
{
|
||||
float top, bottom, h;
|
||||
if (gl())
|
||||
if (inverted_y())
|
||||
{
|
||||
top = std::min(this->top(), box.top());
|
||||
bottom = std::max(this->bottom(), box.bottom());
|
||||
|
|
|
@ -28,14 +28,15 @@ class Box : public SDL_FRect
|
|||
|
||||
private:
|
||||
|
||||
bool use_gl_coordinates;
|
||||
bool invert_y_state = false;
|
||||
|
||||
public:
|
||||
|
||||
Box(const glm::vec2& = {0, 0}, const glm::vec2& = {0, 0}, bool = false);
|
||||
Box(float, float, float, float, bool = false);
|
||||
Box(const SDL_Rect&, bool = false);
|
||||
void gl(bool);
|
||||
bool gl() const;
|
||||
void invert_y(bool);
|
||||
bool inverted_y() const;
|
||||
float width() const;
|
||||
void width(float);
|
||||
float height() const;
|
||||
|
|
|
@ -14,11 +14,23 @@ glm::ivec2 Display::window_size() const
|
|||
return size;
|
||||
}
|
||||
|
||||
/* Return the window dimensions as a Box object. If use_gl_coordinates is set, the lower left will be (0, 0).
|
||||
* Otherwise, the top left will be (0, 0). */
|
||||
Box Display::window_box(bool use_gl_coordinates) const
|
||||
/* Return the window dimensions in pixels as a Box object. If invert_y is set, the lower left will be (0, 0).
|
||||
* Otherwise, the top left will be (0, 0). Setting invert will cause the values to be compatible with
|
||||
* glViewport. */
|
||||
Box Display::window_box(bool invert_y) const
|
||||
{
|
||||
return Box(glm::vec2(0, 0), window_size(), use_gl_coordinates);
|
||||
return Box(glm::vec2(0, 0), window_size(), invert_y);
|
||||
}
|
||||
|
||||
/* Return a box object with NDC coordinates of the window subsection. The subsection should be specified in
|
||||
* pixel coordinates. */
|
||||
Box Display::ndc_subsection(const Box& subsection) const
|
||||
{
|
||||
Box ndc_subsection = ndc;
|
||||
Box window = window_box(subsection.inverted_y());
|
||||
ndc_subsection.move({(subsection.x - window.x) / window.width() * 2.0f, (subsection.y - window.y) / window.height() * 2.0f});
|
||||
ndc_subsection.size({subsection.width() / window.width() * 2.0f, subsection.height() / window.height() * 2.0f});
|
||||
return ndc_subsection;
|
||||
}
|
||||
|
||||
/* Get the pixel format of display at specified index (defaults to index 0) */
|
||||
|
@ -45,18 +57,22 @@ void Display::screen_pixels(unsigned char* pixels, int w, int h, int x, int y) c
|
|||
if (get_root()->is_gl_context)
|
||||
{
|
||||
GLenum format;
|
||||
#if SDL_BYTEORDER == SDL_BIG_ENDIAN
|
||||
format = GL_BGRA;
|
||||
#else
|
||||
format = GL_RGBA;
|
||||
#endif
|
||||
if constexpr (SDL_BYTEORDER == SDL_BIG_ENDIAN)
|
||||
{
|
||||
format = GL_BGRA;
|
||||
}
|
||||
else
|
||||
{
|
||||
format = GL_RGBA;
|
||||
}
|
||||
glReadBuffer(GL_FRONT);
|
||||
glReadPixels(x, y, w, h, format, GL_UNSIGNED_BYTE, pixels);
|
||||
// SDL_Log("(%i, %i, %i) (%i, %i, %i, %i)",
|
||||
// glCheckFramebufferStatus(GL_FRAMEBUFFER),
|
||||
// glCheckFramebufferStatus(GL_READ_FRAMEBUFFER),
|
||||
// glCheckFramebufferStatus(GL_DRAW_FRAMEBUFFER),
|
||||
// pixels[0], pixels[1], pixels[2], pixels[3]);
|
||||
/* Debug statement showing the framebuffer status and first pixel read */
|
||||
std::ostringstream message;
|
||||
message << "read framebuffer status: " << glCheckFramebufferStatus(GL_READ_FRAMEBUFFER) <<
|
||||
", draw framebuffer status: " << glCheckFramebufferStatus(GL_DRAW_FRAMEBUFFER) <<
|
||||
", upper left screen pixel value read: " << pixels[0] << " " << pixels[1] << " " << pixels[2] << " " << pixels[3];
|
||||
sb::Log::log(message, sb::Log::DEBUG);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
@ -17,11 +17,13 @@ class Display : public Node
|
|||
public:
|
||||
|
||||
const static int bpp = 32;
|
||||
inline const static Box ndc {-1.0f, -1.0f, 2.0f, 2.0f, true};
|
||||
|
||||
Display(Node*);
|
||||
glm::ivec2 window_size() const;
|
||||
Uint32 pixel_format(int = 0) const;
|
||||
Box window_box(bool = false) const;
|
||||
Box ndc_subsection(const Box&) const;
|
||||
void screen_pixels(unsigned char*, int, int, int = 0, int = 0) const;
|
||||
SDL_Surface* screen_surface() const;
|
||||
SDL_Surface* screen_surface_from_pixels(unsigned char*, bool) const;
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/* /\ +--------------------------------------------------------------+
|
||||
____/ \____ /| - zlib/MIT/Unlicenced game framework licensed to freely use, |
|
||||
\ / / | copy, modify and sell without restriction |
|
||||
\ / / | copy, and modify without restriction |
|
||||
+--\ ^__^ /--+ | |
|
||||
| ~/ \~ | | - originally created at [http://nugget.fun] |
|
||||
| ~~~~~~~~~~~~ | +--------------------------------------------------------------+
|
||||
|
|
16
src/Node.cpp
16
src/Node.cpp
|
@ -1,3 +1,13 @@
|
|||
/* /\ +--------------------------------------------------------------+
|
||||
____/ \____ /| - zlib/MIT/Unlicenced game framework licensed to freely use, |
|
||||
\ / / | copy, and modify without restriction |
|
||||
+--\ ^__^ /--+ | |
|
||||
| ~/ \~ | | - originally created at [http://nugget.fun] |
|
||||
| ~~~~~~~~~~~~ | +--------------------------------------------------------------+
|
||||
| SPACE ~~~~~ | /
|
||||
| ~~~~~~~ BOX |/
|
||||
+-------------*/
|
||||
|
||||
#include "Configuration.hpp"
|
||||
#include "Delegate.hpp"
|
||||
#include "Display.hpp"
|
||||
|
@ -99,9 +109,11 @@ const Game* Node::get_root() const
|
|||
return dynamic_cast<const Game*>(r);
|
||||
}
|
||||
|
||||
Box Node::window_box(bool use_gl_coordinates)
|
||||
/* Get the window dimensions in pixels as a box object. If invert_y is set, the bottom left will be (0, 0).
|
||||
* Otherwise, it the top left will be (0, 0). */
|
||||
Box Node::window_box(bool invert_y)
|
||||
{
|
||||
return get_display().window_box(use_gl_coordinates);
|
||||
return get_display().window_box(invert_y);
|
||||
}
|
||||
|
||||
void Node::suppress_input()
|
||||
|
|
10
src/Node.hpp
10
src/Node.hpp
|
@ -1,3 +1,13 @@
|
|||
/* /\ +--------------------------------------------------------------+
|
||||
____/ \____ /| - zlib/MIT/Unlicenced game framework licensed to freely use, |
|
||||
\ / / | copy, and modify without restriction |
|
||||
+--\ ^__^ /--+ | |
|
||||
| ~/ \~ | | - originally created at [http://nugget.fun] |
|
||||
| ~~~~~~~~~~~~ | +--------------------------------------------------------------+
|
||||
| SPACE ~~~~~ | /
|
||||
| ~~~~~~~ BOX |/
|
||||
+-------------*/
|
||||
|
||||
#ifndef SB_NODE_H_
|
||||
#define SB_NODE_H_
|
||||
|
||||
|
|
Loading…
Reference in New Issue