Skip to content

Commit

Permalink
[SUTK] Bug Fixes and Added AnchorRect to specify anchors relative to …
Browse files Browse the repository at this point in the history
…the parent container
  • Loading branch information
ravi688 committed Jul 31, 2024
1 parent e0c3b2d commit d688d8a
Show file tree
Hide file tree
Showing 14 changed files with 299 additions and 27 deletions.
47 changes: 47 additions & 0 deletions sutk/include/sutk/AnchorRect.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
#pragma once

#include <sutk/defines.hpp> // for SUTK_API, and Rect2D

namespace SUTK
{
class Container;

// This class is derived from Container
class SUTK_API AnchorRect
{
private:
Rect2Df m_rect;
Rect2Df m_constraintRect;
Container& m_childRect;
Container& m_parentRect;
AnchorRect(Container& childRect, Container& parentRect) noexcept;

friend class Container;
// should be called by the parent container whenever its rect is resized or changes its position
void onParentResize(const Rect2Df& newRect, bool isPositionChanged, bool isSizeChanged) noexcept;
// should be called by the child container whenever its rect is resized or changes its position
void onChildResize(const Rect2Df& newRect, bool isPositionChanged, bool isSizeChanged) noexcept;

Rect2Df getUnnormalizedAnchorRect() noexcept;
void recalculateConstraints() noexcept;
public:

// getters
Rect2Df getRect() const noexcept { return m_rect; }

// setters

void setRect(Rect2Df rect) noexcept;

void setTopLeft(Vec2Df point) noexcept;
void setBottomRight(Vec2Df point) noexcept;

void setTopRight(Vec2Df point) noexcept;
void setBottomLeft(Vec2Df point) noexcept;

void extendTopLeft(Vec2Df disp) noexcept;
void extendTopRight(Vec2Df disp) noexcept;
void extendBottomRight(Vec2Df disp) noexcept;
void extendBottomLeft(Vec2Df disp) noexcept;
};
}
42 changes: 32 additions & 10 deletions sutk/include/sutk/Container.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
#include <sutk/UIDriver.hpp>

#include <sutk/IDebuggable.hpp> // for SUTK::IDebuggable class
#include <sutk/AnchorRect.hpp> // for SUTK::AnchorRect class

namespace SUTK
{
Expand All @@ -18,6 +19,7 @@ namespace SUTK
private:
std::vector<Container*> m_containers;
Rect2Df m_rect;
AnchorRect* m_anchorRect;
Container* m_parent;
RenderRectContainer* m_renderRectCont;
RenderRect* m_renderRect;
Expand All @@ -27,6 +29,7 @@ namespace SUTK
protected:
// this can only be called by SUTK::UIDriver
Container(SUTK::UIDriver& driver, Container* parent = NULL);
virtual ~Container();

friend class UIDriver;

Expand All @@ -38,27 +41,46 @@ namespace SUTK
// called after removing this container from 'parent' container
virtual void onRemove(Container* parent);
// called after rect of this container has been resized
// isPositionChanged is set to true if position has been modified
// isPositionChanged is set to true if position has been modified or has changed its position
// isSizeChanged is set to true if size has been modified
virtual void onResize(const Rect2Df& newRect, bool isPositionChanged, bool isSizeChanged);
// called after rect of its parent container has been resized or has changed its position
virtual void onParentResize(const Rect2Df& newRect, bool isPositionChanged, bool isSizeChanged);
public:

// IMPLEMENTATION of IDebuggable
virtual void enableDebug(bool isEnable = false) noexcept override;

// parent getters
Container* getParent() { return m_parent; }
void setParent(Container* parent) noexcept;
const Container* getParent() const { return m_parent; }
// parent setters
void setParent(Container* parent) noexcept;

// rect getters
Rect2Df getRect() const { return m_rect; }
Vec2Df getPosition() const noexcept { return m_rect.getPosition(); }
Vec2Df getSize() const noexcept { return m_rect.getSize(); }
// rect setters
virtual void setRect(Rect2Df rect) { m_rect = rect; onResize(rect, true, true); }
void setPosition(Vec2Df pos) { m_rect.setPosition(pos); onResize(m_rect, true, false); }
void setSize(Vec2Df size) { m_rect.setSize(size); onResize(m_rect, false, true); }

// anchor rect getters
AnchorRect* getAnchorRect() const noexcept { return m_anchorRect; }

// coordinate conversion functions

// converts global coordinates (in centimeters) to local coordinates (in centimeters) in its rect
Vec2Df getScreenCoordsToLocalCoords(Vec2Df screenCoords) const;
// converts local coordinates in its rect (in centimeters) to global coordinates (in centimeters)
Vec2Df getLocalCoordsToScreenCoords(Vec2Df localCoords) const;
virtual void setRect(Rect2Df rect) { m_rect = rect; onResize(rect, true, true); }
void setPosition(Vec2Df pos) { m_rect.setPosition(pos); onResize(m_rect, true, false); }
Vec2Df getPosition() const noexcept { return m_rect.getPosition(); }
void setSize(Vec2Df size) { m_rect.setSize(size); onResize(m_rect, false, true); }
Vec2Df getSize() const noexcept { return m_rect.getSize(); }

// addition and removal of child containers

// adds a new container as a child to this container
virtual void add(Container* container);
// removes an existing container from this container
virtual void remove(Container* container);

// IMPLEMENTATION of IDebuggable
virtual void enableDebug(bool isEnable = false) noexcept override;
};
}
4 changes: 2 additions & 2 deletions sutk/include/sutk/Geometry.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -77,9 +77,9 @@ namespace SUTK

