Refactor tweening some.
This commit is contained in:
@@ -34,8 +34,7 @@ namespace JUI {
|
||||
/// 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.
|
||||
/// 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:
|
||||
/// 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++".
|
||||
@@ -44,6 +43,7 @@ namespace JUI {
|
||||
Widget(Widget* parent);
|
||||
virtual ~Widget() {}
|
||||
public:
|
||||
#pragma region Events
|
||||
/// An event that triggers when the widget is in-focus, generally when the mouse is hovering it.
|
||||
/// (The actual trigger may differ for each widget)
|
||||
Event<> Focused;
|
||||
@@ -61,10 +61,9 @@ namespace JUI {
|
||||
Event<Widget *> ChildRemoved;
|
||||
/// This event triggers right before this widget gets deallocated.
|
||||
Event<Widget *> Destroying;
|
||||
#pragma endregion
|
||||
public:
|
||||
Tween* TweenPosition(const UDim2& goal, TweenInfo params = {});
|
||||
Tween* TweenSize(const UDim2& goal, TweenInfo params = {});
|
||||
|
||||
#pragma region Hierarchy
|
||||
/// Adds a given widget to this widget's list of children.
|
||||
/// @return The widget in question.
|
||||
Widget* Add(Widget* newChild);
|
||||
@@ -95,6 +94,24 @@ namespace JUI {
|
||||
/// @see GetFamilyTreeRoot().
|
||||
Widget* GetParent() const;
|
||||
|
||||
|
||||
/// Sets the parent object of this widget. Positioning and sizing of a widget is relative to it's parent.
|
||||
void Parent(Widget*);
|
||||
|
||||
/// Returns true if this widget is a 'descendant' of the specified potential ancestor. Otherwise returns false.
|
||||
bool IsDescendantOf(Widget *ancestor);
|
||||
|
||||
/// Returns true if this widget is a 'ancestor' of the specified potential descendant. Otherwise returns false.
|
||||
bool IsAncestorOf(Widget *descendant);
|
||||
|
||||
/// 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;
|
||||
|
||||
#pragma endregion
|
||||
|
||||
#pragma region Layout
|
||||
|
||||
/// Returns the menu-coordinates that are used to position this widget in relation to its parent.
|
||||
/// @see class UDim2, Position(const UDim2&),
|
||||
[[nodiscard]] UDim2 Position() const;
|
||||
@@ -125,17 +142,13 @@ namespace JUI {
|
||||
/// @see Size(), class UDim2.
|
||||
void Size(const UDim2&);
|
||||
|
||||
/// Sets the parent object of this widget. Positioning and sizing of a widget is relative to it's parent.
|
||||
void Parent(Widget*);
|
||||
/// Creates and runs an animation on the Position of this widget.
|
||||
Tween* TweenPosition(const UDim2& goal, TweenInfo params = {});
|
||||
|
||||
/// Returns true if this widget is a 'descendant' of the specified potential ancestor. Otherwise returns false.
|
||||
bool IsDescendantOf(Widget *ancestor);
|
||||
|
||||
/// Returns true if this widget is a 'ancestor' of the specified potential descendant. Otherwise returns false.
|
||||
bool IsAncestorOf(Widget *descendant);
|
||||
/// Creates and runs an animation on the Size of this widget.
|
||||
Tween* TweenSize(const UDim2& goal, TweenInfo params = {});
|
||||
|
||||
/// Determines the origin point of a Widget, relative to it's absolute size.
|
||||
/// TODO: Better explain what this allows for.
|
||||
[[nodiscard]] Vector2 AnchorPoint() const;
|
||||
|
||||
///
|
||||
@@ -144,6 +157,8 @@ namespace JUI {
|
||||
///
|
||||
Tween* TweenAnchorPoint(const Vector2& goal, TweenInfo info = {});
|
||||
|
||||
#pragma endregion
|
||||
|
||||
#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.
|
||||
@@ -245,6 +260,7 @@ namespace JUI {
|
||||
|
||||
#pragma endregion
|
||||
|
||||
#pragma region Metadata
|
||||
/// 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().
|
||||
@@ -264,9 +280,7 @@ namespace JUI {
|
||||
/// @see IsVisible().
|
||||
void Visible(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;
|
||||
|
||||
|
||||
/// Returns whether or not the mouse is inside this widget's approximate bounding-box.
|
||||
bool IsMouseInside() const;
|
||||
@@ -275,6 +289,10 @@ namespace JUI {
|
||||
void LayoutOrder(int value) { layout_order = value;}
|
||||
|
||||
|
||||
|
||||
|
||||
#pragma endregion
|
||||
|
||||
/// Returns the complete bounding box around this instance that will be rendered onto.
|
||||
/// This differs from AbsolutePosition and AbsoluteSize in that they are computed for positioning elements relative to each other.
|
||||
/// Only this method represents the full bounding box of the widget.
|
||||
@@ -290,12 +308,8 @@ namespace JUI {
|
||||
|
||||
public:
|
||||
|
||||
// TODO: Consider calling J2D::Begin here.
|
||||
virtual void PreDraw() {}
|
||||
// TODO: Consider calling J2D::End here.
|
||||
virtual void PostDraw() {}
|
||||
|
||||
|
||||
virtual void InnerDraw() {}
|
||||
|
||||
|
||||
|
@@ -85,13 +85,14 @@ namespace JUI
|
||||
int repeats = 0;
|
||||
bool reverse = false;
|
||||
EasingFunc easing = &EasingFunctions::EaseInOutLinear;
|
||||
bool overwritable = true;
|
||||
};
|
||||
|
||||
/// A class that represents an animation-in-action.
|
||||
class Tween {
|
||||
public:
|
||||
Tween(TweenTickFunc tick_func);
|
||||
Tween(TweenTickFunc tick_func, TweenInfo info) {
|
||||
Tween(TweenTickFunc tick_func, const TweenInfo& info) {
|
||||
this->tick_func = tick_func;
|
||||
|
||||
this->time = info.time;
|
||||
@@ -99,6 +100,7 @@ namespace JUI
|
||||
this->repeat_count = info.repeats;
|
||||
this->reverses = info.reverse;
|
||||
this->easing_func = info.easing;
|
||||
this->overwritable = info.overwritable;
|
||||
}
|
||||
Event<> Completed;
|
||||
|
||||
@@ -120,6 +122,7 @@ namespace JUI
|
||||
bool alive = true;
|
||||
bool paused = false;
|
||||
bool completed = false;
|
||||
bool overwritable = true;
|
||||
|
||||
|
||||
void Cancel();
|
||||
|
@@ -270,9 +270,14 @@ void Widget::UpdateTweens(float elapsed) {
|
||||
t->Update(elapsed);
|
||||
|
||||
// TODO: Remove tweens if "dead"
|
||||
std::ranges::remove_if(tweens.begin(), tweens.end(), [](Tween* t){
|
||||
return t->HasCompleted();
|
||||
});
|
||||
|
||||
tweens.erase(std::remove_if(tweens.begin(), tweens.end(), [](Tween* t){
|
||||
if (t->HasCompleted())
|
||||
{
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}), tweens.end());
|
||||
}
|
||||
|
||||
void Widget::Update(float delta) {
|
||||
@@ -604,8 +609,24 @@ Tween* Widget::TweenMarginBottom(const JUI::UDim& goal, JUI::TweenInfo info) {
|
||||
return t;
|
||||
}
|
||||
|
||||
Tween *Widget::TweenAnchorPoint(const Vector2 &goal, TweenInfo info) {
|
||||
Vector2 start = this->AnchorPoint();
|
||||
|
||||
TweenTickFunc updateTillGoalReached = [this, start, goal] (float elapsed, float progress) mutable {
|
||||
Vector2 step = start.Lerp(goal, progress);
|
||||
|
||||
AnchorPoint(step);
|
||||
};
|
||||
|
||||
Tween* t = new Tween(updateTillGoalReached, info);
|
||||
tweens.push_back(t);
|
||||
return t;
|
||||
}
|
||||
|
||||
|
||||
|
||||
float Widget::ComputeElementPadding(float size, const UDim &padding) {
|
||||
return padding.Pixels + (padding.Scale * size);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
Reference in New Issue
Block a user