Widget System Architecture
Overview
The widget system manages the UI in a hierarchical structure and handles input processing. By inheriting from CUserWidget, custom widgets can be easily implemented. Built-in widgets that are implemented by inheriting from CWidget, already support basic interactions such as dragging. This provides a developer-friendly UI that can be applied with minimal effort.
Widget Input System Processing Flowchart | Full View
/Block-References/01_Game-Projcets/Self-Made-Game-Framework/Source/Widget-Input-System-Processing-Flowchart_Eng.png)
This diagram illustrates the update and input processing flow of the widget system.
Widget Related Class Descriptions
1. CSceneUI Class | View Repository
class CSceneUI { public: CSceneUI(); virtual ~CSceneUI(); private: std::vector<CWidget*> mWidgets; CWidget* mCurrHovered = nullptr; CWidget* mHeldWidget = nullptr; public: virtual bool Init(); virtual void Update(float deltaTime); virtual void LateUpdate(float deltaTime); virtual void Render(SDL_Renderer* renderer); public: CWidget* FindWidget(size_t id); void BringWidgetToTop(CWidget* widget); CWidget* GetHoveredWidget() const { return mCurrHovered; } CWidget* GetHeldWidget() const { return mHeldWidget; } void SetHeldWidget(CWidget* heldWidget) { mHeldWidget = heldWidget; } protected: void AddWidget(CWidget* widget); private: void SetSceneUI(CWidget* widget); CWidget* FindHoveredWidget(const FVector2D& mousePos); CWidget* FindHoveredInTree(CWidget* widget, const FVector2D& mousePos); void UpdateInput(); };
- Role:
- Class that manages the UI elements in the scene and handles mouse input to process interaction with widgets.
- Key Variables:
mWidgets:- List of root widgets directly registered in the scene UI.
mCurrHovered:- Widget currently hovered by the mouse cursor.
mHeldWidget:- Widget currently held by the mouse.
- Key Methods:
- CWidget* FindHoveredWidget(const FVector2D& mousePos):
- Returns a pointer to the widget currently hovered by the mouse cursor.
- void UpdateInput():
- Checks the mouse position and button states, calls the unhover function if a held widget leaves its area, and calls the hover function if a new widget is hovered.
- CWidget* FindHoveredWidget(const FVector2D& mousePos):
2. CWidget Class | View Repository
class CWidget abstract : public CWidgetBase { friend class CSceneUI; friend class CWidgetComponent; protected: CWidget(); virtual ~CWidget(); protected: CSceneUI* mSceneUI = nullptr; CWidget* mParent = nullptr; std::vector<CWidget*> mChilds; bool mIsInteractable = false; bool mWidgetHovered = false; bool mWidgetHeld = false; protected: virtual void Update(float deltaTime); virtual void LateUpdate(float deltaTime); virtual void Render(SDL_Renderer* renderer, const FVector2D& topLeft = FVector2D::ZERO); virtual void Release() = 0; virtual void HandleHovered(const FVector2D& mousePos, bool isPressed, bool isHeld, bool isReleased); virtual void HandleUnhovered(const FVector2D& mousePos, bool isHeld, bool isReleased); public: CWidget* FindRootWidget(); CWidget* FindWidget(size_t id); void AddChild(CWidget* child); bool DeleteChild(CWidget* child); CSceneUI* GetOwnerSceneUI() const { return mSceneUI; } };
- Role:
- Base class of all built-in widgets and an abstract class.
- Organizes the UI using a hierarchical structure and improves extensibility.
- Provides interaction functionality for all widgets.
- Key Variables:
mParent:- Parent widget of the current widget.
mChilds:- Child widgets of the current widget.
- Key Methods:
virtual void HandleHovered(const FVector2D&, bool, bool, bool):- Virtual function, called when the mouse is over the widget.
virtual void HandleUnhovered(const FVector2D&, bool, bool):- Virtual function, called when the mouse leaves the widget.
3. CUserWidget Class | View Repository
class CUserWidget abstract : public CWidget { public: CUserWidget(); virtual ~CUserWidget(); private: bool mIsMovable = false; FVector2D mDragOffset = FVector2D::ZERO; protected: virtual void Construct() = 0; virtual void Release() = 0; public: void SetInteractable(bool interactable) { mIsInteractable = interactable; mIsMovable &= mIsInteractable; } void SetMovable(bool movable) { mIsMovable = movable; mIsInteractable |= movable; } protected: void HandleDragging(const FVector2D& mousePos, bool isPressed, bool isHeld, bool isReleased); };
- Role:
- Base class of user-defined widgets and an abstract class.
- Provides basic interaction features such as mouse dragging.
- Key Variables:
mIsMovable:- Indicates whether the widget is draggable.
mDragOffset:- Stores the offset between the mouse and the widget position during dragging.
- Key Method:
- void HandleDragging(const FVector2D&, bool, bool, bool):
- On mouse click, processes dragging of the widget.
- Drag Start: Brings the widget under the mouse to the top.
- Drag Move: Updates the widget position based on the mouse.
- Drag End: Releases the mouse button and ends the drag.
- On mouse click, processes dragging of the widget.
- void HandleDragging(const FVector2D&, bool, bool, bool):
Conclusion
The widget system provides clear and structured UI management through its hierarchical architecture, integrated input handling and interactive features to support an accessible UI. Designed similarly to Unreal Engine, it provided an understanding of how built-in and custom widgets functioned within the UI hierarchy in practice.