위젯 시스템 구조


개요

위젯 시스템은 계층 구조로 UI를 관리하고 입력 처리를 수행합니다. CUserWidget을 상속받아 사용자 정의 위젯을 쉽게 만들 수 있으며, CWidget을 상속하여 만든 기본 제공 위젯과 함께 드래그 등 기본 상호작용 기능도 이미 구현되어 있어 간단히 적용 가능한 개발 친화적 UI를 제공합니다.


위젯 입력 처리 시스템 흐름도 | 자세히 보기

본 흐름도는 위젯 시스템의 업데이트 및 입력 처리 흐름 과정을 보여줍니다.


위젯 관련 클래스 목록 및 설명

1. CSceneUI 클래스 | 저장소 보기

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();
};

  • 역할:
    • 씬의 UI를 관리하며, 마우스 입력을 받아 위젯과 상호작용을 처리하는 클래스입니다.
  • 핵심 변수들:
    • mWidgets:
      • 씬 UI에 직접 등록된 최상위 위젯 목록입니다.
    • mCurrHovered:
      • 마우스 커서와 닿아 있는 위젯입니다.
    • mHeldWidget:
      • 마우스로 홀드 중인 위젯입니다.
  • 핵심 함수들:
    • CWidget* FindHoveredWidget(const FVector2D& mousePos):
      • 마우스 커서와 닿아 있는 위젯의 포인터를 반환합니다.
    • void UpdateInput():
      • 마우스 위치와 버튼 상태를 확인하여, 홀드 중인 위젯이 영역을 벗어나면 호버 해제 함수를 호출하고, 새로 호버된 위젯이 있으면 호버 함수를 호출합니다.

2. CWidget 클래스 | 저장소 보기

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; }
};

  • 역할:
    • 모든 기본 제공 위젯의 부모 클래스이며, 추상화 클래스입니다.
    • 계층 구조를 기반으로, UI를 구조적으로 관리하고 확장성을 높입니다.
    • 모든 위젯의 상호작용 기능을 제공합니다.
  • 핵심 변수들:
    • mParent:
      • 현재 위젯의 부모 위젯입니다.
    • mChilds:
      • 현재 위젯의 자식 위젯들입니다.
  • 핵심 함수들:
    • virtual void HandleHovered(const FVector2D&, bool, bool, bool):
      • 마우스가 위젯 위에 있을 때 호출되는 가상 함수입니다.
    • virtual void HandleUnhovered(const FVector2D&, bool, bool):
      • 마우스가 위젯에서 벗어날 때 호출되는 가상 함수입니다.

3. CUserWidget 클래스 | 저장소 보기

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);
};

  • 역할:
    • 사용자 정의 위젯의 부모 클래스이며, 추상화 클래스입니다.
    • 마우스 드래그와 같은 기본 상호작용 기능을 제공합니다.
  • 핵심 변수들:
    • mIsMovable:
      • 위젯이 드래그 가능한지 여부를 나타냅니다.
    • mDragOffset:
      • 드래그 시, 마우스와 위젯 위치 차이를 저장합니다.
  • 핵심 함수:
    • void HandleDragging(const FVector2D&, bool, bool, bool):
      • 마우스 클릭시, 위젯을 드래그 처리합니다.
        • 드래그 시작: 마우스 아래 위젯을 최상단으로 이동합니다.
        • 드래그 진행: 마우스 위치에 따라 위젯 위치를 갱신합니다.
        • 드래그 종료: 마우스를 놓고 드래그를 종료합니다.

맺는 말

위젯 시스템은 계층 구조 기반 UI 관리로 구조를 명확히 하고, 입력 처리와 상호작용 기능을 통합하여 직관적인 UI 구성을 지원합니다. 언리얼 엔진과 유사한 구조로 설계하여, 기본 제공 위젯과 사용자 정의 위젯을 만들며 UI 계층 구조가 실제로 어떻게 동작하는지 이해할 수 있었습니다.