using UnityEngine; using UnityEditor; using UnityEditorInternal; namespace YKMoonEditor { /// /// 描绘可拖拽List /// public class UReorderableList { private ReorderableList m_ReorderableList; public SerializedObject serializedObject { get; private set; } public SerializedProperty elements { get; private set; } public bool showResize = false; private float elementHeight; private ReorderableList.ElementCallbackDelegate drawElementCallback; public UReorderableList(SerializedObject serializedObject, SerializedProperty elements, float elementHeight, ReorderableList.ElementCallbackDelegate drawElementCallback = null) { this.serializedObject = serializedObject; this.elements = elements; this.elementHeight = elementHeight; if (drawElementCallback == null) { this.drawElementCallback = DrawElementWithIndex; } else { this.drawElementCallback = drawElementCallback; } m_ReorderableList = new ReorderableList(serializedObject, elements, true, true, true, true); m_ReorderableList.drawHeaderCallback = this.DrawEventHeader; m_ReorderableList.drawElementCallback = this.DrawEventListener; m_ReorderableList.drawFooterCallback = this.FooterCallback; } private void UpdateExpanded() { if(elements.isExpanded) { m_ReorderableList.displayAdd = true; m_ReorderableList.displayRemove = true; m_ReorderableList.elementHeight = elementHeight; m_ReorderableList.footerHeight = 13f; } else { m_ReorderableList.displayAdd = false; m_ReorderableList.displayRemove = false; m_ReorderableList.elementHeight = 0f; m_ReorderableList.footerHeight = 0; } } public void DoLayoutList() { UpdateExpanded(); m_ReorderableList.DoLayoutList(); } public void DoList(Rect rect) { UpdateExpanded(); m_ReorderableList.DoList(rect); } protected virtual void DrawEventHeader(Rect headerRect) { float offsetWidth = 10; headerRect.xMin += offsetWidth; { Rect rect = headerRect; GUIContent content = new GUIContent(string.Format("{0} ({1})", elements.name, m_ReorderableList.count), elements.tooltip); elements.isExpanded = EditorGUI.BeginFoldoutHeaderGroup(rect, elements.isExpanded, content); } EditorGUI.EndFoldoutHeaderGroup(); } /// /// 描绘子物体 /// private void DrawEventListener(Rect rect, int index, bool isactive, bool isfocused) { if(!elements.isExpanded) { return; } drawElementCallback?.Invoke(rect, index, isactive, isfocused); } private void DoResize(ReorderableList list, int size) { size = Mathf.Max(0, size); if (list.serializedProperty != null) { list.serializedProperty.arraySize = size; if(list.index >= (list.serializedProperty.arraySize - 1)) { list.index = list.serializedProperty.arraySize - 1; } } else { if(size < list.list.Count) { while(size < list.list.Count) { list.list.RemoveAt(list.list.Count - 1); } }else if(size > list.list.Count) { while(size > list.list.Count) { ReorderableList.defaultBehaviours.DoAddButton(list); } } if(list.index >= (list.list.Count - 1)) { list.index = list.list.Count - 1; } } } /// /// 描绘下边 /// /// private void FooterCallback(Rect rect) { if (!elements.isExpanded) { return; } var list = m_ReorderableList; float xMax = rect.xMax; float x = rect.xMax - 8f; float buttonSize = 25f; if(showResize) { x -= buttonSize; } if(list.displayAdd) { x -= buttonSize; } if(list.displayRemove) { x -= buttonSize; } rect = new Rect(x, rect.y, xMax - x, rect.height); if(Event.current.type == UnityEngine.EventType.Repaint) { ReorderableList.defaultBehaviours.footerBackground.Draw(rect, false, false, false, false); } Rect pos = new Rect(x + 4f, rect.y - 3f, 25f, 13f); //resize if (showResize) { pos.height = 16f; int newCount = EditorGUI.IntField(pos, list.count); if (newCount != list.count) { DoResize(list, newCount); if(list.onChangedCallback != null) { list.onChangedCallback(list); } } pos.x += buttonSize; } //addButton if(list.displayAdd) { pos.width = 25f; pos.height = 13f; using(new EditorGUI.DisabledScope((list.onCanAddCallback != null) && !list.onCanAddCallback(list))) { if(GUI.Button(pos, (list.onAddDropdownCallback == null) ? ReorderableList.defaultBehaviours.iconToolbarPlus : ReorderableList.defaultBehaviours.iconToolbarPlusMore, ReorderableList.defaultBehaviours.preButton)) { if(list.onAddDropdownCallback != null) { list.onAddDropdownCallback(pos, list); } else if(list.onAddCallback != null) { list.onAddCallback(list); } else { ReorderableList.defaultBehaviours.DoAddButton(list); } if(list.onChangedCallback != null) { list.onChangedCallback(list); } } } pos.x += buttonSize; } //removeButton if(list.displayRemove) { pos.width = 25f; pos.height = 13f; using(new EditorGUI.DisabledScope(((list.index < 0) || (list.index >= list.count)) || ((list.onCanRemoveCallback != null) && !list.onCanRemoveCallback(list)))) { if(GUI.Button(pos, ReorderableList.defaultBehaviours.iconToolbarMinus, ReorderableList.defaultBehaviours.preButton)) { if(list.onRemoveCallback == null) { ReorderableList.defaultBehaviours.DoRemoveButton(list); } else { list.onRemoveCallback(list); } if(list.onChangedCallback != null) { list.onChangedCallback(list); } } } pos.x += buttonSize; } } #region DefaultDrawer public void DrawElementWithIndex(Rect drawRectInput, int index, bool isactive, bool isfocused) { var elementProperty = m_ReorderableList.serializedProperty.GetArrayElementAtIndex(index); drawRectInput.xMax -= 32; Rect drawRect = drawRectInput; //Index { var rect = drawRect; rect.width = 30; GUI.Label(rect, index.ToString()); drawRect.x += rect.width; } drawRect.yMin += 2; drawRect.yMax -= 2; EditorGUI.PropertyField(drawRect, elementProperty, GUIContent.none); } #endregion } }