+ 이 글은 작성자가 직접 공부하고 복습하며 작성한 글입니다. 만약 직접 작성하지 않았다면, 꼭 출처를 밝히겠습니다!

 + 이 글은 개인적인 공부를 바탕으로 작성되었기에, 틀린 부분이 있을 수 있으며, 틀린 부분이 있다면 알려주시면 감사하겠습니다!

 + 이 글을 다른 곳으로 가져가신다면, 꼭 출처를 남겨주세요~

 + '참고사이트'는 공부하기 위해 참고한 사이트들을 모아 둔 것입니다.

 + 혹시라도 문제가 된다면 바로 조취를 취할테니, 말해주시면 감사하겠습니다!


<종류별로 BP를 만들었을 때의 파일 모양>



UWidget?

Widget에서 사용되는 가장 Base Class.


UUserWidget?

말 그대로, User가 직접 여러 종류의 Widget을 선택 및 관리하여 화면에 보여지는 Widget이다.

즉, 화면에 보여지는 여러 Widget들을 감싸고 있는 것이 UUserWidget이라고 생각해 된다.


UPanelWidget?

여러 Widget들을 배치할 수 있는 Panel로 사용되는 Widget.

배치되는 Widget들을 Child로 생각해, Slots 멤버 변수를 통해 관리한다.

Unity의 UIPanel을 생각하면 될 것 같다.


WidgetTree?

WidgetTree는 말그대로 Widget의 상하관계에 대한 구조를 Tree형태로 관리하는 Class를 말한다.

이 Class를 통해, 부모/자식 Widget의 정보를 확인해서, 원하는 정보를 참조할 수 있다.


- Root Widget

WidgetTree Class 내부에는 RootWidget이라는 멤버변수가 있는데, 이것은 WidgetTree를 가지고 있는 Widget 중에서 가장 상단에 있는 Panel Widget을 가리키고있다.

내부적으로 어떻게 생성되는지 확인해봤는데...

참조를 통해 알게된 사용되는 함수들 중, BlueprintFactory 함수를 보면, FactoryCreateNew(~~~)를 통새 RootWidget을 초기화 시켜주고있다.

이것을 보니, BP에서 작업할 때, CanvasPanel이 없다면 그냥 만들어서 RootWidget으로 넣어버리는 것 같다.

뭔가 더 내부적으로 파들어가고싶은데... 이거 답이 없을 정도로 깊어지고... 엔진 디버깅을 해야하기에 지금은 멈췄다.


아래의 코드는 Children Widget을 찾기 위해 내부적으로 많이 사용되는 함수의 로직이다.


< ForWidgetAndChildren() >


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
// Search for any named slot with content that we need to dive into.
    if ( INamedSlotInterface* NamedSlotHost = Cast<INamedSlotInterface>(Widget) )
    {
        TArray<FName> SlotNames;
        NamedSlotHost->GetSlotNames(SlotNames);
 
        for ( FName SlotName : SlotNames )
        {
            if ( UWidget* SlotContent = NamedSlotHost->GetContentForSlot(SlotName) )
            {
                Predicate(SlotContent);
 
                ForWidgetAndChildren(SlotContent, Predicate);
            }
        }
    }
 
    // Search standard children.
    if ( UPanelWidget* PanelParent = Cast<UPanelWidget>(Widget) )
    {
        for ( int32 ChildIndex = 0; ChildIndex < PanelParent->GetChildrenCount(); ChildIndex++ )
        {
            if ( UWidget* ChildWidget = PanelParent->GetChildAt(ChildIndex) )
            {
                Predicate(ChildWidget);
 
                ForWidgetAndChildren(ChildWidget, Predicate);
            }
        }
    }
cs


 INamedSlotInterface를 가진 Widget부터 찾고, 그 뒤에 PanelWidget인지 확인해서 widget들을 순회한다.


INamedSlotInterface는... 어디서 사용되는지 찾아봐도 나오지 않는데, 이름을 통해 의도를 생각해보면, Widget Slot을 만들 때, 이걸 Implement해서 사용해라. 그러면 API를 통해 Slot으로 관리하기 편할 것이다. 라는 의미인 듯 싶다.


* WidgetTree를 잘 이용하면, Runtime에 Widget들을 잘 통제할 수 있을 것이다!





Copyright © -강정이좋아- 무단 전재 및 재배포는 하지 말아주세요.

+ Recent posts