Wednesday, November 13, 2013

NGUI의 UICenterOnChild 동작 원리

재밌는 방식으로 구성되어 있어 문서로 정리해 본다.

UICenterOnChild는 스크립트 콤포넌트로 추가되면 Draggable Object들을 화면 가운데로 정렬 하는데 이 정렬을 위해서 드래그가 끝났을 때 코드가 실행된다. UIDraggablePanel의 소스를 살펴 보면 UICenterOnChild와 연결된 부분은 전혀 없고

public OnDragFinished onDragFinished;

델리게이트 함수만 호출한다. 그런데 재밌는 점은 코드 어디에도 onDragFinished를 설정하는 부분이 없다는 점이다. 보통은 호출자에서 호출되는 부분의 함수를 연결하는데 NGUI는 그렇게 하지 않았다.

아무튼 onDragFinished가 연결되어 있다면 (null이 아니라면) 함수를 호출한다. 이는 다음과 같이 연결된다.

UICenterOnChild가 처음에 실행되면 OnEnable()가 호출되는데 여기서 Recenter()를 호출한다. Recenter는 OnDragFinished()가 호출될 때도 호출이 되는데 델리게이트를 연결하는 부분과 실제로 Center에 오브젝트를 정렬하는 기능 2개가 하나에 들어가 있다. (그래서 헷갈린다. 좋은 설계는 아니다.)

Recenter의 내부에 다음과 같은 코드가 있다.

---
if (mDrag == null)
{
mDrag = NGUITools.FindInParents<UIDraggablePanel>(gameObject);

if (mDrag == null)
{
Debug.LogWarning(GetType() + " requires " + typeof(UIDraggablePanel) + " on a parent object in order to work", this);
enabled = false;
return;
}
else
{
mDrag.onDragFinished = OnDragFinished;

if (mDrag.horizontalScrollBar != null)
mDrag.horizontalScrollBar.onDragFinished = OnDragFinished;

if (mDrag.verticalScrollBar != null)
mDrag.verticalScrollBar.onDragFinished = OnDragFinished;
}
}
if (mDrag.panel == null) return;

---

이 부분이 델리게이트를 연결하는 부분이ㅐ다. NGUITools의 FindINParents함수를 호출해서 현재 gameobject의 부모에 오브젝트를 가지고 온다. (그것은 UIDraggablePanel이 된다.)

그리고 mDrag의 onDragFinished에 현재 UICenterOnChild의 OnDragFinished 델리게이트를 연결한다. 이렇게 함으로써 UIDraggablePanel에서 드래그가 끝났을 때 UICenterOnChild의 OnDragFinished를 호출하고 여기서 오브젝트를 가운데로 정렬하는 로직이 실행된다.


끝.

Task in UnrealEngine

 https://www.youtube.com/watch?v=1lBadANnJaw