desktop-maesty/steve
7 years ago
107 changed files with 7773 additions and 1890 deletions
@ -0,0 +1,230 @@
|
||||
using System.Collections.Generic; |
||||
using System.Text; |
||||
using System.Text.RegularExpressions; |
||||
|
||||
namespace Fungus |
||||
{ |
||||
/// <summary> |
||||
/// Handles replacing vary text segments. Keeps history of previous replacements to allow for ordered |
||||
/// sequence of variation. Inspired by https://github.com/inkle/ink/blob/master/Documentation/WritingWithInk.md#6-variable-text |
||||
/// |
||||
/// [] mark the bounds of the vary section |
||||
/// | divide elements within the variation |
||||
/// |
||||
/// Default behaviour is to show one element after another and hold the final element. Such that [a|b|c] will show |
||||
/// a the first time it is parsed, b the second and every subsequent time it will show c. |
||||
/// |
||||
/// Empty sections are allowed, such that [a||c], on second showing it will have 0 characters. |
||||
/// |
||||
/// Supports nested sections, that are only evaluated if their parent element is chosen. |
||||
/// |
||||
/// This behaviour can be modified with certain characters at the start of the [], eg. [&a|b|c]; |
||||
/// - & does not hold the final element it wraps back around to the begining in a looping fashion |
||||
/// - ! does not hold the final element, it instead returns empty for the varying section |
||||
/// - ~ chooses a random element every time it is encountered |
||||
/// </summary> |
||||
public static class TextVariationHandler |
||||
{ |
||||
public class Section |
||||
{ |
||||
public VaryType type = VaryType.Sequence; |
||||
|
||||
public enum VaryType |
||||
{ |
||||
Sequence, |
||||
Cycle, |
||||
Once, |
||||
Random |
||||
} |
||||
|
||||
public string entire = string.Empty; |
||||
public List<string> elements = new List<string>(); |
||||
|
||||
public string Select(ref int index) |
||||
{ |
||||
switch (type) |
||||
{ |
||||
case VaryType.Sequence: |
||||
index = UnityEngine.Mathf.Min(index, elements.Count - 1); |
||||
break; |
||||
case VaryType.Cycle: |
||||
index = index % elements.Count; |
||||
break; |
||||
case VaryType.Once: |
||||
//clamp to 1 more than options |
||||
index = UnityEngine.Mathf.Min(index, elements.Count); |
||||
break; |
||||
case VaryType.Random: |
||||
index = UnityEngine.Random.Range(0, elements.Count); |
||||
break; |
||||
default: |
||||
break; |
||||
} |
||||
|
||||
if (index >= 0 && index < elements.Count) |
||||
return elements[index]; |
||||
|
||||
return string.Empty; |
||||
} |
||||
} |
||||
|
||||
static Dictionary<int, int> hashedSections = new Dictionary<int, int>(); |
||||
|
||||
static public void ClearHistory() |
||||
{ |
||||
hashedSections.Clear(); |
||||
} |
||||
|
||||
/// <summary> |
||||
/// Simple parser to extract depth matched []. |
||||
/// |
||||
/// Such that a string of "[Hail and well met|Hello|[Good |]Morning] Traveler" will return |
||||
/// "[Hail and well met|Hello|[Good |]Morning]" |
||||
/// and string of "Hail and well met|Hello|[Good |]Morning" |
||||
/// will return [Good |] |
||||
/// </summary> |
||||
/// <param name="input"></param> |
||||
/// <param name="varyingSections"></param> |
||||
/// <returns></returns> |
||||
static public bool TokenizeVarySections(string input, List<Section> varyingSections) |
||||
{ |
||||
varyingSections.Clear(); |
||||
int currentDepth = 0; |
||||
int curStartIndex = 0; |
||||
int curPipeIndex = 0; |
||||
Section curSection = null; |
||||
|
||||
for (int i = 0; i < input.Length; i++) |
||||
{ |
||||
switch (input[i]) |
||||
{ |
||||
case '[': |
||||
if (currentDepth == 0) |
||||
{ |
||||
curSection = new Section(); |
||||
varyingSections.Add(curSection); |
||||
|
||||
//determine type and skip control char |
||||
var typedIndicatingChar = input[i + 1]; |
||||
switch (typedIndicatingChar) |
||||
{ |
||||
case '~': |
||||
curSection.type = Section.VaryType.Random; |
||||
break; |
||||
case '&': |
||||
curSection.type = Section.VaryType.Cycle; |
||||
break; |
||||
case '!': |
||||
curSection.type = Section.VaryType.Once; |
||||
break; |
||||
default: |
||||
break; |
||||
} |
||||
|
||||
|
||||
//mark start |
||||
curStartIndex = i; |
||||
curPipeIndex = i + 1; |
||||
} |
||||
currentDepth++; |
||||
break; |
||||
case ']': |
||||
if (currentDepth == 1) |
||||
{ |
||||
|
||||
//extract, including the ] |
||||
curSection.entire = input.Substring(curStartIndex, i - curStartIndex + 1); |
||||
|
||||
|
||||
//close an element if we started one |
||||
if (curStartIndex != curPipeIndex - 1) |
||||
{ |
||||
curSection.elements.Add(input.Substring(curPipeIndex, i - curPipeIndex)); |
||||
} |
||||
|
||||
//if has control var, clean first element |
||||
if(curSection.type != Section.VaryType.Sequence) |
||||
{ |
||||
curSection.elements[0] = curSection.elements[0].Substring(1); |
||||
} |
||||
} |
||||
currentDepth--; |
||||
break; |
||||
case '|': |
||||
if (currentDepth == 1) |
||||
{ |
||||
//split |
||||
curSection.elements.Add(input.Substring(curPipeIndex, i - curPipeIndex)); |
||||
|
||||
//over the | on the next one |
||||
curPipeIndex = i + 1; |
||||
} |
||||
break; |
||||
default: |
||||
break; |
||||
} |
||||
} |
||||
|
||||
return varyingSections.Count > 0; |
||||
} |
||||
|
||||
/// <summary> |
||||
/// Uses the results of a run of tokenisation to choose the appropriate elements |
||||
/// </summary> |
||||
/// <param name="input"></param> |
||||
/// <param name="parentHash">When called recursively, we pass down the current objects hash so as to |
||||
/// avoid similar sub /sub sub/ etc. variations</param> |
||||
/// <returns></returns> |
||||
static public string SelectVariations(string input, int parentHash = 0) |
||||
{ |
||||
// Match the regular expression pattern against a text string. |
||||
List<Section> sections = new List<Section>(); |
||||
bool foundSections = TokenizeVarySections(input, sections); |
||||
|
||||
if (!foundSections) |
||||
return input; |
||||
|
||||
StringBuilder sb = new StringBuilder(); |
||||
sb.Length = 0; |
||||
sb.Append(input); |
||||
|
||||
for (int i = 0; i < sections.Count; i++) |
||||
{ |
||||
var curSection = sections[i]; |
||||
string selected = string.Empty; |
||||
|
||||
//fetched hashed value |
||||
int index = -1; |
||||
|
||||
//as input and entire can be the same thing we need to shuffle these bits |
||||
//we use some xorshift style mixing |
||||
int inputHash = input.GetHashCode(); |
||||
inputHash ^= inputHash << 13; |
||||
int curSecHash = curSection.entire.GetHashCode(); |
||||
curSecHash ^= curSecHash >> 17; |
||||
int key = inputHash ^ curSecHash ^ parentHash; |
||||
|
||||
int foundVal = 0; |
||||
if (hashedSections.TryGetValue(key, out foundVal)) |
||||
{ |
||||
index = foundVal; |
||||
} |
||||
|
||||
index++; |
||||
|
||||
selected = curSection.Select(ref index); |
||||
|
||||
//update hashed value |
||||
hashedSections[key] = index; |
||||
|
||||
//handle sub vary within selected section |
||||
selected = SelectVariations(selected, key); |
||||
|
||||
//update with selecton |
||||
sb.Replace(curSection.entire, selected); |
||||
} |
||||
|
||||
return sb.ToString(); |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2 |
||||
guid: eb68f617801367f4dbfcd7f01911d7eb |
||||
MonoImporter: |
||||
externalObjects: {} |
||||
serializedVersion: 2 |
||||
defaultReferences: [] |
||||
executionOrder: 0 |
||||
icon: {instanceID: 0} |
||||
userData: |
||||
assetBundleName: |
||||
assetBundleVariant: |
@ -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 |
||||
guid: 1351e3cf05fcef04cbafc172b277cd32 |
||||
folderAsset: yes |
||||
timeCreated: 1434110041 |
||||
licenseType: Free |
||||
DefaultImporter: |
||||
externalObjects: {} |
||||
userData: |
||||
assetBundleName: |
||||
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
@ -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 |
||||
guid: 8fc66c8c3ee484548a40e9b4cb50f206 |
||||
TextScriptImporter: |
||||
externalObjects: {} |
||||
userData: |
||||
assetBundleName: |
||||
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 |
||||
guid: d5735c08f13f43a44be11da81110e424 |
||||
guid: c4b649ac64aa4bd428c41192aba38c61 |
||||
TextScriptImporter: |
||||
externalObjects: {} |
||||
userData: |
||||
assetBundleName: |
||||
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: |
@ -0,0 +1,218 @@
|
||||
Fungus is governed by the Asset Store EULA and MIT license; however, the |
||||
following components are governed by the licenses indicated below: |
||||
|
||||
================= |
||||
|
||||
CsvParser |
||||
MIT License |
||||
|
||||
Copyright 2014 ideafixxxer |
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: |
||||
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. |
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. |
||||
|
||||
================= |
||||
|
||||
MoonSharp |
||||
MIT License |
||||
|
||||
Copyright (c) 2014-2016, Marco Mastropaolo |
||||
All rights reserved. |
||||
|
||||
Parts of the string library are based on the KopiLua project (https://github.com/NLua/KopiLua) |
||||
Copyright (c) 2012 LoDC |
||||
|
||||
Visual Studio Code debugger code is based on code from Microsoft vscode-mono-debug project (https://github.com/Microsoft/vscode-mono-debug). |
||||
Copyright (c) Microsoft Corporation - released under MIT license. |
||||
|
||||
Remote Debugger icons are from the Eclipse project (https://www.eclipse.org/). |
||||
Copyright of The Eclipse Foundation |
||||
|
||||
The MoonSharp icon is (c) Isaac, 2014-2015 |
||||
|
||||
Redistribution and use in source and binary forms, with or without |
||||
modification, are permitted provided that the following conditions are met: |
||||
|
||||
* Redistributions of source code must retain the above copyright notice, this |
||||
list of conditions and the following disclaimer. |
||||
|
||||
* Redistributions in binary form must reproduce the above copyright notice, |
||||
this list of conditions and the following disclaimer in the documentation |
||||
and/or other materials provided with the distribution. |
||||
|
||||
* Neither the name of the {organization} nor the names of its |
||||
contributors may be used to endorse or promote products derived from |
||||
this software without specific prior written permission. |
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE |
||||
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
||||
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR |
||||
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER |
||||
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, |
||||
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
||||
|
||||
================= |
||||
|
||||
iTween |
||||
MIT License |
||||
|
||||
Copyright (c) 2011 Bob Berkebile (pixelplacment) |
||||
Please direct any bugs/comments/suggestions to http://pixelplacement.com |
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy |
||||
of this software and associated documentation files (the "Software"), to deal |
||||
in the Software without restriction, including without limitation the rights |
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
||||
copies of the Software, and to permit persons to whom the Software is |
||||
furnished to do so, subject to the following conditions: |
||||
|
||||
The above copyright notice and this permission notice shall be included in |
||||
all copies or substantial portions of the Software. |
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN |
||||
THE SOFTWARE. |
||||
|
||||
================= |
||||
|
||||
LeanTween |
||||
MIT License |
||||
|
||||
Copyright (c) 2017 Russell Savage - Dented Pixel |
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy |
||||
of this software and associated documentation files (the "Software"), to deal |
||||
in the Software without restriction, including without limitation the rights |
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
||||
copies of the Software, and to permit persons to whom the Software is |
||||
furnished to do so, subject to the following conditions: |
||||
|
||||
The above copyright notice and this permission notice shall be included in all |
||||
copies or substantial portions of the Software. |
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE |
||||
SOFTWARE. |
||||
|
||||
================= |
||||
|
||||
Easing Equations |
||||
BSD License. |
||||
|
||||
Copyright (c)2001 Robert Penner |
||||
All rights reserved. |
||||
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: |
||||
Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. |
||||
Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. |
||||
Neither the name of the author nor the names of contributors may be used to endorse or promote products derived from this software without specific prior written permission. |
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
||||
|
||||
================= |
||||
|
||||
LineEndingsEditMenu |
||||
MIT License |
||||
|
||||
Copyright (c) 2014 Tiaan Geldenhuys |
||||
|
||||
Permission is hereby granted, free of charge, to any person |
||||
obtaining a copy of this software and associated documentation |
||||
files (the "Software"), to deal in the Software without |
||||
restriction, including without limitation the rights to use, |
||||
copy, modify, merge, publish, distribute, sublicense, and/or |
||||
sell copies of the Software, and to permit persons to whom the |
||||
Software is furnished to do so, subject to the following |
||||
conditions: |
||||
|
||||
The above copyright notice and this permission notice shall be |
||||
included in all copies or substantial portions of the Software. |
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, |
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES |
||||
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND |
||||
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT |
||||
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, |
||||
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING |
||||
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR |
||||
OTHER DEALINGS IN THE SOFTWARE. |
||||
|
||||
================= |
||||
|
||||
MarkerMetro.Unity.WinLegacy |
||||
MIT License |
||||
|
||||
Copyright (c) 2015 Marker Metro |
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy |
||||
of this software and associated documentation files (the "Software"), to deal |
||||
in the Software without restriction, including without limitation the rights |
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
||||
copies of the Software, and to permit persons to whom the Software is |
||||
furnished to do so, subject to the following conditions: |
||||
|
||||
The above copyright notice and this permission notice shall be included in |
||||
all copies or substantial portions of the Software. |
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN |
||||
THE SOFTWARE. |
||||
|
||||
================= |
||||
|
||||
ReorderableListField |
||||
MIT License |
||||
|
||||
The MIT License (MIT) |
||||
|
||||
Copyright (c) 2013-2015 Rotorz Limited |
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy |
||||
of this software and associated documentation files (the "Software"), to deal |
||||
in the Software without restriction, including without limitation the rights |
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
||||
copies of the Software, and to permit persons to whom the Software is |
||||
furnished to do so, subject to the following conditions: |
||||
|
||||
The above copyright notice and this permission notice shall be included in all |
||||
copies or substantial portions of the Software. |
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE |
||||
SOFTWARE. |
||||
|
||||
================= |
||||
|
||||
Usfxr |
||||
Apache License |
||||
|
||||
Copyright 2013 Tiaan Geldenhuys, 2014 Zeh Fernando |
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License"); |
||||
you may not use this file except in compliance with the License. |
||||
You may obtain a copy of the License at |
||||
http://www.apache.org/licenses/LICENSE-2.0 |
||||
|
||||
Unless required by applicable law or agreed to in writing, software |
||||
distributed under the License is distributed on an "AS IS" BASIS, |
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
See the License for the specific language governing permissions and |
||||
limitations under the License. |
@ -1,6 +1,7 @@
|
||||
fileFormatVersion: 2 |
||||
guid: 087430efbff5ee54a8c8273aee1508fc |
||||
guid: f4289f30733584d9f82725b2434edbea |
||||
TextScriptImporter: |
||||
externalObjects: {} |
||||
userData: |
||||
assetBundleName: |
||||
assetBundleVariant: |
@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2 |
||||
guid: 8ed4c59893b9d8043bfb0fdb06ae6ff5 |
||||
folderAsset: yes |
||||
DefaultImporter: |
||||
externalObjects: {} |
||||
userData: |
||||
assetBundleName: |
||||
assetBundleVariant: |
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2 |
||||
guid: 7472e7497ac4ef84b888b1393faf2a30 |
||||
DefaultImporter: |
||||
externalObjects: {} |
||||
userData: |
||||
assetBundleName: |
||||
assetBundleVariant: |
@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2 |
||||
guid: b0ab687196033764d88aa5c2e32c035b |
||||
folderAsset: yes |
||||
DefaultImporter: |
||||
externalObjects: {} |
||||
userData: |
||||
assetBundleName: |
||||
assetBundleVariant: |
@ -0,0 +1,114 @@
|
||||
using UnityEngine; |
||||
using UnityEngine.TestTools; |
||||
using NUnit.Framework; |
||||
using System.Collections; |
||||
|
||||
public class FungusTextVariationSelectionTests |
||||
{ |
||||
[Test] |
||||
public void SimpleSequenceSelection() |
||||
{ |
||||
Fungus.TextVariationHandler.ClearHistory(); |
||||
|
||||
string startingText = @"This is test [a|b|c]"; |
||||
string startingTextA = @"This is test a"; |
||||
string startingTextB = @"This is test b"; |
||||
string startingTextC = @"This is test c"; |
||||
|
||||
string res = string.Empty; |
||||
|
||||
res = Fungus.TextVariationHandler.SelectVariations(startingText); |
||||
Assert.AreEqual(res, startingTextA); |
||||
res = Fungus.TextVariationHandler.SelectVariations(startingText); |
||||
Assert.AreEqual(res, startingTextB); |
||||
res = Fungus.TextVariationHandler.SelectVariations(startingText); |
||||
Assert.AreEqual(res, startingTextC); |
||||
res = Fungus.TextVariationHandler.SelectVariations(startingText); |
||||
Assert.AreEqual(res, startingTextC); |
||||
} |
||||
|
||||
[Test] |
||||
public void SimpleCycleSelection() |
||||
{ |
||||
Fungus.TextVariationHandler.ClearHistory(); |
||||
|
||||
string startingText = @"This is test [&a|b|c]"; |
||||
string startingTextA = @"This is test a"; |
||||
string startingTextB = @"This is test b"; |
||||
string startingTextC = @"This is test c"; |
||||
|
||||
string res = string.Empty; |
||||
|
||||
res = Fungus.TextVariationHandler.SelectVariations(startingText); |
||||
Assert.AreEqual(res, startingTextA); |
||||
res = Fungus.TextVariationHandler.SelectVariations(startingText); |
||||
Assert.AreEqual(res, startingTextB); |
||||
res = Fungus.TextVariationHandler.SelectVariations(startingText); |
||||
Assert.AreEqual(res, startingTextC); |
||||
res = Fungus.TextVariationHandler.SelectVariations(startingText); |
||||
Assert.AreEqual(res, startingTextA); |
||||
res = Fungus.TextVariationHandler.SelectVariations(startingText); |
||||
Assert.AreEqual(res, startingTextB); |
||||
res = Fungus.TextVariationHandler.SelectVariations(startingText); |
||||
Assert.AreEqual(res, startingTextC); |
||||
} |
||||
|
||||
[Test] |
||||
public void SimpleOnceSelection() |
||||
{ |
||||
Fungus.TextVariationHandler.ClearHistory(); |
||||
|
||||
string startingText = @"This is test [!a|b|c]"; |
||||
string startingTextA = @"This is test a"; |
||||
string startingTextB = @"This is test b"; |
||||
string startingTextC = @"This is test c"; |
||||
string startingTextD = @"This is test "; |
||||
|
||||
string res = string.Empty; |
||||
|
||||
res = Fungus.TextVariationHandler.SelectVariations(startingText); |
||||
Assert.AreEqual(res, startingTextA); |
||||
res = Fungus.TextVariationHandler.SelectVariations(startingText); |
||||
Assert.AreEqual(res, startingTextB); |
||||
res = Fungus.TextVariationHandler.SelectVariations(startingText); |
||||
Assert.AreEqual(res, startingTextC); |
||||
res = Fungus.TextVariationHandler.SelectVariations(startingText); |
||||
Assert.AreEqual(res, startingTextD); |
||||
res = Fungus.TextVariationHandler.SelectVariations(startingText); |
||||
Assert.AreEqual(res, startingTextD); |
||||
} |
||||
|
||||
[Test] |
||||
public void NestedSelection() |
||||
{ |
||||
Fungus.TextVariationHandler.ClearHistory(); |
||||
|
||||
string startingText = @"This is test [a||sub [~a|b]|[!b|[~c|d]]]"; |
||||
string startingTextA = @"This is test a"; |
||||
string startingTextBlank = @"This is test "; |
||||
string startingTextSubA = @"This is test sub a"; |
||||
string startingTextSubB = @"This is test sub b"; |
||||
string startingTextB = @"This is test b"; |
||||
string startingTextC = @"This is test c"; |
||||
string startingTextD = @"This is test d"; |
||||
|
||||
string res = string.Empty; |
||||
|
||||
res = Fungus.TextVariationHandler.SelectVariations(startingText); |
||||
Assert.AreEqual(res, startingTextA); |
||||
res = Fungus.TextVariationHandler.SelectVariations(startingText); |
||||
Assert.AreEqual(res, startingTextBlank); |
||||
res = Fungus.TextVariationHandler.SelectVariations(startingText); |
||||
if(res != startingTextSubA && res != startingTextSubB) |
||||
{ |
||||
Assert.Fail(); |
||||
} |
||||
res = Fungus.TextVariationHandler.SelectVariations(startingText); |
||||
Assert.AreEqual(res, startingTextB); |
||||
res = Fungus.TextVariationHandler.SelectVariations(startingText); |
||||
if (res != startingTextC && res != startingTextD) |
||||
{ |
||||
Assert.Fail(); |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2 |
||||
guid: 8769bf7410785704f95413bb0865079c |
||||
MonoImporter: |
||||
externalObjects: {} |
||||
serializedVersion: 2 |
||||
defaultReferences: [] |
||||
executionOrder: 0 |
||||
icon: {instanceID: 0} |
||||
userData: |
||||
assetBundleName: |
||||
assetBundleVariant: |
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in new issue