DataModel partial implementation

This commit is contained in:
2024-07-11 13:29:13 -04:00
parent abc9a756dd
commit c79306d7f0
5 changed files with 231 additions and 7 deletions

View File

@@ -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);
}
};
}

View File

@@ -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);

View File

@@ -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
View File

@@ -0,0 +1 @@
#include <JUI/Rect.hpp>

View File

@@ -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 {}
}