added gl coordinates option to box

This commit is contained in:
frank 2021-09-06 22:11:56 -04:00
parent ada139c26f
commit 18f83968f3
6 changed files with 110 additions and 45 deletions

View File

@ -2,17 +2,27 @@
#include "Segment.hpp"
#include "Box.hpp"
/* Construct a Box by giving the (x, y) coordinate of the NW point and the size as a 2D vector (width, height) */
Box::Box(const glm::vec2& nw, const glm::vec2& size)
/* 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 bottom left is (0, 0) rather than the default
* case where the top left is (0, 0). */
Box::Box(const glm::vec2& corner, const glm::vec2& size, bool use_gl_coordinates)
{
x = nw.x;
y = nw.y;
x = corner.x;
y = corner.y;
w = size.x;
h = size.y;
this->use_gl_coordinates = 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) : Box({rect.x, rect.y}, {rect.w, rect.h}) {}
Box::Box(const SDL_Rect& rect, bool use_gl_coordinates) : Box({rect.x, rect.y}, {rect.w, rect.h}, use_gl_coordinates) {}
/* Returns true if GL coordinate mode was set, meaning the lower left is (0, 0), and coordinates go up from there.
* Otherwise, returns false, meaning SDL mode is set, so the top left is (0, 0), and coordinates go down from there. */
bool Box::gl() const
{
return use_gl_coordinates;
}
/* Return the width */
float Box::width() const
@ -72,7 +82,16 @@ float Box::area() const
/* Return the y coordinate representing the top of the box */
float Box::top() const
{
return y;
/* if lower left is (0, 0), use the bottom to determine this value */
if (gl())
{
return bottom() + height();
}
/* otherwise use the corner Y-coordinate */
else
{
return y;
}
}
/* Return the x coordinate representing the right side of the box */
@ -84,7 +103,16 @@ float Box::right() const
/* Return the y coordinate representing the bottom of the box */
float Box::bottom() const
{
return top() + height();
/* if the lower left is (0, 0), use the stored Y-coordinate */
if (gl())
{
return y;
}
/* otherwise use the top to determine the bottom value */
else
{
return top() + height();
}
}
/* Return the x coordinate representing the left side of the box */
@ -96,13 +124,22 @@ float Box::left() const
/* Return the x component of the center coordinates */
float Box::cx() const
{
return left() + width() / 2;
return left() + width() / 2.0f;
}
/* Return the y component of the center coordinates */
float Box::cy() const
{
return top() + height() / 2;
/* if the lower left is (0, 0), add from the bottom */
if (gl())
{
return bottom() + height() / 2.0f;
}
/* otherwise add from the top */
else
{
return top() + height() / 2.0f;
}
}
/* Set the y coordinate of the top of the box. If drag is set, the other sides of the box will remain in the
@ -110,13 +147,14 @@ float Box::cy() const
* same size, and the bottom location will change, moving the box but preserving the size. */
void Box::top(float top, bool drag)
{
float delta = top - this->top();
if (!drag)
{
y = top;
move({0, delta});
}
else
{
drag_top(top - this->top());
drag_top(delta);
}
}
@ -125,14 +163,13 @@ void Box::top(float top, bool drag)
void Box::drag_top(float delta)
{
float new_location = top() + delta;
if (new_location > bottom())
height(std::abs(bottom() - new_location));
if ((gl() && new_location < bottom()) || (!gl() && new_location > bottom()))
{
top(bottom());
height(new_location - top());
bottom(new_location);
}
else
{
height(bottom() - new_location);
top(new_location);
}
}
@ -187,10 +224,14 @@ void Box::drag_bottom(float delta)
{
float new_location = bottom() + delta;
height(std::abs(top() - new_location));
if (new_location < top())
if ((gl() && new_location > top()) || (!gl() && new_location < bottom()))
{
top(new_location);
}
else
{
bottom(new_location);
}
}
/* Set the x coordinate of the left side of the box. If drag is set, the other sides of the box will remain in the
@ -198,13 +239,14 @@ void Box::drag_bottom(float delta)
* same size, and the right location will change, moving the box but preserving the size. */
void Box::left(float left, bool drag)
{
float delta = left - this->left();
if (!drag)
{
x = left;
move({delta, 0});
}
else
{
drag_left(left - this->left());
drag_left(delta);
}
}
@ -226,15 +268,15 @@ void Box::drag_left(float delta)
}
/* Set the center x component */
void Box::cx(float x)
void Box::cx(float cx)
{
move({x - cx(), 0.0f});
move({cx - this->cx(), 0.0f});
}
/* Set the center y component */
void Box::cy(float y)
void Box::cy(float cy)
{
move({0.0f, y - cy()});
move({0.0f, cy - this->cy()});
}
/* Return the coordinates of the top left corner */
@ -282,13 +324,13 @@ glm::vec2 Box::sw() const
/* Return the coordinates of the center of the left edge */
glm::vec2 Box::west() const
{
return glm::vec2(left(), top() + height() / 2);
return glm::vec2(left(), top() + height() / 2.0f);
}
/* Return the center coordinates */
glm::vec2 Box::center() const
{
return glm::vec2(left() + width() / 2, top() + height() / 2);
return glm::vec2(left() + width() / 2.0f, top() + height() / 2.0f);
}
/* Move the box by specifying the top left corner coordinates */
@ -355,8 +397,10 @@ Box::operator SDL_Rect() const
/* Zero out the values of the box coordinates and size */
void Box::clear()
{
nw(glm::vec2(0, 0));
size(glm::vec2(0, 0));
x = 0;
y = 0;
w = 0;
h = 0;
}
/* Scale the box by multiplying size by {delta.x, delta.y}. If preserve center is set, the box will be scaled
@ -400,8 +444,8 @@ void Box::expand(float delta, bool preserve_center)
/* Move the box in the x and y plane by delta amount */
void Box::move(const glm::vec2& delta)
{
left(left() + delta.x);
top(top() + delta.y);
x += delta.x;
y += delta.y;
}
/* Return a copy of the original box, moved by delta amount in the x and y plane */
@ -416,14 +460,19 @@ Box Box::stamp(const glm::vec2& delta) const
* of the box, so if the sides are equal, it is considered inside. */
bool Box::fits(const Box& container) const
{
return !(top() < container.top() || right() > container.right() ||
bottom() > container.bottom() || left() < container.left());
return
!(
((gl() && top() > container.top()) || (!gl() && top() < container.top())) ||
right() > container.right() ||
((gl() && bottom() < container.bottom()) || (!gl() && bottom() > container.bottom())) ||
left() < container.left()
);
}
/* Removes any part of the box that is not inside the passed crop area box */
void Box::crop(const Box& area)
{
if (top() < area.top())
if ((gl() && top() > area.top()) || (!gl() && top() < area.top()))
{
top(area.top(), true);
}
@ -431,7 +480,7 @@ void Box::crop(const Box& area)
{
right(area.right(), true);
}
if (bottom() > area.bottom())
if ((gl() && bottom() < area.bottom()) || (!gl() && bottom() > area.bottom()))
{
bottom(area.bottom(), true);
}
@ -445,7 +494,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 >= top() && point.y <= bottom();
return point.x >= left() && point.x <= right() && point.y >= (gl() ? bottom() : top()) && point.y <= (gl() ? top() : bottom());
}
/* Returns true if the line segment intersects the box, false otherwise. If intersection is passed and there is a
@ -492,12 +541,22 @@ bool Box::collide(const Segment& segment, glm::vec2& intersection) const
* the box representing the area where the two boxes overlap. */
bool Box::collide(const Box& box, Box* overlap) const
{
float top = std::max(this->top(), box.top());
float top, bottom, h;
if (gl())
{
top = std::min(this->top(), box.top());
bottom = std::max(this->bottom(), box.bottom());
h = top - bottom;
}
else
{
top = std::max(this->top(), box.top());
bottom = std::min(this->bottom(), box.bottom());
h = bottom - top;
}
float right = std::min(this->right(), box.right());
float bottom = std::min(this->bottom(), box.bottom());
float left = std::max(this->left(), box.left());
float w = right - left;
float h = bottom - top;
bool collide = w > 0 && h > 0;
if (collide && overlap != nullptr)
{

View File

@ -16,10 +16,15 @@ class Segment;
class Box : public SDL_FRect
{
private:
bool use_gl_coordinates;
public:
Box(const glm::vec2& = {0, 0}, const glm::vec2& = {0, 0});
Box(const SDL_Rect&);
Box(const glm::vec2& = {0, 0}, const glm::vec2& = {0, 0}, bool = false);
Box(const SDL_Rect&, bool = false);
bool gl() const;
float width() const;
void width(float);
float height() const;

View File

@ -15,10 +15,11 @@ glm::ivec2 Display::window_size() const
return size;
}
/* Return the window dimensions as a Box object */
Box Display::window_box() const
/* 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 Box(glm::vec2(0, 0), window_size());
return Box(glm::vec2(0, 0), window_size(), use_gl_coordinates);
}
/* Get the pixel format of display at specified index (defaults to index 0) */

View File

@ -23,7 +23,7 @@ public:
Display(Node*);
glm::ivec2 window_size() const;
Uint32 pixel_format(int = 0) const;
Box window_box() const;
Box window_box(bool = false) 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;

View File

@ -99,9 +99,9 @@ const Game* Node::get_root() const
return dynamic_cast<const Game*>(r);
}
Box Node::window_box()
Box Node::window_box(bool use_gl_coordinates)
{
return get_display().window_box();
return get_display().window_box(use_gl_coordinates);
}
void Node::suppress_input()

View File

@ -43,7 +43,7 @@ public:
Input& get_input();
Audio& get_audio();
const Game* get_root() const;
Box window_box();
Box window_box(bool = false);
void suppress_input();
void suppress_input_temporarily(int = 0);
void unsuppress_input();