UDN
Search public documentation:

UserInterfaceTechnicalGuideKR
日本語訳
中国翻译

Licensees can log in.

Red links require licensee log in.


Interested in the Unreal Engine?
Visit the Unreal Technology site.

Looking for jobs and company info?
Check out the Epic games site.

Questions about support via UDN?
Contact the UDN Staff

UE3 홈 > 유저 인터페이스와 HUD > UIScene 테크니컬 가이드

UIScene 테크니컬 가이드


UI System 과 그 함수성은 더이상 지원되지 않습니다. 현재 지원되는 유저 인터페이스 시스템에 대한 정보는 스케일폼 GFx 문서를 참고하시기 바랍니다.

개요


본 문서는 프로그래머를 대상으로 한 것으로써 UnrealUI 시스템의 주요 기능이 디자인되고 구현된 방법에 대해 설명합니다.

위젯 장면 레이아웃


다음은 UI 시스템에서 위젯의 제작, 위치 지정, 도킹이 어떻게 처리되는지 소개합니다. 위젯 클래스를 만는 것뿐만 아니라 장면에서의 위젯 배치, 도킹 관계 생성, 위젯 간의 부모/자식 관계가 다루어집니다.

위젯 클래스

위젯은 UnrealUI 장면의 기본 단위입니다. 이들은 고유 동작을 포함한 기능적 화면 객체 및 텍스트, 이미지 및 기타 다른 위젯용 콘테이너를 포함한 기능적 화면 객체의 역할을 모두 합니다. 각 특정 위젯 유형은 배치 가능한 텍스트용 컨테이너의 역할을 하는 Label 위젯 또는 사용자 입력 시 기능을 실행하도록 된 Button 위젯처럼 특정 기능을 장면에 제공하도록 제작됩니다.

디자인 원리

UI 시스템에서 final virtual 은 스크립트와 C++ 모두에 의해 호출되는 함수에 사용됩니다. 파생 스크립트 버전은 함수가 C++에서 직접 호출되면 호출되지 않기 때문에 대부분의 경우 UnrealScript에서 함수들이 재정의되는 것은 바람직하지 않습니다.

위젯 클래스 계층

WidgetClassesClassDiagram2.jpg

UIObject 클래스에서 파생된 모든 위젯 클래스는 모든 기본적인 위젯 클래스에 필요한 데이터 및 메서드를 제공합니다. UIObject 클래스는 UIRoot가 파생되고 최종적으로 Object가 파생되는 UIScreenObject 클래스에서 파생됩니다. 위젯에 대해 설명할 목적으로는 UIScreenObject 클래스와 UIObject 클래스가 가장 중요합니다. UIScreenObject 클래스는 위젯의 위치 지정, 위젯 상대 및 자식 위젯 관계를 다루는데 필요한 대부분의 데이터와 기능을 포함합니다. UIObject 클래스는 위젯의 스타일, 도킹 대상, 소유자 또는 부모와 그의 RenderBounds에 관련된 데이터를 포함합니다.

WidgetClassesClassDiagram1.jpg

UIScreenObject

UIScreenObject 클래스는 위젯 클래스의 핵심 기능을 대부분을 담당합니다. 일반적으로 이 클래스는 위젯 면의 위치 지정, 위젯 상태 및 관리 포커스 전달의 관리뿐만 아니라 자식 데이터의 저장을 처리합니다. 또한 이것은 사용자 입력 기능 및 분할 화면 지원하는데 필요한 플레이어 추적의 대부분을 처리합니다. 이러한 시스템에 대한 좀 더 자세한 정보는 관련된 이 문서의 특정 섹션을 참조해 주십시오.

UIObject

UIObject 클래스는 위젯의 스타일 데이터의 수정 및 업데이트, 도킹 링크의 생성뿐만 아니라 도킹 변경에 따른 위치 해결을 처리합니다. 이 클래스는 객체의 부모 위젯과 부모 장면에 대한 참조와 위젯의 고유 식별자를 포함합니다. 네비게이션 링크의 생성에 대한 대부분의 기능도 또한 UIObject에서 이루어집니다.

UIString

UIObject 클래스는 UI에 의해 표시되는 모든 데이터를 위한 핵심 렌더링이 가능한 실체입니다.

데이터는 TextClipMode 에 따라 다르게 렌더될 수 있습니다.

  • Overdraw (없음): 모든 텍스트는 경계 영역 밖에 있을지라도 그려집니다.
  • Clipped (일반): 영역 밖의 텍스트는 잘립니다.
  • Ellipsis: 몇 개의 마지막 보이는 문자를 생략(ellipsis)으로 교체하여 추가 텍스트가 있음을 나타냅니다.
  • Wrapped (Wrap): 다음 줄로 텍스트를 감쌉니다.새 줄에 대해 줄바꿈(\n) 문자를 반드시 사용해야 합니다.

일반적인 위젯 클래스 구성 요소

각각의 다양한 파생 위젯 클래스는 특정 목적을 가지고 디자인되었지만, 다수의 일반적인 객체가 대부분의 위젯내에 존재합니다. 일반적인 구성 요소의 가장 두드러진 예는 UITexture 클래스의 사용을 통해 볼 수 있습니다. 대부분의 위젯 클래스는 배경 이미지를 표시하는 기능이 있고, 따라서 컨테이너 역할을 하며 해당 이미지에 대한 객체를 표시하기 위해 UITexture 클래스가 필요합니다. 또한 UITexture를 포함하는 위젯은 보통 UITexture의 위치를 지정하기 위한 TextureCoordinates 객체를 포함합니다. 일반 위젯 구성 요소의 또 다른 예는 Label 위젯과 Label Button 위젯에서 문자열을 저장하고 표시하는데 필요한 기능을 제공하는 UIComp_DrawString 클래스에서 볼 수 있습니다. UITexture와 UIComp_DrawString과 같은 구성 요소는 파생 클래스 위젯에 기능을 제공하기 위해서만 사용될 수 없지만 사용자 지정 위젯 클래스의 특별한 구성 요소를 구성하는 기본적인 역할을 수행합니다. UIComp_DrawStringEditbox는 Editbox 위젯의 필요를 위해 만들어진 특별한 위젯 구성 요소의 예이지만 UIComp_DrawString 클래스에서 파생되었습니다.

사용자 지정 위젯 클래스 만들기

위젯 클래스 계층에 의해 제공된 프레임워크와 위젯 클래스 구성 요소를 사용하여 사용자 지정 위젯 클래스를 쉽게 만들 수 있습니다. 사용자 지정 위젯은 기존의 모든 위젯 클래스처럼 UIObject 클래스에서 파생되야 합니다. UIObject 클래스에서 새로운 사용자 지정 위젯 클래스로 확장하면 위젯에 필요한 기본적인 기능을 제공할 수 있습니다. 그러나 기능적인 뼈대 위젯 클래스를 만들려면 단순히 UIObject 클래스를 확장하는 것 이외에 몇 가지 추가적인 단계가 필요합니다.

