Unity EditorWindow & ReorderableList

利用Unity的EditorWindow和ReorderableList來取得特定Gameobject上的Component 

 

​
[Serializable]
public struct item
{
	public GameObject target;
	public MonoScript script;
}

public class HolderItems :ScriptableObject
{
	public List<item> items = new List<item> ();
}

​
​
void OnEnable ()
	{

		var m_HolderItems = CreateInstance<HolderItems> ();

		if (m_HolderItems != null) {

		SerializedObject holderItemsSo = new SerializedObject (m_HolderItems);

		ReorderableList	list = new ReorderableList (holderItemsSo, holderItemsSo.FindProperty ("items"), false, false, true, true);

            //繪製Title
			list.drawHeaderCallback = rect => EditorGUI.LabelField (rect, string.Format ("Create Assets/{0}Holder.cs", holderName));
            
            //繪製每一列
			list.drawElementCallback = (Rect rect, int index, bool isActive, bool isFocused) => {

				var element = list.serializedProperty.GetArrayElementAtIndex (index);

				rect.y += 2;

				GameObject go = (GameObject)element.FindPropertyRelative ("target").objectReferenceValue;

				EditorGUI.PropertyField (new Rect (rect.x, rect.y, 150, EditorGUIUtility.singleLineHeight), element.FindPropertyRelative ("target"), GUIContent.none);
                
				if (go != null) {
                    //取得特定Gameobject的Components並秀出
					componData [index].componGo = go;

					Component[] compons = go.GetComponents<Component> ();

					List<string> componsName = new List<string> ();

					for (int i = 0; i < compons.Length; i++) {
						if (compons [i].GetType ().Name.Contains ("CanvasRenderer"))
							continue;
						componsName.Add (compons [i].GetType ().Name);
					}

					GameObject parentGo = (index != 0) ? go : componData [0].componGo;

					while (parentGo.transform.parent != null) {
						if (parentGo.transform.parent.name.Contains ("canvas_"))
							break;
						parentGo = parentGo.transform.parent.gameObject;
					}

					StringBuilder holderNameBuilder = new StringBuilder ();

					string[] parentNames = parentGo.name.Split ('_');

					for (int s = 0; s < parentNames.Length; s++) {
						holderNameBuilder.Append (upperStringFirst (parentNames [s]));
					}

					if (index != 0) {
						if (!holderNameBuilder.ToString ().Equals (holderName)) {
							Debug.LogErrorFormat ("{0} && First GameObejct is not Same Root , {0} Parent is {1} !", go.name, parentGo.name);
						}
					} else {
						holderName = holderNameBuilder.ToString ();
					}

					componsName.Add (go.GetType ().Name);

					componsName.Add ("Script");

					componData [index].SetComponsName (componsName);

					componData [index].componIndex = EditorGUI.Popup (new Rect (rect.x + 200, rect.y, 150, EditorGUIUtility.singleLineHeight), componData [index].componIndex, componsName.ToArray (), EditorStyles.popup);

					if (componData [index].GetComponName ().Equals ("Script")) {
						EditorGUI.PropertyField (new Rect (rect.x + 400, rect.y, 150, EditorGUIUtility.singleLineHeight), element.FindPropertyRelative ("script"), GUIContent.none);
					} else {
						componData [index].arrayIndex = EditorGUI.Popup (new Rect (rect.x + 400, rect.y, 150, EditorGUIUtility.singleLineHeight), componData [index].arrayIndex, componData [index].componIsArray, EditorStyles.popup);
					}
				}

			};
		}

		list.onAddCallback = (ReorderableList addList) => {

			//Base Add
			var index = addList.serializedProperty.arraySize;
			addList.serializedProperty.arraySize++;
			addList.index = index;

			//ComponData List Add Item
			componData.Add (new holderComponData ());

			//Gameobject Clear
			var element = addList.serializedProperty.GetArrayElementAtIndex (index);
			element.FindPropertyRelative ("target").objectReferenceValue = null;
		};

		list.onRemoveCallback = (ReorderableList removeList) => {

			//ComponData List Remove At ListIndex
			componData.RemoveAt (removeList.index);

			//Base Remove
			ReorderableList.defaultBehaviours.DoRemoveButton (removeList);
		};


		Repaint ();
}

​

    void OnGUI ()
    {

        if (holderItemsSo.targetObject != null) {
            holderItemsSo.Update ();
            list.DoLayoutList ();
            holderItemsSo.ApplyModifiedProperties ();
        }  
    }