DataModel partial implementation
This commit is contained in:
@@ -1,8 +1,50 @@
|
||||
//
|
||||
// Created by dawsh on 7/10/24.
|
||||
//
|
||||
|
||||
#ifndef RECT_HPP
|
||||
#define RECT_HPP
|
||||
|
||||
#endif //RECT_HPP
|
||||
#pragma once
|
||||
|
||||
#include <JUI/Widget.hpp>
|
||||
|
||||
namespace JUI {
|
||||
/// The Rect Widget Class
|
||||
/// Renders a rectangle or "box" and also serves as a vesatile container for laying out other widgets.
|
||||
class Rect : public Widget {
|
||||
public: /// Constructors
|
||||
/// The default constructor.
|
||||
Rect();
|
||||
Rect(Widget* parent);
|
||||
~Rect() override {}
|
||||
public:
|
||||
Event<Vector2> MouseEnter;
|
||||
Event<Vector2> MouseExit;
|
||||
Event<Vector2> MousePress;
|
||||
Event<Vector2> MouseRelease;
|
||||
|
||||
public:
|
||||
void Draw() override;
|
||||
void Update(float delta) override;
|
||||
bool IsMouseInside() const;
|
||||
|
||||
Color4 GetBGColor() const;
|
||||
Color4 GetBorderColor() const;
|
||||
float GetBorderWidth() const;
|
||||
|
||||
|
||||
void SetBGColor(const Color4&);
|
||||
void SetBorderColor(const Color4&);
|
||||
void SetBorderWidth(float f);
|
||||
|
||||
|
||||
void SetCornerRounding(float radius);
|
||||
void SetCornerRounding(float tlRadius, float trRadius, float blRadius, float brRadius);
|
||||
void SetCornerRoundingTL(float radius);
|
||||
void SetCornerRoundingTR(float radius);
|
||||
void SetCornerRoundingBL(float radius);
|
||||
void SetCornerRoundingBR(float radius);
|
||||
|
||||
|
||||
void SetBorderStyling(const Color4& color, float width) {
|
||||
SetBorderColor(color);
|
||||
SetBorderWidth(width);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
@@ -4,10 +4,16 @@
|
||||
#include <vector>
|
||||
#include <J3ML/LinearAlgebra.h>
|
||||
#include <JUI/UDim2.hpp>
|
||||
#include <JGL/Color3.h>
|
||||
#include <JGL/Color4.h>
|
||||
|
||||
namespace JUI
|
||||
{
|
||||
|
||||
using namespace J3ML::Math;
|
||||
using namespace J3ML::LinearAlgebra;
|
||||
using namespace JGL;
|
||||
|
||||
class Widget
|
||||
{
|
||||
public:
|
||||
@@ -36,6 +42,30 @@ namespace JUI
|
||||
virtual float GetAbsoluteRotation() const;
|
||||
Widget* GetParent() const;
|
||||
|
||||
UDim2 GetPosition() const;
|
||||
|
||||
UDim2 GetSize() const;
|
||||
|
||||
void SetPosition(const UDim2 &pos);
|
||||
|
||||
void SetSize(const UDim2 &s);
|
||||
|
||||
void SetParent(Widget*);
|
||||
|
||||
bool IsDescendantOf(Widget *ancestor);
|
||||
|
||||
bool IsAncestorOf(Widget *descendant);
|
||||
|
||||
Vector2 GetAnchorPoint() const;
|
||||
|
||||
|
||||
UDim GetPaddingLeft() const;
|
||||
UDim GetPaddingTop() const;
|
||||
UDim GetPaddingRight() const;
|
||||
UDim GetPaddingBottom() const;
|
||||
|
||||
|
||||
|
||||
public:
|
||||
virtual void Draw();
|
||||
virtual void Update(float delta);
|
||||
|
10
main.cpp
10
main.cpp
@@ -38,8 +38,18 @@ public:
|
||||
JUIDevelopmentTestWindow() : ReWindow::RWindow() {}
|
||||
};
|
||||
|
||||
JUI::Scene* CreateScene() {
|
||||
using namespace JUI;
|
||||
|
||||
Scene root;
|
||||
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
|
||||
auto* scene = CreateScene();
|
||||
|
||||
auto* window = new JUIDevelopmentTestWindow("Test Window", 600, 480);
|
||||
window->setRenderer(RenderingAPI::OPENGL);
|
||||
window->Open();
|
||||
|
1
src/JUI/Rect.cpp
Normal file
1
src/JUI/Rect.cpp
Normal file
@@ -0,0 +1 @@
|
||||
#include <JUI/Rect.hpp>
|
@@ -1 +1,142 @@
|
||||
#include <JUI/Widget.hpp>
|
||||
#include <JUI/Widget.hpp>
|
||||
|
||||
|
||||
namespace JUI {
|
||||
void Widget::SetParent(Widget* parent) {
|
||||
// hold a reference to this so it doesn't get collected as we're working.
|
||||
Widget* oldParent = this->parent;
|
||||
|
||||
// New parent is old parent, do nothing, maybe raise a warning.
|
||||
if (parent == oldParent)
|
||||
return;
|
||||
|
||||
// Don't allow for an instance to be parented to itself
|
||||
if (this == parent)
|
||||
throw std::runtime_error("Cannot parent a widget to itself.");
|
||||
// You're trying to break the linearity of the object hierarchy by creating a circle in the graph.
|
||||
if (this->IsAncestorOf(parent))
|
||||
throw std::runtime_error("Cannot create circular reference.");
|
||||
|
||||
for (Widget* ancestor: this->GetAncestors()) {
|
||||
if (oldParent && !ancestor->IsAncestorOf(parent) && parent != ancestor) {
|
||||
ancestor->DescendantRemoved(this);
|
||||
for (Widget* descendant : this->GetDescendants()) {
|
||||
ancestor->DescendantRemoved(descendant);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Remove ourselves from our parent (if we have one)
|
||||
if (this->parent) {
|
||||
// this->parent->ChildRemoved(this)
|
||||
std::erase(parent->children, this);
|
||||
}
|
||||
|
||||
// Update our old parent to the new one
|
||||
this->parent = parent;
|
||||
|
||||
// If our parent is set to nullptr, we can't update it's vector of children
|
||||
if (!parent) return;
|
||||
|
||||
// Add ourselves to our new parent's list of children
|
||||
parent->children.emplace_back(this);
|
||||
//newParent->ChildAdded(this);
|
||||
|
||||
for (Widget* ancestor : this->GetAncestors()) {
|
||||
if (!oldParent || (!oldParent->IsDescendantOf(parent) && oldParent != ancestor)) {
|
||||
// Don't fire unless an instance is actually a new descendant
|
||||
ancestor->DescendantAdded(this);
|
||||
for (Widget* descendant: this->GetDescendants()) {
|
||||
ancestor->DescendantAdded(descendant);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool Widget::IsDescendantOf(Widget* ancestor) {
|
||||
if (ancestor == nullptr) return false;
|
||||
|
||||
Widget* instance = this;
|
||||
while (instance->GetParent()) {
|
||||
instance = instance->GetParent();
|
||||
if (instance == ancestor)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Widget::IsAncestorOf(Widget* descendant) {
|
||||
if (descendant == nullptr) return false;
|
||||
Widget* instance = descendant;
|
||||
while (instance->GetParent()) {
|
||||
instance = instance->GetParent();
|
||||
if (instance == this)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
std::vector<Widget *> Widget::GetChildren() {
|
||||
return this->children;
|
||||
}
|
||||
|
||||
std::vector<Widget *> Widget::GetDescendants() {
|
||||
std::vector<Widget*> descendants;
|
||||
for (auto& child: this->GetChildren()) {
|
||||
descendants.push_back(child);
|
||||
std::vector<Widget*> recursiveDescendants = child->GetDescendants();
|
||||
descendants.insert(descendants.end(), recursiveDescendants.begin(), recursiveDescendants.end());
|
||||
}
|
||||
return descendants;
|
||||
}
|
||||
|
||||
std::vector<Widget*> Widget::GetAncestors() {
|
||||
std::vector<Widget*> ancestors;
|
||||
for (Widget *ancestor = this->parent; ancestor; ancestor = ancestor->parent) {
|
||||
ancestors.push_back(ancestor);
|
||||
}
|
||||
return ancestors;
|
||||
}
|
||||
|
||||
Widget* Widget::GetParent() const { return parent;}
|
||||
|
||||
UDim2 Widget::GetPosition() const { return position; }
|
||||
UDim2 Widget::GetSize() const { return size;}
|
||||
|
||||
void Widget::SetPosition(const UDim2& pos) {
|
||||
position = pos;
|
||||
}
|
||||
|
||||
void Widget::SetSize(const UDim2& s) { size = s; }
|
||||
|
||||
Vector2 Widget::GetAbsolutePosition() const {
|
||||
auto child_pos_scale = this->GetPosition().GetScale();
|
||||
auto child_pos_pixels = this->GetPosition().GetPixels();
|
||||
auto parent_abs_size = this->GetParent()->GetAbsoluteSize();
|
||||
auto parent_abs_pos = this->GetParent()->GetAbsolutePosition();
|
||||
|
||||
auto abs_size = GetAbsoluteSize();
|
||||
|
||||
auto anchor_offset = abs_size * GetAnchorPoint();
|
||||
|
||||
UDim padding_h = parent->GetPaddingLeft(); // TODO: Factor in PaddingRight
|
||||
UDim padding_v = parent->GetPaddingTop(); // TODO: Factor in PaddingBottom
|
||||
|
||||
float calculated_padding_x = padding_h.Pixels + (padding_h.Scale * parent_abs_size.x);
|
||||
float calculated_padding_y = padding_v.Pixels + (padding_v.Scale * parent_abs_size.y);
|
||||
|
||||
Vector2 padding_offset = {calculated_padding_x, calculated_padding_y};
|
||||
|
||||
|
||||
Vector2 absolute_position =
|
||||
parent_abs_pos + child_pos_pixels + (parent_abs_size * child_pos_scale) + padding_offset;
|
||||
|
||||
return absolute_position - anchor_offset;
|
||||
}
|
||||
|
||||
// TODO: implement padding shrinking abs_size
|
||||
Vector2 Widget::GetAbsoluteSize() const {}
|
||||
|
||||
|
||||
}
|
Reference in New Issue
Block a user