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 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 | using UnityEngine; using System.Collections.Generic; using UnityEditor; using System.IO; // NGUI 라이브러리의 경우 // UIButton 컴포넌트는 UIButtonColor 을 상속받는다. // UIButtonColor에는 tweenTarget 변수가 있으며, 이 변수가 tweening을 할 대상 오브젝트를 가진다. // 근데, UIButtonColor.OnInit 메소드에 Unity 버전 4.6, 4.3, 4.5등에 대해 tweenTarget에 Light 컴포넌트가 없으면 // tweenTarget을 null로 할당하는 코드가 있다. 우선 이부분을 주석처리하고 하면 에디터상에서 변경한 버튼컴포넌트 프리팹이 // 씬 화면에 로딩되어도 정상적으로 tweenTarget레퍼런스가 끊기지 않는다. public class LegacyButtonChanger : Editor { private static UIButtonMessage[] legacyUIButtonsMsgs; private static UIEventTrigger[] legacyUIEventTriggers; [MenuItem("LegacyButtonChanger/ChangeLegacyButtons")] public static void ChangeLegacyButtons() { Debug.Log("<color=green><b>[Changer_Logging]</b></color>Start Log legacy buttons"); string[] filesFolderPath = Directory.GetFiles("Assets/Prefabs/Lobby/"); // 주어진 파일 폴더경로에서 .prefab 확장의 파일들을 검색한다. // 해당 파일에 child로 속한 파일들은 얻을 수 없으므로 해당 파일을 root로 하여 // Legacy한 컴포넌트들을 가져온다. foreach (var p in filesFolderPath) { if (Path.GetExtension(p).Equals(".prefab")) { GameObject root = AssetDatabase.LoadAssetAtPath(p, typeof(Object)) as GameObject; if (root == null) Debug.Log("Loaded Asset is NULL"); else { ExtractLegacyBtns(root); ChangeBtnComponent(); //EditorUtility.SetDirty(root); } } } Debug.Log("<color=green><b>[Changer_Logging]</b></color>Finish Log legacy buttons"); } private static void ExtractLegacyBtns(GameObject root) { legacyUIButtonsMsgs = root.GetComponentsInChildren<UIButtonMessage>(); legacyUIEventTriggers = root.GetComponentsInChildren<UIEventTrigger>(); } private static void ChangeBtnComponent() { // UIButtonMessages.. if (legacyUIButtonsMsgs != null) { foreach (var msgComp in legacyUIButtonsMsgs) { string targetFuncName = msgComp.functionName; if (msgComp.target == null) { Debug.Log(string.Format("")); continue; } if(targetFuncName == null) { Debug.Log(string.Format("")); continue; } if(targetFuncName == "") { Debug.Log(string.Format("")); continue; } MonoBehaviour[] targetMonoComponents = msgComp.target.GetComponents<MonoBehaviour>(); if (targetMonoComponents != null) { foreach (var targetMonoComp in targetMonoComponents) { if (targetMonoComp == null) { Debug.Log("Target의 컴포넌트가 Missing 이거나 Null 입니다."); continue; } System.Type scriptType = targetMonoComp.GetType(); if (scriptType.GetMethod(targetFuncName) != null) { Debug.Log(string.Format("{0} msgComponent :: {1} is, type--> {2}" , msgComp.name, targetMonoComp.name, targetMonoComp.GetType())); GameObject toBeAttachedObj = msgComp.gameObject; // 타겟의 모노비헤이비어와 메소드이름을 주어 생성하면 // 이벤트델리게이트 클래스 안에서 해당 메소드를 리플렉션하여 파라미터가 필요한지 아닌지를 확인한다. // EventDelegate ed = new EventDelegate(targetMonoComp, targetFuncName); EventDelegate.Parameter param = new EventDelegate.Parameter(); // 파라미터로, 새로운 UIButton 컴포턴트가 붙어야할 오브젝트를 할당해준다. param.obj = toBeAttachedObj; // 추출한 타겟의 메소드에서 파라미터를 요구한다면. if(ed.parameters != null) { ed.parameters[0] = param; } else // 추출한 타겟의 메소드에서는 파라미터가 없다. { // 파라미터를 할당해 줄 필요가 없다. } AddUIButtonComp(toBeAttachedObj, ed); RemoveUIButtonMessage(toBeAttachedObj); break; } else { // GetType().GetMethod() 리플렉션에서 메소드를 구해오는건 public만 가능. // 실패한다면 해당 메소드 접근자는 private 이다. // 실패한 경우, 해당 메소드가 어느 스크립트에 존재하는지 로그를 남겨야한다. Debug.Log(string.Format("<color=red><b>[Changer_Alert]</b></color> <b>@Private Accesser Find@" +"</b> scriptName : {0}, methodName :{1}", scriptType.Name, targetFuncName)); } } } } } // UIEventTriggers.. if (legacyUIEventTriggers != null) { foreach (var trigger in legacyUIEventTriggers) { Debug.Log(string.Format("attached {0} prefab's parent : {1}, :: {2} is trigger, {3} (OnClick..) ", trigger.gameObject, trigger.gameObject.transform.parent, trigger.name, trigger.onClick)); GameObject toBeAttachedObj = trigger.gameObject; AddUIButtonComp(toBeAttachedObj, trigger.onClick); RemoveUIEventTrigger(toBeAttachedObj); } } } private static void AddUIButtonComp(GameObject toBeAttachedObj, EventDelegate onClickEvent) { UIButton uiButtonComp = toBeAttachedObj.GetComponent<UIButton>(); if (uiButtonComp != null) { bool isExist = uiButtonComp.onClick.Exists((other) => { return other.methodName.Equals(onClickEvent.methodName); }); if (isExist == false) { uiButtonComp.onClick.Add(onClickEvent); } // onClick list에 동일한 이벤트가 있던 없던, tween target은 설정해준다. uiButtonComp.tweenTarget = toBeAttachedObj; } else { UIButton addedComponent = toBeAttachedObj.AddComponent<UIButton>(); addedComponent.onClick.Add(onClickEvent); addedComponent.tweenTarget = toBeAttachedObj; } } private static void AddUIButtonComp(GameObject toBeAttachedObj, List<EventDelegate> onClickEvents) { UIButton uiButtonComp = toBeAttachedObj.GetComponent<UIButton>(); if (uiButtonComp != null) { uiButtonComp.onClick = onClickEvents; uiButtonComp.tweenTarget = toBeAttachedObj; } else { UIButton addedComponent = toBeAttachedObj.AddComponent<UIButton>(); addedComponent.onClick = onClickEvents; addedComponent.tweenTarget = toBeAttachedObj; } } private static void RemoveUIEventTrigger(GameObject obj) { if (obj.GetComponent<UIEventTrigger>() != null) DestroyImmediate(obj.GetComponent<UIEventTrigger>(), true); } private static void RemoveUIButtonMessage(GameObject obj) { if (obj.GetComponent<UIButtonMessage>() != null) DestroyImmediate(obj.GetComponent<UIButtonMessage>(), true); } } |
2019년 4월 12일 금요일
# NGUI 컴포넌트 교체하는 샘플 코드
피드 구독하기:
댓글 (Atom)
댓글 없음:
댓글 쓰기