Awesome collaborative changes.
This commit is contained in:
@@ -61,9 +61,8 @@ namespace JUI {
|
||||
/// This event triggers right before this widget gets deallocated.
|
||||
Event<Widget *> Destroying;
|
||||
public:
|
||||
|
||||
Tween* TweenPositionTo(const UDim2& goal, TweenInfo params = {});
|
||||
Tween* TweenSizeTo(const UDim2& goal, TweenInfo params = {});
|
||||
Tween* TweenPosition(const UDim2& goal, TweenInfo params = {});
|
||||
Tween* TweenSize(const UDim2& goal, TweenInfo params = {});
|
||||
|
||||
|
||||
|
||||
@@ -142,6 +141,9 @@ namespace JUI {
|
||||
|
||||
void AnchorPoint(const Vector2 &point);
|
||||
|
||||
Tween* TweenAnchorPoint(const Vector2& goal, TweenInfo info = {});
|
||||
|
||||
#pragma region Padding
|
||||
/// Returns the padding factor on the left of this widget.
|
||||
/// Padding refers to spacing on the inside of elements, while margin is spacing outside the element.
|
||||
/// @see PaddingLeft(), class UDim.
|
||||
@@ -159,6 +161,8 @@ namespace JUI {
|
||||
/// @see PaddingBottom(), class UDim.
|
||||
[[nodiscard]] UDim PaddingBottom() const;
|
||||
|
||||
|
||||
|
||||
/// Sets the padding factor on the left of this widget.
|
||||
/// Padding refers to spacing on the inside of elements, while margin is spacing outside the element.
|
||||
/// @see PaddingLeft(), class UDim.
|
||||
@@ -175,6 +179,7 @@ namespace JUI {
|
||||
/// Padding refers to spacing on the inside of elements, while margin is spacing outside the element.
|
||||
/// @see PaddingLeft(), class UDim.
|
||||
void PaddingBottom(const UDim &pad_bottom);
|
||||
|
||||
/// Sets the padding factor on the four respective sides of this widget.
|
||||
/// Padding refers to spacing on the inside of elements, while margin is spacing outside the element.
|
||||
/// @param left
|
||||
@@ -187,6 +192,16 @@ namespace JUI {
|
||||
/// Padding refers to spacing on the inside of elements, while margin is spacing outside the element.
|
||||
void Padding(const UDim& padding);
|
||||
|
||||
Tween* TweenPaddingLeft(const UDim &goal, TweenInfo info = {});
|
||||
Tween* TweenPaddingRight(const UDim &goal, TweenInfo info = {});
|
||||
Tween* TweenPaddingTop(const UDim &goal, TweenInfo info = {});
|
||||
Tween* TweenPaddingBottom(const UDim &goal, TweenInfo info = {});
|
||||
Tween* TweenPadding(const UDim& goalLeft, const UDim& goalTop, const UDim& goalRight, const UDim& goalBottom, TweenInfo info = {});
|
||||
Tween* TweenPadding(const UDim& goal, TweenInfo info = {});
|
||||
|
||||
#pragma endregion
|
||||
|
||||
#pragma region Margin
|
||||
/// Returns the margin factor on the left of this widget.
|
||||
[[nodiscard]] UDim MarginLeft() const;
|
||||
/// Returns the margin factor on the top of this widget.
|
||||
@@ -220,6 +235,16 @@ namespace JUI {
|
||||
/// @see Margin(const UDim&, const UDim&, const UDim&, const UDim&).
|
||||
void Margin(const UDim& margin);
|
||||
|
||||
Tween* TweenMarginLeft(const UDim &goal, TweenInfo info = {});
|
||||
Tween* TweenMarginTop(const UDim &goal, TweenInfo info = {});
|
||||
Tween* TweenMarginBottom(const UDim &goal, TweenInfo info = {});
|
||||
Tween* TweenMarginRight(const UDim &goal, TweenInfo info = {});
|
||||
|
||||
Tween* TweenMargin(const UDim& goalLeft, const UDim& goalTop, const UDim& goalRight, const UDim& goalBottom, TweenInfo info = {});
|
||||
Tween* TweenMargin(const UDim& goal, TweenInfo info = {});
|
||||
|
||||
#pragma endregion
|
||||
|
||||
/// Returns this widgets mnemonic name.
|
||||
/// Widgets can optionally be assigned a name that can be used to retrieve it from a widget tree node.
|
||||
/// @see Name().
|
||||
|
@@ -90,9 +90,7 @@ namespace JUI
|
||||
/// A class that represents an animation-in-action.
|
||||
class Tween {
|
||||
public:
|
||||
Tween(TweenTickFunc tick_func) {
|
||||
this->tick_func = tick_func;
|
||||
}
|
||||
Tween(TweenTickFunc tick_func);
|
||||
Tween(TweenTickFunc tick_func, TweenInfo info) {
|
||||
this->tick_func = tick_func;
|
||||
|
||||
|
@@ -13,92 +13,44 @@
|
||||
|
||||
#include <JUI/Base/Widget.hpp>
|
||||
#include <JUI/Widgets/Rect.hpp>
|
||||
#include "JUI/Mixins/Clickable.hpp"
|
||||
#include "JUI/Mixins/Hoverable.hpp"
|
||||
#include "Button.hpp"
|
||||
#include "JUI/Base/ImageBase.hpp"
|
||||
#include <JUI/Mixins/Clickable.hpp>
|
||||
#include <JUI/Mixins/Hoverable.hpp>
|
||||
#include <JUI/Widgets/Button.hpp>
|
||||
#include <JUI/Base/ImageBase.hpp>
|
||||
#include <JUI/Widgets/ImageButton.hpp>
|
||||
|
||||
namespace JUI
|
||||
{
|
||||
class Checkbox : public Button {
|
||||
// TODO: Find a nice way to implement a checkmark.
|
||||
|
||||
class CheckboxBase {
|
||||
public:
|
||||
Checkbox() : Button() { }
|
||||
|
||||
explicit Checkbox(Widget *parent) : Checkbox()
|
||||
{
|
||||
this->Parent(parent);
|
||||
}
|
||||
|
||||
void Update(float delta) override
|
||||
{
|
||||
Button::Update(delta);
|
||||
}
|
||||
|
||||
|
||||
void OnRelease(const J3ML::LinearAlgebra::Vector2 &mouse_pos, const JUI::MouseButton &bnt, bool still_hovering) override
|
||||
{
|
||||
Button::OnRelease(mouse_pos, bnt, still_hovering);
|
||||
checked = !checked;
|
||||
}
|
||||
|
||||
void InnerDraw() override
|
||||
{
|
||||
Rect::InnerDraw();
|
||||
if (checked)
|
||||
{
|
||||
//J2D::Begin();
|
||||
Vector2 check_padding = {2, 2};
|
||||
RectBase::Draw(check_color, check_color, GetAbsolutePosition()+check_padding, GetAbsoluteSize()-(check_padding*2));
|
||||
//J2D::End();
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Draw() override
|
||||
{
|
||||
if (!visible)
|
||||
return;
|
||||
|
||||
//J2D::Begin();
|
||||
Vector2 abs_pos = GetAbsolutePosition();
|
||||
Vector2 abs_size = GetAbsoluteSize();
|
||||
|
||||
auto root_size = GetFamilyTreeRoot()->GetAbsoluteSize();
|
||||
|
||||
GLint *old_scissor_bounds;
|
||||
bool clip_was_enabled;
|
||||
|
||||
if (clips_descendants) {
|
||||
clip_was_enabled = glIsEnabled(GL_SCISSOR_TEST);
|
||||
if (clip_was_enabled)
|
||||
glGetIntegerv(GL_SCISSOR_BOX, old_scissor_bounds);
|
||||
|
||||
float presumed_screen_height = 600;
|
||||
glScissor(abs_pos.x, presumed_screen_height-abs_size.y-abs_pos.y, abs_size.x, abs_size.y);
|
||||
glEnable(GL_SCISSOR_TEST);
|
||||
}
|
||||
|
||||
RectBase::Draw(abs_pos, abs_size);
|
||||
|
||||
// Draw Child Elements with scissor clipping still active
|
||||
Widget::Draw();
|
||||
|
||||
// Returns clip to previous state
|
||||
if (clips_descendants)
|
||||
{
|
||||
//glScissor(old_scissor_bounds[0], old_scissor_bounds[1], old_scissor_bounds[2], old_scissor_bounds[3]);
|
||||
|
||||
if (!clip_was_enabled) {}
|
||||
glDisable(GL_SCISSOR_TEST);
|
||||
|
||||
}
|
||||
|
||||
//J2D::End();
|
||||
}
|
||||
[[nodiscard]] Color4 CheckedColor() const { return check_color; }
|
||||
void CheckedColor(const Color4& color) { check_color = color; }
|
||||
bool IsChecked() const { return checked;}
|
||||
void SetChecked(bool value) { checked = value; }
|
||||
Tween* TweenCheckedColor(const Color4& goal, TweenInfo info = {});
|
||||
protected:
|
||||
bool checked;
|
||||
Color4 check_color = Colors::Red;
|
||||
};
|
||||
|
||||
class Checkbox : public Button, public CheckboxBase {
|
||||
public:
|
||||
Checkbox();
|
||||
explicit Checkbox(Widget *parent);
|
||||
void Update(float delta) override;
|
||||
void OnRelease(const J3ML::LinearAlgebra::Vector2 &mouse_pos, const JUI::MouseButton &bnt, bool still_hovering) override;
|
||||
void InnerDraw() override;
|
||||
|
||||
protected:
|
||||
private:
|
||||
};
|
||||
|
||||
class ImageCheckbox : public ImageButton, public CheckboxBase {
|
||||
public:
|
||||
protected:
|
||||
private:
|
||||
};
|
||||
|
||||
}
|
@@ -1,3 +1,5 @@
|
||||
#pragma once
|
||||
|
||||
#include <JUI/Base/ImageBase.hpp>
|
||||
#include <JUI/Widgets/Button.hpp>
|
||||
|
||||
@@ -10,8 +12,8 @@ public:
|
||||
void Update(float delta) override;
|
||||
void Draw() override;
|
||||
public:
|
||||
ImageButton() : ImageBase(), Button() {}
|
||||
explicit ImageButton(Widget* parent) : ImageButton() { Parent(parent); }
|
||||
ImageButton();
|
||||
explicit ImageButton(Widget* parent);
|
||||
public:
|
||||
~ImageButton() override = default;
|
||||
};
|
@@ -18,8 +18,12 @@
|
||||
|
||||
namespace JUI
|
||||
{
|
||||
class ImageRect: public Rect, public ImageBase
|
||||
{
|
||||
class ImageRect: public Rect, public ImageBase {
|
||||
public:
|
||||
ImageRect();
|
||||
explicit ImageRect(Widget* parent);
|
||||
void Update(float delta) override;
|
||||
|
||||
void Draw() override;
|
||||
};
|
||||
}
|
@@ -15,6 +15,11 @@ namespace JUI {
|
||||
class ScrollingRect;
|
||||
}
|
||||
|
||||
// TODO: Fix direction of ScrollBar itself
|
||||
// TODO: MouseWheel scroll, and ScrollBar clickable
|
||||
// TODO: Clamp range of ScrollBar
|
||||
|
||||
|
||||
/// A Rectangle Widget which has a larger renderable area than the visible area.
|
||||
/// This allows user-controlled scrolling of the viewable content.
|
||||
class JUI::ScrollingRect : public Rect {
|
||||
@@ -45,8 +50,7 @@ public:
|
||||
void CanvasSize(const Vector2i& new_size);
|
||||
void InnerDraw() override;
|
||||
void Draw() override;
|
||||
void Update(float delta) override
|
||||
{
|
||||
void Update(float delta) override {
|
||||
//scroll += delta*5;
|
||||
//canvas->Resize(Vector2i(GetAbsoluteSize().x, GetAbsoluteSize().y));
|
||||
Rect::Update(delta);
|
||||
|
84
main.cpp
84
main.cpp
@@ -79,48 +79,98 @@ JUI::Scene* CreateScene() {
|
||||
//auto* horizontal = new HorizontalListLayout(root);
|
||||
//horizontal->ZIndex(1);
|
||||
|
||||
auto* sizer_1 = new Rect(root);
|
||||
//sizer_1->ZIndex(4);
|
||||
sizer_1->Size({0,-24,0.2f, 1.f});
|
||||
sizer_1->Position({0, 24, 0, 0});
|
||||
sizer_1->BGColor(Colors::Grays::Gainsboro);
|
||||
auto* column_rect = new Rect(root);
|
||||
//column_rect->ZIndex(4);
|
||||
column_rect->Size({0, -24, 0.2f, 1.f});
|
||||
column_rect->Position({0, 24, 0, 0});
|
||||
column_rect->BGColor(Colors::Grays::Gainsboro);
|
||||
|
||||
auto* s1_vert = new VerticalListLayout(sizer_1);
|
||||
auto* column_layout = new VerticalListLayout(column_rect);
|
||||
|
||||
auto* button = new TextButton(s1_vert);
|
||||
auto* btn_container1 = new Rect(column_layout);
|
||||
btn_container1->Size({100_percent, 24_px});
|
||||
|
||||
auto* btn_h_layout1 = new HorizontalListLayout(btn_container1);
|
||||
btn_h_layout1->Padding({2_px});
|
||||
|
||||
auto* button = new TextButton(btn_h_layout1);
|
||||
//button->Position({5, 105, 0, 0});
|
||||
button->Size({0, 35, 1, 0});
|
||||
button->Size({0, 20, 0.32f, 0});
|
||||
button->SetTextColor(Colors::Black);
|
||||
button->SetContent("Button");
|
||||
button->AlignLeft();
|
||||
button->Padding(5_px);
|
||||
//button->Padding(5_px);
|
||||
|
||||
auto* tt2 = new JUI::Tooltip(button);
|
||||
tt2->SetContent("Test 123");
|
||||
|
||||
auto* button2 = new TextButton(s1_vert);
|
||||
auto* button2 = new TextButton(btn_h_layout1);
|
||||
//button2->Position({5, 105, 0, 0});
|
||||
button2->Size({0, 35, 1, 0});
|
||||
button2->Size({0, 20, 0.32f, 0});
|
||||
button2->SetTextColor(Colors::Black);
|
||||
button2->SetContent("Button");
|
||||
button2->AlignCenterHorizontally();
|
||||
|
||||
auto* button3 = new TextButton(s1_vert);
|
||||
auto* button3 = new TextButton(btn_h_layout1);
|
||||
//button2->Position({5, 105, 0, 0});
|
||||
button3->Size({0, 35, 1, 0});
|
||||
button3->Size({0, 20, 0.32f, 0});
|
||||
button3->SetTextColor(Colors::Black);
|
||||
button3->SetContent("Button");
|
||||
button3->AlignRight();
|
||||
|
||||
auto* checkbox_container = new Rect(s1_vert);
|
||||
checkbox_container->Size({0, 35, 1, 0});
|
||||
auto* btn_container2 = new Rect(column_layout);
|
||||
btn_container2->Size({100_percent, 24_px});
|
||||
|
||||
auto* btn_h_layout2 = new HorizontalListLayout(btn_container2);
|
||||
btn_h_layout2->Padding({2_px});
|
||||
|
||||
|
||||
auto* button4 = new TextButton(btn_h_layout2);
|
||||
//button->Position({5, 105, 0, 0});
|
||||
button4->Size({0, 20, 0.32f, 0});
|
||||
button4->SetTextColor(Colors::Black);
|
||||
button4->SetContent("Button");
|
||||
button4->AlignLeft();
|
||||
//button4->CornerRounding(4);
|
||||
|
||||
auto* button5 = new TextButton(btn_h_layout2);
|
||||
//button2->Position({5, 105, 0, 0});
|
||||
button5->Size({0, 20, 0.32f, 0});
|
||||
button5->SetTextColor(Colors::Black);
|
||||
button5->SetContent("Button");
|
||||
button5->AlignCenterHorizontally();
|
||||
//button5->CornerRounding(4);
|
||||
|
||||
auto* button6 = new TextButton(btn_h_layout2);
|
||||
//button2->Position({5, 105, 0, 0});
|
||||
button6->Size({0, 20, 0.32f, 0});
|
||||
button6->SetTextColor(Colors::Black);
|
||||
button6->SetContent("Button");
|
||||
button6->AlignRight();
|
||||
//button6->CornerRounding(4);
|
||||
|
||||
auto* checkbox_container = new Rect(column_layout);
|
||||
checkbox_container->Size({0, 24, 1, 0});
|
||||
|
||||
auto* checkbox_horiz = new HorizontalListLayout(checkbox_container);
|
||||
checkbox_horiz->Padding(2_px);
|
||||
|
||||
auto* label = new TextRect(checkbox_horiz);
|
||||
label->SetContent("Checkboxes");
|
||||
label->AutoFitSizeToText(true);
|
||||
|
||||
auto* check1 = new Checkbox(checkbox_horiz);
|
||||
check1->Size({20_px, 20_px});
|
||||
auto* check2 = new Checkbox(checkbox_horiz);
|
||||
check2->Size({20_px, 20_px});
|
||||
check2->CheckedColor(Colors::Blue);
|
||||
check2->CornerRounding(7);
|
||||
auto* check3 = new Checkbox(checkbox_horiz);
|
||||
check3->Size({20_px, 20_px});
|
||||
check3->CheckedColor(Colors::Oranges::Coral);
|
||||
check3->CornerRounding(7);
|
||||
|
||||
auto* input_form = new TextInputForm(s1_vert);
|
||||
auto* input_form = new TextInputForm(column_layout);
|
||||
input_form->Size({0,30, 1, 0});
|
||||
input_form->SetContent("");
|
||||
input_form->SetTextSize(14);
|
||||
@@ -130,7 +180,7 @@ JUI::Scene* CreateScene() {
|
||||
other_window->Size({30_percent, 25_percent});
|
||||
other_window->SetTitle("Another Window");
|
||||
|
||||
Tween* t = other_window->TweenPositionTo({50_percent, 50_percent}, {.time = 5});
|
||||
Tween* t = other_window->TweenPosition({50_percent, 50_percent}, {.time = 5});
|
||||
|
||||
t->Completed += [] () { std::cout << "This Dick" << std::endl; };
|
||||
|
||||
|
@@ -2,180 +2,169 @@
|
||||
#include <jlog/Logger.hpp>
|
||||
#include <J3ML/Geometry/AABB2D.hpp>
|
||||
|
||||
namespace JUI {
|
||||
using namespace JUI;
|
||||
|
||||
Widget::Widget() {
|
||||
name = "Widget";
|
||||
children = std::vector<Widget *>();
|
||||
}
|
||||
Widget::Widget() {
|
||||
name = "Widget";
|
||||
children = std::vector<Widget *>();
|
||||
}
|
||||
Widget::Widget(Widget* parent) : Widget() {
|
||||
this->Parent(parent);
|
||||
}
|
||||
|
||||
Widget::Widget(Widget* parent) : Widget()
|
||||
{
|
||||
this->Parent(parent);
|
||||
}
|
||||
void Widget::Parent(Widget* newParent) {
|
||||
// hold a reference to this so it doesn't get collected as we're working.
|
||||
Widget* oldParent = this->parent;
|
||||
|
||||
void Widget::Parent(Widget* newParent) {
|
||||
// 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 (newParent == oldParent)
|
||||
return;
|
||||
|
||||
// New parent is old parent, do nothing, maybe raise a warning.
|
||||
if (newParent == oldParent)
|
||||
return;
|
||||
// Don't allow for an instance to be parented to itself
|
||||
if (this == newParent)
|
||||
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(newParent))
|
||||
throw std::runtime_error("Cannot create circular reference.");
|
||||
|
||||
// Don't allow for an instance to be parented to itself
|
||||
if (this == newParent)
|
||||
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(newParent))
|
||||
throw std::runtime_error("Cannot create circular reference.");
|
||||
|
||||
for (Widget* ancestor: this->GetAncestors()) {
|
||||
if (oldParent && !ancestor->IsAncestorOf(newParent) && newParent != 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(this->parent->children, this);
|
||||
}
|
||||
|
||||
// Update our old parent to the new one
|
||||
this->parent = newParent;
|
||||
|
||||
// If our parent is set to nullptr, we can't update it's vector of children
|
||||
if (!newParent) return;
|
||||
|
||||
// Add ourselves to our new parent's list of children
|
||||
newParent->children.emplace_back(this);
|
||||
//newParent->ChildAdded(this);
|
||||
|
||||
for (Widget* ancestor : this->GetAncestors()) {
|
||||
if (!oldParent || (!oldParent->IsDescendantOf(newParent) && oldParent != ancestor)) {
|
||||
// Don't fire unless an instance is actually a new descendant
|
||||
ancestor->DescendantAdded(this);
|
||||
for (Widget* descendant: this->GetDescendants()) {
|
||||
ancestor->DescendantAdded(descendant);
|
||||
}
|
||||
}
|
||||
for (Widget* ancestor: this->GetAncestors()) {
|
||||
if (oldParent && !ancestor->IsAncestorOf(newParent) && newParent != ancestor) {
|
||||
ancestor->DescendantRemoved(this);
|
||||
for (Widget* descendant : this->GetDescendants())
|
||||
ancestor->DescendantRemoved(descendant);
|
||||
}
|
||||
}
|
||||
|
||||
bool Widget::IsDescendantOf(Widget* ancestor) {
|
||||
if (ancestor == nullptr) return false;
|
||||
// Remove ourselves from our parent (if we have one)
|
||||
if (this->parent)
|
||||
std::erase(this->parent->children, this);
|
||||
|
||||
Widget* instance = this;
|
||||
while (instance->GetParent()) {
|
||||
instance = instance->GetParent();
|
||||
if (instance == ancestor)
|
||||
return true;
|
||||
// Update our old parent to the new one
|
||||
this->parent = newParent;
|
||||
|
||||
// If our parent is set to nullptr, we can't update it's vector of children
|
||||
if (!newParent) return;
|
||||
|
||||
// Add ourselves to our new parent's list of children
|
||||
newParent->children.emplace_back(this);
|
||||
//newParent->ChildAdded(this);
|
||||
|
||||
for (Widget* ancestor : this->GetAncestors()) {
|
||||
if (!oldParent || (!oldParent->IsDescendantOf(newParent) && oldParent != ancestor)) {
|
||||
// Don't fire unless an instance is actually a new descendant
|
||||
ancestor->DescendantAdded(this);
|
||||
for (Widget* descendant: this->GetDescendants())
|
||||
ancestor->DescendantAdded(descendant);
|
||||
}
|
||||
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;
|
||||
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;
|
||||
}
|
||||
|
||||
Vector2 Widget::AnchorPoint() const {
|
||||
return anchor_point;
|
||||
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;
|
||||
}
|
||||
|
||||
UDim Widget::PaddingLeft() const { return pad_left;}
|
||||
UDim Widget::PaddingTop() const { return pad_top;}
|
||||
UDim Widget::PaddingRight() const { return pad_right;}
|
||||
UDim Widget::PaddingBottom() const { return pad_bottom;}
|
||||
Vector2 Widget::AnchorPoint() const {
|
||||
return anchor_point;
|
||||
}
|
||||
|
||||
void Widget::PaddingLeft (const UDim& pad_left) { this->pad_left = pad_left; }
|
||||
void Widget::PaddingTop (const UDim& pad_top) { this->pad_top = pad_top; }
|
||||
void Widget::PaddingRight (const UDim& pad_right) { this->pad_right = pad_right; }
|
||||
void Widget::PaddingBottom(const UDim& pad_bottom) { this->pad_bottom = pad_bottom; }
|
||||
UDim Widget::PaddingLeft() const { return pad_left;}
|
||||
UDim Widget::PaddingTop() const { return pad_top;}
|
||||
UDim Widget::PaddingRight() const { return pad_right;}
|
||||
UDim Widget::PaddingBottom() const { return pad_bottom;}
|
||||
|
||||
void Widget::Padding(const UDim &left, const UDim &top, const UDim &right, const UDim &bottom) {
|
||||
PaddingLeft(left);
|
||||
PaddingTop(top);
|
||||
PaddingRight(right);
|
||||
PaddingBottom(bottom);
|
||||
void Widget::PaddingLeft (const UDim& value) { this->pad_left = value; }
|
||||
void Widget::PaddingTop (const UDim& pad_top) { this->pad_top = pad_top; }
|
||||
void Widget::PaddingRight (const UDim& pad_right) { this->pad_right = pad_right; }
|
||||
void Widget::PaddingBottom(const UDim& pad_bottom) { this->pad_bottom = pad_bottom; }
|
||||
|
||||
void Widget::Padding(const UDim &left, const UDim &top, const UDim &right, const UDim &bottom) {
|
||||
PaddingLeft(left);
|
||||
PaddingTop(top);
|
||||
PaddingRight(right);
|
||||
PaddingBottom(bottom);
|
||||
}
|
||||
|
||||
void Widget::Padding(const UDim &padding) {
|
||||
Padding(padding, padding, padding, padding);
|
||||
}
|
||||
|
||||
UDim Widget::MarginLeft () const { return margin_left;}
|
||||
UDim Widget::MarginTop () const { return margin_top;}
|
||||
UDim Widget::MarginRight () const { return margin_right;}
|
||||
UDim Widget::MarginBottom() const { return margin_bottom;}
|
||||
|
||||
void Widget::MarginLeft(const UDim& ml) { margin_left = ml;}
|
||||
void Widget::MarginTop(const UDim& mt) { margin_top = mt;}
|
||||
void Widget::MarginRight(const UDim& mr) { margin_right = mr;}
|
||||
void Widget::MarginBottom(const UDim& mb) { margin_bottom = mb;}
|
||||
|
||||
void Widget::Margin(const UDim &left, const UDim &top, const UDim &right, const UDim &bottom) {
|
||||
MarginLeft(left);
|
||||
MarginTop(top);
|
||||
MarginRight(right);
|
||||
MarginBottom(bottom);
|
||||
}
|
||||
|
||||
void Widget::Margin(const UDim &margin) {
|
||||
Margin(margin, margin, margin, margin);
|
||||
}
|
||||
|
||||
std::string Widget::Name() const { return name; }
|
||||
void Widget::Name(const std::string& new_name) { name = new_name;}
|
||||
|
||||
bool Widget::IsVisible() const { return visible; }
|
||||
void Widget::Visible(bool enabled) { visible = enabled;}
|
||||
|
||||
Widget* Widget::GetParent() const { return parent; }
|
||||
|
||||
UDim2 Widget::Position() const { return position; }
|
||||
void Widget::Position(const UDim2& pos) { position = pos; }
|
||||
|
||||
UDim2 Widget::Size() const { return size;}
|
||||
void Widget::Size(const UDim2& s) { size = s; }
|
||||
|
||||
float Widget::GetAbsoluteRotation() const {
|
||||
// TODO: implement rotation correctly!!
|
||||
return rotation;
|
||||
}
|
||||
|
||||
std::vector<Widget *> Widget::GetChildren() { return 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;
|
||||
}
|
||||
|
||||
void Widget::Padding(const UDim &padding) {
|
||||
Padding(padding, padding, padding, padding);
|
||||
}
|
||||
|
||||
UDim Widget::MarginLeft () const { return margin_left;}
|
||||
UDim Widget::MarginTop () const { return margin_top;}
|
||||
UDim Widget::MarginRight () const { return margin_right;}
|
||||
UDim Widget::MarginBottom() const { return margin_bottom;}
|
||||
|
||||
void Widget::MarginLeft(const UDim& ml) { margin_left = ml;}
|
||||
void Widget::MarginTop(const UDim& mt) { margin_top = mt;}
|
||||
void Widget::MarginRight(const UDim& mr) { margin_right = mr;}
|
||||
void Widget::MarginBottom(const UDim& mb) { margin_bottom = mb;}
|
||||
|
||||
void Widget::Margin(const UDim &left, const UDim &top, const UDim &right, const UDim &bottom) {
|
||||
MarginLeft(left);
|
||||
MarginTop(top);
|
||||
MarginRight(right);
|
||||
MarginBottom(bottom);
|
||||
}
|
||||
|
||||
void Widget::Margin(const UDim &margin) {
|
||||
Margin(margin, margin, margin, margin);
|
||||
}
|
||||
|
||||
std::string Widget::Name() const { return name; }
|
||||
void Widget::Name(const std::string& new_name) { name = new_name;}
|
||||
|
||||
bool Widget::IsVisible() const { return visible; }
|
||||
void Widget::Visible(bool enabled) { visible = enabled;}
|
||||
|
||||
Widget* Widget::GetParent() const {
|
||||
|
||||
return parent;
|
||||
}
|
||||
|
||||
UDim2 Widget::Position() const { return position; }
|
||||
void Widget::Position(const UDim2& pos) { position = pos; }
|
||||
|
||||
UDim2 Widget::Size() const { return size;}
|
||||
void Widget::Size(const UDim2& s) { size = s; }
|
||||
|
||||
float Widget::GetAbsoluteRotation() const {
|
||||
// TODO: implement rotation correctly!!
|
||||
return rotation;
|
||||
}
|
||||
|
||||
|
||||
std::vector<Widget *> Widget::GetChildren() { return 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;
|
||||
}
|
||||
std::vector<Widget*> Widget::GetAncestors() {
|
||||
std::vector<Widget*> ancestors;
|
||||
for (Widget *ancestor = this->parent; ancestor; ancestor = ancestor->parent)
|
||||
ancestors.push_back(ancestor);
|
||||
return ancestors;
|
||||
}
|
||||
|
||||
/*float Widget::GetAbsoluteMarginLeft() {}
|
||||
float Widget::GetAbsoluteMarginRight() {}
|
||||
@@ -188,259 +177,412 @@ namespace JUI {
|
||||
|
||||
|
||||
|
||||
Vector2 Widget::GetAbsolutePaddingTopLeft() const {
|
||||
auto parent_abs_size = this->GetParent()->GetAbsoluteSize();
|
||||
Vector2 Widget::GetAbsolutePaddingTopLeft() const {
|
||||
auto parent_abs_size = this->GetParent()->GetAbsoluteSize();
|
||||
|
||||
UDim padding_h = parent->PaddingLeft();
|
||||
UDim padding_v = parent->PaddingTop();
|
||||
UDim padding_h = parent->PaddingLeft();
|
||||
UDim padding_v = parent->PaddingTop();
|
||||
|
||||
float padding_x = padding_h.Pixels + (padding_h.Scale * parent_abs_size.x);
|
||||
float padding_y = padding_v.Pixels + (padding_v.Scale * parent_abs_size.y);
|
||||
float padding_x = padding_h.Pixels + (padding_h.Scale * parent_abs_size.x);
|
||||
float padding_y = padding_v.Pixels + (padding_v.Scale * parent_abs_size.y);
|
||||
|
||||
return {padding_x, padding_y};
|
||||
}
|
||||
return {padding_x, padding_y};
|
||||
}
|
||||
|
||||
Vector2 Widget::GetAbsoluteMarginTopLeft()
|
||||
{
|
||||
// TODO: Implement correctly.
|
||||
Vector2 Widget::GetAbsoluteMarginTopLeft() {
|
||||
// TODO: Implement correctly.
|
||||
return {0,0};
|
||||
}
|
||||
|
||||
Vector2 Widget::GetAbsolutePaddingBottomRight() const {
|
||||
UDim padding_h = parent->PaddingLeft() + parent->PaddingRight();
|
||||
float final_pad_x = padding_h.Pixels + (padding_h.Scale * parent->GetAbsoluteSize().x);
|
||||
|
||||
UDim padding_v = parent->PaddingTop() + parent->PaddingBottom();
|
||||
float final_pad_y = padding_v.Pixels + (padding_v.Scale * parent->GetAbsoluteSize().y);
|
||||
|
||||
Vector2 padding = {final_pad_x, final_pad_y};
|
||||
|
||||
return padding;
|
||||
}
|
||||
|
||||
Vector2 Widget::GetAbsoluteMarginBottomRight() {
|
||||
// TODO: Implement correctly.
|
||||
return {0,0};
|
||||
}
|
||||
|
||||
|
||||
Vector2 Widget::GetAbsolutePosition() const {
|
||||
|
||||
if (this->parent == nullptr)
|
||||
return {0,0};
|
||||
}
|
||||
|
||||
Vector2 Widget::GetAbsolutePaddingBottomRight() const {
|
||||
UDim padding_h = parent->PaddingLeft() + parent->PaddingRight();
|
||||
float final_pad_x = padding_h.Pixels + (padding_h.Scale * parent->GetAbsoluteSize().x);
|
||||
auto child_pos_scale = this->Position().GetScale();
|
||||
auto child_pos_pixels = this->Position().GetPixels();
|
||||
auto parent_abs_size = this->GetParent()->GetAbsoluteSize();
|
||||
auto parent_abs_pos = this->GetParent()->GetAbsolutePosition();
|
||||
|
||||
UDim padding_v = parent->PaddingTop() + parent->PaddingBottom();
|
||||
float final_pad_y = padding_v.Pixels + (padding_v.Scale * parent->GetAbsoluteSize().y);
|
||||
auto abs_size = GetAbsoluteSize();
|
||||
|
||||
Vector2 padding = {final_pad_x, final_pad_y};
|
||||
auto anchor_offset = abs_size * AnchorPoint();
|
||||
|
||||
return padding;
|
||||
}
|
||||
Vector2 padding_offset = GetAbsolutePaddingTopLeft();
|
||||
|
||||
Vector2 Widget::GetAbsoluteMarginBottomRight()
|
||||
{
|
||||
// TODO: Implement correctly.
|
||||
return {0,0};
|
||||
}
|
||||
|
||||
|
||||
Vector2 Widget::GetAbsolutePosition() const {
|
||||
|
||||
if (this->parent == nullptr)
|
||||
return {0,0};
|
||||
|
||||
auto child_pos_scale = this->Position().GetScale();
|
||||
auto child_pos_pixels = this->Position().GetPixels();
|
||||
auto parent_abs_size = this->GetParent()->GetAbsoluteSize();
|
||||
auto parent_abs_pos = this->GetParent()->GetAbsolutePosition();
|
||||
|
||||
auto abs_size = GetAbsoluteSize();
|
||||
|
||||
auto anchor_offset = abs_size * AnchorPoint();
|
||||
|
||||
Vector2 padding_offset = GetAbsolutePaddingTopLeft();
|
||||
|
||||
Vector2 absolute_position =
|
||||
Vector2 absolute_position =
|
||||
parent_abs_pos + child_pos_pixels + (parent_abs_size * child_pos_scale) + padding_offset;
|
||||
|
||||
return absolute_position - anchor_offset;
|
||||
}
|
||||
|
||||
Vector2 Widget::GetAbsoluteSize() const {
|
||||
|
||||
if (this->GetParent() == nullptr)
|
||||
return {0,0};
|
||||
|
||||
Vector2 child_size_scale = this->Size().GetScale();
|
||||
Vector2 child_size_px = this->Size().GetPixels();
|
||||
|
||||
Vector2 parent_abs_size = this->GetParent()->GetAbsoluteSize();
|
||||
|
||||
Vector2 pad_size_reduction = GetAbsolutePaddingBottomRight();
|
||||
|
||||
Vector2 abs_size = child_size_px + (parent_abs_size * child_size_scale) - pad_size_reduction;
|
||||
|
||||
return abs_size;
|
||||
return absolute_position - anchor_offset;
|
||||
}
|
||||
|
||||
Vector2 Widget::GetAbsoluteSize() const {
|
||||
|
||||
if (this->GetParent() == nullptr)
|
||||
return {0,0};
|
||||
|
||||
Vector2 child_size_scale = this->Size().GetScale();
|
||||
Vector2 child_size_px = this->Size().GetPixels();
|
||||
|
||||
Vector2 parent_abs_size = this->GetParent()->GetAbsoluteSize();
|
||||
|
||||
Vector2 pad_size_reduction = GetAbsolutePaddingBottomRight();
|
||||
|
||||
Vector2 abs_size = child_size_px + (parent_abs_size * child_size_scale) - pad_size_reduction;
|
||||
|
||||
return abs_size;
|
||||
}
|
||||
|
||||
|
||||
std::optional<Widget*> Widget::FindFirstChild(const std::string& search_name) {
|
||||
for (auto& child : children) {
|
||||
if (child->Name() == search_name)
|
||||
return child;
|
||||
}
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
|
||||
std::optional<Widget*> Widget::FindFirstChild(const std::string& search_name) {
|
||||
for (auto& child : children) {
|
||||
if (child->Name() == search_name)
|
||||
return child;
|
||||
}
|
||||
return std::nullopt;
|
||||
}
|
||||
void Widget::Draw() {
|
||||
if (!visible)
|
||||
return;
|
||||
|
||||
PreDraw();
|
||||
InnerDraw();
|
||||
PostDraw();
|
||||
|
||||
DrawChildWidgets();
|
||||
}
|
||||
|
||||
void Widget::UpdateTweens(float elapsed) {
|
||||
for (Tween* t: tweens)
|
||||
t->Update(elapsed);
|
||||
|
||||
// TODO: Remove tweens if "dead"
|
||||
std::ranges::remove_if(tweens.begin(), tweens.end(), [](Tween* t){
|
||||
return t->HasCompleted();
|
||||
});
|
||||
}
|
||||
|
||||
void Widget::Update(float delta) {
|
||||
UpdateChildWidgets(delta);
|
||||
UpdateTweens(delta);
|
||||
}
|
||||
|
||||
struct {
|
||||
bool operator()(Widget* a, Widget* b) const { return a->ZIndex() < b->ZIndex();}
|
||||
}
|
||||
|
||||
zIndexSort;
|
||||
|
||||
void Widget::DrawChildWidgets() {
|
||||
std::sort(children.begin(), children.end(), zIndexSort);
|
||||
for (auto child : children)
|
||||
child->Draw();
|
||||
}
|
||||
|
||||
void Widget::UpdateChildWidgets(float delta) {
|
||||
for (auto child : children)
|
||||
child->Update(delta);
|
||||
}
|
||||
|
||||
Widget* Widget::GetFamilyTreeRoot() const {
|
||||
// This is stupid, Fix ASAP!
|
||||
auto parent = this->GetParent();
|
||||
if (parent->GetParent() == nullptr)
|
||||
return parent;
|
||||
return parent->GetFamilyTreeRoot();
|
||||
}
|
||||
|
||||
bool Widget::IsMouseInside() const {
|
||||
float x = last_known_mouse_pos.x;
|
||||
float y = last_known_mouse_pos.y;
|
||||
auto pos = GetAbsolutePosition();
|
||||
auto size = GetAbsoluteSize();
|
||||
|
||||
if (x > pos.x && y > pos.y && x < pos.x + size.x && y < pos.y + size.y)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void Widget::ObserveMouseInput(MouseButton btn, bool pressed) {
|
||||
mbtn = btn;
|
||||
mb_state = pressed;
|
||||
|
||||
for (Widget* child : children)
|
||||
child->ObserveMouseInput(btn, pressed);
|
||||
}
|
||||
|
||||
void Widget::ObserveMouseMovement(const Vector2 &latest_known_pos) {
|
||||
last_known_mouse_pos = latest_known_pos;
|
||||
|
||||
for (Widget* child: children)
|
||||
child->ObserveMouseMovement(latest_known_pos);
|
||||
}
|
||||
|
||||
void Widget::ObserveKeyInput(Key key, bool pressed) {
|
||||
for (Widget* child : children)
|
||||
child->ObserveKeyInput(key, pressed);
|
||||
}
|
||||
|
||||
|
||||
void Widget::Draw() {
|
||||
if (!visible)
|
||||
return;
|
||||
bool Widget::IsAncestorOf(Widget *descendant) const {
|
||||
if (descendant == nullptr)
|
||||
return false;
|
||||
|
||||
PreDraw();
|
||||
InnerDraw();
|
||||
PostDraw();
|
||||
|
||||
DrawChildWidgets();
|
||||
}
|
||||
|
||||
void Widget::UpdateTweens(float elapsed)
|
||||
{
|
||||
for (Tween* t: tweens) {
|
||||
t->Update(elapsed);
|
||||
}
|
||||
|
||||
// TODO: Remove tweens if "dead"
|
||||
std::ranges::remove_if(tweens.begin(), tweens.end(), [](Tween* t){
|
||||
return t->HasCompleted();
|
||||
});
|
||||
}
|
||||
|
||||
void Widget::Update(float delta) {
|
||||
|
||||
UpdateChildWidgets(delta);
|
||||
UpdateTweens(delta);
|
||||
}
|
||||
|
||||
struct {
|
||||
bool operator()(Widget* a, Widget* b) const { return a->ZIndex() < b->ZIndex();}
|
||||
} zIndexSort;
|
||||
|
||||
void Widget::DrawChildWidgets() {
|
||||
std::sort(children.begin(), children.end(), zIndexSort);
|
||||
for (auto child : children) {
|
||||
child->Draw();
|
||||
}
|
||||
}
|
||||
|
||||
void Widget::UpdateChildWidgets(float delta) {
|
||||
for (auto child : children) {
|
||||
child->Update(delta);
|
||||
}
|
||||
}
|
||||
|
||||
Widget* Widget::GetFamilyTreeRoot() const {
|
||||
// This is stupid, Fix ASAP!
|
||||
auto parent = this->GetParent();
|
||||
if (parent->GetParent() == nullptr)
|
||||
return parent;
|
||||
return parent->GetFamilyTreeRoot();
|
||||
}
|
||||
|
||||
bool Widget::IsMouseInside() const {
|
||||
float x = last_known_mouse_pos.x;
|
||||
float y = last_known_mouse_pos.y;
|
||||
auto pos = GetAbsolutePosition();
|
||||
auto size = GetAbsoluteSize();
|
||||
|
||||
if (x > pos.x && y > pos.y && x < pos.x + size.x && y < pos.y + size.y) {
|
||||
Widget* instance = descendant;
|
||||
while (instance->GetParent()) {
|
||||
instance = instance->GetParent();
|
||||
if (instance == this)
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Widget::IsDescendantOf(Widget *ancestor) const {
|
||||
if (ancestor == nullptr)
|
||||
return false;
|
||||
const Widget *instance = this;
|
||||
while (instance->GetParent()) {
|
||||
instance = instance->GetParent();
|
||||
if (instance == ancestor)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void Widget::ObserveMouseInput(MouseButton btn, bool pressed) {
|
||||
mbtn = btn;
|
||||
mb_state = pressed;
|
||||
Widget *Widget::Add(Widget *newChild) {
|
||||
newChild->Parent(this);
|
||||
return newChild;
|
||||
}
|
||||
|
||||
for (Widget* child : children)
|
||||
{
|
||||
child->ObserveMouseInput(btn, pressed);
|
||||
}
|
||||
}
|
||||
void Widget::AnchorPoint(const Vector2& point) {
|
||||
anchor_point = point;
|
||||
}
|
||||
|
||||
void Widget::ObserveMouseMovement(const Vector2 &latest_known_pos) {
|
||||
int Widget::ZIndex() const { return zindex;}
|
||||
|
||||
last_known_mouse_pos = latest_known_pos;
|
||||
void Widget::ZIndex(int new_zindex) { zindex = new_zindex; }
|
||||
|
||||
for (Widget* child : children)
|
||||
{
|
||||
child->ObserveMouseMovement(latest_known_pos);
|
||||
}
|
||||
}
|
||||
AABB2D Widget::GetActualRenderBounds() const {
|
||||
return {GetAbsolutePosition(), GetAbsoluteSize()};
|
||||
}
|
||||
|
||||
void Widget::ObserveKeyInput(Key key, bool pressed) {
|
||||
for (Widget* child : children) {
|
||||
child->ObserveKeyInput(key, pressed);
|
||||
}
|
||||
}
|
||||
void Widget::SetViewportSize(const Vector2 &vps) {
|
||||
viewport_size = vps;
|
||||
|
||||
for(auto& child : children)
|
||||
child->SetViewportSize(viewport_size);
|
||||
}
|
||||
|
||||
bool Widget::IsAncestorOf(Widget *descendant) const {
|
||||
if (descendant == nullptr)
|
||||
return false;
|
||||
Widget *instance = descendant;
|
||||
while (instance->GetParent()) {
|
||||
instance = instance->GetParent();
|
||||
if (instance == this)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
AABB2D Widget::AbsoluteBounds() const {
|
||||
return {GetAbsolutePosition(), GetAbsoluteSize()};
|
||||
}
|
||||
|
||||
bool Widget::IsDescendantOf(Widget *ancestor) const {
|
||||
if (ancestor == nullptr)
|
||||
return false;
|
||||
const Widget *instance = this;
|
||||
while (instance->GetParent()) {
|
||||
instance = instance->GetParent();
|
||||
if (instance == ancestor)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
Tween* Widget::TweenPosition(const UDim2& goal, TweenInfo params) {
|
||||
UDim2 start_position = this->Position();
|
||||
TweenTickFunc updateTillGoalReached = [this, start_position, goal] (float elapsed, float progress) mutable {
|
||||
UDim2 pos = start_position.Lerp(goal, progress);
|
||||
Position(pos);
|
||||
};
|
||||
|
||||
Widget *Widget::Add(Widget *newChild) {
|
||||
newChild->Parent(this);
|
||||
return newChild;
|
||||
}
|
||||
Tween* t = new Tween(updateTillGoalReached, params);
|
||||
tweens.push_back(t);
|
||||
return t;
|
||||
}
|
||||
|
||||
void Widget::AnchorPoint(const Vector2& point) {
|
||||
anchor_point = point;
|
||||
}
|
||||
Tween* Widget::TweenSize(const UDim2& goal, TweenInfo params) {
|
||||
UDim2 start_size = this->Size();
|
||||
TweenTickFunc updateTillGoalReached = [this, start_size, goal] (float elapsed, float progress) mutable {
|
||||
UDim2 step_size = start_size.Lerp(goal, progress);
|
||||
Size(step_size);
|
||||
};
|
||||
|
||||
int Widget::ZIndex() const { return zindex;}
|
||||
Tween* t = new Tween(updateTillGoalReached, params);
|
||||
tweens.push_back(t);
|
||||
return t;
|
||||
}
|
||||
|
||||
void Widget::ZIndex(int new_zindex) { zindex = new_zindex; }
|
||||
Tween* Widget::TweenPaddingLeft(const JUI::UDim& goal, JUI::TweenInfo info) {
|
||||
//UDum2
|
||||
UDim start_padding = this->PaddingLeft();
|
||||
TweenTickFunc updateTillGoalReached = [this, start_padding, goal] (float elapsed, float progress) mutable {
|
||||
UDim step_padding = start_padding.Lerp(goal, progress);
|
||||
PaddingLeft(step_padding);
|
||||
};
|
||||
|
||||
AABB2D Widget::GetActualRenderBounds() const {
|
||||
return {GetAbsolutePosition(), GetAbsoluteSize()};
|
||||
}
|
||||
Tween* t = new Tween(updateTillGoalReached, info);
|
||||
tweens.push_back(t);
|
||||
|
||||
void Widget::SetViewportSize(const Vector2 &vps) {
|
||||
viewport_size = vps;
|
||||
return t;
|
||||
}
|
||||
|
||||
for(auto& child : children)
|
||||
{
|
||||
child->SetViewportSize(viewport_size);
|
||||
}
|
||||
}
|
||||
Tween* Widget::TweenPaddingRight(const JUI::UDim& goal, JUI::TweenInfo info) {
|
||||
//UDum2
|
||||
UDim start_padding = this->PaddingRight();
|
||||
TweenTickFunc updateTillGoalReached = [this, start_padding, goal] (float elapsed, float progress) mutable {
|
||||
UDim step_padding = start_padding.Lerp(goal, progress);
|
||||
PaddingRight(step_padding);
|
||||
};
|
||||
|
||||
AABB2D Widget::AbsoluteBounds() const {
|
||||
return {GetAbsolutePosition(), GetAbsoluteSize()};
|
||||
}
|
||||
Tween* t = new Tween(updateTillGoalReached, info);
|
||||
tweens.push_back(t);
|
||||
return t;
|
||||
}
|
||||
|
||||
Tween *Widget::TweenPositionTo(const UDim2 &goal, TweenInfo params) {
|
||||
UDim2 start_position = this->Position();
|
||||
TweenTickFunc updateTillGoalReached = [this, start_position, goal] (float elapsed, float progress) mutable {
|
||||
UDim2 pos = start_position.Lerp(goal, progress);
|
||||
Position(pos);
|
||||
};
|
||||
Tween* t = new Tween(updateTillGoalReached, params);
|
||||
tweens.push_back(t);
|
||||
return t;
|
||||
}
|
||||
Tween* Widget::TweenPaddingTop(const JUI::UDim& goal, JUI::TweenInfo info) {
|
||||
//UDum2
|
||||
UDim start_padding = this->PaddingTop();
|
||||
TweenTickFunc updateTillGoalReached = [this, start_padding, goal] (float elapsed, float progress) mutable {
|
||||
UDim step_padding = start_padding.Lerp(goal, progress);
|
||||
PaddingTop(step_padding);
|
||||
};
|
||||
|
||||
Tween *Widget::TweenSizeTo(const UDim2 &goal, TweenInfo info) {
|
||||
UDim2 start_size = this->Size();
|
||||
TweenTickFunc updateTillGoalReached = [this, start_size, goal] (float elapsed, float progress) mutable {
|
||||
UDim2 step_size = start_size.Lerp(goal, progress);
|
||||
Size(step_size);
|
||||
};
|
||||
Tween* t = new Tween(updateTillGoalReached, info);
|
||||
tweens.push_back(t);
|
||||
return t;
|
||||
}
|
||||
Tween* t = new Tween(updateTillGoalReached, info);
|
||||
tweens.push_back(t);
|
||||
return t;
|
||||
}
|
||||
|
||||
Tween* Widget::TweenPaddingBottom(const JUI::UDim& goal, JUI::TweenInfo info) {
|
||||
//UDum2
|
||||
UDim start_padding = this->PaddingBottom();
|
||||
TweenTickFunc updateTillGoalReached = [this, start_padding, goal] (float elapsed, float progress) mutable {
|
||||
UDim step_padding = start_padding.Lerp(goal, progress);
|
||||
PaddingBottom(step_padding);
|
||||
};
|
||||
|
||||
Tween* t = new Tween(updateTillGoalReached, info);
|
||||
tweens.push_back(t);
|
||||
return t;
|
||||
}
|
||||
|
||||
Tween *Widget::TweenPadding(const JUI::UDim &gl, const JUI::UDim >, const JUI::UDim &gr,
|
||||
const JUI::UDim &gb, JUI::TweenInfo info) {
|
||||
UDim spl = this->PaddingLeft();
|
||||
UDim spr = this->PaddingRight();
|
||||
UDim spt = this->PaddingTop();
|
||||
UDim spb = this->PaddingBottom();
|
||||
|
||||
TweenTickFunc updateTillGoalReached = [this, spl, spr, spt, spb, gl, gt, gr, gb] (float elapsed, float progress) mutable {
|
||||
UDim step_l = spl.Lerp(gl, progress);
|
||||
UDim step_r = spr.Lerp(gr, progress);
|
||||
UDim step_b = spb.Lerp(gb, progress);
|
||||
UDim step_t = spt.Lerp(gt, progress);
|
||||
Padding(step_l, step_r, step_b, step_t);
|
||||
};
|
||||
|
||||
Tween* t = new Tween(updateTillGoalReached, info);
|
||||
tweens.push_back(t);
|
||||
return t;
|
||||
}
|
||||
|
||||
Tween *Widget::TweenPadding(const JUI::UDim &goal, JUI::TweenInfo info) {
|
||||
UDim start_padding = this->PaddingTop(); // TODO: Determine which side is most appropriate as start_point.
|
||||
TweenTickFunc updateTillGoalReached = [this, start_padding, goal] (float elapsed, float progress) mutable {
|
||||
UDim step_padding = start_padding.Lerp(goal, progress);
|
||||
Padding(step_padding);
|
||||
};
|
||||
|
||||
Tween* t = new Tween(updateTillGoalReached, info);
|
||||
tweens.push_back(t);
|
||||
return t;
|
||||
}
|
||||
|
||||
Tween *Widget::TweenMargin(const JUI::UDim &gl, const JUI::UDim >, const JUI::UDim &gr,
|
||||
const JUI::UDim &gb, JUI::TweenInfo info) {
|
||||
UDim spl = this->MarginLeft();
|
||||
UDim spr = this->MarginRight();
|
||||
UDim spt = this->MarginTop();
|
||||
UDim spb = this->MarginBottom();
|
||||
|
||||
TweenTickFunc updateTillGoalReached = [this, spl, spr, spt, spb, gl, gt, gr, gb] (float elapsed, float progress) mutable {
|
||||
UDim step_l = spl.Lerp(gl, progress);
|
||||
UDim step_r = spr.Lerp(gr, progress);
|
||||
UDim step_b = spb.Lerp(gb, progress);
|
||||
UDim step_t = spt.Lerp(gt, progress);
|
||||
Margin(step_l, step_r, step_b, step_t);
|
||||
};
|
||||
|
||||
Tween* t = new Tween(updateTillGoalReached, info);
|
||||
tweens.push_back(t);
|
||||
return t;
|
||||
}
|
||||
|
||||
Tween *Widget::TweenMargin(const JUI::UDim &goal, JUI::TweenInfo info) {
|
||||
UDim start_Margin = this->MarginTop(); // TODO: Determine which side is most appropriate as start_point.
|
||||
TweenTickFunc updateTillGoalReached = [this, start_Margin, goal] (float elapsed, float progress) mutable {
|
||||
UDim step_Margin = start_Margin.Lerp(goal, progress);
|
||||
Margin(step_Margin);
|
||||
};
|
||||
|
||||
Tween* t = new Tween(updateTillGoalReached, info);
|
||||
tweens.push_back(t);
|
||||
return t;
|
||||
}
|
||||
|
||||
Tween* Widget::TweenMarginLeft(const JUI::UDim& goal, JUI::TweenInfo info) {
|
||||
UDim start = this->MarginLeft();
|
||||
TweenTickFunc updateTillGoalReached = [this, start, goal] (float elapsed, float progress) mutable {
|
||||
UDim step = start.Lerp(goal, progress);
|
||||
MarginLeft(step);
|
||||
};
|
||||
|
||||
Tween* t = new Tween(updateTillGoalReached, info);
|
||||
tweens.push_back(t);
|
||||
return t;
|
||||
}
|
||||
|
||||
Tween* Widget::TweenMarginRight(const JUI::UDim& goal, JUI::TweenInfo info) {
|
||||
UDim start = this->MarginRight();
|
||||
TweenTickFunc updateTillGoalReached = [this, start, goal] (float elapsed, float progress) mutable {
|
||||
UDim step = start.Lerp(goal, progress);
|
||||
MarginRight(step);
|
||||
};
|
||||
|
||||
Tween* t = new Tween(updateTillGoalReached, info);
|
||||
tweens.push_back(t);
|
||||
return t;
|
||||
}
|
||||
|
||||
Tween* Widget::TweenMarginTop(const JUI::UDim& goal, JUI::TweenInfo info) {
|
||||
UDim start = this->MarginTop();
|
||||
TweenTickFunc updateTillGoalReached = [this, start, goal] (float elapsed, float progress) mutable {
|
||||
UDim step = start.Lerp(goal, progress);
|
||||
MarginTop(step);
|
||||
};
|
||||
|
||||
Tween* t = new Tween(updateTillGoalReached, info);
|
||||
tweens.push_back(t);
|
||||
return t;
|
||||
}
|
||||
|
||||
Tween* Widget::TweenMarginBottom(const JUI::UDim& goal, JUI::TweenInfo info) {
|
||||
UDim start = this->MarginBottom();
|
||||
TweenTickFunc updateTillGoalReached = [this, start, goal] (float elapsed, float progress) mutable {
|
||||
UDim step = start.Lerp(goal, progress);
|
||||
MarginBottom(step);
|
||||
};
|
||||
|
||||
Tween* t = new Tween(updateTillGoalReached, info);
|
||||
tweens.push_back(t);
|
||||
return t;
|
||||
}
|
@@ -195,4 +195,8 @@ namespace JUI
|
||||
bool Tween::HasCompleted() const { return completed; }
|
||||
|
||||
void Tween::Start() { progress = 0; Resume(); }
|
||||
|
||||
Tween::Tween(TweenTickFunc tick_func) {
|
||||
this->tick_func = tick_func;
|
||||
}
|
||||
}
|
@@ -5,4 +5,31 @@ namespace JUI
|
||||
{
|
||||
|
||||
|
||||
Checkbox::Checkbox() : Button(), CheckboxBase() { }
|
||||
|
||||
Checkbox::Checkbox(Widget *parent) : Checkbox()
|
||||
{
|
||||
this->Parent(parent);
|
||||
}
|
||||
|
||||
void Checkbox::Update(float delta) {
|
||||
Button::Update(delta);
|
||||
}
|
||||
|
||||
void Checkbox::OnRelease(const Vector2 &mouse_pos, const MouseButton &bnt, bool still_hovering) {
|
||||
Button::OnRelease(mouse_pos, bnt, still_hovering);
|
||||
checked = !checked;
|
||||
}
|
||||
|
||||
void Checkbox::InnerDraw() {
|
||||
Rect::InnerDraw();
|
||||
if (checked)
|
||||
{
|
||||
//J2D::Begin();
|
||||
Vector2 check_padding = {2, 2};
|
||||
RectBase::Draw(check_color, check_color, GetAbsolutePosition()+check_padding, GetAbsoluteSize()-(check_padding*2));
|
||||
//J2D::End();
|
||||
|
||||
}
|
||||
}
|
||||
}
|
@@ -8,3 +8,7 @@ void JUI::ImageButton::Draw() {
|
||||
Button::Draw();
|
||||
ImageBase::Draw(GetAbsolutePosition()+GetAbsolutePaddingTopLeft(), GetAbsoluteSize()-GetAbsolutePaddingBottomRight());
|
||||
}
|
||||
|
||||
JUI::ImageButton::ImageButton() : ImageBase(), Button() {}
|
||||
|
||||
JUI::ImageButton::ImageButton(JUI::Widget *parent) : ImageButton() { Parent(parent); }
|
||||
|
@@ -1,2 +1,16 @@
|
||||
#include <JUI/Widgets/ImageRect.hpp>
|
||||
|
||||
JUI::ImageRect::ImageRect() : Rect(), ImageBase() {}
|
||||
|
||||
JUI::ImageRect::ImageRect(JUI::Widget *parent) : ImageRect() {
|
||||
Parent(parent);
|
||||
}
|
||||
|
||||
void JUI::ImageRect::Update(float delta) {
|
||||
Rect::Update(delta);
|
||||
}
|
||||
|
||||
void JUI::ImageRect::Draw() {
|
||||
Rect::Draw();
|
||||
ImageBase::Draw(GetAbsolutePosition()+GetAbsolutePaddingTopLeft(), GetAbsoluteSize()-GetAbsolutePaddingBottomRight());
|
||||
}
|
||||
|
@@ -11,7 +11,6 @@ namespace JUI
|
||||
this->Parent(parent);
|
||||
}
|
||||
|
||||
|
||||
struct {
|
||||
bool operator()(Widget* a, Widget* b) const { return a->LayoutOrder() > b->LayoutOrder();}
|
||||
} layoutOrderSort;
|
||||
|
Reference in New Issue
Block a user