// default add button behavior public void DoAddButton(RuntimeReorderableList list) { if (list.RuntimeSerializedProperty != null) { list.RuntimeSerializedProperty.ArraySize += 1; list.index = list.RuntimeSerializedProperty.ArraySize - 1; } else { // this is ugly but there are a lot of cases like null types and default constructors Type elementType = list.list.GetType().GetElementType(); if (elementType == typeof(string)) { list.index = list.list.Add(""); } else if (elementType != null && elementType.GetConstructor(Type.EmptyTypes) == null) { Debug.LogError("Cannot add element. Type " + elementType.ToString() + " has no default constructor. Implement a default constructor or implement your own add behaviour."); } else if (list.list.GetType().GetGenericArguments()[0] != null) { list.index = list.list.Add(Activator.CreateInstance(list.list.GetType().GetGenericArguments()[0])); } else if (elementType != null) { list.index = list.list.Add(Activator.CreateInstance(elementType)); } else { Debug.LogError("Cannot add element of type Null."); } } }
protected virtual void OnRemove(RuntimeReorderableList list, System.Type type) { if (typeof(ScriptableObject).IsAssignableFrom(type)) { // Reference type is not supported! } RuntimeReorderableList.defaultBehaviours.DoRemoveButton(list); }
private void OnRemoveHandler(RuntimeReorderableList list) { System.Type type = null; if (reorderableTypeDict.TryGetValue(list, out type)) { OnRemove(list, type); } }
private void OnAddDropdownHandler(Rect position, RuntimeReorderableList list) { System.Type type = null; if (reorderableTypeDict.TryGetValue(list, out type)) { OnAddDropdown(position, list, type); } }
public void AddProperty(RuntimeSerializedProperty property) { // Check if this property actually belongs to the same direct child if (!property.GetRootPath().Equals(Parent)) { return; } if (runtimeReorderableListDict.ContainsKey(property.PropertyPath)) { return; } RuntimeReorderableList propList = new RuntimeReorderableList( property.RuntimeSerializedObject.SerializedObject, property, draggable: true, displayHeader: false, displayAddButton: true, displayRemoveButton: true) { headerHeight = 5 }; propList.drawElementBackgroundCallback = (Rect position, int index, bool active, bool focused) => { if (DrawBackgroundCallback != null) { Rect backgroundRect = new Rect(position); if (index <= 0) { backgroundRect.yMin -= 8; } if (index >= propList.count - 1) { backgroundRect.yMax += 3; } EditorGUI.DrawRect(backgroundRect, DrawBackgroundCallback(active, focused)); } else { propList.drawElementBackgroundCallback = null; } }; propList.drawElementCallback = (Rect position, int index, bool active, bool focused) => { var iterProp = property.GetArrayElementAtIndex(index); var elementName = iterProp.DisplayName; if (ElementNameCallback != null) { elementName = ElementNameCallback(index); } RuntimeEasyGUI.PropertyField(position, iterProp, new GUIContent(elementName), ElementAttributes); }; propList.elementHeightCallback = index => ElementHeightCallback(property, index); runtimeReorderableListDict.Add(property.PropertyPath, propList); }
protected virtual void OnAddDropdown(Rect position, RuntimeReorderableList list, System.Type type) { GenericMenu popupMenu = new GenericMenu(); Dictionary <ContextMenuAttribute, System.Type> dropdownTypes = null; if (!dropdownTypeDict.TryGetValue(type, out dropdownTypes)) { dropdownTypes = new Dictionary <ContextMenuAttribute, System.Type>(); foreach (var t in EasyEditor.Types.Where(t => type.IsAssignableFrom(t))) { if (t.HasAttribute <ContextMenuAttribute>()) { dropdownTypes.Add(t.AllAttributes <ContextMenuAttribute>().FirstOrDefault(), t); } else { dropdownTypes.Add(new ContextMenuAttribute(t.Name, false, int.MaxValue), t); } } dropdownTypes = dropdownTypes.OrderBy(i => i.Key.Priority).ToDictionary(kvp => kvp.Key, kvp => kvp.Value); } if (dropdownTypes.Count > 0) { foreach (var kvp in dropdownTypes) { var content = new GUIContent(kvp.Key.MenuItem); var index = list.RuntimeSerializedProperty.ArraySize; if (kvp.Value == typeof(GameObject) || kvp.Value.IsSubclassOf(typeof(Component))) { popupMenu.AddDisabledItem(content); } else if (kvp.Value.IsSubclassOf(typeof(ScriptableObject))) { // Reference type is not supported! } else { popupMenu.AddItem(content, false, () => { var obj = System.Activator.CreateInstance(kvp.Value); list.RuntimeSerializedProperty.ArraySize++; list.index = index; list.RuntimeSerializedProperty.GetArrayElementAtIndex(index).StringValue = RuntimeObject.ToJson(kvp.Value.ToString(), JsonUtility.ToJson(obj)); list.RuntimeSerializedProperty.RuntimeSerializedObject.ApplyModifiedProperties(); }); } } } popupMenu.ShowAsContext(); }
// default remove button behavior public void DoRemoveButton(RuntimeReorderableList list) { if (list.RuntimeSerializedProperty != null) { list.RuntimeSerializedProperty.DeleteArrayElementAtIndex(list.index); if (list.index >= list.RuntimeSerializedProperty.ArraySize - 1) { list.index = list.RuntimeSerializedProperty.ArraySize - 1; } } else { list.list.RemoveAt(list.index); if (list.index >= list.list.Count - 1) { list.index = list.list.Count - 1; } } }
// draw the default footer public void DrawFooter(Rect rect, RuntimeReorderableList list) { float rightEdge = rect.xMax; float leftEdge = rightEdge - 8f; if (list.displayAdd) { leftEdge -= 25; } if (list.displayRemove) { leftEdge -= 25; } rect = new Rect(leftEdge, rect.y, rightEdge - leftEdge, rect.height); Rect addRect = new Rect(leftEdge + 4, rect.y - 3, 25, 13); Rect removeRect = new Rect(rightEdge - 29, rect.y - 3, 25, 13); if (Event.current.type == EventType.Repaint) { footerBackground.Draw(rect, false, false, false, false); } if (list.displayAdd) { using (new EditorGUI.DisabledScope( list.onCanAddCallback != null && !list.onCanAddCallback(list))) { if (GUI.Button(addRect, list.onAddDropdownCallback != null ? iconToolbarPlusMore : iconToolbarPlus, preButton)) { if (list.onAddDropdownCallback != null) { list.onAddDropdownCallback(addRect, list); } else if (list.onAddCallback != null) { list.onAddCallback(list); } else { DoAddButton(list); } if (list.onChangedCallback != null) { list.onChangedCallback(list); } } } } if (list.displayRemove) { using (new EditorGUI.DisabledScope( list.index < 0 || list.index >= list.count || (list.onCanRemoveCallback != null && !list.onCanRemoveCallback(list)))) { if (GUI.Button(removeRect, iconToolbarMinus, preButton)) { if (list.onRemoveCallback == null) { DoRemoveButton(list); } else { list.onRemoveCallback(list); } if (list.onChangedCallback != null) { list.onChangedCallback(list); } } } } }