기본 클래스에 의해 제공되는 메서드는 모든 위젯에 UIObject::Render_widget 메서드를 제외한 기본적인 구현을 제공합니다. UIObject 클래스는 기본적으로 렌더 가능한 객체를 포함하지 않기 때문에, Render_Widget 메서드를 구현하지 않습니다. Render_Method가 정의되지 않은 사실은 UIObject 클래스가 인스턴스화되어 있지 않기 때문에 아무 문제가 되지 않지만, 그러나 모든 사용자 지정 위젯 클래스는 인스턴스화 되기 전에 이것을 구현해야 합니다. 위젯이 UITexture 또는 UIComp_String과 같은 일반적인 위젯 구성 요소를 활용하고 있다면 위젯의 Render_Method는 구성 요소의 각 렌더링 함수를 호출하여 Render_Method에 전달되는 FRenderInterface 인스턴스를 제공합니다.

UIObject 클래스에서 파생된 사용자 지정 위젯은 또한 다수의 상태 및 이벤트를 상속합니다. UIObject는 UIObject에서 확장된 UIScreenObject 클래스의 Default Properties에서 정의된 것처럼 기본적으로 Enable 및 Disable 상태를 포함합니다. 또한 UIObject의 Default Properties에 의해 위젯의 Kismet Global Sequence에 추가된 이벤트 및 액션도 있습니다. 이벤트에는 UIEvent_Initialized, UIEvent_OnEnterState, UIEvent_OnLeaveState가 포함됩니다. 액션에는 UIAction_ActivateInitialState가 포함됩니다. 추가 Kismet 이벤트와 액션은 UIObject와 UIScreenObject 클래스에서와 동일한 방법으로 사용자 지정 위젯의 Default Properties에서 정의될 수 있습니다.

  • 다음은 UIObject.uc의 UIObject Default Properties에서 참조된 것입니다.
   // 액션
   Begin Object Class=UIAction_ActivateInitialState Name=ActivateInitialState
   End Object

   // 출력 링크가 액션에 연결되는 이벤트.
   Begin Object Class=UIEvent_Initialized Name=WidgetInitializedEvent
      OutputLinks(0)=(LinkDesc="Output",Links=((LinkedOp=ActivateInitialState)))
   End Object

   Begin Object Class=UIEvent_OnEnterState Name=EnteredStateEvent
   End Object

   // 객체 추가
   Begin Object Class=UIComp_Event Name=WidgetEventComponent
      DefaultEvents.Add((EventTemplate=WidgetInitializedEvent))
      DefaultEvents.Add((EventTemplate=EnteredStateEvent))
   End Object
        
   EventProvider=WidgetEventComponent

기본 뼈대 위젯을 만드는데 필요한 마지막 단계는 Default Properties에서 Primary Style을 정의하는 것입니다. 사용자 지정 위젯에 의해 활용되는 Primary Style은 위젯에 제시될 데이터에 따릅니다. 위젯이 UIComp_DrawString을 포함한다면, UIStyle_Text 스타일이 가장 적합하다고 말할 수 있습니다. 다음은 위젯 클래스의 스크립트를 통해 Primary Style을 UIStyle_Image 스타일로 설정하는 예입니다.

  • 다음은 UIButton.uc의 UIButton Default Properties에서 참조된 것입니다.
   PrimaryStyle=(DefaultStyleTag="ButtonBackground",RequiredStyleClass=class'Engine.UIStyle_Image')

Label Button을 통한 사용자 지정 위젯 클래스의 예

해야할 일.

위젯 위치 지정

뷰포트에서 위젯의 위치는 최종적으로 위젯 4면의 위치에 의해 결정됩니다. 위젯 면의 실제 픽셀 위치는 모든 위젯 클래스가 파생되는 UIObject 클래스의 RenderBounds 부동 배열에 의해 정의됩니다. 그러나 위젯의 RenderBounds는 최종적으로 UIScreenValue_Bounds Position 구조체에 의해 결정됩니다. Position 구조체는 UIObject에서 파생된 클래스인 UIScreenObject 클래스의 구성 요소이며, 그 안의 값은 뷰포트 픽셀 전용인 RenderBounds와 달리 모든 스케일 유형? 에 저장될 수 있습니다. 위젯 면의 위치에 대한 모든 변경은 위젯 RenderBounds의 실제 픽셀 위치를 계산하는데 사용되는 Position 필드에서 이루어져야 합니다.

위젯 위치 설정하기

주어진 위젯 면 중 1개의 위치를 변경하는 것은 UIScreenObject::SetPosition 메서드를 통해 이루어져야 합니다. 위젯 면의 RenderBounds를 직접 변경하는 것은 가능하지만, 다른 위젯 면이 해당 면 또는 해당 면의 자식에 도킹되어 있을 수 있어 업데이될 필요가 있기 때문에 현명한 방법은 아닙니다. SetPosition 메서드는 제공된 면과 새 위치 값을 기준으로 주어진 위젯의 특정 면의 Position 필드를 설정합니다. SetPosition은 새 면 위치에 대한 모든 스케일 유형? 대리자를 사용하여 호출될 수 있습니다. 스케일 유형?은 사용자 가이드?의 위젯 위치 지정 섹션에 정의되어 있습니다. 새 값으로 제공된 스케일 유형?이 위젯의 Position 필드에 저장된 값의 대리자와 다른 경우에는 변환이 수행됩니다. 새 면 위치가 적절한 스케일 유형?으로 변환된 후 기존 면의 위치는 새 위치와 비교하여 면의 위치가 변경되었는지 여부와 장면이 모든 위젯 면 위치를 업데이트해야 하는지 여부를 결정합니다. 업데이트가 필요한 경우 UIScene::RequestSceneUpdate가 호출되어 다음 UIScene::Update 호출 중 위젯 면의 위치를 처리할 필요가 있다는 것을 장면에 알립니다. 다음 프레임에서 UIScene::Update는 UIScene::ResolveScenePostion을 호출하여 업데이트된 Position 필드에 따라 장면에 있는 모든 위젯 면의 RenderBounds를 처리합니다.

  • 면 위치 설정 시퀀스 도표

WidgetPositioningSequenceDiagram.jpg

UnrealEd를 통한 위젯 위치 설정

UI 에디터 를 사용하여 위젯의 면 위치는 장면 뷰포트에서 위젯의 크기를 조정하는 핸들을 드래그하거나 Positioning 에디터에서 텍스트 필드를 사용하여 재배치될 수 있습니다.

디자이너가 위젯의 면 중 1개의 크기 조정 핸들을 드래그하는 첫 번째 시나리오는 다음과 같은 이벤트 시퀀스의 결과를 초래합니다. 위젯의 면을 드래그한 후 마우스 버튼을 놓아 입력이 수신될 때 UIScreenObject::SetPosition이 각 면에 대해 호출됩니다. 디자이너 면을 드래그한 위치에 따라 해당 면의 위치에 대한 새 값이 SetPosition에 전달됩니다. SetPosition에 모든 스케일 유형?의 값이 전달될 수 있지만 PixelOwner 스케일 유형? 형식의 새 값이 SetPosition에 전달됩니다. 스케일 유형?은 사용자 가이드의 위젯 위치 지정 섹션에서 정의되어 있습니다.

