added gl coordinates option to box
This commit is contained in:
parent
ada139c26f
commit
18f83968f3
131
src/Box.cpp
131
src/Box.cpp
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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) */
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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();
|
||||
|
|
Loading…
Reference in New Issue