Topology getTopology() const noexcept { return m_topology; }

VertexPositionArray& getVertexPositionArray() { return m_positionArrayInfo.array; }
VertexPositionArray& getVertexPositionArrayForWrite() { m_positionArrayInfo.isModified = true; return m_positionArrayInfo.array; }
const VertexPositionArray& getVertexPositionArray() const { return m_positionArrayInfo.array; }
VertexIndexArray& getVertexIndexArray() { return m_indexArrayInfo.array; }
VertexIndexArray& getVertexIndexArrayForWrite() { m_indexArrayInfo.isModified = true; return m_indexArrayInfo.array; }
const VertexIndexArray& getVertexIndexArray() const { return m_indexArrayInfo.array; }

bool isVertexIndexArrayModified() const noexcept { return m_indexArrayInfo.isModified; }
Expand Down
1 change: 1 addition & 0 deletions sutk/include/sutk/RenderRectContainer.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ namespace SUTK

protected:
virtual void onAdd(Container* parent) override;
virtual void onParentResize(const Rect2Df& newRect, bool isPositionChanged, bool isSizeChanged) override;
virtual void onResize(const Rect2Df& newRect, bool isPositionChanged, bool isSizeChanged) override;

public:
Expand Down
1 change: 1 addition & 0 deletions sutk/include/sutk/TextContainer.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ namespace SUTK
protected:
virtual void onAdd(Container* parent) override;
virtual void onResize(const Rect2Df& newRect, bool isPositionChanged, bool isSizeChanged) override;
virtual void onParentResize(const Rect2Df& newRect, bool isPositionChanged, bool isSizeChanged) override;

public:

Expand Down
55 changes: 55 additions & 0 deletions sutk/include/sutk/defines.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,23 @@ namespace SUTK

constexpr Rect2D() noexcept : x(0), y(0), width(0), height(0) { }
constexpr Rect2D(T _x, T _y, T _width, T _height) noexcept : x(_x), y(_y), width(_width), height(_height) { }
constexpr Rect2D(Vec2D<T> pos, Vec2D<T> size) noexcept : x(pos.x), y(pos.y), width(size.width), height(size.height) { }

// (u + du) - Constraint
// du + r
// Constraint: u - r

// this is being used in calculate constraints between two rects
Rect2D<T> operator-(const Rect2D<T>& rect) const noexcept
{
constexpr auto neg = NegativeSign<T>::value;
return { x + neg * rect.x, y + neg * rect.y, width + neg * rect.width, height + neg * rect.height };
}

Rect2D<T> operator+(const Rect2D<T>& rect) const noexcept
{
return { x + rect.x, y + rect.y, width + rect.width, height + rect.height };
}

Vec2D<T> getPosition() const noexcept { return { x, y }; }
Vec2D<T> getSize() const noexcept { return { width, height }; }
Expand Down Expand Up @@ -178,6 +195,44 @@ namespace SUTK
height = size.height;
}

// returns true, if either of width and height is negative
// otherwise false.
bool isInverted() const noexcept
{
return ((NegativeSign<T>::value * width) > 0) || ((NegativeSign<T>::value * height) > 0);
}

void setTopLeft(Vec2D<T> point) noexcept
{
auto bottomRight = getBottomRight();
x = point.x;
y = point.y;
width = bottomRight.x - point.x;
height = bottomRight.y - point.y;
}

void setBottomRight(Vec2D<T> point) noexcept
{
width = point.x - x;
height = point.y - y;
}

void setTopRight(Vec2D<T> point) noexcept
{
T bottomLeftYCoord = y + height;
y = point.y;
width = point.x - x;
height = bottomLeftYCoord - point.y;
}

void setBottomLeft(Vec2D<T> point) noexcept
{
T bottomRightXCoord = x + width;
x = point.x;
height = point.y - y;
width = bottomRightXCoord - point.x;
}