이 시나리오에서 UIScene::RequestSceneUpdate는 UUIScreenObject::SetPosition에서 호출됩니다. 각 면의 모든 위치가 설정된 후 대리자 함수인 NotifyPositionChanged를 통해 위치가 변경되었음을 알리는 UUIScreenObject::RefreshPosition()이 호출됩니다.

Positioning 에디터를 통해 위젯 면의 위치가 변경되는 2번째 시나리오는 UIScreenObject::SetPosition을 활용하지 않습니다. 대신 위젯의 Position 필드가 직접 변경됩니다. Position 필드가 설정된 후 위젯의 RenderBounds가 업데이트될 필요가 있다는 것을 장면에 알리기 위해 UIScene::RequestSceneUpdate가 호출됩니다. RequestSceneUpdate 호출 후 즉시 UIScene::UpdateScene이 호출됩니다. 그런 다음 UIScene::UpdateScene이 UIScene::ResolveScenePositions를 호출하여 장면에 있는 모든 위젯 면의 RenderBounds를 처리합니다.

두 시나리오에서 최종 결과는 UUIScreenObject::RefreshPosition()을 호출하는 것입니다.

위젯 도킹

도킹은 2개의 면 위치간의 관계를 생성하기 위해 한 위젯의 면이 다른 위젯의 면에 도킹하는 과정입니다. 이 관계는 도킹된 면의 위치가 도킹하는 면에 패딩이라는 오프셋을 더하거나 뺀 것과 동일해 지는 것과 같습니다. 또 다른 면이 도킹되는 해당 면의 위치에 대한 모든 변경은 도킹된 면에 전달됩니다. 도킹 동작에 대한 상세 설명은 사용자 가이드? 에서 찾을 수 있습니다. 기술적 가이드의 목적으로 언급되야 하는 도킹 시스템의 2가지 주요 구성 요소가 있습니다. 첫 번째는 UIObject 클래스에서 파생되는 모든 위젯에 포함되어 있는 UIDockingSet 구조체입니다. 이 구조체는 위젯의 어떤 면이 어떤 위젯의 어떤 면에 도킹되는가에 대한 정보를 포함하고 있습니다. 이 구조체에 값을 설정하는 것은 "도킹 링크 만들기” 섹션에서 설명됩니다. 2번째 구성 요소는 UIScene 클래스에 존재하는 DockingStack입니다. DockingStack은 도킹와 자식 관계에 의해 만들어진 의존성에 의해 정렬되는 장면에 있는 모든 위젯 면의 목록을 제공합니다. DockingStack은 "도킹 스택" 섹션에서 설명됩니다.

도킹 링크 만들기

두 위젯의 면간에 도킹 링크를 만드는 것은 도킹되어지는 면을 가진 위젯에서 UIObject::SetDockingTarget를 호출하는 것처럼 간단합니다. SetDockingTarget에 도킹된 위젯의 어떤 면이 어떤 대상 위젯의 어떤 면에 도킹되어지는 가에 대한 정보가 제공되야 합니다. 그런 다음 이 함수는 지정된 대상 위젯의 지정된 면에 상응하는 UIDockingSet 구성 요소인 DockTargets의 도킹된 면에 대한 필드를 설정합니다. 도킹 링크에 대한 정보가 일단 설정되면 UIScene::RequestSceneUpdate가 장면에서 호출되어 새 도킹 링크를 설명하기 위해 DockingStack이 업데이트될 필요가 있다는 것을 알립니다. 즉시 UIScene::RebuildDockingStack이 UIScene::Update 에서 호출되어 DockingStack을 재빌드합니다.

도킹 스택

UIObject 클래스는 DockTargets라는 UIDockingSet 구성 요소를 포함합니다. UIDockingSet는 어떤 위젯의 어떤 면이 컨테이너 위젯의 주어진 면에 연결되어지는 가에 대한 정보를 포함하고 있습니다. 이것은 UIScene::Update가 UIScene::ResolveScenePostion을 호출할 때 위젯의 RenderBounds를 계산하는데 사용되는 정보입니다. 그러나 ResolveScenePostion이 호출될 때 장면에 있는 위젯은 임의적으로 업데이트될 수 없습니다. 위젯의 도킹된 면의 위치에 대한 업데이트는 반드시 도킹하는 면의 업데이트 후 실행되야 합니다. 그렇지 않으면 도킹된 위젯 면으로의 위치 변경의 전달이 손실되게 됩니다. 또한 면 위치 전달은 부모 위젯과 자식 위젯 사이의 문제입니다. UIScene 클래스의 DockingStack 구성 요소는 이 문제에 대한 해결책입니다. DockingStack은 도킹된 면과 부모 및 자식 위젯 관계에 의해 만들어진 종속성에 따라 정렬되는 장면에서의 모든 위젯 면의 스택입니다. DockingStack는 위치 전달 종속성을 해결하기 위해 ResolveScenePostion이 위젯에서 여러 번 반복하는 것 대신에 한 패스에서 반복할 수 있는 데이터 구조를 제공합니다. 장면에 있는 각 면에 대해 ResolveScenePostion은 면의 위치와 도킹되는 경우 도킹되는 면의 위치에 따라 주어진 면의 RenderBounds를 다시 계산하기 위해 UIObject::ResolveFacePosition을 호출합니다.

  • 면 위치 처리 도표

https://udn.epicgames.com/pub/Three/UserInterfaceTechnicalGuideKR/WidgetDockingSequenceDiagram.jpg"

입력 처리


다음은 UI 시스템에서 입력 과정이 처리되는 방법에 대한 좀 더 포괄적인 개요입니다. 이것은 위젯이 응답하는 입력 키가 어떻게 정의되어 있는지, 해당 입력 키 이벤트가 수신될 때 해당 알림을 수신하기 위하여 위젯이 어떻게 자신을 등록하는지, 해당 위젯이 입력 키 이벤트 자체를 수신할 때 무엇이 일어나는지를 다룹니다.

기본 컨트롤 흐름

장면이 입력 키 이벤트를 수신할 때 InputSubscriptions 맵에서 해당 이벤트와 연관된 키 이름을 조회합니다. 이것은 그 정확한 순간에 해당 입력 키 이벤트에 응답하기 위해 적합한 위젯의 목록을 반환합니다. 그런 다음 장면은 위젯이 해당 입력 키 이벤트에 응달할 기회를 허용하기 위해 그러한 위젯에서 ProcessInputKey를 호출합니다. 따라서 특정 입력 키에 대해 장면의 InputSubscriptions 맵에 있는 위젯만이 ProcessInputKey로의 호출을 받습니다. UUIScene::SubscribeInputEvent를 호출하여 위젯은 이 배열에 추가되고 UUIScene::UnsubscribeInputEvent를 호출하여 삭제됩니다.

