diff --git a/Assets/Fungus/Scripts/Editor/HierarchyIcons.cs b/Assets/Fungus/Scripts/Editor/HierarchyIcons.cs index 1c681464..7e6c59c4 100644 --- a/Assets/Fungus/Scripts/Editor/HierarchyIcons.cs +++ b/Assets/Fungus/Scripts/Editor/HierarchyIcons.cs @@ -31,7 +31,11 @@ namespace Fungus { initalHierarchyCheckFlag = true; EditorApplication.hierarchyWindowItemOnGUI += HierarchyIconCallback; +#if UNITY_2018_1_OR_NEWER EditorApplication.hierarchyChanged += HierarchyChanged; +#else + EditorApplication.hierarchyWindowChanged += HierarchyChanged; +#endif } //track all gameobjectIds that have flowcharts on them diff --git a/Assets/Fungus/Thirdparty/Reorderable List Field/Demo.meta b/Assets/Fungus/Thirdparty/Reorderable List Field/Demo.meta new file mode 100644 index 00000000..bc648b7f --- /dev/null +++ b/Assets/Fungus/Thirdparty/Reorderable List Field/Demo.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: a747a40b0f1ab6f48b28b29fdb77f2ed +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Fungus/Thirdparty/Reorderable List Field/Demo/DemoBehaviour.cs b/Assets/Fungus/Thirdparty/Reorderable List Field/Demo/DemoBehaviour.cs new file mode 100644 index 00000000..7627e3d7 --- /dev/null +++ b/Assets/Fungus/Thirdparty/Reorderable List Field/Demo/DemoBehaviour.cs @@ -0,0 +1,12 @@ +// Copyright (c) Rotorz Limited. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root. + +using System.Collections.Generic; +using UnityEngine; + +public class DemoBehaviour : MonoBehaviour { + + public List wishlist = new List(); + public List points = new List(); + +} \ No newline at end of file diff --git a/Assets/Fungus/Thirdparty/Reorderable List Field/Demo/DemoBehaviour.cs.meta b/Assets/Fungus/Thirdparty/Reorderable List Field/Demo/DemoBehaviour.cs.meta new file mode 100644 index 00000000..07bc0810 --- /dev/null +++ b/Assets/Fungus/Thirdparty/Reorderable List Field/Demo/DemoBehaviour.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: acf5477b21448904ebe3636dcb6a0276 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Fungus/Thirdparty/Reorderable List Field/Demo/DemoBehaviourUnityScript.js b/Assets/Fungus/Thirdparty/Reorderable List Field/Demo/DemoBehaviourUnityScript.js new file mode 100644 index 00000000..eb70a9c4 --- /dev/null +++ b/Assets/Fungus/Thirdparty/Reorderable List Field/Demo/DemoBehaviourUnityScript.js @@ -0,0 +1,8 @@ +// Copyright (c) Rotorz Limited. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root. +#pragma strict + +import System.Collections.Generic; + +var wishlist:List. = new List.(); +var points:List. = new List.(); diff --git a/Assets/Fungus/Thirdparty/Reorderable List Field/Demo/DemoBehaviourUnityScript.js.meta b/Assets/Fungus/Thirdparty/Reorderable List Field/Demo/DemoBehaviourUnityScript.js.meta new file mode 100644 index 00000000..24f33963 --- /dev/null +++ b/Assets/Fungus/Thirdparty/Reorderable List Field/Demo/DemoBehaviourUnityScript.js.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 253f52cce58987b4e8f2108722555925 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Fungus/Thirdparty/Reorderable List Field/Demo/Editor.meta b/Assets/Fungus/Thirdparty/Reorderable List Field/Demo/Editor.meta new file mode 100644 index 00000000..51fb2bd1 --- /dev/null +++ b/Assets/Fungus/Thirdparty/Reorderable List Field/Demo/Editor.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: bd53be4000846a648b766b6c79bf6bbd +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Fungus/Thirdparty/Reorderable List Field/Demo/Editor/DemoBehaviourEditor.cs b/Assets/Fungus/Thirdparty/Reorderable List Field/Demo/Editor/DemoBehaviourEditor.cs new file mode 100644 index 00000000..f4df2802 --- /dev/null +++ b/Assets/Fungus/Thirdparty/Reorderable List Field/Demo/Editor/DemoBehaviourEditor.cs @@ -0,0 +1,30 @@ +// Copyright (c) Rotorz Limited. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root. + +using Rotorz.ReorderableList; +using UnityEditor; + +[CustomEditor(typeof(DemoBehaviour))] +public class DemoBehaviourEditor : Editor { + + private SerializedProperty _wishlistProperty; + private SerializedProperty _pointsProperty; + + private void OnEnable() { + _wishlistProperty = serializedObject.FindProperty("wishlist"); + _pointsProperty = serializedObject.FindProperty("points"); + } + + public override void OnInspectorGUI() { + serializedObject.Update(); + + ReorderableListGUI.Title("Wishlist"); + ReorderableListGUI.ListField(_wishlistProperty); + + ReorderableListGUI.Title("Points"); + ReorderableListGUI.ListField(_pointsProperty); + + serializedObject.ApplyModifiedProperties(); + } + +} \ No newline at end of file diff --git a/Assets/Fungus/Thirdparty/Reorderable List Field/Demo/Editor/DemoBehaviourEditor.cs.meta b/Assets/Fungus/Thirdparty/Reorderable List Field/Demo/Editor/DemoBehaviourEditor.cs.meta new file mode 100644 index 00000000..825b6601 --- /dev/null +++ b/Assets/Fungus/Thirdparty/Reorderable List Field/Demo/Editor/DemoBehaviourEditor.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 036558d96cb3f6a418344bd5fb29215e +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Fungus/Thirdparty/Reorderable List Field/Demo/Editor/MultiListEditorWindowDemo.cs b/Assets/Fungus/Thirdparty/Reorderable List Field/Demo/Editor/MultiListEditorWindowDemo.cs new file mode 100644 index 00000000..9afb1903 --- /dev/null +++ b/Assets/Fungus/Thirdparty/Reorderable List Field/Demo/Editor/MultiListEditorWindowDemo.cs @@ -0,0 +1,184 @@ +using UnityEngine; +using UnityEditor; +using Rotorz.ReorderableList; +using System.Collections.Generic; + +public class MultiListEditorWindowDemo : EditorWindow { + + [MenuItem("Window/Multi List Demo (C#)")] + private static void ShowWindow() { + GetWindow("Multi List"); + } + + private class ExampleListAdaptor : GenericListAdaptor, IReorderableListDropTarget { + + private const float MouseDragThresholdInPixels = 0.6f; + + // Static reference to the list adaptor of the selected item. + private static ExampleListAdaptor s_SelectedList; + // Static reference limits selection to one item in one list. + private static string s_SelectedItem; + // Position in GUI where mouse button was anchored before dragging occurred. + private static Vector2 s_MouseDownPosition; + + // Holds data representing the item that is being dragged. + private class DraggedItem { + + public static readonly string TypeName = typeof(DraggedItem).FullName; + + public readonly ExampleListAdaptor SourceListAdaptor; + public readonly int Index; + public readonly string ShoppingItem; + + public DraggedItem(ExampleListAdaptor sourceList, int index, string shoppingItem) { + SourceListAdaptor = sourceList; + Index = index; + ShoppingItem = shoppingItem; + } + + } + + public ExampleListAdaptor(IList list) : base(list, null, 16f) { + } + + public override void DrawItemBackground(Rect position, int index) { + if (this == s_SelectedList && List[index] == s_SelectedItem) { + Color restoreColor = GUI.color; + GUI.color = ReorderableListStyles.SelectionBackgroundColor; + GUI.DrawTexture(position, EditorGUIUtility.whiteTexture); + GUI.color = restoreColor; + } + } + + public override void DrawItem(Rect position, int index) { + string shoppingItem = List[index]; + + int controlID = GUIUtility.GetControlID(FocusType.Passive); + + switch (Event.current.GetTypeForControl(controlID)) { + case EventType.MouseDown: + Rect totalItemPosition = ReorderableListGUI.CurrentItemTotalPosition; + if (totalItemPosition.Contains(Event.current.mousePosition)) { + // Select this list item. + s_SelectedList = this; + s_SelectedItem = shoppingItem; + } + + // Calculate rectangle of draggable area of the list item. + // This example excludes the grab handle at the left. + Rect draggableRect = totalItemPosition; + draggableRect.x = position.x; + draggableRect.width = position.width; + + if (Event.current.button == 0 && draggableRect.Contains(Event.current.mousePosition)) { + // Select this list item. + s_SelectedList = this; + s_SelectedItem = shoppingItem; + + // Lock onto this control whilst left mouse button is held so + // that we can start a drag-and-drop operation when user drags. + GUIUtility.hotControl = controlID; + s_MouseDownPosition = Event.current.mousePosition; + Event.current.Use(); + } + break; + + case EventType.MouseDrag: + if (GUIUtility.hotControl == controlID) { + GUIUtility.hotControl = 0; + + // Begin drag-and-drop operation when the user drags the mouse + // pointer across the threshold. This threshold helps to avoid + // inadvertently starting a drag-and-drop operation. + if (Vector2.Distance(s_MouseDownPosition, Event.current.mousePosition) >= MouseDragThresholdInPixels) { + // Prepare data that will represent the item. + var item = new DraggedItem(this, index, shoppingItem); + + // Start drag-and-drop operation with the Unity API. + DragAndDrop.PrepareStartDrag(); + // Need to reset `objectReferences` and `paths` because `PrepareStartDrag` + // doesn't seem to reset these (at least, in Unity 4.x). + DragAndDrop.objectReferences = new Object[0]; + DragAndDrop.paths = new string[0]; + + DragAndDrop.SetGenericData(DraggedItem.TypeName, item); + DragAndDrop.StartDrag(shoppingItem); + } + + // Use this event so that the host window gets repainted with + // each mouse movement. + Event.current.Use(); + } + break; + + case EventType.Repaint: + EditorStyles.label.Draw(position, shoppingItem, false, false, false, false); + break; + } + } + + public bool CanDropInsert(int insertionIndex) { + if (!ReorderableListControl.CurrentListPosition.Contains(Event.current.mousePosition)) + return false; + + // Drop insertion is possible if the current drag-and-drop operation contains + // the supported type of custom data. + return DragAndDrop.GetGenericData(DraggedItem.TypeName) is DraggedItem; + } + + public void ProcessDropInsertion(int insertionIndex) { + if (Event.current.type == EventType.DragPerform) { + var draggedItem = DragAndDrop.GetGenericData(DraggedItem.TypeName) as DraggedItem; + + // Are we just reordering within the same list? + if (draggedItem.SourceListAdaptor == this) { + Move(draggedItem.Index, insertionIndex); + } + else { + // Nope, we are moving the item! + List.Insert(insertionIndex, draggedItem.ShoppingItem); + draggedItem.SourceListAdaptor.Remove(draggedItem.Index); + + // Ensure that the item remains selected at its new location! + s_SelectedList = this; + } + } + } + + } + + private List _shoppingList; + private ExampleListAdaptor _shoppingListAdaptor; + + private List _purchaseList; + private ExampleListAdaptor _purchaseListAdaptor; + + private void OnEnable() { + _shoppingList = new List() { "Bread", "Carrots", "Beans", "Steak", "Coffee", "Fries" }; + _shoppingListAdaptor = new ExampleListAdaptor(_shoppingList); + + _purchaseList = new List() { "Cheese", "Crackers" }; + _purchaseListAdaptor = new ExampleListAdaptor(_purchaseList); + } + + private void OnGUI() { + GUILayout.BeginHorizontal(); + + var columnWidth = GUILayout.Width(position.width / 2f - 6); + + // Draw list control on left side of the window. + GUILayout.BeginVertical(columnWidth); + ReorderableListGUI.Title("Shopping List"); + ReorderableListGUI.ListField(_shoppingListAdaptor); + GUILayout.EndVertical(); + + // Draw list control on right side of the window. + GUILayout.BeginVertical(columnWidth); + ReorderableListGUI.Title("Purchase List"); + ReorderableListGUI.ListField(_purchaseListAdaptor); + GUILayout.EndVertical(); + + GUILayout.EndHorizontal(); + } + +} diff --git a/Assets/Fungus/Thirdparty/Reorderable List Field/Demo/Editor/MultiListEditorWindowDemo.cs.meta b/Assets/Fungus/Thirdparty/Reorderable List Field/Demo/Editor/MultiListEditorWindowDemo.cs.meta new file mode 100644 index 00000000..2212a369 --- /dev/null +++ b/Assets/Fungus/Thirdparty/Reorderable List Field/Demo/Editor/MultiListEditorWindowDemo.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: a42361912a901e04bbe1405e84b81b8d +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Fungus/Thirdparty/Reorderable List Field/Demo/Editor/ReorderableListDemo.cs b/Assets/Fungus/Thirdparty/Reorderable List Field/Demo/Editor/ReorderableListDemo.cs new file mode 100644 index 00000000..1485b67b --- /dev/null +++ b/Assets/Fungus/Thirdparty/Reorderable List Field/Demo/Editor/ReorderableListDemo.cs @@ -0,0 +1,79 @@ +// Copyright (c) Rotorz Limited. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root. + +using Rotorz.ReorderableList; +using System.Collections.Generic; +using UnityEditor; +using UnityEngine; + +public class ReorderableListDemo : EditorWindow { + + [MenuItem("Window/List Demo (C#)")] + static void ShowWindow() { + GetWindow("List Demo"); + } + + public List shoppingList; + public List purchaseList; + + private void OnEnable() { + shoppingList = new List(); + shoppingList.Add("Bread"); + shoppingList.Add("Carrots"); + shoppingList.Add("Beans"); + shoppingList.Add("Steak"); + shoppingList.Add("Coffee"); + shoppingList.Add("Fries"); + + purchaseList = new List(); + purchaseList.Add("Cheese"); + purchaseList.Add("Crackers"); + } + + private Vector2 _scrollPosition; + + private void OnGUI() { + _scrollPosition = GUILayout.BeginScrollView(_scrollPosition); + + ReorderableListGUI.Title("Shopping List"); + ReorderableListGUI.ListField(shoppingList, PendingItemDrawer, DrawEmpty); + + ReorderableListGUI.Title("Purchased Items"); + ReorderableListGUI.ListField(purchaseList, PurchasedItemDrawer, DrawEmpty, ReorderableListFlags.HideAddButton | ReorderableListFlags.DisableReordering); + + GUILayout.EndScrollView(); + } + + private string PendingItemDrawer(Rect position, string itemValue) { + // Text fields do not like null values! + if (itemValue == null) + itemValue = ""; + + position.width -= 50; + itemValue = EditorGUI.TextField(position, itemValue); + + position.x = position.xMax + 5; + position.width = 45; + if (GUI.Button(position, "Info")) { + } + + return itemValue; + } + + private string PurchasedItemDrawer(Rect position, string itemValue) { + position.width -= 50; + GUI.Label(position, itemValue); + + position.x = position.xMax + 5; + position.width = 45; + if (GUI.Button(position, "Info")) { + } + + return itemValue; + } + + private void DrawEmpty() { + GUILayout.Label("No items in list.", EditorStyles.miniLabel); + } + +} \ No newline at end of file diff --git a/Assets/Fungus/Thirdparty/Reorderable List Field/Demo/Editor/ReorderableListDemo.cs.meta b/Assets/Fungus/Thirdparty/Reorderable List Field/Demo/Editor/ReorderableListDemo.cs.meta new file mode 100644 index 00000000..198cb753 --- /dev/null +++ b/Assets/Fungus/Thirdparty/Reorderable List Field/Demo/Editor/ReorderableListDemo.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: a8187beba641e99409b4648cca1becd3 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Fungus/Thirdparty/Reorderable List Field/Editor.meta b/Assets/Fungus/Thirdparty/Reorderable List Field/Editor.meta index a70a23a1..2245fc48 100644 --- a/Assets/Fungus/Thirdparty/Reorderable List Field/Editor.meta +++ b/Assets/Fungus/Thirdparty/Reorderable List Field/Editor.meta @@ -1,9 +1,8 @@ fileFormatVersion: 2 guid: 1351e3cf05fcef04cbafc172b277cd32 folderAsset: yes -timeCreated: 1434110041 -licenseType: Free DefaultImporter: + externalObjects: {} userData: assetBundleName: assetBundleVariant: diff --git a/Assets/Fungus/Thirdparty/Reorderable List Field/Editor/Editor.ReorderableList.dll b/Assets/Fungus/Thirdparty/Reorderable List Field/Editor/Editor.ReorderableList.dll deleted file mode 100755 index 4c02b9dc..00000000 Binary files a/Assets/Fungus/Thirdparty/Reorderable List Field/Editor/Editor.ReorderableList.dll and /dev/null differ diff --git a/Assets/Fungus/Thirdparty/Reorderable List Field/Editor/Editor.ReorderableList.dll.meta b/Assets/Fungus/Thirdparty/Reorderable List Field/Editor/Editor.ReorderableList.dll.meta deleted file mode 100644 index 7ce66fc7..00000000 --- a/Assets/Fungus/Thirdparty/Reorderable List Field/Editor/Editor.ReorderableList.dll.meta +++ /dev/null @@ -1,22 +0,0 @@ -fileFormatVersion: 2 -guid: 21d076cb9a4ec214a8cb820e69657bc3 -PluginImporter: - serializedVersion: 1 - iconMap: {} - executionOrder: {} - isPreloaded: 0 - platformData: - Any: - enabled: 0 - settings: {} - Editor: - enabled: 1 - settings: - DefaultValueInitialized: true - WindowsStoreApps: - enabled: 0 - settings: - CPU: AnyCPU - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/Fungus/Thirdparty/Reorderable List Field/Editor/Editor.ReorderableList.xml b/Assets/Fungus/Thirdparty/Reorderable List Field/Editor/Editor.ReorderableList.xml deleted file mode 100755 index d299d67d..00000000 --- a/Assets/Fungus/Thirdparty/Reorderable List Field/Editor/Editor.ReorderableList.xml +++ /dev/null @@ -1,1811 +0,0 @@ - - - - Editor.ReorderableList - - - - - Arguments which are passed to . - - - - - Initializes a new instance of . - - Reorderable list adaptor. - Position of the add menu button. - - - - Gets adaptor to reorderable list container. - - - - - Gets position of the add menu button. - - - - - An event handler which is invoked when the "Add Menu" button is clicked. - - Object which raised event. - Event arguments. - - - - Factory methods that create - instances that can then be used to build element adder menus. - - - - - Gets a to build an element - adder menu for a context object of the type . - - Type of the context object that elements can be added to. - - A new instance. - - - - - Gets a to build an element - adder menu for a context object of the type . - - Contract type of addable elements. - Type of the context object that elements can be added to. - - A new instance. - - - - - Annotate implementations with a - to associate it with the contract - type of addable elements. - - - - - Initializes a new instance of the class. - - Contract type of addable elements. - - - - Gets the contract type of addable elements. - - - - - Provides meta information which is useful when creating new implementations of - the interface. - - - - - Gets an array of all the concrete element types that implement the specified - . - - Contract type of addable elements. - - An array of zero or more concrete element types. - - - If is null. - - - - - Gets a filtered array of the concrete element types that implement the - specified . - - Contract type of addable elements. - An array of zero or more filters. - - An array of zero or more concrete element types. - - - If is null. - - - - - Gets an array of instances - that are associated with the specified . - - Contract type of addable elements. - Type of the context object that elements can be added to. - - An array containing zero or more instances. - - - If is null. - - - - - Gets an array of the types - that are associated with the specified . - - Contract type of addable elements. - Type of the context object that elements can be added to. - - An array containing zero or more . - - - If is null. - - - - - Reorderable list adaptor for generic list. - - Type of list element. - - - - Initializes a new instance of . - - The list which can be reordered. - Callback to draw list item. - Height of list item in pixels. - - - - Add new element at end of list. - - - - - Occurs before any list items are drawn. - - - - - Determines whether an item can be reordered by dragging mouse. - - Zero-based index for list element. - - A value of true if item can be dragged; otherwise false. - - - - - Determines whether an item can be removed from list. - - Zero-based index for list element. - - A value of true if item can be removed; otherwise false. - - - - - Clear all elements from list. - - - - - Gets count of elements in list. - - - - - Draws main interface for a list item. - - Position in GUI. - Zero-based index of array element. - - - - Draws background of a list item. - - Total position of list element in GUI. - Zero-based index of array element. - - - - Duplicate existing element. - - Zero-based index of list element. - - - - Occurs after all list items have been drawn. - - - - - Fixed height of each list item. - - - - - Gets height of list item in pixels. - - Zero-based index of array element. - - Measurement in pixels. - - - - - Insert new element at specified index. - - Zero-based index for list element. - - - - Gets element from list. - - Zero-based index of element. - - The element. - - - - - Gets the underlying list data structure. - - - - - Move element from source index to destination index. - - Zero-based index of source element. - Zero-based index of destination element. - - - - Remove element at specified index. - - Zero-based index of list element. - - - - Interface for an object which adds elements to a context object of the type - . - - Type of the context object that elements can be added to. - - - - Adds an element of the specified to the associated - context object. - - Type of element to add. - - The new element. - - - - - Determines whether a new element of the specified can - be added to the associated context object. - - Type of element to add. - - A value of true if an element of the specified type can be added; - otherwise, a value of false. - - - - - Gets the context object. - - - - - Interface for a menu interface. - - - - - Displays the drop-down menu inside an editor GUI. - - Position of menu button in the GUI. - - - - Gets a value indicating whether the menu contains any items. - - - - - Interface for building an . - - Type of the context object that elements can be added to. - - - - Adds a custom command to the menu. - - The custom command. - - If is null. - - - - - Adds a filter function which determines whether types can be included or - whether they need to be excluded. - - Filter function. - - If is null. - - - - - Builds and returns a new instance. - - - A new instance each time the method is invoked. - - - - - Sets contract type of the elements that can be included in the . - Only non-abstract class types that are assignable from the - will be included in the built menu. - - Contract type of addable elements. - - - - Set the implementation which is used - when adding new elements to the context object. - - Element adder. - - - - Set the function that formats the display of type names in the user interface. - - Function that formats display name of type; or null. - - - - Interface for a menu command that can be included in an - either by annotating an implementation of the - interface with or directly by - calling . - - Type of the context object that elements can be added to. - - - - Determines whether the command can be executed. - - The associated element adder provides access to - the instance. - - A value of true if the command can execute; otherwise, false. - - - - - Gets the content of the menu command. - - - - - Executes the command. - - The associated element adder provides access to - the instance. - - - - Adaptor allowing reorderable list control to interface with list data. - - - - - Add new element at end of list. - - - - - Occurs before any list items are drawn. - - - - - Determines whether an item can be reordered by dragging mouse. - - Zero-based index for list element. - - A value of true if item can be dragged; otherwise false. - - - - - Determines whether an item can be removed from list. - - Zero-based index for list element. - - A value of true if item can be removed; otherwise false. - - - - - Clear all elements from list. - - - - - Gets count of elements in list. - - - - - Draws main interface for a list item. - - Position in GUI. - Zero-based index of array element. - - - - Draws background of a list item. - - Total position of list element in GUI. - Zero-based index of array element. - - - - Duplicate existing element. - - Zero-based index of list element. - - - - Occurs after all list items have been drawn. - - - - - Gets height of list item in pixels. - - Zero-based index of array element. - - Measurement in pixels. - - - - - Insert new element at specified index. - - Zero-based index for list element. - - - - Move element from source index to destination index. - - Zero-based index of source element. - Zero-based index of destination element. - - - - Remove element at specified index. - - Zero-based index of list element. - - - - Can be implemented along with when drop - insertion or ordering is desired. - - - - - Determines whether an item is being dragged and that it can be inserted - or moved by dropping somewhere into the reorderable list control. - - Zero-based index of insertion. - - A value of true if item can be dropped; otherwise false. - - - - - Processes the current drop insertion operation when - returns a value of true to process, accept or cancel. - - Zero-based index of insertion. - - - - Arguments which are passed to . - - - - - Initializes a new instance of . - - Reorderable list adaptor. - Zero-based index of item. - Indicates if inserted item was duplicated from another item. - - - - Gets adaptor to reorderable list container which contains element. - - - - - Gets zero-based index of item which was inserted. - - - - - Indicates if inserted item was duplicated from another item. - - - - - An event handler which is invoked after new list item is inserted. - - Object which raised event. - Event arguments. - - - - Arguments which are passed to . - - - - - Initializes a new instance of . - - Reorderable list adaptor. - Old zero-based index of item. - New zero-based index of item. - - - - Gets adaptor to reorderable list container which contains element. - - - - - Gets new zero-based index of the item which was moved. - - - - - Gets old zero-based index of the item which was moved. - - - - - An event handler which is invoked after a list item is moved. - - Object which raised event. - Event arguments. - - - - Arguments which are passed to . - - - - - Initializes a new instance of . - - Reorderable list adaptor. - Zero-based index of item. - Xero-based index of item destination. - - - - Gets adaptor to reorderable list container which contains element. - - - - - Gets the new candidate zero-based index for the item. - - - - - Gets current zero-based index of item which is going to be moved. - - - - - Gets zero-based index of item after it has been moved. - - - - - An event handler which is invoked before a list item is moved. - - Object which raised event. - Event arguments. - - - - Arguments which are passed to . - - - - - Initializes a new instance of . - - Reorderable list adaptor. - Zero-based index of item. - - - - Gets adaptor to reorderable list container which contains element. - - - - - Gets zero-based index of item which is being removed. - - - - - An event handler which is invoked before a list item is removed. - - Object which raised event. - Event arguments. - - - - Base class for custom reorderable list control. - - - - - Initializes a new instance of . - - - - - Initializes a new instance of . - - Optional flags which affect behavior of control. - - - - Add item at end of list and raises the event . - - Reorderable list adaptor. - - - - Invoked to generate context menu for list item. - - Menu which can be populated. - Zero-based index of item which was right-clicked. - Reorderable list adaptor. - - - - Occurs when add menu button is clicked. - - - - - Background color of anchor list item. - - - - - Calculate height of list control in pixels. - - Reorderable list adaptor. - - Required list height in pixels. - - - - - Calculate height of list control in pixels. - - Count of items in list. - Fixed height of list item. - - Required list height in pixels. - - - - - Remove all items from list. - - Reorderable list adaptor. - - Returns a value of false if operation was cancelled. - - - - - Content for "Clear All" command. - - - - - Content for "Duplicate" command. - - - - - Content for "Insert Above" command. - - - - - Content for "Insert Below" command. - - - - - Content for "Move to Bottom" command. - - - - - Content for "Move to Top" command. - - - - - Content for "Remove" command. - - - - - Gets or sets style used to draw background of list control. - - - - - Gets the total position of the list item that is currently being drawn. - - - - - Gets the control ID of the list that is currently being drawn. - - - - - Gets the position of the list control that is currently being drawn. - - - - - Default functionality to handle context command. - - - - - Call to manually perform command. - - Name of command. This is the text shown in the context menu. - Zero-based index of item which was right-clicked. - Reorderable list adaptor. - - A value of true if command was known; otherwise false. - - - - - Call to manually perform command. - - Content representing command. - Zero-based index of item which was right-clicked. - Reorderable list adaptor. - - A value of true if command was known; otherwise false. - - - - - Draw layout version of list control. - - Unique ID of list control. - Reorderable list adaptor. - Delegate for drawing empty list. - - - - Draw layout version of list control. - - Unique ID of list control. - Reorderable list adaptor. - Delegate for drawing empty list. - - - - Draw list control with absolute positioning. - - Position of list control in GUI. - Reorderable list adaptor. - Delegate for drawing empty list. - - - - Draw list control with absolute positioning. - - Position of list control in GUI. - Reorderable list adaptor. - Delegate for drawing empty list. - - - - Generate and draw control from state object. - - Reorderable list adaptor. - Delegate for drawing empty list. - Optional flags to pass into list field. - - - - Generate and draw control from state object. - - Position of control. - Reorderable list adaptor. - Delegate for drawing empty list. - Optional flags to pass into list field. - - - - Draws drop insertion indicator. - - Position if the drop indicator. - - - - Duplicate specified item and raises the event . - - Reorderable list adaptor. - Zero-based index of item. - - - - Gets or sets flags which affect behavior of control. - - - - - Gets or sets style used to draw footer buttons. - - - - - Invoked to handle context command. - - Name of command. This is the text shown in the context menu. - Zero-based index of item which was right-clicked. - Reorderable list adaptor. - - A value of true if command was known; otherwise false. - - - - - Gets or sets a boolean value indicating whether a horizontal line should be - shown below the last list item at the end of the list control. - - - - - Gets or sets a boolean value indicating whether a horizontal line should be - shown above the first list item at the start of the list control. - - - - - Gets or sets the color of the horizontal lines that appear between list items. - - - - - Insert item at specified index and raises the event . - - Reorderable list adaptor. - Zero-based index of item. - - - - Gets or sets style used to draw list item buttons (like the remove button). - - - - - Occurs after list item is inserted or duplicated. - - - - - Occurs after list item has been moved. - - - - - Occurs immediately before list item is moved allowing for move operation to be cancelled. - - - - - Occurs before list item is removed and allowing for remove operation to be cancelled. - - - - - Move item from source index to destination index. - - Reorderable list adaptor. - Zero-based index of source item. - Zero-based index of destination index. - - - - Raises event when add menu button is clicked. - - Event arguments. - - - - Raises event after list item is inserted or duplicated. - - Event arguments. - - - - Raises event after list item has been moved. - - Event arguments. - - - - Raises event immediately before list item is moved and provides oppertunity to cancel. - - Event arguments. - - - - Raises event before list item is removed and provides oppertunity to cancel. - - Event arguments. - - - - Remove specified item. - - Reorderable list adaptor. - Zero-based index of item. - - Returns a value of false if operation was cancelled. - - - - - Background color of target slot when dragging list item. - - - - - Invoked to draw content for empty list. - - - - - Invoked to draw content for empty list with absolute positioning. - - Position of empty content. - - - - Invoked to draw list item. - - Position of list item. - The list item. - Type of item list. - - The modified value. - - - - - Additional flags which can be passed into reorderable list field. - - - - - Hide grab handles and disable reordering of list items. - - - - - Hide add button at base of control. - - - - - Hide remove buttons from list items. - - - - - Do not display context menu upon right-clicking grab handle. - - - - - Hide "Duplicate" option from context menu. - - - - - Do not automatically focus first control of newly added items. - - - - - Show zero-based index of array elements. - - - - - Do not attempt to clip items which are out of view. - - - - - Utility class for drawing reorderable lists. - - - - - Calculate height of list field for adapted collection. - - Reorderable list adaptor. - Optional flags to pass into list field. - - Required list height in pixels. - - - - - Calculate height of list field for adapted collection. - - Reorderable list adaptor. - Optional flags to pass into list field. - - Required list height in pixels. - - - - - Calculate height of list field for absolute positioning. - - Count of items in list. - Fixed height of list item. - Optional flags to pass into list field. - - Required list height in pixels. - - - - - Calculate height of list field for absolute positioning. - - Count of items in list. - Fixed height of list item. - Optional flags to pass into list field. - - Required list height in pixels. - - - - - Calculate height of list field for absolute positioning. - - Count of items in list. - Fixed height of list item. - Optional flags to pass into list field. - - Required list height in pixels. - - - - - Calculate height of list field for absolute positioning. - - Count of items in list. - Fixed height of list item. - Optional flags to pass into list field. - - Required list height in pixels. - - - - - Calculate height of list field for absolute positioning. - - Serializable property. - Optional flags to pass into list field. - - Required list height in pixels. - - - - - Calculate height of list field for absolute positioning. - - Serializable property. - Optional flags to pass into list field. - - Required list height in pixels. - - - - - Gets the zero-based index of the list item that is currently being drawn; - or a value of -1 if no item is currently being drawn. - - - - - Gets the total position of the list item that is currently being drawn. - - - - - Gets the control ID of the list that is currently being drawn. - - - - - Gets the position of the list control that is currently being drawn. - - - - - Default list item drawer implementation. - - Position to draw list item control(s). - Value of list item. - Type of list item. - - Unmodified value of list item. - - - - - Default list item height is 18 pixels. - - - - - Gets or sets the zero-based index of the last item that was changed. A value of -1 - indicates that no item was changed by list. - - - - - Draw list field control for adapted collection. - - Reorderable list adaptor. - Callback to draw custom content for empty list (optional). - Optional flags to pass into list field. - - - - Draw list field control for adapted collection. - - Reorderable list adaptor. - Callback to draw custom content for empty list (optional). - Optional flags to pass into list field. - - - - Draw list field control for adapted collection. - - Reorderable list adaptor. - Callback to draw custom content for empty list (optional). - Optional flags to pass into list field. - - - - Draw list field control for adapted collection. - - Reorderable list adaptor. - Callback to draw custom content for empty list (optional). - Optional flags to pass into list field. - - - - Draw list field control. - - The list which can be reordered. - Callback to draw list item. - Callback to draw custom content for empty list (optional). - Height of a single list item. - Optional flags to pass into list field. - Type of list item. - - - - Draw list field control. - - The list which can be reordered. - Callback to draw list item. - Callback to draw custom content for empty list (optional). - Height of a single list item. - Optional flags to pass into list field. - Type of list item. - - - - Draw list field control. - - The list which can be reordered. - Callback to draw list item. - Callback to draw custom content for empty list (optional). - Height of a single list item. - Optional flags to pass into list field. - Type of list item. - - - - Draw list field control. - - The list which can be reordered. - Callback to draw list item. - Callback to draw custom content for empty list (optional). - Height of a single list item. - Optional flags to pass into list field. - Type of list item. - - - - Draw list field control. - - The list which can be reordered. - Callback to draw list item. - Callback to draw custom content for empty list (optional). - Height of a single list item. - Optional flags to pass into list field. - Type of list item. - - - - Draw list field control. - - The list which can be reordered. - Callback to draw list item. - Callback to draw custom content for empty list (optional). - Height of a single list item. - Optional flags to pass into list field. - Type of list item. - - - - Draw list field control. - - The list which can be reordered. - Callback to draw list item. - Callback to draw custom content for empty list (optional). - Height of a single list item. - Optional flags to pass into list field. - Type of list item. - - - - Draw list field control. - - The list which can be reordered. - Callback to draw list item. - Callback to draw custom content for empty list (optional). - Height of a single list item. - Optional flags to pass into list field. - Type of list item. - - - - Draw list field control for serializable property array. - - Serializable property. - Use fixed height for items rather than . - Callback to draw custom content for empty list (optional). - Optional flags to pass into list field. - - - - Draw list field control for serializable property array. - - Serializable property. - Use fixed height for items rather than . - Callback to draw custom content for empty list (optional). - Optional flags to pass into list field. - - - - Draw list field control for serializable property array. - - Serializable property. - Use fixed height for items rather than . - Callback to draw custom content for empty list (optional). - Optional flags to pass into list field. - - - - Draw list field control for serializable property array. - - Serializable property. - Use fixed height for items rather than . - Callback to draw custom content for empty list (optional). - Optional flags to pass into list field. - - - - Draw list field control for serializable property array. - - Serializable property. - Use fixed height for items rather than . - Callback to draw custom content for empty list (optional). - Optional flags to pass into list field. - - - - Draw list field control for serializable property array. - - Serializable property. - Use fixed height for items rather than . - Callback to draw custom content for empty list (optional). - Optional flags to pass into list field. - - - - Draw list field control for serializable property array. - - Serializable property. - Use fixed height for items rather than . - Callback to draw custom content for empty list (optional). - Optional flags to pass into list field. - - - - Draw list field control for serializable property array. - - Serializable property. - Use fixed height for items rather than . - Callback to draw custom content for empty list (optional). - Optional flags to pass into list field. - - - - Draw list field control for adapted collection. - - Position of control. - Reorderable list adaptor. - Callback to draw custom content for empty list (optional). - Optional flags to pass into list field. - - - - Draw list field control for adapted collection. - - Position of control. - Reorderable list adaptor. - Callback to draw custom content for empty list (optional). - Optional flags to pass into list field. - - - - Draw list field control for adapted collection. - - Position of control. - Reorderable list adaptor. - Callback to draw custom content for empty list (optional). - Optional flags to pass into list field. - - - - Draw list field control for adapted collection. - - Position of control. - Reorderable list adaptor. - Callback to draw custom content for empty list (optional). - Optional flags to pass into list field. - - - - Draw list field control with absolute positioning. - - Position of control. - The list which can be reordered. - Callback to draw list item. - Callback to draw custom content for empty list (optional). - Height of a single list item. - Optional flags to pass into list field. - Type of list item. - - - - Draw list field control with absolute positioning. - - Position of control. - The list which can be reordered. - Callback to draw list item. - Callback to draw custom content for empty list (optional). - Height of a single list item. - Optional flags to pass into list field. - Type of list item. - - - - Draw list field control with absolute positioning. - - Position of control. - The list which can be reordered. - Callback to draw list item. - Callback to draw custom content for empty list (optional). - Height of a single list item. - Optional flags to pass into list field. - Type of list item. - - - - Draw list field control with absolute positioning. - - Position of control. - The list which can be reordered. - Callback to draw list item. - Callback to draw custom content for empty list (optional). - Height of a single list item. - Optional flags to pass into list field. - Type of list item. - - - - Draw list field control with absolute positioning. - - Position of control. - The list which can be reordered. - Callback to draw list item. - Callback to draw custom content for empty list (optional). - Height of a single list item. - Optional flags to pass into list field. - Type of list item. - - - - Draw list field control with absolute positioning. - - Position of control. - The list which can be reordered. - Callback to draw list item. - Callback to draw custom content for empty list (optional). - Height of a single list item. - Optional flags to pass into list field. - Type of list item. - - - - Draw list field control with absolute positioning. - - Position of control. - The list which can be reordered. - Callback to draw list item. - Callback to draw custom content for empty list (optional). - Height of a single list item. - Optional flags to pass into list field. - Type of list item. - - - - Draw list field control with absolute positioning. - - Position of control. - The list which can be reordered. - Callback to draw list item. - Callback to draw custom content for empty list (optional). - Height of a single list item. - Optional flags to pass into list field. - Type of list item. - - - - Draw list field control for serializable property array. - - Position of control. - Serializable property. - Use fixed height for items rather than . - Callback to draw custom content for empty list (optional). - Optional flags to pass into list field. - - - - Draw list field control for serializable property array. - - Position of control. - Serializable property. - Use fixed height for items rather than . - Callback to draw custom content for empty list (optional). - Optional flags to pass into list field. - - - - Draw list field control for serializable property array. - - Position of control. - Serializable property. - Use fixed height for items rather than . - Callback to draw custom content for empty list (optional). - Optional flags to pass into list field. - - - - Draw list field control for serializable property array. - - Position of control. - Serializable property. - Use fixed height for items rather than . - Callback to draw custom content for empty list (optional). - Optional flags to pass into list field. - - - - Draw list field control for serializable property array. - - Position of control. - Serializable property. - Use fixed height for items rather than . - Callback to draw custom content for empty list (optional). - Optional flags to pass into list field. - - - - Draw list field control for serializable property array. - - Position of control. - Serializable property. - Use fixed height for items rather than . - Callback to draw custom content for empty list (optional). - Optional flags to pass into list field. - - - - Draw list field control for serializable property array. - - Position of control. - Serializable property. - Use fixed height for items rather than . - Callback to draw custom content for empty list (optional). - Optional flags to pass into list field. - - - - Draw list field control for serializable property array. - - Position of control. - Serializable property. - Use fixed height for items rather than . - Callback to draw custom content for empty list (optional). - Optional flags to pass into list field. - - - - Draws text field allowing list items to be edited. - - Position to draw list item control(s). - Value of list item. - - Modified value of list item. - - - - - Draw title control for list field. - - Text for title control. - - - - Draw title control for list field. - - Content for title control. - - - - Draw title control for list field with absolute positioning. - - Position of control. - Text for title control. - - - - Draw title control for list field with absolute positioning. - - Position of control. - Content for title control. - - - - Styles for the . - - - - - Gets style for the background of list control. - - - - - Gets an alternative style for the background of list control. - - - - - Gets style for footer button. - - - - - Gets an alternative style for footer button. - - - - - Gets color for the horizontal lines that appear between list items. - - - - - Gets style for remove item button. - - - - - Gets style for the background of a selected item. - - - - - Gets color of background for a selected list item. - - - - - Gets style for title header. - - - - - Reorderable list adaptor for serialized array property. - - - - - Initializes a new instance of . - - Serialized property for entire array. - - - - Initializes a new instance of . - - Serialized property for entire array. - Non-zero height overrides property drawer height calculation. - - - - Add new element at end of list. - - - - - Gets the underlying serialized array property. - - - - - Occurs before any list items are drawn. - - - - - Determines whether an item can be reordered by dragging mouse. - - Zero-based index for list element. - - A value of true if item can be dragged; otherwise false. - - - - - Determines whether an item can be removed from list. - - Zero-based index for list element. - - A value of true if item can be removed; otherwise false. - - - - - Clear all elements from list. - - - - - Gets count of elements in list. - - - - - Draws main interface for a list item. - - Position in GUI. - Zero-based index of array element. - - - - Draws background of a list item. - - Total position of list element in GUI. - Zero-based index of array element. - - - - Duplicate existing element. - - Zero-based index of list element. - - - - Occurs after all list items have been drawn. - - - - - Fixed height of each list item. - - - - - Gets height of list item in pixels. - - Zero-based index of array element. - - Measurement in pixels. - - - - - Insert new element at specified index. - - Zero-based index for list element. - - - - Gets element from list. - - Zero-based index of element. - - Serialized property wrapper for array element. - - - - - Move element from source index to destination index. - - Zero-based index of source element. - Zero-based index of destination element. - - - - Remove element at specified index. - - Zero-based index of list element. - - - \ No newline at end of file diff --git a/Assets/Fungus/Thirdparty/Reorderable List Field/Editor/Editor.ReorderableList.xml.meta b/Assets/Fungus/Thirdparty/Reorderable List Field/Editor/Editor.ReorderableList.xml.meta deleted file mode 100644 index a9d60fc3..00000000 --- a/Assets/Fungus/Thirdparty/Reorderable List Field/Editor/Editor.ReorderableList.xml.meta +++ /dev/null @@ -1,6 +0,0 @@ -fileFormatVersion: 2 -guid: 087430efbff5ee54a8c8273aee1508fc -TextScriptImporter: - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/Fungus/Thirdparty/Reorderable List Field/Editor/Element Adder Menu.meta b/Assets/Fungus/Thirdparty/Reorderable List Field/Editor/Element Adder Menu.meta new file mode 100644 index 00000000..d4e0b3ce --- /dev/null +++ b/Assets/Fungus/Thirdparty/Reorderable List Field/Editor/Element Adder Menu.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 646cdcce8adedda43a7b99aaefae2f4a +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Fungus/Thirdparty/Reorderable List Field/Editor/Element Adder Menu/ElementAdderMenuBuilder.cs b/Assets/Fungus/Thirdparty/Reorderable List Field/Editor/Element Adder Menu/ElementAdderMenuBuilder.cs new file mode 100644 index 00000000..925206e0 --- /dev/null +++ b/Assets/Fungus/Thirdparty/Reorderable List Field/Editor/Element Adder Menu/ElementAdderMenuBuilder.cs @@ -0,0 +1,109 @@ +// Copyright (c) Rotorz Limited. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root. + +using System; + +namespace Rotorz.ReorderableList { + + /// + /// Factory methods that create + /// instances that can then be used to build element adder menus. + /// + /// + /// The following example demonstrates how to build and display a menu which + /// allows the user to add elements to a given context object upon clicking a button: + /// { + /// public ShoppingListElementAdder(ShoppingList shoppingList) { + /// Object = shoppingList; + /// } + /// + /// public ShoppingList Object { get; private set; } + /// + /// public bool CanAddElement(Type type) { + /// return true; + /// } + /// public object AddElement(Type type) { + /// var instance = Activator.CreateInstance(type); + /// shoppingList.Add((ShoppingItem)instance); + /// return instance; + /// } + /// } + /// + /// private void DrawAddMenuButton(ShoppingList shoppingList) { + /// var content = new GUIContent("Add Menu"); + /// Rect position = GUILayoutUtility.GetRect(content, GUI.skin.button); + /// if (GUI.Button(position, content)) { + /// var builder = ElementAdderMenuBuilder.For(ShoppingItem); + /// builder.SetElementAdder(new ShoppingListElementAdder(shoppingList)); + /// var menu = builder.GetMenu(); + /// menu.DropDown(buttonPosition); + /// } + /// } + /// ]]> + /// { + /// var _object:ShoppingList; + /// + /// function ShoppingListElementAdder(shoppingList:ShoppingList) { + /// Object = shoppingList; + /// } + /// + /// function get Object():ShoppingList { return _object; } + /// + /// function CanAddElement(type:Type):boolean { + /// return true; + /// } + /// function AddElement(type:Type):System.Object { + /// var instance = Activator.CreateInstance(type); + /// shoppingList.Add((ShoppingItem)instance); + /// return instance; + /// } + /// } + /// + /// function DrawAddMenuButton(shoppingList:ShoppingList) { + /// var content = new GUIContent('Add Menu'); + /// var position = GUILayoutUtility.GetRect(content, GUI.skin.button); + /// if (GUI.Button(position, content)) { + /// var builder = ElementAdderMenuBuilder.For.(ShoppingItem); + /// builder.SetElementAdder(new ShoppingListElementAdder(shoppingList)); + /// var menu = builder.GetMenu(); + /// menu.DropDown(buttonPosition); + /// } + /// } + /// ]]> + /// + public static class ElementAdderMenuBuilder { + + /// + /// Gets a to build an element + /// adder menu for a context object of the type . + /// + /// Type of the context object that elements can be added to. + /// + /// A new instance. + /// + /// + public static IElementAdderMenuBuilder For() { + return new GenericElementAdderMenuBuilder(); + } + + /// + /// Gets a to build an element + /// adder menu for a context object of the type . + /// + /// Type of the context object that elements can be added to. + /// Contract type of addable elements. + /// + /// A new instance. + /// + /// + public static IElementAdderMenuBuilder For(Type contractType) { + var builder = For(); + builder.SetContractType(contractType); + return builder; + } + + } + +} diff --git a/Assets/Fungus/Thirdparty/Reorderable List Field/Editor/Element Adder Menu/ElementAdderMenuBuilder.cs.meta b/Assets/Fungus/Thirdparty/Reorderable List Field/Editor/Element Adder Menu/ElementAdderMenuBuilder.cs.meta new file mode 100644 index 00000000..ee311965 --- /dev/null +++ b/Assets/Fungus/Thirdparty/Reorderable List Field/Editor/Element Adder Menu/ElementAdderMenuBuilder.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: e6152605dacd77c4db43aa59c2498ba6 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Fungus/Thirdparty/Reorderable List Field/Editor/Element Adder Menu/ElementAdderMenuCommandAttribute.cs b/Assets/Fungus/Thirdparty/Reorderable List Field/Editor/Element Adder Menu/ElementAdderMenuCommandAttribute.cs new file mode 100644 index 00000000..3135721c --- /dev/null +++ b/Assets/Fungus/Thirdparty/Reorderable List Field/Editor/Element Adder Menu/ElementAdderMenuCommandAttribute.cs @@ -0,0 +1,67 @@ +// Copyright (c) Rotorz Limited. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root. + +using System; + +namespace Rotorz.ReorderableList { + + /// + /// Annotate implementations with a + /// to associate it with the contract + /// type of addable elements. + /// + /// + /// The following source code demonstrates how to add a helper menu command to + /// the add element menu of a shopping list: + /// { + /// public AddFavoriteShoppingItemsCommand() { + /// Content = new GUIContent("Add Favorite Items"); + /// } + /// + /// public GUIContent Content { get; private set; } + /// + /// public bool CanExecute(IElementAdder elementAdder) { + /// return true; + /// } + /// public void Execute(IElementAdder elementAdder) { + /// // TODO: Add favorite items to the shopping list! + /// } + /// } + /// ]]> + /// { + /// var _content:GUIContent = new GUIContent('Add Favorite Items'); + /// + /// function get Content():GUIContent { return _content; } + /// + /// function CanExecute(elementAdder:IElementAdder.):boolean { + /// return true; + /// } + /// function Execute(elementAdder:IElementAdder.) { + /// // TODO: Add favorite items to the shopping list! + /// } + /// } + /// ]]> + /// + [AttributeUsage(AttributeTargets.Class, AllowMultiple = true, Inherited = false)] + public sealed class ElementAdderMenuCommandAttribute : Attribute { + + /// + /// Initializes a new instance of the class. + /// + /// Contract type of addable elements. + public ElementAdderMenuCommandAttribute(Type contractType) { + ContractType = contractType; + } + + /// + /// Gets the contract type of addable elements. + /// + public Type ContractType { get; private set; } + + } + +} diff --git a/Assets/Fungus/Thirdparty/Reorderable List Field/Editor/Element Adder Menu/ElementAdderMenuCommandAttribute.cs.meta b/Assets/Fungus/Thirdparty/Reorderable List Field/Editor/Element Adder Menu/ElementAdderMenuCommandAttribute.cs.meta new file mode 100644 index 00000000..90ea04c3 --- /dev/null +++ b/Assets/Fungus/Thirdparty/Reorderable List Field/Editor/Element Adder Menu/ElementAdderMenuCommandAttribute.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: dab0906e0834f954b9c6427d5af66288 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Fungus/Thirdparty/Reorderable List Field/Editor/Element Adder Menu/ElementAdderMeta.cs b/Assets/Fungus/Thirdparty/Reorderable List Field/Editor/Element Adder Menu/ElementAdderMeta.cs new file mode 100644 index 00000000..44d4f8a7 --- /dev/null +++ b/Assets/Fungus/Thirdparty/Reorderable List Field/Editor/Element Adder Menu/ElementAdderMeta.cs @@ -0,0 +1,170 @@ +// Copyright (c) Rotorz Limited. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root. + +using System; +using System.Collections.Generic; +using System.Linq; + +namespace Rotorz.ReorderableList { + + /// + /// Provides meta information which is useful when creating new implementations of + /// the interface. + /// + public static class ElementAdderMeta { + + #region Adder Menu Command Types + + private static Dictionary>> s_ContextMap = new Dictionary>>(); + + private static IEnumerable GetMenuCommandTypes() { + return + from a in AppDomain.CurrentDomain.GetAssemblies() + from t in a.GetTypes() + where t.IsClass && !t.IsAbstract && t.IsDefined(typeof(ElementAdderMenuCommandAttribute), false) + where typeof(IElementAdderMenuCommand).IsAssignableFrom(t) + select t; + } + + /// + /// Gets an array of the types + /// that are associated with the specified . + /// + /// Type of the context object that elements can be added to. + /// Contract type of addable elements. + /// + /// An array containing zero or more . + /// + /// + /// If is null. + /// + /// + public static Type[] GetMenuCommandTypes(Type contractType) { + if (contractType == null) + throw new ArgumentNullException("contractType"); + + Dictionary> contractMap; + List commandTypes; + if (s_ContextMap.TryGetValue(typeof(TContext), out contractMap)) { + if (contractMap.TryGetValue(contractType, out commandTypes)) + return commandTypes.ToArray(); + } + else { + contractMap = new Dictionary>(); + s_ContextMap[typeof(TContext)] = contractMap; + } + + commandTypes = new List(); + + foreach (var commandType in GetMenuCommandTypes()) { + var attributes = (ElementAdderMenuCommandAttribute[])Attribute.GetCustomAttributes(commandType, typeof(ElementAdderMenuCommandAttribute)); + if (!attributes.Any(a => a.ContractType == contractType)) + continue; + + commandTypes.Add(commandType); + } + + contractMap[contractType] = commandTypes; + return commandTypes.ToArray(); + } + + /// + /// Gets an array of instances + /// that are associated with the specified . + /// + /// Type of the context object that elements can be added to. + /// Contract type of addable elements. + /// + /// An array containing zero or more instances. + /// + /// + /// If is null. + /// + /// + public static IElementAdderMenuCommand[] GetMenuCommands(Type contractType) { + var commandTypes = GetMenuCommandTypes(contractType); + var commands = new IElementAdderMenuCommand[commandTypes.Length]; + for (int i = 0; i < commandTypes.Length; ++i) + commands[i] = (IElementAdderMenuCommand)Activator.CreateInstance(commandTypes[i]); + return commands; + } + + #endregion + + #region Concrete Element Types + + private static Dictionary s_ConcreteElementTypes = new Dictionary(); + + private static IEnumerable GetConcreteElementTypesHelper(Type contractType) { + if (contractType == null) + throw new ArgumentNullException("contractType"); + + Type[] concreteTypes; + if (!s_ConcreteElementTypes.TryGetValue(contractType, out concreteTypes)) { + concreteTypes = + (from a in AppDomain.CurrentDomain.GetAssemblies() + from t in a.GetTypes() + where t.IsClass && !t.IsAbstract && contractType.IsAssignableFrom(t) + orderby t.Name + select t + ).ToArray(); + s_ConcreteElementTypes[contractType] = concreteTypes; + } + + return concreteTypes; + } + + /// + /// Gets a filtered array of the concrete element types that implement the + /// specified . + /// + /// + /// A type is excluded from the resulting array when one or more of the + /// specified returns a value of false. + /// + /// Contract type of addable elements. + /// An array of zero or more filters. + /// + /// An array of zero or more concrete element types. + /// + /// + /// If is null. + /// + /// + public static Type[] GetConcreteElementTypes(Type contractType, Func[] filters) { + return + (from t in GetConcreteElementTypesHelper(contractType) + where IsTypeIncluded(t, filters) + select t + ).ToArray(); + } + + /// + /// Gets an array of all the concrete element types that implement the specified + /// . + /// + /// Contract type of addable elements. + /// + /// An array of zero or more concrete element types. + /// + /// + /// If is null. + /// + /// + public static Type[] GetConcreteElementTypes(Type contractType) { + return GetConcreteElementTypesHelper(contractType).ToArray(); + } + + private static bool IsTypeIncluded(Type concreteType, Func[] filters) { + if (filters != null) + foreach (var filter in filters) + if (!filter(concreteType)) + return false; + return true; + } + + #endregion + + } + +} diff --git a/Assets/Fungus/Thirdparty/Reorderable List Field/Editor/Element Adder Menu/ElementAdderMeta.cs.meta b/Assets/Fungus/Thirdparty/Reorderable List Field/Editor/Element Adder Menu/ElementAdderMeta.cs.meta new file mode 100644 index 00000000..08dcfd44 --- /dev/null +++ b/Assets/Fungus/Thirdparty/Reorderable List Field/Editor/Element Adder Menu/ElementAdderMeta.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 159bf54b15add1440aaed680e94b81fc +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Fungus/Thirdparty/Reorderable List Field/Editor/Element Adder Menu/GenericElementAdderMenu.cs b/Assets/Fungus/Thirdparty/Reorderable List Field/Editor/Element Adder Menu/GenericElementAdderMenu.cs new file mode 100644 index 00000000..a855d4ea --- /dev/null +++ b/Assets/Fungus/Thirdparty/Reorderable List Field/Editor/Element Adder Menu/GenericElementAdderMenu.cs @@ -0,0 +1,38 @@ +// Copyright (c) Rotorz Limited. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root. + +using UnityEditor; +using UnityEngine; + +namespace Rotorz.ReorderableList { + + internal sealed class GenericElementAdderMenu : IElementAdderMenu { + + private GenericMenu _innerMenu = new GenericMenu(); + + public GenericElementAdderMenu() { + } + + public void AddItem(GUIContent content, GenericMenu.MenuFunction handler) { + _innerMenu.AddItem(content, false, handler); + } + + public void AddDisabledItem(GUIContent content) { + _innerMenu.AddDisabledItem(content); + } + + public void AddSeparator(string path = "") { + _innerMenu.AddSeparator(path); + } + + public bool IsEmpty { + get { return _innerMenu.GetItemCount() == 0; } + } + + public void DropDown(Rect position) { + _innerMenu.DropDown(position); + } + + } + +} diff --git a/Assets/Fungus/Thirdparty/Reorderable List Field/Editor/Element Adder Menu/GenericElementAdderMenu.cs.meta b/Assets/Fungus/Thirdparty/Reorderable List Field/Editor/Element Adder Menu/GenericElementAdderMenu.cs.meta new file mode 100644 index 00000000..6c3d6327 --- /dev/null +++ b/Assets/Fungus/Thirdparty/Reorderable List Field/Editor/Element Adder Menu/GenericElementAdderMenu.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 662b5dcb25b78f94f9afe8d3f402b628 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Fungus/Thirdparty/Reorderable List Field/Editor/Element Adder Menu/GenericElementAdderMenuBuilder.cs b/Assets/Fungus/Thirdparty/Reorderable List Field/Editor/Element Adder Menu/GenericElementAdderMenuBuilder.cs new file mode 100644 index 00000000..a3bbf56e --- /dev/null +++ b/Assets/Fungus/Thirdparty/Reorderable List Field/Editor/Element Adder Menu/GenericElementAdderMenuBuilder.cs @@ -0,0 +1,102 @@ +// Copyright (c) Rotorz Limited. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root. + +using System; +using System.Collections.Generic; +using UnityEditor; +using UnityEngine; + +namespace Rotorz.ReorderableList { + + internal sealed class GenericElementAdderMenuBuilder : IElementAdderMenuBuilder { + + private static string NicifyTypeName(Type type) { + return ObjectNames.NicifyVariableName(type.Name); + } + + private Type _contractType; + private IElementAdder _elementAdder; + private Func _typeDisplayNameFormatter; + private List> _typeFilters = new List>(); + private List> _customCommands = new List>(); + + public GenericElementAdderMenuBuilder() { + _typeDisplayNameFormatter = NicifyTypeName; + } + + public void SetContractType(Type contractType) { + _contractType = contractType; + } + + public void SetElementAdder(IElementAdder elementAdder) { + _elementAdder = elementAdder; + } + + public void SetTypeDisplayNameFormatter(Func formatter) { + _typeDisplayNameFormatter = formatter ?? NicifyTypeName; + } + + public void AddTypeFilter(Func typeFilter) { + if (typeFilter == null) + throw new ArgumentNullException("typeFilter"); + + _typeFilters.Add(typeFilter); + } + + public void AddCustomCommand(IElementAdderMenuCommand command) { + if (command == null) + throw new ArgumentNullException("command"); + + _customCommands.Add(command); + } + + public IElementAdderMenu GetMenu() { + var menu = new GenericElementAdderMenu(); + + AddCommandsToMenu(menu, _customCommands); + + if (_contractType != null) { + AddCommandsToMenu(menu, ElementAdderMeta.GetMenuCommands(_contractType)); + AddConcreteTypesToMenu(menu, ElementAdderMeta.GetConcreteElementTypes(_contractType, _typeFilters.ToArray())); + } + + return menu; + } + + private void AddCommandsToMenu(GenericElementAdderMenu menu, IList> commands) { + if (commands.Count == 0) + return; + + if (!menu.IsEmpty) + menu.AddSeparator(); + + foreach (var command in commands) { + if (_elementAdder != null && command.CanExecute(_elementAdder)) + menu.AddItem(command.Content, () => command.Execute(_elementAdder)); + else + menu.AddDisabledItem(command.Content); + } + } + + private void AddConcreteTypesToMenu(GenericElementAdderMenu menu, Type[] concreteTypes) { + if (concreteTypes.Length == 0) + return; + + if (!menu.IsEmpty) + menu.AddSeparator(); + + foreach (var concreteType in concreteTypes) { + var content = new GUIContent(_typeDisplayNameFormatter(concreteType)); + if (_elementAdder != null && _elementAdder.CanAddElement(concreteType)) + menu.AddItem(content, () => { + if (_elementAdder.CanAddElement(concreteType)) + _elementAdder.AddElement(concreteType); + }); + else + menu.AddDisabledItem(content); + } + } + + } + +} diff --git a/Assets/Fungus/Thirdparty/Reorderable List Field/Editor/Element Adder Menu/GenericElementAdderMenuBuilder.cs.meta b/Assets/Fungus/Thirdparty/Reorderable List Field/Editor/Element Adder Menu/GenericElementAdderMenuBuilder.cs.meta new file mode 100644 index 00000000..1013915a --- /dev/null +++ b/Assets/Fungus/Thirdparty/Reorderable List Field/Editor/Element Adder Menu/GenericElementAdderMenuBuilder.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: da8782cb7448c234fb86e9503326ce9c +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Fungus/Thirdparty/Reorderable List Field/Editor/Element Adder Menu/IElementAdder.cs b/Assets/Fungus/Thirdparty/Reorderable List Field/Editor/Element Adder Menu/IElementAdder.cs new file mode 100644 index 00000000..3535e8eb --- /dev/null +++ b/Assets/Fungus/Thirdparty/Reorderable List Field/Editor/Element Adder Menu/IElementAdder.cs @@ -0,0 +1,43 @@ +// Copyright (c) Rotorz Limited. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root. + +using System; + +namespace Rotorz.ReorderableList { + + /// + /// Interface for an object which adds elements to a context object of the type + /// . + /// + /// Type of the context object that elements can be added to. + public interface IElementAdder { + + /// + /// Gets the context object. + /// + TContext Object { get; } + + /// + /// Determines whether a new element of the specified can + /// be added to the associated context object. + /// + /// Type of element to add. + /// + /// A value of true if an element of the specified type can be added; + /// otherwise, a value of false. + /// + bool CanAddElement(Type type); + + /// + /// Adds an element of the specified to the associated + /// context object. + /// + /// Type of element to add. + /// + /// The new element. + /// + object AddElement(Type type); + + } + +} diff --git a/Assets/Fungus/Thirdparty/Reorderable List Field/Editor/Element Adder Menu/IElementAdder.cs.meta b/Assets/Fungus/Thirdparty/Reorderable List Field/Editor/Element Adder Menu/IElementAdder.cs.meta new file mode 100644 index 00000000..9572f0f4 --- /dev/null +++ b/Assets/Fungus/Thirdparty/Reorderable List Field/Editor/Element Adder Menu/IElementAdder.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 811c0b5125dc50746b66457b5c96741d +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Fungus/Thirdparty/Reorderable List Field/Editor/Element Adder Menu/IElementAdderMenu.cs b/Assets/Fungus/Thirdparty/Reorderable List Field/Editor/Element Adder Menu/IElementAdderMenu.cs new file mode 100644 index 00000000..540370cf --- /dev/null +++ b/Assets/Fungus/Thirdparty/Reorderable List Field/Editor/Element Adder Menu/IElementAdderMenu.cs @@ -0,0 +1,33 @@ +// Copyright (c) Rotorz Limited. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root. + +using UnityEngine; + +namespace Rotorz.ReorderableList { + + /// + /// Interface for a menu interface. + /// + public interface IElementAdderMenu { + + /// + /// Gets a value indicating whether the menu contains any items. + /// + /// + /// true if the menu contains one or more items; otherwise, false. + /// + bool IsEmpty { get; } + + /// + /// Displays the drop-down menu inside an editor GUI. + /// + /// + /// This method should only be used during OnGUI and OnSceneGUI + /// events; for instance, inside an editor window, a custom inspector or scene view. + /// + /// Position of menu button in the GUI. + void DropDown(Rect position); + + } + +} diff --git a/Assets/Fungus/Thirdparty/Reorderable List Field/Editor/Element Adder Menu/IElementAdderMenu.cs.meta b/Assets/Fungus/Thirdparty/Reorderable List Field/Editor/Element Adder Menu/IElementAdderMenu.cs.meta new file mode 100644 index 00000000..38e2b80d --- /dev/null +++ b/Assets/Fungus/Thirdparty/Reorderable List Field/Editor/Element Adder Menu/IElementAdderMenu.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 7452dc2d2d6305947ab39a48354ab4bb +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Fungus/Thirdparty/Reorderable List Field/Editor/Element Adder Menu/IElementAdderMenuBuilder.cs b/Assets/Fungus/Thirdparty/Reorderable List Field/Editor/Element Adder Menu/IElementAdderMenuBuilder.cs new file mode 100644 index 00000000..783891fb --- /dev/null +++ b/Assets/Fungus/Thirdparty/Reorderable List Field/Editor/Element Adder Menu/IElementAdderMenuBuilder.cs @@ -0,0 +1,76 @@ +// Copyright (c) Rotorz Limited. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root. + +using System; + +namespace Rotorz.ReorderableList { + + /// + /// Interface for building an . + /// + /// Type of the context object that elements can be added to. + public interface IElementAdderMenuBuilder { + + /// + /// Sets contract type of the elements that can be included in the . + /// Only non-abstract class types that are assignable from the + /// will be included in the built menu. + /// + /// Contract type of addable elements. + void SetContractType(Type contractType); + + /// + /// Set the implementation which is used + /// when adding new elements to the context object. + /// + /// + /// Specify a value of null for to + /// prevent the selection of any types. + /// + /// Element adder. + void SetElementAdder(IElementAdder elementAdder); + + /// + /// Set the function that formats the display of type names in the user interface. + /// + /// + /// Specify a value of null for to + /// assume the default formatting function. + /// + /// Function that formats display name of type; or null. + void SetTypeDisplayNameFormatter(Func formatter); + + /// + /// Adds a filter function which determines whether types can be included or + /// whether they need to be excluded. + /// + /// + /// If a filter function returns a value of false then that type + /// will not be included in the menu interface. + /// + /// Filter function. + /// + /// If is null. + /// + void AddTypeFilter(Func typeFilter); + + /// + /// Adds a custom command to the menu. + /// + /// The custom command. + /// + /// If is null. + /// + void AddCustomCommand(IElementAdderMenuCommand command); + + /// + /// Builds and returns a new instance. + /// + /// + /// A new instance each time the method is invoked. + /// + IElementAdderMenu GetMenu(); + + } + +} diff --git a/Assets/Fungus/Thirdparty/Reorderable List Field/Editor/Element Adder Menu/IElementAdderMenuBuilder.cs.meta b/Assets/Fungus/Thirdparty/Reorderable List Field/Editor/Element Adder Menu/IElementAdderMenuBuilder.cs.meta new file mode 100644 index 00000000..c279ceb2 --- /dev/null +++ b/Assets/Fungus/Thirdparty/Reorderable List Field/Editor/Element Adder Menu/IElementAdderMenuBuilder.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 2810812b845cceb4e9a0f7c0de842f29 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Fungus/Thirdparty/Reorderable List Field/Editor/Element Adder Menu/IElementAdderMenuCommand.cs b/Assets/Fungus/Thirdparty/Reorderable List Field/Editor/Element Adder Menu/IElementAdderMenuCommand.cs new file mode 100644 index 00000000..be6eb7ca --- /dev/null +++ b/Assets/Fungus/Thirdparty/Reorderable List Field/Editor/Element Adder Menu/IElementAdderMenuCommand.cs @@ -0,0 +1,41 @@ +// Copyright (c) Rotorz Limited. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root. + +using UnityEngine; + +namespace Rotorz.ReorderableList { + + /// + /// Interface for a menu command that can be included in an + /// either by annotating an implementation of the + /// interface with or directly by + /// calling . + /// + /// Type of the context object that elements can be added to. + public interface IElementAdderMenuCommand { + + /// + /// Gets the content of the menu command. + /// + GUIContent Content { get; } + + /// + /// Determines whether the command can be executed. + /// + /// The associated element adder provides access to + /// the instance. + /// + /// A value of true if the command can execute; otherwise, false. + /// + bool CanExecute(IElementAdder elementAdder); + + /// + /// Executes the command. + /// + /// The associated element adder provides access to + /// the instance. + void Execute(IElementAdder elementAdder); + + } + +} diff --git a/Assets/Fungus/Thirdparty/Reorderable List Field/Editor/Element Adder Menu/IElementAdderMenuCommand.cs.meta b/Assets/Fungus/Thirdparty/Reorderable List Field/Editor/Element Adder Menu/IElementAdderMenuCommand.cs.meta new file mode 100644 index 00000000..dfa90fa8 --- /dev/null +++ b/Assets/Fungus/Thirdparty/Reorderable List Field/Editor/Element Adder Menu/IElementAdderMenuCommand.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 3fc42d99c85c1bc409897df1dae25bd4 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Fungus/Thirdparty/Reorderable List Field/Editor/GenericListAdaptor.cs b/Assets/Fungus/Thirdparty/Reorderable List Field/Editor/GenericListAdaptor.cs new file mode 100644 index 00000000..4ac38465 --- /dev/null +++ b/Assets/Fungus/Thirdparty/Reorderable List Field/Editor/GenericListAdaptor.cs @@ -0,0 +1,145 @@ +// Copyright (c) Rotorz Limited. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root. + +using System; +using System.Collections.Generic; +using UnityEngine; + +namespace Rotorz.ReorderableList { + + /// + /// Reorderable list adaptor for generic list. + /// + /// + /// This adaptor can be subclassed to add special logic to item height calculation. + /// You may want to implement a custom adaptor class where specialised functionality + /// is needed. + /// List elements which implement the interface are + /// cloned using that interface upon duplication; otherwise the item value or reference is + /// simply copied. + /// + /// Type of list element. + public class GenericListAdaptor : IReorderableListAdaptor { + + private IList _list; + + private ReorderableListControl.ItemDrawer _itemDrawer; + + /// + /// Fixed height of each list item. + /// + public float FixedItemHeight; + + /// + /// Gets the underlying list data structure. + /// + public IList List { + get { return _list; } + } + + /// + /// Gets element from list. + /// + /// Zero-based index of element. + /// + /// The element. + /// + public T this[int index] { + get { return _list[index]; } + } + + #region Construction + + /// + /// Initializes a new instance of . + /// + /// The list which can be reordered. + /// Callback to draw list item. + /// Height of list item in pixels. + public GenericListAdaptor(IList list, ReorderableListControl.ItemDrawer itemDrawer, float itemHeight) { + this._list = list; + this._itemDrawer = itemDrawer ?? ReorderableListGUI.DefaultItemDrawer; + this.FixedItemHeight = itemHeight; + } + + #endregion + + #region IReorderableListAdaptor - Implementation + + /// + public int Count { + get { return _list.Count; } + } + + /// + public virtual bool CanDrag(int index) { + return true; + } + /// + public virtual bool CanRemove(int index) { + return true; + } + + /// + public virtual void Add() { + _list.Add(default(T)); + } + /// + public virtual void Insert(int index) { + _list.Insert(index, default(T)); + } + /// + public virtual void Duplicate(int index) { + T newItem = _list[index]; + + ICloneable existingItem = newItem as ICloneable; + if (existingItem != null) + newItem = (T)existingItem.Clone(); + + _list.Insert(index + 1, newItem); + } + /// + public virtual void Remove(int index) { + _list.RemoveAt(index); + } + /// + public virtual void Move(int sourceIndex, int destIndex) { + if (destIndex > sourceIndex) + --destIndex; + + T item = _list[sourceIndex]; + _list.RemoveAt(sourceIndex); + _list.Insert(destIndex, item); + } + /// + public virtual void Clear() { + _list.Clear(); + } + + /// + public virtual void BeginGUI() { + } + + /// + public virtual void EndGUI() { + } + + /// + public virtual void DrawItemBackground(Rect position, int index) { + } + + /// + public virtual void DrawItem(Rect position, int index) { + _list[index] = _itemDrawer(position, _list[index]); + } + + /// + public virtual float GetItemHeight(int index) { + return FixedItemHeight; + } + + #endregion + + } + +} diff --git a/Assets/Fungus/Thirdparty/Reorderable List Field/Editor/GenericListAdaptor.cs.meta b/Assets/Fungus/Thirdparty/Reorderable List Field/Editor/GenericListAdaptor.cs.meta new file mode 100644 index 00000000..c1042b6d --- /dev/null +++ b/Assets/Fungus/Thirdparty/Reorderable List Field/Editor/GenericListAdaptor.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 9860e7f6c1d1b8d45b13889a965e172f +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Fungus/Thirdparty/Reorderable List Field/Editor/IReorderableListAdaptor.cs b/Assets/Fungus/Thirdparty/Reorderable List Field/Editor/IReorderableListAdaptor.cs new file mode 100644 index 00000000..1aa3112d --- /dev/null +++ b/Assets/Fungus/Thirdparty/Reorderable List Field/Editor/IReorderableListAdaptor.cs @@ -0,0 +1,131 @@ +// Copyright (c) Rotorz Limited. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root. + +using UnityEngine; + +namespace Rotorz.ReorderableList { + + /// + /// Adaptor allowing reorderable list control to interface with list data. + /// + /// + public interface IReorderableListAdaptor { + + /// + /// Gets count of elements in list. + /// + int Count { get; } + + /// + /// Determines whether an item can be reordered by dragging mouse. + /// + /// + /// This should be a light-weight method since it will be used to determine + /// whether grab handle should be included for each item in a reorderable list. + /// Please note that returning a value of false does not prevent movement + /// on list item since other draggable items can be moved around it. + /// + /// Zero-based index for list element. + /// + /// A value of true if item can be dragged; otherwise false. + /// + bool CanDrag(int index); + /// + /// Determines whether an item can be removed from list. + /// + /// + /// This should be a light-weight method since it will be used to determine + /// whether remove button should be included for each item in list. + /// This is redundant when + /// is specified. + /// + /// Zero-based index for list element. + /// + /// A value of true if item can be removed; otherwise false. + /// + bool CanRemove(int index); + + /// + /// Add new element at end of list. + /// + void Add(); + /// + /// Insert new element at specified index. + /// + /// Zero-based index for list element. + void Insert(int index); + /// + /// Duplicate existing element. + /// + /// + /// Consider using the interface to + /// duplicate list elements where appropriate. + /// + /// Zero-based index of list element. + void Duplicate(int index); + /// + /// Remove element at specified index. + /// + /// Zero-based index of list element. + void Remove(int index); + /// + /// Move element from source index to destination index. + /// + /// Zero-based index of source element. + /// Zero-based index of destination element. + void Move(int sourceIndex, int destIndex); + /// + /// Clear all elements from list. + /// + void Clear(); + + /// + /// Occurs before any list items are drawn. + /// + /// + /// This method is only used to handle GUI repaint events. + /// + /// + void BeginGUI(); + /// + /// Occurs after all list items have been drawn. + /// + /// + /// This method is only used to handle GUI repaint events. + /// + /// + void EndGUI(); + + /// + /// Draws background of a list item. + /// + /// + /// This method is only used to handle GUI repaint events. + /// Background of list item spans a slightly larger area than the main + /// interface that is drawn by since it is + /// drawn behind the grab handle. + /// + /// Total position of list element in GUI. + /// Zero-based index of array element. + void DrawItemBackground(Rect position, int index); + /// + /// Draws main interface for a list item. + /// + /// + /// This method is used to handle all GUI events. + /// + /// Position in GUI. + /// Zero-based index of array element. + void DrawItem(Rect position, int index); + /// + /// Gets height of list item in pixels. + /// + /// Zero-based index of array element. + /// + /// Measurement in pixels. + /// + float GetItemHeight(int index); + + } + +} diff --git a/Assets/Fungus/Thirdparty/Reorderable List Field/Editor/IReorderableListAdaptor.cs.meta b/Assets/Fungus/Thirdparty/Reorderable List Field/Editor/IReorderableListAdaptor.cs.meta new file mode 100644 index 00000000..b62368ee --- /dev/null +++ b/Assets/Fungus/Thirdparty/Reorderable List Field/Editor/IReorderableListAdaptor.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 27a7bce836d771f4a84b172af5132fe7 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Fungus/Thirdparty/Reorderable List Field/Editor/IReorderableListDropTarget.cs b/Assets/Fungus/Thirdparty/Reorderable List Field/Editor/IReorderableListDropTarget.cs new file mode 100644 index 00000000..18676dae --- /dev/null +++ b/Assets/Fungus/Thirdparty/Reorderable List Field/Editor/IReorderableListDropTarget.cs @@ -0,0 +1,49 @@ +// Copyright (c) Rotorz Limited. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root. + +namespace Rotorz.ReorderableList { + + /// + /// Can be implemented along with when drop + /// insertion or ordering is desired. + /// + /// + /// This type of "drop" functionality can occur when the "drag" phase of the + /// drag and drop operation was initiated elsewhere. For example, a custom + /// could insert entirely new items by + /// dragging and dropping from the Unity "Project" window. + /// + /// + public interface IReorderableListDropTarget { + + /// + /// Determines whether an item is being dragged and that it can be inserted + /// or moved by dropping somewhere into the reorderable list control. + /// + /// + /// This method is always called whilst drawing an editor GUI. + /// + /// Zero-based index of insertion. + /// + /// A value of true if item can be dropped; otherwise false. + /// + /// + bool CanDropInsert(int insertionIndex); + + /// + /// Processes the current drop insertion operation when + /// returns a value of true to process, accept or cancel. + /// + /// + /// This method is always called whilst drawing an editor GUI. + /// This method is only called when + /// returns a value of true. + /// + /// Zero-based index of insertion. + /// + /// + void ProcessDropInsertion(int insertionIndex); + + } + +} diff --git a/Assets/Fungus/Thirdparty/Reorderable List Field/Editor/IReorderableListDropTarget.cs.meta b/Assets/Fungus/Thirdparty/Reorderable List Field/Editor/IReorderableListDropTarget.cs.meta new file mode 100644 index 00000000..85dee66a --- /dev/null +++ b/Assets/Fungus/Thirdparty/Reorderable List Field/Editor/IReorderableListDropTarget.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: d1806c8b705782141acdbee308edf82c +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Fungus/Thirdparty/Reorderable List Field/Editor/Internal.meta b/Assets/Fungus/Thirdparty/Reorderable List Field/Editor/Internal.meta new file mode 100644 index 00000000..9e5d070c --- /dev/null +++ b/Assets/Fungus/Thirdparty/Reorderable List Field/Editor/Internal.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 1080d4950a85a2b4da9d5653fff71a13 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Fungus/Thirdparty/Reorderable List Field/Editor/Internal/GUIHelper.cs b/Assets/Fungus/Thirdparty/Reorderable List Field/Editor/Internal/GUIHelper.cs new file mode 100644 index 00000000..6d729e29 --- /dev/null +++ b/Assets/Fungus/Thirdparty/Reorderable List Field/Editor/Internal/GUIHelper.cs @@ -0,0 +1,140 @@ +// Copyright (c) Rotorz Limited. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root. + +using System; +using System.Reflection; +using UnityEditor; +using UnityEngine; + +namespace Rotorz.ReorderableList.Internal { + + /// + /// Utility functions to assist with GUIs. + /// + /// + public static class GUIHelper { + + static GUIHelper() { + var tyGUIClip = Type.GetType("UnityEngine.GUIClip,UnityEngine"); + if (tyGUIClip != null) { + var piVisibleRect = tyGUIClip.GetProperty("visibleRect", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); + if (piVisibleRect != null) { + var getMethod = piVisibleRect.GetGetMethod(true) ?? piVisibleRect.GetGetMethod(false); + VisibleRect = (Func)Delegate.CreateDelegate(typeof(Func), getMethod); + } + } + + var miFocusTextInControl = typeof(EditorGUI).GetMethod("FocusTextInControl", BindingFlags.Static | BindingFlags.Public); + if (miFocusTextInControl == null) + miFocusTextInControl = typeof(GUI).GetMethod("FocusControl", BindingFlags.Static | BindingFlags.Public); + + FocusTextInControl = (Action)Delegate.CreateDelegate(typeof(Action), miFocusTextInControl); + + s_SeparatorColor = EditorGUIUtility.isProSkin + ? new Color(0.11f, 0.11f, 0.11f) + : new Color(0.5f, 0.5f, 0.5f); + + s_SeparatorStyle = new GUIStyle(); + s_SeparatorStyle.normal.background = EditorGUIUtility.whiteTexture; + s_SeparatorStyle.stretchWidth = true; + } + + /// + /// Gets visible rectangle within GUI. + /// + /// + /// VisibleRect = TopmostRect + scrollViewOffsets + /// + public static Func VisibleRect; + + /// + /// Focus control and text editor where applicable. + /// + public static Action FocusTextInControl; + + private static GUIStyle s_TempStyle = new GUIStyle(); + + /// + /// Draw texture using to workaround bug in Unity where + /// flickers when embedded inside a property drawer. + /// + /// Position of which to draw texture in space of GUI. + /// Texture. + public static void DrawTexture(Rect position, Texture2D texture) { + if (Event.current.type != EventType.Repaint) + return; + + s_TempStyle.normal.background = texture; + + s_TempStyle.Draw(position, GUIContent.none, false, false, false, false); + } + + private static GUIContent s_TempIconContent = new GUIContent(); + private static readonly int s_IconButtonHint = "_ReorderableIconButton_".GetHashCode(); + + public static bool IconButton(Rect position, bool visible, Texture2D iconNormal, Texture2D iconActive, GUIStyle style) { + int controlID = GUIUtility.GetControlID(s_IconButtonHint, FocusType.Passive); + bool result = false; + + position.height += 1; + + switch (Event.current.GetTypeForControl(controlID)) { + case EventType.MouseDown: + // Do not allow button to be pressed using right mouse button since + // context menu should be shown instead! + if (GUI.enabled && Event.current.button != 1 && position.Contains(Event.current.mousePosition)) { + GUIUtility.hotControl = controlID; + GUIUtility.keyboardControl = 0; + Event.current.Use(); + } + break; + + case EventType.MouseDrag: + if (GUIUtility.hotControl == controlID) + Event.current.Use(); + break; + + case EventType.MouseUp: + if (GUIUtility.hotControl == controlID) { + GUIUtility.hotControl = 0; + result = position.Contains(Event.current.mousePosition); + Event.current.Use(); + } + break; + + case EventType.Repaint: + if (visible) { + bool isActive = GUIUtility.hotControl == controlID && position.Contains(Event.current.mousePosition); + s_TempIconContent.image = isActive ? iconActive : iconNormal; + position.height -= 1; + style.Draw(position, s_TempIconContent, isActive, isActive, false, false); + } + break; + } + + return result; + } + + public static bool IconButton(Rect position, Texture2D iconNormal, Texture2D iconActive, GUIStyle style) { + return IconButton(position, true, iconNormal, iconActive, style); + } + + private static readonly Color s_SeparatorColor; + private static readonly GUIStyle s_SeparatorStyle; + + public static void Separator(Rect position, Color color) { + if (Event.current.type == EventType.Repaint) { + Color restoreColor = GUI.color; + GUI.color = color; + s_SeparatorStyle.Draw(position, false, false, false, false); + GUI.color = restoreColor; + } + } + + public static void Separator(Rect position) { + Separator(position, s_SeparatorColor); + } + + } + +} diff --git a/Assets/Fungus/Thirdparty/Reorderable List Field/Editor/Internal/GUIHelper.cs.meta b/Assets/Fungus/Thirdparty/Reorderable List Field/Editor/Internal/GUIHelper.cs.meta new file mode 100644 index 00000000..620f0b4f --- /dev/null +++ b/Assets/Fungus/Thirdparty/Reorderable List Field/Editor/Internal/GUIHelper.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 26c2c1b444cf6a446b03219116f2f827 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Fungus/Thirdparty/Reorderable List Field/Editor/Internal/ReorderableListResources.cs b/Assets/Fungus/Thirdparty/Reorderable List Field/Editor/Internal/ReorderableListResources.cs new file mode 100644 index 00000000..57905450 --- /dev/null +++ b/Assets/Fungus/Thirdparty/Reorderable List Field/Editor/Internal/ReorderableListResources.cs @@ -0,0 +1,193 @@ +// Copyright (c) Rotorz Limited. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root. + +using System; +using UnityEditor; +using UnityEngine; + +namespace Rotorz.ReorderableList.Internal { + + /// + public enum ReorderableListTexture { + Icon_Add_Normal = 0, + Icon_Add_Active, + Icon_AddMenu_Normal, + Icon_AddMenu_Active, + Icon_Menu_Normal, + Icon_Menu_Active, + Icon_Remove_Normal, + Icon_Remove_Active, + Button_Normal, + Button_Active, + Button2_Normal, + Button2_Active, + TitleBackground, + ContainerBackground, + Container2Background, + GrabHandle, + } + + /// + /// Resources to assist with reorderable list control. + /// + /// + public static class ReorderableListResources { + + static ReorderableListResources() { + GenerateSpecialTextures(); + LoadResourceAssets(); + } + + #region Texture Resources + + /// + /// Resource assets for light skin. + /// + /// + /// Resource assets are PNG images which have been encoded using a base-64 + /// string so that actual asset files are not necessary. + /// + private static string[] s_LightSkin = { + "iVBORw0KGgoAAAANSUhEUgAAAAgAAAAICAYAAADED76LAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAACxJREFUeNpi/P//PwMM6OvrgzkXL15khIkxMRAABBUw6unp/afMBNo7EiDAAEKeD5EsXZcTAAAAAElFTkSuQmCC", + "iVBORw0KGgoAAAANSUhEUgAAAAgAAAAICAYAAADED76LAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAC1JREFUeNpi/P//PwMM3L17F8xRVlZmhIkxMRAABBUw3rlz5z9lJtDekQABBgCvqxGbQWpEqwAAAABJRU5ErkJggg==", + "iVBORw0KGgoAAAANSUhEUgAAABYAAAAICAYAAAD9aA/QAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAERJREFUeNpi/P//PwMxQF9fH6zw4sWLjMSoZ2KgEaCZwYz4ggLmfVwAX7AMjIuJjTxsPqOKi9EtA/GpFhQww2E0QIABAPF5IGHNU7adAAAAAElFTkSuQmCC", + "iVBORw0KGgoAAAANSUhEUgAAABYAAAAICAYAAAD9aA/QAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAERJREFUeNpi/P//PwMx4O7du2CFysrKjMSoZ2KgEaCZwYz4ggLmfVwAX7AMjIuJjTxsPqOKi9EtA/GpFhQww2E0QIABACBuGkOOEiPJAAAAAElFTkSuQmCC", + "iVBORw0KGgoAAAANSUhEUgAAAAUAAAAICAYAAAAx8TU7AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAADBJREFUeNpi/P//PwM6YGLAAigUZNHX18ewienixYuMyAJgPshJIKynp/cfxgYIMACCMhb+oVNPwwAAAABJRU5ErkJggg==", + "iVBORw0KGgoAAAANSUhEUgAAAAUAAAAICAYAAAAx8TU7AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAADFJREFUeNpi/P//PwM6YGLAAigUZLl79y6GTUzKysqMyAJgPshJIHznzp3/MDZAgAEAkoIW/jHg7H4AAAAASUVORK5CYII=", + "iVBORw0KGgoAAAANSUhEUgAAAAgAAAACCAIAAADq9gq6AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAABVJREFUeNpiVFZWZsAGmBhwAIAAAwAURgBt4C03ZwAAAABJRU5ErkJggg==", + "iVBORw0KGgoAAAANSUhEUgAAAAgAAAACCAIAAADq9gq6AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAABVJREFUeNpivHPnDgM2wMSAAwAEGAB8VgKYlvqkBwAAAABJRU5ErkJggg==", + "iVBORw0KGgoAAAANSUhEUgAAAAcAAAAFCAYAAACJmvbYAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAEFJREFUeNpiKCoq+v/p06f/ly9fhmMQHyTOxIAH4JVkARHv379nkJeXhwuC+CDA+P//f4bi4uL/6Lp6e3sZAQIMACmoI7rWhl0KAAAAAElFTkSuQmCC", + "iVBORw0KGgoAAAANSUhEUgAAAAcAAAAFCAYAAACJmvbYAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAEFJREFUeNpiFBER+f/jxw8GNjY2Bhj49esXAwcHBwMTAx6AV5IFRPz58wdFEMZn/P//P4OoqOh/dF2vX79mBAgwADpeFCsbeaC+AAAAAElFTkSuQmCC", + "iVBORw0KGgoAAAANSUhEUgAAAAcAAAAHCAYAAADEUlfTAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAFBJREFUeNpi/P//P0NxcfF/BjTQ29vLyFBUVPT/4cOH/z99+gTHID5InAWkSlBQkAEoANclLy8PppkY8AC8kmBj379/DzcKxgcBRnyuBQgwACVNLqBePwzmAAAAAElFTkSuQmCC", + "iVBORw0KGgoAAAANSUhEUgAAAAcAAAAHCAYAAADEUlfTAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAElJREFUeNp8jjEKADEIBNdDrCz1/w+0tRQMOchxpHC6dVhW6m64e+MiIojMrDMTzPyJqoKq4r1sISJ3GQ8GRsln48/JNH27BBgAUhQbSyMxqzEAAAAASUVORK5CYII=", + "iVBORw0KGgoAAAANSUhEUgAAAAUAAAAECAYAAABGM/VAAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAEFJREFUeNpi/P//P0NxcfF/BgRgZP78+fN/VVVVhpCQEAZjY2OGs2fPNrCApBwdHRkePHgAVwoWnDVrFgMyAAgwAAt4E1dCq1obAAAAAElFTkSuQmCC", + "iVBORw0KGgoAAAANSUhEUgAAAAUAAAAECAYAAABGM/VAAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAADtJREFUeNpi/P//P0NxcfF/Bijo7e1lZCgqKvr/6dOn/5cvXwbTID4TSPb9+/cM8vLyYBoEGLFpBwgwAHGiI8KoD3BZAAAAAElFTkSuQmCC", + "iVBORw0KGgoAAAANSUhEUgAAAAUAAAAECAIAAADJUWIXAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAACJJREFUeNpiDA0NZUACLEDc2dkJ4ZSXlzMxoAJGNPUAAQYAwbcFBwYygqkAAAAASUVORK5CYII=", + "iVBORw0KGgoAAAANSUhEUgAAAAkAAAAFCAYAAACXU8ZrAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAACdJREFUeNpi/PTp038GAoClvr6ekBoGxv//CRrEwPL582fqWAcQYAAnaA2zsd+RkQAAAABJRU5ErkJggg==", + }; + /// + /// Resource assets for dark skin. + /// + /// + /// Resource assets are PNG images which have been encoded using a base-64 + /// string so that actual asset files are not necessary. + /// + private static string[] s_DarkSkin = { + "iVBORw0KGgoAAAANSUhEUgAAAAgAAAAKCAYAAACJxx+AAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAE9JREFUeNpi/P//PwM+wITMOXr06H8QxqmAoAnYAOORI0f+U2aCsrIy3ISFCxeC6fj4eIQCZG/CfGBtbc1IvBXIJqioqIA5d+7cgZsAEGAAsHYfVsuw0XYAAAAASUVORK5CYII=", + "iVBORw0KGgoAAAANSUhEUgAAAAgAAAAKCAYAAACJxx+AAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAEZJREFUeNpi/P//PwM+wITM+Q8FOBUQNAEbYPmPxRHIYoRN4OLignO+ffsGppHFGJFtgBnNCATEW4HMgRn9/ft3uBhAgAEAbZ0gJEmOtOAAAAAASUVORK5CYII=", + "iVBORw0KGgoAAAANSUhEUgAAABYAAAAKCAYAAACwoK7bAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAG1JREFUeNpi/P//PwMtABOxCo8ePfofhKluMM1cTCpgxBfGhLxubW3NOLhcrKKiApdcuHAhmI6Pj4fL37lzhxGXzxiJTW4wzdi8D3IAzGKY5VQJCpDLYT4B0WCfgFxMDFZWVv4PwoTUwNgAAQYA7Mltu4fEN4wAAAAASUVORK5CYII=", + "iVBORw0KGgoAAAANSUhEUgAAABYAAAAKCAYAAACwoK7bAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAGVJREFUeNpi/P//PwMtABOxCv9DAdUNppmLSQWM+HxHyOuMQEB3F7Pgk+Ti4oKzv337hiH2/ft3nD5jJDaiYZqxeZ+Tk/M/zGKY5VQJCqDLGWE+AdEgPtEuBrkKZgg+NTB5gAADAJGHOCAbby7zAAAAAElFTkSuQmCC", + "iVBORw0KGgoAAAANSUhEUgAAAAUAAAAKCAYAAAB8OZQwAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAADpJREFUeNpi/P//PwM6YGLAAmghyHL06FEM65ni4+NRBMB8kDuVlZX/Hzly5D+IBrsbRMAkYGyAAAMAB7YiCOfAQ0cAAAAASUVORK5CYII=", + "iVBORw0KGgoAAAANSUhEUgAAAAUAAAAKCAYAAAB8OZQwAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAADdJREFUeNpi/P//PwM6YGLAAmghyPIfi/VMXFxcKAJgPkghBwfH/3///v0H0WCNIAImAWMDBBgA09Igc2M/ueMAAAAASUVORK5CYII=", + "iVBORw0KGgoAAAANSUhEUgAAAAgAAAAECAYAAACzzX7wAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAACJJREFUeNpi/P//PwM+wHL06FG8KpgYCABGZWVlvCYABBgA7/sHvGw+cz8AAAAASUVORK5CYII=", + "iVBORw0KGgoAAAANSUhEUgAAAAgAAAAECAYAAACzzX7wAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAACBJREFUeNpi/P//PwM+wPKfgAomBgKAhYuLC68CgAADAAxjByOjCHIRAAAAAElFTkSuQmCC", + "iVBORw0KGgoAAAANSUhEUgAAAAcAAAAFCAYAAACJmvbYAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAERJREFUeNpiVFZW/u/i4sLw4sULBhiQkJBg2LNnDwMTAx6AV5IFRLx9+xZsFAyA+CDA+P//fwYVFZX/6Lru3LnDCBBgAEqlFEYRrf2nAAAAAElFTkSuQmCC", + "iVBORw0KGgoAAAANSUhEUgAAAAcAAAAFCAYAAACJmvbYAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAEFJREFUeNpiFBER+f/jxw8GNjY2Bhj49esXAwcHBwMTAx6AV5IFRPz58wdFEMZn/P//P4OoqOh/dF2vX79mBAgwADpeFCsbeaC+AAAAAElFTkSuQmCC", + "iVBORw0KGgoAAAANSUhEUgAAAAcAAAAHCAYAAADEUlfTAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAExJREFUeNpi/P//P4OKisp/BjRw584dRhaQhKGhIYOwsDBc4u3bt2ANLCAOSOLFixdwSQkJCTDNxIAH4JVkgdkBMwrGBwFGfK4FCDAAV1AdhemEguIAAAAASUVORK5CYII=", + "iVBORw0KGgoAAAANSUhEUgAAAAcAAAAHCAYAAADEUlfTAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAElJREFUeNp8jjEKADEIBNdDrCz1/w+0tRQMOchxpHC6dVhW6m64e+MiIojMrDMTzPyJqoKq4r1sISJ3GQ8GRsln48/JNH27BBgAUhQbSyMxqzEAAAAASUVORK5CYII=", + "iVBORw0KGgoAAAANSUhEUgAAAAUAAAAECAYAAABGM/VAAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAADtJREFUeNpi/P//P4OKisp/Bii4c+cOIwtIQE9Pj+HLly9gQRCfBcQACbx69QqmmAEseO/ePQZkABBgAD04FXsmmijSAAAAAElFTkSuQmCC", + "iVBORw0KGgoAAAANSUhEUgAAAAUAAAAECAYAAABGM/VAAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAD1JREFUeNpi/P//P4OKisp/Bii4c+cOIwtIwMXFheHFixcMEhISYAVMINm3b9+CBUA0CDCiazc0NGQECDAAdH0YelA27kgAAAAASUVORK5CYII=", + "iVBORw0KGgoAAAANSUhEUgAAAAUAAAAECAYAAABGM/VAAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAACZJREFUeNpi/P//vxQDGmABEffv3/8ME1BUVORlYsACGLFpBwgwABaWCjfQEetnAAAAAElFTkSuQmCC", + "iVBORw0KGgoAAAANSUhEUgAAAAkAAAAFCAYAAACXU8ZrAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAACRJREFUeNpizM3N/c9AADAqKysTVMTi5eXFSFAREFPHOoAAAwBCfwcAO8g48QAAAABJRU5ErkJggg==", + }; + + /// + /// Gets light or dark version of the specified texture. + /// + /// + /// + public static Texture2D GetTexture(ReorderableListTexture name) { + return s_Cached[(int)name]; + } + + #endregion + + #region Generated Resources + + public static Texture2D texHighlightColor { get; private set; } + + /// + /// Generate special textures. + /// + private static void GenerateSpecialTextures() { + texHighlightColor = CreatePixelTexture("(Generated) Highlight Color", ReorderableListStyles.SelectionBackgroundColor); + } + + /// + /// Create 1x1 pixel texture of specified color. + /// + /// Name for texture object. + /// Pixel color. + /// + /// The new Texture2D instance. + /// + public static Texture2D CreatePixelTexture(string name, Color color) { + var tex = new Texture2D(1, 1, TextureFormat.ARGB32, false, true); + tex.name = name; + tex.hideFlags = HideFlags.HideAndDontSave; + tex.filterMode = FilterMode.Point; + tex.SetPixel(0, 0, color); + tex.Apply(); + return tex; + } + + #endregion + + #region Load PNG from Base-64 Encoded String + + private static Texture2D[] s_Cached; + + /// + /// Read textures from base-64 encoded strings. Automatically selects assets based + /// upon whether the light or dark (pro) skin is active. + /// + private static void LoadResourceAssets() { + var skin = EditorGUIUtility.isProSkin ? s_DarkSkin : s_LightSkin; + s_Cached = new Texture2D[skin.Length]; + + for (int i = 0; i < s_Cached.Length; ++i) { + // Get image data (PNG) from base64 encoded strings. + byte[] imageData = Convert.FromBase64String(skin[i]); + + // Gather image size from image data. + int texWidth, texHeight; + GetImageSize(imageData, out texWidth, out texHeight); + + // Generate texture asset. + var tex = new Texture2D(texWidth, texHeight, TextureFormat.ARGB32, false, true); + tex.hideFlags = HideFlags.HideAndDontSave; + tex.name = "(Generated) ReorderableList:" + i; + tex.filterMode = FilterMode.Point; +#if UNITY_2017_1_OR_NEWER + ImageConversion.LoadImage(tex, imageData, markNonReadable: true); +#else + tex.LoadImage(imageData); +#endif + + s_Cached[i] = tex; + } + + s_LightSkin = null; + s_DarkSkin = null; + } + + /// + /// Read width and height if PNG file in pixels. + /// + /// PNG image data. + /// Width of image in pixels. + /// Height of image in pixels. + private static void GetImageSize(byte[] imageData, out int width, out int height) { + width = ReadInt(imageData, 3 + 15); + height = ReadInt(imageData, 3 + 15 + 2 + 2); + } + + private static int ReadInt(byte[] imageData, int offset) { + return (imageData[offset] << 8) | imageData[offset + 1]; + } + + #endregion + + } + +} diff --git a/Assets/Fungus/Thirdparty/Reorderable List Field/Editor/Internal/ReorderableListResources.cs.meta b/Assets/Fungus/Thirdparty/Reorderable List Field/Editor/Internal/ReorderableListResources.cs.meta new file mode 100644 index 00000000..23933194 --- /dev/null +++ b/Assets/Fungus/Thirdparty/Reorderable List Field/Editor/Internal/ReorderableListResources.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 1d9acb5346b0f3c478d5678c6a0e4f42 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Fungus/Thirdparty/Reorderable List Field/Editor/Internal/SerializedPropertyUtility.cs b/Assets/Fungus/Thirdparty/Reorderable List Field/Editor/Internal/SerializedPropertyUtility.cs new file mode 100644 index 00000000..ccd51f97 --- /dev/null +++ b/Assets/Fungus/Thirdparty/Reorderable List Field/Editor/Internal/SerializedPropertyUtility.cs @@ -0,0 +1,179 @@ +// Copyright (c) Rotorz Limited. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root. + +using System; +using UnityEditor; +using UnityEngine; + +namespace Rotorz.ReorderableList.Internal { + + /// + /// Utility functionality for implementations. + /// + public static class SerializedPropertyUtility { + + /// + /// Reset the value of a property. + /// + /// Serialized property for a serialized property. + public static void ResetValue(SerializedProperty property) { + if (property == null) + throw new ArgumentNullException("property"); + + switch (property.propertyType) { + case SerializedPropertyType.Integer: + property.intValue = 0; + break; + case SerializedPropertyType.Boolean: + property.boolValue = false; + break; + case SerializedPropertyType.Float: + property.floatValue = 0f; + break; + case SerializedPropertyType.String: + property.stringValue = ""; + break; + case SerializedPropertyType.Color: + property.colorValue = Color.black; + break; + case SerializedPropertyType.ObjectReference: + property.objectReferenceValue = null; + break; + case SerializedPropertyType.LayerMask: + property.intValue = 0; + break; + case SerializedPropertyType.Enum: + property.enumValueIndex = 0; + break; + case SerializedPropertyType.Vector2: + property.vector2Value = default(Vector2); + break; + case SerializedPropertyType.Vector3: + property.vector3Value = default(Vector3); + break; + case SerializedPropertyType.Vector4: + property.vector4Value = default(Vector4); + break; + case SerializedPropertyType.Rect: + property.rectValue = default(Rect); + break; + case SerializedPropertyType.ArraySize: + property.intValue = 0; + break; + case SerializedPropertyType.Character: + property.intValue = 0; + break; + case SerializedPropertyType.AnimationCurve: + property.animationCurveValue = AnimationCurve.Linear(0f, 0f, 1f, 1f); + break; + case SerializedPropertyType.Bounds: + property.boundsValue = default(Bounds); + break; + case SerializedPropertyType.Gradient: + //!TODO: Amend when Unity add a public API for setting the gradient. + break; + } + + if (property.isArray) { + property.arraySize = 0; + } + + ResetChildPropertyValues(property); + } + + private static void ResetChildPropertyValues(SerializedProperty element) { + if (!element.hasChildren) + return; + + var childProperty = element.Copy(); + int elementPropertyDepth = element.depth; + bool enterChildren = true; + + while (childProperty.Next(enterChildren) && childProperty.depth > elementPropertyDepth) { + enterChildren = false; + ResetValue(childProperty); + } + } + + /// + /// Copies value of into . + /// + /// Destination property. + /// Source property. + public static void CopyPropertyValue(SerializedProperty destProperty, SerializedProperty sourceProperty) { + if (destProperty == null) + throw new ArgumentNullException("destProperty"); + if (sourceProperty == null) + throw new ArgumentNullException("sourceProperty"); + + sourceProperty = sourceProperty.Copy(); + destProperty = destProperty.Copy(); + + CopyPropertyValueSingular(destProperty, sourceProperty); + + if (sourceProperty.hasChildren) { + int elementPropertyDepth = sourceProperty.depth; + while (sourceProperty.Next(true) && destProperty.Next(true) && sourceProperty.depth > elementPropertyDepth) + CopyPropertyValueSingular(destProperty, sourceProperty); + } + } + + private static void CopyPropertyValueSingular(SerializedProperty destProperty, SerializedProperty sourceProperty) { + switch (destProperty.propertyType) { + case SerializedPropertyType.Integer: + destProperty.intValue = sourceProperty.intValue; + break; + case SerializedPropertyType.Boolean: + destProperty.boolValue = sourceProperty.boolValue; + break; + case SerializedPropertyType.Float: + destProperty.floatValue = sourceProperty.floatValue; + break; + case SerializedPropertyType.String: + destProperty.stringValue = sourceProperty.stringValue; + break; + case SerializedPropertyType.Color: + destProperty.colorValue = sourceProperty.colorValue; + break; + case SerializedPropertyType.ObjectReference: + destProperty.objectReferenceValue = sourceProperty.objectReferenceValue; + break; + case SerializedPropertyType.LayerMask: + destProperty.intValue = sourceProperty.intValue; + break; + case SerializedPropertyType.Enum: + destProperty.enumValueIndex = sourceProperty.enumValueIndex; + break; + case SerializedPropertyType.Vector2: + destProperty.vector2Value = sourceProperty.vector2Value; + break; + case SerializedPropertyType.Vector3: + destProperty.vector3Value = sourceProperty.vector3Value; + break; + case SerializedPropertyType.Vector4: + destProperty.vector4Value = sourceProperty.vector4Value; + break; + case SerializedPropertyType.Rect: + destProperty.rectValue = sourceProperty.rectValue; + break; + case SerializedPropertyType.ArraySize: + destProperty.intValue = sourceProperty.intValue; + break; + case SerializedPropertyType.Character: + destProperty.intValue = sourceProperty.intValue; + break; + case SerializedPropertyType.AnimationCurve: + destProperty.animationCurveValue = sourceProperty.animationCurveValue; + break; + case SerializedPropertyType.Bounds: + destProperty.boundsValue = sourceProperty.boundsValue; + break; + case SerializedPropertyType.Gradient: + //!TODO: Amend when Unity add a public API for setting the gradient. + break; + } + } + + } + +} diff --git a/Assets/Fungus/Thirdparty/Reorderable List Field/Editor/Internal/SerializedPropertyUtility.cs.meta b/Assets/Fungus/Thirdparty/Reorderable List Field/Editor/Internal/SerializedPropertyUtility.cs.meta new file mode 100644 index 00000000..e1ea9387 --- /dev/null +++ b/Assets/Fungus/Thirdparty/Reorderable List Field/Editor/Internal/SerializedPropertyUtility.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: e720cba766c708b40a725fddfbdb4436 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Fungus/Thirdparty/Reorderable List Field/Editor/ReorderableListControl.cs b/Assets/Fungus/Thirdparty/Reorderable List Field/Editor/ReorderableListControl.cs new file mode 100644 index 00000000..b8bc8744 --- /dev/null +++ b/Assets/Fungus/Thirdparty/Reorderable List Field/Editor/ReorderableListControl.cs @@ -0,0 +1,2000 @@ +// Copyright (c) Rotorz Limited. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root. + +using Rotorz.ReorderableList.Internal; +using System.Collections.Generic; +using UnityEditor; +using UnityEngine; + +namespace Rotorz.ReorderableList { + + /// + /// Base class for custom reorderable list control. + /// + public class ReorderableListControl { + + /// + /// Invoked to draw list item. + /// + /// + /// GUI controls must be positioned absolutely within the given rectangle since + /// list items must be sized consistently. + /// + /// + /// The following listing presents a text field for each list item: + /// wishlist = new List(); + /// + /// private void OnGUI() { + /// ReorderableListGUI.ListField(wishlist, DrawListItem); + /// } + /// + /// private string DrawListItem(Rect position, string value) { + /// // Text fields do not like `null` values! + /// if (value == null) + /// value = ""; + /// return EditorGUI.TextField(position, value); + /// } + /// } + /// ]]> + /// ; + /// + /// function OnGUI() { + /// ReorderableListGUI.ListField(wishlist, DrawListItem); + /// } + /// + /// function DrawListItem(position:Rect, value:String):String { + /// // Text fields do not like `null` values! + /// if (value == null) + /// value = ''; + /// return EditorGUI.TextField(position, value); + /// } + /// } + /// ]]> + /// + /// Type of item list. + /// Position of list item. + /// The list item. + /// + /// The modified value. + /// + public delegate T ItemDrawer(Rect position, T item); + + /// + /// Invoked to draw content for empty list. + /// + /// + /// Callback should make use of GUILayout to present controls. + /// + /// + /// The following listing displays a label for empty list control: + /// _list; + /// + /// private void OnEnable() { + /// _list = new List(); + /// } + /// private void OnGUI() { + /// ReorderableListGUI.ListField(_list, ReorderableListGUI.TextFieldItemDrawer, DrawEmptyMessage); + /// } + /// + /// private string DrawEmptyMessage() { + /// GUILayout.Label("List is empty!", EditorStyles.miniLabel); + /// } + /// } + /// ]]> + /// ; + /// + /// function OnEnable() { + /// _list = new List.(); + /// } + /// function OnGUI() { + /// ReorderableListGUI.ListField(_list, ReorderableListGUI.TextFieldItemDrawer, DrawEmptyMessage); + /// } + /// + /// function DrawEmptyMessage() { + /// GUILayout.Label('List is empty!', EditorStyles.miniLabel); + /// } + /// } + /// ]]> + /// + public delegate void DrawEmpty(); + /// + /// Invoked to draw content for empty list with absolute positioning. + /// + /// Position of empty content. + public delegate void DrawEmptyAbsolute(Rect position); + + #region Custom Styles + + /// + /// Background color of anchor list item. + /// + public static readonly Color AnchorBackgroundColor; + /// + /// Background color of target slot when dragging list item. + /// + public static readonly Color TargetBackgroundColor; + + /// + /// Style for right-aligned label for element number prefix. + /// + private static GUIStyle s_RightAlignedLabelStyle; + + static ReorderableListControl() { + s_CurrentListStack = new Stack(); + s_CurrentListStack.Push(default(ListInfo)); + + s_CurrentItemStack = new Stack(); + s_CurrentItemStack.Push(new ItemInfo(-1, default(Rect))); + + if (EditorGUIUtility.isProSkin) { + AnchorBackgroundColor = new Color(85f / 255f, 85f / 255f, 85f / 255f, 0.85f); + TargetBackgroundColor = new Color(0, 0, 0, 0.5f); + } + else { + AnchorBackgroundColor = new Color(225f / 255f, 225f / 255f, 225f / 255f, 0.85f); + TargetBackgroundColor = new Color(0, 0, 0, 0.5f); + } + } + + #endregion + + #region Utility + + private static readonly int s_ReorderableListControlHint = "_ReorderableListControl_".GetHashCode(); + + private static int GetReorderableListControlID() { + return GUIUtility.GetControlID(s_ReorderableListControlHint, FocusType.Passive); + } + + /// + /// Generate and draw control from state object. + /// + /// Reorderable list adaptor. + /// Delegate for drawing empty list. + /// Optional flags to pass into list field. + public static void DrawControlFromState(IReorderableListAdaptor adaptor, DrawEmpty drawEmpty, ReorderableListFlags flags) { + int controlID = GetReorderableListControlID(); + + var control = GUIUtility.GetStateObject(typeof(ReorderableListControl), controlID) as ReorderableListControl; + control.Flags = flags; + control.Draw(controlID, adaptor, drawEmpty); + } + + /// + /// Generate and draw control from state object. + /// + /// Position of control. + /// Reorderable list adaptor. + /// Delegate for drawing empty list. + /// Optional flags to pass into list field. + public static void DrawControlFromState(Rect position, IReorderableListAdaptor adaptor, DrawEmptyAbsolute drawEmpty, ReorderableListFlags flags) { + int controlID = GetReorderableListControlID(); + + var control = GUIUtility.GetStateObject(typeof(ReorderableListControl), controlID) as ReorderableListControl; + control.Flags = flags; + control.Draw(position, controlID, adaptor, drawEmpty); + } + + #endregion + + /// + /// Position of mouse upon anchoring item for drag. + /// + private static float s_AnchorMouseOffset; + /// + /// Zero-based index of anchored list item. + /// + private static int s_AnchorIndex = -1; + /// + /// Zero-based index of target list item for reordering. + /// + private static int s_TargetIndex = -1; + + /// + /// Unique ID of list control which should be automatically focused. A value + /// of zero indicates that no control is to be focused. + /// + private static int s_AutoFocusControlID = 0; + /// + /// Zero-based index of item which should be focused. + /// + private static int s_AutoFocusIndex = -1; + + private struct ListInfo { + public int ControlID; + public Rect Position; + + public ListInfo(int controlID, Rect position) { + ControlID = controlID; + Position = position; + } + } + + private struct ItemInfo { + public int ItemIndex; + public Rect ItemPosition; + + public ItemInfo(int itemIndex, Rect itemPosition) { + ItemIndex = itemIndex; + ItemPosition = itemPosition; + } + } + + /// + /// Represents the current stack of nested reorderable list control positions. + /// + private static Stack s_CurrentListStack; + + /// + /// Represents the current stack of nested reorderable list items. + /// + private static Stack s_CurrentItemStack; + + /// + /// Gets the control ID of the list that is currently being drawn. + /// + public static int CurrentListControlID { + get { return s_CurrentListStack.Peek().ControlID; } + } + + /// + /// Gets the position of the list control that is currently being drawn. + /// + /// + /// The value of this property should be ignored for + /// type events when using reorderable list controls with automatic layout. + /// + /// + public static Rect CurrentListPosition { + get { return s_CurrentListStack.Peek().Position; } + } + + /// + /// Gets the zero-based index of the list item that is currently being drawn; + /// or a value of -1 if no item is currently being drawn. + /// + /// + /// Use instead. + /// + internal static int CurrentItemIndex { + get { return s_CurrentItemStack.Peek().ItemIndex; } + } + + /// + /// Gets the total position of the list item that is currently being drawn. + /// + /// + /// The value of this property should be ignored for + /// type events when using reorderable list controls with automatic layout. + /// + /// + /// + public static Rect CurrentItemTotalPosition { + get { return s_CurrentItemStack.Peek().ItemPosition; } + } + + #region Properties + + private ReorderableListFlags _flags; + + /// + /// Gets or sets flags which affect behavior of control. + /// + public ReorderableListFlags Flags { + get { return _flags; } + set { _flags = value; } + } + + /// + /// Gets a value indicating whether any footer controls are shown. + /// + private bool HasFooterControls { + get { return HasSizeField || HasAddButton || HasAddMenuButton; } + } + /// + /// Gets a value indicating whether the size field is shown. + /// + private bool HasSizeField { + get { return (_flags & ReorderableListFlags.ShowSizeField) != 0; } + } + /// + /// Gets a value indicating whether add button is shown. + /// + private bool HasAddButton { + get { return (_flags & ReorderableListFlags.HideAddButton) == 0; } + } + /// + /// Gets a value indicating whether add menu button is shown. + /// + private bool HasAddMenuButton { get; set; } + + /// + /// Gets a value indicating whether remove buttons are shown. + /// + private bool HasRemoveButtons { + get { return (_flags & ReorderableListFlags.HideRemoveButtons) == 0; } + } + + private float _verticalSpacing = 10f; + private GUIStyle _containerStyle; + private GUIStyle _footerButtonStyle; + private GUIStyle _itemButtonStyle; + + /// + /// Gets or sets the vertical spacing below the reorderable list control. + /// + public float VerticalSpacing { + get { return _verticalSpacing; } + set { _verticalSpacing = value; } + } + /// + /// Gets or sets style used to draw background of list control. + /// + /// + public GUIStyle ContainerStyle { + get { return _containerStyle; } + set { _containerStyle = value; } + } + /// + /// Gets or sets style used to draw footer buttons. + /// + /// + public GUIStyle FooterButtonStyle { + get { return _footerButtonStyle; } + set { _footerButtonStyle = value; } + } + /// + /// Gets or sets style used to draw list item buttons (like the remove button). + /// + /// + public GUIStyle ItemButtonStyle { + get { return _itemButtonStyle; } + set { _itemButtonStyle = value; } + } + + private Color _horizontalLineColor; + private bool _horizontalLineAtStart = false; + private bool _horizontalLineAtEnd = false; + + /// + /// Gets or sets the color of the horizontal lines that appear between list items. + /// + public Color HorizontalLineColor { + get { return _horizontalLineColor; } + set { _horizontalLineColor = value; } + } + + /// + /// Gets or sets a boolean value indicating whether a horizontal line should be + /// shown above the first list item at the start of the list control. + /// + /// + /// Horizontal line is not drawn for an empty list regardless of the value + /// of this property. + /// + public bool HorizontalLineAtStart { + get { return _horizontalLineAtStart; } + set { _horizontalLineAtStart = value; } + } + + /// + /// Gets or sets a boolean value indicating whether a horizontal line should be + /// shown below the last list item at the end of the list control. + /// + /// + /// Horizontal line is not drawn for an empty list regardless of the value + /// of this property. + /// + public bool HorizontalLineAtEnd { + get { return _horizontalLineAtEnd; } + set { _horizontalLineAtEnd = value; } + } + + #endregion + + #region Events + + private event AddMenuClickedEventHandler _addMenuClicked; + private int _addMenuClickedSubscriberCount = 0; + + /// + /// Occurs when add menu button is clicked. + /// + /// + /// Add menu button is only shown when there is at least one subscriber to this event. + /// + public event AddMenuClickedEventHandler AddMenuClicked { + add { + if (value == null) + return; + _addMenuClicked += value; + ++_addMenuClickedSubscriberCount; + HasAddMenuButton = _addMenuClickedSubscriberCount != 0; + } + remove { + if (value == null) + return; + _addMenuClicked -= value; + --_addMenuClickedSubscriberCount; + HasAddMenuButton = _addMenuClickedSubscriberCount != 0; + } + } + + /// + /// Raises event when add menu button is clicked. + /// + /// Event arguments. + protected virtual void OnAddMenuClicked(AddMenuClickedEventArgs args) { + if (_addMenuClicked != null) + _addMenuClicked(this, args); + } + + /// + /// Occurs after list item is inserted or duplicated. + /// + public event ItemInsertedEventHandler ItemInserted; + + /// + /// Raises event after list item is inserted or duplicated. + /// + /// Event arguments. + protected virtual void OnItemInserted(ItemInsertedEventArgs args) { + if (ItemInserted != null) + ItemInserted(this, args); + } + + /// + /// Occurs before list item is removed and allowing for remove operation to be cancelled. + /// + public event ItemRemovingEventHandler ItemRemoving; + + /// + /// Raises event before list item is removed and provides oppertunity to cancel. + /// + /// Event arguments. + protected virtual void OnItemRemoving(ItemRemovingEventArgs args) { + if (ItemRemoving != null) + ItemRemoving(this, args); + } + + /// + /// Occurs immediately before list item is moved allowing for move operation to be cancelled. + /// + public event ItemMovingEventHandler ItemMoving; + + /// + /// Raises event immediately before list item is moved and provides oppertunity to cancel. + /// + /// Event arguments. + protected virtual void OnItemMoving(ItemMovingEventArgs args) { + if (ItemMoving != null) + ItemMoving(this, args); + } + + /// + /// Occurs after list item has been moved. + /// + public event ItemMovedEventHandler ItemMoved; + + /// + /// Raises event after list item has been moved. + /// + /// Event arguments. + protected virtual void OnItemMoved(ItemMovedEventArgs args) { + if (ItemMoved != null) + ItemMoved(this, args); + } + + #endregion + + #region Construction + + /// + /// Initializes a new instance of . + /// + public ReorderableListControl() { + _containerStyle = ReorderableListStyles.Container; + _footerButtonStyle = ReorderableListStyles.FooterButton; + _itemButtonStyle = ReorderableListStyles.ItemButton; + + _horizontalLineColor = ReorderableListStyles.HorizontalLineColor; + } + + /// + /// Initializes a new instance of . + /// + /// Optional flags which affect behavior of control. + public ReorderableListControl(ReorderableListFlags flags) + : this() { + this.Flags = flags; + } + + #endregion + + #region Control State + + /// + /// Unique Id of control. + /// + private int _controlID; + /// + /// Visible rectangle of control. + /// + private Rect _visibleRect; + /// + /// Width of index label in pixels (zero indicates no label). + /// + private float _indexLabelWidth; + /// + /// Indicates whether item is currently being dragged within control. + /// + private bool _tracking; + /// + /// Indicates if reordering is allowed. + /// + private bool _allowReordering; + + /// + /// A boolean value indicating whether drop insertion is allowed. + /// + private bool _allowDropInsertion; + /// + /// Zero-based index for drop insertion when applicable; othewise, a value of -1. + /// + private int _insertionIndex; + /// + /// Position of drop insertion on Y-axis in GUI space. + /// + private float _insertionPosition; + + /// + /// New size input value. + /// + private int _newSizeInput; + + /// + /// Prepare initial state for list control. + /// + /// Unique ID of list control. + /// Reorderable list adaptor. + private void PrepareState(int controlID, IReorderableListAdaptor adaptor) { + _controlID = controlID; + _visibleRect = GUIHelper.VisibleRect(); + + if ((Flags & ReorderableListFlags.ShowIndices) != 0) + _indexLabelWidth = CountDigits(adaptor.Count) * 8 + 8; + else + _indexLabelWidth = 0; + + _tracking = IsTrackingControl(controlID); + + _allowReordering = (Flags & ReorderableListFlags.DisableReordering) == 0; + + // The value of this field is reset each time the control is drawn and may + // be invalidated when list items are drawn. + _allowDropInsertion = true; + } + + private static int CountDigits(int number) { + return Mathf.Max(2, Mathf.CeilToInt(Mathf.Log10((float)number))); + } + + #endregion + + #region Event Handling + + // Indicates whether a "MouseDrag" event should be simulated on the next Layout/Repaint. + private static int s_SimulateMouseDragControlID; + + /// + /// Indicate that first control of list item should be automatically focused + /// if possible. + /// + /// Unique ID of list control. + /// Zero-based index of list item. + private void AutoFocusItem(int controlID, int itemIndex) { + if ((Flags & ReorderableListFlags.DisableAutoFocus) == 0) { + s_AutoFocusControlID = controlID; + s_AutoFocusIndex = itemIndex; + } + } + + /// + /// Draw remove button. + /// + /// Position of button. + /// Indicates if control is visible within GUI. + /// + /// A value of true if clicked; otherwise false. + /// + private bool DoRemoveButton(Rect position, bool visible) { + var iconNormal = ReorderableListResources.GetTexture(ReorderableListTexture.Icon_Remove_Normal); + var iconActive = ReorderableListResources.GetTexture(ReorderableListTexture.Icon_Remove_Active); + + return GUIHelper.IconButton(position, visible, iconNormal, iconActive, ItemButtonStyle); + } + + private static bool s_TrackingCancelBlockContext; + + /// + /// Begin tracking drag and drop within list. + /// + /// Unique ID of list control. + /// Zero-based index of item which is going to be dragged. + private static void BeginTrackingReorderDrag(int controlID, int itemIndex) { + GUIUtility.hotControl = controlID; + GUIUtility.keyboardControl = 0; + s_AnchorIndex = itemIndex; + s_TargetIndex = itemIndex; + s_TrackingCancelBlockContext = false; + } + + /// + /// Stop tracking drag and drop. + /// + private static void StopTrackingReorderDrag() { + GUIUtility.hotControl = 0; + s_AnchorIndex = -1; + s_TargetIndex = -1; + } + + /// + /// Gets a value indicating whether item in current list is currently being tracked. + /// + /// Unique ID of list control. + /// + /// A value of true if item is being tracked; otherwise false. + /// + private static bool IsTrackingControl(int controlID) { + return !s_TrackingCancelBlockContext && GUIUtility.hotControl == controlID; + } + + /// + /// Accept reordering. + /// + /// Reorderable list adaptor. + private void AcceptReorderDrag(IReorderableListAdaptor adaptor) { + try { + // Reorder list as needed! + s_TargetIndex = Mathf.Clamp(s_TargetIndex, 0, adaptor.Count + 1); + if (s_TargetIndex != s_AnchorIndex && s_TargetIndex != s_AnchorIndex + 1) + MoveItem(adaptor, s_AnchorIndex, s_TargetIndex); + } + finally { + StopTrackingReorderDrag(); + } + } + + private static Rect s_DragItemPosition; + + // Micro-optimisation to avoid repeated construction. + private static Rect s_RemoveButtonPosition; + + private void DrawListItem(Rect position, IReorderableListAdaptor adaptor, int itemIndex) { + bool isRepainting = Event.current.type == EventType.Repaint; + bool isVisible = (position.y < _visibleRect.yMax && position.yMax > _visibleRect.y); + bool isDraggable = _allowReordering && adaptor.CanDrag(itemIndex); + + Rect itemContentPosition = position; + itemContentPosition.x = position.x + 2; + itemContentPosition.y += 1; + itemContentPosition.width = position.width - 4; + itemContentPosition.height = position.height - 4; + + // Make space for grab handle? + if (isDraggable) { + itemContentPosition.x += 20; + itemContentPosition.width -= 20; + } + + // Make space for element index. + if (_indexLabelWidth != 0) { + itemContentPosition.width -= _indexLabelWidth; + + if (isRepainting && isVisible) + s_RightAlignedLabelStyle.Draw(new Rect(itemContentPosition.x, position.y, _indexLabelWidth, position.height - 4), itemIndex + ":", false, false, false, false); + + itemContentPosition.x += _indexLabelWidth; + } + + // Make space for remove button? + if (HasRemoveButtons) + itemContentPosition.width -= 27; + + try { + s_CurrentItemStack.Push(new ItemInfo(itemIndex, position)); + EditorGUI.BeginChangeCheck(); + + if (isRepainting && isVisible) { + // Draw background of list item. + var backgroundPosition = new Rect(position.x, position.y, position.width, position.height - 1); + adaptor.DrawItemBackground(backgroundPosition, itemIndex); + + // Draw grab handle? + if (isDraggable) { + var texturePosition = new Rect(position.x + 6, position.y + position.height / 2f - 3, 9, 5); + GUIHelper.DrawTexture(texturePosition, ReorderableListResources.GetTexture(ReorderableListTexture.GrabHandle)); + } + + // Draw horizontal line between list items. + if (!_tracking || itemIndex != s_AnchorIndex) { + if (itemIndex != 0 || HorizontalLineAtStart) { + var horizontalLinePosition = new Rect(position.x, position.y - 1, position.width, 1); + GUIHelper.Separator(horizontalLinePosition, HorizontalLineColor); + } + } + } + + // Allow control to be automatically focused. + if (s_AutoFocusIndex == itemIndex) + GUI.SetNextControlName("AutoFocus_" + _controlID + "_" + itemIndex); + + // Present actual control. + adaptor.DrawItem(itemContentPosition, itemIndex); + + if (EditorGUI.EndChangeCheck()) + ReorderableListGUI.IndexOfChangedItem = itemIndex; + + // Draw remove button? + if (HasRemoveButtons && adaptor.CanRemove(itemIndex)) { + s_RemoveButtonPosition = position; + s_RemoveButtonPosition.width = 27; + s_RemoveButtonPosition.x = itemContentPosition.xMax + 2; + s_RemoveButtonPosition.y -= 1; + + if (DoRemoveButton(s_RemoveButtonPosition, isVisible)) + RemoveItem(adaptor, itemIndex); + } + + // Check for context click? + if ((Flags & ReorderableListFlags.DisableContextMenu) == 0) { + if (Event.current.GetTypeForControl(_controlID) == EventType.ContextClick && position.Contains(Event.current.mousePosition)) { + ShowContextMenu(itemIndex, adaptor); + Event.current.Use(); + } + } + } + finally { + s_CurrentItemStack.Pop(); + } + } + + private void DrawFloatingListItem(IReorderableListAdaptor adaptor, float targetSlotPosition) { + if (Event.current.type == EventType.Repaint) { + Color restoreColor = GUI.color; + + // Fill background of target area. + Rect targetPosition = s_DragItemPosition; + targetPosition.y = targetSlotPosition - 1; + targetPosition.height = 1; + + GUIHelper.Separator(targetPosition, HorizontalLineColor); + + --targetPosition.x; + ++targetPosition.y; + targetPosition.width += 2; + targetPosition.height = s_DragItemPosition.height - 1; + + GUI.color = TargetBackgroundColor; + GUIHelper.DrawTexture(targetPosition, EditorGUIUtility.whiteTexture); + + // Fill background of item which is being dragged. + --s_DragItemPosition.x; + s_DragItemPosition.width += 2; + --s_DragItemPosition.height; + + GUI.color = AnchorBackgroundColor; + GUIHelper.DrawTexture(s_DragItemPosition, EditorGUIUtility.whiteTexture); + + ++s_DragItemPosition.x; + s_DragItemPosition.width -= 2; + ++s_DragItemPosition.height; + + // Draw horizontal splitter above and below. + GUI.color = new Color(0f, 0f, 0f, 0.6f); + targetPosition.y = s_DragItemPosition.y - 1; + targetPosition.height = 1; + GUIHelper.DrawTexture(targetPosition, EditorGUIUtility.whiteTexture); + + targetPosition.y += s_DragItemPosition.height; + GUIHelper.DrawTexture(targetPosition, EditorGUIUtility.whiteTexture); + + GUI.color = restoreColor; + } + + DrawListItem(s_DragItemPosition, adaptor, s_AnchorIndex); + } + + // Counter is incremented whenever a reorderable list control reacts as a drop + // target allowing parent reorderable list controls to suppress any reaction that + // they might otherwise have. + private static int s_DropTargetNestedCounter = 0; + + /// + /// Draw list container and items. + /// + /// Position of list control in GUI. + /// Reorderable list adaptor. + private void DrawListContainerAndItems(Rect position, IReorderableListAdaptor adaptor) { + int initialDropTargetNestedCounterValue = s_DropTargetNestedCounter; + + // Get local copy of event information for efficiency. + EventType eventType = Event.current.GetTypeForControl(_controlID); + Vector2 mousePosition = Event.current.mousePosition; + + int newTargetIndex = s_TargetIndex; + + // Position of first item in list. + float firstItemY = position.y + ContainerStyle.padding.top; + // Maximum position of dragged item. + float dragItemMaxY = (position.yMax - ContainerStyle.padding.bottom) - s_DragItemPosition.height + 1; + + bool isMouseDragEvent = eventType == EventType.MouseDrag; + if (s_SimulateMouseDragControlID == _controlID && eventType == EventType.Repaint) { + s_SimulateMouseDragControlID = 0; + isMouseDragEvent = true; + } + if (isMouseDragEvent && _tracking) { + // Reset target index and adjust when looping through list items. + if (mousePosition.y < firstItemY) + newTargetIndex = 0; + else if (mousePosition.y >= position.yMax) + newTargetIndex = adaptor.Count; + + s_DragItemPosition.y = Mathf.Clamp(mousePosition.y + s_AnchorMouseOffset, firstItemY, dragItemMaxY); + } + + switch (eventType) { + case EventType.MouseDown: + if (_tracking) { + // Cancel drag when other mouse button is pressed. + s_TrackingCancelBlockContext = true; + Event.current.Use(); + } + break; + + case EventType.MouseUp: + if (_controlID == GUIUtility.hotControl) { + // Allow user code to change control over reordering during drag. + if (!s_TrackingCancelBlockContext && _allowReordering) + AcceptReorderDrag(adaptor); + else + StopTrackingReorderDrag(); + Event.current.Use(); + } + break; + + case EventType.KeyDown: + if (_tracking && Event.current.keyCode == KeyCode.Escape) { + StopTrackingReorderDrag(); + Event.current.Use(); + } + break; + + case EventType.ExecuteCommand: + if (s_ContextControlID == _controlID) { + int itemIndex = s_ContextItemIndex; + try { + DoCommand(s_ContextCommandName, itemIndex, adaptor); + Event.current.Use(); + } + finally { + s_ContextControlID = 0; + s_ContextItemIndex = 0; + } + } + break; + + case EventType.Repaint: + // Draw caption area of list. + ContainerStyle.Draw(position, GUIContent.none, false, false, false, false); + break; + } + + ReorderableListGUI.IndexOfChangedItem = -1; + + // Draw list items! + Rect itemPosition = new Rect(position.x + ContainerStyle.padding.left, firstItemY, position.width - ContainerStyle.padding.horizontal, 0); + float targetSlotPosition = dragItemMaxY; + + _insertionIndex = 0; + _insertionPosition = itemPosition.yMax; + + float lastMidPoint = 0f; + float lastHeight = 0f; + + int count = adaptor.Count; + for (int i = 0; i < count; ++i) { + itemPosition.y = itemPosition.yMax; + itemPosition.height = 0; + + lastMidPoint = itemPosition.y - lastHeight / 2f; + + if (_tracking) { + // Does this represent the target index? + if (i == s_TargetIndex) { + targetSlotPosition = itemPosition.y; + itemPosition.y += s_DragItemPosition.height; + } + + // Do not draw item if it is currently being dragged. + // Draw later so that it is shown in front of other controls. + if (i == s_AnchorIndex) + continue; + + // Update position for current item. + itemPosition.height = adaptor.GetItemHeight(i) + 4; + lastHeight = itemPosition.height; + } + else { + // Update position for current item. + itemPosition.height = adaptor.GetItemHeight(i) + 4; + lastHeight = itemPosition.height; + + // Does this represent the drop insertion index? + float midpoint = itemPosition.y + itemPosition.height / 2f; + if (mousePosition.y > lastMidPoint && mousePosition.y <= midpoint) { + _insertionIndex = i; + _insertionPosition = itemPosition.y; + } + } + + if (_tracking && isMouseDragEvent) { + float midpoint = itemPosition.y + itemPosition.height / 2f; + + if (s_TargetIndex < i) { + if (s_DragItemPosition.yMax > lastMidPoint && s_DragItemPosition.yMax < midpoint) + newTargetIndex = i; + } + else if (s_TargetIndex > i) { + if (s_DragItemPosition.y > lastMidPoint && s_DragItemPosition.y < midpoint) + newTargetIndex = i; + } + + /*if (s_DragItemPosition.y > itemPosition.y && s_DragItemPosition.y <= midpoint) + newTargetIndex = i; + else if (s_DragItemPosition.yMax > midpoint && s_DragItemPosition.yMax <= itemPosition.yMax) + newTargetIndex = i + 1;*/ + } + + // Draw list item. + DrawListItem(itemPosition, adaptor, i); + + // Did list count change (i.e. item removed)? + if (adaptor.Count < count) { + // We assume that it was this item which was removed, so --i allows us + // to process the next item as usual. + count = adaptor.Count; + --i; + continue; + } + + // Event has already been used, skip to next item. + if (Event.current.type != EventType.Used) { + switch (eventType) { + case EventType.MouseDown: + if (GUI.enabled && itemPosition.Contains(mousePosition)) { + // Remove input focus from control before attempting a context click or drag. + GUIUtility.keyboardControl = 0; + + if (_allowReordering && adaptor.CanDrag(i) && Event.current.button == 0) { + s_DragItemPosition = itemPosition; + + BeginTrackingReorderDrag(_controlID, i); + s_AnchorMouseOffset = itemPosition.y - mousePosition.y; + s_TargetIndex = i; + + Event.current.Use(); + } + } + break; +/* DEBUG + case EventType.Repaint: + GUI.color = Color.red; + GUI.DrawTexture(new Rect(0, lastMidPoint, 10, 1), EditorGUIUtility.whiteTexture); + GUI.color = Color.yellow; + GUI.DrawTexture(new Rect(5, itemPosition.y + itemPosition.height / 2f, 10, 1), EditorGUIUtility.whiteTexture); + GUI.color = Color.white; + break; +//*/ + } + } + } + + if (HorizontalLineAtEnd) { + var horizontalLinePosition = new Rect(itemPosition.x, position.yMax - ContainerStyle.padding.vertical, itemPosition.width, 1); + GUIHelper.Separator(horizontalLinePosition, HorizontalLineColor); + } + + lastMidPoint = position.yMax - lastHeight / 2f; + + // Assume that drop insertion is not allowed at this time; we can change our + // mind a little further down ;) + _allowDropInsertion = false; + + // Item which is being dragged should be shown on top of other controls! + if (IsTrackingControl(_controlID)) { + if (isMouseDragEvent) { + if (s_DragItemPosition.yMax >= lastMidPoint) + newTargetIndex = count; + + s_TargetIndex = newTargetIndex; + + // Force repaint to occur so that dragging rectangle is visible. + // But only if this is a real MouseDrag event!! + if (eventType == EventType.MouseDrag) + Event.current.Use(); + } + + DrawFloatingListItem(adaptor, targetSlotPosition); +/* DEBUG + if (eventType == EventType.Repaint) { + GUI.color = Color.blue; + GUI.DrawTexture(new Rect(100, lastMidPoint, 20, 1), EditorGUIUtility.whiteTexture); + GUI.color = Color.white; + } +//*/ + } + else { + // Cannot react to drop insertion if a nested drop target has already reacted! + if (s_DropTargetNestedCounter == initialDropTargetNestedCounterValue) { + if (Event.current.mousePosition.y >= lastMidPoint) { + _insertionIndex = adaptor.Count; + _insertionPosition = itemPosition.yMax; + } + _allowDropInsertion = true; + } + } + + // Fake control to catch input focus if auto focus was not possible. + GUIUtility.GetControlID(FocusType.Keyboard); + + if (isMouseDragEvent && (Flags & ReorderableListFlags.DisableAutoScroll) == 0 && IsTrackingControl(_controlID)) + AutoScrollTowardsMouse(); + } + + private static bool ContainsRect(Rect a, Rect b) { + return a.Contains(new Vector2(b.xMin, b.yMin)) && a.Contains(new Vector2(b.xMax, b.yMax)); + } + + private void AutoScrollTowardsMouse() { + const float triggerPaddingInPixels = 8f; + const float maximumRangeInPixels = 4f; + + Rect visiblePosition = GUIHelper.VisibleRect(); + Vector2 mousePosition = Event.current.mousePosition; + Rect mouseRect = new Rect(mousePosition.x - triggerPaddingInPixels, mousePosition.y - triggerPaddingInPixels, triggerPaddingInPixels * 2, triggerPaddingInPixels * 2); + + if (!ContainsRect(visiblePosition, mouseRect)) { + if (mousePosition.y < visiblePosition.center.y) + mousePosition = new Vector2(mouseRect.xMin, mouseRect.yMin); + else + mousePosition = new Vector2(mouseRect.xMax, mouseRect.yMax); + + mousePosition.x = Mathf.Max(mousePosition.x - maximumRangeInPixels, mouseRect.xMax); + mousePosition.y = Mathf.Min(mousePosition.y + maximumRangeInPixels, mouseRect.yMax); + GUI.ScrollTo(new Rect(mousePosition.x, mousePosition.y, 1, 1)); + + s_SimulateMouseDragControlID = _controlID; + + var focusedWindow = EditorWindow.focusedWindow; + if (focusedWindow != null) + focusedWindow.Repaint(); + } + } + + private void HandleDropInsertion(Rect position, IReorderableListAdaptor adaptor) { + var target = adaptor as IReorderableListDropTarget; + if (target == null || !_allowDropInsertion) + return; + + if (target.CanDropInsert(_insertionIndex)) { + ++s_DropTargetNestedCounter; + + switch (Event.current.type) { + case EventType.DragUpdated: + DragAndDrop.visualMode = DragAndDropVisualMode.Move; + DragAndDrop.activeControlID = _controlID; + target.ProcessDropInsertion(_insertionIndex); + Event.current.Use(); + break; + + case EventType.DragPerform: + target.ProcessDropInsertion(_insertionIndex); + + DragAndDrop.AcceptDrag(); + DragAndDrop.activeControlID = 0; + Event.current.Use(); + break; + + default: + target.ProcessDropInsertion(_insertionIndex); + break; + } + + if (DragAndDrop.activeControlID == _controlID && Event.current.type == EventType.Repaint) + DrawDropIndicator(new Rect(position.x, _insertionPosition - 2, position.width, 3)); + } + } + + /// + /// Draws drop insertion indicator. + /// + /// + /// This method is only ever called during repaint events. + /// + /// Position if the drop indicator. + protected virtual void DrawDropIndicator(Rect position) { + GUIHelper.Separator(position); + } + + /// + /// Checks to see if list control needs to be automatically focused. + /// + private void CheckForAutoFocusControl() { + if (Event.current.type == EventType.Used) + return; + + // Automatically focus control! + if (s_AutoFocusControlID == _controlID) { + s_AutoFocusControlID = 0; + GUIHelper.FocusTextInControl("AutoFocus_" + _controlID + "_" + s_AutoFocusIndex); + s_AutoFocusIndex = -1; + } + } + + /// + /// Draw additional controls below list control and highlight drop target. + /// + /// Position of list control in GUI. + /// Reorderable list adaptor. + private void DrawFooterControls(Rect position, IReorderableListAdaptor adaptor) { + if (HasFooterControls) { + Rect buttonPosition = new Rect(position.xMax - 30, position.yMax - 1, 30, FooterButtonStyle.fixedHeight); + + Rect menuButtonPosition = buttonPosition; + var menuIconNormal = ReorderableListResources.GetTexture(ReorderableListTexture.Icon_AddMenu_Normal); + var menuIconActive = ReorderableListResources.GetTexture(ReorderableListTexture.Icon_AddMenu_Active); + + if (HasSizeField) { + // Draw size field. + Rect sizeFieldPosition = new Rect( + position.x, + position.yMax + 1, + Mathf.Max(150f, position.width / 3f), + 16f + ); + + DrawSizeFooterControl(sizeFieldPosition, adaptor); + } + + if (HasAddButton) { + // Draw add menu drop-down button. + if (HasAddMenuButton) { + menuButtonPosition.x = buttonPosition.xMax - 14; + menuButtonPosition.xMax = buttonPosition.xMax; + menuIconNormal = ReorderableListResources.GetTexture(ReorderableListTexture.Icon_Menu_Normal); + menuIconActive = ReorderableListResources.GetTexture(ReorderableListTexture.Icon_Menu_Active); + buttonPosition.width -= 5; + buttonPosition.x = menuButtonPosition.x - buttonPosition.width + 1; + } + + // Draw add item button. + var iconNormal = ReorderableListResources.GetTexture(ReorderableListTexture.Icon_Add_Normal); + var iconActive = ReorderableListResources.GetTexture(ReorderableListTexture.Icon_Add_Active); + + if (GUIHelper.IconButton(buttonPosition, true, iconNormal, iconActive, FooterButtonStyle)) { + // Append item to list. + GUIUtility.keyboardControl = 0; + AddItem(adaptor); + } + } + + if (HasAddMenuButton) { + // Draw add menu drop-down button. + if (GUIHelper.IconButton(menuButtonPosition, true, menuIconNormal, menuIconActive, FooterButtonStyle)) { + GUIUtility.keyboardControl = 0; + Rect totalAddButtonPosition = buttonPosition; + totalAddButtonPosition.xMax = position.xMax; + OnAddMenuClicked(new AddMenuClickedEventArgs(adaptor, totalAddButtonPosition)); + + // This will be helpful in many circumstances; including by default! + GUIUtility.ExitGUI(); + } + } + } + } + + private void DrawSizeFooterControl(Rect position, IReorderableListAdaptor adaptor) { + float restoreLabelWidth = EditorGUIUtility.labelWidth; + EditorGUIUtility.labelWidth = 60f; + + DrawSizeField(position, adaptor); + + EditorGUIUtility.labelWidth = restoreLabelWidth; + } + + /// + /// Cache of container heights mapped by control ID. + /// + private static Dictionary s_ContainerHeightCache = new Dictionary(); + + private Rect GetListRectWithAutoLayout(IReorderableListAdaptor adaptor, float padding) { + float totalHeight; + + // Calculate position of list field using layout engine. + if (Event.current.type == EventType.Layout) { + totalHeight = CalculateListHeight(adaptor); + s_ContainerHeightCache[_controlID] = totalHeight; + } + else { + totalHeight = s_ContainerHeightCache.ContainsKey(_controlID) + ? s_ContainerHeightCache[_controlID] + : 0; + } + + totalHeight += padding; + + return GUILayoutUtility.GetRect(GUIContent.none, ContainerStyle, GUILayout.Height(totalHeight)); + } + + /// + /// Do layout version of list field. + /// + /// Reorderable list adaptor. + /// Padding in pixels. + /// + /// Position of list container area in GUI (excludes footer area). + /// + private Rect DrawLayoutListField(IReorderableListAdaptor adaptor, float padding) { + Rect position = GetListRectWithAutoLayout(adaptor, padding); + + // Make room for footer buttons? + if (HasFooterControls) + position.height -= FooterButtonStyle.fixedHeight; + + // Make room for vertical spacing below footer buttons. + position.height -= VerticalSpacing; + + s_CurrentListStack.Push(new ListInfo(_controlID, position)); + try { + // Draw list as normal. + adaptor.BeginGUI(); + DrawListContainerAndItems(position, adaptor); + HandleDropInsertion(position, adaptor); + adaptor.EndGUI(); + } + finally { + s_CurrentListStack.Pop(); + } + + CheckForAutoFocusControl(); + + return position; + } + + /// + /// Draw content for empty list (layout version). + /// + /// Reorderable list adaptor. + /// Callback to draw empty content. + /// + /// Position of list container area in GUI (excludes footer area). + /// + private Rect DrawLayoutEmptyList(IReorderableListAdaptor adaptor, DrawEmpty drawEmpty) { + Rect position = EditorGUILayout.BeginVertical(ContainerStyle); + { + if (drawEmpty != null) + drawEmpty(); + else + Debug.LogError("Unexpected call to 'DrawLayoutEmptyList'"); + + s_CurrentListStack.Push(new ListInfo(_controlID, position)); + try { + adaptor.BeginGUI(); + _insertionIndex = 0; + _insertionPosition = position.y + 2; + HandleDropInsertion(position, adaptor); + adaptor.EndGUI(); + } + finally { + s_CurrentListStack.Pop(); + } + } + EditorGUILayout.EndVertical(); + + // Allow room for footer buttons? + if (HasFooterControls) + GUILayoutUtility.GetRect(0, FooterButtonStyle.fixedHeight - 1); + + return position; + } + + /// + /// Draw content for empty list (layout version). + /// + /// Position of list control in GUI. + /// Callback to draw empty content. + private void DrawEmptyListControl(Rect position, DrawEmptyAbsolute drawEmpty) { + if (Event.current.type == EventType.Repaint) + ContainerStyle.Draw(position, GUIContent.none, false, false, false, false); + + // Take padding into consideration when drawing empty content. + position = ContainerStyle.padding.Remove(position); + + if (drawEmpty != null) + drawEmpty(position); + } + + /// + /// Correct if for some reason one or more styles are missing! + /// + private void FixStyles() { + ContainerStyle = ContainerStyle ?? ReorderableListStyles.Container; + FooterButtonStyle = FooterButtonStyle ?? ReorderableListStyles.FooterButton; + ItemButtonStyle = ItemButtonStyle ?? ReorderableListStyles.ItemButton; + + if (s_RightAlignedLabelStyle == null) { + s_RightAlignedLabelStyle = new GUIStyle(GUI.skin.label); + s_RightAlignedLabelStyle.alignment = TextAnchor.MiddleRight; + s_RightAlignedLabelStyle.padding.right = 4; + } + } + + /// + /// Draw layout version of list control. + /// + /// Unique ID of list control. + /// Reorderable list adaptor. + /// Delegate for drawing empty list. + private void Draw(int controlID, IReorderableListAdaptor adaptor, DrawEmpty drawEmpty) { + FixStyles(); + PrepareState(controlID, adaptor); + + Rect position; + if (adaptor.Count > 0) + position = DrawLayoutListField(adaptor, 0f); + else if (drawEmpty == null) + position = DrawLayoutListField(adaptor, 5f); + else + position = DrawLayoutEmptyList(adaptor, drawEmpty); + + DrawFooterControls(position, adaptor); + } + + /// + public void Draw(IReorderableListAdaptor adaptor, DrawEmpty drawEmpty) { + int controlID = GetReorderableListControlID(); + Draw(controlID, adaptor, drawEmpty); + } + + /// + public void Draw(IReorderableListAdaptor adaptor) { + int controlID = GetReorderableListControlID(); + Draw(controlID, adaptor, null); + } + + /// + /// Draw list control with absolute positioning. + /// + /// Position of list control in GUI. + /// Unique ID of list control. + /// Reorderable list adaptor. + /// Delegate for drawing empty list. + private void Draw(Rect position, int controlID, IReorderableListAdaptor adaptor, DrawEmptyAbsolute drawEmpty) { + FixStyles(); + PrepareState(controlID, adaptor); + + // Allow for footer area. + if (HasFooterControls) + position.height -= FooterButtonStyle.fixedHeight; + + // Make room for vertical spacing below footer buttons. + position.height -= VerticalSpacing; + + s_CurrentListStack.Push(new ListInfo(_controlID, position)); + try { + adaptor.BeginGUI(); + + DrawListContainerAndItems(position, adaptor); + HandleDropInsertion(position, adaptor); + CheckForAutoFocusControl(); + + if (adaptor.Count == 0) { + ReorderableListGUI.IndexOfChangedItem = -1; + DrawEmptyListControl(position, drawEmpty); + } + + adaptor.EndGUI(); + } + finally { + s_CurrentListStack.Pop(); + } + + DrawFooterControls(position, adaptor); + } + + /// + /// Draw list control with absolute positioning. + /// + /// Position of list control in GUI. + /// Reorderable list adaptor. + /// Delegate for drawing empty list. + public void Draw(Rect position, IReorderableListAdaptor adaptor, DrawEmptyAbsolute drawEmpty) { + int controlID = GetReorderableListControlID(); + Draw(position, controlID, adaptor, drawEmpty); + } + + /// + public void Draw(Rect position, IReorderableListAdaptor adaptor) { + int controlID = GetReorderableListControlID(); + Draw(position, controlID, adaptor, null); + } + + #endregion + + #region Size Field + + private static readonly GUIContent s_Temp = new GUIContent(); + private static readonly GUIContent s_SizePrefixLabel = new GUIContent("Size"); + + /// + /// Draw list size field with absolute positioning and a custom prefix label. + /// + /// + /// Specify a value of GUIContent.none for argument + /// to omit prefix label from the drawn control. + /// + /// Position of list control in GUI. + /// Prefix label for the control. + /// Reorderable list adaptor. + public void DrawSizeField(Rect position, GUIContent label, IReorderableListAdaptor adaptor) { + int sizeControlID = GUIUtility.GetControlID(FocusType.Passive); + string sizeControlName = "ReorderableListControl.Size." + sizeControlID; + GUI.SetNextControlName(sizeControlName); + + if (GUI.GetNameOfFocusedControl() == sizeControlName) { + if (Event.current.rawType == EventType.KeyDown) { + switch (Event.current.keyCode) { + case KeyCode.Return: + case KeyCode.KeypadEnter: + ResizeList(adaptor, _newSizeInput); + Event.current.Use(); + break; + } + } + _newSizeInput = EditorGUI.IntField(position, label, _newSizeInput); + } + else { + EditorGUI.IntField(position, label, adaptor.Count); + _newSizeInput = adaptor.Count; + } + } + + /// + /// Draw list size field with absolute positioning and a custom prefix label. + /// + /// Position of list control in GUI. + /// Prefix label for the control. + /// Reorderable list adaptor. + public void DrawSizeField(Rect position, string label, IReorderableListAdaptor adaptor) { + s_Temp.text = label; + DrawSizeField(position, s_Temp, adaptor); + } + + /// + /// Draw list size field with absolute positioning with the default prefix label. + /// + /// Position of list control in GUI. + /// Reorderable list adaptor. + public void DrawSizeField(Rect position, IReorderableListAdaptor adaptor) { + DrawSizeField(position, s_SizePrefixLabel, adaptor); + } + + /// + /// Draw list size field with automatic layout and a custom prefix label. + /// + /// + /// Specify a value of GUIContent.none for argument + /// to omit prefix label from the drawn control. + /// + /// Prefix label for the control. + /// Reorderable list adaptor. + public void DrawSizeField(GUIContent label, IReorderableListAdaptor adaptor) { + Rect position = GUILayoutUtility.GetRect(0, EditorGUIUtility.singleLineHeight); + DrawSizeField(position, label, adaptor); + } + + /// + /// Draw list size field with automatic layout and a custom prefix label. + /// + /// Prefix label for the control. + /// Reorderable list adaptor. + public void DrawSizeField(string label, IReorderableListAdaptor adaptor) { + s_Temp.text = label; + DrawSizeField(s_Temp, adaptor); + } + + /// + /// Draw list size field with automatic layout and the default prefix label. + /// + /// Reorderable list adaptor. + public void DrawSizeField(IReorderableListAdaptor adaptor) { + DrawSizeField(s_SizePrefixLabel, adaptor); + } + + #endregion + + #region Context Menu + + /// + /// Content for "Move to Top" command. + /// + protected static readonly GUIContent CommandMoveToTop = new GUIContent("Move to Top"); + /// + /// Content for "Move to Bottom" command. + /// + protected static readonly GUIContent CommandMoveToBottom = new GUIContent("Move to Bottom"); + /// + /// Content for "Insert Above" command. + /// + protected static readonly GUIContent CommandInsertAbove = new GUIContent("Insert Above"); + /// + /// Content for "Insert Below" command. + /// + protected static readonly GUIContent CommandInsertBelow = new GUIContent("Insert Below"); + /// + /// Content for "Duplicate" command. + /// + protected static readonly GUIContent CommandDuplicate = new GUIContent("Duplicate"); + /// + /// Content for "Remove" command. + /// + protected static readonly GUIContent CommandRemove = new GUIContent("Remove"); + /// + /// Content for "Clear All" command. + /// + protected static readonly GUIContent CommandClearAll = new GUIContent("Clear All"); + + // Command control id and item index are assigned when context menu is shown. + private static int s_ContextControlID; + private static int s_ContextItemIndex; + + // Command name is assigned by default context menu handler. + private static string s_ContextCommandName; + + private void ShowContextMenu(int itemIndex, IReorderableListAdaptor adaptor) { + GenericMenu menu = new GenericMenu(); + + s_ContextControlID = _controlID; + s_ContextItemIndex = itemIndex; + + AddItemsToMenu(menu, itemIndex, adaptor); + + if (menu.GetItemCount() > 0) + menu.ShowAsContext(); + } + + /// + /// Default functionality to handle context command. + /// + /// + /// Can be used when adding custom items to the context menu: + /// + /// + /// + /// + protected static readonly GenericMenu.MenuFunction2 DefaultContextHandler = DefaultContextMenuHandler; + + private static void DefaultContextMenuHandler(object userData) { + var commandContent = userData as GUIContent; + if (commandContent == null || string.IsNullOrEmpty(commandContent.text)) + return; + + s_ContextCommandName = commandContent.text; + + var e = EditorGUIUtility.CommandEvent("ReorderableListContextCommand"); + EditorWindow.focusedWindow.SendEvent(e); + } + + /// + /// Invoked to generate context menu for list item. + /// + /// Menu which can be populated. + /// Zero-based index of item which was right-clicked. + /// Reorderable list adaptor. + protected virtual void AddItemsToMenu(GenericMenu menu, int itemIndex, IReorderableListAdaptor adaptor) { + if ((Flags & ReorderableListFlags.DisableReordering) == 0) { + if (itemIndex > 0) + menu.AddItem(CommandMoveToTop, false, DefaultContextHandler, CommandMoveToTop); + else + menu.AddDisabledItem(CommandMoveToTop); + + if (itemIndex + 1 < adaptor.Count) + menu.AddItem(CommandMoveToBottom, false, DefaultContextHandler, CommandMoveToBottom); + else + menu.AddDisabledItem(CommandMoveToBottom); + + if (HasAddButton) { + menu.AddSeparator(""); + + menu.AddItem(CommandInsertAbove, false, DefaultContextHandler, CommandInsertAbove); + menu.AddItem(CommandInsertBelow, false, DefaultContextHandler, CommandInsertBelow); + + if ((Flags & ReorderableListFlags.DisableDuplicateCommand) == 0) + menu.AddItem(CommandDuplicate, false, DefaultContextHandler, CommandDuplicate); + } + } + + if (HasRemoveButtons) { + if (menu.GetItemCount() > 0) + menu.AddSeparator(""); + + menu.AddItem(CommandRemove, false, DefaultContextHandler, CommandRemove); + menu.AddSeparator(""); + menu.AddItem(CommandClearAll, false, DefaultContextHandler, CommandClearAll); + } + } + + #endregion + + #region Command Handling + + /// + /// Invoked to handle context command. + /// + /// + /// It is important to set the value of GUI.changed to true if any + /// changes are made by command handler. + /// Default command handling functionality can be inherited: + /// + /// + /// + /// Name of command. This is the text shown in the context menu. + /// Zero-based index of item which was right-clicked. + /// Reorderable list adaptor. + /// + /// A value of true if command was known; otherwise false. + /// + protected virtual bool HandleCommand(string commandName, int itemIndex, IReorderableListAdaptor adaptor) { + switch (commandName) { + case "Move to Top": + MoveItem(adaptor, itemIndex, 0); + return true; + case "Move to Bottom": + MoveItem(adaptor, itemIndex, adaptor.Count); + return true; + + case "Insert Above": + InsertItem(adaptor, itemIndex); + return true; + case "Insert Below": + InsertItem(adaptor, itemIndex + 1); + return true; + case "Duplicate": + DuplicateItem(adaptor, itemIndex); + return true; + + case "Remove": + RemoveItem(adaptor, itemIndex); + return true; + case "Clear All": + ClearAll(adaptor); + return true; + + default: + return false; + } + } + + /// + /// Call to manually perform command. + /// + /// + /// Warning message is logged to console if attempted to execute unknown command. + /// + /// Name of command. This is the text shown in the context menu. + /// Zero-based index of item which was right-clicked. + /// Reorderable list adaptor. + /// + /// A value of true if command was known; otherwise false. + /// + public bool DoCommand(string commandName, int itemIndex, IReorderableListAdaptor adaptor) { + if (!HandleCommand(s_ContextCommandName, itemIndex, adaptor)) { + Debug.LogWarning("Unknown context command."); + return false; + } + return true; + } + + /// + /// Call to manually perform command. + /// + /// + /// Warning message is logged to console if attempted to execute unknown command. + /// + /// Content representing command. + /// Zero-based index of item which was right-clicked. + /// Reorderable list adaptor. + /// + /// A value of true if command was known; otherwise false. + /// + public bool DoCommand(GUIContent command, int itemIndex, IReorderableListAdaptor adaptor) { + return DoCommand(command.text, itemIndex, adaptor); + } + + #endregion + + #region Methods + + /// + /// Calculate height of list control in pixels. + /// + /// Reorderable list adaptor. + /// + /// Required list height in pixels. + /// + public float CalculateListHeight(IReorderableListAdaptor adaptor) { + FixStyles(); + + float totalHeight = ContainerStyle.padding.vertical - 1 + VerticalSpacing; + + // Take list items into consideration. + int count = adaptor.Count; + for (int i = 0; i < count; ++i) + totalHeight += adaptor.GetItemHeight(i); + // Add spacing between list items. + totalHeight += 4 * count; + + // Add height of footer buttons. + if (HasFooterControls) + totalHeight += FooterButtonStyle.fixedHeight; + + return totalHeight; + } + + /// + /// Calculate height of list control in pixels. + /// + /// Count of items in list. + /// Fixed height of list item. + /// + /// Required list height in pixels. + /// + public float CalculateListHeight(int itemCount, float itemHeight) { + FixStyles(); + + float totalHeight = ContainerStyle.padding.vertical - 1 + VerticalSpacing; + + // Take list items into consideration. + totalHeight += (itemHeight + 4) * itemCount; + + // Add height of footer buttons. + if (HasFooterControls) + totalHeight += FooterButtonStyle.fixedHeight; + + return totalHeight; + } + + /// + /// Move item from source index to destination index. + /// + /// Reorderable list adaptor. + /// Zero-based index of source item. + /// Zero-based index of destination index. + protected void MoveItem(IReorderableListAdaptor adaptor, int sourceIndex, int destIndex) { + // Raise event before moving item so that the operation can be cancelled. + var movingEventArgs = new ItemMovingEventArgs(adaptor, sourceIndex, destIndex); + OnItemMoving(movingEventArgs); + if (!movingEventArgs.Cancel) { + adaptor.Move(sourceIndex, destIndex); + + // Item was actually moved! + int newIndex = destIndex; + if (newIndex > sourceIndex) + --newIndex; + OnItemMoved(new ItemMovedEventArgs(adaptor, sourceIndex, newIndex)); + + GUI.changed = true; + } + ReorderableListGUI.IndexOfChangedItem = -1; + } + + /// + /// Add item at end of list and raises the event . + /// + /// Reorderable list adaptor. + protected void AddItem(IReorderableListAdaptor adaptor) { + adaptor.Add(); + AutoFocusItem(s_ContextControlID, adaptor.Count - 1); + + GUI.changed = true; + ReorderableListGUI.IndexOfChangedItem = -1; + + var args = new ItemInsertedEventArgs(adaptor, adaptor.Count - 1, false); + OnItemInserted(args); + } + + /// + /// Insert item at specified index and raises the event . + /// + /// Reorderable list adaptor. + /// Zero-based index of item. + protected void InsertItem(IReorderableListAdaptor adaptor, int itemIndex) { + adaptor.Insert(itemIndex); + AutoFocusItem(s_ContextControlID, itemIndex); + + GUI.changed = true; + ReorderableListGUI.IndexOfChangedItem = -1; + + var args = new ItemInsertedEventArgs(adaptor, itemIndex, false); + OnItemInserted(args); + } + + /// + /// Duplicate specified item and raises the event . + /// + /// Reorderable list adaptor. + /// Zero-based index of item. + protected void DuplicateItem(IReorderableListAdaptor adaptor, int itemIndex) { + adaptor.Duplicate(itemIndex); + AutoFocusItem(s_ContextControlID, itemIndex + 1); + + GUI.changed = true; + ReorderableListGUI.IndexOfChangedItem = -1; + + var args = new ItemInsertedEventArgs(adaptor, itemIndex + 1, true); + OnItemInserted(args); + } + + /// + /// Remove specified item. + /// + /// + /// The event is raised prior to removing item + /// and allows removal to be cancelled. + /// + /// Reorderable list adaptor. + /// Zero-based index of item. + /// + /// Returns a value of false if operation was cancelled. + /// + protected bool RemoveItem(IReorderableListAdaptor adaptor, int itemIndex) { + var args = new ItemRemovingEventArgs(adaptor, itemIndex); + OnItemRemoving(args); + if (args.Cancel) + return false; + + adaptor.Remove(itemIndex); + + GUI.changed = true; + ReorderableListGUI.IndexOfChangedItem = -1; + + return true; + } + + /// + /// Remove all items from list. + /// + /// + /// The event is raised for each item prior to + /// clearing array and allows entire operation to be cancelled. + /// + /// Reorderable list adaptor. + /// + /// Returns a value of false if operation was cancelled. + /// + protected bool ClearAll(IReorderableListAdaptor adaptor) { + if (adaptor.Count == 0) + return true; + + var args = new ItemRemovingEventArgs(adaptor, 0); + int count = adaptor.Count; + for (int i = 0; i < count; ++i) { + args.ItemIndex = i; + OnItemRemoving(args); + if (args.Cancel) + return false; + } + + adaptor.Clear(); + + GUI.changed = true; + ReorderableListGUI.IndexOfChangedItem = -1; + + return true; + } + + /// + /// Set count of items in list by adding or removing items. + /// + /// Reorderable list adaptor. + /// New count of items. + /// + /// Returns a value of false if operation was cancelled. + /// + protected bool ResizeList(IReorderableListAdaptor adaptor, int newCount) { + if (newCount < 0) { + // Do nothing when new count is negative. + return true; + } + + int removeCount = Mathf.Max(0, adaptor.Count - newCount); + int addCount = Mathf.Max(0, newCount - adaptor.Count); + + while (removeCount-- > 0) { + if (!RemoveItem(adaptor, adaptor.Count - 1)) + return false; + } + while (addCount-- > 0) { + AddItem(adaptor); + } + + return true; + } + + #endregion + + } + +} diff --git a/Assets/Fungus/Thirdparty/Reorderable List Field/Editor/ReorderableListControl.cs.meta b/Assets/Fungus/Thirdparty/Reorderable List Field/Editor/ReorderableListControl.cs.meta new file mode 100644 index 00000000..7a6e67a3 --- /dev/null +++ b/Assets/Fungus/Thirdparty/Reorderable List Field/Editor/ReorderableListControl.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 02045e26a7a39c440ba538e3c9ca2248 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Fungus/Thirdparty/Reorderable List Field/Editor/ReorderableListEvents.cs b/Assets/Fungus/Thirdparty/Reorderable List Field/Editor/ReorderableListEvents.cs new file mode 100644 index 00000000..091456c1 --- /dev/null +++ b/Assets/Fungus/Thirdparty/Reorderable List Field/Editor/ReorderableListEvents.cs @@ -0,0 +1,216 @@ +// Copyright (c) Rotorz Limited. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root. + +using System; +using System.ComponentModel; +using UnityEngine; + +namespace Rotorz.ReorderableList { + + /// + /// Arguments which are passed to . + /// + public sealed class AddMenuClickedEventArgs : EventArgs { + + /// + /// Gets adaptor to reorderable list container. + /// + public IReorderableListAdaptor Adaptor { get; private set; } + /// + /// Gets position of the add menu button. + /// + public Rect ButtonPosition { get; internal set; } + + /// + /// Initializes a new instance of . + /// + /// Reorderable list adaptor. + /// Position of the add menu button. + public AddMenuClickedEventArgs(IReorderableListAdaptor adaptor, Rect buttonPosition) { + this.Adaptor = adaptor; + this.ButtonPosition = buttonPosition; + } + + } + + /// + /// An event handler which is invoked when the "Add Menu" button is clicked. + /// + /// Object which raised event. + /// Event arguments. + public delegate void AddMenuClickedEventHandler(object sender, AddMenuClickedEventArgs args); + + /// + /// Arguments which are passed to . + /// + public sealed class ItemInsertedEventArgs : EventArgs { + + /// + /// Gets adaptor to reorderable list container which contains element. + /// + public IReorderableListAdaptor Adaptor { get; private set; } + /// + /// Gets zero-based index of item which was inserted. + /// + public int ItemIndex { get; private set; } + + /// + /// Indicates if inserted item was duplicated from another item. + /// + public bool WasDuplicated { get; private set; } + + /// + /// Initializes a new instance of . + /// + /// Reorderable list adaptor. + /// Zero-based index of item. + /// Indicates if inserted item was duplicated from another item. + public ItemInsertedEventArgs(IReorderableListAdaptor adaptor, int itemIndex, bool wasDuplicated) { + this.Adaptor = adaptor; + this.ItemIndex = itemIndex; + this.WasDuplicated = wasDuplicated; + } + + } + + /// + /// An event handler which is invoked after new list item is inserted. + /// + /// Object which raised event. + /// Event arguments. + public delegate void ItemInsertedEventHandler(object sender, ItemInsertedEventArgs args); + + /// + /// Arguments which are passed to . + /// + public sealed class ItemRemovingEventArgs : CancelEventArgs { + + /// + /// Gets adaptor to reorderable list container which contains element. + /// + public IReorderableListAdaptor Adaptor { get; private set; } + /// + /// Gets zero-based index of item which is being removed. + /// + public int ItemIndex { get; internal set; } + + /// + /// Initializes a new instance of . + /// + /// Reorderable list adaptor. + /// Zero-based index of item. + public ItemRemovingEventArgs(IReorderableListAdaptor adaptor, int itemIndex) { + this.Adaptor = adaptor; + this.ItemIndex = itemIndex; + } + + } + + /// + /// An event handler which is invoked before a list item is removed. + /// + /// + /// Item removal can be cancelled by setting + /// to true. + /// + /// Object which raised event. + /// Event arguments. + public delegate void ItemRemovingEventHandler(object sender, ItemRemovingEventArgs args); + + /// + /// Arguments which are passed to . + /// + public sealed class ItemMovingEventArgs : CancelEventArgs { + + /// + /// Gets adaptor to reorderable list container which contains element. + /// + public IReorderableListAdaptor Adaptor { get; private set; } + /// + /// Gets current zero-based index of item which is going to be moved. + /// + public int ItemIndex { get; internal set; } + /// + /// Gets the new candidate zero-based index for the item. + /// + /// + public int DestinationItemIndex { get; internal set; } + + /// + /// Gets zero-based index of item after it has been moved. + /// + /// + public int NewItemIndex { + get { + int result = DestinationItemIndex; + if (result > ItemIndex) + --result; + return result; + } + } + + /// + /// Initializes a new instance of . + /// + /// Reorderable list adaptor. + /// Zero-based index of item. + /// Xero-based index of item destination. + public ItemMovingEventArgs(IReorderableListAdaptor adaptor, int itemIndex, int destinationItemIndex) { + this.Adaptor = adaptor; + this.ItemIndex = itemIndex; + this.DestinationItemIndex = destinationItemIndex; + } + + } + + /// + /// An event handler which is invoked before a list item is moved. + /// + /// + /// Moving of item can be cancelled by setting + /// to true. + /// + /// Object which raised event. + /// Event arguments. + public delegate void ItemMovingEventHandler(object sender, ItemMovingEventArgs args); + + /// + /// Arguments which are passed to . + /// + public sealed class ItemMovedEventArgs : EventArgs { + + /// + /// Gets adaptor to reorderable list container which contains element. + /// + public IReorderableListAdaptor Adaptor { get; private set; } + /// + /// Gets old zero-based index of the item which was moved. + /// + public int OldItemIndex { get; internal set; } + /// + /// Gets new zero-based index of the item which was moved. + /// + public int NewItemIndex { get; internal set; } + + /// + /// Initializes a new instance of . + /// + /// Reorderable list adaptor. + /// Old zero-based index of item. + /// New zero-based index of item. + public ItemMovedEventArgs(IReorderableListAdaptor adaptor, int oldItemIndex, int newItemIndex) { + this.Adaptor = adaptor; + this.OldItemIndex = oldItemIndex; + this.NewItemIndex = newItemIndex; + } + + } + + /// + /// An event handler which is invoked after a list item is moved. + /// + /// Object which raised event. + /// Event arguments. + public delegate void ItemMovedEventHandler(object sender, ItemMovedEventArgs args); + +} diff --git a/Assets/Fungus/Thirdparty/Reorderable List Field/Editor/ReorderableListEvents.cs.meta b/Assets/Fungus/Thirdparty/Reorderable List Field/Editor/ReorderableListEvents.cs.meta new file mode 100644 index 00000000..c217a011 --- /dev/null +++ b/Assets/Fungus/Thirdparty/Reorderable List Field/Editor/ReorderableListEvents.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 1d75c9b7fc704a6488376beccd1a93a4 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Fungus/Thirdparty/Reorderable List Field/Editor/ReorderableListFlags.cs b/Assets/Fungus/Thirdparty/Reorderable List Field/Editor/ReorderableListFlags.cs new file mode 100644 index 00000000..ebb24c04 --- /dev/null +++ b/Assets/Fungus/Thirdparty/Reorderable List Field/Editor/ReorderableListFlags.cs @@ -0,0 +1,62 @@ +// Copyright (c) Rotorz Limited. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root. + +using System; + +namespace Rotorz.ReorderableList { + + /// + /// Additional flags which can be passed into reorderable list field. + /// + /// + /// Multiple flags can be specified if desired: + /// + /// + [Flags] + public enum ReorderableListFlags { + /// + /// Hide grab handles and disable reordering of list items. + /// + DisableReordering = 0x0001, + /// + /// Hide add button at base of control. + /// + HideAddButton = 0x0002, + /// + /// Hide remove buttons from list items. + /// + HideRemoveButtons = 0x0004, + /// + /// Do not display context menu upon right-clicking grab handle. + /// + DisableContextMenu = 0x0008, + /// + /// Hide "Duplicate" option from context menu. + /// + DisableDuplicateCommand = 0x0010, + /// + /// Do not automatically focus first control of newly added items. + /// + DisableAutoFocus = 0x0020, + /// + /// Show zero-based index of array elements. + /// + ShowIndices = 0x0040, + /// + [Obsolete("This flag is redundant because the clipping optimization was removed.")] + DisableClipping = 0x0080, + /// + /// Do not attempt to automatically scroll when list is inside a scroll view and + /// the mouse pointer is dragged outside of the visible portion of the list. + /// + DisableAutoScroll = 0x0100, + /// + /// Show "Size" field at base of list control. + /// + ShowSizeField = 0x0200, + } + +} diff --git a/Assets/Fungus/Thirdparty/Reorderable List Field/Editor/ReorderableListFlags.cs.meta b/Assets/Fungus/Thirdparty/Reorderable List Field/Editor/ReorderableListFlags.cs.meta new file mode 100644 index 00000000..d8bfe856 --- /dev/null +++ b/Assets/Fungus/Thirdparty/Reorderable List Field/Editor/ReorderableListFlags.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 8413004edec065f4c881fdb12b5d48b4 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Fungus/Thirdparty/Reorderable List Field/Editor/ReorderableListGUI.cs b/Assets/Fungus/Thirdparty/Reorderable List Field/Editor/ReorderableListGUI.cs new file mode 100644 index 00000000..1305174e --- /dev/null +++ b/Assets/Fungus/Thirdparty/Reorderable List Field/Editor/ReorderableListGUI.cs @@ -0,0 +1,576 @@ +// Copyright (c) Rotorz Limited. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root. + +using System.Collections.Generic; +using UnityEditor; +using UnityEngine; + +namespace Rotorz.ReorderableList { + + /// + /// Utility class for drawing reorderable lists. + /// + public static class ReorderableListGUI { + + /// + /// Default list item height is 18 pixels. + /// + public const float DefaultItemHeight = 18; + + /// + /// Gets or sets the zero-based index of the last item that was changed. A value of -1 + /// indicates that no item was changed by list. + /// + /// + /// This property should not be set when items are added or removed. + /// + public static int IndexOfChangedItem { get; internal set; } + + /// + /// Gets the control ID of the list that is currently being drawn. + /// + public static int CurrentListControlID { + get { return ReorderableListControl.CurrentListControlID; } + } + + /// + /// Gets the position of the list control that is currently being drawn. + /// + /// + /// The value of this property should be ignored for + /// type events when using reorderable list controls with automatic layout. + /// + /// + public static Rect CurrentListPosition { + get { return ReorderableListControl.CurrentListPosition; } + } + + /// + /// Gets the zero-based index of the list item that is currently being drawn; + /// or a value of -1 if no item is currently being drawn. + /// + public static int CurrentItemIndex { + get { return ReorderableListControl.CurrentItemIndex; } + } + + /// + /// Gets the total position of the list item that is currently being drawn. + /// + /// + /// The value of this property should be ignored for + /// type events when using reorderable list controls with automatic layout. + /// + /// + /// + public static Rect CurrentItemTotalPosition { + get { return ReorderableListControl.CurrentItemTotalPosition; } + } + + #region Basic Item Drawers + + /// + /// Default list item drawer implementation. + /// + /// + /// Always presents the label "Item drawer not implemented.". + /// + /// Position to draw list item control(s). + /// Value of list item. + /// + /// Unmodified value of list item. + /// + /// Type of list item. + public static T DefaultItemDrawer(Rect position, T item) { + GUI.Label(position, "Item drawer not implemented."); + return item; + } + + /// + /// Draws text field allowing list items to be edited. + /// + /// + /// Null values are automatically changed to empty strings since null + /// values cannot be edited using a text field. + /// Value of GUI.changed is set to true if value of item + /// is modified. + /// + /// Position to draw list item control(s). + /// Value of list item. + /// + /// Modified value of list item. + /// + public static string TextFieldItemDrawer(Rect position, string item) { + if (item == null) { + item = ""; + GUI.changed = true; + } + return EditorGUI.TextField(position, item); + } + + #endregion + + /// + /// Gets the default list control implementation. + /// + private static ReorderableListControl DefaultListControl { get; set; } + + static ReorderableListGUI() { + DefaultListControl = new ReorderableListControl(); + + // Duplicate default styles to prevent user scripts from interferring with + // the default list control instance. + DefaultListControl.ContainerStyle = new GUIStyle(ReorderableListStyles.Container); + DefaultListControl.FooterButtonStyle = new GUIStyle(ReorderableListStyles.FooterButton); + DefaultListControl.ItemButtonStyle = new GUIStyle(ReorderableListStyles.ItemButton); + + IndexOfChangedItem = -1; + } + + private static GUIContent s_Temp = new GUIContent(); + + #region Title Control + + /// + /// Draw title control for list field. + /// + /// + /// When needed, should be shown immediately before list field. + /// + /// + /// + /// + /// + /// Content for title control. + public static void Title(GUIContent title) { + Rect position = GUILayoutUtility.GetRect(title, ReorderableListStyles.Title); + Title(position, title); + GUILayout.Space(-1); + } + + /// + /// Draw title control for list field. + /// + /// + /// When needed, should be shown immediately before list field. + /// + /// + /// + /// + /// + /// Text for title control. + public static void Title(string title) { + s_Temp.text = title; + Title(s_Temp); + } + + /// + /// Draw title control for list field with absolute positioning. + /// + /// Position of control. + /// Content for title control. + public static void Title(Rect position, GUIContent title) { + if (Event.current.type == EventType.Repaint) + ReorderableListStyles.Title.Draw(position, title, false, false, false, false); + } + + /// + /// Draw title control for list field with absolute positioning. + /// + /// Position of control. + /// Text for title control. + public static void Title(Rect position, string text) { + s_Temp.text = text; + Title(position, s_Temp); + } + + #endregion + + #region List Control + + /// + /// Draw list field control. + /// + /// The list which can be reordered. + /// Callback to draw list item. + /// Callback to draw custom content for empty list (optional). + /// Height of a single list item. + /// Optional flags to pass into list field. + /// Type of list item. + private static void DoListField(IList list, ReorderableListControl.ItemDrawer drawItem, ReorderableListControl.DrawEmpty drawEmpty, float itemHeight, ReorderableListFlags flags) { + var adaptor = new GenericListAdaptor(list, drawItem, itemHeight); + ReorderableListControl.DrawControlFromState(adaptor, drawEmpty, flags); + } + /// + /// Draw list field control with absolute positioning. + /// + /// Position of control. + /// The list which can be reordered. + /// Callback to draw list item. + /// Callback to draw custom content for empty list (optional). + /// Height of a single list item. + /// Optional flags to pass into list field. + /// Type of list item. + private static void DoListFieldAbsolute(Rect position, IList list, ReorderableListControl.ItemDrawer drawItem, ReorderableListControl.DrawEmptyAbsolute drawEmpty, float itemHeight, ReorderableListFlags flags) { + var adaptor = new GenericListAdaptor(list, drawItem, itemHeight); + ReorderableListControl.DrawControlFromState(position, adaptor, drawEmpty, flags); + } + + + /// + public static void ListField(IList list, ReorderableListControl.ItemDrawer drawItem, ReorderableListControl.DrawEmpty drawEmpty, float itemHeight, ReorderableListFlags flags) { + DoListField(list, drawItem, drawEmpty, itemHeight, flags); + } + /// + public static void ListFieldAbsolute(Rect position, IList list, ReorderableListControl.ItemDrawer drawItem, ReorderableListControl.DrawEmptyAbsolute drawEmpty, float itemHeight, ReorderableListFlags flags) { + DoListFieldAbsolute(position, list, drawItem, drawEmpty, itemHeight, flags); + } + + + /// + public static void ListField(IList list, ReorderableListControl.ItemDrawer drawItem, ReorderableListControl.DrawEmpty drawEmpty, float itemHeight) { + DoListField(list, drawItem, drawEmpty, itemHeight, 0); + } + /// + public static void ListFieldAbsolute(Rect position, IList list, ReorderableListControl.ItemDrawer drawItem, ReorderableListControl.DrawEmptyAbsolute drawEmpty, float itemHeight) { + DoListFieldAbsolute(position, list, drawItem, drawEmpty, itemHeight, 0); + } + + + /// + public static void ListField(IList list, ReorderableListControl.ItemDrawer drawItem, ReorderableListControl.DrawEmpty drawEmpty, ReorderableListFlags flags) { + DoListField(list, drawItem, drawEmpty, DefaultItemHeight, flags); + } + /// + public static void ListFieldAbsolute(Rect position, IList list, ReorderableListControl.ItemDrawer drawItem, ReorderableListControl.DrawEmptyAbsolute drawEmpty, ReorderableListFlags flags) { + DoListFieldAbsolute(position, list, drawItem, drawEmpty, DefaultItemHeight, flags); + } + + + /// + public static void ListField(IList list, ReorderableListControl.ItemDrawer drawItem, ReorderableListControl.DrawEmpty drawEmpty) { + DoListField(list, drawItem, drawEmpty, DefaultItemHeight, 0); + } + /// + public static void ListFieldAbsolute(Rect position, IList list, ReorderableListControl.ItemDrawer drawItem, ReorderableListControl.DrawEmptyAbsolute drawEmpty) { + DoListFieldAbsolute(position, list, drawItem, drawEmpty, DefaultItemHeight, 0); + } + + + /// + public static void ListField(IList list, ReorderableListControl.ItemDrawer drawItem, float itemHeight, ReorderableListFlags flags) { + DoListField(list, drawItem, null, itemHeight, flags); + } + /// + public static void ListFieldAbsolute(Rect position, IList list, ReorderableListControl.ItemDrawer drawItem, float itemHeight, ReorderableListFlags flags) { + DoListFieldAbsolute(position, list, drawItem, null, itemHeight, flags); + } + + + /// + public static void ListField(IList list, ReorderableListControl.ItemDrawer drawItem, float itemHeight) { + DoListField(list, drawItem, null, itemHeight, 0); + } + /// + public static void ListFieldAbsolute(Rect position, IList list, ReorderableListControl.ItemDrawer drawItem, float itemHeight) { + DoListFieldAbsolute(position, list, drawItem, null, itemHeight, 0); + } + + + /// + public static void ListField(IList list, ReorderableListControl.ItemDrawer drawItem, ReorderableListFlags flags) { + DoListField(list, drawItem, null, DefaultItemHeight, flags); + } + /// + public static void ListFieldAbsolute(Rect position, IList list, ReorderableListControl.ItemDrawer drawItem, ReorderableListFlags flags) { + DoListFieldAbsolute(position, list, drawItem, null, DefaultItemHeight, flags); + } + + + /// + public static void ListField(IList list, ReorderableListControl.ItemDrawer drawItem) { + DoListField(list, drawItem, null, DefaultItemHeight, 0); + } + /// + public static void ListFieldAbsolute(Rect position, IList list, ReorderableListControl.ItemDrawer drawItem) { + DoListFieldAbsolute(position, list, drawItem, null, DefaultItemHeight, 0); + } + + + /// + /// Calculate height of list field for absolute positioning. + /// + /// Count of items in list. + /// Fixed height of list item. + /// Optional flags to pass into list field. + /// + /// Required list height in pixels. + /// + public static float CalculateListFieldHeight(int itemCount, float itemHeight, ReorderableListFlags flags) { + // We need to push/pop flags so that nested controls are properly calculated. + var restoreFlags = DefaultListControl.Flags; + try { + DefaultListControl.Flags = flags; + return DefaultListControl.CalculateListHeight(itemCount, itemHeight); + } + finally { + DefaultListControl.Flags = restoreFlags; + } + } + + /// + public static float CalculateListFieldHeight(int itemCount, ReorderableListFlags flags) { + return CalculateListFieldHeight(itemCount, DefaultItemHeight, flags); + } + /// + public static float CalculateListFieldHeight(int itemCount, float itemHeight) { + return CalculateListFieldHeight(itemCount, itemHeight, 0); + } + /// + public static float CalculateListFieldHeight(int itemCount) { + return CalculateListFieldHeight(itemCount, DefaultItemHeight, 0); + } + + #endregion + + #region SerializedProperty Control + + /// + /// Draw list field control for serializable property array. + /// + /// Serializable property. + /// Use fixed height for items rather than . + /// Callback to draw custom content for empty list (optional). + /// Optional flags to pass into list field. + private static void DoListField(SerializedProperty arrayProperty, float fixedItemHeight, ReorderableListControl.DrawEmpty drawEmpty, ReorderableListFlags flags) { + var adaptor = new SerializedPropertyAdaptor(arrayProperty, fixedItemHeight); + ReorderableListControl.DrawControlFromState(adaptor, drawEmpty, flags); + } + /// + /// Draw list field control for serializable property array. + /// + /// Position of control. + /// Serializable property. + /// Use fixed height for items rather than . + /// Callback to draw custom content for empty list (optional). + /// Optional flags to pass into list field. + private static void DoListFieldAbsolute(Rect position, SerializedProperty arrayProperty, float fixedItemHeight, ReorderableListControl.DrawEmptyAbsolute drawEmpty, ReorderableListFlags flags) { + var adaptor = new SerializedPropertyAdaptor(arrayProperty, fixedItemHeight); + ReorderableListControl.DrawControlFromState(position, adaptor, drawEmpty, flags); + } + + + /// + public static void ListField(SerializedProperty arrayProperty, ReorderableListControl.DrawEmpty drawEmpty, ReorderableListFlags flags) { + DoListField(arrayProperty, 0, drawEmpty, flags); + } + /// + public static void ListFieldAbsolute(Rect position, SerializedProperty arrayProperty, ReorderableListControl.DrawEmptyAbsolute drawEmpty, ReorderableListFlags flags) { + DoListFieldAbsolute(position, arrayProperty, 0, drawEmpty, flags); + } + + + /// + public static void ListField(SerializedProperty arrayProperty, ReorderableListControl.DrawEmpty drawEmpty) { + DoListField(arrayProperty, 0, drawEmpty, 0); + } + /// + public static void ListFieldAbsolute(Rect position, SerializedProperty arrayProperty, ReorderableListControl.DrawEmptyAbsolute drawEmpty) { + DoListFieldAbsolute(position, arrayProperty, 0, drawEmpty, 0); + } + + + /// + public static void ListField(SerializedProperty arrayProperty, ReorderableListFlags flags) { + DoListField(arrayProperty, 0, null, flags); + } + /// + public static void ListFieldAbsolute(Rect position, SerializedProperty arrayProperty, ReorderableListFlags flags) { + DoListFieldAbsolute(position, arrayProperty, 0, null, flags); + } + + + /// + public static void ListField(SerializedProperty arrayProperty) { + DoListField(arrayProperty, 0, null, 0); + } + /// + public static void ListFieldAbsolute(Rect position, SerializedProperty arrayProperty) { + DoListFieldAbsolute(position, arrayProperty, 0, null, 0); + } + + + /// + /// Calculate height of list field for absolute positioning. + /// + /// Serializable property. + /// Optional flags to pass into list field. + /// + /// Required list height in pixels. + /// + public static float CalculateListFieldHeight(SerializedProperty arrayProperty, ReorderableListFlags flags) { + // We need to push/pop flags so that nested controls are properly calculated. + var restoreFlags = DefaultListControl.Flags; + try { + DefaultListControl.Flags = flags; + return DefaultListControl.CalculateListHeight(new SerializedPropertyAdaptor(arrayProperty)); + } + finally { + DefaultListControl.Flags = restoreFlags; + } + } + + /// + public static float CalculateListFieldHeight(SerializedProperty arrayProperty) { + return CalculateListFieldHeight(arrayProperty, 0); + } + + #endregion + + #region SerializedProperty Control (Fixed Item Height) + + /// + public static void ListField(SerializedProperty arrayProperty, float fixedItemHeight, ReorderableListControl.DrawEmpty drawEmpty, ReorderableListFlags flags) { + DoListField(arrayProperty, fixedItemHeight, drawEmpty, flags); + } + /// + public static void ListFieldAbsolute(Rect position, SerializedProperty arrayProperty, float fixedItemHeight, ReorderableListControl.DrawEmptyAbsolute drawEmpty, ReorderableListFlags flags) { + DoListFieldAbsolute(position, arrayProperty, fixedItemHeight, drawEmpty, flags); + } + + + /// + public static void ListField(SerializedProperty arrayProperty, float fixedItemHeight, ReorderableListControl.DrawEmpty drawEmpty) { + DoListField(arrayProperty, fixedItemHeight, drawEmpty, 0); + } + /// + public static void ListFieldAbsolute(Rect position, SerializedProperty arrayProperty, float fixedItemHeight, ReorderableListControl.DrawEmptyAbsolute drawEmpty) { + DoListFieldAbsolute(position, arrayProperty, fixedItemHeight, drawEmpty, 0); + } + + + /// + public static void ListField(SerializedProperty arrayProperty, float fixedItemHeight, ReorderableListFlags flags) { + DoListField(arrayProperty, fixedItemHeight, null, flags); + } + /// + public static void ListFieldAbsolute(Rect position, SerializedProperty arrayProperty, float fixedItemHeight, ReorderableListFlags flags) { + DoListFieldAbsolute(position, arrayProperty, fixedItemHeight, null, flags); + } + + + /// + public static void ListField(SerializedProperty arrayProperty, float fixedItemHeight) { + DoListField(arrayProperty, fixedItemHeight, null, 0); + } + /// + public static void ListFieldAbsolute(Rect position, SerializedProperty arrayProperty, float fixedItemHeight) { + DoListFieldAbsolute(position, arrayProperty, fixedItemHeight, null, 0); + } + + #endregion + + #region Adaptor Control + + /// + /// Draw list field control for adapted collection. + /// + /// Reorderable list adaptor. + /// Callback to draw custom content for empty list (optional). + /// Optional flags to pass into list field. + private static void DoListField(IReorderableListAdaptor adaptor, ReorderableListControl.DrawEmpty drawEmpty, ReorderableListFlags flags = 0) { + ReorderableListControl.DrawControlFromState(adaptor, drawEmpty, flags); + } + /// + /// Draw list field control for adapted collection. + /// + /// Position of control. + /// Reorderable list adaptor. + /// Callback to draw custom content for empty list (optional). + /// Optional flags to pass into list field. + private static void DoListFieldAbsolute(Rect position, IReorderableListAdaptor adaptor, ReorderableListControl.DrawEmptyAbsolute drawEmpty, ReorderableListFlags flags = 0) { + ReorderableListControl.DrawControlFromState(position, adaptor, drawEmpty, flags); + } + + + /// + public static void ListField(IReorderableListAdaptor adaptor, ReorderableListControl.DrawEmpty drawEmpty, ReorderableListFlags flags) { + DoListField(adaptor, drawEmpty, flags); + } + /// + public static void ListFieldAbsolute(Rect position, IReorderableListAdaptor adaptor, ReorderableListControl.DrawEmptyAbsolute drawEmpty, ReorderableListFlags flags) { + DoListFieldAbsolute(position, adaptor, drawEmpty, flags); + } + + + /// + public static void ListField(IReorderableListAdaptor adaptor, ReorderableListControl.DrawEmpty drawEmpty) { + DoListField(adaptor, drawEmpty, 0); + } + /// + public static void ListFieldAbsolute(Rect position, IReorderableListAdaptor adaptor, ReorderableListControl.DrawEmptyAbsolute drawEmpty) { + DoListFieldAbsolute(position, adaptor, drawEmpty, 0); + } + + + /// + public static void ListField(IReorderableListAdaptor adaptor, ReorderableListFlags flags) { + DoListField(adaptor, null, flags); + } + /// + public static void ListFieldAbsolute(Rect position, IReorderableListAdaptor adaptor, ReorderableListFlags flags) { + DoListFieldAbsolute(position, adaptor, null, flags); + } + + + /// + public static void ListField(IReorderableListAdaptor adaptor) { + DoListField(adaptor, null, 0); + } + /// + public static void ListFieldAbsolute(Rect position, IReorderableListAdaptor adaptor) { + DoListFieldAbsolute(position, adaptor, null, 0); + } + + + /// + /// Calculate height of list field for adapted collection. + /// + /// Reorderable list adaptor. + /// Optional flags to pass into list field. + /// + /// Required list height in pixels. + /// + public static float CalculateListFieldHeight(IReorderableListAdaptor adaptor, ReorderableListFlags flags) { + // We need to push/pop flags so that nested controls are properly calculated. + var restoreFlags = DefaultListControl.Flags; + try { + DefaultListControl.Flags = flags; + return DefaultListControl.CalculateListHeight(adaptor); + } + finally { + DefaultListControl.Flags = restoreFlags; + } + } + + /// + public static float CalculateListFieldHeight(IReorderableListAdaptor adaptor) { + return CalculateListFieldHeight(adaptor, 0); + } + + #endregion + + } + +} diff --git a/Assets/Fungus/Thirdparty/Reorderable List Field/Editor/ReorderableListGUI.cs.meta b/Assets/Fungus/Thirdparty/Reorderable List Field/Editor/ReorderableListGUI.cs.meta new file mode 100644 index 00000000..1cdd488e --- /dev/null +++ b/Assets/Fungus/Thirdparty/Reorderable List Field/Editor/ReorderableListGUI.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 0cda42c9be3a73c469749c5422090d9a +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Fungus/Thirdparty/Reorderable List Field/Editor/ReorderableListStyles.cs b/Assets/Fungus/Thirdparty/Reorderable List Field/Editor/ReorderableListStyles.cs new file mode 100644 index 00000000..3bd5f52a --- /dev/null +++ b/Assets/Fungus/Thirdparty/Reorderable List Field/Editor/ReorderableListStyles.cs @@ -0,0 +1,114 @@ +// Copyright (c) Rotorz Limited. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root. + +using Rotorz.ReorderableList.Internal; +using UnityEditor; +using UnityEngine; + +namespace Rotorz.ReorderableList { + + /// + /// Styles for the . + /// + public static class ReorderableListStyles { + + static ReorderableListStyles() { + Title = new GUIStyle(); + Title.border = new RectOffset(2, 2, 2, 1); + Title.margin = new RectOffset(5, 5, 5, 0); + Title.padding = new RectOffset(5, 5, 3, 3); + Title.alignment = TextAnchor.MiddleLeft; + Title.normal.background = ReorderableListResources.GetTexture(ReorderableListTexture.TitleBackground); + Title.normal.textColor = EditorGUIUtility.isProSkin + ? new Color(0.8f, 0.8f, 0.8f) + : new Color(0.2f, 0.2f, 0.2f); + + Container = new GUIStyle(); + Container.border = new RectOffset(2, 2, 2, 2); + Container.margin = new RectOffset(5, 5, 0, 0); + Container.padding = new RectOffset(2, 2, 2, 2); + Container.normal.background = ReorderableListResources.GetTexture(ReorderableListTexture.ContainerBackground); + + Container2 = new GUIStyle(Container); + Container2.normal.background = ReorderableListResources.GetTexture(ReorderableListTexture.Container2Background); + + FooterButton = new GUIStyle(); + FooterButton.fixedHeight = 16; + FooterButton.alignment = TextAnchor.MiddleCenter; + FooterButton.normal.background = ReorderableListResources.GetTexture(ReorderableListTexture.Button_Normal); + FooterButton.active.background = ReorderableListResources.GetTexture(ReorderableListTexture.Button_Active); + FooterButton.border = new RectOffset(3, 3, 1, 3); + FooterButton.padding = new RectOffset(2, 2, 0, 2); + FooterButton.clipping = TextClipping.Overflow; + + FooterButton2 = new GUIStyle(); + FooterButton2.fixedHeight = 18; + FooterButton2.alignment = TextAnchor.MiddleCenter; + FooterButton2.normal.background = ReorderableListResources.GetTexture(ReorderableListTexture.Button2_Normal); + FooterButton2.active.background = ReorderableListResources.GetTexture(ReorderableListTexture.Button2_Active); + FooterButton2.border = new RectOffset(3, 3, 3, 3); + FooterButton2.padding = new RectOffset(2, 2, 2, 2); + FooterButton2.clipping = TextClipping.Overflow; + + ItemButton = new GUIStyle(); + ItemButton.active.background = ReorderableListResources.CreatePixelTexture("Dark Pixel (List GUI)", new Color32(18, 18, 18, 255)); + ItemButton.imagePosition = ImagePosition.ImageOnly; + ItemButton.alignment = TextAnchor.MiddleCenter; + ItemButton.overflow = new RectOffset(0, 0, -1, 0); + ItemButton.padding = new RectOffset(0, 0, 1, 0); + ItemButton.contentOffset = new Vector2(0, -1f); + + SelectedItem = new GUIStyle(); + SelectedItem.normal.background = ReorderableListResources.texHighlightColor; + SelectedItem.normal.textColor = Color.white; + SelectedItem.fontSize = 12; + } + + /// + /// Gets style for title header. + /// + public static GUIStyle Title { get; private set; } + + /// + /// Gets style for the background of list control. + /// + public static GUIStyle Container { get; private set; } + /// + /// Gets an alternative style for the background of list control. + /// + public static GUIStyle Container2 { get; private set; } + /// + /// Gets style for footer button. + /// + public static GUIStyle FooterButton { get; private set; } + /// + /// Gets an alternative style for footer button. + /// + public static GUIStyle FooterButton2 { get; private set; } + /// + /// Gets style for remove item button. + /// + public static GUIStyle ItemButton { get; private set; } + + /// + /// Gets style for the background of a selected item. + /// + public static GUIStyle SelectedItem { get; private set; } + + /// + /// Gets color for the horizontal lines that appear between list items. + /// + public static Color HorizontalLineColor { + get { return EditorGUIUtility.isProSkin ? new Color(1f, 1f, 1f, 0.14f) : new Color(0.59f, 0.59f, 0.59f, 0.55f); } + } + + /// + /// Gets color of background for a selected list item. + /// + public static Color SelectionBackgroundColor { + get { return EditorGUIUtility.isProSkin ? new Color32(62, 95, 150, 255) : new Color32(62, 125, 231, 255); } + } + + } + +} diff --git a/Assets/Fungus/Thirdparty/Reorderable List Field/Editor/ReorderableListStyles.cs.meta b/Assets/Fungus/Thirdparty/Reorderable List Field/Editor/ReorderableListStyles.cs.meta new file mode 100644 index 00000000..7883dfc4 --- /dev/null +++ b/Assets/Fungus/Thirdparty/Reorderable List Field/Editor/ReorderableListStyles.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: c4843f314e955fb459f99b33194fbebd +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Fungus/Thirdparty/Reorderable List Field/Editor/SerializedPropertyAdaptor.cs b/Assets/Fungus/Thirdparty/Reorderable List Field/Editor/SerializedPropertyAdaptor.cs new file mode 100644 index 00000000..59fdafb3 --- /dev/null +++ b/Assets/Fungus/Thirdparty/Reorderable List Field/Editor/SerializedPropertyAdaptor.cs @@ -0,0 +1,159 @@ +// Copyright (c) Rotorz Limited. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root. + +using Rotorz.ReorderableList.Internal; +using System; +using UnityEditor; +using UnityEngine; + +namespace Rotorz.ReorderableList { + + /// + /// Reorderable list adaptor for serialized array property. + /// + /// + /// This adaptor can be subclassed to add special logic to item height calculation. + /// You may want to implement a custom adaptor class where specialised functionality + /// is needed. + /// List elements are not cloned using the + /// interface when using a to + /// manipulate lists. + /// + public class SerializedPropertyAdaptor : IReorderableListAdaptor { + + private SerializedProperty _arrayProperty; + + /// + /// Fixed height of each list item. + /// + /// + /// Non-zero value overrides property drawer height calculation + /// which is more efficient. + /// + public float FixedItemHeight; + + /// + /// Gets element from list. + /// + /// Zero-based index of element. + /// + /// Serialized property wrapper for array element. + /// + public SerializedProperty this[int index] { + get { return _arrayProperty.GetArrayElementAtIndex(index); } + } + + /// + /// Gets the underlying serialized array property. + /// + public SerializedProperty arrayProperty { + get { return _arrayProperty; } + } + + #region Construction + + /// + /// Initializes a new instance of . + /// + /// Serialized property for entire array. + /// Non-zero height overrides property drawer height calculation. + public SerializedPropertyAdaptor(SerializedProperty arrayProperty, float fixedItemHeight) { + if (arrayProperty == null) + throw new ArgumentNullException("Array property was null."); + if (!arrayProperty.isArray) + throw new InvalidOperationException("Specified serialized propery is not an array."); + + this._arrayProperty = arrayProperty; + this.FixedItemHeight = fixedItemHeight; + } + + /// + /// Initializes a new instance of . + /// + /// Serialized property for entire array. + public SerializedPropertyAdaptor(SerializedProperty arrayProperty) : this(arrayProperty, 0f) { + } + + #endregion + + #region IReorderableListAdaptor - Implementation + + /// + public int Count { + get { return _arrayProperty.arraySize; } + } + + /// + public virtual bool CanDrag(int index) { + return true; + } + /// + public virtual bool CanRemove(int index) { + return true; + } + + /// + public void Add() { + int newIndex = _arrayProperty.arraySize; + ++_arrayProperty.arraySize; + SerializedPropertyUtility.ResetValue(_arrayProperty.GetArrayElementAtIndex(newIndex)); + } + /// + public void Insert(int index) { + _arrayProperty.InsertArrayElementAtIndex(index); + SerializedPropertyUtility.ResetValue(_arrayProperty.GetArrayElementAtIndex(index)); + } + /// + public void Duplicate(int index) { + _arrayProperty.InsertArrayElementAtIndex(index); + } + /// + public void Remove(int index) { + // Unity doesn't remove element when it contains an object reference. + var elementProperty = _arrayProperty.GetArrayElementAtIndex(index); + if (elementProperty.propertyType == SerializedPropertyType.ObjectReference) + elementProperty.objectReferenceValue = null; + + _arrayProperty.DeleteArrayElementAtIndex(index); + } + /// + public void Move(int sourceIndex, int destIndex) { + if (destIndex > sourceIndex) + --destIndex; + _arrayProperty.MoveArrayElement(sourceIndex, destIndex); + } + /// + public void Clear() { + _arrayProperty.ClearArray(); + } + + /// + public virtual void BeginGUI() { + } + + /// + public virtual void EndGUI() { + } + + /// + public virtual void DrawItemBackground(Rect position, int index) { + } + + /// + public virtual void DrawItem(Rect position, int index) { + EditorGUI.PropertyField(position, this[index], GUIContent.none, false); + } + + /// + public virtual float GetItemHeight(int index) { + return FixedItemHeight != 0f + ? FixedItemHeight + : EditorGUI.GetPropertyHeight(this[index], GUIContent.none, false) + ; + } + + #endregion + + } + +} diff --git a/Assets/Fungus/Thirdparty/Reorderable List Field/Editor/SerializedPropertyAdaptor.cs.meta b/Assets/Fungus/Thirdparty/Reorderable List Field/Editor/SerializedPropertyAdaptor.cs.meta new file mode 100644 index 00000000..ed40b949 --- /dev/null +++ b/Assets/Fungus/Thirdparty/Reorderable List Field/Editor/SerializedPropertyAdaptor.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 591bfb933f0cb1a429927d177e35f97d +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Fungus/Thirdparty/Reorderable List Field/LICENSE.txt b/Assets/Fungus/Thirdparty/Reorderable List Field/LICENSE.txt index 68f7deeb..73001aaf 100755 --- a/Assets/Fungus/Thirdparty/Reorderable List Field/LICENSE.txt +++ b/Assets/Fungus/Thirdparty/Reorderable List Field/LICENSE.txt @@ -1,4 +1,4 @@ -The MIT License (MIT) +The MIT License (MIT) Copyright (c) 2013-2015 Rotorz Limited diff --git a/Assets/Fungus/Thirdparty/Reorderable List Field/LICENSE.txt.meta b/Assets/Fungus/Thirdparty/Reorderable List Field/LICENSE.txt.meta index 9f94a2ba..5e71e756 100644 --- a/Assets/Fungus/Thirdparty/Reorderable List Field/LICENSE.txt.meta +++ b/Assets/Fungus/Thirdparty/Reorderable List Field/LICENSE.txt.meta @@ -1,6 +1,7 @@ fileFormatVersion: 2 guid: 8fc66c8c3ee484548a40e9b4cb50f206 TextScriptImporter: + externalObjects: {} userData: assetBundleName: assetBundleVariant: diff --git a/Assets/Fungus/Thirdparty/Reorderable List Field/Properties.meta b/Assets/Fungus/Thirdparty/Reorderable List Field/Properties.meta new file mode 100644 index 00000000..a75bc535 --- /dev/null +++ b/Assets/Fungus/Thirdparty/Reorderable List Field/Properties.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: adbb9aeb25106a54e9af119d9d77e332 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Fungus/Thirdparty/Reorderable List Field/Properties/AssemblyInfo.cs b/Assets/Fungus/Thirdparty/Reorderable List Field/Properties/AssemblyInfo.cs new file mode 100644 index 00000000..21a59e6d --- /dev/null +++ b/Assets/Fungus/Thirdparty/Reorderable List Field/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("Editor.ReorderableList")] +[assembly: AssemblyDescription("Reorderable list field for custom Unity editor scripts.")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("Rotorz Limited")] +[assembly: AssemblyProduct("Editor.ReorderableList")] +[assembly: AssemblyCopyright("©2013-2016 Rotorz Limited. All rights reserved.")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("15882e08-6b4f-459f-a1d0-e4b26821f344")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("0.0.0.0")] +[assembly: AssemblyFileVersion("0.4.4.0")] diff --git a/Assets/Fungus/Thirdparty/Reorderable List Field/Properties/AssemblyInfo.cs.meta b/Assets/Fungus/Thirdparty/Reorderable List Field/Properties/AssemblyInfo.cs.meta new file mode 100644 index 00000000..5d771b95 --- /dev/null +++ b/Assets/Fungus/Thirdparty/Reorderable List Field/Properties/AssemblyInfo.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 9229bf01f21bb1842a94bbabd158f241 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Fungus/Thirdparty/Reorderable List Field/README.txt b/Assets/Fungus/Thirdparty/Reorderable List Field/README.md old mode 100755 new mode 100644 similarity index 94% rename from Assets/Fungus/Thirdparty/Reorderable List Field/README.txt rename to Assets/Fungus/Thirdparty/Reorderable List Field/README.md index 6ca1fd5e..03a98a94 --- a/Assets/Fungus/Thirdparty/Reorderable List Field/README.txt +++ b/Assets/Fungus/Thirdparty/Reorderable List Field/README.md @@ -1,4 +1,4 @@ -README +README ====== List control for Unity allowing editor developers to add reorderable list controls to @@ -21,7 +21,7 @@ Features - Subscribe to add/remove item events. - Supports mixed item heights. - Disable drag and/or removal on per-item basis. -- [Drop insertion]() (for use with `UnityEditor.DragAndDrop`). +- Drop insertion (for use with `UnityEditor.DragAndDrop`). - Styles can be overridden on per-list basis if desired. - Subclass list control to override context menu. - Add drop-down to add menu (or instead of add menu). @@ -29,6 +29,12 @@ Features - User guide (Asset Path/Support/User Guide.pdf). - API reference documentation (Asset Path/Support/API Reference.chm). + +Preview (showing drop insertion feature) +---------------------------------------- + +![preview](https://bitbucket.org/rotorz/reorderable-list-editor-field-for-unity/raw/master/preview.gif) + Installing scripts ------------------ @@ -136,4 +142,4 @@ must be met: - The act of submitting a contribution indicates that the contributor agrees with this agreement. This includes (but is not limited to) pull requests, issues, - tickets, e-mails, newsgroups, blogs, forums, etc. \ No newline at end of file + tickets, e-mails, newsgroups, blogs, forums, etc. diff --git a/Assets/Fungus/Thirdparty/Reorderable List Field/README.txt.meta b/Assets/Fungus/Thirdparty/Reorderable List Field/README.md.meta similarity index 61% rename from Assets/Fungus/Thirdparty/Reorderable List Field/README.txt.meta rename to Assets/Fungus/Thirdparty/Reorderable List Field/README.md.meta index a01f2b7c..d1453d88 100644 --- a/Assets/Fungus/Thirdparty/Reorderable List Field/README.txt.meta +++ b/Assets/Fungus/Thirdparty/Reorderable List Field/README.md.meta @@ -1,6 +1,7 @@ fileFormatVersion: 2 -guid: d5735c08f13f43a44be11da81110e424 +guid: c4b649ac64aa4bd428c41192aba38c61 TextScriptImporter: + externalObjects: {} userData: assetBundleName: assetBundleVariant: diff --git a/Assets/Fungus/Thirdparty/Reorderable List Field/Support.meta b/Assets/Fungus/Thirdparty/Reorderable List Field/Support.meta new file mode 100644 index 00000000..1d1ca115 --- /dev/null +++ b/Assets/Fungus/Thirdparty/Reorderable List Field/Support.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 457a6fa816de84a4bb30c03f176b4554 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Fungus/Thirdparty/Reorderable List Field/Support/API Reference.chm b/Assets/Fungus/Thirdparty/Reorderable List Field/Support/API Reference.chm new file mode 100644 index 00000000..dee652f1 Binary files /dev/null and b/Assets/Fungus/Thirdparty/Reorderable List Field/Support/API Reference.chm differ diff --git a/Assets/Fungus/Thirdparty/Reorderable List Field/Support/API Reference.chm.meta b/Assets/Fungus/Thirdparty/Reorderable List Field/Support/API Reference.chm.meta new file mode 100644 index 00000000..aec749ff --- /dev/null +++ b/Assets/Fungus/Thirdparty/Reorderable List Field/Support/API Reference.chm.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: ff01767a12436d745bc2fc6157a4f303 +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Fungus/Thirdparty/Reorderable List Field/Support/API Reference.chw b/Assets/Fungus/Thirdparty/Reorderable List Field/Support/API Reference.chw new file mode 100644 index 00000000..04dc7b4d Binary files /dev/null and b/Assets/Fungus/Thirdparty/Reorderable List Field/Support/API Reference.chw differ diff --git a/Assets/Fungus/Thirdparty/Reorderable List Field/Support/API Reference.chw.meta b/Assets/Fungus/Thirdparty/Reorderable List Field/Support/API Reference.chw.meta new file mode 100644 index 00000000..c15b0473 --- /dev/null +++ b/Assets/Fungus/Thirdparty/Reorderable List Field/Support/API Reference.chw.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 2a6cc2b87d678a44f9aac32c49b2373f +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Fungus/Thirdparty/Reorderable List Field/Support/Resources.zip b/Assets/Fungus/Thirdparty/Reorderable List Field/Support/Resources.zip new file mode 100644 index 00000000..1e16dc7c Binary files /dev/null and b/Assets/Fungus/Thirdparty/Reorderable List Field/Support/Resources.zip differ diff --git a/Assets/Fungus/Thirdparty/Reorderable List Field/Support/Resources.zip.meta b/Assets/Fungus/Thirdparty/Reorderable List Field/Support/Resources.zip.meta new file mode 100644 index 00000000..ce39de24 --- /dev/null +++ b/Assets/Fungus/Thirdparty/Reorderable List Field/Support/Resources.zip.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 560954e67fbf14b43a2d6638190e8325 +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Fungus/Thirdparty/Reorderable List Field/Support/User Guide.pdf b/Assets/Fungus/Thirdparty/Reorderable List Field/Support/User Guide.pdf new file mode 100644 index 00000000..fdd90b29 Binary files /dev/null and b/Assets/Fungus/Thirdparty/Reorderable List Field/Support/User Guide.pdf differ diff --git a/Assets/Fungus/Thirdparty/Reorderable List Field/Support/User Guide.pdf.meta b/Assets/Fungus/Thirdparty/Reorderable List Field/Support/User Guide.pdf.meta new file mode 100644 index 00000000..ed12ff96 --- /dev/null +++ b/Assets/Fungus/Thirdparty/Reorderable List Field/Support/User Guide.pdf.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 397430eb6d7634449b41b059589c33bc +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Fungus/Thirdparty/Reorderable List Field/preview.gif b/Assets/Fungus/Thirdparty/Reorderable List Field/preview.gif new file mode 100644 index 00000000..6690891a Binary files /dev/null and b/Assets/Fungus/Thirdparty/Reorderable List Field/preview.gif differ diff --git a/Assets/Fungus/Thirdparty/Reorderable List Field/preview.gif.meta b/Assets/Fungus/Thirdparty/Reorderable List Field/preview.gif.meta new file mode 100644 index 00000000..14f0b881 --- /dev/null +++ b/Assets/Fungus/Thirdparty/Reorderable List Field/preview.gif.meta @@ -0,0 +1,86 @@ +fileFormatVersion: 2 +guid: 195bac68939599148a3fbf5108bcfc20 +TextureImporter: + fileIDToRecycleName: {} + externalObjects: {} + serializedVersion: 6 + mipmaps: + mipMapMode: 0 + enableMipMap: 0 + sRGBTexture: 1 + linearTexture: 0 + fadeOut: 0 + borderMipMap: 0 + mipMapsPreserveCoverage: 0 + alphaTestReferenceValue: 0.5 + mipMapFadeDistanceStart: 1 + mipMapFadeDistanceEnd: 3 + bumpmap: + convertToNormalMap: 0 + externalNormalMap: 0 + heightScale: 0.25 + normalMapFilter: 0 + isReadable: 0 + streamingMipmaps: 0 + streamingMipmapsPriority: 0 + grayScaleToAlpha: 0 + generateCubemap: 6 + cubemapConvolution: 0 + seamlessCubemap: 0 + textureFormat: 1 + maxTextureSize: 2048 + textureSettings: + serializedVersion: 2 + filterMode: -1 + aniso: -1 + mipBias: -100 + wrapU: 1 + wrapV: 1 + wrapW: 1 + nPOTScale: 0 + lightmap: 0 + compressionQuality: 50 + spriteMode: 1 + spriteExtrude: 1 + spriteMeshType: 1 + alignment: 0 + spritePivot: {x: 0.5, y: 0.5} + spritePixelsToUnits: 100 + spriteBorder: {x: 0, y: 0, z: 0, w: 0} + spriteGenerateFallbackPhysicsShape: 1 + alphaUsage: 1 + alphaIsTransparency: 1 + spriteTessellationDetail: -1 + textureType: 8 + textureShape: 1 + singleChannelComponent: 0 + maxTextureSizeSet: 0 + compressionQualitySet: 0 + textureFormatSet: 0 + platformSettings: + - serializedVersion: 2 + buildTarget: DefaultTexturePlatform + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + androidETC2FallbackOverride: 0 + spriteSheet: + serializedVersion: 2 + sprites: [] + outline: [] + physicsShape: [] + bones: [] + spriteID: d7ebb509f3bb7c54e835241e12983aa1 + vertices: [] + indices: + edges: [] + weights: [] + spritePackingTag: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Fungus/Thirdparty/Reorderable List Field/screenshot.png b/Assets/Fungus/Thirdparty/Reorderable List Field/screenshot.png new file mode 100644 index 00000000..b06af9a5 Binary files /dev/null and b/Assets/Fungus/Thirdparty/Reorderable List Field/screenshot.png differ diff --git a/Assets/Fungus/Thirdparty/Reorderable List Field/screenshot.png.meta b/Assets/Fungus/Thirdparty/Reorderable List Field/screenshot.png.meta new file mode 100644 index 00000000..d243a129 --- /dev/null +++ b/Assets/Fungus/Thirdparty/Reorderable List Field/screenshot.png.meta @@ -0,0 +1,86 @@ +fileFormatVersion: 2 +guid: ab7d0b47fabb22f4f84981c741f083f9 +TextureImporter: + fileIDToRecycleName: {} + externalObjects: {} + serializedVersion: 6 + mipmaps: + mipMapMode: 0 + enableMipMap: 0 + sRGBTexture: 1 + linearTexture: 0 + fadeOut: 0 + borderMipMap: 0 + mipMapsPreserveCoverage: 0 + alphaTestReferenceValue: 0.5 + mipMapFadeDistanceStart: 1 + mipMapFadeDistanceEnd: 3 + bumpmap: + convertToNormalMap: 0 + externalNormalMap: 0 + heightScale: 0.25 + normalMapFilter: 0 + isReadable: 0 + streamingMipmaps: 0 + streamingMipmapsPriority: 0 + grayScaleToAlpha: 0 + generateCubemap: 6 + cubemapConvolution: 0 + seamlessCubemap: 0 + textureFormat: 1 + maxTextureSize: 2048 + textureSettings: + serializedVersion: 2 + filterMode: -1 + aniso: -1 + mipBias: -100 + wrapU: 1 + wrapV: 1 + wrapW: 1 + nPOTScale: 0 + lightmap: 0 + compressionQuality: 50 + spriteMode: 1 + spriteExtrude: 1 + spriteMeshType: 1 + alignment: 0 + spritePivot: {x: 0.5, y: 0.5} + spritePixelsToUnits: 100 + spriteBorder: {x: 0, y: 0, z: 0, w: 0} + spriteGenerateFallbackPhysicsShape: 1 + alphaUsage: 1 + alphaIsTransparency: 1 + spriteTessellationDetail: -1 + textureType: 8 + textureShape: 1 + singleChannelComponent: 0 + maxTextureSizeSet: 0 + compressionQualitySet: 0 + textureFormatSet: 0 + platformSettings: + - serializedVersion: 2 + buildTarget: DefaultTexturePlatform + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + androidETC2FallbackOverride: 0 + spriteSheet: + serializedVersion: 2 + sprites: [] + outline: [] + physicsShape: [] + bones: [] + spriteID: 21a9e3756c473cb4daeeb1820c46b5e2 + vertices: [] + indices: + edges: [] + weights: [] + spritePackingTag: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/UnityTestTools/IntegrationTestsFramework/TestRunner/Editor/IntegrationTestsRunnerWindow.cs b/Assets/UnityTestTools/IntegrationTestsFramework/TestRunner/Editor/IntegrationTestsRunnerWindow.cs index 152b7b3a..96be653f 100644 --- a/Assets/UnityTestTools/IntegrationTestsFramework/TestRunner/Editor/IntegrationTestsRunnerWindow.cs +++ b/Assets/UnityTestTools/IntegrationTestsFramework/TestRunner/Editor/IntegrationTestsRunnerWindow.cs @@ -59,8 +59,13 @@ namespace UnityTest { EditorApplication.hierarchyWindowItemOnGUI -= OnHierarchyWindowItemDraw; EditorApplication.hierarchyWindowItemOnGUI += OnHierarchyWindowItemDraw; +#if UNITY_2018_1_OR_NEWER EditorApplication.hierarchyChanged -= OnHierarchyChangeUpdate; EditorApplication.hierarchyChanged += OnHierarchyChangeUpdate; +#else + EditorApplication.hierarchyWindowChanged -= OnHierarchyChangeUpdate; + EditorApplication.hierarchyWindowChanged += OnHierarchyChangeUpdate; +#endif EditorApplication.update -= BackgroundSceneChangeWatch; EditorApplication.update += BackgroundSceneChangeWatch; #if UNITY_2017_2_OR_NEWER @@ -86,7 +91,11 @@ namespace UnityTest { EditorApplication.hierarchyWindowItemOnGUI -= OnHierarchyWindowItemDraw; EditorApplication.update -= BackgroundSceneChangeWatch; +#if UNITY_2018_1_OR_NEWER EditorApplication.hierarchyChanged -= OnHierarchyChangeUpdate; +#else + EditorApplication.hierarchyWindowChanged -= OnHierarchyChangeUpdate; +#endif #if UNITY_2017_2_OR_NEWER EditorApplication.playModeStateChanged -= OnPlaymodeStateChanged; #else diff --git a/Assets/UnityTestTools/IntegrationTestsFramework/TestRunner/Editor/PlatformRunner/PlayerSettingConfigurator.cs b/Assets/UnityTestTools/IntegrationTestsFramework/TestRunner/Editor/PlatformRunner/PlayerSettingConfigurator.cs index cd729b20..18978890 100644 --- a/Assets/UnityTestTools/IntegrationTestsFramework/TestRunner/Editor/PlatformRunner/PlayerSettingConfigurator.cs +++ b/Assets/UnityTestTools/IntegrationTestsFramework/TestRunner/Editor/PlatformRunner/PlayerSettingConfigurator.cs @@ -18,7 +18,12 @@ namespace UnityTest private ResolutionDialogSetting m_DisplayResolutionDialog; private bool m_RunInBackground; + +#if UNITY_2018_1_OR_NEWER private FullScreenMode m_FullScreen; +#else + private bool m_FullScreen; +#endif private bool m_ResizableWindow; private readonly List m_TempFileList = new List(); @@ -34,9 +39,13 @@ namespace UnityTest m_RunInBackground = PlayerSettings.runInBackground; PlayerSettings.runInBackground = true; - +#if UNITY_2018_1_OR_NEWER m_FullScreen = PlayerSettings.fullScreenMode; PlayerSettings.fullScreenMode = FullScreenMode.Windowed; +#else + m_FullScreen = PlayerSettings.defaultIsFullScreen; + PlayerSettings.defaultIsFullScreen = false; +#endif m_ResizableWindow = PlayerSettings.resizableWindow; PlayerSettings.resizableWindow = true; @@ -44,7 +53,11 @@ namespace UnityTest public void RevertSettingsChanges() { +#if UNITY_2018_1_OR_NEWER PlayerSettings.fullScreenMode = m_FullScreen; +#else + PlayerSettings.defaultIsFullScreen = m_FullScreen; +#endif PlayerSettings.runInBackground = m_RunInBackground; PlayerSettings.displayResolutionDialog = m_DisplayResolutionDialog; PlayerSettings.resizableWindow = m_ResizableWindow; diff --git a/Packages/manifest.json b/Packages/manifest.json index 526aca60..1342d0a7 100644 --- a/Packages/manifest.json +++ b/Packages/manifest.json @@ -1,4 +1,39 @@ { - "dependencies": { - } + "dependencies": { + "com.unity.ads": "2.0.8", + "com.unity.analytics": "2.0.16", + "com.unity.package-manager-ui": "1.9.11", + "com.unity.purchasing": "2.0.3", + "com.unity.textmeshpro": "1.2.4", + "com.unity.modules.ai": "1.0.0", + "com.unity.modules.animation": "1.0.0", + "com.unity.modules.assetbundle": "1.0.0", + "com.unity.modules.audio": "1.0.0", + "com.unity.modules.cloth": "1.0.0", + "com.unity.modules.director": "1.0.0", + "com.unity.modules.imageconversion": "1.0.0", + "com.unity.modules.imgui": "1.0.0", + "com.unity.modules.jsonserialize": "1.0.0", + "com.unity.modules.particlesystem": "1.0.0", + "com.unity.modules.physics": "1.0.0", + "com.unity.modules.physics2d": "1.0.0", + "com.unity.modules.screencapture": "1.0.0", + "com.unity.modules.terrain": "1.0.0", + "com.unity.modules.terrainphysics": "1.0.0", + "com.unity.modules.tilemap": "1.0.0", + "com.unity.modules.ui": "1.0.0", + "com.unity.modules.uielements": "1.0.0", + "com.unity.modules.umbra": "1.0.0", + "com.unity.modules.unityanalytics": "1.0.0", + "com.unity.modules.unitywebrequest": "1.0.0", + "com.unity.modules.unitywebrequestassetbundle": "1.0.0", + "com.unity.modules.unitywebrequestaudio": "1.0.0", + "com.unity.modules.unitywebrequesttexture": "1.0.0", + "com.unity.modules.unitywebrequestwww": "1.0.0", + "com.unity.modules.vehicles": "1.0.0", + "com.unity.modules.video": "1.0.0", + "com.unity.modules.vr": "1.0.0", + "com.unity.modules.wind": "1.0.0", + "com.unity.modules.xr": "1.0.0" + } }