First commit for private source control. Older commits available on Github.
This commit is contained in:
@@ -0,0 +1,205 @@
|
||||
using UnityEngine;
|
||||
using UnityEditor;
|
||||
using UnityEditorInternal;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace NaughtyAttributes.Editor
|
||||
{
|
||||
public class ReorderableListPropertyDrawer : SpecialCasePropertyDrawerBase
|
||||
{
|
||||
public static readonly ReorderableListPropertyDrawer Instance = new ReorderableListPropertyDrawer();
|
||||
|
||||
private readonly Dictionary<string, ReorderableList> _reorderableListsByPropertyName = new Dictionary<string, ReorderableList>();
|
||||
|
||||
private GUIStyle _labelStyle;
|
||||
|
||||
private GUIStyle GetLabelStyle()
|
||||
{
|
||||
if (_labelStyle == null)
|
||||
{
|
||||
_labelStyle = new GUIStyle(EditorStyles.boldLabel);
|
||||
_labelStyle.richText = true;
|
||||
}
|
||||
|
||||
return _labelStyle;
|
||||
}
|
||||
|
||||
private string GetPropertyKeyName(SerializedProperty property)
|
||||
{
|
||||
return property.serializedObject.targetObject.GetInstanceID() + "." + property.name;
|
||||
}
|
||||
|
||||
protected override float GetPropertyHeight_Internal(SerializedProperty property)
|
||||
{
|
||||
if (property.isArray)
|
||||
{
|
||||
string key = GetPropertyKeyName(property);
|
||||
|
||||
if (_reorderableListsByPropertyName.TryGetValue(key, out ReorderableList reorderableList) == false)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
return reorderableList.GetHeight();
|
||||
}
|
||||
|
||||
return EditorGUI.GetPropertyHeight(property, true);
|
||||
}
|
||||
|
||||
protected override void OnGUI_Internal(Rect rect, SerializedProperty property, GUIContent label)
|
||||
{
|
||||
if (property.isArray)
|
||||
{
|
||||
string key = GetPropertyKeyName(property);
|
||||
|
||||
ReorderableList reorderableList = null;
|
||||
if (!_reorderableListsByPropertyName.ContainsKey(key))
|
||||
{
|
||||
reorderableList = new ReorderableList(property.serializedObject, property, true, true, true, true)
|
||||
{
|
||||
drawHeaderCallback = (Rect r) =>
|
||||
{
|
||||
EditorGUI.LabelField(r, string.Format("{0}: {1}", label.text, property.arraySize), GetLabelStyle());
|
||||
HandleDragAndDrop(r, reorderableList);
|
||||
},
|
||||
|
||||
drawElementCallback = (Rect r, int index, bool isActive, bool isFocused) =>
|
||||
{
|
||||
SerializedProperty element = property.GetArrayElementAtIndex(index);
|
||||
r.y += 1.0f;
|
||||
r.x += 10.0f;
|
||||
r.width -= 10.0f;
|
||||
|
||||
EditorGUI.PropertyField(new Rect(r.x, r.y, r.width, EditorGUIUtility.singleLineHeight), element, true);
|
||||
},
|
||||
|
||||
elementHeightCallback = (int index) =>
|
||||
{
|
||||
return EditorGUI.GetPropertyHeight(property.GetArrayElementAtIndex(index)) + 4.0f;
|
||||
}
|
||||
};
|
||||
|
||||
_reorderableListsByPropertyName[key] = reorderableList;
|
||||
}
|
||||
|
||||
reorderableList = _reorderableListsByPropertyName[key];
|
||||
|
||||
if (rect == default)
|
||||
{
|
||||
reorderableList.DoLayoutList();
|
||||
}
|
||||
else
|
||||
{
|
||||
reorderableList.DoList(rect);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
string message = typeof(ReorderableListAttribute).Name + " can be used only on arrays or lists";
|
||||
NaughtyEditorGUI.HelpBox_Layout(message, MessageType.Warning, context: property.serializedObject.targetObject);
|
||||
EditorGUILayout.PropertyField(property, true);
|
||||
}
|
||||
}
|
||||
|
||||
public void ClearCache()
|
||||
{
|
||||
_reorderableListsByPropertyName.Clear();
|
||||
}
|
||||
|
||||
private Object GetAssignableObject(Object obj, ReorderableList list)
|
||||
{
|
||||
System.Type listType = PropertyUtility.GetPropertyType(list.serializedProperty);
|
||||
System.Type elementType = ReflectionUtility.GetListElementType(listType);
|
||||
|
||||
if (elementType == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
System.Type objType = obj.GetType();
|
||||
|
||||
if (elementType.IsAssignableFrom(objType))
|
||||
{
|
||||
return obj;
|
||||
}
|
||||
|
||||
if (objType == typeof(GameObject))
|
||||
{
|
||||
if (typeof(Transform).IsAssignableFrom(elementType))
|
||||
{
|
||||
Transform transform = ((GameObject)obj).transform;
|
||||
if (elementType == typeof(RectTransform))
|
||||
{
|
||||
RectTransform rectTransform = transform as RectTransform;
|
||||
return rectTransform;
|
||||
}
|
||||
else
|
||||
{
|
||||
return transform;
|
||||
}
|
||||
}
|
||||
else if (typeof(MonoBehaviour).IsAssignableFrom(elementType))
|
||||
{
|
||||
return ((GameObject)obj).GetComponent(elementType);
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private void HandleDragAndDrop(Rect rect, ReorderableList list)
|
||||
{
|
||||
var currentEvent = Event.current;
|
||||
var usedEvent = false;
|
||||
|
||||
switch (currentEvent.type)
|
||||
{
|
||||
case EventType.DragExited:
|
||||
if (GUI.enabled)
|
||||
{
|
||||
HandleUtility.Repaint();
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case EventType.DragUpdated:
|
||||
case EventType.DragPerform:
|
||||
if (rect.Contains(currentEvent.mousePosition) && GUI.enabled)
|
||||
{
|
||||
// Check each single object, so we can add multiple objects in a single drag.
|
||||
bool didAcceptDrag = false;
|
||||
Object[] references = DragAndDrop.objectReferences;
|
||||
foreach (Object obj in references)
|
||||
{
|
||||
Object assignableObject = GetAssignableObject(obj, list);
|
||||
if (assignableObject != null)
|
||||
{
|
||||
DragAndDrop.visualMode = DragAndDropVisualMode.Copy;
|
||||
if (currentEvent.type == EventType.DragPerform)
|
||||
{
|
||||
list.serializedProperty.arraySize++;
|
||||
int arrayEnd = list.serializedProperty.arraySize - 1;
|
||||
list.serializedProperty.GetArrayElementAtIndex(arrayEnd).objectReferenceValue = assignableObject;
|
||||
didAcceptDrag = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (didAcceptDrag)
|
||||
{
|
||||
GUI.changed = true;
|
||||
DragAndDrop.AcceptDrag();
|
||||
usedEvent = true;
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
if (usedEvent)
|
||||
{
|
||||
currentEvent.Use();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
fileFormatVersion: 2
|
||||
guid: bf36691a6d456564db2fcbfa8726b3f3
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 129996
|
||||
packageName: NaughtyAttributes
|
||||
packageVersion: 2.1.4
|
||||
assetPath: Assets/NaughtyAttributes/Scripts/Editor/PropertyDrawers_SpecialCase/ReorderableListPropertyDrawer.cs
|
||||
uploadId: 480834
|
||||
@@ -0,0 +1,74 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
|
||||
namespace NaughtyAttributes.Editor
|
||||
{
|
||||
public abstract class SpecialCasePropertyDrawerBase
|
||||
{
|
||||
public void OnGUI(Rect rect, SerializedProperty property)
|
||||
{
|
||||
// Check if visible
|
||||
bool visible = PropertyUtility.IsVisible(property);
|
||||
if (!visible)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Validate
|
||||
ValidatorAttribute[] validatorAttributes = PropertyUtility.GetAttributes<ValidatorAttribute>(property);
|
||||
foreach (var validatorAttribute in validatorAttributes)
|
||||
{
|
||||
validatorAttribute.GetValidator().ValidateProperty(property);
|
||||
}
|
||||
|
||||
// Check if enabled and draw
|
||||
EditorGUI.BeginChangeCheck();
|
||||
bool enabled = PropertyUtility.IsEnabled(property);
|
||||
|
||||
using (new EditorGUI.DisabledScope(disabled: !enabled))
|
||||
{
|
||||
OnGUI_Internal(rect, property, PropertyUtility.GetLabel(property));
|
||||
}
|
||||
|
||||
// Call OnValueChanged callbacks
|
||||
if (EditorGUI.EndChangeCheck())
|
||||
{
|
||||
PropertyUtility.CallOnValueChangedCallbacks(property);
|
||||
}
|
||||
}
|
||||
|
||||
public float GetPropertyHeight(SerializedProperty property)
|
||||
{
|
||||
return GetPropertyHeight_Internal(property);
|
||||
}
|
||||
|
||||
protected abstract void OnGUI_Internal(Rect rect, SerializedProperty property, GUIContent label);
|
||||
protected abstract float GetPropertyHeight_Internal(SerializedProperty property);
|
||||
}
|
||||
|
||||
public static class SpecialCaseDrawerAttributeExtensions
|
||||
{
|
||||
private static Dictionary<Type, SpecialCasePropertyDrawerBase> _drawersByAttributeType;
|
||||
|
||||
static SpecialCaseDrawerAttributeExtensions()
|
||||
{
|
||||
_drawersByAttributeType = new Dictionary<Type, SpecialCasePropertyDrawerBase>();
|
||||
_drawersByAttributeType[typeof(ReorderableListAttribute)] = ReorderableListPropertyDrawer.Instance;
|
||||
}
|
||||
|
||||
public static SpecialCasePropertyDrawerBase GetDrawer(this SpecialCaseDrawerAttribute attr)
|
||||
{
|
||||
SpecialCasePropertyDrawerBase drawer;
|
||||
if (_drawersByAttributeType.TryGetValue(attr.GetType(), out drawer))
|
||||
{
|
||||
return drawer;
|
||||
}
|
||||
else
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 771776453ad34b045a41dea54856fa12
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 129996
|
||||
packageName: NaughtyAttributes
|
||||
packageVersion: 2.1.4
|
||||
assetPath: Assets/NaughtyAttributes/Scripts/Editor/PropertyDrawers_SpecialCase/SpecialCasePropertyDrawerBase.cs
|
||||
uploadId: 480834
|
||||
Reference in New Issue
Block a user