입력 키 및 상태

입력 키에 관련된 정보는 InputKeyAction 구조체에 저장됩니다. 이 구조체는 입력 키 이름, 입력 키 상태(눌러짐, 누른 것을 놓음 등), 위젯이 해당 입력 키 이벤트를 수신할 때 활성화되는 선택적 UIAction을 정의합니다. 위젯이 응답할 수 있는 입력 키는 현재 활성 상태인 UIStates에 따라 다릅니다. UIState는 그 상태가 활성화인 경우 위젯이 응답하는 입력 키를 정의하는 InputKeyAction 구조체의 배열을 포함합니다. 상태가 활성화되면, 상태의 InputKeyAction 배열에 있는 모든 입력 키는 "현재 수신하고 있는 입력 키"의 위젯 목록에 추가됩니다. 그리고 상태가 비활성화되면 상태의 InputKeyAction 배열의 입력 키에 의해 포함된 입력 키는 위젯이 응답하는 입력 키 이름의 위젯의 실행 목록(UUIState::OnActivate() 및 UUIComp_Event::RegisterInputEvents 참조)에서 삭제됩니다.

위젯의 상태 입력 키 재정의

UIEvent_ProcessInput 객체( "입력 프로세서"라고도 함)는 각 위젯의 상태 시퀀스에 있는 이벤트 노드입니다. 그 역할은 입력 키 이벤트를 UIActions로 전송하는 것입니다. 입력 프로세서는 절대 위젯의 메인 시퀀스가 아닌 상태 시퀀스에 의해 항상 포함됩니다. 이렇게 하면 입력 키는 항상 특정 메뉴 상태를 주시하고, 따라서 상태가 비활성화되면 위젯이 그런 상태에 있는 동안에만 활성화되는 입력 키는 위젯이 응답하는 입력 키 목록에서 자동으로 제거됩니다. 위젯의 입력 프로세서에 입력 키를 추가하여 사용자가 개별 위젯의 입력 처리 동작을 변경할 수 있습니다. 입력 프로세서는 UIAction 객체로의 입력 키 이름의 맵을 포함합니다. 해당 맵에 포함된 입력 키 이름은 입력 에일리어스 또는 해당 위젯 클래스와 이미 연관되지 않은 새 키를 통해 해당 위젯 클래스에 이미 연결된 것들고 포함할 수 있습니다. 그렇게 하면 이 입력 키에 연관된 기본 동작을 완벽하게 재정의할 수 있습니다. 그런 다음 사용자는 수동으로 해당 위젯의 상태 시퀀스내의 이 입력 키와 연관된 액션을 구현합니다.

입력 이벤트 에일리어스

Input Event Aliases는 이러한 키의 사용자 입력에 따라 위젯이 실행할 수 있는 액션을 일련의 입력 키와 연관시키는 방법을 제공합니다. 각 위젯 유형에는 위젯의 기능을 표현하는 고유의 에일리어스 집합을 포함됩니다. 예를 들면, EditBox에는 SubmitText 에일리어스가 있고, Button에는 Clicked 에일리어스가 있습니다. 디자이너는 어떤 위젯 상황에 어떤 입력 키가 Default Alias Key Bindings Editor를 통해 시작되는지를 선택할 수 있고, 그런 다음 이러한 설정은 GameInput.ini 파일에 저장됩니다. 에일리어스 이름의 목록은 각 widget 클래스의 GetSupportedUIActionKeyNames() 함수에 설정됩니다. 프로그래머는 ProcessInputKey() 함수내에서 위젯이 어떻게 이벤트 에일리어스에 반응하는지를 정의합니다.

위젯에 의한 입력 키 이벤트 처리

위젯은 보내진 입력 키 이벤트를 2가지 방법으로 자동으로 처리합니다. 첫 번째는 이 엔터 키와 관련된 모든 Kismet UIActions을 시작시키기 위해 위젯은 키 이벤트를 위젯의 Input Processo에 전달하려 합니다. 할당된 UIActions이 Kismet에 없기 때문에 이것이 성공하지 않으면 위젯은 위젯 클래스의 기본 입력 처리 함수인 ProcessInputKey를 호출합니다. 입력 키 이벤트가 수신될 때 활성화되어야 할 관련 UIAction을 갖기 위해 입력 키가 필요하지 않습니다. 사실, 대부분의 경우 필요하지 않습니다. UIAction은 입력 키 이벤트에 따른 일부 액션을 실행하기 위한 쉬운 방법을 디자이너에게 제공하기 위한 것입니다. 대부분의 경우, 입력 키 이벤트에 따라 실행되는 논리는 위젯 클래스를 작성하는 사람에 의해 C++로 작성됩니다. 위젯용 ProcessInputKey 메서드에서 입력 키 이벤트가 수신되면 원하는 대로 무엇이든 할 수 있습니다. 기본 동작은 어떤 입력 에일리어스가 연관된 입력 키인지 알아낸 다음, 적절하게 해당 액션 에일리어스에 응답합니다. 이 변환 과정은 디자이너에 의해 이전에 지정된 입력 에일리어스 이름에 반응하는 UUIObject::TranslateKey() 함수를 호출하여 실행될 수 있습니다.

위젯이 응답할 입력 키 이벤트 정의하기

위젯이 응답할 입력 키를 정의하는 데에는2 가지 방법이 있습니다. 입력 키와 그의 선택적 관련 액션을 Kismet 상태 입력 이벤트 프로세서에서 정의할 수 있거나 또는 해당 위젯 클래스의 이벤트 에일리어스를 정의하고 Default Alias Key Binding Editor를 통해 입력 키를 이러한 에일리어스에 연결시켜 정의할 수 있습니다. Kismet 내에서의 위젯에 입력 키를 추가하는 것은 해당 위젯의 인스턴스만이 그러한 입력 키에 응답하게 된다는 것을 의미합니다. 기본 Alias Key Binding Editor에서 입력 키를 정의하는 것은 해당 위젯 클래스의 모든 인스턴스가 이러한 입력 이벤트를 포함하는 것임을 의미합니다.

입력 이벤트 에일리어스에 어떤 위젯이 반응할 지를 정의하는 것은 GetSupportedUIActionKeyNames() 함수내에서 할 수 있습니다. 원하는 입력 에일리어스 이름을 out_KeyNames 배열에 추가하기만 하면 Default Alias Key Binding Editor를 통해 입력 키를 이 에일리어스에 연결시킬 수 있습니다. 모든 위젯 클래스 고유의 에일리어스 키 바인딩은 예를 들어 DefaultInputs.ini와 같은 .ini 파일에 저장됩니다.

입력 키 이벤트의 연결 및 처리 방법의 비교적 간단한 예제는 UIButton 클래스를 참조하십시오.

