OnGod
This commit is contained in:
@@ -48,7 +48,7 @@ CPMAddPackage(
|
||||
|
||||
CPMAddPackage(
|
||||
NAME ReWindow
|
||||
URL https://git.redacted.cc/Redacted/ReWindow/archive/Prerelease-5.zip
|
||||
URL https://git.redacted.cc/Redacted/ReWindow/archive/Prerelease-6.zip
|
||||
)
|
||||
|
||||
CPMAddPackage(
|
||||
|
@@ -16,43 +16,86 @@ namespace JUI
|
||||
enum class V { Top, Center, Bottom }; // Vertical
|
||||
}
|
||||
|
||||
|
||||
/// How should a text widget behave when it's text runs out of room?
|
||||
enum class TextOverflowMode
|
||||
{
|
||||
WRAP, /// Wraps at the nearest 'word', or otherwise appropriate stop in text.
|
||||
WRAP_ANYWHERE, /// Wraps the text anywhere.
|
||||
TRUNCATE, /// Cuts the text off and suffixes '...' to indicate the lack of the full intended message.
|
||||
TRUNCATE_ANYWHERE, /// Cuts the text off and suffixes '...' to indicate the lack of the full intended message.
|
||||
TRUNCATE_NO_DOTS, /// Cuts the text off at the first appropriate break in text.
|
||||
TRUNCATE_ANYWHERE_NO_DOTS /// Cuts the text off at any point in the string.
|
||||
};
|
||||
|
||||
/// TextBase class, implements core mechanics of drawing text in JUI, and is used by Text Widget class.
|
||||
class TextBase {
|
||||
public:
|
||||
TextBase();
|
||||
|
||||
[[nodiscard]] std::string GetContent() const;
|
||||
[[nodiscard]] Color4 GetTextColor() const;
|
||||
[[nodiscard]] Color4 GetOutlineColor() const;
|
||||
[[nodiscard]] TextAlign::H GetHorizontalTextAlign() const;
|
||||
[[nodiscard]] TextAlign::V GetVerticalTextAlign() const;
|
||||
[[nodiscard]] bool GetWordWrap() const;
|
||||
|
||||
TextOverflowMode GetOverflowMode() const;
|
||||
|
||||
/// Returns the
|
||||
[[nodiscard]] Vector2 GetTextBounds() const;
|
||||
[[nodiscard]] Vector2 GetTextPosition() const;
|
||||
JGL::Font GetFont() const;
|
||||
u32 GetTextSize() const;
|
||||
[[nodiscard]] JGL::Font GetFont() const;
|
||||
[[nodiscard]] u32 GetTextSize() const;
|
||||
|
||||
void SetOverflowMode(const TextOverflowMode& mode);
|
||||
|
||||
void SetTextSize(u32 size);
|
||||
|
||||
void SetFont(const JGL::Font& font);
|
||||
|
||||
void SetContent(const std::string& content);
|
||||
|
||||
void SetTextColor(const Color4& color);
|
||||
|
||||
void SetOutlineColor(const Color4& color);
|
||||
|
||||
/// Set the horizontal alignment of this text widget in relation to it's parent,
|
||||
/// while keeping the text retained inside the parent widget's bounds.
|
||||
/// @see TextAlign::H
|
||||
void SetHorizontalTextAlign(const TextAlign::H& align);
|
||||
/// Set the vertical alignment of this text widget in relation to it's parent,
|
||||
/// while keeping the text retained inside the parent widget's bounds.
|
||||
/// @see TextAlign::V
|
||||
void SetVerticalTextAlign(const TextAlign::V& align);
|
||||
|
||||
/// Sets the horizontal and vertical alignment of this text widget.
|
||||
/// @see TextAlign::H and TextAlign::V.
|
||||
void SetTextAlign(const TextAlign::H& h_align, const TextAlign::V& v_align);
|
||||
|
||||
/// Aligns the text of this widget to the left-hand-side of the parent's bounding box.
|
||||
/// @see SetHorizontalTextAlign, TextAlign::H
|
||||
void AlignLeft();
|
||||
/// Aligns the text of this widget to the right-hand-side of the parent's bounding box.
|
||||
/// @see SetHorizontalTextAlign, TextAlign::H
|
||||
void AlignRight();
|
||||
/// Aligns the text of this widget to the top of the parent's bounding box.
|
||||
/// @see SetVerticalTextAlign, TextAlign::V
|
||||
void AlignTop();
|
||||
/// Aligns the text of this widget to the bottom of the parent's bounding box.
|
||||
/// @see SetVerticalTextAlign, TextAlign::V
|
||||
void AlignBottom();
|
||||
/// Centers the text of this widget in relation to the parent's bounding box.
|
||||
/// @see SetHorizontalTextAlign, SetVerticalTextAlign, TextAlign enums
|
||||
void AlignCenterBoth();
|
||||
/// Alias for AlignCenterBoth().
|
||||
void Center();
|
||||
/// Aligns the text of this widget to the horizontal center of the parent's bounding box.
|
||||
void AlignCenterHorizontally();
|
||||
/// Aligns the text of this widget to the vertical center of the parent's bounding box.
|
||||
void AlignCenterVertically();
|
||||
|
||||
|
||||
/// Renders the aligned text string within a bounding-box specified by abs_pos (top-left corner), and abs_size.
|
||||
/// @see Widget::Draw(), Text::Draw().
|
||||
void Draw(const Vector2& abs_pos, const Vector2& abs_size);
|
||||
|
||||
void SetWordWrap(bool wrap);
|
||||
@@ -65,8 +108,10 @@ namespace JUI
|
||||
bool word_wrap = false;
|
||||
TextAlign::H h_align = TextAlign::H::Left;
|
||||
TextAlign::V v_align = TextAlign::V::Top;
|
||||
TextOverflowMode overflow_mode;
|
||||
JGL::Font set_font;
|
||||
u32 text_size;
|
||||
|
||||
};
|
||||
|
||||
}
|
@@ -44,9 +44,13 @@ namespace JUI
|
||||
Event<Widget *> ChildRemoved;
|
||||
Event<Widget *> Destroying;
|
||||
public:
|
||||
|
||||
|
||||
/// Adds a given widget to this widget's list of children.
|
||||
/// @return The widget in question.
|
||||
Widget* Add(Widget* newChild);
|
||||
bool IsAncestorOf(Widget* w) const;
|
||||
bool IsDescendantOf(Widget* w) const;
|
||||
bool IsAncestorOf(Widget* descendant) const;
|
||||
bool IsDescendantOf(Widget* ancestor) const;
|
||||
|
||||
/// Returns the first child widget that has the given symbolic name, Otherwise, a nullpointer is returned
|
||||
/// TODO: Use std::optional here and anywhere else a nullptr could be returned.
|
||||
@@ -69,8 +73,12 @@ namespace JUI
|
||||
/// TODO: Use std::optional here and anywhere else a nullptr could be returned.
|
||||
Widget* GetParent() const;
|
||||
|
||||
/// Returns the menu-coordinates that are used to position this widget in relation to its parent.
|
||||
/// @see class UDim2, SetSize(),
|
||||
[[nodiscard]] UDim2 GetPosition() const;
|
||||
|
||||
/// Returns the menu-coordinates that are used to size this widget in relation to its parent.
|
||||
/// @see SetSize(), class UDim2
|
||||
[[nodiscard]] UDim2 GetSize() const;
|
||||
|
||||
void SetPosition(const UDim2 &pos);
|
||||
@@ -99,35 +107,86 @@ namespace JUI
|
||||
|
||||
void SetPadding(const UDim& padding);
|
||||
|
||||
/// Returns the margin factor on the left of this widget.
|
||||
[[nodiscard]] UDim GetMarginLeft() const;
|
||||
/// Returns the margin factor on the top of this widget.
|
||||
[[nodiscard]] UDim GetMarginTop() const;
|
||||
/// Returns the margin factor on the right of this widget.
|
||||
[[nodiscard]] UDim GetMarginRight() const;
|
||||
|
||||
/// Returns the margin factor on the bottom of this widget.
|
||||
[[nodiscard]] UDim GetMarginBottom() const;
|
||||
|
||||
/// Sets the amount (in Pixels + Scale) to apply margin on the left-side of the widget.
|
||||
/// @see UDim, SetMargin()
|
||||
void SetMarginLeft(const UDim &ml);
|
||||
/// Sets the amount (in Pixels + Scale) to apply margin on the top-side of the widget.
|
||||
/// @see UDim, SetMargin()
|
||||
void SetMarginTop(const UDim &mt);
|
||||
/// Sets the amount (in Pixels + Scale) to apply margin on the right-side of the widget.
|
||||
/// @see UDim, SetMargin()
|
||||
void SetMarginRight(const UDim &mr);
|
||||
/// Sets the amount (in Pixels + Scale) to apply margin on the bottom-side of the widget.
|
||||
/// @see UDim, SetMargin()
|
||||
void SetMarginBottom(const UDim &mb);
|
||||
|
||||
/// Sets the margin factor of each side of the widget.
|
||||
/// @param left The amount of margin to apply on the left. (Pixels, Scale)
|
||||
/// @param top The amount of margin to apply on the top.
|
||||
/// @param right The amount of margin to apply on the right.
|
||||
/// @param bottom The amount of margin to apply on the bottom.
|
||||
void SetMargin(const UDim& left, const UDim& top, const UDim& right, const UDim& bottom);
|
||||
|
||||
/// Sets the margin factor on all four sides of this widget to the same value.
|
||||
/// @see SetMargin(const UDim&, const UDim&, const UDim&, const UDim&).
|
||||
void SetMargin(const UDim& margin);
|
||||
|
||||
|
||||
/// 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 GetName().
|
||||
[[nodiscard]] std::string GetName() const;
|
||||
|
||||
/// Sets this widgets mnemonic name.
|
||||
/// Widgets can optionally be assigned a name that can be used to retrieve it from a widget tree node.
|
||||
/// @see GetName().
|
||||
void SetName(const std::string &new_name);
|
||||
|
||||
/// Returns whether the widget is to be rendered.
|
||||
/// This function does not indicate whether the widget is **actually seeable** on-screen.
|
||||
/// @see SetVisible().
|
||||
[[nodiscard]] bool IsVisible() const;
|
||||
|
||||
/// Sets whether the widget is to be rendered. Children are also not rendered if disabled.
|
||||
/// @see IsVisible().
|
||||
void SetVisible(bool enabled);
|
||||
|
||||
|
||||
/// Returns the first ancestor in this widgets hierarchy that does not have its own parent.
|
||||
/// In a well-formed JUI menu, this **should** always be a Scene.
|
||||
Widget* GetFamilyTreeRoot() const;
|
||||
|
||||
public:
|
||||
/// Renders the widget to the current OpenGL Context using JGL.
|
||||
/// The user should call this on their Scene instances only. JUI will handle the rest.
|
||||
virtual void Draw();
|
||||
/// Performs the update logic of the widget.
|
||||
/// The user should call this on their Scene instances only. JUI will handle the rest.
|
||||
virtual void Update(float delta);
|
||||
/// Informs a widget that the mouse has been moved to a new location.
|
||||
/// This is designed in such a way that the end-user can plug this into their existing code.
|
||||
/// The user should call this on their Scene instances only. JUI will handle the rest.
|
||||
/// See ReWindowIntegrationDemo for an example.
|
||||
virtual void ObserveMouseMovement(const Vector2& latest_known_pos);
|
||||
/// Informs a widget that a mouse button has pressed or released.
|
||||
/// This is designed in such a way that the end-user can plug this into their existing code.
|
||||
/// The user should call this on their Scene instances only. JUI will handle the rest.
|
||||
/// See ReWindowIntegrationDemo for an example.
|
||||
virtual void ObserveMouseInput(int btn, bool pressed);
|
||||
protected:
|
||||
void DrawChildWidgets();
|
||||
void UpdateChildWidgets(float delta);
|
||||
Widget* GetFamilyTreeRoot() const;
|
||||
protected:
|
||||
Vector2 last_known_mouse_pos;
|
||||
UDim2 position;
|
||||
UDim2 size;
|
||||
Widget* parent = nullptr;
|
||||
|
@@ -7,6 +7,12 @@ namespace JUI
|
||||
{
|
||||
class Button : public Widget, public RectBase, public Clickable
|
||||
{
|
||||
public:
|
||||
Color4 GetHoveredBGColor()
|
||||
{
|
||||
|
||||
}
|
||||
protected:
|
||||
private:
|
||||
};
|
||||
}
|
@@ -47,6 +47,7 @@ namespace JUI {
|
||||
|
||||
void SetBorderStyling(const Color4& color, float width);
|
||||
protected:
|
||||
bool mouse_inside_debounce;
|
||||
float border_width = 1.f;
|
||||
Color4 bg_color = {128,128,128, 255};
|
||||
Color4 border_color = {192, 192, 192, 0};
|
||||
|
@@ -1,5 +1,5 @@
|
||||
#pragma once
|
||||
#include "JUI/Base/Widget.hpp"
|
||||
#include <JUI/Base/Widget.hpp>
|
||||
|
||||
|
||||
namespace JUI
|
||||
@@ -12,6 +12,12 @@ namespace JUI
|
||||
void Draw() override;
|
||||
void SetViewportSize(int w, int h);
|
||||
|
||||
// TODO: Interface for passing input to JUI in a relatively
|
||||
// independent way
|
||||
Event<Vector2> MouseMoved;
|
||||
|
||||
|
||||
|
||||
void Update(float delta) override;
|
||||
|
||||
[[nodiscard]] Vector2 GetAbsolutePosition() const override;
|
||||
|
43
main.cpp
43
main.cpp
@@ -32,6 +32,16 @@ JUI::Scene* CreateScene() {
|
||||
auto size = UDim2(64, 64, 0, 0);
|
||||
element->SetSize({0, 0, 0.5f, 0.5f});
|
||||
element->SetClipsDescendants(true);
|
||||
element->SetBorderColor({255,255,255});
|
||||
element->SetBorderWidth(2.f);
|
||||
|
||||
element->MouseEnter += [element] (auto coords) {
|
||||
element->SetBGColor({0,128,0});
|
||||
};
|
||||
|
||||
element->MouseExit += [element] (auto coords) {
|
||||
element->SetBGColor({0, 64, 0});
|
||||
};
|
||||
|
||||
Text* text = new Text(element);
|
||||
text->SetContent("YO MAMA");
|
||||
@@ -55,10 +65,8 @@ public:
|
||||
|
||||
// TODO: Delete when we update to the next release of JGL
|
||||
glPixelStorei(GL_UNPACK_ALIGNMENT, 1); // NOTE: This MUST be called for text rendering to work properly!!!
|
||||
|
||||
}
|
||||
|
||||
|
||||
void Update()
|
||||
{
|
||||
scene->Update(0.f);
|
||||
@@ -95,6 +103,7 @@ public:
|
||||
|
||||
int main()
|
||||
{
|
||||
using namespace ReWindow;
|
||||
//LOGLEVEL(jlog::severity::none)
|
||||
|
||||
auto* window = new JUIDevelopmentTestWindow("Test Window", 800, 600);
|
||||
@@ -118,6 +127,36 @@ int main()
|
||||
JGL::Update(size);
|
||||
};
|
||||
|
||||
window->OnMouseMoveEvent += [&] (MouseMoveEvent e)
|
||||
{
|
||||
scene->ObserveMouseMovement(e.Position);
|
||||
};
|
||||
|
||||
window->OnMouseButtonUpEvent += [&] (MouseButtonUpEvent e) {
|
||||
/// Invalid operands to binary expression 'MouseButton' and 'const MouseButton'
|
||||
if (e.Button == MouseButtons::Left)
|
||||
scene->ObserveMouseInput(1, false);
|
||||
if (e.Button == MouseButtons::Middle)
|
||||
scene->ObserveMouseInput(2, false);
|
||||
if (e.Button == MouseButtons::Right)
|
||||
scene->ObserveMouseInput(3, false);
|
||||
};
|
||||
|
||||
window->OnMouseButtonDownEvent += [&] (MouseButtonDownEvent e) {
|
||||
if (e.Button == MouseButtons::Left)
|
||||
scene->ObserveMouseInput(1, true);
|
||||
if (e.Button == MouseButtons::Middle)
|
||||
scene->ObserveMouseInput(2, true);
|
||||
if (e.Button == MouseButtons::Right)
|
||||
scene->ObserveMouseInput(3, true);
|
||||
};
|
||||
|
||||
window->OnMouseButtonDownEvent += [&] (MouseButtonDownEvent e) {};
|
||||
|
||||
window->OnKeyDownEvent += [&] (KeyDownEvent e) {};
|
||||
|
||||
window->OnKeyUpEvent += [&] (KeyUpEvent e) {};
|
||||
|
||||
while (window->isAlive()) {
|
||||
window->pollEvents();
|
||||
window->refresh();
|
||||
|
@@ -101,8 +101,6 @@ namespace JUI {
|
||||
|
||||
TextAlign::V TextBase::GetVerticalTextAlign() const {return v_align;}
|
||||
|
||||
bool TextBase::GetWordWrap() const {return word_wrap;}
|
||||
|
||||
Vector2 TextBase::GetTextBounds() const { return GetFont().MeasureString(content, text_size); }
|
||||
|
||||
JGL::Font TextBase::GetFont() const { return set_font;}
|
||||
|
@@ -264,5 +264,51 @@ namespace JUI {
|
||||
return parent->GetFamilyTreeRoot();
|
||||
}
|
||||
|
||||
void Widget::ObserveMouseInput(int btn, bool 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);
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
Widget *Widget::Add(Widget *newChild) {
|
||||
newChild->SetParent(this);
|
||||
return newChild;
|
||||
}
|
||||
|
||||
|
||||
}
|
@@ -59,6 +59,22 @@ namespace JUI {
|
||||
|
||||
|
||||
void Rect::Update(float delta) {
|
||||
|
||||
if (IsMouseInside() && !mouse_inside_debounce)
|
||||
{
|
||||
MouseEnter.Invoke(last_known_mouse_pos);
|
||||
mouse_inside_debounce = true;
|
||||
}
|
||||
|
||||
if (!IsMouseInside() && mouse_inside_debounce)
|
||||
{
|
||||
MouseExit.Invoke(last_known_mouse_pos);
|
||||
mouse_inside_debounce = false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
Widget::Update(delta);
|
||||
}
|
||||
|
||||
@@ -83,6 +99,17 @@ namespace JUI {
|
||||
SetBorderWidth(width);
|
||||
}
|
||||
|
||||
bool Rect::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;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
Reference in New Issue
Block a user