Chris Gregan
6 years ago
committed by
GitHub
12 changed files with 856 additions and 398 deletions
@ -0,0 +1,262 @@
|
||||
using UnityEditor; |
||||
using UnityEngine; |
||||
using System; |
||||
using System.Collections.Generic; |
||||
using System.Linq; |
||||
|
||||
namespace Fungus.EditorUtils |
||||
{ |
||||
/// <summary> |
||||
/// Common base for PopupWindowContent that is a search filterable list a la AddComponent |
||||
/// |
||||
/// Inspired by https://github.com/roboryantron/UnityEditorJunkie/blob/master/Assets/SearchableEnum/Code/Editor/SearchablePopup.cs |
||||
/// </summary> |
||||
public abstract class BasePopupWindowContent : PopupWindowContent |
||||
{ |
||||
/// <summary> |
||||
/// Called when the user has confirmed an item from the menu. |
||||
/// </summary> |
||||
/// <param name="index">Index of into the original list of items to show given to the popupcontent</param> |
||||
abstract protected void SelectByOrigIndex(int index); |
||||
|
||||
/// <summary> |
||||
/// Called during Base Ctor, must fill allItems list so the ctor can continue to fill |
||||
/// the visible items and current selected index. |
||||
/// </summary> |
||||
abstract protected void PrepareAllItems(); |
||||
|
||||
/// <summary> |
||||
/// Internal representation of 1 row of our popup list |
||||
/// </summary> |
||||
public class FilteredListItem |
||||
{ |
||||
public FilteredListItem(int index, string str, string tip = "") |
||||
{ |
||||
origIndex = index; |
||||
name = str; |
||||
lowerName = str.ToLowerInvariant(); |
||||
content = new GUIContent(str, tip); |
||||
} |
||||
public int origIndex; |
||||
public string name, lowerName; |
||||
public GUIContent content; |
||||
} |
||||
|
||||
protected int hoverIndex; |
||||
protected readonly string SEARCH_CONTROL_NAME = "PopupSearchControlName"; |
||||
protected readonly float ROW_HEIGHT = EditorGUIUtility.singleLineHeight; |
||||
protected List<FilteredListItem> allItems = new List<FilteredListItem>(), |
||||
visibleItems = new List<FilteredListItem>(); |
||||
protected string currentFilter = string.Empty; |
||||
protected Vector2 scroll; |
||||
protected int scrollToIndex; |
||||
protected float scrollOffset; |
||||
protected int currentIndex; |
||||
protected Vector2 size; |
||||
protected bool hasNoneOption = false; |
||||
|
||||
static readonly char[] SEARCH_SPLITS = new char[]{ CATEGORY_CHAR, ' ' }; |
||||
protected static readonly char CATEGORY_CHAR = '/'; |
||||
|
||||
public BasePopupWindowContent(string currentHandlerName, int width, int height, bool showNoneOption = false) |
||||
{ |
||||
this.size = new Vector2(width, height); |
||||
hasNoneOption = showNoneOption; |
||||
|
||||
PrepareAllItems(); |
||||
|
||||
allItems.Sort((lhs, rhs) => |
||||
{ |
||||
//order root level objects first |
||||
var islhsRoot = lhs.lowerName.IndexOf(CATEGORY_CHAR) != -1; |
||||
var isrhsRoot = rhs.lowerName.IndexOf(CATEGORY_CHAR) != -1; |
||||
|
||||
if(islhsRoot == isrhsRoot) |
||||
return lhs.lowerName.CompareTo(rhs.lowerName); |
||||
return islhsRoot ? 1 : -1; |
||||
}); |
||||
UpdateFilter(); |
||||
currentIndex = Mathf.Max(0, visibleItems.FindIndex(x=>x.name.Contains(currentHandlerName))); |
||||
hoverIndex = currentIndex; |
||||
} |
||||
|
||||
public override void OnGUI(Rect rect) |
||||
{ |
||||
Rect searchRect = new Rect(0, 0, rect.width, EditorStyles.toolbar.fixedHeight); |
||||
Rect scrollRect = Rect.MinMaxRect(0, searchRect.yMax, rect.xMax, rect.yMax); |
||||
|
||||
HandleKeyboard(); |
||||
DrawSearch(searchRect); |
||||
DrawSelectionArea(scrollRect); |
||||
} |
||||
|
||||
public override Vector2 GetWindowSize() |
||||
{ |
||||
return size; |
||||
} |
||||
|
||||
private void DrawSearch(Rect rect) |
||||
{ |
||||
if (Event.current.type == EventType.Repaint) |
||||
EditorStyles.toolbar.Draw(rect, false, false, false, false); |
||||
|
||||
Rect searchRect = new Rect(rect); |
||||
searchRect.xMin += 6; |
||||
searchRect.xMax -= 6; |
||||
searchRect.y += 2; |
||||
|
||||
GUI.FocusControl(SEARCH_CONTROL_NAME); |
||||
GUI.SetNextControlName(SEARCH_CONTROL_NAME); |
||||
var prevFilter = currentFilter; |
||||
currentFilter = GUI.TextField(searchRect, currentFilter); |
||||
|
||||
if (prevFilter != currentFilter) |
||||
{ |
||||
UpdateFilter(); |
||||
} |
||||
} |
||||
|
||||
private void UpdateFilter() |
||||
{ |
||||
var curlower = currentFilter.ToLowerInvariant(); |
||||
var lowers = curlower.Split(SEARCH_SPLITS); |
||||
lowers = lowers.Where(x => x.Length > 0).ToArray(); |
||||
|
||||
if (lowers == null || lowers.Length == 0) |
||||
{ |
||||
visibleItems.AddRange(allItems); |
||||
} |
||||
else |
||||
{ |
||||
visibleItems = allItems.Where(x => |
||||
{ |
||||
//we want all tokens |
||||
foreach (var item in lowers) |
||||
{ |
||||
if (!x.lowerName.Contains(item)) |
||||
return false; |
||||
} |
||||
return true; |
||||
}).ToList(); |
||||
} |
||||
|
||||
hoverIndex = 0; |
||||
scroll = Vector2.zero; |
||||
if(hasNoneOption) |
||||
visibleItems.Insert(0, new FilteredListItem(-1, "None")); |
||||
} |
||||
|
||||
private void DrawSelectionArea(Rect scrollRect) |
||||
{ |
||||
Rect contentRect = new Rect(0, 0, |
||||
scrollRect.width - GUI.skin.verticalScrollbar.fixedWidth, |
||||
visibleItems.Count * ROW_HEIGHT); |
||||
|
||||
scroll = GUI.BeginScrollView(scrollRect, scroll, contentRect); |
||||
|
||||
Rect rowRect = new Rect(0, 0, scrollRect.width, ROW_HEIGHT); |
||||
|
||||
for (int i = 0; i < visibleItems.Count; i++) |
||||
{ |
||||
if (scrollToIndex == i && |
||||
(Event.current.type == EventType.Repaint |
||||
|| Event.current.type == EventType.Layout)) |
||||
{ |
||||
Rect r = new Rect(rowRect); |
||||
r.y += scrollOffset; |
||||
GUI.ScrollTo(r); |
||||
scrollToIndex = -1; |
||||
scroll.x = 0; |
||||
} |
||||
|
||||
if (rowRect.Contains(Event.current.mousePosition)) |
||||
{ |
||||
if (Event.current.type == EventType.MouseMove || |
||||
Event.current.type == EventType.ScrollWheel) |
||||
{ |
||||
//if new item force update so it's snappier |
||||
if (hoverIndex != 1) |
||||
{ |
||||
this.editorWindow.Repaint(); |
||||
} |
||||
|
||||
hoverIndex = i; |
||||
} |
||||
|
||||
if (Event.current.type == EventType.MouseDown) |
||||
{ |
||||
//onSelectionMade(list.Entries[i].Index); |
||||
SelectByOrigIndex(visibleItems[i].origIndex); |
||||
EditorWindow.focusedWindow.Close(); |
||||
} |
||||
} |
||||
|
||||
DrawRow(rowRect, i); |
||||
|
||||
rowRect.y = rowRect.yMax; |
||||
} |
||||
|
||||
GUI.EndScrollView(); |
||||
} |
||||
|
||||
private static void DrawBox(Rect rect, Color tint) |
||||
{ |
||||
Color c = GUI.color; |
||||
GUI.color = tint; |
||||
GUI.Box(rect, ""); |
||||
GUI.color = c; |
||||
} |
||||
|
||||
private void DrawRow(Rect rowRect, int i) |
||||
{ |
||||
if (i == currentIndex) |
||||
DrawBox(rowRect, Color.cyan); |
||||
else if (i == hoverIndex) |
||||
DrawBox(rowRect, Color.white); |
||||
|
||||
Rect labelRect = new Rect(rowRect); |
||||
//labelRect.xMin += ROW_INDENT; |
||||
|
||||
GUI.Label(labelRect, visibleItems[i].content); |
||||
} |
||||
|
||||
/// <summary> |
||||
/// Process keyboard input to navigate the choices or make a selection. |
||||
/// </summary> |
||||
private void HandleKeyboard() |
||||
{ |
||||
if (Event.current.type == EventType.KeyDown) |
||||
{ |
||||
if (Event.current.keyCode == KeyCode.DownArrow) |
||||
{ |
||||
hoverIndex = Mathf.Min(visibleItems.Count - 1, hoverIndex + 1); |
||||
Event.current.Use(); |
||||
scrollToIndex = hoverIndex; |
||||
scrollOffset = ROW_HEIGHT; |
||||
} |
||||
|
||||
if (Event.current.keyCode == KeyCode.UpArrow) |
||||
{ |
||||
hoverIndex = Mathf.Max(0, hoverIndex - 1); |
||||
Event.current.Use(); |
||||
scrollToIndex = hoverIndex; |
||||
scrollOffset = -ROW_HEIGHT; |
||||
} |
||||
|
||||
if (Event.current.keyCode == KeyCode.Return) |
||||
{ |
||||
if (hoverIndex >= 0 && hoverIndex < visibleItems.Count) |
||||
{ |
||||
SelectByOrigIndex(visibleItems[hoverIndex].origIndex); |
||||
EditorWindow.focusedWindow.Close(); |
||||
} |
||||
} |
||||
|
||||
if (Event.current.keyCode == KeyCode.Escape) |
||||
{ |
||||
EditorWindow.focusedWindow.Close(); |
||||
} |
||||
} |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2 |
||||
guid: be9eead8f19216444b4a87e94fe02ed3 |
||||
MonoImporter: |
||||
externalObjects: {} |
||||
serializedVersion: 2 |
||||
defaultReferences: [] |
||||
executionOrder: 0 |
||||
icon: {instanceID: 0} |
||||
userData: |
||||
assetBundleName: |
||||
assetBundleVariant: |
@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2 |
||||
guid: b99cf5f1ea08b914c94ee372bc4d76a7 |
||||
folderAsset: yes |
||||
DefaultImporter: |
||||
externalObjects: {} |
||||
userData: |
||||
assetBundleName: |
||||
assetBundleVariant: |
@ -0,0 +1,176 @@
|
||||
using UnityEditor; |
||||
using UnityEngine; |
||||
using System; |
||||
using System.Collections.Generic; |
||||
using System.Linq; |
||||
|
||||
namespace Fungus.EditorUtils |
||||
{ |
||||
/// <summary> |
||||
/// Searchable Popup Window for adding a command to a block |
||||
/// </summary> |
||||
public class CommandSelectorPopupWindowContent : BasePopupWindowContent |
||||
{ |
||||
static List<System.Type> commandTypes; |
||||
|
||||
static void CacheCommandTypes() |
||||
{ |
||||
commandTypes = EditorExtensions.FindDerivedTypes(typeof(Command)).Where(x => !x.IsAbstract).ToList(); |
||||
} |
||||
|
||||
[UnityEditor.Callbacks.DidReloadScripts] |
||||
private static void OnScriptsReloaded() |
||||
{ |
||||
CacheCommandTypes(); |
||||
} |
||||
|
||||
static Block curBlock; |
||||
static protected List<KeyValuePair<System.Type, CommandInfoAttribute>> filteredAttributes; |
||||
|
||||
public CommandSelectorPopupWindowContent(string currentHandlerName, int width, int height) |
||||
: base(currentHandlerName, width, height) |
||||
{ |
||||
} |
||||
|
||||
protected override void SelectByOrigIndex(int index) |
||||
{ |
||||
var commandType = (index >= 0 && index < commandTypes.Count) ? commandTypes[index] : null; |
||||
AddCommandCallback(commandType); |
||||
} |
||||
|
||||
protected override void PrepareAllItems() |
||||
{ |
||||
if (commandTypes == null || commandTypes.Count == 0) |
||||
{ |
||||
CacheCommandTypes(); |
||||
} |
||||
|
||||
|
||||
filteredAttributes = GetFilteredSupportedCommands(curBlock.GetFlowchart()); |
||||
|
||||
foreach (var item in filteredAttributes) |
||||
{ |
||||
//force lookup to orig index here to account for commmand lists being filtered by users |
||||
var newFilteredItem = new FilteredListItem(commandTypes.IndexOf(item.Key), (item.Value.Category.Length > 0 ? item.Value.Category + CATEGORY_CHAR : "") + item.Value.CommandName, item.Value.HelpText); |
||||
allItems.Add(newFilteredItem); |
||||
} |
||||
} |
||||
|
||||
static public void ShowCommandMenu(Rect position, string currentHandlerName, Block block, int width, int height) |
||||
{ |
||||
curBlock = block; |
||||
|
||||
|
||||
if (FungusEditorPreferences.useExperimentalMenus) |
||||
{ |
||||
var win = new CommandSelectorPopupWindowContent(currentHandlerName, |
||||
width, (int)(height - EditorGUIUtility.singleLineHeight * 3)); |
||||
PopupWindow.Show(position, win); |
||||
} |
||||
else |
||||
{ |
||||
//need to ensure we have filtered data |
||||
filteredAttributes = GetFilteredSupportedCommands(curBlock.GetFlowchart()); |
||||
} |
||||
|
||||
//old method |
||||
DoOlderMenu(); |
||||
} |
||||
|
||||
protected static List<KeyValuePair<System.Type, CommandInfoAttribute>> GetFilteredSupportedCommands(Flowchart flowchart) |
||||
{ |
||||
List<KeyValuePair<System.Type, CommandInfoAttribute>> filteredAttributes = BlockEditor.GetFilteredCommandInfoAttribute(commandTypes); |
||||
|
||||
filteredAttributes.Sort(BlockEditor.CompareCommandAttributes); |
||||
|
||||
filteredAttributes = filteredAttributes.Where(x => flowchart.IsCommandSupported(x.Value)).ToList(); |
||||
|
||||
return filteredAttributes; |
||||
} |
||||
|
||||
|
||||
static protected void DoOlderMenu() |
||||
{ |
||||
GenericMenu commandMenu = new GenericMenu(); |
||||
|
||||
// Build menu list |
||||
|
||||
foreach (var keyPair in filteredAttributes) |
||||
{ |
||||
GUIContent menuItem; |
||||
if (keyPair.Value.Category == "") |
||||
{ |
||||
menuItem = new GUIContent(keyPair.Value.CommandName); |
||||
} |
||||
else |
||||
{ |
||||
menuItem = new GUIContent(keyPair.Value.Category + CATEGORY_CHAR + keyPair.Value.CommandName); |
||||
} |
||||
|
||||
commandMenu.AddItem(menuItem, false, AddCommandCallback, keyPair.Key); |
||||
} |
||||
|
||||
commandMenu.ShowAsContext(); |
||||
} |
||||
|
||||
//Used by GenericMenu Delegate |
||||
static protected void AddCommandCallback(object obj) |
||||
{ |
||||
Type command = obj as Type; |
||||
if (command != null) |
||||
{ |
||||
AddCommandCallback(command); |
||||
} |
||||
} |
||||
|
||||
|
||||
static protected void AddCommandCallback(Type commandType) |
||||
{ |
||||
var block = curBlock; |
||||
if (block == null || commandType == null) |
||||
{ |
||||
return; |
||||
} |
||||
|
||||
var flowchart = (Flowchart)block.GetFlowchart(); |
||||
|
||||
// Use index of last selected command in list, or end of list if nothing selected. |
||||
int index = -1; |
||||
foreach (var command in flowchart.SelectedCommands) |
||||
{ |
||||
if (command.CommandIndex + 1 > index) |
||||
{ |
||||
index = command.CommandIndex + 1; |
||||
} |
||||
} |
||||
if (index == -1) |
||||
{ |
||||
index = block.CommandList.Count; |
||||
} |
||||
|
||||
var newCommand = Undo.AddComponent(block.gameObject, commandType) as Command; |
||||
block.GetFlowchart().AddSelectedCommand(newCommand); |
||||
newCommand.ParentBlock = block; |
||||
newCommand.ItemId = flowchart.NextItemId(); |
||||
|
||||
// Let command know it has just been added to the block |
||||
newCommand.OnCommandAdded(block); |
||||
|
||||
Undo.RecordObject(block, "Set command type"); |
||||
if (index < block.CommandList.Count - 1) |
||||
{ |
||||
block.CommandList.Insert(index, newCommand); |
||||
} |
||||
else |
||||
{ |
||||
block.CommandList.Add(newCommand); |
||||
} |
||||
|
||||
// Because this is an async call, we need to force prefab instances to record changes |
||||
PrefabUtility.RecordPrefabInstancePropertyModifications(block); |
||||
|
||||
flowchart.ClearSelectedCommands(); |
||||
|
||||
} |
||||
} |
||||
} |
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2 |
||||
guid: 0e2650550a8549143b9eaab2c2dad511 |
||||
MonoImporter: |
||||
externalObjects: {} |
||||
serializedVersion: 2 |
||||
defaultReferences: [] |
||||
executionOrder: 0 |
||||
icon: {instanceID: 0} |
||||
userData: |
||||
assetBundleName: |
||||
assetBundleVariant: |
@ -0,0 +1,156 @@
|
||||
using UnityEditor; |
||||
using UnityEngine; |
||||
using System; |
||||
using System.Collections.Generic; |
||||
using System.Linq; |
||||
|
||||
namespace Fungus.EditorUtils |
||||
{ |
||||
/// <summary> |
||||
/// Searchable Popup Window for selecting Event type, used by block editor |
||||
/// </summary> |
||||
public class EventSelectorPopupWindowContent : BasePopupWindowContent |
||||
{ |
||||
static List<System.Type> eventHandlerTypes; |
||||
|
||||
static void CacheEventHandlerTypes() |
||||
{ |
||||
eventHandlerTypes = EditorExtensions.FindDerivedTypes(typeof(EventHandler)).Where(x => !x.IsAbstract).ToList(); |
||||
} |
||||
|
||||
[UnityEditor.Callbacks.DidReloadScripts] |
||||
private static void OnScriptsReloaded() |
||||
{ |
||||
CacheEventHandlerTypes(); |
||||
} |
||||
|
||||
protected class SetEventHandlerOperation |
||||
{ |
||||
public Block block; |
||||
public Type eventHandlerType; |
||||
} |
||||
|
||||
protected Block block; |
||||
public EventSelectorPopupWindowContent(string currentHandlerName, Block block, int width, int height) |
||||
:base(currentHandlerName, width, height, true) |
||||
{ |
||||
this.block = block; |
||||
} |
||||
|
||||
protected override void PrepareAllItems() |
||||
{ |
||||
if (eventHandlerTypes == null || eventHandlerTypes.Count == 0) |
||||
{ |
||||
CacheEventHandlerTypes(); |
||||
} |
||||
|
||||
int i = 0; |
||||
foreach (System.Type type in eventHandlerTypes) |
||||
{ |
||||
EventHandlerInfoAttribute info = EventHandlerEditor.GetEventHandlerInfo(type); |
||||
if (info != null) |
||||
{ |
||||
allItems.Add(new FilteredListItem(i, (info.Category.Length > 0 ? info.Category + CATEGORY_CHAR : "") + info.EventHandlerName, info.HelpText)); |
||||
} |
||||
else |
||||
{ |
||||
allItems.Add(new FilteredListItem(i, type.Name, info.HelpText)); |
||||
} |
||||
|
||||
i++; |
||||
} |
||||
} |
||||
|
||||
override protected void SelectByOrigIndex(int index) |
||||
{ |
||||
SetEventHandlerOperation operation = new SetEventHandlerOperation(); |
||||
operation.block = block; |
||||
operation.eventHandlerType = (index >= 0 && index < eventHandlerTypes.Count) ? eventHandlerTypes[index] : null; |
||||
OnSelectEventHandler(operation); |
||||
} |
||||
|
||||
|
||||
static public void DoEventHandlerPopUp(Rect position, string currentHandlerName, Block block, int width, int height) |
||||
{ |
||||
if (FungusEditorPreferences.useExperimentalMenus) |
||||
{ |
||||
//new method |
||||
EventSelectorPopupWindowContent win = new EventSelectorPopupWindowContent(currentHandlerName, block, width, height); |
||||
PopupWindow.Show(position, win); |
||||
} |
||||
//old method |
||||
DoOlderMenu(block); |
||||
} |
||||
|
||||
static protected void DoOlderMenu(Block block) |
||||
{ |
||||
|
||||
SetEventHandlerOperation noneOperation = new SetEventHandlerOperation(); |
||||
noneOperation.block = block; |
||||
noneOperation.eventHandlerType = null; |
||||
|
||||
GenericMenu eventHandlerMenu = new GenericMenu(); |
||||
eventHandlerMenu.AddItem(new GUIContent("None"), false, OnSelectEventHandler, noneOperation); |
||||
|
||||
// Add event handlers with no category first |
||||
foreach (System.Type type in eventHandlerTypes) |
||||
{ |
||||
EventHandlerInfoAttribute info = EventHandlerEditor.GetEventHandlerInfo(type); |
||||
if (info != null && |
||||
info.Category.Length == 0) |
||||
{ |
||||
SetEventHandlerOperation operation = new SetEventHandlerOperation(); |
||||
operation.block = block; |
||||
operation.eventHandlerType = type; |
||||
|
||||
eventHandlerMenu.AddItem(new GUIContent(info.EventHandlerName), false, OnSelectEventHandler, operation); |
||||
} |
||||
} |
||||
|
||||
// Add event handlers with a category afterwards |
||||
foreach (System.Type type in eventHandlerTypes) |
||||
{ |
||||
EventHandlerInfoAttribute info = EventHandlerEditor.GetEventHandlerInfo(type); |
||||
if (info != null && |
||||
info.Category.Length > 0) |
||||
{ |
||||
SetEventHandlerOperation operation = new SetEventHandlerOperation(); |
||||
operation.block = block; |
||||
operation.eventHandlerType = type; |
||||
string typeName = info.Category + "/" + info.EventHandlerName; |
||||
eventHandlerMenu.AddItem(new GUIContent(typeName), false, OnSelectEventHandler, operation); |
||||
} |
||||
} |
||||
|
||||
eventHandlerMenu.ShowAsContext(); |
||||
} |
||||
|
||||
static protected void OnSelectEventHandler(object obj) |
||||
{ |
||||
SetEventHandlerOperation operation = obj as SetEventHandlerOperation; |
||||
Block block = operation.block; |
||||
System.Type selectedType = operation.eventHandlerType; |
||||
if (block == null) |
||||
{ |
||||
return; |
||||
} |
||||
|
||||
Undo.RecordObject(block, "Set Event Handler"); |
||||
|
||||
if (block._EventHandler != null) |
||||
{ |
||||
Undo.DestroyObjectImmediate(block._EventHandler); |
||||
} |
||||
|
||||
if (selectedType != null) |
||||
{ |
||||
EventHandler newHandler = Undo.AddComponent(block.gameObject, selectedType) as EventHandler; |
||||
newHandler.ParentBlock = block; |
||||
block._EventHandler = newHandler; |
||||
} |
||||
|
||||
// Because this is an async call, we need to force prefab instances to record changes |
||||
PrefabUtility.RecordPrefabInstancePropertyModifications(block); |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2 |
||||
guid: f9ca5de337e96bf4c8a414c5c374d629 |
||||
MonoImporter: |
||||
externalObjects: {} |
||||
serializedVersion: 2 |
||||
defaultReferences: [] |
||||
executionOrder: 0 |
||||
icon: {instanceID: 0} |
||||
userData: |
||||
assetBundleName: |
||||
assetBundleVariant: |
@ -0,0 +1,130 @@
|
||||
using System.Collections; |
||||
using System.Collections.Generic; |
||||
using UnityEngine; |
||||
using UnityEditor; |
||||
using System.Linq; |
||||
|
||||
namespace Fungus.EditorUtils |
||||
{ |
||||
/// <summary> |
||||
/// Show the variable selection window as a searchable popup |
||||
/// </summary> |
||||
public class VariableSelectPopupWindowContent : BasePopupWindowContent |
||||
{ |
||||
static readonly int POPUP_WIDTH = 200, POPUP_HEIGHT = 200; |
||||
static List<System.Type> types; |
||||
|
||||
static void CacheVariableTypes() |
||||
{ |
||||
var derivedType = typeof(Variable); |
||||
types = EditorExtensions.FindDerivedTypes(derivedType) |
||||
.Where(x => !x.IsAbstract && derivedType.IsAssignableFrom(x)) |
||||
.ToList(); |
||||
} |
||||
|
||||
[UnityEditor.Callbacks.DidReloadScripts] |
||||
private static void OnScriptsReloaded() |
||||
{ |
||||
CacheVariableTypes(); |
||||
} |
||||
|
||||
protected override void PrepareAllItems() |
||||
{ |
||||
if(types == null || types.Count == 0) |
||||
{ |
||||
CacheVariableTypes(); |
||||
} |
||||
|
||||
int i = 0; |
||||
foreach (var item in types) |
||||
{ |
||||
VariableInfoAttribute variableInfo = VariableEditor.GetVariableInfo(item); |
||||
if (variableInfo != null) |
||||
{ |
||||
allItems.Add(new FilteredListItem(i, (variableInfo.Category.Length > 0 ? variableInfo.Category + CATEGORY_CHAR : "") + variableInfo.VariableType)); |
||||
} |
||||
|
||||
i++; |
||||
} |
||||
} |
||||
|
||||
protected override void SelectByOrigIndex(int index) |
||||
{ |
||||
AddVariable(types[index]); |
||||
} |
||||
|
||||
static public void DoAddVariable(Rect position, string currentHandlerName, Flowchart flowchart) |
||||
{ |
||||
curFlowchart = flowchart; |
||||
if (FungusEditorPreferences.useExperimentalMenus) |
||||
{ |
||||
//new method |
||||
VariableSelectPopupWindowContent win = new VariableSelectPopupWindowContent(currentHandlerName, POPUP_WIDTH, POPUP_HEIGHT); |
||||
PopupWindow.Show(position, win); |
||||
} |
||||
//old method |
||||
DoOlderMenu(flowchart); |
||||
} |
||||
|
||||
static protected void DoOlderMenu(Flowchart flowchart) |
||||
{ |
||||
GenericMenu menu = new GenericMenu(); |
||||
|
||||
// Add variable types without a category |
||||
foreach (var type in types) |
||||
{ |
||||
VariableInfoAttribute variableInfo = VariableEditor.GetVariableInfo(type); |
||||
if (variableInfo == null || |
||||
variableInfo.Category != "") |
||||
{ |
||||
continue; |
||||
} |
||||
|
||||
GUIContent typeName = new GUIContent(variableInfo.VariableType); |
||||
|
||||
menu.AddItem(typeName, false, AddVariable, type); |
||||
} |
||||
|
||||
// Add types with a category |
||||
foreach (var type in types) |
||||
{ |
||||
VariableInfoAttribute variableInfo = VariableEditor.GetVariableInfo(type); |
||||
if (variableInfo == null || |
||||
variableInfo.Category == "") |
||||
{ |
||||
continue; |
||||
} |
||||
|
||||
GUIContent typeName = new GUIContent(variableInfo.Category + CATEGORY_CHAR + variableInfo.VariableType); |
||||
|
||||
menu.AddItem(typeName, false, AddVariable, type); |
||||
} |
||||
|
||||
menu.ShowAsContext(); |
||||
} |
||||
|
||||
private static Flowchart curFlowchart; |
||||
|
||||
public VariableSelectPopupWindowContent(string currentHandlerName, int width, int height) |
||||
: base(currentHandlerName, width, height) |
||||
{ |
||||
} |
||||
|
||||
protected static void AddVariable(object obj) |
||||
{ |
||||
System.Type t = obj as System.Type; |
||||
if (t == null) |
||||
{ |
||||
return; |
||||
} |
||||
|
||||
Undo.RecordObject(curFlowchart, "Add Variable"); |
||||
Variable newVariable = curFlowchart.gameObject.AddComponent(t) as Variable; |
||||
newVariable.Key = curFlowchart.GetUniqueVariableKey(""); |
||||
curFlowchart.Variables.Add(newVariable); |
||||
|
||||
// Because this is an async call, we need to force prefab instances to record changes |
||||
PrefabUtility.RecordPrefabInstancePropertyModifications(curFlowchart); |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2 |
||||
guid: 933b6fc31e5eac04ea3b2a1fa9a3b418 |
||||
MonoImporter: |
||||
externalObjects: {} |
||||
serializedVersion: 2 |
||||
defaultReferences: [] |
||||
executionOrder: 0 |
||||
icon: {instanceID: 0} |
||||
userData: |
||||
assetBundleName: |
||||
assetBundleVariant: |
Loading…
Reference in new issue