여러 플레이어의 입력 처리

다음은 장면이 여러 플레이어의 입력이 구분하여 처리하는 방법에 대한 간단한 설명입니다. 장면에 입력 키 이벤트가 통지될 경우 이 이벤트를 유발한 컨트롤러의 인덱스도 또한 통지됩니다. 그러나 내부적으로 장면은 좀 더 일반적인 PlayerIndex를 사용하여 플레이어를 구분하므로 장면은 컨틀롤러 인덱스를 UUIScene::PreprocessInput 함수내의 플레이어 인덱스로 변환시킵니다. 내부적으로 장면은 입력 키와 InputSubscriptions 맵에서 처리하도록 구독하는 위젯간의 매핑을 저장합니다. 이 지도의 각 항목은 입력 키 이름과 FInputEventSubscription 객체의 배열을 포함하고 있습니다. 해당 배열의 각 인덱스는 플레이어 인덱스에 해당하기 때문에 각 플레이어는 각 입력 키에 대한 고유 핸들러의 구독을 가지고 있습니다. 그런 다음 장면은 입력 키 이벤트 발생을 유발한 플레이어의 이 입력 이벤트에만 반응하도록 구독하는 위젯을 획득하기 위해 계속 진행합니다. 장면은 이러한 개별 위젯 입력 핸들러를 시작시킵니다. 이 과정은 UUIScene::InputKey 함수에서 볼 수 있습니다.

플레이어 입력 마스크

각 UUIScreenObject는 PlayerInputMask 데이터 필드를 포함합니다. 이 값은 이 컨트롤이 Engine.GamePlayers 배열 어떤 인덱스로부터 입력을 처리할지를 지정합니다. 입력 키를 처리하기 위해 위젯이 자신을 장면으로 구독하는 경우 PlayerInputMask에서 지정된 플레이어에만 그렇게 합니다. 데이터 필드는 스크립트 이벤트 함수인 UIScreenObject::EnablePlayerInput and UIScreenObject::DisablePlayerInput을 통해 설정될 수 있습니다. PlayerInputMask는 비트필드처럼 구현됩니다. 컨트롤이 플레이어 인덱스 2에서 입력을 받아야 할 경우 마스크 값은 2 번째 비트 위치에 1을 갖습니다. 따라서 255의 PlayerInputMask 값은 이 컨트롤이 모든 게임 패드에서 입력을 받아들인다는 것을 의미합니다.

분할 화면

UI 시스템은 분할 화면 UI를 만들는 것을 지원합니다. UI 시스템은 여러 장면이 각 플레이어당 1개씩 동시에 열려질 수 있게 하고, 각 장면이 다른 플레이어의 입력을 처리하는 방법을 지정할 수 있게 합니다. GameUISceneClient는 현재 활성화된 장면을 계속해서 추적하는 역할을 하는 클래스입니다. 이것은 작업에 필요한 모든 데이터를 장면에 제공하고, 렌더링을 장면에 전달하고, 입력 키 이벤트를 전달합니다.

어떤 장면이 어떤 플레이어의 입력을 받는지 EScreenInputMode 필드에 따라 컨트롤 할 수 있습니다. 각 UUIScene 객체는 플레이어 입력 제약을 지정할 수 있게 하는 EScreenInputMode 필드를 포함합니다. 장면의 입력 모드는 UIScene::SetSceneinputMode 스크립트 함수를 통해 지정할 수 있습니다. 장면의 초기화 중 CalculateInputMask 스크립트 함수를 호출되고 이것은 EScreenInputMode 값과 장면을 활성화시킨 플레이어 인덱스 값에 따라 장면의 PlayerInputMask를 적절하게 설정합니다. 다음은 사용 가능한 화면 입력 모드의 개요입니다.

INPUTMODE_None
이 장면은 입력을 전혀 처리하지 않습니다. HUD 장면처럼 입력을 전혀 처리하지 않는 장면의 입력 프로세스를 최적화하는데 유용합니다.

INPUTMODE_Locked
이 장면에서는 동시 입력이 지원되지 않습니다. 이 장면과 연관된 게임패드의 입력만이 처리됩니다. 다른 게임패드의 입력은 무시되고 처리되지 않습니다. 이것은 가장 일반적인 입력 모드입니다.

INPUTMODE_MatchingOnly
이 장면과 연관되지 않은 게임패드의 입력이 스택의 다음 장면으로 전달된 다는 것을 제외하고는 INPUTMODE_Locked와 비슷합니다. 사용 예제는 각 플레이어가 자신의 프로필 선택 메뉴를 열 수 있도록 선택 장면의 윤곽을 그리는데 사용됩니다.

INPUTMODE_ActiveOnly
플레이어에 연관된 활성 게임패드에서만 입력이 받아들여진다는 것을 제외하고는 INPUTMODE_Free와 비슷합니다. 모든 입력과 포커스는 어디에서 발생하는지에 상관없이 동일한 게임패드에서 발생되는 것처럼 처리됩니다. 모든 활성 플레이어가 이 화면과 상호 작용할 수 있도록 합니다.

INPUTMODE_Free
플레이어와 연관되지 않더라도 모든 활성 게임패드는 이 메뉴와 상호 작용할 수 있습니다. 캐릭터 선택 메뉴처럼 추가 플레이어가 활성화될 수 있도록 하는 메뉴에서 사용됩니다.

INPUTMODE_Simultaneous
모든 활성 게임패드의 입력이 이 장면을 통해 처리됩니다. 장면은 각 활성 게임패드에 대한 고유한 컨트롤 집합을 포함하며,이러한 컨트롤은 그것과 연관된 게임 패드의 입력에만 반응합니다. 장면에서 모든 플레이어가 동일한 컨트롤과 상호 작용할 수 있는 장면에서 사용됩니다(대부분의 격투 게임의 캐릭터 선택 메뉴처럼)

입력 처리 시나리오의 예제

InputHandlingSequenceDiagram.jpg

이 도표는 입력 키 이벤트가 사용자에서 위젯으로 전달되는 방법과 위젯이 입력 키 이벤트를 처리하는 방법에 대해 설명합니다. 플레이어가 입력 키 이벤트를 유발할 때 현재 장면은 이 입력 키를 처리하기 위해 현재 구독하는 위젯이 어떤 것인지 찾기 위해 InputSubscriptions 맵을 조회합니다. 그런 다음 입력 처리를 특정 위젯으로 수집합니다. 위젯 HandleInputKeyEvent 함수는 먼저 기본 입력 처리를 재정의하는 이 입력 키와 연관된 모든 Kismet UIActions를 트리거하는 것을 시도합니다. 특정 위젯의 재정의가 Kismet에 없는 경우 기본 입력 처리 구현을 포함한 ProcessInputKey 메서드가 호출됩니다.

  • 입력 처리 시퀀스 도표

포커스 체인 및 바운드 네비게이션


FocusChainDrawings.vsd:

네비게이션의 개요