void extendTopLeft(Vec2D<T> disp) noexcept
{
extendTop(disp.y);
Expand Down
96 changes: 96 additions & 0 deletions sutk/source/AnchorRect.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
#include <sutk/AnchorRect.hpp>
#include <sutk/Container.hpp> // for SUTK::Container member functions

namespace SUTK
{
AnchorRect::AnchorRect(Container& childRect, Container& parentRect) noexcept : m_childRect(childRect), m_parentRect(parentRect)
{
// NOTE: initially the anchor rect is degenerate (width and height both is zero) and has position as { 0, 0 }

recalculateConstraints();
}

Rect2Df AnchorRect::getUnnormalizedAnchorRect() noexcept
{
Vec2Df parentSize = m_parentRect.getSize();
// calculate unnormalized anchor rect in the parent rect's local coordinates
Rect2Df anchorRect { m_rect.getPosition() * parentSize, m_rect.getSize() * parentSize };
return anchorRect;
}

void AnchorRect::recalculateConstraints() noexcept
{
Rect2Df anchorRect = getUnnormalizedAnchorRect();
// signed difference is the constraint
m_constraintRect = anchorRect - m_childRect.getRect();
}

void AnchorRect::onParentResize(const Rect2Df& newRect, bool isPositionChanged, bool isSizeChanged) noexcept
{
Rect2Df anchorRect = getUnnormalizedAnchorRect();
Rect2Df newChildRect = anchorRect - m_constraintRect;
m_childRect.setRect(newChildRect);
}

void AnchorRect::onChildResize(const Rect2Df& newRect, bool isPositionChanged, bool isSizeChanged) noexcept
{
recalculateConstraints();
}

void AnchorRect::setRect(Rect2Df rect) noexcept
{
m_rect = rect;
recalculateConstraints();
}

void AnchorRect::setTopLeft(Vec2Df point) noexcept
{
m_rect.setTopLeft(point);
recalculateConstraints();
}

void AnchorRect::setBottomRight(Vec2Df point) noexcept
{
m_rect.setBottomRight(point);
recalculateConstraints();
}


void AnchorRect::setTopRight(Vec2Df point) noexcept
{
m_rect.setTopRight(point);
recalculateConstraints();
}

void AnchorRect::setBottomLeft(Vec2Df point) noexcept
{
m_rect.setBottomLeft(point);
recalculateConstraints();
}


void AnchorRect::extendTopLeft(Vec2Df disp) noexcept
{
m_rect.extendTopLeft(disp);
recalculateConstraints();
}

void AnchorRect::extendTopRight(Vec2Df disp) noexcept
{
m_rect.extendTopRight(disp);
recalculateConstraints();
}

void AnchorRect::extendBottomRight(Vec2Df disp) noexcept
{
m_rect.extendBottomRight(disp);
recalculateConstraints();
}

void AnchorRect::extendBottomLeft(Vec2Df disp) noexcept
{
m_rect.extendBottomLeft(disp);
recalculateConstraints();
}

}
38 changes: 33 additions & 5 deletions sutk/source/Container.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,24 @@

namespace SUTK
{
Container::Container(SUTK::UIDriver& driver, Container* parent) : UIDriverObject(driver), m_rect({0, 0, 100, 100}), m_parent(NULL), m_renderRectCont(NULL), m_renderRect(NULL), m_isDebug(false)
Container::Container(SUTK::UIDriver& driver, Container* parent) :
UIDriverObject(driver),
m_rect({0, 0, 5.0f, 5.0f}),
m_anchorRect(NULL),
m_parent(NULL),
m_renderRectCont(NULL),
m_renderRect(NULL),
m_isDebug(false)
{
setParent(parent);
if(parent != NULL)
m_anchorRect = new AnchorRect(*this, *parent);
}

Container::~Container()
{
if(m_anchorRect != NULL)
delete m_anchorRect;
}

void Container::setParent(Container* parent) noexcept
Expand Down Expand Up @@ -74,14 +89,28 @@ namespace SUTK
container->setParent(NULL);
}

void Container::onParentResize(const Rect2Df& newRect, bool isPositionChanged, bool isSizeChanged)
{
if(m_anchorRect != NULL)
m_anchorRect->onParentResize(newRect, isPositionChanged, isSizeChanged);
}

void Container::onResize(const Rect2Df& newRect, bool isPositionChanged, bool isSizeChanged)
{
// if this container is resized and update the renderRect's size as well
if(m_renderRectCont != NULL)
{
_assert(m_isDebug);
m_renderRectCont->setRect({ 0, 0, getRect().width, getRect().height });
if(isSizeChanged)
m_renderRectCont->setRect({ 0, 0, newRect.width, newRect.height });
}

if(m_anchorRect != NULL)
m_anchorRect->onChildResize(newRect, isPositionChanged, isSizeChanged);

// inform the child containers that parent's rect has been resized or has changed its position
for(Container*& container : m_containers)
container->onParentResize(newRect, isPositionChanged, isSizeChanged);
}

void Container::enableDebug(bool isEnable) noexcept
Expand All @@ -95,10 +124,9 @@ namespace SUTK

// create SUTKU::RenderRect and establish parent-child link with SUTK::RenderRectContainer just created
m_renderRect = getUIDriver().createRenderable<RenderRect>(m_renderRectCont);
m_renderRectCont->setRenderRect(m_renderRect);

m_renderRectCont->setRect({ 0, 0, getRect().width, getRect().height });
m_renderRect->setThickness(0.05f);

m_renderRectCont->setRenderRect(m_renderRect);
}
m_isDebug = true;
}
Expand Down
Loading

0 comments on commit d688d8a

Please sign in to comment.