desktop-maesty/steve
6 years ago
85 changed files with 5615 additions and 1849 deletions
@ -0,0 +1,8 @@ |
|||||||
|
fileFormatVersion: 2 |
||||||
|
guid: a747a40b0f1ab6f48b28b29fdb77f2ed |
||||||
|
folderAsset: yes |
||||||
|
DefaultImporter: |
||||||
|
externalObjects: {} |
||||||
|
userData: |
||||||
|
assetBundleName: |
||||||
|
assetBundleVariant: |
@ -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<string> wishlist = new List<string>(); |
||||||
|
public List<Vector2> points = new List<Vector2>(); |
||||||
|
|
||||||
|
} |
@ -0,0 +1,11 @@ |
|||||||
|
fileFormatVersion: 2 |
||||||
|
guid: acf5477b21448904ebe3636dcb6a0276 |
||||||
|
MonoImporter: |
||||||
|
externalObjects: {} |
||||||
|
serializedVersion: 2 |
||||||
|
defaultReferences: [] |
||||||
|
executionOrder: 0 |
||||||
|
icon: {instanceID: 0} |
||||||
|
userData: |
||||||
|
assetBundleName: |
||||||
|
assetBundleVariant: |
@ -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.<String> = new List.<String>(); |
||||||
|
var points:List.<Vector2> = new List.<Vector2>(); |
@ -0,0 +1,11 @@ |
|||||||
|
fileFormatVersion: 2 |
||||||
|
guid: 253f52cce58987b4e8f2108722555925 |
||||||
|
MonoImporter: |
||||||
|
externalObjects: {} |
||||||
|
serializedVersion: 2 |
||||||
|
defaultReferences: [] |
||||||
|
executionOrder: 0 |
||||||
|
icon: {instanceID: 0} |
||||||
|
userData: |
||||||
|
assetBundleName: |
||||||
|
assetBundleVariant: |
@ -0,0 +1,8 @@ |
|||||||
|
fileFormatVersion: 2 |
||||||
|
guid: bd53be4000846a648b766b6c79bf6bbd |
||||||
|
folderAsset: yes |
||||||
|
DefaultImporter: |
||||||
|
externalObjects: {} |
||||||
|
userData: |
||||||
|
assetBundleName: |
||||||
|
assetBundleVariant: |
@ -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(); |
||||||
|
} |
||||||
|
|
||||||
|
} |
@ -0,0 +1,11 @@ |
|||||||
|
fileFormatVersion: 2 |
||||||
|
guid: 036558d96cb3f6a418344bd5fb29215e |
||||||
|
MonoImporter: |
||||||
|
externalObjects: {} |
||||||
|
serializedVersion: 2 |
||||||
|
defaultReferences: [] |
||||||
|
executionOrder: 0 |
||||||
|
icon: {instanceID: 0} |
||||||
|
userData: |
||||||
|
assetBundleName: |
||||||
|
assetBundleVariant: |
@ -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<MultiListEditorWindowDemo>("Multi List"); |
||||||
|
} |
||||||
|
|
||||||
|
private class ExampleListAdaptor : GenericListAdaptor<string>, 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<string> 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<string> _shoppingList; |
||||||
|
private ExampleListAdaptor _shoppingListAdaptor; |
||||||
|
|
||||||
|
private List<string> _purchaseList; |
||||||
|
private ExampleListAdaptor _purchaseListAdaptor; |
||||||
|
|
||||||
|
private void OnEnable() { |
||||||
|
_shoppingList = new List<string>() { "Bread", "Carrots", "Beans", "Steak", "Coffee", "Fries" }; |
||||||
|
_shoppingListAdaptor = new ExampleListAdaptor(_shoppingList); |
||||||
|
|
||||||
|
_purchaseList = new List<string>() { "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(); |
||||||
|
} |
||||||
|
|
||||||
|
} |
@ -0,0 +1,11 @@ |
|||||||
|
fileFormatVersion: 2 |
||||||
|
guid: a42361912a901e04bbe1405e84b81b8d |
||||||
|
MonoImporter: |
||||||
|
externalObjects: {} |
||||||
|
serializedVersion: 2 |
||||||
|
defaultReferences: [] |
||||||
|
executionOrder: 0 |
||||||
|
icon: {instanceID: 0} |
||||||
|
userData: |
||||||
|
assetBundleName: |
||||||
|
assetBundleVariant: |
@ -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<ReorderableListDemo>("List Demo"); |
||||||
|
} |
||||||
|
|
||||||
|
public List<string> shoppingList; |
||||||
|
public List<string> purchaseList; |
||||||
|
|
||||||
|
private void OnEnable() { |
||||||
|
shoppingList = new List<string>(); |
||||||
|
shoppingList.Add("Bread"); |
||||||
|
shoppingList.Add("Carrots"); |
||||||
|
shoppingList.Add("Beans"); |
||||||
|
shoppingList.Add("Steak"); |
||||||
|
shoppingList.Add("Coffee"); |
||||||
|
shoppingList.Add("Fries"); |
||||||
|
|
||||||
|
purchaseList = new List<string>(); |
||||||
|
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); |
||||||
|
} |
||||||
|
|
||||||
|
} |
@ -0,0 +1,11 @@ |
|||||||
|
fileFormatVersion: 2 |
||||||
|
guid: a8187beba641e99409b4648cca1becd3 |
||||||
|
MonoImporter: |
||||||
|
externalObjects: {} |
||||||
|
serializedVersion: 2 |
||||||
|
defaultReferences: [] |
||||||
|
executionOrder: 0 |
||||||
|
icon: {instanceID: 0} |
||||||
|
userData: |
||||||
|
assetBundleName: |
||||||
|
assetBundleVariant: |
@ -1,9 +1,8 @@ |
|||||||
fileFormatVersion: 2 |
fileFormatVersion: 2 |
||||||
guid: 1351e3cf05fcef04cbafc172b277cd32 |
guid: 1351e3cf05fcef04cbafc172b277cd32 |
||||||
folderAsset: yes |
folderAsset: yes |
||||||
timeCreated: 1434110041 |
|
||||||
licenseType: Free |
|
||||||
DefaultImporter: |
DefaultImporter: |
||||||
|
externalObjects: {} |
||||||
userData: |
userData: |
||||||
assetBundleName: |
assetBundleName: |
||||||
assetBundleVariant: |
assetBundleVariant: |
||||||
|
Binary file not shown.
@ -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: |
|
File diff suppressed because it is too large
Load Diff
@ -1,6 +0,0 @@ |
|||||||
fileFormatVersion: 2 |
|
||||||
guid: 087430efbff5ee54a8c8273aee1508fc |
|
||||||
TextScriptImporter: |
|
||||||
userData: |
|
||||||
assetBundleName: |
|
||||||
assetBundleVariant: |
|
@ -0,0 +1,8 @@ |
|||||||
|
fileFormatVersion: 2 |
||||||
|
guid: 646cdcce8adedda43a7b99aaefae2f4a |
||||||
|
folderAsset: yes |
||||||
|
DefaultImporter: |
||||||
|
externalObjects: {} |
||||||
|
userData: |
||||||
|
assetBundleName: |
||||||
|
assetBundleVariant: |
@ -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 { |
||||||
|
|
||||||
|
/// <summary> |
||||||
|
/// Factory methods that create <see cref="IElementAdderMenuBuilder{TContext}"/> |
||||||
|
/// instances that can then be used to build element adder menus. |
||||||
|
/// </summary> |
||||||
|
/// <example> |
||||||
|
/// <para>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:</para> |
||||||
|
/// <code language="csharp"><![CDATA[ |
||||||
|
/// public class ShoppingListElementAdder : IElementAdder<ShoppingList> { |
||||||
|
/// 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<ShoppingList>(ShoppingItem); |
||||||
|
/// builder.SetElementAdder(new ShoppingListElementAdder(shoppingList)); |
||||||
|
/// var menu = builder.GetMenu(); |
||||||
|
/// menu.DropDown(buttonPosition); |
||||||
|
/// } |
||||||
|
/// } |
||||||
|
/// ]]></code> |
||||||
|
/// <code language="unityscript"><![CDATA[ |
||||||
|
/// public class ShoppingListElementAdder extends IElementAdder.<ShoppingList> { |
||||||
|
/// 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.<ShoppingList>(ShoppingItem); |
||||||
|
/// builder.SetElementAdder(new ShoppingListElementAdder(shoppingList)); |
||||||
|
/// var menu = builder.GetMenu(); |
||||||
|
/// menu.DropDown(buttonPosition); |
||||||
|
/// } |
||||||
|
/// } |
||||||
|
/// ]]></code> |
||||||
|
/// </example> |
||||||
|
public static class ElementAdderMenuBuilder { |
||||||
|
|
||||||
|
/// <summary> |
||||||
|
/// Gets a <see cref="IElementAdderMenuBuilder{TContext}"/> to build an element |
||||||
|
/// adder menu for a context object of the type <typeparamref name="TContext"/>. |
||||||
|
/// </summary> |
||||||
|
/// <typeparam name="TContext">Type of the context object that elements can be added to.</typeparam> |
||||||
|
/// <returns> |
||||||
|
/// A new <see cref="IElementAdderMenuBuilder{TContext}"/> instance. |
||||||
|
/// </returns> |
||||||
|
/// <seealso cref="IElementAdderMenuBuilder{TContext}.SetContractType(Type)"/> |
||||||
|
public static IElementAdderMenuBuilder<TContext> For<TContext>() { |
||||||
|
return new GenericElementAdderMenuBuilder<TContext>(); |
||||||
|
} |
||||||
|
|
||||||
|
/// <summary> |
||||||
|
/// Gets a <see cref="IElementAdderMenuBuilder{TContext}"/> to build an element |
||||||
|
/// adder menu for a context object of the type <typeparamref name="TContext"/>. |
||||||
|
/// </summary> |
||||||
|
/// <typeparam name="TContext">Type of the context object that elements can be added to.</typeparam> |
||||||
|
/// <param name="contractType">Contract type of addable elements.</param> |
||||||
|
/// <returns> |
||||||
|
/// A new <see cref="IElementAdderMenuBuilder{TContext}"/> instance. |
||||||
|
/// </returns> |
||||||
|
/// <seealso cref="IElementAdderMenuBuilder{TContext}.SetContractType(Type)"/> |
||||||
|
public static IElementAdderMenuBuilder<TContext> For<TContext>(Type contractType) { |
||||||
|
var builder = For<TContext>(); |
||||||
|
builder.SetContractType(contractType); |
||||||
|
return builder; |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
} |
@ -0,0 +1,11 @@ |
|||||||
|
fileFormatVersion: 2 |
||||||
|
guid: e6152605dacd77c4db43aa59c2498ba6 |
||||||
|
MonoImporter: |
||||||
|
externalObjects: {} |
||||||
|
serializedVersion: 2 |
||||||
|
defaultReferences: [] |
||||||
|
executionOrder: 0 |
||||||
|
icon: {instanceID: 0} |
||||||
|
userData: |
||||||
|
assetBundleName: |
||||||
|
assetBundleVariant: |
@ -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 { |
||||||
|
|
||||||
|
/// <summary> |
||||||
|
/// Annotate <see cref="IElementAdderMenuCommand{TContext}"/> implementations with a |
||||||
|
/// <see cref="ElementAdderMenuCommandAttribute"/> to associate it with the contract |
||||||
|
/// type of addable elements. |
||||||
|
/// </summary> |
||||||
|
/// <example> |
||||||
|
/// <para>The following source code demonstrates how to add a helper menu command to |
||||||
|
/// the add element menu of a shopping list:</para> |
||||||
|
/// <code language="csharp"><![CDATA[ |
||||||
|
/// [ElementAdderMenuCommand(typeof(ShoppingItem))] |
||||||
|
/// public class AddFavoriteShoppingItemsCommand : IElementAdderMenuCommand<ShoppingList> { |
||||||
|
/// public AddFavoriteShoppingItemsCommand() { |
||||||
|
/// Content = new GUIContent("Add Favorite Items"); |
||||||
|
/// } |
||||||
|
/// |
||||||
|
/// public GUIContent Content { get; private set; } |
||||||
|
/// |
||||||
|
/// public bool CanExecute(IElementAdder<ShoppingList> elementAdder) { |
||||||
|
/// return true; |
||||||
|
/// } |
||||||
|
/// public void Execute(IElementAdder<ShoppingList> elementAdder) { |
||||||
|
/// // TODO: Add favorite items to the shopping list! |
||||||
|
/// } |
||||||
|
/// } |
||||||
|
/// ]]></code> |
||||||
|
/// <code language="unityscript"><![CDATA[ |
||||||
|
/// @ElementAdderMenuCommand(ShoppingItem) |
||||||
|
/// class AddFavoriteShoppingItemsCommand extends IElementAdderMenuCommand.<ShoppingList> { |
||||||
|
/// var _content:GUIContent = new GUIContent('Add Favorite Items'); |
||||||
|
/// |
||||||
|
/// function get Content():GUIContent { return _content; } |
||||||
|
/// |
||||||
|
/// function CanExecute(elementAdder:IElementAdder.<ShoppingList>):boolean { |
||||||
|
/// return true; |
||||||
|
/// } |
||||||
|
/// function Execute(elementAdder:IElementAdder.<ShoppingList>) { |
||||||
|
/// // TODO: Add favorite items to the shopping list! |
||||||
|
/// } |
||||||
|
/// } |
||||||
|
/// ]]></code> |
||||||
|
/// </example> |
||||||
|
[AttributeUsage(AttributeTargets.Class, AllowMultiple = true, Inherited = false)] |
||||||
|
public sealed class ElementAdderMenuCommandAttribute : Attribute { |
||||||
|
|
||||||
|
/// <summary> |
||||||
|
/// Initializes a new instance of the <see cref="ElementAdderMenuCommandAttribute"/> class. |
||||||
|
/// </summary> |
||||||
|
/// <param name="contractType">Contract type of addable elements.</param> |
||||||
|
public ElementAdderMenuCommandAttribute(Type contractType) { |
||||||
|
ContractType = contractType; |
||||||
|
} |
||||||
|
|
||||||
|
/// <summary> |
||||||
|
/// Gets the contract type of addable elements. |
||||||
|
/// </summary> |
||||||
|
public Type ContractType { get; private set; } |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
} |
@ -0,0 +1,11 @@ |
|||||||
|
fileFormatVersion: 2 |
||||||
|
guid: dab0906e0834f954b9c6427d5af66288 |
||||||
|
MonoImporter: |
||||||
|
externalObjects: {} |
||||||
|
serializedVersion: 2 |
||||||
|
defaultReferences: [] |
||||||
|
executionOrder: 0 |
||||||
|
icon: {instanceID: 0} |
||||||
|
userData: |
||||||
|
assetBundleName: |
||||||
|
assetBundleVariant: |
@ -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 { |
||||||
|
|
||||||
|
/// <summary> |
||||||
|
/// Provides meta information which is useful when creating new implementations of |
||||||
|
/// the <see cref="IElementAdderMenuBuilder{TContext}"/> interface. |
||||||
|
/// </summary> |
||||||
|
public static class ElementAdderMeta { |
||||||
|
|
||||||
|
#region Adder Menu Command Types |
||||||
|
|
||||||
|
private static Dictionary<Type, Dictionary<Type, List<Type>>> s_ContextMap = new Dictionary<Type, Dictionary<Type, List<Type>>>(); |
||||||
|
|
||||||
|
private static IEnumerable<Type> GetMenuCommandTypes<TContext>() { |
||||||
|
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<TContext>).IsAssignableFrom(t) |
||||||
|
select t; |
||||||
|
} |
||||||
|
|
||||||
|
/// <summary> |
||||||
|
/// Gets an array of the <see cref="IElementAdderMenuCommand{TContext}"/> types |
||||||
|
/// that are associated with the specified <paramref name="contractType"/>. |
||||||
|
/// </summary> |
||||||
|
/// <typeparam name="TContext">Type of the context object that elements can be added to.</typeparam> |
||||||
|
/// <param name="contractType">Contract type of addable elements.</param> |
||||||
|
/// <returns> |
||||||
|
/// An array containing zero or more <see cref="System.Type"/>. |
||||||
|
/// </returns> |
||||||
|
/// <exception cref="System.ArgumentNullException"> |
||||||
|
/// If <paramref name="contractType"/> is <c>null</c>. |
||||||
|
/// </exception> |
||||||
|
/// <seealso cref="GetMenuCommands{TContext}(Type)"/> |
||||||
|
public static Type[] GetMenuCommandTypes<TContext>(Type contractType) { |
||||||
|
if (contractType == null) |
||||||
|
throw new ArgumentNullException("contractType"); |
||||||
|
|
||||||
|
Dictionary<Type, List<Type>> contractMap; |
||||||
|
List<Type> commandTypes; |
||||||
|
if (s_ContextMap.TryGetValue(typeof(TContext), out contractMap)) { |
||||||
|
if (contractMap.TryGetValue(contractType, out commandTypes)) |
||||||
|
return commandTypes.ToArray(); |
||||||
|
} |
||||||
|
else { |
||||||
|
contractMap = new Dictionary<Type, List<Type>>(); |
||||||
|
s_ContextMap[typeof(TContext)] = contractMap; |
||||||
|
} |
||||||
|
|
||||||
|
commandTypes = new List<Type>(); |
||||||
|
|
||||||
|
foreach (var commandType in GetMenuCommandTypes<TContext>()) { |
||||||
|
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(); |
||||||
|
} |
||||||
|
|
||||||
|
/// <summary> |
||||||
|
/// Gets an array of <see cref="IElementAdderMenuCommand{TContext}"/> instances |
||||||
|
/// that are associated with the specified <paramref name="contractType"/>. |
||||||
|
/// </summary> |
||||||
|
/// <typeparam name="TContext">Type of the context object that elements can be added to.</typeparam> |
||||||
|
/// <param name="contractType">Contract type of addable elements.</param> |
||||||
|
/// <returns> |
||||||
|
/// An array containing zero or more <see cref="IElementAdderMenuCommand{TContext}"/> instances. |
||||||
|
/// </returns> |
||||||
|
/// <exception cref="System.ArgumentNullException"> |
||||||
|
/// If <paramref name="contractType"/> is <c>null</c>. |
||||||
|
/// </exception> |
||||||
|
/// <seealso cref="GetMenuCommandTypes{TContext}(Type)"/> |
||||||
|
public static IElementAdderMenuCommand<TContext>[] GetMenuCommands<TContext>(Type contractType) { |
||||||
|
var commandTypes = GetMenuCommandTypes<TContext>(contractType); |
||||||
|
var commands = new IElementAdderMenuCommand<TContext>[commandTypes.Length]; |
||||||
|
for (int i = 0; i < commandTypes.Length; ++i) |
||||||
|
commands[i] = (IElementAdderMenuCommand<TContext>)Activator.CreateInstance(commandTypes[i]); |
||||||
|
return commands; |
||||||
|
} |
||||||
|
|
||||||
|
#endregion |
||||||
|
|
||||||
|
#region Concrete Element Types |
||||||
|
|
||||||
|
private static Dictionary<Type, Type[]> s_ConcreteElementTypes = new Dictionary<Type, Type[]>(); |
||||||
|
|
||||||
|
private static IEnumerable<Type> 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; |
||||||
|
} |
||||||
|
|
||||||
|
/// <summary> |
||||||
|
/// Gets a filtered array of the concrete element types that implement the |
||||||
|
/// specified <paramref name="contractType"/>. |
||||||
|
/// </summary> |
||||||
|
/// <remarks> |
||||||
|
/// <para>A type is excluded from the resulting array when one or more of the |
||||||
|
/// specified <paramref name="filters"/> returns a value of <c>false</c>.</para> |
||||||
|
/// </remarks> |
||||||
|
/// <param name="contractType">Contract type of addable elements.</param> |
||||||
|
/// <param name="filters">An array of zero or more filters.</param> |
||||||
|
/// <returns> |
||||||
|
/// An array of zero or more concrete element types. |
||||||
|
/// </returns> |
||||||
|
/// <exception cref="System.ArgumentNullException"> |
||||||
|
/// If <paramref name="contractType"/> is <c>null</c>. |
||||||
|
/// </exception> |
||||||
|
/// <seealso cref="GetConcreteElementTypes(Type)"/> |
||||||
|
public static Type[] GetConcreteElementTypes(Type contractType, Func<Type, bool>[] filters) { |
||||||
|
return |
||||||
|
(from t in GetConcreteElementTypesHelper(contractType) |
||||||
|
where IsTypeIncluded(t, filters) |
||||||
|
select t |
||||||
|
).ToArray(); |
||||||
|
} |
||||||
|
|
||||||
|
/// <summary> |
||||||
|
/// Gets an array of all the concrete element types that implement the specified |
||||||
|
/// <paramref name="contractType"/>. |
||||||
|
/// </summary> |
||||||
|
/// <param name="contractType">Contract type of addable elements.</param> |
||||||
|
/// <returns> |
||||||
|
/// An array of zero or more concrete element types. |
||||||
|
/// </returns> |
||||||
|
/// <exception cref="System.ArgumentNullException"> |
||||||
|
/// If <paramref name="contractType"/> is <c>null</c>. |
||||||
|
/// </exception> |
||||||
|
/// <seealso cref="GetConcreteElementTypes(Type, Func{Type, bool}[])"/> |
||||||
|
public static Type[] GetConcreteElementTypes(Type contractType) { |
||||||
|
return GetConcreteElementTypesHelper(contractType).ToArray(); |
||||||
|
} |
||||||
|
|
||||||
|
private static bool IsTypeIncluded(Type concreteType, Func<Type, bool>[] filters) { |
||||||
|
if (filters != null) |
||||||
|
foreach (var filter in filters) |
||||||
|
if (!filter(concreteType)) |
||||||
|
return false; |
||||||
|
return true; |
||||||
|
} |
||||||
|
|
||||||
|
#endregion |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
} |
@ -0,0 +1,11 @@ |
|||||||
|
fileFormatVersion: 2 |
||||||
|
guid: 159bf54b15add1440aaed680e94b81fc |
||||||
|
MonoImporter: |
||||||
|
externalObjects: {} |
||||||
|
serializedVersion: 2 |
||||||
|
defaultReferences: [] |
||||||
|
executionOrder: 0 |
||||||
|
icon: {instanceID: 0} |
||||||
|
userData: |
||||||
|
assetBundleName: |
||||||
|
assetBundleVariant: |
@ -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); |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
} |
@ -0,0 +1,11 @@ |
|||||||
|
fileFormatVersion: 2 |
||||||
|
guid: 662b5dcb25b78f94f9afe8d3f402b628 |
||||||
|
MonoImporter: |
||||||
|
externalObjects: {} |
||||||
|
serializedVersion: 2 |
||||||
|
defaultReferences: [] |
||||||
|
executionOrder: 0 |
||||||
|
icon: {instanceID: 0} |
||||||
|
userData: |
||||||
|
assetBundleName: |
||||||
|
assetBundleVariant: |
@ -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<TContext> : IElementAdderMenuBuilder<TContext> { |
||||||
|
|
||||||
|
private static string NicifyTypeName(Type type) { |
||||||
|
return ObjectNames.NicifyVariableName(type.Name); |
||||||
|
} |
||||||
|
|
||||||
|
private Type _contractType; |
||||||
|
private IElementAdder<TContext> _elementAdder; |
||||||
|
private Func<Type, string> _typeDisplayNameFormatter; |
||||||
|
private List<Func<Type, bool>> _typeFilters = new List<Func<Type, bool>>(); |
||||||
|
private List<IElementAdderMenuCommand<TContext>> _customCommands = new List<IElementAdderMenuCommand<TContext>>(); |
||||||
|
|
||||||
|
public GenericElementAdderMenuBuilder() { |
||||||
|
_typeDisplayNameFormatter = NicifyTypeName; |
||||||
|
} |
||||||
|
|
||||||
|
public void SetContractType(Type contractType) { |
||||||
|
_contractType = contractType; |
||||||
|
} |
||||||
|
|
||||||
|
public void SetElementAdder(IElementAdder<TContext> elementAdder) { |
||||||
|
_elementAdder = elementAdder; |
||||||
|
} |
||||||
|
|
||||||
|
public void SetTypeDisplayNameFormatter(Func<Type, string> formatter) { |
||||||
|
_typeDisplayNameFormatter = formatter ?? NicifyTypeName; |
||||||
|
} |
||||||
|
|
||||||
|
public void AddTypeFilter(Func<Type, bool> typeFilter) { |
||||||
|
if (typeFilter == null) |
||||||
|
throw new ArgumentNullException("typeFilter"); |
||||||
|
|
||||||
|
_typeFilters.Add(typeFilter); |
||||||
|
} |
||||||
|
|
||||||
|
public void AddCustomCommand(IElementAdderMenuCommand<TContext> 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<TContext>(_contractType)); |
||||||
|
AddConcreteTypesToMenu(menu, ElementAdderMeta.GetConcreteElementTypes(_contractType, _typeFilters.ToArray())); |
||||||
|
} |
||||||
|
|
||||||
|
return menu; |
||||||
|
} |
||||||
|
|
||||||
|
private void AddCommandsToMenu(GenericElementAdderMenu menu, IList<IElementAdderMenuCommand<TContext>> 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); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
} |
@ -0,0 +1,11 @@ |
|||||||
|
fileFormatVersion: 2 |
||||||
|
guid: da8782cb7448c234fb86e9503326ce9c |
||||||
|
MonoImporter: |
||||||
|
externalObjects: {} |
||||||
|
serializedVersion: 2 |
||||||
|
defaultReferences: [] |
||||||
|
executionOrder: 0 |
||||||
|
icon: {instanceID: 0} |
||||||
|
userData: |
||||||
|
assetBundleName: |
||||||
|
assetBundleVariant: |
@ -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 { |
||||||
|
|
||||||
|
/// <summary> |
||||||
|
/// Interface for an object which adds elements to a context object of the type |
||||||
|
/// <typeparamref name="TContext"/>. |
||||||
|
/// </summary> |
||||||
|
/// <typeparam name="TContext">Type of the context object that elements can be added to.</typeparam> |
||||||
|
public interface IElementAdder<TContext> { |
||||||
|
|
||||||
|
/// <summary> |
||||||
|
/// Gets the context object. |
||||||
|
/// </summary> |
||||||
|
TContext Object { get; } |
||||||
|
|
||||||
|
/// <summary> |
||||||
|
/// Determines whether a new element of the specified <paramref name="type"/> can |
||||||
|
/// be added to the associated context object. |
||||||
|
/// </summary> |
||||||
|
/// <param name="type">Type of element to add.</param> |
||||||
|
/// <returns> |
||||||
|
/// A value of <c>true</c> if an element of the specified type can be added; |
||||||
|
/// otherwise, a value of <c>false</c>. |
||||||
|
/// </returns> |
||||||
|
bool CanAddElement(Type type); |
||||||
|
|
||||||
|
/// <summary> |
||||||
|
/// Adds an element of the specified <paramref name="type"/> to the associated |
||||||
|
/// context object. |
||||||
|
/// </summary> |
||||||
|
/// <param name="type">Type of element to add.</param> |
||||||
|
/// <returns> |
||||||
|
/// The new element. |
||||||
|
/// </returns> |
||||||
|
object AddElement(Type type); |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
} |
@ -0,0 +1,11 @@ |
|||||||
|
fileFormatVersion: 2 |
||||||
|
guid: 811c0b5125dc50746b66457b5c96741d |
||||||
|
MonoImporter: |
||||||
|
externalObjects: {} |
||||||
|
serializedVersion: 2 |
||||||
|
defaultReferences: [] |
||||||
|
executionOrder: 0 |
||||||
|
icon: {instanceID: 0} |
||||||
|
userData: |
||||||
|
assetBundleName: |
||||||
|
assetBundleVariant: |
@ -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 { |
||||||
|
|
||||||
|
/// <summary> |
||||||
|
/// Interface for a menu interface. |
||||||
|
/// </summary> |
||||||
|
public interface IElementAdderMenu { |
||||||
|
|
||||||
|
/// <summary> |
||||||
|
/// Gets a value indicating whether the menu contains any items. |
||||||
|
/// </summary> |
||||||
|
/// <value> |
||||||
|
/// <c>true</c> if the menu contains one or more items; otherwise, <c>false</c>. |
||||||
|
/// </value> |
||||||
|
bool IsEmpty { get; } |
||||||
|
|
||||||
|
/// <summary> |
||||||
|
/// Displays the drop-down menu inside an editor GUI. |
||||||
|
/// </summary> |
||||||
|
/// <remarks> |
||||||
|
/// <para>This method should only be used during <b>OnGUI</b> and <b>OnSceneGUI</b> |
||||||
|
/// events; for instance, inside an editor window, a custom inspector or scene view.</para> |
||||||
|
/// </remarks> |
||||||
|
/// <param name="position">Position of menu button in the GUI.</param> |
||||||
|
void DropDown(Rect position); |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
} |
@ -0,0 +1,11 @@ |
|||||||
|
fileFormatVersion: 2 |
||||||
|
guid: 7452dc2d2d6305947ab39a48354ab4bb |
||||||
|
MonoImporter: |
||||||
|
externalObjects: {} |
||||||
|
serializedVersion: 2 |
||||||
|
defaultReferences: [] |
||||||
|
executionOrder: 0 |
||||||
|
icon: {instanceID: 0} |
||||||
|
userData: |
||||||
|
assetBundleName: |
||||||
|
assetBundleVariant: |
@ -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 { |
||||||
|
|
||||||
|
/// <summary> |
||||||
|
/// Interface for building an <see cref="IElementAdderMenu"/>. |
||||||
|
/// </summary> |
||||||
|
/// <typeparam name="TContext">Type of the context object that elements can be added to.</typeparam> |
||||||
|
public interface IElementAdderMenuBuilder<TContext> { |
||||||
|
|
||||||
|
/// <summary> |
||||||
|
/// Sets contract type of the elements that can be included in the <see cref="IElementAdderMenu"/>. |
||||||
|
/// Only non-abstract class types that are assignable from the <paramref name="contractType"/> |
||||||
|
/// will be included in the built menu. |
||||||
|
/// </summary> |
||||||
|
/// <param name="contractType">Contract type of addable elements.</param> |
||||||
|
void SetContractType(Type contractType); |
||||||
|
|
||||||
|
/// <summary> |
||||||
|
/// Set the <see cref="IElementAdder{TContext}"/> implementation which is used |
||||||
|
/// when adding new elements to the context object. |
||||||
|
/// </summary> |
||||||
|
/// <remarks> |
||||||
|
/// <para>Specify a value of <c>null</c> for <paramref name="elementAdder"/> to |
||||||
|
/// prevent the selection of any types.</para> |
||||||
|
/// </remarks> |
||||||
|
/// <param name="elementAdder">Element adder.</param> |
||||||
|
void SetElementAdder(IElementAdder<TContext> elementAdder); |
||||||
|
|
||||||
|
/// <summary> |
||||||
|
/// Set the function that formats the display of type names in the user interface. |
||||||
|
/// </summary> |
||||||
|
/// <remarks> |
||||||
|
/// <para>Specify a value of <c>null</c> for <paramref name="formatter"/> to |
||||||
|
/// assume the default formatting function.</para> |
||||||
|
/// </remarks> |
||||||
|
/// <param name="formatter">Function that formats display name of type; or <c>null</c>.</param> |
||||||
|
void SetTypeDisplayNameFormatter(Func<Type, string> formatter); |
||||||
|
|
||||||
|
/// <summary> |
||||||
|
/// Adds a filter function which determines whether types can be included or |
||||||
|
/// whether they need to be excluded. |
||||||
|
/// </summary> |
||||||
|
/// <remarks> |
||||||
|
/// <para>If a filter function returns a value of <c>false</c> then that type |
||||||
|
/// will not be included in the menu interface.</para> |
||||||
|
/// </remarks> |
||||||
|
/// <param name="typeFilter">Filter function.</param> |
||||||
|
/// <exception cref="System.ArgumentNullException"> |
||||||
|
/// If <paramref name="typeFilter"/> is <c>null</c>. |
||||||
|
/// </exception> |
||||||
|
void AddTypeFilter(Func<Type, bool> typeFilter); |
||||||
|
|
||||||
|
/// <summary> |
||||||
|
/// Adds a custom command to the menu. |
||||||
|
/// </summary> |
||||||
|
/// <param name="command">The custom command.</param> |
||||||
|
/// <exception cref="System.ArgumentNullException"> |
||||||
|
/// If <paramref name="command"/> is <c>null</c>. |
||||||
|
/// </exception> |
||||||
|
void AddCustomCommand(IElementAdderMenuCommand<TContext> command); |
||||||
|
|
||||||
|
/// <summary> |
||||||
|
/// Builds and returns a new <see cref="IElementAdderMenu"/> instance. |
||||||
|
/// </summary> |
||||||
|
/// <returns> |
||||||
|
/// A new <see cref="IElementAdderMenu"/> instance each time the method is invoked. |
||||||
|
/// </returns> |
||||||
|
IElementAdderMenu GetMenu(); |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
} |
@ -0,0 +1,11 @@ |
|||||||
|
fileFormatVersion: 2 |
||||||
|
guid: 2810812b845cceb4e9a0f7c0de842f29 |
||||||
|
MonoImporter: |
||||||
|
externalObjects: {} |
||||||
|
serializedVersion: 2 |
||||||
|
defaultReferences: [] |
||||||
|
executionOrder: 0 |
||||||
|
icon: {instanceID: 0} |
||||||
|
userData: |
||||||
|
assetBundleName: |
||||||
|
assetBundleVariant: |
@ -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 { |
||||||
|
|
||||||
|
/// <summary> |
||||||
|
/// Interface for a menu command that can be included in an <see cref="IElementAdderMenu"/> |
||||||
|
/// either by annotating an implementation of the <see cref="IElementAdderMenuCommand{TContext}"/> |
||||||
|
/// interface with <see cref="ElementAdderMenuCommandAttribute"/> or directly by |
||||||
|
/// calling <see cref="IElementAdderMenuBuilder{TContext}.AddCustomCommand"/>. |
||||||
|
/// </summary> |
||||||
|
/// <typeparam name="TContext">Type of the context object that elements can be added to.</typeparam> |
||||||
|
public interface IElementAdderMenuCommand<TContext> { |
||||||
|
|
||||||
|
/// <summary> |
||||||
|
/// Gets the content of the menu command. |
||||||
|
/// </summary> |
||||||
|
GUIContent Content { get; } |
||||||
|
|
||||||
|
/// <summary> |
||||||
|
/// Determines whether the command can be executed. |
||||||
|
/// </summary> |
||||||
|
/// <param name="elementAdder">The associated element adder provides access to |
||||||
|
/// the <typeparamref name="TContext"/> instance.</param> |
||||||
|
/// <returns> |
||||||
|
/// A value of <c>true</c> if the command can execute; otherwise, <c>false</c>. |
||||||
|
/// </returns> |
||||||
|
bool CanExecute(IElementAdder<TContext> elementAdder); |
||||||
|
|
||||||
|
/// <summary> |
||||||
|
/// Executes the command. |
||||||
|
/// </summary> |
||||||
|
/// <param name="elementAdder">The associated element adder provides access to |
||||||
|
/// the <typeparamref name="TContext"/> instance.</param> |
||||||
|
void Execute(IElementAdder<TContext> elementAdder); |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
} |
@ -0,0 +1,11 @@ |
|||||||
|
fileFormatVersion: 2 |
||||||
|
guid: 3fc42d99c85c1bc409897df1dae25bd4 |
||||||
|
MonoImporter: |
||||||
|
externalObjects: {} |
||||||
|
serializedVersion: 2 |
||||||
|
defaultReferences: [] |
||||||
|
executionOrder: 0 |
||||||
|
icon: {instanceID: 0} |
||||||
|
userData: |
||||||
|
assetBundleName: |
||||||
|
assetBundleVariant: |
@ -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 { |
||||||
|
|
||||||
|
/// <summary> |
||||||
|
/// Reorderable list adaptor for generic list. |
||||||
|
/// </summary> |
||||||
|
/// <remarks> |
||||||
|
/// <para>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.</para> |
||||||
|
/// <para>List elements which implement the <see cref="System.ICloneable"/> interface are |
||||||
|
/// cloned using that interface upon duplication; otherwise the item value or reference is |
||||||
|
/// simply copied.</para> |
||||||
|
/// </remarks> |
||||||
|
/// <typeparam name="T">Type of list element.</typeparam> |
||||||
|
public class GenericListAdaptor<T> : IReorderableListAdaptor { |
||||||
|
|
||||||
|
private IList<T> _list; |
||||||
|
|
||||||
|
private ReorderableListControl.ItemDrawer<T> _itemDrawer; |
||||||
|
|
||||||
|
/// <summary> |
||||||
|
/// Fixed height of each list item. |
||||||
|
/// </summary> |
||||||
|
public float FixedItemHeight; |
||||||
|
|
||||||
|
/// <summary> |
||||||
|
/// Gets the underlying list data structure. |
||||||
|
/// </summary> |
||||||
|
public IList<T> List { |
||||||
|
get { return _list; } |
||||||
|
} |
||||||
|
|
||||||
|
/// <summary> |
||||||
|
/// Gets element from list. |
||||||
|
/// </summary> |
||||||
|
/// <param name="index">Zero-based index of element.</param> |
||||||
|
/// <returns> |
||||||
|
/// The element. |
||||||
|
/// </returns> |
||||||
|
public T this[int index] { |
||||||
|
get { return _list[index]; } |
||||||
|
} |
||||||
|
|
||||||
|
#region Construction |
||||||
|
|
||||||
|
/// <summary> |
||||||
|
/// Initializes a new instance of <see cref="GenericListAdaptor{T}"/>. |
||||||
|
/// </summary> |
||||||
|
/// <param name="list">The list which can be reordered.</param> |
||||||
|
/// <param name="itemDrawer">Callback to draw list item.</param> |
||||||
|
/// <param name="itemHeight">Height of list item in pixels.</param> |
||||||
|
public GenericListAdaptor(IList<T> list, ReorderableListControl.ItemDrawer<T> itemDrawer, float itemHeight) { |
||||||
|
this._list = list; |
||||||
|
this._itemDrawer = itemDrawer ?? ReorderableListGUI.DefaultItemDrawer; |
||||||
|
this.FixedItemHeight = itemHeight; |
||||||
|
} |
||||||
|
|
||||||
|
#endregion |
||||||
|
|
||||||
|
#region IReorderableListAdaptor - Implementation |
||||||
|
|
||||||
|
/// <inheritdoc/> |
||||||
|
public int Count { |
||||||
|
get { return _list.Count; } |
||||||
|
} |
||||||
|
|
||||||
|
/// <inheritdoc/> |
||||||
|
public virtual bool CanDrag(int index) { |
||||||
|
return true; |
||||||
|
} |
||||||
|
/// <inheritdoc/> |
||||||
|
public virtual bool CanRemove(int index) { |
||||||
|
return true; |
||||||
|
} |
||||||
|
|
||||||
|
/// <inheritdoc/> |
||||||
|
public virtual void Add() { |
||||||
|
_list.Add(default(T)); |
||||||
|
} |
||||||
|
/// <inheritdoc/> |
||||||
|
public virtual void Insert(int index) { |
||||||
|
_list.Insert(index, default(T)); |
||||||
|
} |
||||||
|
/// <inheritdoc/> |
||||||
|
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); |
||||||
|
} |
||||||
|
/// <inheritdoc/> |
||||||
|
public virtual void Remove(int index) { |
||||||
|
_list.RemoveAt(index); |
||||||
|
} |
||||||
|
/// <inheritdoc/> |
||||||
|
public virtual void Move(int sourceIndex, int destIndex) { |
||||||
|
if (destIndex > sourceIndex) |
||||||
|
--destIndex; |
||||||
|
|
||||||
|
T item = _list[sourceIndex]; |
||||||
|
_list.RemoveAt(sourceIndex); |
||||||
|
_list.Insert(destIndex, item); |
||||||
|
} |
||||||
|
/// <inheritdoc/> |
||||||
|
public virtual void Clear() { |
||||||
|
_list.Clear(); |
||||||
|
} |
||||||
|
|
||||||
|
/// <inheritdoc/> |
||||||
|
public virtual void BeginGUI() { |
||||||
|
} |
||||||
|
|
||||||
|
/// <inheritdoc/> |
||||||
|
public virtual void EndGUI() { |
||||||
|
} |
||||||
|
|
||||||
|
/// <inheritdoc/> |
||||||
|
public virtual void DrawItemBackground(Rect position, int index) { |
||||||
|
} |
||||||
|
|
||||||
|
/// <inheritdoc/> |
||||||
|
public virtual void DrawItem(Rect position, int index) { |
||||||
|
_list[index] = _itemDrawer(position, _list[index]); |
||||||
|
} |
||||||
|
|
||||||
|
/// <inheritdoc/> |
||||||
|
public virtual float GetItemHeight(int index) { |
||||||
|
return FixedItemHeight; |
||||||
|
} |
||||||
|
|
||||||
|
#endregion |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
} |
@ -0,0 +1,11 @@ |
|||||||
|
fileFormatVersion: 2 |
||||||
|
guid: 9860e7f6c1d1b8d45b13889a965e172f |
||||||
|
MonoImporter: |
||||||
|
externalObjects: {} |
||||||
|
serializedVersion: 2 |
||||||
|
defaultReferences: [] |
||||||
|
executionOrder: 0 |
||||||
|
icon: {instanceID: 0} |
||||||
|
userData: |
||||||
|
assetBundleName: |
||||||
|
assetBundleVariant: |
@ -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 { |
||||||
|
|
||||||
|
/// <summary> |
||||||
|
/// Adaptor allowing reorderable list control to interface with list data. |
||||||
|
/// </summary> |
||||||
|
/// <see cref="IReorderableListDropTarget"/> |
||||||
|
public interface IReorderableListAdaptor { |
||||||
|
|
||||||
|
/// <summary> |
||||||
|
/// Gets count of elements in list. |
||||||
|
/// </summary> |
||||||
|
int Count { get; } |
||||||
|
|
||||||
|
/// <summary> |
||||||
|
/// Determines whether an item can be reordered by dragging mouse. |
||||||
|
/// </summary> |
||||||
|
/// <remarks> |
||||||
|
/// <para>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.</para> |
||||||
|
/// <para>Please note that returning a value of <c>false</c> does not prevent movement |
||||||
|
/// on list item since other draggable items can be moved around it.</para> |
||||||
|
/// </remarks> |
||||||
|
/// <param name="index">Zero-based index for list element.</param> |
||||||
|
/// <returns> |
||||||
|
/// A value of <c>true</c> if item can be dragged; otherwise <c>false</c>. |
||||||
|
/// </returns> |
||||||
|
bool CanDrag(int index); |
||||||
|
/// <summary> |
||||||
|
/// Determines whether an item can be removed from list. |
||||||
|
/// </summary> |
||||||
|
/// <remarks> |
||||||
|
/// <para>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.</para> |
||||||
|
/// <para>This is redundant when <see cref="ReorderableListFlags.HideRemoveButtons"/> |
||||||
|
/// is specified.</para> |
||||||
|
/// </remarks> |
||||||
|
/// <param name="index">Zero-based index for list element.</param> |
||||||
|
/// <returns> |
||||||
|
/// A value of <c>true</c> if item can be removed; otherwise <c>false</c>. |
||||||
|
/// </returns> |
||||||
|
bool CanRemove(int index); |
||||||
|
|
||||||
|
/// <summary> |
||||||
|
/// Add new element at end of list. |
||||||
|
/// </summary> |
||||||
|
void Add(); |
||||||
|
/// <summary> |
||||||
|
/// Insert new element at specified index. |
||||||
|
/// </summary> |
||||||
|
/// <param name="index">Zero-based index for list element.</param> |
||||||
|
void Insert(int index); |
||||||
|
/// <summary> |
||||||
|
/// Duplicate existing element. |
||||||
|
/// </summary> |
||||||
|
/// <remarks> |
||||||
|
/// <para>Consider using the <see cref="System.ICloneable"/> interface to |
||||||
|
/// duplicate list elements where appropriate.</para> |
||||||
|
/// </remarks> |
||||||
|
/// <param name="index">Zero-based index of list element.</param> |
||||||
|
void Duplicate(int index); |
||||||
|
/// <summary> |
||||||
|
/// Remove element at specified index. |
||||||
|
/// </summary> |
||||||
|
/// <param name="index">Zero-based index of list element.</param> |
||||||
|
void Remove(int index); |
||||||
|
/// <summary> |
||||||
|
/// Move element from source index to destination index. |
||||||
|
/// </summary> |
||||||
|
/// <param name="sourceIndex">Zero-based index of source element.</param> |
||||||
|
/// <param name="destIndex">Zero-based index of destination element.</param> |
||||||
|
void Move(int sourceIndex, int destIndex); |
||||||
|
/// <summary> |
||||||
|
/// Clear all elements from list. |
||||||
|
/// </summary> |
||||||
|
void Clear(); |
||||||
|
|
||||||
|
/// <summary> |
||||||
|
/// Occurs before any list items are drawn. |
||||||
|
/// </summary> |
||||||
|
/// <remarks> |
||||||
|
/// <para>This method is only used to handle GUI repaint events.</para> |
||||||
|
/// </remarks> |
||||||
|
/// <see cref="EndGUI()"/> |
||||||
|
void BeginGUI(); |
||||||
|
/// <summary> |
||||||
|
/// Occurs after all list items have been drawn. |
||||||
|
/// </summary> |
||||||
|
/// <remarks> |
||||||
|
/// <para>This method is only used to handle GUI repaint events.</para> |
||||||
|
/// </remarks> |
||||||
|
/// <see cref="BeginGUI()"/> |
||||||
|
void EndGUI(); |
||||||
|
|
||||||
|
/// <summary> |
||||||
|
/// Draws background of a list item. |
||||||
|
/// </summary> |
||||||
|
/// <remarks> |
||||||
|
/// <para>This method is only used to handle GUI repaint events.</para> |
||||||
|
/// <para>Background of list item spans a slightly larger area than the main |
||||||
|
/// interface that is drawn by <see cref="DrawItem(Rect, int)"/> since it is |
||||||
|
/// drawn behind the grab handle.</para> |
||||||
|
/// </remarks> |
||||||
|
/// <param name="position">Total position of list element in GUI.</param> |
||||||
|
/// <param name="index">Zero-based index of array element.</param> |
||||||
|
void DrawItemBackground(Rect position, int index); |
||||||
|
/// <summary> |
||||||
|
/// Draws main interface for a list item. |
||||||
|
/// </summary> |
||||||
|
/// <remarks> |
||||||
|
/// <para>This method is used to handle all GUI events.</para> |
||||||
|
/// </remarks> |
||||||
|
/// <param name="position">Position in GUI.</param> |
||||||
|
/// <param name="index">Zero-based index of array element.</param> |
||||||
|
void DrawItem(Rect position, int index); |
||||||
|
/// <summary> |
||||||
|
/// Gets height of list item in pixels. |
||||||
|
/// </summary> |
||||||
|
/// <param name="index">Zero-based index of array element.</param> |
||||||
|
/// <returns> |
||||||
|
/// Measurement in pixels. |
||||||
|
/// </returns> |
||||||
|
float GetItemHeight(int index); |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
} |
@ -0,0 +1,11 @@ |
|||||||
|
fileFormatVersion: 2 |
||||||
|
guid: 27a7bce836d771f4a84b172af5132fe7 |
||||||
|
MonoImporter: |
||||||
|
externalObjects: {} |
||||||
|
serializedVersion: 2 |
||||||
|
defaultReferences: [] |
||||||
|
executionOrder: 0 |
||||||
|
icon: {instanceID: 0} |
||||||
|
userData: |
||||||
|
assetBundleName: |
||||||
|
assetBundleVariant: |
@ -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 { |
||||||
|
|
||||||
|
/// <summary> |
||||||
|
/// Can be implemented along with <see cref="IReorderableListAdaptor"/> when drop |
||||||
|
/// insertion or ordering is desired. |
||||||
|
/// </summary> |
||||||
|
/// <remarks> |
||||||
|
/// <para>This type of "drop" functionality can occur when the "drag" phase of the |
||||||
|
/// drag and drop operation was initiated elsewhere. For example, a custom |
||||||
|
/// <see cref="IReorderableListAdaptor"/> could insert entirely new items by |
||||||
|
/// dragging and dropping from the Unity "Project" window.</para> |
||||||
|
/// </remarks> |
||||||
|
/// <see cref="IReorderableListAdaptor"/> |
||||||
|
public interface IReorderableListDropTarget { |
||||||
|
|
||||||
|
/// <summary> |
||||||
|
/// Determines whether an item is being dragged and that it can be inserted |
||||||
|
/// or moved by dropping somewhere into the reorderable list control. |
||||||
|
/// </summary> |
||||||
|
/// <remarks> |
||||||
|
/// <para>This method is always called whilst drawing an editor GUI.</para> |
||||||
|
/// </remarks> |
||||||
|
/// <param name="insertionIndex">Zero-based index of insertion.</param> |
||||||
|
/// <returns> |
||||||
|
/// A value of <c>true</c> if item can be dropped; otherwise <c>false</c>. |
||||||
|
/// </returns> |
||||||
|
/// <see cref="UnityEditor.DragAndDrop"/> |
||||||
|
bool CanDropInsert(int insertionIndex); |
||||||
|
|
||||||
|
/// <summary> |
||||||
|
/// Processes the current drop insertion operation when <see cref="CanDropInsert(int)"/> |
||||||
|
/// returns a value of <c>true</c> to process, accept or cancel. |
||||||
|
/// </summary> |
||||||
|
/// <remarks> |
||||||
|
/// <para>This method is always called whilst drawing an editor GUI.</para> |
||||||
|
/// <para>This method is only called when <see cref="CanDropInsert(int)"/> |
||||||
|
/// returns a value of <c>true</c>.</para> |
||||||
|
/// </remarks> |
||||||
|
/// <param name="insertionIndex">Zero-based index of insertion.</param> |
||||||
|
/// <see cref="ReorderableListGUI.CurrentListControlID"/> |
||||||
|
/// <see cref="UnityEditor.DragAndDrop"/> |
||||||
|
void ProcessDropInsertion(int insertionIndex); |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
} |
@ -0,0 +1,11 @@ |
|||||||
|
fileFormatVersion: 2 |
||||||
|
guid: d1806c8b705782141acdbee308edf82c |
||||||
|
MonoImporter: |
||||||
|
externalObjects: {} |
||||||
|
serializedVersion: 2 |
||||||
|
defaultReferences: [] |
||||||
|
executionOrder: 0 |
||||||
|
icon: {instanceID: 0} |
||||||
|
userData: |
||||||
|
assetBundleName: |
||||||
|
assetBundleVariant: |
@ -0,0 +1,8 @@ |
|||||||
|
fileFormatVersion: 2 |
||||||
|
guid: 1080d4950a85a2b4da9d5653fff71a13 |
||||||
|
folderAsset: yes |
||||||
|
DefaultImporter: |
||||||
|
externalObjects: {} |
||||||
|
userData: |
||||||
|
assetBundleName: |
||||||
|
assetBundleVariant: |
@ -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 { |
||||||
|
|
||||||
|
/// <summary> |
||||||
|
/// Utility functions to assist with GUIs. |
||||||
|
/// </summary> |
||||||
|
/// <exclude/> |
||||||
|
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<Rect>)Delegate.CreateDelegate(typeof(Func<Rect>), 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<string>)Delegate.CreateDelegate(typeof(Action<string>), 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; |
||||||
|
} |
||||||
|
|
||||||
|
/// <summary> |
||||||
|
/// Gets visible rectangle within GUI. |
||||||
|
/// </summary> |
||||||
|
/// <remarks> |
||||||
|
/// <para>VisibleRect = TopmostRect + scrollViewOffsets</para> |
||||||
|
/// </remarks> |
||||||
|
public static Func<Rect> VisibleRect; |
||||||
|
|
||||||
|
/// <summary> |
||||||
|
/// Focus control and text editor where applicable. |
||||||
|
/// </summary> |
||||||
|
public static Action<string> FocusTextInControl; |
||||||
|
|
||||||
|
private static GUIStyle s_TempStyle = new GUIStyle(); |
||||||
|
|
||||||
|
/// <summary> |
||||||
|
/// Draw texture using <see cref="GUIStyle"/> to workaround bug in Unity where |
||||||
|
/// <see cref="GUI.DrawTexture"/> flickers when embedded inside a property drawer. |
||||||
|
/// </summary> |
||||||
|
/// <param name="position">Position of which to draw texture in space of GUI.</param> |
||||||
|
/// <param name="texture">Texture.</param> |
||||||
|
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); |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
} |
@ -0,0 +1,11 @@ |
|||||||
|
fileFormatVersion: 2 |
||||||
|
guid: 26c2c1b444cf6a446b03219116f2f827 |
||||||
|
MonoImporter: |
||||||
|
externalObjects: {} |
||||||
|
serializedVersion: 2 |
||||||
|
defaultReferences: [] |
||||||
|
executionOrder: 0 |
||||||
|
icon: {instanceID: 0} |
||||||
|
userData: |
||||||
|
assetBundleName: |
||||||
|
assetBundleVariant: |
@ -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 { |
||||||
|
|
||||||
|
/// <exclude/> |
||||||
|
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, |
||||||
|
} |
||||||
|
|
||||||
|
/// <summary> |
||||||
|
/// Resources to assist with reorderable list control. |
||||||
|
/// </summary> |
||||||
|
/// <exclude/> |
||||||
|
public static class ReorderableListResources { |
||||||
|
|
||||||
|
static ReorderableListResources() { |
||||||
|
GenerateSpecialTextures(); |
||||||
|
LoadResourceAssets(); |
||||||
|
} |
||||||
|
|
||||||
|
#region Texture Resources |
||||||
|
|
||||||
|
/// <summary> |
||||||
|
/// Resource assets for light skin. |
||||||
|
/// </summary> |
||||||
|
/// <remarks> |
||||||
|
/// <para>Resource assets are PNG images which have been encoded using a base-64 |
||||||
|
/// string so that actual asset files are not necessary.</para> |
||||||
|
/// </remarks> |
||||||
|
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==", |
||||||
|
}; |
||||||
|
/// <summary> |
||||||
|
/// Resource assets for dark skin. |
||||||
|
/// </summary> |
||||||
|
/// <remarks> |
||||||
|
/// <para>Resource assets are PNG images which have been encoded using a base-64 |
||||||
|
/// string so that actual asset files are not necessary.</para> |
||||||
|
/// </remarks> |
||||||
|
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==", |
||||||
|
}; |
||||||
|
|
||||||
|
/// <summary> |
||||||
|
/// Gets light or dark version of the specified texture. |
||||||
|
/// </summary> |
||||||
|
/// <param name="name"></param> |
||||||
|
/// <returns></returns> |
||||||
|
public static Texture2D GetTexture(ReorderableListTexture name) { |
||||||
|
return s_Cached[(int)name]; |
||||||
|
} |
||||||
|
|
||||||
|
#endregion |
||||||
|
|
||||||
|
#region Generated Resources |
||||||
|
|
||||||
|
public static Texture2D texHighlightColor { get; private set; } |
||||||
|
|
||||||
|
/// <summary> |
||||||
|
/// Generate special textures. |
||||||
|
/// </summary> |
||||||
|
private static void GenerateSpecialTextures() { |
||||||
|
texHighlightColor = CreatePixelTexture("(Generated) Highlight Color", ReorderableListStyles.SelectionBackgroundColor); |
||||||
|
} |
||||||
|
|
||||||
|
/// <summary> |
||||||
|
/// Create 1x1 pixel texture of specified color. |
||||||
|
/// </summary> |
||||||
|
/// <param name="name">Name for texture object.</param> |
||||||
|
/// <param name="color">Pixel color.</param> |
||||||
|
/// <returns> |
||||||
|
/// The new <c>Texture2D</c> instance. |
||||||
|
/// </returns> |
||||||
|
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; |
||||||
|
|
||||||
|
/// <summary> |
||||||
|
/// Read textures from base-64 encoded strings. Automatically selects assets based |
||||||
|
/// upon whether the light or dark (pro) skin is active. |
||||||
|
/// </summary> |
||||||
|
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; |
||||||
|
} |
||||||
|
|
||||||
|
/// <summary> |
||||||
|
/// Read width and height if PNG file in pixels. |
||||||
|
/// </summary> |
||||||
|
/// <param name="imageData">PNG image data.</param> |
||||||
|
/// <param name="width">Width of image in pixels.</param> |
||||||
|
/// <param name="height">Height of image in pixels.</param> |
||||||
|
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 |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
} |
@ -0,0 +1,11 @@ |
|||||||
|
fileFormatVersion: 2 |
||||||
|
guid: 1d9acb5346b0f3c478d5678c6a0e4f42 |
||||||
|
MonoImporter: |
||||||
|
externalObjects: {} |
||||||
|
serializedVersion: 2 |
||||||
|
defaultReferences: [] |
||||||
|
executionOrder: 0 |
||||||
|
icon: {instanceID: 0} |
||||||
|
userData: |
||||||
|
assetBundleName: |
||||||
|
assetBundleVariant: |
@ -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 { |
||||||
|
|
||||||
|
/// <summary> |
||||||
|
/// Utility functionality for <see cref="SerializedPropertyAdaptor"/> implementations. |
||||||
|
/// </summary> |
||||||
|
public static class SerializedPropertyUtility { |
||||||
|
|
||||||
|
/// <summary> |
||||||
|
/// Reset the value of a property. |
||||||
|
/// </summary> |
||||||
|
/// <param name="property">Serialized property for a serialized property.</param> |
||||||
|
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); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/// <summary> |
||||||
|
/// Copies value of <paramref name="sourceProperty"/> into <pararef name="destProperty"/>. |
||||||
|
/// </summary> |
||||||
|
/// <param name="destProperty">Destination property.</param> |
||||||
|
/// <param name="sourceProperty">Source property.</param> |
||||||
|
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; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
} |
@ -0,0 +1,11 @@ |
|||||||
|
fileFormatVersion: 2 |
||||||
|
guid: e720cba766c708b40a725fddfbdb4436 |
||||||
|
MonoImporter: |
||||||
|
externalObjects: {} |
||||||
|
serializedVersion: 2 |
||||||
|
defaultReferences: [] |
||||||
|
executionOrder: 0 |
||||||
|
icon: {instanceID: 0} |
||||||
|
userData: |
||||||
|
assetBundleName: |
||||||
|
assetBundleVariant: |
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,11 @@ |
|||||||
|
fileFormatVersion: 2 |
||||||
|
guid: 02045e26a7a39c440ba538e3c9ca2248 |
||||||
|
MonoImporter: |
||||||
|
externalObjects: {} |
||||||
|
serializedVersion: 2 |
||||||
|
defaultReferences: [] |
||||||
|
executionOrder: 0 |
||||||
|
icon: {instanceID: 0} |
||||||
|
userData: |
||||||
|
assetBundleName: |
||||||
|
assetBundleVariant: |
@ -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 { |
||||||
|
|
||||||
|
/// <summary> |
||||||
|
/// Arguments which are passed to <see cref="AddMenuClickedEventHandler"/>. |
||||||
|
/// </summary> |
||||||
|
public sealed class AddMenuClickedEventArgs : EventArgs { |
||||||
|
|
||||||
|
/// <summary> |
||||||
|
/// Gets adaptor to reorderable list container. |
||||||
|
/// </summary> |
||||||
|
public IReorderableListAdaptor Adaptor { get; private set; } |
||||||
|
/// <summary> |
||||||
|
/// Gets position of the add menu button. |
||||||
|
/// </summary> |
||||||
|
public Rect ButtonPosition { get; internal set; } |
||||||
|
|
||||||
|
/// <summary> |
||||||
|
/// Initializes a new instance of <see cref="ItemMovedEventArgs"/>. |
||||||
|
/// </summary> |
||||||
|
/// <param name="adaptor">Reorderable list adaptor.</param> |
||||||
|
/// <param name="buttonPosition">Position of the add menu button.</param> |
||||||
|
public AddMenuClickedEventArgs(IReorderableListAdaptor adaptor, Rect buttonPosition) { |
||||||
|
this.Adaptor = adaptor; |
||||||
|
this.ButtonPosition = buttonPosition; |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
/// <summary> |
||||||
|
/// An event handler which is invoked when the "Add Menu" button is clicked. |
||||||
|
/// </summary> |
||||||
|
/// <param name="sender">Object which raised event.</param> |
||||||
|
/// <param name="args">Event arguments.</param> |
||||||
|
public delegate void AddMenuClickedEventHandler(object sender, AddMenuClickedEventArgs args); |
||||||
|
|
||||||
|
/// <summary> |
||||||
|
/// Arguments which are passed to <see cref="ItemInsertedEventHandler"/>. |
||||||
|
/// </summary> |
||||||
|
public sealed class ItemInsertedEventArgs : EventArgs { |
||||||
|
|
||||||
|
/// <summary> |
||||||
|
/// Gets adaptor to reorderable list container which contains element. |
||||||
|
/// </summary> |
||||||
|
public IReorderableListAdaptor Adaptor { get; private set; } |
||||||
|
/// <summary> |
||||||
|
/// Gets zero-based index of item which was inserted. |
||||||
|
/// </summary> |
||||||
|
public int ItemIndex { get; private set; } |
||||||
|
|
||||||
|
/// <summary> |
||||||
|
/// Indicates if inserted item was duplicated from another item. |
||||||
|
/// </summary> |
||||||
|
public bool WasDuplicated { get; private set; } |
||||||
|
|
||||||
|
/// <summary> |
||||||
|
/// Initializes a new instance of <see cref="ItemInsertedEventArgs"/>. |
||||||
|
/// </summary> |
||||||
|
/// <param name="adaptor">Reorderable list adaptor.</param> |
||||||
|
/// <param name="itemIndex">Zero-based index of item.</param> |
||||||
|
/// <param name="wasDuplicated">Indicates if inserted item was duplicated from another item.</param> |
||||||
|
public ItemInsertedEventArgs(IReorderableListAdaptor adaptor, int itemIndex, bool wasDuplicated) { |
||||||
|
this.Adaptor = adaptor; |
||||||
|
this.ItemIndex = itemIndex; |
||||||
|
this.WasDuplicated = wasDuplicated; |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
/// <summary> |
||||||
|
/// An event handler which is invoked after new list item is inserted. |
||||||
|
/// </summary> |
||||||
|
/// <param name="sender">Object which raised event.</param> |
||||||
|
/// <param name="args">Event arguments.</param> |
||||||
|
public delegate void ItemInsertedEventHandler(object sender, ItemInsertedEventArgs args); |
||||||
|
|
||||||
|
/// <summary> |
||||||
|
/// Arguments which are passed to <see cref="ItemRemovingEventHandler"/>. |
||||||
|
/// </summary> |
||||||
|
public sealed class ItemRemovingEventArgs : CancelEventArgs { |
||||||
|
|
||||||
|
/// <summary> |
||||||
|
/// Gets adaptor to reorderable list container which contains element. |
||||||
|
/// </summary> |
||||||
|
public IReorderableListAdaptor Adaptor { get; private set; } |
||||||
|
/// <summary> |
||||||
|
/// Gets zero-based index of item which is being removed. |
||||||
|
/// </summary> |
||||||
|
public int ItemIndex { get; internal set; } |
||||||
|
|
||||||
|
/// <summary> |
||||||
|
/// Initializes a new instance of <see cref="ItemRemovingEventArgs"/>. |
||||||
|
/// </summary> |
||||||
|
/// <param name="adaptor">Reorderable list adaptor.</param> |
||||||
|
/// <param name="itemIndex">Zero-based index of item.</param> |
||||||
|
public ItemRemovingEventArgs(IReorderableListAdaptor adaptor, int itemIndex) { |
||||||
|
this.Adaptor = adaptor; |
||||||
|
this.ItemIndex = itemIndex; |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
/// <summary> |
||||||
|
/// An event handler which is invoked before a list item is removed. |
||||||
|
/// </summary> |
||||||
|
/// <remarks> |
||||||
|
/// <para>Item removal can be cancelled by setting <see cref="CancelEventArgs.Cancel"/> |
||||||
|
/// to <c>true</c>.</para> |
||||||
|
/// </remarks> |
||||||
|
/// <param name="sender">Object which raised event.</param> |
||||||
|
/// <param name="args">Event arguments.</param> |
||||||
|
public delegate void ItemRemovingEventHandler(object sender, ItemRemovingEventArgs args); |
||||||
|
|
||||||
|
/// <summary> |
||||||
|
/// Arguments which are passed to <see cref="ItemMovingEventHandler"/>. |
||||||
|
/// </summary> |
||||||
|
public sealed class ItemMovingEventArgs : CancelEventArgs { |
||||||
|
|
||||||
|
/// <summary> |
||||||
|
/// Gets adaptor to reorderable list container which contains element. |
||||||
|
/// </summary> |
||||||
|
public IReorderableListAdaptor Adaptor { get; private set; } |
||||||
|
/// <summary> |
||||||
|
/// Gets current zero-based index of item which is going to be moved. |
||||||
|
/// </summary> |
||||||
|
public int ItemIndex { get; internal set; } |
||||||
|
/// <summary> |
||||||
|
/// Gets the new candidate zero-based index for the item. |
||||||
|
/// </summary> |
||||||
|
/// <seealso cref="NewItemIndex"/> |
||||||
|
public int DestinationItemIndex { get; internal set; } |
||||||
|
|
||||||
|
/// <summary> |
||||||
|
/// Gets zero-based index of item <strong>after</strong> it has been moved. |
||||||
|
/// </summary> |
||||||
|
/// <seealso cref="DestinationItemIndex"/> |
||||||
|
public int NewItemIndex { |
||||||
|
get { |
||||||
|
int result = DestinationItemIndex; |
||||||
|
if (result > ItemIndex) |
||||||
|
--result; |
||||||
|
return result; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/// <summary> |
||||||
|
/// Initializes a new instance of <see cref="ItemMovingEventArgs"/>. |
||||||
|
/// </summary> |
||||||
|
/// <param name="adaptor">Reorderable list adaptor.</param> |
||||||
|
/// <param name="itemIndex">Zero-based index of item.</param> |
||||||
|
/// <param name="destinationItemIndex">Xero-based index of item destination.</param> |
||||||
|
public ItemMovingEventArgs(IReorderableListAdaptor adaptor, int itemIndex, int destinationItemIndex) { |
||||||
|
this.Adaptor = adaptor; |
||||||
|
this.ItemIndex = itemIndex; |
||||||
|
this.DestinationItemIndex = destinationItemIndex; |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
/// <summary> |
||||||
|
/// An event handler which is invoked before a list item is moved. |
||||||
|
/// </summary> |
||||||
|
/// <remarks> |
||||||
|
/// <para>Moving of item can be cancelled by setting <see cref="CancelEventArgs.Cancel"/> |
||||||
|
/// to <c>true</c>.</para> |
||||||
|
/// </remarks> |
||||||
|
/// <param name="sender">Object which raised event.</param> |
||||||
|
/// <param name="args">Event arguments.</param> |
||||||
|
public delegate void ItemMovingEventHandler(object sender, ItemMovingEventArgs args); |
||||||
|
|
||||||
|
/// <summary> |
||||||
|
/// Arguments which are passed to <see cref="ItemMovedEventHandler"/>. |
||||||
|
/// </summary> |
||||||
|
public sealed class ItemMovedEventArgs : EventArgs { |
||||||
|
|
||||||
|
/// <summary> |
||||||
|
/// Gets adaptor to reorderable list container which contains element. |
||||||
|
/// </summary> |
||||||
|
public IReorderableListAdaptor Adaptor { get; private set; } |
||||||
|
/// <summary> |
||||||
|
/// Gets old zero-based index of the item which was moved. |
||||||
|
/// </summary> |
||||||
|
public int OldItemIndex { get; internal set; } |
||||||
|
/// <summary> |
||||||
|
/// Gets new zero-based index of the item which was moved. |
||||||
|
/// </summary> |
||||||
|
public int NewItemIndex { get; internal set; } |
||||||
|
|
||||||
|
/// <summary> |
||||||
|
/// Initializes a new instance of <see cref="ItemMovedEventArgs"/>. |
||||||
|
/// </summary> |
||||||
|
/// <param name="adaptor">Reorderable list adaptor.</param> |
||||||
|
/// <param name="oldItemIndex">Old zero-based index of item.</param> |
||||||
|
/// <param name="newItemIndex">New zero-based index of item.</param> |
||||||
|
public ItemMovedEventArgs(IReorderableListAdaptor adaptor, int oldItemIndex, int newItemIndex) { |
||||||
|
this.Adaptor = adaptor; |
||||||
|
this.OldItemIndex = oldItemIndex; |
||||||
|
this.NewItemIndex = newItemIndex; |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
/// <summary> |
||||||
|
/// An event handler which is invoked after a list item is moved. |
||||||
|
/// </summary> |
||||||
|
/// <param name="sender">Object which raised event.</param> |
||||||
|
/// <param name="args">Event arguments.</param> |
||||||
|
public delegate void ItemMovedEventHandler(object sender, ItemMovedEventArgs args); |
||||||
|
|
||||||
|
} |
@ -0,0 +1,11 @@ |
|||||||
|
fileFormatVersion: 2 |
||||||
|
guid: 1d75c9b7fc704a6488376beccd1a93a4 |
||||||
|
MonoImporter: |
||||||
|
externalObjects: {} |
||||||
|
serializedVersion: 2 |
||||||
|
defaultReferences: [] |
||||||
|
executionOrder: 0 |
||||||
|
icon: {instanceID: 0} |
||||||
|
userData: |
||||||
|
assetBundleName: |
||||||
|
assetBundleVariant: |
@ -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 { |
||||||
|
|
||||||
|
/// <summary> |
||||||
|
/// Additional flags which can be passed into reorderable list field. |
||||||
|
/// </summary> |
||||||
|
/// <example> |
||||||
|
/// <para>Multiple flags can be specified if desired:</para> |
||||||
|
/// <code language="csharp"><![CDATA[ |
||||||
|
/// var flags = ReorderableListFlags.HideAddButton | ReorderableListFlags.HideRemoveButtons; |
||||||
|
/// ReorderableListGUI.ListField(list, flags); |
||||||
|
/// ]]></code> |
||||||
|
/// </example> |
||||||
|
[Flags] |
||||||
|
public enum ReorderableListFlags { |
||||||
|
/// <summary> |
||||||
|
/// Hide grab handles and disable reordering of list items. |
||||||
|
/// </summary> |
||||||
|
DisableReordering = 0x0001, |
||||||
|
/// <summary> |
||||||
|
/// Hide add button at base of control. |
||||||
|
/// </summary> |
||||||
|
HideAddButton = 0x0002, |
||||||
|
/// <summary> |
||||||
|
/// Hide remove buttons from list items. |
||||||
|
/// </summary> |
||||||
|
HideRemoveButtons = 0x0004, |
||||||
|
/// <summary> |
||||||
|
/// Do not display context menu upon right-clicking grab handle. |
||||||
|
/// </summary> |
||||||
|
DisableContextMenu = 0x0008, |
||||||
|
/// <summary> |
||||||
|
/// Hide "Duplicate" option from context menu. |
||||||
|
/// </summary> |
||||||
|
DisableDuplicateCommand = 0x0010, |
||||||
|
/// <summary> |
||||||
|
/// Do not automatically focus first control of newly added items. |
||||||
|
/// </summary> |
||||||
|
DisableAutoFocus = 0x0020, |
||||||
|
/// <summary> |
||||||
|
/// Show zero-based index of array elements. |
||||||
|
/// </summary> |
||||||
|
ShowIndices = 0x0040, |
||||||
|
/// <exclude/> |
||||||
|
[Obsolete("This flag is redundant because the clipping optimization was removed.")] |
||||||
|
DisableClipping = 0x0080, |
||||||
|
/// <summary> |
||||||
|
/// 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. |
||||||
|
/// </summary> |
||||||
|
DisableAutoScroll = 0x0100, |
||||||
|
/// <summary> |
||||||
|
/// Show "Size" field at base of list control. |
||||||
|
/// </summary> |
||||||
|
ShowSizeField = 0x0200, |
||||||
|
} |
||||||
|
|
||||||
|
} |
@ -0,0 +1,11 @@ |
|||||||
|
fileFormatVersion: 2 |
||||||
|
guid: 8413004edec065f4c881fdb12b5d48b4 |
||||||
|
MonoImporter: |
||||||
|
externalObjects: {} |
||||||
|
serializedVersion: 2 |
||||||
|
defaultReferences: [] |
||||||
|
executionOrder: 0 |
||||||
|
icon: {instanceID: 0} |
||||||
|
userData: |
||||||
|
assetBundleName: |
||||||
|
assetBundleVariant: |
@ -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 { |
||||||
|
|
||||||
|
/// <summary> |
||||||
|
/// Utility class for drawing reorderable lists. |
||||||
|
/// </summary> |
||||||
|
public static class ReorderableListGUI { |
||||||
|
|
||||||
|
/// <summary> |
||||||
|
/// Default list item height is 18 pixels. |
||||||
|
/// </summary> |
||||||
|
public const float DefaultItemHeight = 18; |
||||||
|
|
||||||
|
/// <summary> |
||||||
|
/// 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. |
||||||
|
/// </summary> |
||||||
|
/// <remarks> |
||||||
|
/// <para>This property should not be set when items are added or removed.</para> |
||||||
|
/// </remarks> |
||||||
|
public static int IndexOfChangedItem { get; internal set; } |
||||||
|
|
||||||
|
/// <summary> |
||||||
|
/// Gets the control ID of the list that is currently being drawn. |
||||||
|
/// </summary> |
||||||
|
public static int CurrentListControlID { |
||||||
|
get { return ReorderableListControl.CurrentListControlID; } |
||||||
|
} |
||||||
|
|
||||||
|
/// <summary> |
||||||
|
/// Gets the position of the list control that is currently being drawn. |
||||||
|
/// </summary> |
||||||
|
/// <remarks> |
||||||
|
/// <para>The value of this property should be ignored for <see cref="EventType.Layout"/> |
||||||
|
/// type events when using reorderable list controls with automatic layout.</para> |
||||||
|
/// </remarks> |
||||||
|
/// <see cref="CurrentItemTotalPosition"/> |
||||||
|
public static Rect CurrentListPosition { |
||||||
|
get { return ReorderableListControl.CurrentListPosition; } |
||||||
|
} |
||||||
|
|
||||||
|
/// <summary> |
||||||
|
/// 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. |
||||||
|
/// </summary> |
||||||
|
public static int CurrentItemIndex { |
||||||
|
get { return ReorderableListControl.CurrentItemIndex; } |
||||||
|
} |
||||||
|
|
||||||
|
/// <summary> |
||||||
|
/// Gets the total position of the list item that is currently being drawn. |
||||||
|
/// </summary> |
||||||
|
/// <remarks> |
||||||
|
/// <para>The value of this property should be ignored for <see cref="EventType.Layout"/> |
||||||
|
/// type events when using reorderable list controls with automatic layout.</para> |
||||||
|
/// </remarks> |
||||||
|
/// <see cref="CurrentItemIndex"/> |
||||||
|
/// <see cref="CurrentListPosition"/> |
||||||
|
public static Rect CurrentItemTotalPosition { |
||||||
|
get { return ReorderableListControl.CurrentItemTotalPosition; } |
||||||
|
} |
||||||
|
|
||||||
|
#region Basic Item Drawers |
||||||
|
|
||||||
|
/// <summary> |
||||||
|
/// Default list item drawer implementation. |
||||||
|
/// </summary> |
||||||
|
/// <remarks> |
||||||
|
/// <para>Always presents the label "Item drawer not implemented.".</para> |
||||||
|
/// </remarks> |
||||||
|
/// <param name="position">Position to draw list item control(s).</param> |
||||||
|
/// <param name="item">Value of list item.</param> |
||||||
|
/// <returns> |
||||||
|
/// Unmodified value of list item. |
||||||
|
/// </returns> |
||||||
|
/// <typeparam name="T">Type of list item.</typeparam> |
||||||
|
public static T DefaultItemDrawer<T>(Rect position, T item) { |
||||||
|
GUI.Label(position, "Item drawer not implemented."); |
||||||
|
return item; |
||||||
|
} |
||||||
|
|
||||||
|
/// <summary> |
||||||
|
/// Draws text field allowing list items to be edited. |
||||||
|
/// </summary> |
||||||
|
/// <remarks> |
||||||
|
/// <para>Null values are automatically changed to empty strings since null |
||||||
|
/// values cannot be edited using a text field.</para> |
||||||
|
/// <para>Value of <c>GUI.changed</c> is set to <c>true</c> if value of item |
||||||
|
/// is modified.</para> |
||||||
|
/// </remarks> |
||||||
|
/// <param name="position">Position to draw list item control(s).</param> |
||||||
|
/// <param name="item">Value of list item.</param> |
||||||
|
/// <returns> |
||||||
|
/// Modified value of list item. |
||||||
|
/// </returns> |
||||||
|
public static string TextFieldItemDrawer(Rect position, string item) { |
||||||
|
if (item == null) { |
||||||
|
item = ""; |
||||||
|
GUI.changed = true; |
||||||
|
} |
||||||
|
return EditorGUI.TextField(position, item); |
||||||
|
} |
||||||
|
|
||||||
|
#endregion |
||||||
|
|
||||||
|
/// <summary> |
||||||
|
/// Gets the default list control implementation. |
||||||
|
/// </summary> |
||||||
|
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 |
||||||
|
|
||||||
|
/// <summary> |
||||||
|
/// Draw title control for list field. |
||||||
|
/// </summary> |
||||||
|
/// <remarks> |
||||||
|
/// <para>When needed, should be shown immediately before list field.</para> |
||||||
|
/// </remarks> |
||||||
|
/// <example> |
||||||
|
/// <code language="csharp"><![CDATA[ |
||||||
|
/// ReorderableListGUI.Title(titleContent); |
||||||
|
/// ReorderableListGUI.ListField(list, DynamicListGU.TextFieldItemDrawer); |
||||||
|
/// ]]></code> |
||||||
|
/// <code language="unityscript"><![CDATA[ |
||||||
|
/// ReorderableListGUI.Title(titleContent); |
||||||
|
/// ReorderableListGUI.ListField(list, DynamicListGU.TextFieldItemDrawer); |
||||||
|
/// ]]></code> |
||||||
|
/// </example> |
||||||
|
/// <param name="title">Content for title control.</param> |
||||||
|
public static void Title(GUIContent title) { |
||||||
|
Rect position = GUILayoutUtility.GetRect(title, ReorderableListStyles.Title); |
||||||
|
Title(position, title); |
||||||
|
GUILayout.Space(-1); |
||||||
|
} |
||||||
|
|
||||||
|
/// <summary> |
||||||
|
/// Draw title control for list field. |
||||||
|
/// </summary> |
||||||
|
/// <remarks> |
||||||
|
/// <para>When needed, should be shown immediately before list field.</para> |
||||||
|
/// </remarks> |
||||||
|
/// <example> |
||||||
|
/// <code language="csharp"><![CDATA[ |
||||||
|
/// ReorderableListGUI.Title("Your Title"); |
||||||
|
/// ReorderableListGUI.ListField(list, DynamicListGU.TextFieldItemDrawer); |
||||||
|
/// ]]></code> |
||||||
|
/// <code language="unityscript"><![CDATA[ |
||||||
|
/// ReorderableListGUI.Title('Your Title'); |
||||||
|
/// ReorderableListGUI.ListField(list, DynamicListGU.TextFieldItemDrawer); |
||||||
|
/// ]]></code> |
||||||
|
/// </example> |
||||||
|
/// <param name="title">Text for title control.</param> |
||||||
|
public static void Title(string title) { |
||||||
|
s_Temp.text = title; |
||||||
|
Title(s_Temp); |
||||||
|
} |
||||||
|
|
||||||
|
/// <summary> |
||||||
|
/// Draw title control for list field with absolute positioning. |
||||||
|
/// </summary> |
||||||
|
/// <param name="position">Position of control.</param> |
||||||
|
/// <param name="title">Content for title control.</param> |
||||||
|
public static void Title(Rect position, GUIContent title) { |
||||||
|
if (Event.current.type == EventType.Repaint) |
||||||
|
ReorderableListStyles.Title.Draw(position, title, false, false, false, false); |
||||||
|
} |
||||||
|
|
||||||
|
/// <summary> |
||||||
|
/// Draw title control for list field with absolute positioning. |
||||||
|
/// </summary> |
||||||
|
/// <param name="position">Position of control.</param> |
||||||
|
/// <param name="text">Text for title control.</param> |
||||||
|
public static void Title(Rect position, string text) { |
||||||
|
s_Temp.text = text; |
||||||
|
Title(position, s_Temp); |
||||||
|
} |
||||||
|
|
||||||
|
#endregion |
||||||
|
|
||||||
|
#region List<T> Control |
||||||
|
|
||||||
|
/// <summary> |
||||||
|
/// Draw list field control. |
||||||
|
/// </summary> |
||||||
|
/// <param name="list">The list which can be reordered.</param> |
||||||
|
/// <param name="drawItem">Callback to draw list item.</param> |
||||||
|
/// <param name="drawEmpty">Callback to draw custom content for empty list (optional).</param> |
||||||
|
/// <param name="itemHeight">Height of a single list item.</param> |
||||||
|
/// <param name="flags">Optional flags to pass into list field.</param> |
||||||
|
/// <typeparam name="T">Type of list item.</typeparam> |
||||||
|
private static void DoListField<T>(IList<T> list, ReorderableListControl.ItemDrawer<T> drawItem, ReorderableListControl.DrawEmpty drawEmpty, float itemHeight, ReorderableListFlags flags) { |
||||||
|
var adaptor = new GenericListAdaptor<T>(list, drawItem, itemHeight); |
||||||
|
ReorderableListControl.DrawControlFromState(adaptor, drawEmpty, flags); |
||||||
|
} |
||||||
|
/// <summary> |
||||||
|
/// Draw list field control with absolute positioning. |
||||||
|
/// </summary> |
||||||
|
/// <param name="position">Position of control.</param> |
||||||
|
/// <param name="list">The list which can be reordered.</param> |
||||||
|
/// <param name="drawItem">Callback to draw list item.</param> |
||||||
|
/// <param name="drawEmpty">Callback to draw custom content for empty list (optional).</param> |
||||||
|
/// <param name="itemHeight">Height of a single list item.</param> |
||||||
|
/// <param name="flags">Optional flags to pass into list field.</param> |
||||||
|
/// <typeparam name="T">Type of list item.</typeparam> |
||||||
|
private static void DoListFieldAbsolute<T>(Rect position, IList<T> list, ReorderableListControl.ItemDrawer<T> drawItem, ReorderableListControl.DrawEmptyAbsolute drawEmpty, float itemHeight, ReorderableListFlags flags) { |
||||||
|
var adaptor = new GenericListAdaptor<T>(list, drawItem, itemHeight); |
||||||
|
ReorderableListControl.DrawControlFromState(position, adaptor, drawEmpty, flags); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
/// <inheritdoc cref="DoListField{T}(IList{T}, ReorderableListControl.ItemDrawer{T}, ReorderableListControl.DrawEmpty, float, ReorderableListFlags)"/> |
||||||
|
public static void ListField<T>(IList<T> list, ReorderableListControl.ItemDrawer<T> drawItem, ReorderableListControl.DrawEmpty drawEmpty, float itemHeight, ReorderableListFlags flags) { |
||||||
|
DoListField<T>(list, drawItem, drawEmpty, itemHeight, flags); |
||||||
|
} |
||||||
|
/// <inheritdoc cref="DoListFieldAbsolute{T}(Rect, IList{T}, ReorderableListControl.ItemDrawer{T}, ReorderableListControl.DrawEmptyAbsolute, float, ReorderableListFlags)"/> |
||||||
|
public static void ListFieldAbsolute<T>(Rect position, IList<T> list, ReorderableListControl.ItemDrawer<T> drawItem, ReorderableListControl.DrawEmptyAbsolute drawEmpty, float itemHeight, ReorderableListFlags flags) { |
||||||
|
DoListFieldAbsolute<T>(position, list, drawItem, drawEmpty, itemHeight, flags); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
/// <inheritdoc cref="DoListField{T}(IList{T}, ReorderableListControl.ItemDrawer{T}, ReorderableListControl.DrawEmpty, float, ReorderableListFlags)"/> |
||||||
|
public static void ListField<T>(IList<T> list, ReorderableListControl.ItemDrawer<T> drawItem, ReorderableListControl.DrawEmpty drawEmpty, float itemHeight) { |
||||||
|
DoListField<T>(list, drawItem, drawEmpty, itemHeight, 0); |
||||||
|
} |
||||||
|
/// <inheritdoc cref="DoListFieldAbsolute{T}(Rect, IList{T}, ReorderableListControl.ItemDrawer{T}, ReorderableListControl.DrawEmptyAbsolute, float, ReorderableListFlags)"/> |
||||||
|
public static void ListFieldAbsolute<T>(Rect position, IList<T> list, ReorderableListControl.ItemDrawer<T> drawItem, ReorderableListControl.DrawEmptyAbsolute drawEmpty, float itemHeight) { |
||||||
|
DoListFieldAbsolute<T>(position, list, drawItem, drawEmpty, itemHeight, 0); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
/// <inheritdoc cref="DoListField{T}(IList{T}, ReorderableListControl.ItemDrawer{T}, ReorderableListControl.DrawEmpty, float, ReorderableListFlags)"/> |
||||||
|
public static void ListField<T>(IList<T> list, ReorderableListControl.ItemDrawer<T> drawItem, ReorderableListControl.DrawEmpty drawEmpty, ReorderableListFlags flags) { |
||||||
|
DoListField<T>(list, drawItem, drawEmpty, DefaultItemHeight, flags); |
||||||
|
} |
||||||
|
/// <inheritdoc cref="DoListFieldAbsolute{T}(Rect, IList{T}, ReorderableListControl.ItemDrawer{T}, ReorderableListControl.DrawEmptyAbsolute, float, ReorderableListFlags)"/> |
||||||
|
public static void ListFieldAbsolute<T>(Rect position, IList<T> list, ReorderableListControl.ItemDrawer<T> drawItem, ReorderableListControl.DrawEmptyAbsolute drawEmpty, ReorderableListFlags flags) { |
||||||
|
DoListFieldAbsolute<T>(position, list, drawItem, drawEmpty, DefaultItemHeight, flags); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
/// <inheritdoc cref="DoListField{T}(IList{T}, ReorderableListControl.ItemDrawer{T}, ReorderableListControl.DrawEmpty, float, ReorderableListFlags)"/> |
||||||
|
public static void ListField<T>(IList<T> list, ReorderableListControl.ItemDrawer<T> drawItem, ReorderableListControl.DrawEmpty drawEmpty) { |
||||||
|
DoListField<T>(list, drawItem, drawEmpty, DefaultItemHeight, 0); |
||||||
|
} |
||||||
|
/// <inheritdoc cref="DoListFieldAbsolute{T}(Rect, IList{T}, ReorderableListControl.ItemDrawer{T}, ReorderableListControl.DrawEmptyAbsolute, float, ReorderableListFlags)"/> |
||||||
|
public static void ListFieldAbsolute<T>(Rect position, IList<T> list, ReorderableListControl.ItemDrawer<T> drawItem, ReorderableListControl.DrawEmptyAbsolute drawEmpty) { |
||||||
|
DoListFieldAbsolute<T>(position, list, drawItem, drawEmpty, DefaultItemHeight, 0); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
/// <inheritdoc cref="DoListField{T}(IList{T}, ReorderableListControl.ItemDrawer{T}, ReorderableListControl.DrawEmpty, float, ReorderableListFlags)"/> |
||||||
|
public static void ListField<T>(IList<T> list, ReorderableListControl.ItemDrawer<T> drawItem, float itemHeight, ReorderableListFlags flags) { |
||||||
|
DoListField<T>(list, drawItem, null, itemHeight, flags); |
||||||
|
} |
||||||
|
/// <inheritdoc cref="DoListFieldAbsolute{T}(Rect, IList{T}, ReorderableListControl.ItemDrawer{T}, ReorderableListControl.DrawEmptyAbsolute, float, ReorderableListFlags)"/> |
||||||
|
public static void ListFieldAbsolute<T>(Rect position, IList<T> list, ReorderableListControl.ItemDrawer<T> drawItem, float itemHeight, ReorderableListFlags flags) { |
||||||
|
DoListFieldAbsolute<T>(position, list, drawItem, null, itemHeight, flags); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
/// <inheritdoc cref="DoListField{T}(IList{T}, ReorderableListControl.ItemDrawer{T}, ReorderableListControl.DrawEmpty, float, ReorderableListFlags)"/> |
||||||
|
public static void ListField<T>(IList<T> list, ReorderableListControl.ItemDrawer<T> drawItem, float itemHeight) { |
||||||
|
DoListField<T>(list, drawItem, null, itemHeight, 0); |
||||||
|
} |
||||||
|
/// <inheritdoc cref="DoListFieldAbsolute{T}(Rect, IList{T}, ReorderableListControl.ItemDrawer{T}, ReorderableListControl.DrawEmptyAbsolute, float, ReorderableListFlags)"/> |
||||||
|
public static void ListFieldAbsolute<T>(Rect position, IList<T> list, ReorderableListControl.ItemDrawer<T> drawItem, float itemHeight) { |
||||||
|
DoListFieldAbsolute<T>(position, list, drawItem, null, itemHeight, 0); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
/// <inheritdoc cref="DoListField{T}(IList{T}, ReorderableListControl.ItemDrawer{T}, ReorderableListControl.DrawEmpty, float, ReorderableListFlags)"/> |
||||||
|
public static void ListField<T>(IList<T> list, ReorderableListControl.ItemDrawer<T> drawItem, ReorderableListFlags flags) { |
||||||
|
DoListField<T>(list, drawItem, null, DefaultItemHeight, flags); |
||||||
|
} |
||||||
|
/// <inheritdoc cref="DoListFieldAbsolute{T}(Rect, IList{T}, ReorderableListControl.ItemDrawer{T}, ReorderableListControl.DrawEmptyAbsolute, float, ReorderableListFlags)"/> |
||||||
|
public static void ListFieldAbsolute<T>(Rect position, IList<T> list, ReorderableListControl.ItemDrawer<T> drawItem, ReorderableListFlags flags) { |
||||||
|
DoListFieldAbsolute<T>(position, list, drawItem, null, DefaultItemHeight, flags); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
/// <inheritdoc cref="DoListField{T}(IList{T}, ReorderableListControl.ItemDrawer{T}, ReorderableListControl.DrawEmpty, float, ReorderableListFlags)"/> |
||||||
|
public static void ListField<T>(IList<T> list, ReorderableListControl.ItemDrawer<T> drawItem) { |
||||||
|
DoListField<T>(list, drawItem, null, DefaultItemHeight, 0); |
||||||
|
} |
||||||
|
/// <inheritdoc cref="DoListFieldAbsolute{T}(Rect, IList{T}, ReorderableListControl.ItemDrawer{T}, ReorderableListControl.DrawEmptyAbsolute, float, ReorderableListFlags)"/> |
||||||
|
public static void ListFieldAbsolute<T>(Rect position, IList<T> list, ReorderableListControl.ItemDrawer<T> drawItem) { |
||||||
|
DoListFieldAbsolute<T>(position, list, drawItem, null, DefaultItemHeight, 0); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
/// <summary> |
||||||
|
/// Calculate height of list field for absolute positioning. |
||||||
|
/// </summary> |
||||||
|
/// <param name="itemCount">Count of items in list.</param> |
||||||
|
/// <param name="itemHeight">Fixed height of list item.</param> |
||||||
|
/// <param name="flags">Optional flags to pass into list field.</param> |
||||||
|
/// <returns> |
||||||
|
/// Required list height in pixels. |
||||||
|
/// </returns> |
||||||
|
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; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/// <inheritdoc cref="CalculateListFieldHeight(int, float, ReorderableListFlags)"/> |
||||||
|
public static float CalculateListFieldHeight(int itemCount, ReorderableListFlags flags) { |
||||||
|
return CalculateListFieldHeight(itemCount, DefaultItemHeight, flags); |
||||||
|
} |
||||||
|
/// <inheritdoc cref="CalculateListFieldHeight(int, float, ReorderableListFlags)"/> |
||||||
|
public static float CalculateListFieldHeight(int itemCount, float itemHeight) { |
||||||
|
return CalculateListFieldHeight(itemCount, itemHeight, 0); |
||||||
|
} |
||||||
|
/// <inheritdoc cref="CalculateListFieldHeight(int, float, ReorderableListFlags)"/> |
||||||
|
public static float CalculateListFieldHeight(int itemCount) { |
||||||
|
return CalculateListFieldHeight(itemCount, DefaultItemHeight, 0); |
||||||
|
} |
||||||
|
|
||||||
|
#endregion |
||||||
|
|
||||||
|
#region SerializedProperty Control |
||||||
|
|
||||||
|
/// <summary> |
||||||
|
/// Draw list field control for serializable property array. |
||||||
|
/// </summary> |
||||||
|
/// <param name="arrayProperty">Serializable property.</param> |
||||||
|
/// <param name="fixedItemHeight">Use fixed height for items rather than <see cref="UnityEditor.EditorGUI.GetPropertyHeight(SerializedProperty)"/>.</param> |
||||||
|
/// <param name="drawEmpty">Callback to draw custom content for empty list (optional).</param> |
||||||
|
/// <param name="flags">Optional flags to pass into list field.</param> |
||||||
|
private static void DoListField(SerializedProperty arrayProperty, float fixedItemHeight, ReorderableListControl.DrawEmpty drawEmpty, ReorderableListFlags flags) { |
||||||
|
var adaptor = new SerializedPropertyAdaptor(arrayProperty, fixedItemHeight); |
||||||
|
ReorderableListControl.DrawControlFromState(adaptor, drawEmpty, flags); |
||||||
|
} |
||||||
|
/// <summary> |
||||||
|
/// Draw list field control for serializable property array. |
||||||
|
/// </summary> |
||||||
|
/// <param name="position">Position of control.</param> |
||||||
|
/// <param name="arrayProperty">Serializable property.</param> |
||||||
|
/// <param name="fixedItemHeight">Use fixed height for items rather than <see cref="UnityEditor.EditorGUI.GetPropertyHeight(SerializedProperty)"/>.</param> |
||||||
|
/// <param name="drawEmpty">Callback to draw custom content for empty list (optional).</param> |
||||||
|
/// <param name="flags">Optional flags to pass into list field.</param> |
||||||
|
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); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
/// <inheritdoc cref="DoListField(SerializedProperty, float, ReorderableListControl.DrawEmpty, ReorderableListFlags)"/> |
||||||
|
public static void ListField(SerializedProperty arrayProperty, ReorderableListControl.DrawEmpty drawEmpty, ReorderableListFlags flags) { |
||||||
|
DoListField(arrayProperty, 0, drawEmpty, flags); |
||||||
|
} |
||||||
|
/// <inheritdoc cref="DoListFieldAbsolute(Rect, SerializedProperty, float, ReorderableListControl.DrawEmptyAbsolute, ReorderableListFlags)"/> |
||||||
|
public static void ListFieldAbsolute(Rect position, SerializedProperty arrayProperty, ReorderableListControl.DrawEmptyAbsolute drawEmpty, ReorderableListFlags flags) { |
||||||
|
DoListFieldAbsolute(position, arrayProperty, 0, drawEmpty, flags); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
/// <inheritdoc cref="DoListField(SerializedProperty, float, ReorderableListControl.DrawEmpty, ReorderableListFlags)"/> |
||||||
|
public static void ListField(SerializedProperty arrayProperty, ReorderableListControl.DrawEmpty drawEmpty) { |
||||||
|
DoListField(arrayProperty, 0, drawEmpty, 0); |
||||||
|
} |
||||||
|
/// <inheritdoc cref="DoListFieldAbsolute(Rect, SerializedProperty, float, ReorderableListControl.DrawEmptyAbsolute, ReorderableListFlags)"/> |
||||||
|
public static void ListFieldAbsolute(Rect position, SerializedProperty arrayProperty, ReorderableListControl.DrawEmptyAbsolute drawEmpty) { |
||||||
|
DoListFieldAbsolute(position, arrayProperty, 0, drawEmpty, 0); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
/// <inheritdoc cref="DoListField(SerializedProperty, float, ReorderableListControl.DrawEmpty, ReorderableListFlags)"/> |
||||||
|
public static void ListField(SerializedProperty arrayProperty, ReorderableListFlags flags) { |
||||||
|
DoListField(arrayProperty, 0, null, flags); |
||||||
|
} |
||||||
|
/// <inheritdoc cref="DoListFieldAbsolute(Rect, SerializedProperty, float, ReorderableListControl.DrawEmptyAbsolute, ReorderableListFlags)"/> |
||||||
|
public static void ListFieldAbsolute(Rect position, SerializedProperty arrayProperty, ReorderableListFlags flags) { |
||||||
|
DoListFieldAbsolute(position, arrayProperty, 0, null, flags); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
/// <inheritdoc cref="DoListField(SerializedProperty, float, ReorderableListControl.DrawEmpty, ReorderableListFlags)"/> |
||||||
|
public static void ListField(SerializedProperty arrayProperty) { |
||||||
|
DoListField(arrayProperty, 0, null, 0); |
||||||
|
} |
||||||
|
/// <inheritdoc cref="DoListFieldAbsolute(Rect, SerializedProperty, float, ReorderableListControl.DrawEmptyAbsolute, ReorderableListFlags)"/> |
||||||
|
public static void ListFieldAbsolute(Rect position, SerializedProperty arrayProperty) { |
||||||
|
DoListFieldAbsolute(position, arrayProperty, 0, null, 0); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
/// <summary> |
||||||
|
/// Calculate height of list field for absolute positioning. |
||||||
|
/// </summary> |
||||||
|
/// <param name="arrayProperty">Serializable property.</param> |
||||||
|
/// <param name="flags">Optional flags to pass into list field.</param> |
||||||
|
/// <returns> |
||||||
|
/// Required list height in pixels. |
||||||
|
/// </returns> |
||||||
|
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; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/// <inheritdoc cref="CalculateListFieldHeight(SerializedProperty, ReorderableListFlags)"/> |
||||||
|
public static float CalculateListFieldHeight(SerializedProperty arrayProperty) { |
||||||
|
return CalculateListFieldHeight(arrayProperty, 0); |
||||||
|
} |
||||||
|
|
||||||
|
#endregion |
||||||
|
|
||||||
|
#region SerializedProperty Control (Fixed Item Height) |
||||||
|
|
||||||
|
/// <inheritdoc cref="DoListField(SerializedProperty, float, ReorderableListControl.DrawEmpty, ReorderableListFlags)"/> |
||||||
|
public static void ListField(SerializedProperty arrayProperty, float fixedItemHeight, ReorderableListControl.DrawEmpty drawEmpty, ReorderableListFlags flags) { |
||||||
|
DoListField(arrayProperty, fixedItemHeight, drawEmpty, flags); |
||||||
|
} |
||||||
|
/// <inheritdoc cref="DoListFieldAbsolute(Rect, SerializedProperty, float, ReorderableListControl.DrawEmptyAbsolute, ReorderableListFlags)"/> |
||||||
|
public static void ListFieldAbsolute(Rect position, SerializedProperty arrayProperty, float fixedItemHeight, ReorderableListControl.DrawEmptyAbsolute drawEmpty, ReorderableListFlags flags) { |
||||||
|
DoListFieldAbsolute(position, arrayProperty, fixedItemHeight, drawEmpty, flags); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
/// <inheritdoc cref="DoListField(SerializedProperty, float, ReorderableListControl.DrawEmpty, ReorderableListFlags)"/> |
||||||
|
public static void ListField(SerializedProperty arrayProperty, float fixedItemHeight, ReorderableListControl.DrawEmpty drawEmpty) { |
||||||
|
DoListField(arrayProperty, fixedItemHeight, drawEmpty, 0); |
||||||
|
} |
||||||
|
/// <inheritdoc cref="DoListFieldAbsolute(Rect, SerializedProperty, float, ReorderableListControl.DrawEmptyAbsolute, ReorderableListFlags)"/> |
||||||
|
public static void ListFieldAbsolute(Rect position, SerializedProperty arrayProperty, float fixedItemHeight, ReorderableListControl.DrawEmptyAbsolute drawEmpty) { |
||||||
|
DoListFieldAbsolute(position, arrayProperty, fixedItemHeight, drawEmpty, 0); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
/// <inheritdoc cref="DoListField(SerializedProperty, float, ReorderableListControl.DrawEmpty, ReorderableListFlags)"/> |
||||||
|
public static void ListField(SerializedProperty arrayProperty, float fixedItemHeight, ReorderableListFlags flags) { |
||||||
|
DoListField(arrayProperty, fixedItemHeight, null, flags); |
||||||
|
} |
||||||
|
/// <inheritdoc cref="DoListFieldAbsolute(Rect, SerializedProperty, float, ReorderableListControl.DrawEmptyAbsolute, ReorderableListFlags)"/> |
||||||
|
public static void ListFieldAbsolute(Rect position, SerializedProperty arrayProperty, float fixedItemHeight, ReorderableListFlags flags) { |
||||||
|
DoListFieldAbsolute(position, arrayProperty, fixedItemHeight, null, flags); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
/// <inheritdoc cref="DoListField(SerializedProperty, float, ReorderableListControl.DrawEmpty, ReorderableListFlags)"/> |
||||||
|
public static void ListField(SerializedProperty arrayProperty, float fixedItemHeight) { |
||||||
|
DoListField(arrayProperty, fixedItemHeight, null, 0); |
||||||
|
} |
||||||
|
/// <inheritdoc cref="DoListFieldAbsolute(Rect, SerializedProperty, float, ReorderableListControl.DrawEmptyAbsolute, ReorderableListFlags)"/> |
||||||
|
public static void ListFieldAbsolute(Rect position, SerializedProperty arrayProperty, float fixedItemHeight) { |
||||||
|
DoListFieldAbsolute(position, arrayProperty, fixedItemHeight, null, 0); |
||||||
|
} |
||||||
|
|
||||||
|
#endregion |
||||||
|
|
||||||
|
#region Adaptor Control |
||||||
|
|
||||||
|
/// <summary> |
||||||
|
/// Draw list field control for adapted collection. |
||||||
|
/// </summary> |
||||||
|
/// <param name="adaptor">Reorderable list adaptor.</param> |
||||||
|
/// <param name="drawEmpty">Callback to draw custom content for empty list (optional).</param> |
||||||
|
/// <param name="flags">Optional flags to pass into list field.</param> |
||||||
|
private static void DoListField(IReorderableListAdaptor adaptor, ReorderableListControl.DrawEmpty drawEmpty, ReorderableListFlags flags = 0) { |
||||||
|
ReorderableListControl.DrawControlFromState(adaptor, drawEmpty, flags); |
||||||
|
} |
||||||
|
/// <summary> |
||||||
|
/// Draw list field control for adapted collection. |
||||||
|
/// </summary> |
||||||
|
/// <param name="position">Position of control.</param> |
||||||
|
/// <param name="adaptor">Reorderable list adaptor.</param> |
||||||
|
/// <param name="drawEmpty">Callback to draw custom content for empty list (optional).</param> |
||||||
|
/// <param name="flags">Optional flags to pass into list field.</param> |
||||||
|
private static void DoListFieldAbsolute(Rect position, IReorderableListAdaptor adaptor, ReorderableListControl.DrawEmptyAbsolute drawEmpty, ReorderableListFlags flags = 0) { |
||||||
|
ReorderableListControl.DrawControlFromState(position, adaptor, drawEmpty, flags); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
/// <inheritdoc cref="DoListField(IReorderableListAdaptor, ReorderableListControl.DrawEmpty, ReorderableListFlags)"/> |
||||||
|
public static void ListField(IReorderableListAdaptor adaptor, ReorderableListControl.DrawEmpty drawEmpty, ReorderableListFlags flags) { |
||||||
|
DoListField(adaptor, drawEmpty, flags); |
||||||
|
} |
||||||
|
/// <inheritdoc cref="DoListFieldAbsolute(Rect, IReorderableListAdaptor, ReorderableListControl.DrawEmptyAbsolute, ReorderableListFlags)"/> |
||||||
|
public static void ListFieldAbsolute(Rect position, IReorderableListAdaptor adaptor, ReorderableListControl.DrawEmptyAbsolute drawEmpty, ReorderableListFlags flags) { |
||||||
|
DoListFieldAbsolute(position, adaptor, drawEmpty, flags); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
/// <inheritdoc cref="DoListField(IReorderableListAdaptor, ReorderableListControl.DrawEmpty, ReorderableListFlags)"/> |
||||||
|
public static void ListField(IReorderableListAdaptor adaptor, ReorderableListControl.DrawEmpty drawEmpty) { |
||||||
|
DoListField(adaptor, drawEmpty, 0); |
||||||
|
} |
||||||
|
/// <inheritdoc cref="DoListFieldAbsolute(Rect, IReorderableListAdaptor, ReorderableListControl.DrawEmptyAbsolute, ReorderableListFlags)"/> |
||||||
|
public static void ListFieldAbsolute(Rect position, IReorderableListAdaptor adaptor, ReorderableListControl.DrawEmptyAbsolute drawEmpty) { |
||||||
|
DoListFieldAbsolute(position, adaptor, drawEmpty, 0); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
/// <inheritdoc cref="DoListField(IReorderableListAdaptor, ReorderableListControl.DrawEmpty, ReorderableListFlags)"/> |
||||||
|
public static void ListField(IReorderableListAdaptor adaptor, ReorderableListFlags flags) { |
||||||
|
DoListField(adaptor, null, flags); |
||||||
|
} |
||||||
|
/// <inheritdoc cref="DoListFieldAbsolute(Rect, IReorderableListAdaptor, ReorderableListControl.DrawEmptyAbsolute, ReorderableListFlags)"/> |
||||||
|
public static void ListFieldAbsolute(Rect position, IReorderableListAdaptor adaptor, ReorderableListFlags flags) { |
||||||
|
DoListFieldAbsolute(position, adaptor, null, flags); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
/// <inheritdoc cref="DoListField(IReorderableListAdaptor, ReorderableListControl.DrawEmpty, ReorderableListFlags)"/> |
||||||
|
public static void ListField(IReorderableListAdaptor adaptor) { |
||||||
|
DoListField(adaptor, null, 0); |
||||||
|
} |
||||||
|
/// <inheritdoc cref="DoListFieldAbsolute(Rect, IReorderableListAdaptor, ReorderableListControl.DrawEmptyAbsolute, ReorderableListFlags)"/> |
||||||
|
public static void ListFieldAbsolute(Rect position, IReorderableListAdaptor adaptor) { |
||||||
|
DoListFieldAbsolute(position, adaptor, null, 0); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
/// <summary> |
||||||
|
/// Calculate height of list field for adapted collection. |
||||||
|
/// </summary> |
||||||
|
/// <param name="adaptor">Reorderable list adaptor.</param> |
||||||
|
/// <param name="flags">Optional flags to pass into list field.</param> |
||||||
|
/// <returns> |
||||||
|
/// Required list height in pixels. |
||||||
|
/// </returns> |
||||||
|
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; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/// <inheritdoc cref="CalculateListFieldHeight(IReorderableListAdaptor, ReorderableListFlags)"/> |
||||||
|
public static float CalculateListFieldHeight(IReorderableListAdaptor adaptor) { |
||||||
|
return CalculateListFieldHeight(adaptor, 0); |
||||||
|
} |
||||||
|
|
||||||
|
#endregion |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
} |
@ -0,0 +1,11 @@ |
|||||||
|
fileFormatVersion: 2 |
||||||
|
guid: 0cda42c9be3a73c469749c5422090d9a |
||||||
|
MonoImporter: |
||||||
|
externalObjects: {} |
||||||
|
serializedVersion: 2 |
||||||
|
defaultReferences: [] |
||||||
|
executionOrder: 0 |
||||||
|
icon: {instanceID: 0} |
||||||
|
userData: |
||||||
|
assetBundleName: |
||||||
|
assetBundleVariant: |
@ -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 { |
||||||
|
|
||||||
|
/// <summary> |
||||||
|
/// Styles for the <see cref="ReorderableListControl"/>. |
||||||
|
/// </summary> |
||||||
|
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; |
||||||
|
} |
||||||
|
|
||||||
|
/// <summary> |
||||||
|
/// Gets style for title header. |
||||||
|
/// </summary> |
||||||
|
public static GUIStyle Title { get; private set; } |
||||||
|
|
||||||
|
/// <summary> |
||||||
|
/// Gets style for the background of list control. |
||||||
|
/// </summary> |
||||||
|
public static GUIStyle Container { get; private set; } |
||||||
|
/// <summary> |
||||||
|
/// Gets an alternative style for the background of list control. |
||||||
|
/// </summary> |
||||||
|
public static GUIStyle Container2 { get; private set; } |
||||||
|
/// <summary> |
||||||
|
/// Gets style for footer button. |
||||||
|
/// </summary> |
||||||
|
public static GUIStyle FooterButton { get; private set; } |
||||||
|
/// <summary> |
||||||
|
/// Gets an alternative style for footer button. |
||||||
|
/// </summary> |
||||||
|
public static GUIStyle FooterButton2 { get; private set; } |
||||||
|
/// <summary> |
||||||
|
/// Gets style for remove item button. |
||||||
|
/// </summary> |
||||||
|
public static GUIStyle ItemButton { get; private set; } |
||||||
|
|
||||||
|
/// <summary> |
||||||
|
/// Gets style for the background of a selected item. |
||||||
|
/// </summary> |
||||||
|
public static GUIStyle SelectedItem { get; private set; } |
||||||
|
|
||||||
|
/// <summary> |
||||||
|
/// Gets color for the horizontal lines that appear between list items. |
||||||
|
/// </summary> |
||||||
|
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); } |
||||||
|
} |
||||||
|
|
||||||
|
/// <summary> |
||||||
|
/// Gets color of background for a selected list item. |
||||||
|
/// </summary> |
||||||
|
public static Color SelectionBackgroundColor { |
||||||
|
get { return EditorGUIUtility.isProSkin ? new Color32(62, 95, 150, 255) : new Color32(62, 125, 231, 255); } |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
} |
@ -0,0 +1,11 @@ |
|||||||
|
fileFormatVersion: 2 |
||||||
|
guid: c4843f314e955fb459f99b33194fbebd |
||||||
|
MonoImporter: |
||||||
|
externalObjects: {} |
||||||
|
serializedVersion: 2 |
||||||
|
defaultReferences: [] |
||||||
|
executionOrder: 0 |
||||||
|
icon: {instanceID: 0} |
||||||
|
userData: |
||||||
|
assetBundleName: |
||||||
|
assetBundleVariant: |
@ -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 { |
||||||
|
|
||||||
|
/// <summary> |
||||||
|
/// Reorderable list adaptor for serialized array property. |
||||||
|
/// </summary> |
||||||
|
/// <remarks> |
||||||
|
/// <para>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.</para> |
||||||
|
/// <para>List elements are <b>not</b> cloned using the <see cref="System.ICloneable"/> |
||||||
|
/// interface when using a <see cref="UnityEditor.SerializedProperty"/> to |
||||||
|
/// manipulate lists.</para> |
||||||
|
/// </remarks> |
||||||
|
public class SerializedPropertyAdaptor : IReorderableListAdaptor { |
||||||
|
|
||||||
|
private SerializedProperty _arrayProperty; |
||||||
|
|
||||||
|
/// <summary> |
||||||
|
/// Fixed height of each list item. |
||||||
|
/// </summary> |
||||||
|
/// <remarks> |
||||||
|
/// <para>Non-zero value overrides property drawer height calculation |
||||||
|
/// which is more efficient.</para> |
||||||
|
/// </remarks> |
||||||
|
public float FixedItemHeight; |
||||||
|
|
||||||
|
/// <summary> |
||||||
|
/// Gets element from list. |
||||||
|
/// </summary> |
||||||
|
/// <param name="index">Zero-based index of element.</param> |
||||||
|
/// <returns> |
||||||
|
/// Serialized property wrapper for array element. |
||||||
|
/// </returns> |
||||||
|
public SerializedProperty this[int index] { |
||||||
|
get { return _arrayProperty.GetArrayElementAtIndex(index); } |
||||||
|
} |
||||||
|
|
||||||
|
/// <summary> |
||||||
|
/// Gets the underlying serialized array property. |
||||||
|
/// </summary> |
||||||
|
public SerializedProperty arrayProperty { |
||||||
|
get { return _arrayProperty; } |
||||||
|
} |
||||||
|
|
||||||
|
#region Construction |
||||||
|
|
||||||
|
/// <summary> |
||||||
|
/// Initializes a new instance of <see cref="SerializedPropertyAdaptor"/>. |
||||||
|
/// </summary> |
||||||
|
/// <param name="arrayProperty">Serialized property for entire array.</param> |
||||||
|
/// <param name="fixedItemHeight">Non-zero height overrides property drawer height calculation.</param> |
||||||
|
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; |
||||||
|
} |
||||||
|
|
||||||
|
/// <summary> |
||||||
|
/// Initializes a new instance of <see cref="SerializedPropertyAdaptor"/>. |
||||||
|
/// </summary> |
||||||
|
/// <param name="arrayProperty">Serialized property for entire array.</param> |
||||||
|
public SerializedPropertyAdaptor(SerializedProperty arrayProperty) : this(arrayProperty, 0f) { |
||||||
|
} |
||||||
|
|
||||||
|
#endregion |
||||||
|
|
||||||
|
#region IReorderableListAdaptor - Implementation |
||||||
|
|
||||||
|
/// <inheritdoc/> |
||||||
|
public int Count { |
||||||
|
get { return _arrayProperty.arraySize; } |
||||||
|
} |
||||||
|
|
||||||
|
/// <inheritdoc/> |
||||||
|
public virtual bool CanDrag(int index) { |
||||||
|
return true; |
||||||
|
} |
||||||
|
/// <inheritdoc/> |
||||||
|
public virtual bool CanRemove(int index) { |
||||||
|
return true; |
||||||
|
} |
||||||
|
|
||||||
|
/// <inheritdoc/> |
||||||
|
public void Add() { |
||||||
|
int newIndex = _arrayProperty.arraySize; |
||||||
|
++_arrayProperty.arraySize; |
||||||
|
SerializedPropertyUtility.ResetValue(_arrayProperty.GetArrayElementAtIndex(newIndex)); |
||||||
|
} |
||||||
|
/// <inheritdoc/> |
||||||
|
public void Insert(int index) { |
||||||
|
_arrayProperty.InsertArrayElementAtIndex(index); |
||||||
|
SerializedPropertyUtility.ResetValue(_arrayProperty.GetArrayElementAtIndex(index)); |
||||||
|
} |
||||||
|
/// <inheritdoc/> |
||||||
|
public void Duplicate(int index) { |
||||||
|
_arrayProperty.InsertArrayElementAtIndex(index); |
||||||
|
} |
||||||
|
/// <inheritdoc/> |
||||||
|
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); |
||||||
|
} |
||||||
|
/// <inheritdoc/> |
||||||
|
public void Move(int sourceIndex, int destIndex) { |
||||||
|
if (destIndex > sourceIndex) |
||||||
|
--destIndex; |
||||||
|
_arrayProperty.MoveArrayElement(sourceIndex, destIndex); |
||||||
|
} |
||||||
|
/// <inheritdoc/> |
||||||
|
public void Clear() { |
||||||
|
_arrayProperty.ClearArray(); |
||||||
|
} |
||||||
|
|
||||||
|
/// <inheritdoc/> |
||||||
|
public virtual void BeginGUI() { |
||||||
|
} |
||||||
|
|
||||||
|
/// <inheritdoc/> |
||||||
|
public virtual void EndGUI() { |
||||||
|
} |
||||||
|
|
||||||
|
/// <inheritdoc/> |
||||||
|
public virtual void DrawItemBackground(Rect position, int index) { |
||||||
|
} |
||||||
|
|
||||||
|
/// <inheritdoc/> |
||||||
|
public virtual void DrawItem(Rect position, int index) { |
||||||
|
EditorGUI.PropertyField(position, this[index], GUIContent.none, false); |
||||||
|
} |
||||||
|
|
||||||
|
/// <inheritdoc/> |
||||||
|
public virtual float GetItemHeight(int index) { |
||||||
|
return FixedItemHeight != 0f |
||||||
|
? FixedItemHeight |
||||||
|
: EditorGUI.GetPropertyHeight(this[index], GUIContent.none, false) |
||||||
|
; |
||||||
|
} |
||||||
|
|
||||||
|
#endregion |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
} |
@ -0,0 +1,11 @@ |
|||||||
|
fileFormatVersion: 2 |
||||||
|
guid: 591bfb933f0cb1a429927d177e35f97d |
||||||
|
MonoImporter: |
||||||
|
externalObjects: {} |
||||||
|
serializedVersion: 2 |
||||||
|
defaultReferences: [] |
||||||
|
executionOrder: 0 |
||||||
|
icon: {instanceID: 0} |
||||||
|
userData: |
||||||
|
assetBundleName: |
||||||
|
assetBundleVariant: |
@ -1,6 +1,7 @@ |
|||||||
fileFormatVersion: 2 |
fileFormatVersion: 2 |
||||||
guid: 8fc66c8c3ee484548a40e9b4cb50f206 |
guid: 8fc66c8c3ee484548a40e9b4cb50f206 |
||||||
TextScriptImporter: |
TextScriptImporter: |
||||||
|
externalObjects: {} |
||||||
userData: |
userData: |
||||||
assetBundleName: |
assetBundleName: |
||||||
assetBundleVariant: |
assetBundleVariant: |
||||||
|
@ -0,0 +1,8 @@ |
|||||||
|
fileFormatVersion: 2 |
||||||
|
guid: adbb9aeb25106a54e9af119d9d77e332 |
||||||
|
folderAsset: yes |
||||||
|
DefaultImporter: |
||||||
|
externalObjects: {} |
||||||
|
userData: |
||||||
|
assetBundleName: |
||||||
|
assetBundleVariant: |
@ -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")] |
@ -0,0 +1,11 @@ |
|||||||
|
fileFormatVersion: 2 |
||||||
|
guid: 9229bf01f21bb1842a94bbabd158f241 |
||||||
|
MonoImporter: |
||||||
|
externalObjects: {} |
||||||
|
serializedVersion: 2 |
||||||
|
defaultReferences: [] |
||||||
|
executionOrder: 0 |
||||||
|
icon: {instanceID: 0} |
||||||
|
userData: |
||||||
|
assetBundleName: |
||||||
|
assetBundleVariant: |
@ -1,6 +1,7 @@ |
|||||||
fileFormatVersion: 2 |
fileFormatVersion: 2 |
||||||
guid: d5735c08f13f43a44be11da81110e424 |
guid: c4b649ac64aa4bd428c41192aba38c61 |
||||||
TextScriptImporter: |
TextScriptImporter: |
||||||
|
externalObjects: {} |
||||||
userData: |
userData: |
||||||
assetBundleName: |
assetBundleName: |
||||||
assetBundleVariant: |
assetBundleVariant: |
@ -0,0 +1,8 @@ |
|||||||
|
fileFormatVersion: 2 |
||||||
|
guid: 457a6fa816de84a4bb30c03f176b4554 |
||||||
|
folderAsset: yes |
||||||
|
DefaultImporter: |
||||||
|
externalObjects: {} |
||||||
|
userData: |
||||||
|
assetBundleName: |
||||||
|
assetBundleVariant: |
Binary file not shown.
@ -0,0 +1,7 @@ |
|||||||
|
fileFormatVersion: 2 |
||||||
|
guid: ff01767a12436d745bc2fc6157a4f303 |
||||||
|
DefaultImporter: |
||||||
|
externalObjects: {} |
||||||
|
userData: |
||||||
|
assetBundleName: |
||||||
|
assetBundleVariant: |
Binary file not shown.
@ -0,0 +1,7 @@ |
|||||||
|
fileFormatVersion: 2 |
||||||
|
guid: 2a6cc2b87d678a44f9aac32c49b2373f |
||||||
|
DefaultImporter: |
||||||
|
externalObjects: {} |
||||||
|
userData: |
||||||
|
assetBundleName: |
||||||
|
assetBundleVariant: |
Binary file not shown.
@ -0,0 +1,7 @@ |
|||||||
|
fileFormatVersion: 2 |
||||||
|
guid: 560954e67fbf14b43a2d6638190e8325 |
||||||
|
DefaultImporter: |
||||||
|
externalObjects: {} |
||||||
|
userData: |
||||||
|
assetBundleName: |
||||||
|
assetBundleVariant: |
Binary file not shown.
@ -0,0 +1,7 @@ |
|||||||
|
fileFormatVersion: 2 |
||||||
|
guid: 397430eb6d7634449b41b059589c33bc |
||||||
|
DefaultImporter: |
||||||
|
externalObjects: {} |
||||||
|
userData: |
||||||
|
assetBundleName: |
||||||
|
assetBundleVariant: |
After Width: | Height: | Size: 60 KiB |
@ -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: |
After Width: | Height: | Size: 8.9 KiB |
@ -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: |
@ -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" |
||||||
|
} |
||||||
} |
} |
||||||
|
Loading…
Reference in new issue