장면에서 위젯간을 이동하는 것은 위젯의 상태를 변경시킵니다. 현 사용자가 선택한 위젯이 Focused(포커스된) 상태에 있습니다. 사용자가 위젯간을 이동하면 현재 상태에서 벗어나고 Focused 상태로 들어섭니다. 위젯간을 이동하는 데에는 Unbound와 Bound의 2 가지 방법이 있습니다. 언바운드 네비게이션은 포커스 체인 도구를 사용하여 설정되고 바운드 네비게이션은 위젯 Tab 순서에 의해 정의됩니다.

바운드 네비게이션은 위젯 면과 관련 있습니다. 각 위젯에는 왼쪽, 오른쪽, 위, 아래의 4가지 면이 포함됩니다. 각 면은 다른 위젯에 연결될 수 있습니다. 장면내의 위젯 포커스 경로는 언바운드 네비게이션은 입력 이벤트를 수신하면 이 연결을 따릅니다. 바운드 네비게이션은 초기엔 시스템에 의해 설정되고 위젯 TabIndex 순서의 변경을 통해 디자이너가 수정할 수 있습니다. 이 두 경우 네비게이션 순서는 현재 어떤 위젯이 보이고 또는 사용 가능한지에 따라 게임에서 동적으로 변경할 수 있습니다.

포커스를 받을 수 있는 위젯

모든 위젯이 장면내에서 항상 포커스를 받을 수 있는 것은 아닙니다. 특정 액션이 포커스 경로를 방해할 수 있는 위젯을 사용가능/사용불가로 만들 수 있습니다. 위젯이 포커스를 받기 위해서는 다음 조건이 반드시 충족되야 합니다.

  1. 위젯이 반드시 보여야 하고
  2. 사용불가 상태에 있지 말아야 한다.

이러한 값은 위젯의 StateStack*에 존재하는 *bHidden 플래그 및 상태에 의해 표시됩니다.

언바운드 네비게이션

각 위젯은 게임내의 각 플레이어에 대한 FUINavigationData 필드를 포함합니다. 이 Navigation 데이터는 해당 네비게이션 입력 이벤트가 수신될 때 포커스를 받아야 하는 각 면에 대해 하나씩, 총 4개의 위젯 대상을 저장합니다. 네비게이션 링크는 디자이너에 의해 설정될 수 있거나 또는 UI 시스템에 의해 자동으로 설정될 수 있습니다. 처음에 모든 네비게이션 링크는 정의되지 않습니다. 디자이너가 이러한 링크들을 정의하지 않는 경우 UI 시스템에 의해 자동으로 설정됩니다. 링크는 다른 위젯에 연결되거나 또는 명시적으로 NULL로 설정될 시 정의됩니다. NULL 위젯 링크는 UI 시스템 자동 링크 생성 과정 내내 생략됩니다. UI 시스템내의 자동 링크 생성은 각 고유의 "가장 최선의 선택" 대상을 지정합니다. 자동 포커스 링크 생성에 대한 알고리즘은 다음과 같이 되어 있습니다. 자동 링크는 장면의 형제 위젯간에만 설정됩니다. 자동 포커스 링크는 부모 위젯과 자식 위젯간에 절대 생성되지 않습니다. 자식에 포커스가 있는 경우 그 부모에도 반드시 포커스가 있어야 합니다. 시스템은 어떤 위젯이 각 면에 가장 가까운를 비교하고 또한 소스 면에 대해 "올바르게" 위치되어 있는지 확인하여 소스 위젯의 각 면을 다른 형제 위젯에 연결합니다. 예를 들면, 대상 위젯의 왼쪽 면은 소스 위젯의 오른쪽 면을 넘어서야 합니다. 이 알고리즘은 UUIObject::GenerateAutoNavigationLinks 메서드내에서 볼 수 있습니다.

링크가 정의되면 시스템은 언바운드 네비게이션 이벤트를 처리할 준비가 됩니다. 네비게이션 이벤트는 다른 입력 키 이벤트와 마찬가지로 처리됩니다. 이는 즉 현재 포커스 상태에 있는 위젯이 포커스된 상태로 입장하면 위젯 자체를 장면으로 구독하여 네비게이션 입력 이벤트를 처리하는 것을 의미합니다. 사용자가 왼쪽 화살표를 누르면 해당 입력 이벤트는 포커스 상태에 있는 위젯으로 전달되고, 그런 다음 이 위젯은 어떤 대상이 현재 Navigation 데이터 필드에 지정되었는지에 따라 다음엔 포커스가 어디로 가야할지를 결정합니다. 실제 상황에서 위젯의 부모는 네비게이션 이벤트를 수신한 적절한 위젯 형제에게 포커스를 전달합니다. 네비게이션 이벤트를 처리하는 과정은 모든 위젯에 걸쳐 일반적이고 UUIScreenObject::ProcessInputKey와 UUIScreenObject::NavigateFocus 메서드에서 찾아볼 수 있습니다(아래의 바운드 장면 네비게이션 시나리오의 예제를 참조하십시오).

부모와 자식 위젯간의 포커스 전달

부모 위젯에 의한 포커스 획득 절차에는 특별한 규칙이 있습니다. 부모 위젯이 자식 위젯을 포함하고 포커스를 받으면 그 포커스는 가장 적격의 자식 위젯에 자동으로 전달됩니다. 가장 적격인 위젯은 디자이너에 의해 UIEditor에 설정된 TabIndex 값에 의해 결정됩니다. 디자이너가 자식에 대한 TabIndex 값을 지정하지 않으면 가장 적격의 자식은 현재 UUIScreenObject::Children 배열의 첫 번째 위치에 있는 위젯입니다. 부모가 포커스를 자식에서 전달한 후 부모 위젯과 자식 위젯이 모두 포커스 상태가 되지만 자식 위젯만이 모든 입력 이벤트에 반응하게 됩니다. 이 시점에서 포커스 네비게이션은 자식 위젯의 범위에 남아있게 되지만 1가지 중요한 특징을 갖게 됩니다. 자식 위젯이 네비게이션 입력 이벤트를 수신하지만 지정된 방향으로 정의된 포커스 링크가 없는 경우, 네비게이션 요청을 부모에게 전달합니다. 그런 다음 부모 위젯의 포커스 체인은 다음 포커스 대상을 결정합니다. 따라서 포커스는 부모의 자식에서 부모의 형제를 건너뛰게 됩니다.

바운드 네비게이션

