326 lines
11 KiB
C#
326 lines
11 KiB
C#
using UnityEditor;
|
|
using UnityEditorInternal;
|
|
using UnityEngine;
|
|
using UnityEngine.UI;
|
|
|
|
namespace UnityEditor.UI
|
|
{
|
|
[CustomEditor(typeof(UXGroup))]
|
|
public class UXGroupInspector : Editor
|
|
{
|
|
private SerializedProperty m_Toggles;
|
|
private SerializedProperty m_AllowSwitchOff;
|
|
private SerializedProperty m_DefaultToggle;
|
|
private UXGroup m_Target;
|
|
private ReorderableList m_ReorderableList;
|
|
|
|
private void OnEnable()
|
|
{
|
|
m_Target = (UXGroup)target;
|
|
m_Toggles = serializedObject.FindProperty("m_Toggles");
|
|
m_AllowSwitchOff = serializedObject.FindProperty("m_AllowSwitchOff");
|
|
m_DefaultToggle = serializedObject.FindProperty("m_DefaultToggle");
|
|
|
|
m_ReorderableList = new ReorderableList(serializedObject, m_Toggles, true, true, true, true)
|
|
{
|
|
drawHeaderCallback = DrawHeader,
|
|
drawElementCallback = DrawElement,
|
|
onAddCallback = OnAddList,
|
|
onRemoveCallback = OnRemoveList,
|
|
onChangedCallback = OnChanged
|
|
};
|
|
}
|
|
|
|
public override void OnInspectorGUI()
|
|
{
|
|
serializedObject.Update();
|
|
|
|
EditorGUILayout.PropertyField(m_AllowSwitchOff);
|
|
DrawDefaultToggleSelector();
|
|
DrawTools();
|
|
|
|
bool isPlaying = Application.isPlaying || EditorApplication.isPlaying;
|
|
m_ReorderableList.draggable = !isPlaying;
|
|
m_ReorderableList.displayAdd = !isPlaying;
|
|
m_ReorderableList.displayRemove = !isPlaying;
|
|
|
|
bool previousEnabled = GUI.enabled;
|
|
GUI.enabled = !isPlaying;
|
|
m_ReorderableList.DoLayoutList();
|
|
GUI.enabled = previousEnabled;
|
|
|
|
serializedObject.ApplyModifiedProperties();
|
|
|
|
if (!Application.isPlaying)
|
|
m_Target.EnsureValidState();
|
|
}
|
|
|
|
private void DrawDefaultToggleSelector()
|
|
{
|
|
int toggleCount = CountValidToggles();
|
|
bool requireDefault = !m_AllowSwitchOff.boolValue && toggleCount > 0;
|
|
int optionOffset = requireDefault ? 0 : 1;
|
|
string[] options = new string[toggleCount + optionOffset];
|
|
UXToggle[] toggles = new UXToggle[toggleCount];
|
|
if (!requireDefault)
|
|
options[0] = "<None>";
|
|
|
|
int write = 0;
|
|
for (int i = 0; i < m_Toggles.arraySize; i++)
|
|
{
|
|
UXToggle toggle = m_Toggles.GetArrayElementAtIndex(i).objectReferenceValue as UXToggle;
|
|
if (toggle == null)
|
|
continue;
|
|
|
|
toggles[write] = toggle;
|
|
options[write + optionOffset] = "[" + i + "] " + toggle.name;
|
|
write++;
|
|
}
|
|
|
|
UXToggle currentDefault = m_DefaultToggle.objectReferenceValue as UXToggle;
|
|
int currentIndex = requireDefault ? -1 : 0;
|
|
for (int i = 0; i < toggles.Length; i++)
|
|
{
|
|
if (toggles[i] == currentDefault)
|
|
{
|
|
currentIndex = i + optionOffset;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (requireDefault && currentIndex < 0)
|
|
{
|
|
currentDefault = GetSelectedToggle(toggles);
|
|
if (currentDefault == null)
|
|
currentDefault = toggles[0];
|
|
|
|
m_DefaultToggle.objectReferenceValue = currentDefault;
|
|
for (int i = 0; i < toggles.Length; i++)
|
|
{
|
|
if (toggles[i] == currentDefault)
|
|
{
|
|
currentIndex = i;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
else if (!requireDefault && currentDefault != null && currentIndex == 0)
|
|
{
|
|
m_DefaultToggle.objectReferenceValue = null;
|
|
}
|
|
|
|
EditorGUI.BeginChangeCheck();
|
|
int newIndex = EditorGUILayout.Popup("Default Toggle", currentIndex, options);
|
|
if (EditorGUI.EndChangeCheck())
|
|
{
|
|
UXToggle newDefault = newIndex >= optionOffset ? toggles[newIndex - optionOffset] : null;
|
|
m_DefaultToggle.objectReferenceValue = newDefault;
|
|
serializedObject.ApplyModifiedProperties();
|
|
|
|
if (newDefault != null)
|
|
{
|
|
AssignGroup(newDefault, m_Target);
|
|
}
|
|
}
|
|
}
|
|
|
|
private static UXToggle GetSelectedToggle(UXToggle[] toggles)
|
|
{
|
|
for (int i = 0; i < toggles.Length; i++)
|
|
{
|
|
UXToggle toggle = toggles[i];
|
|
if (toggle != null && toggle.isOn)
|
|
return toggle;
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
private void DrawTools()
|
|
{
|
|
EditorGUILayout.BeginHorizontal();
|
|
if (GUILayout.Button("Collect Children"))
|
|
{
|
|
CollectChildren();
|
|
}
|
|
|
|
if (GUILayout.Button("Clean Nulls"))
|
|
{
|
|
CleanNulls();
|
|
}
|
|
|
|
if (GUILayout.Button("Sort By Hierarchy"))
|
|
{
|
|
SortByHierarchy();
|
|
}
|
|
|
|
EditorGUILayout.EndHorizontal();
|
|
}
|
|
|
|
private void DrawHeader(Rect rect)
|
|
{
|
|
EditorGUI.LabelField(rect, "Toggles", EditorStyles.boldLabel);
|
|
}
|
|
|
|
private void DrawElement(Rect rect, int index, bool isActive, bool isFocused)
|
|
{
|
|
SerializedProperty element = m_Toggles.GetArrayElementAtIndex(index);
|
|
UXToggle oldToggle = element.objectReferenceValue as UXToggle;
|
|
|
|
rect.y += 2;
|
|
Rect fieldRect = new Rect(rect.x, rect.y, rect.width, EditorGUIUtility.singleLineHeight);
|
|
string label = oldToggle != null ? "[" + index + "] " + oldToggle.name : "[" + index + "] Null";
|
|
|
|
bool duplicate = oldToggle != null && HasDuplicate(oldToggle, index);
|
|
bool wrongGroup = oldToggle != null && oldToggle.group != null && oldToggle.group != m_Target;
|
|
if (duplicate || wrongGroup)
|
|
EditorGUI.DrawRect(fieldRect, new Color(1f, 0.55f, 0f, 0.2f));
|
|
|
|
EditorGUI.BeginChangeCheck();
|
|
UXToggle newToggle = EditorGUI.ObjectField(fieldRect, label, oldToggle, typeof(UXToggle), true) as UXToggle;
|
|
if (EditorGUI.EndChangeCheck())
|
|
{
|
|
if (oldToggle != null && oldToggle != newToggle)
|
|
AssignGroup(oldToggle, null);
|
|
|
|
if (newToggle != null && oldToggle != newToggle)
|
|
AssignGroup(newToggle, m_Target);
|
|
|
|
element.objectReferenceValue = newToggle;
|
|
serializedObject.ApplyModifiedProperties();
|
|
m_Target.EnsureValidState();
|
|
}
|
|
}
|
|
|
|
private void OnAddList(ReorderableList list)
|
|
{
|
|
m_Toggles.arraySize++;
|
|
m_Toggles.GetArrayElementAtIndex(m_Toggles.arraySize - 1).objectReferenceValue = null;
|
|
serializedObject.ApplyModifiedProperties();
|
|
}
|
|
|
|
private void OnRemoveList(ReorderableList list)
|
|
{
|
|
if (list.index < 0 || list.index >= m_Toggles.arraySize)
|
|
return;
|
|
|
|
UXToggle oldToggle = m_Toggles.GetArrayElementAtIndex(list.index).objectReferenceValue as UXToggle;
|
|
if (oldToggle != null)
|
|
AssignGroup(oldToggle, null);
|
|
|
|
m_Toggles.DeleteArrayElementAtIndex(list.index);
|
|
serializedObject.ApplyModifiedProperties();
|
|
m_Target.EnsureValidState();
|
|
}
|
|
|
|
private void OnChanged(ReorderableList list)
|
|
{
|
|
serializedObject.ApplyModifiedProperties();
|
|
if (!Application.isPlaying)
|
|
m_Target.EnsureValidState();
|
|
}
|
|
|
|
private void CollectChildren()
|
|
{
|
|
UXToggle[] toggles = m_Target.GetComponentsInChildren<UXToggle>(true);
|
|
m_Toggles.arraySize = toggles.Length;
|
|
for (int i = 0; i < toggles.Length; i++)
|
|
{
|
|
m_Toggles.GetArrayElementAtIndex(i).objectReferenceValue = toggles[i];
|
|
AssignGroup(toggles[i], m_Target);
|
|
}
|
|
|
|
serializedObject.ApplyModifiedProperties();
|
|
m_Target.EnsureValidState();
|
|
EditorUtility.SetDirty(m_Target);
|
|
}
|
|
|
|
private void CleanNulls()
|
|
{
|
|
for (int i = m_Toggles.arraySize - 1; i >= 0; i--)
|
|
{
|
|
if (m_Toggles.GetArrayElementAtIndex(i).objectReferenceValue == null)
|
|
m_Toggles.DeleteArrayElementAtIndex(i);
|
|
}
|
|
|
|
serializedObject.ApplyModifiedProperties();
|
|
m_Target.EnsureValidState();
|
|
EditorUtility.SetDirty(m_Target);
|
|
}
|
|
|
|
private void SortByHierarchy()
|
|
{
|
|
int count = CountValidToggles();
|
|
UXToggle[] toggles = new UXToggle[count];
|
|
int write = 0;
|
|
for (int i = 0; i < m_Toggles.arraySize; i++)
|
|
{
|
|
UXToggle toggle = m_Toggles.GetArrayElementAtIndex(i).objectReferenceValue as UXToggle;
|
|
if (toggle != null)
|
|
{
|
|
toggles[write] = toggle;
|
|
write++;
|
|
}
|
|
}
|
|
|
|
System.Array.Sort(toggles, CompareHierarchyIndex);
|
|
m_Toggles.arraySize = toggles.Length;
|
|
for (int i = 0; i < toggles.Length; i++)
|
|
m_Toggles.GetArrayElementAtIndex(i).objectReferenceValue = toggles[i];
|
|
|
|
serializedObject.ApplyModifiedProperties();
|
|
m_Target.EnsureValidState();
|
|
EditorUtility.SetDirty(m_Target);
|
|
}
|
|
|
|
private int CountValidToggles()
|
|
{
|
|
int count = 0;
|
|
for (int i = 0; i < m_Toggles.arraySize; i++)
|
|
{
|
|
if (m_Toggles.GetArrayElementAtIndex(i).objectReferenceValue != null)
|
|
count++;
|
|
}
|
|
|
|
return count;
|
|
}
|
|
|
|
private bool HasDuplicate(UXToggle toggle, int selfIndex)
|
|
{
|
|
for (int i = 0; i < m_Toggles.arraySize; i++)
|
|
{
|
|
if (i != selfIndex && m_Toggles.GetArrayElementAtIndex(i).objectReferenceValue == toggle)
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
private static int CompareHierarchyIndex(UXToggle left, UXToggle right)
|
|
{
|
|
int leftIndex = left.transform.GetSiblingIndex();
|
|
int rightIndex = right.transform.GetSiblingIndex();
|
|
if (leftIndex < rightIndex)
|
|
return -1;
|
|
|
|
if (leftIndex > rightIndex)
|
|
return 1;
|
|
|
|
return 0;
|
|
}
|
|
|
|
private static void AssignGroup(UXToggle toggle, UXGroup group)
|
|
{
|
|
if (toggle == null)
|
|
return;
|
|
|
|
SerializedObject serializedToggle = new SerializedObject(toggle);
|
|
SerializedProperty groupProperty = serializedToggle.FindProperty("m_Group");
|
|
groupProperty.objectReferenceValue = group;
|
|
serializedToggle.ApplyModifiedProperties();
|
|
toggle.group = group;
|
|
EditorUtility.SetDirty(toggle);
|
|
}
|
|
}
|
|
}
|