A ton of edits.. I don't even know
This commit is contained in:
@@ -1,6 +1,6 @@
|
|||||||
cmake_minimum_required(VERSION 3.18..3.27)
|
cmake_minimum_required(VERSION 3.18..3.27)
|
||||||
project(JUI
|
project(JUI
|
||||||
VERSION 1.1
|
VERSION 4.0
|
||||||
LANGUAGES CXX)
|
LANGUAGES CXX)
|
||||||
|
|
||||||
if (PROJECT_SOURCE_DIR STREQUAL PROJECT_BINARY_DIR)
|
if (PROJECT_SOURCE_DIR STREQUAL PROJECT_BINARY_DIR)
|
||||||
|
@@ -11,6 +11,16 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
|
||||||
|
/// Ideal refactor:
|
||||||
|
/// * Completely separate Component for a given behavior / area of concern
|
||||||
|
/// * XYZStyler class, stored as a pointer in the widget.
|
||||||
|
/// * Smart pointers
|
||||||
|
/// * Intelligent layout.
|
||||||
|
/// *
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#include <Event.h>
|
#include <Event.h>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
@@ -31,17 +41,37 @@ namespace JUI {
|
|||||||
using namespace J3ML::Math;
|
using namespace J3ML::Math;
|
||||||
using namespace J3ML::LinearAlgebra;
|
using namespace J3ML::LinearAlgebra;
|
||||||
|
|
||||||
|
struct EventArgs {
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
struct FocusedArgs {};
|
||||||
|
struct UnfocusedEventArgs {};
|
||||||
|
struct ChildAddedEventArgs {};
|
||||||
|
struct ChildRemovedEventArgs {};
|
||||||
|
|
||||||
|
/// TODO: Refactor the member functions providing the parent-child hierarchy into the Node mixin.
|
||||||
|
template <class TNode>
|
||||||
|
class Node {
|
||||||
|
public:
|
||||||
|
|
||||||
|
protected:
|
||||||
|
std::vector<TNode*> children;
|
||||||
|
TNode* parent;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
/// Widget is the base class for all JUI elements and represents any object that can be in the tree hierarchy.
|
/// Widget is the base class for all JUI elements and represents any object that can be in the tree hierarchy.
|
||||||
/// Some widgets are expressly used for layout, and therefore do not strictly speaking 'Appear' on screen.
|
/// Some widgets are expressly used for layout, and therefore do not strictly-speaking 'Appear' on screen.
|
||||||
/// Widgets exist in a tree hierarchy where each object has one parent, and an arbitrary number of children. No circular references are allowed.
|
/// Widgets exist in a tree hierarchy where each object has one parent, and an arbitrary number of children. No circular references are allowed.
|
||||||
class Widget {
|
class Widget {
|
||||||
public:
|
public:
|
||||||
/// The default constructor for Widget. Generally, JUI widgets will initialize member data,
|
/// The default constructor for Widget. Generally, JUI widgets will initialize member data,
|
||||||
/// and apply a default style in this constructor. Be aware of this, as this is not "idiomatic C++".
|
/// and apply a default style in this constructor. Be aware of this, as this is not "idiomatic C++".
|
||||||
Widget();
|
Widget();
|
||||||
/// Construct a new widget by specifying it's parent,
|
/// Construct a new widget by specifying its parent,
|
||||||
explicit Widget(Widget* parent);
|
explicit Widget(Widget* parent);
|
||||||
virtual ~Widget() {}
|
virtual ~Widget() = default;
|
||||||
public:
|
public:
|
||||||
#pragma region Events
|
#pragma region Events
|
||||||
/// An event that triggers when the widget is in-focus, generally when the mouse is hovering it.
|
/// An event that triggers when the widget is in-focus, generally when the mouse is hovering it.
|
||||||
@@ -111,6 +141,8 @@ namespace JUI {
|
|||||||
/// In a well-formed JUI menu, this **should** always be a Scene.
|
/// In a well-formed JUI menu, this **should** always be a Scene.
|
||||||
Widget* GetFamilyTreeRoot() const;
|
Widget* GetFamilyTreeRoot() const;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#pragma endregion
|
#pragma endregion
|
||||||
|
|
||||||
#pragma region Layout
|
#pragma region Layout
|
||||||
@@ -391,6 +423,8 @@ namespace JUI {
|
|||||||
int layout_order = 0;
|
int layout_order = 0;
|
||||||
Vector2 viewport_size{0,0};
|
Vector2 viewport_size{0,0};
|
||||||
|
|
||||||
|
bool is_mouse_inside = false;
|
||||||
|
|
||||||
/// Returns the amount of pixels this widget will be padded by from the top-left.
|
/// Returns the amount of pixels this widget will be padded by from the top-left.
|
||||||
/// Generally, the widget will be shrunk and moved over by this amount, relative to the parent.
|
/// Generally, the widget will be shrunk and moved over by this amount, relative to the parent.
|
||||||
Vector2 GetAbsolutePaddingTopLeft() const;
|
Vector2 GetAbsolutePaddingTopLeft() const;
|
||||||
@@ -401,5 +435,8 @@ namespace JUI {
|
|||||||
Vector2 GetAbsoluteMarginTopLeft();
|
Vector2 GetAbsoluteMarginTopLeft();
|
||||||
Vector2 GetAbsoluteMarginBottomRight();
|
Vector2 GetAbsoluteMarginBottomRight();
|
||||||
void UpdateTweens(float elapsed);
|
void UpdateTweens(float elapsed);
|
||||||
|
|
||||||
|
/// Calculate if mouse is inside this element at the start of it's update frame.
|
||||||
|
bool ComputeIsMouseInside() const;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@@ -14,10 +14,27 @@
|
|||||||
#include <J3ML/LinearAlgebra/Vector2.hpp>
|
#include <J3ML/LinearAlgebra/Vector2.hpp>
|
||||||
#include <JUI/Base/Widget.hpp>
|
#include <JUI/Base/Widget.hpp>
|
||||||
|
|
||||||
|
#include "Hoverable.hpp"
|
||||||
|
|
||||||
namespace JUI {
|
namespace JUI {
|
||||||
|
|
||||||
|
|
||||||
|
struct ClickEventArgs {
|
||||||
|
public:
|
||||||
|
protected:
|
||||||
|
private:
|
||||||
|
};
|
||||||
|
struct ReleaseEventArgs {
|
||||||
|
public:
|
||||||
|
protected:
|
||||||
|
private:
|
||||||
|
};
|
||||||
|
|
||||||
/// A mixin helper class that provides behavior and events for clickable widgets.
|
/// A mixin helper class that provides behavior and events for clickable widgets.
|
||||||
class Clickable {
|
class Clickable {
|
||||||
public:
|
public:
|
||||||
|
Event<std::optional<ClickEventArgs>> Clicked;
|
||||||
|
Event<ReleaseEventArgs> Released;
|
||||||
|
|
||||||
Event<Vector2, MouseButton> OnClickEvent;
|
Event<Vector2, MouseButton> OnClickEvent;
|
||||||
Event<Vector2, MouseButton, bool> OnReleaseEvent;
|
Event<Vector2, MouseButton, bool> OnReleaseEvent;
|
||||||
@@ -34,4 +51,4 @@ namespace JUI {
|
|||||||
bool clicked = false;
|
bool clicked = false;
|
||||||
bool click_debounce = false;
|
bool click_debounce = false;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@@ -18,6 +18,14 @@
|
|||||||
|
|
||||||
namespace JUI
|
namespace JUI
|
||||||
{
|
{
|
||||||
|
|
||||||
|
/// Interface for anything that can report mouse presence.
|
||||||
|
class IMouseAware {
|
||||||
|
public:
|
||||||
|
virtual ~IMouseAware() = default;
|
||||||
|
virtual bool IsMouseAware() const = 0;
|
||||||
|
};
|
||||||
|
|
||||||
/// A mixin helper class that provides behavior for hoverable objects.
|
/// A mixin helper class that provides behavior for hoverable objects.
|
||||||
/// A hoverable object pays attention to when the mouse enters and leaves it's bounds.
|
/// A hoverable object pays attention to when the mouse enters and leaves it's bounds.
|
||||||
class Hoverable {
|
class Hoverable {
|
||||||
@@ -39,7 +47,10 @@ namespace JUI
|
|||||||
virtual void OnExitChildren(const Vector2& mouse);
|
virtual void OnExitChildren(const Vector2& mouse);
|
||||||
virtual void OnExitDescendants(const Vector2& mouse);
|
virtual void OnExitDescendants(const Vector2& mouse);
|
||||||
|
|
||||||
void Update(const Vector2& m_pos, float delta);
|
void Update(bool mouse_inside, float delta);
|
||||||
|
|
||||||
|
/// @note This member function **must** be implemented for classes that implement Hoverable.
|
||||||
|
//[[nodiscard]] virtual bool IsMouseInside() const = 0;
|
||||||
//virtual void SetTooltip(const std::string& content, float delay) {}
|
//virtual void SetTooltip(const std::string& content, float delay) {}
|
||||||
protected:
|
protected:
|
||||||
//Tooltip* tooltip = nullptr;
|
//Tooltip* tooltip = nullptr;
|
||||||
|
@@ -164,4 +164,11 @@ namespace JUI {
|
|||||||
private:
|
private:
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class ColorPickerDialog : public Window {
|
||||||
|
public:
|
||||||
|
protected:
|
||||||
|
private:
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -124,6 +124,5 @@ namespace JUI {
|
|||||||
protected:
|
protected:
|
||||||
FpsGraph* data_graph;
|
FpsGraph* data_graph;
|
||||||
private:
|
private:
|
||||||
|
|
||||||
};
|
};
|
||||||
}
|
}
|
@@ -17,6 +17,8 @@
|
|||||||
|
|
||||||
namespace JUI {
|
namespace JUI {
|
||||||
|
|
||||||
|
struct LinkInvokedEventArgs {};
|
||||||
|
|
||||||
/// Controls when Link widgets fire their Cicked callback. It can fire right when the widget is clicked, or when it is is released.
|
/// Controls when Link widgets fire their Cicked callback. It can fire right when the widget is clicked, or when it is is released.
|
||||||
enum class LinkClickMode { Press, Release };
|
enum class LinkClickMode { Press, Release };
|
||||||
|
|
||||||
@@ -24,8 +26,8 @@ namespace JUI {
|
|||||||
class Link : public Text, public Clickable, public Hoverable {
|
class Link : public Text, public Clickable, public Hoverable {
|
||||||
public:
|
public:
|
||||||
enum LinkClickMode ClickMode = LinkClickMode::Release;
|
enum LinkClickMode ClickMode = LinkClickMode::Release;
|
||||||
|
Event<std::optional<LinkInvokedEventArgs>> Invoked;
|
||||||
/// This event is fired when the user clicks/releases the link.
|
/// This event is fired when the user clicks/releases the link.
|
||||||
Event<> Clicked;
|
|
||||||
Link() : Text(), Clickable(), Hoverable() {}
|
Link() : Text(), Clickable(), Hoverable() {}
|
||||||
explicit Link(const std::string& content) : Link() {
|
explicit Link(const std::string& content) : Link() {
|
||||||
this->Content(content);
|
this->Content(content);
|
||||||
@@ -54,7 +56,7 @@ namespace JUI {
|
|||||||
TextColor(Colors::White);
|
TextColor(Colors::White);
|
||||||
|
|
||||||
if (!fire_on_release) {
|
if (!fire_on_release) {
|
||||||
Clicked.Invoke();
|
Clicked.Invoke(std::nullopt);
|
||||||
already_clicked = true;
|
already_clicked = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -69,7 +71,7 @@ namespace JUI {
|
|||||||
|
|
||||||
TextColor(Colors::Black);
|
TextColor(Colors::Black);
|
||||||
if (fire_on_release) {
|
if (fire_on_release) {
|
||||||
Clicked.Invoke();
|
Clicked.Invoke(std::nullopt);
|
||||||
already_clicked = true;
|
already_clicked = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -80,9 +82,8 @@ namespace JUI {
|
|||||||
Text::Update(delta);
|
Text::Update(delta);
|
||||||
|
|
||||||
// TODO: Why does hovered not handle this?
|
// TODO: Why does hovered not handle this?
|
||||||
hovered = IsMouseInside();
|
|
||||||
|
|
||||||
Hoverable::Update(last_known_mouse_pos, delta);
|
Hoverable::Update(IsMouseInside(), delta);
|
||||||
|
|
||||||
// TODO: This is duplicated between here and Window.cpp
|
// TODO: This is duplicated between here and Window.cpp
|
||||||
// Will be abstracted away into Clickable shortly.
|
// Will be abstracted away into Clickable shortly.
|
||||||
|
10
include/JUI/Widgets/ToggleButton.hpp
Normal file
10
include/JUI/Widgets/ToggleButton.hpp
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "Button.hpp"
|
||||||
|
|
||||||
|
|
||||||
|
namespace JUI {
|
||||||
|
/// The
|
||||||
|
class ToggleButton : public Button {
|
||||||
|
|
||||||
|
};
|
||||||
|
}
|
18
main.cpp
18
main.cpp
@@ -331,13 +331,21 @@ JUI::Rect* CreateWidgetList(JUI::Widget* root) {
|
|||||||
auto* radio_c_btn = new Checkbox(radio_btn_set_layout);
|
auto* radio_c_btn = new Checkbox(radio_btn_set_layout);
|
||||||
radio_c_btn->Size({20_px, 20_px});
|
radio_c_btn->Size({20_px, 20_px});
|
||||||
|
|
||||||
auto* linkbox = new Rect(collapsible->ContentBox());
|
auto* link_container = new Rect(collapsible->ContentBox());
|
||||||
linkbox->Size({100_percent, 30_px});
|
{
|
||||||
linkbox->Position({0_px, 20_px});
|
link_container->Size({100_percent, 30_px});
|
||||||
|
link_container->Position({0_px, 20_px});
|
||||||
|
|
||||||
|
auto* link = new JUI::Link(link_container);
|
||||||
|
link->Content("Clickable Link");
|
||||||
|
link->Clicked += [](auto event) {
|
||||||
|
std::cout << "Link Released" << std::endl;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
auto* link = new JUI::Link(linkbox);
|
|
||||||
link->Content("This Dick");
|
|
||||||
// What the FUCK?
|
// What the FUCK?
|
||||||
|
|
||||||
/*auto* radio_c_label = new TextRect(radio_btn_set_layout);
|
/*auto* radio_c_label = new TextRect(radio_btn_set_layout);
|
||||||
|
@@ -281,6 +281,9 @@ void Widget::UpdateTweens(float elapsed) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Widget::Update(float delta) {
|
void Widget::Update(float delta) {
|
||||||
|
|
||||||
|
is_mouse_inside = ComputeIsMouseInside();
|
||||||
|
|
||||||
UpdateChildWidgets(delta);
|
UpdateChildWidgets(delta);
|
||||||
UpdateTweens(delta);
|
UpdateTweens(delta);
|
||||||
}
|
}
|
||||||
@@ -313,7 +316,8 @@ Widget* Widget::GetFamilyTreeRoot() const {
|
|||||||
return parent->GetFamilyTreeRoot();
|
return parent->GetFamilyTreeRoot();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Widget::IsMouseInside() const {
|
|
||||||
|
bool Widget::ComputeIsMouseInside() const {
|
||||||
float x = last_known_mouse_pos.x;
|
float x = last_known_mouse_pos.x;
|
||||||
float y = last_known_mouse_pos.y;
|
float y = last_known_mouse_pos.y;
|
||||||
auto pos = GetAbsolutePosition();
|
auto pos = GetAbsolutePosition();
|
||||||
@@ -325,6 +329,20 @@ bool Widget::IsMouseInside() const {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Widget::IsMouseInside() const {
|
||||||
|
return is_mouse_inside;
|
||||||
|
|
||||||
|
/*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;*/
|
||||||
|
}
|
||||||
|
|
||||||
bool Widget::IsMouseInsideChildren(bool include_this) const {
|
bool Widget::IsMouseInsideChildren(bool include_this) const {
|
||||||
if (include_this)
|
if (include_this)
|
||||||
if (IsMouseInside())
|
if (IsMouseInside())
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
#include <JUI/Mixins/Clickable.hpp>
|
#include <JUI/Mixins/Clickable.hpp>
|
||||||
|
|
||||||
void JUI::Clickable::Update(const Vector2 &mpos, const JUI::MouseButton &btn, bool hovering) {
|
void JUI::Clickable::Update(const Vector2 &mpos, const JUI::MouseButton &btn, bool hovering) {
|
||||||
|
//Hoverable::Update(mpos, delta);
|
||||||
}
|
}
|
||||||
|
|
||||||
void JUI::Clickable::OnRelease(const Vector2 &MousePos, const JUI::MouseButton &MouseButton, bool MouseStillOver) {
|
void JUI::Clickable::OnRelease(const Vector2 &MousePos, const JUI::MouseButton &MouseButton, bool MouseStillOver) {
|
||||||
|
@@ -27,8 +27,9 @@ void JUI::Hoverable::OnExitDescendants(const Vector2& mouse) {
|
|||||||
// TODO: Implement
|
// TODO: Implement
|
||||||
}
|
}
|
||||||
|
|
||||||
void JUI::Hoverable::Update(const Vector2 &m_pos, float delta) {
|
void JUI::Hoverable::Update(bool mouse_inside, float delta) {
|
||||||
|
|
||||||
|
hovered = mouse_inside;
|
||||||
/*if (tooltip != nullptr)
|
/*if (tooltip != nullptr)
|
||||||
{
|
{
|
||||||
if (IsHovered()) {
|
if (IsHovered()) {
|
||||||
@@ -41,12 +42,12 @@ void JUI::Hoverable::Update(const Vector2 &m_pos, float delta) {
|
|||||||
|
|
||||||
|
|
||||||
if (IsHovered() && !hover_debounce) {
|
if (IsHovered() && !hover_debounce) {
|
||||||
OnHover(m_pos);
|
OnHover({0,0});
|
||||||
hover_debounce = true;
|
hover_debounce = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!IsHovered() && hover_debounce) {
|
if (!IsHovered() && hover_debounce) {
|
||||||
OnExit(m_pos);
|
OnExit({0,0});
|
||||||
hover_debounce = false;
|
hover_debounce = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -46,9 +46,8 @@ namespace JUI {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Button::Update(float delta) {
|
void Button::Update(float delta) {
|
||||||
hovered = IsMouseInside();
|
|
||||||
|
|
||||||
Hoverable::Update(last_known_mouse_pos, delta);
|
Hoverable::Update(IsMouseInside(), delta);
|
||||||
|
|
||||||
// TODO: This is duplicated between here and Window.cpp
|
// TODO: This is duplicated between here and Window.cpp
|
||||||
// Will be abstracted away into Clickable shortly.
|
// Will be abstracted away into Clickable shortly.
|
||||||
|
@@ -28,12 +28,8 @@ namespace JUI
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Slider::Update(float delta) {
|
void Slider::Update(float delta) {
|
||||||
bool selected = Rect::IsMouseInside();
|
|
||||||
|
|
||||||
|
Hoverable::Update(Rect::IsMouseInside(), delta);
|
||||||
hovered = IsMouseInside();
|
|
||||||
|
|
||||||
Hoverable::Update(last_known_mouse_pos, delta);
|
|
||||||
|
|
||||||
// TODO: This is duplicated between here and Window.cpp
|
// TODO: This is duplicated between here and Window.cpp
|
||||||
// Will be abstracted away into Clickable shortly.
|
// Will be abstracted away into Clickable shortly.
|
||||||
|
@@ -215,9 +215,8 @@ namespace JUI {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Widget::Update(delta);
|
Widget::Update(delta);
|
||||||
hovered = IsMouseInside();
|
|
||||||
|
|
||||||
Hoverable::Update(last_known_mouse_pos, delta);
|
Hoverable::Update(IsMouseInside(), delta);
|
||||||
|
|
||||||
// TODO: This is duplicated between here and Window.cpp
|
// TODO: This is duplicated between here and Window.cpp
|
||||||
// Will be abstracted away into Clickable shortly.
|
// Will be abstracted away into Clickable shortly.
|
||||||
@@ -226,7 +225,6 @@ namespace JUI {
|
|||||||
OnClick(last_known_mouse_pos, mbtn);
|
OnClick(last_known_mouse_pos, mbtn);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if (prev_mb_state && !mb_state)
|
if (prev_mb_state && !mb_state)
|
||||||
{
|
{
|
||||||
OnRelease(last_known_mouse_pos, mbtn, IsHovered());
|
OnRelease(last_known_mouse_pos, mbtn, IsHovered());
|
||||||
|
Reference in New Issue
Block a user