바운드 네비게이션은 장면의 모든 위젯에 걸쳐 "선형" 방식으로 반복합니다. 현재의 위젯에서 다음 1개 또는 이전 1개의 위젯만으로 네비게이션할 수 있습니다. 각 위젯은 바운드 네비게이션 이벤트가 발생할 시 포커스를 받는 형제 위젯을 포함하는 FUIFocusPropagationData 배열을 갖습니다. FUIFocusPropagationData::NextFocusTarget는 NextControl 이벤트의 경우에 포커스를 받는 위젯이고, FUIFocusPropagationData::PrevFocusTarget은 PrevControl 이벤트의 경우에 포커스를 받는 위젯입니다. 이러한 대상은 UUIScreenObject::RebuildKeyboardNavigationLinks가 호출될 때 요청된 장면이 업데이트하는 동안 할당됩니다. 링크 재빌드 과정의 순서는 위젯의 TabIndex 값에 따라 형제 위젯을 배열합니다. 가장 작은 탭 값을 가진 위젯이 포커스를 먼저 받고 그 다음 대상은 두 번째로 가장 작은 TabIndex 값을 갖는 형제 위젯입니다. 2개 이상의 위젯이 동일한 TabIndex 값을 갖는 경우, 각각의 순서는 부모의 Children 배열에서의 현 위치에 따라 결정됩니다. 다음과 이전 컨트롤로 포커스 전환시키는 것을 처리하는 메서드는 UUIScreenObject::NextControl and UUIScreenObject::PrevControl입니다. 이것은 현재 위젯에 다음 컨트롤이 없으면 의미가 없습니다. 그 이유는 이것이 마지막 TabIndex와 형제 관계를 맺은 다음, 바운드 네비게이션 처리는 NextControl 또는 PrevControl 요청을 위젯의 부모에게 전달하고, 부모의 링크는 다음 포커스 대상을 결정하기 때문입니다. 따라서, 형제만이 아닌 장면에 있는 모든 위젯에 걸쳐 반복을 하게됩니다.

언바운 장면 네비게이션 시나리오의 예제

다음은 장면에서 사용자가 한 위젯에서 다른 위젯으로 이동하는 시나리오입니다. 장면에는 Button0은 Button1과 Button2의 부모이고 Button2는 Button3의 부모인 4개의 버튼이 있습니다. 시나리오는 Button1에 포커스가 있고 사용자가 포커스를 Button2로 이동하는 것으로부터 시작됩니다.

  • 버튼 계층

FocusChainDiagramButtonHierarchy.jpg

  • 네비게이션 이벤트 시퀀스 도표

FocusChainNavFocusSequenceDiagram.jpg

이 도표는 시스템이 NavFocus 입력 이벤트를 수신할 때 무슨 일이 발생하는지, 그리고 포커스를 현재 위젯에서 네비게이션 대상에 어떻게 전달하는지에 대해 설명합니다. 사용자가 NavFocus 이벤트를 현재 포커스된 Button1으로 보냅니다. Button1은 NavigateFocus 호출을 Button1의 FUINavigationData 필드의 네비게이션 대상인 형제 위젯을 검색하는 부모에 전달합니다(디자이너가 Button1의 포커스 체인 대상을 지정하지 않았으면 Button0은 부모에 호출을 전달하고 Button0의 포커스 체인 대상이 선택됩니다). 포커스 체인 링크는 Button2가 포커스를 받는 형제 위젯이라는 것을 보여주므로 SetFocus 호출을 전달합니다. 이 메서드를 실행하면 대상이 포커스 상태로 전환되고 또한 포커스를 자식(있는 경우)에 전달합니다. 그러므로 이 예제에서 Button2와 Button3 모두 결과적으로 포커스 상태가 됩니다.

  • 포커스 획득 시퀀스 도표

FocusChainGainFocusSequenceDiagram.jpg

이 도표는 포커스 획득하기 위해 위젯을 호출하면 무슨 일이 일어나는지, 이전에 포커스된 컨트롤이 어떻게 자신의 포커스를 잃는지에 대해 설명하고 있습니다. 위젯의 UUIScreenObject::GainFocus 메서드가 호출되면 ActivateState (포커스된)가 호출될 때 위젯 상태 전환이 발생하고, 이것은 위젯의 현재 상태를 스택에 포커스된 상태를 추가합니다. 그런 다음, 위젯 부모에 포커스 되었다는 것을 알려야 합니다. 부모는 현재 어떤 자식이 포커스에 있는지에 정보를 저장하는 것을 담당하고 또한 이전에 포커스된 컨트롤을 찾아 이 포커스를 소멸시키는 것도 담당합니다. Button0은 FPlayerInteractionData 배열을 검색하여 이 경우에는 Button1인 이전에 포커스된 컨트롤을 찾습니다. Button1이 포커스를 잃을 때, 포커스를 얻기전의 상태로 돌아갑니다. Button0의 다음 단계는 아직 포커스되지 않은 경우 포커스 상태로 전환하는 것입니다. 모든 적절한 위젯이 위젯의 상태를 변경한 후, 기존 컨트롤(Button2)은 입력 키 이벤트의 새 대기자로 자신을 등록합니다.

메뉴 상태


개요

Widget State(위젯 상태)은 특정 사용자 입력 설정, Kismet 논리, 스타일 데이터를 포함할 수 있는 위젯에 적용될 수 있는 조건입니다. 다음은 Unreal 시스템에서 메뉴 상태가 어떻게 작동하는지에 대한 보다 포괄적인 설명입니다.

상태 클래스

모든 위젯 상태에 대한 일반적인 추상 클래스는 UUIState입니다. 이것은 Kismet 시퀀스 논리와 사용자가 정의한 입력 키 이벤트 재정의와 같은 위젯에 관련된 상태 고유의 정보를 담고 있습니다. 또한 상태는 위젯의 활성화 및 비활성화 요청의 처리도 담당합니다. 프로그래머는 일반 UUIState 클래스에서 파생되는 새로운 상태를 만들 수 있습니다. 파생 상태에서 이 상태가 활성/비활성화될 때 행해지는 기본 액션을 변경할 수 있습니다. Unreal Script 이벤트 함수인 OnActivate을 구현하거나 또는 C++에서 OnActivate 메서드를 재정의하여 기본 상태 활성 동작을 변경할 수 있습니다. 마찬가지로 비활성 상태의 동작은 상태 스크립트 또는 C++ 구현에서 OnDeactivate 함수를 재정의하여 변경될 수 있습니다. 이러한 메서드 모두 모든 위젯에 걸쳐 이 상태의 모든 인스턴스에 영향을 미칩니다. 그러나 활성화/비활성화 시 1개의 특정 상태 인스턴스 동작을 변경하려면 Kismet 통해 이벤트 "Enter State"와 "Leave State"에 논리를 추가함으로써 그렇게 할 수 있습니다. 추가 예제는 기존의 상태의 구현, 예를 들어 UUIState_Active를 참조해 주십시오.

위젯이 상태와 상호 작용하는 방법

각 UUIScreenObject(위젯)는 프로그래머에 의해 정의된 들어갈 수 있는 상태 목록 있지만 정의상 모든 위젯은 반드시 적어도 활성화/비활성 상태를 포함해야 합니다. 지원되는 상태의 해당 목록은 상태 이름을 DefaultStates 배열에 추가하여 위젯 클래스 기본 속성 블록에서 정의됩니다.

  • 다음은 UIButton.uc의 UIButton DefaultProperties에서 참조된 것입니다.
      // 상태
      DefaultStates.Add(class'Engine.UIState_Focused')
      DefaultStates.Add(class'Engine.UIState_Active')
      DefaultStates.Add(class'Engine.UIState_Pressed')

