Instantly share code, notes, and snippets.
Last active
January 14, 2016 11:23
-
Star
(0)
0
You must be signed in to star a gist -
Fork
(0)
0
You must be signed in to fork a gist
-
Save yasuakiohama/022c9e3f3330778a09e4 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// | |
// Unity5.2.3p3 | |
// SortComponentsWindow.cs | |
// http://yasuaki-ohama.hatenablog.com/entry/SortComponentsWindow | |
// | |
// Created by yasuaki ohama on 2016/01/11. | |
// http://yasuaki-ohama.com/ | |
// | |
// 機能 | |
// ドラックでコンポーネント入れ替え+更新 | |
// Undo、Redoに対応 | |
// スクリプトが外れている場合の対処 | |
// コンポーネントの順番とスクリプト名を表示 | |
// アタッチしたスクリプト内にある変数の値を表示 | |
using UnityEngine; | |
using UnityEditor; | |
using UnityEditorInternal; | |
using System.Collections.Generic; | |
using System.Linq; | |
using System.Reflection; | |
/// <summary> | |
/// GameObjectのコンポーネントをソートする | |
/// </summary> | |
public sealed class SortComponentsWindow_NoButton : EditorWindow | |
{ | |
/// <summary> | |
/// 参照するGameObject | |
/// </summary> | |
private GameObject m_target = null; | |
/// <summary> | |
/// 参照するオブジェクトのコンポーネントの格納 | |
/// </summary> | |
private Component[] m_targetComponents; | |
/// <summary> | |
/// コンポーネントの入れ替えに利用 | |
/// </summary> | |
private ReorderableList m_reorderableList = null; | |
/// <summary> | |
/// 入れ替えの状態を格納 | |
/// </summary> | |
private List<Component> m_components = new List<Component> (); | |
/// <summary> | |
/// GameObjectのコンポーネントの更新状態と同期 | |
/// </summary> | |
private List<Component> m_diffComponents = new List<Component> (); | |
/// <summary> | |
/// スクロール用変数 | |
/// </summary> | |
private Vector2 m_scrollPosition; | |
/// <summary> | |
/// ソートウィンドウの表示 | |
/// </summary> | |
[MenuItem( "EditorWindow/Sort Components Window" )] | |
private static void Init() | |
{ | |
EditorWindow.GetWindow (typeof(SortComponentsWindow), false, "Sort Components Window"); | |
} | |
/// <summary> | |
/// GameObjectのコンポーネントの更新を反映 | |
/// </summary> | |
/// <param name="components">Components.</param> | |
private void UpdateComponents(List<Component> components) | |
{ | |
components.Clear (); | |
components.AddRange (m_targetComponents); | |
components.RemoveAt (0);// delete Transform | |
if (components == m_components) { | |
m_reorderableList = new ReorderableList (components, typeof(Component)); | |
m_reorderableList.displayAdd = false; | |
m_reorderableList.displayRemove = false; | |
m_reorderableList.drawHeaderCallback = (rect) => { | |
EditorGUI.LabelField(rect, m_target.name + " Components"); | |
}; | |
m_reorderableList.drawElementCallback = (rect, index, isActive, isFocused) => { | |
EditorGUI.LabelField(rect, DrawElementCallback((Object)m_reorderableList.list[index], index)); | |
}; | |
m_reorderableList.onChangedCallback = (list) => { | |
//ソートしたコンポーネントを複製し値を入れる | |
foreach (Component component in m_components) { | |
var addedComponent = Undo.AddComponent (m_target, component.GetType ()); | |
foreach (FieldInfo fi in component.GetType().GetFields()) { | |
fi.SetValue (addedComponent, fi.GetValue (component)); | |
} | |
} | |
//古いコンポーネントの削除 | |
foreach (Component component in m_components) { | |
Undo.DestroyObjectImmediate (component); | |
} | |
UpdateComponents (m_diffComponents); | |
UpdateComponents (m_components); | |
}; | |
} | |
} | |
/// <summary> | |
/// リストの順番とクラス名を表示 | |
/// </summary> | |
/// <returns>The element callback.</returns> | |
/// <param name="obj">Object.</param> | |
/// <param name="index">Index.</param> | |
private string DrawElementCallback(Object obj, int index) | |
{ | |
return string.Format ("{0:D2}:{1}", (index + 1), obj.GetType ()); | |
} | |
/// <summary> | |
/// アタッチしたスクリプト内にある変数の内容を表示する(なければnull) | |
/// 型:GameObject 変数名:target | |
/// 型:String 変数名:key | |
/// 型:int 変数名:value | |
/// </summary> | |
/// <returns>The element callback custom.</returns> | |
/// <param name="obj">Object.</param> | |
/// <param name="index">Index.</param> | |
private string DrawElementCallbackCustom(Object obj, int index) | |
{ | |
var targetName = "null"; | |
var key = "null"; | |
var value = 0; | |
if (obj == null) { | |
return string.Format ("{0:D2}:{1}:{2}:{3}:{4}", (index + 1), obj.GetType (), targetName, key, value); | |
} | |
SerializedObject so = new SerializedObject (obj); | |
if (so.FindProperty ("target") != null) { | |
if (so.FindProperty ("target").objectReferenceValue != null) { | |
targetName = so.FindProperty ("target").objectReferenceValue.name; | |
} | |
} | |
if (so.FindProperty ("key") != null) { | |
if (so.FindProperty ("key").stringValue != null) { | |
key = so.FindProperty ("key").stringValue; | |
} | |
} | |
if (so.FindProperty ("value") != null) { | |
value = so.FindProperty ("value").intValue; | |
} | |
return string.Format ("{0:D2}:{1}:{2}:{3}:{4}", (index + 1), obj.GetType (), targetName, key, value); | |
} | |
/// <summary> | |
/// GameObjectのコンポーネントに更新があるかチェック | |
/// </summary> | |
/// <returns><c>true</c>, if components update was checked, <c>false</c> otherwise.</returns> | |
private bool CheckComponentsUpdate() | |
{ | |
if (m_components.Count != m_targetComponents.Length - 1) { | |
//Debug.Log ("コンポーネントの数が合わない");//ウィンドウの + -を押した場合の対処 | |
return true; | |
} | |
if (m_diffComponents.Count != m_targetComponents.Length - 1) { | |
//Debug.Log ("コンポーネントの数が合わない"); | |
return true; | |
} | |
foreach (var component in m_components) { | |
if (component == null) { | |
//Debug.Log ("componentがnull"); | |
return true; | |
} | |
} | |
foreach (var component in m_diffComponents) { | |
if (component == null) { | |
//Debug.Log ("componentがnull"); | |
return true; | |
} | |
} | |
foreach (var component in m_targetComponents.Select((v, i) => new { index = i, value = v })) { | |
if (component.index == 0) { | |
//Transformはチェックしない | |
continue; | |
} | |
if (component.value != m_diffComponents [component.index - 1]) { | |
//Debug.Log ("オブジェクトの参照先が違う"); | |
return true; | |
} | |
} | |
return false; | |
} | |
private void OnGUI() | |
{ | |
m_target = (GameObject)EditorGUILayout.ObjectField (m_target, typeof(GameObject), true); | |
if (m_target == null) { | |
//オブジェクトがなければ何も表示しない | |
return; | |
} | |
m_targetComponents = m_target.GetComponents<Component> (); | |
foreach (var component in m_targetComponents) { | |
if (component == null) { | |
//スクリプトが外れていれば何も表示しない | |
EditorGUILayout.LabelField ("The referenced script on this Behaviour is missing!"); | |
return; | |
} | |
} | |
//参照しているGameObjectの更新は「EditorGUI.BeginChangeCheck ();」で習得することができないため、 | |
//手動でGameObjectのコンポーネントの更新をチェックする。 | |
//毎回更新を行うとReorderableListで入れ替え操作ができないため更新時のみ反映するようにした | |
if (CheckComponentsUpdate () || m_reorderableList == null) { | |
UpdateComponents (m_diffComponents); | |
UpdateComponents (m_components); | |
} | |
m_scrollPosition = EditorGUILayout.BeginScrollView(m_scrollPosition); | |
//GameObjectのコンポーネントの順番を表示 | |
m_reorderableList.DoLayoutList (); | |
EditorGUILayout.EndScrollView(); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment