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
}
}