장면이 초기화되면 모든 위젯은 DefaultStates 배열에 있는 항목을 인스턴스화하고 UUIScreenObject::InactiveStates 배열을 UUIState 객체로 채웁니다. 위젯의 InactiveStates 목록내에 있는 각 객체는 고유 사용자가 정의할 수 있는 동작의 컨테이너 역할을 합니다. InactiveStates 목록에서의 특정 상태가 활성화되면 그것은 위젯의 StateStack로 이동하고, 현재 해당 스택의 맨 위에 있는 상태가 위젯의 상태를 나타냅니다. 상태 스택에 상태를 추가하여 예를 들어 스택에서 이미 사용 가능화된 상태가 없는 한 위젯은 포커스된 상태로 전환할 수 없습니다와 같은 특정 상태 전환 규칙을 시행할 수 있습니다. StateStack에서 존재하는 상태는 네비게이션 및 입력 키 이벤트를 통해서, 또는 코드를 통해 수동으로 언제든지 비활성화될 수 있습니다. 상태가 비활성화되면 스택에서 제거되며 비활성화된 상태가 스택의 맨 위에 있는 경우, 위젯은 상태를 스택의 이전 상태로 변경합니다.

위젯이 새 상태에 들어가면 내재하는 논리의 변화와 시각적 모습의 변화가 발생합니다. 위젯의 논리는 현 상태의 Kismet 시퀀스에 있는 이벤트와 액션을 및 상태 정의된 입력 키 재정의(overrides)를 통해 표현될 수 있습니다. 새 위젯 상태가 활성화될 경우 기본 동작은 다음과 같습니다.

  1. 상태를 위젯의 StateStack에 넣습니다.
  2. 현재 Kismet에 있는 모든 OnEnterState 이벤트를 트리거합니다.
  3. StateSequence를 위젯의 이 상태에 의해 포함된 논리를 범위에 넣는 EventProvider 구성 요소에 추가합니다.
  4. 상태의 고유 입력 키 핸들러 장면과 함께 적절한 사용자 입력 처리에 등록합니다.
  5. 현 상태에 대한 위젯의 내재하는 스타일 데이터를 변경합니다.

이 기본 동작은 프로그래머에 의해 파생된 클래스에서 재정의할 수 있는 UUIState::OnActivate 메서드에서 찾을 수 있습니다. 새 상태의 시각적 모습은 개별 위젯이 담당하고 각각의 OnStyleResolved 메서드에서 찾을 수 있습니다.

시스템에 의해 정의된 상태

현재 5개의 메뉴 상태가 UI 시스템에 구현되어 있습니다. 각 상태는 특별한 고유 규칙과 행동을 가지고 있습니다. 다음은 위젯이 이러한 상태에 들어갈 때 시스템이 어떻게 반응할지에 대한 자세한 설명입니다.

Active
UUIState_Active 클래스로 표현됩니다. 사용 가능화된 상태가 활성 상태로 들어가기 전에 반드시 위젯의 StateStack내에 존재해야 합니다. 마우스 커서가 어떤 위젯 위에 올 때 위젯이 활성 상태가 됩니다. 위젯이 누름 상태에 있는 경우 UUIState_Active는 예를 들어 StateStack에서 제거되는 것처럼 비활성화될 수 없습니다.

Disabled
UUIState_Disabled 클래스로 표현됩니다. 위젯이 이 상태에 들어가면 StateStack에 있는 모든 상태는 지워지고 비활성화됩니다. 일단 사용 불가능된(disabled) 상태가 되면 위젯은 사용 가능화된(enabled) 상태 밖에 들어갈 수 없습니다. 사용 불가능된 부모 위젯의 자식도 또한 사용 불가능된 상태에 들어가게 됩니다.

Enabled
UUIState_Enabled 클래스로 표현됩니다. 위젯은 반드시 사용 불가능된 상태가 아닌 상태로 전환하기 전에 반드시 사용 가능화된 상태에 있어야 합니다. 사용 가능화된 상태의 비활성화는 또한 스택에서 현재 사용 가능화된 상태 위에 있는 모든 상태를 비활성화 시킵니다.

Focused
UUIState_Focused 클래스로 표현됩니다. 포커스된 상태로 들어가기 전에 위젯은 사용 가능화된 상태여야 합니다. 바운드 및 언바운드 네비게이션 이벤트는 위젯이 이 상태에 들어가게 유발합니다. UI 네비게이션 시스템내에 포커스된 상태에 들어간 위젯의 자식을 포커스로 추가 설정하는 사전에 정의된 행동이 존재합니다. 이 기능으로 인해 입력 이벤트 등록은 UUIState_Focused::OnActivate 메서드에서 이루어지지 않고 UI 시스템 네비게이션 처리 코드에서 수행됩니다. 포커스를 가진 위젯의 자식만이 부모 장면에 자신을 등록하여 사용자 입력 이벤트를 수신합니다. 포커스된 상태의 비활성화는 또한 스택에 존재할 경우 눌러진 상태를 비활성화 시킵니다.

Pressed
UUIState_Pressed 클래스로 표현됩니다. 눌러진 상태로 들어가기 전에 위젯은 반드시 사용 가능화도니 상태에 있어야 합니다. 눌러진 상태의 활성화는 위젯이 포커스된 상태에 들어가게 합니다.

  • 메뉴 상태 클래스 도표

MenuStatesClassDiagram.jpg

데이터 표현


UI에서 데이터가 어떻게 조작되고 표현되는지 데이터 저장소 기술적 가이드 를 참조해 주십시오.

애니메이션


UI에서 위젯을 애니메이션화하는 방법에 대해서는 UI 애니메이션 기술적 가이드 를 참조해 주십시오.

제한 사항


씬간에 움직여 다니기 위해서 염두에 둘 것은, 현재 포커스된 씬을 닫아야 한다는 겁니다.

UI 솔루션에서 애니메이션이나 전이 용도로 다수의 씬을 사용하는 경우, 씬 내의 자체 패널에 넣고서 그걸 마스터 씬으로 사용할 수 있습니다. 기어즈 2의 점수판은 모두 한 UI 씬에 있었으며, 게임타입에 따라 끄고 켰으며, Party Menus에 대한 것과 비슷하게 모든 것은 하나의 UI씬에 있었습니다.

UI 장면 및 위젯 디버깅하기


UI 디버깅 텍스트를 표시하려면 메뉴가 열려있는 상태에서 Ctrl+Alt+D를 누릅니다. 이것은 어떤 위젯이 활성화되었고, 포커스된 상태에 있고, 현재 어떤 상태에 있는지를 보여줍니다.

다운로드


* MenuStatesDrawings.vsd