desktop-maesty/steve
7 years ago
3 changed files with 321 additions and 73 deletions
@ -0,0 +1,299 @@ |
|||||||
|
using UnityEditor; |
||||||
|
using UnityEditorInternal; |
||||||
|
using UnityEngine; |
||||||
|
using System; |
||||||
|
using System.Collections; |
||||||
|
using System.Collections.Generic; |
||||||
|
using System.Linq; |
||||||
|
using System.Text.RegularExpressions; |
||||||
|
using Rotorz.ReorderableList; |
||||||
|
using System.IO; |
||||||
|
using System.Reflection; |
||||||
|
|
||||||
|
namespace Fungus.EditorUtils |
||||||
|
{ |
||||||
|
/// <summary> |
||||||
|
/// Searchable Popup Window for selecting Event type, used by block editor |
||||||
|
/// |
||||||
|
/// Inspired by https://github.com/roboryantron/UnityEditorJunkie/blob/master/Assets/SearchableEnum/Code/Editor/SearchablePopup.cs |
||||||
|
/// </summary> |
||||||
|
public class EventSelectorPopupWindowContent : PopupWindowContent |
||||||
|
{ |
||||||
|
protected class SetEventHandlerOperation |
||||||
|
{ |
||||||
|
public Block block; |
||||||
|
public Type eventHandlerType; |
||||||
|
} |
||||||
|
|
||||||
|
private string currentHandlerName; |
||||||
|
private Block block; |
||||||
|
private List<Type> eventHandlerTypes; |
||||||
|
private int hoverIndex; |
||||||
|
private readonly string SEARCH_CONTROL_NAME = "PopupSearchControlName"; |
||||||
|
private readonly float ROW_HEIGHT = EditorGUIUtility.singleLineHeight; |
||||||
|
private List<string> allItems = new List<string>(), visibleItems = new List<string>(); |
||||||
|
private string currentFilter; |
||||||
|
private Vector2 scroll; |
||||||
|
private int scrollToIndex; |
||||||
|
private float scrollOffset; |
||||||
|
private int currentIndex; |
||||||
|
|
||||||
|
public EventSelectorPopupWindowContent(string currentHandlerName, Block block, List<Type> eventHandlerTypes) |
||||||
|
{ |
||||||
|
this.currentHandlerName = currentHandlerName; |
||||||
|
this.block = block; |
||||||
|
this.eventHandlerTypes = eventHandlerTypes; |
||||||
|
|
||||||
|
foreach (System.Type type in eventHandlerTypes) |
||||||
|
{ |
||||||
|
EventHandlerInfoAttribute info = EventHandlerEditor.GetEventHandlerInfo(type); |
||||||
|
if (info != null) |
||||||
|
{ |
||||||
|
allItems.Add(info.Category + "/" + info.EventHandlerName); |
||||||
|
} |
||||||
|
else |
||||||
|
{ |
||||||
|
allItems.Add(type.Name); |
||||||
|
} |
||||||
|
} |
||||||
|
visibleItems.AddRange(allItems); |
||||||
|
} |
||||||
|
|
||||||
|
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); |
||||||
|
} |
||||||
|
|
||||||
|
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; |
||||||
|
//searchRect.width -= CancelButton.fixedWidth; |
||||||
|
|
||||||
|
GUI.FocusControl(SEARCH_CONTROL_NAME); |
||||||
|
GUI.SetNextControlName(SEARCH_CONTROL_NAME); |
||||||
|
string newText = GUI.TextField(searchRect, "FilterBy"); |
||||||
|
|
||||||
|
//if (list.UpdateFilter(newText)) |
||||||
|
//{ |
||||||
|
// hoverIndex = 0; |
||||||
|
// scroll = Vector2.zero; |
||||||
|
//} |
||||||
|
|
||||||
|
//searchRect.x = searchRect.xMax; |
||||||
|
//searchRect.width = CancelButton.fixedWidth; |
||||||
|
|
||||||
|
//if (string.IsNullOrEmpty(list.Filter)) |
||||||
|
// GUI.Box(searchRect, GUIContent.none, DisabledCancelButton); |
||||||
|
//else if (GUI.Button(searchRect, "x", CancelButton)) |
||||||
|
//{ |
||||||
|
// list.UpdateFilter(""); |
||||||
|
// scroll = Vector2.zero; |
||||||
|
//} |
||||||
|
} |
||||||
|
|
||||||
|
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) |
||||||
|
hoverIndex = i; |
||||||
|
if (Event.current.type == EventType.MouseDown) |
||||||
|
{ |
||||||
|
//onSelectionMade(list.Entries[i].Index); |
||||||
|
SelectByName(visibleItems[i]); |
||||||
|
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]); |
||||||
|
} |
||||||
|
|
||||||
|
/// <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) |
||||||
|
{ |
||||||
|
SelectByName(visibleItems[hoverIndex]); |
||||||
|
//onSelectionMade(list.Entries[hoverIndex].Index); |
||||||
|
EditorWindow.focusedWindow.Close(); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
if (Event.current.keyCode == KeyCode.Escape) |
||||||
|
{ |
||||||
|
EditorWindow.focusedWindow.Close(); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
static public void DoEventHandlerPopUp(Rect rect, string currentHandlerName, Block block, List<Type> eventHandlerTypes) |
||||||
|
{ |
||||||
|
//new method |
||||||
|
EventSelectorPopupWindowContent win = new EventSelectorPopupWindowContent(currentHandlerName, block, eventHandlerTypes); |
||||||
|
PopupWindow.Show(rect, win); |
||||||
|
|
||||||
|
//old method |
||||||
|
|
||||||
|
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); |
||||||
|
} |
||||||
|
|
||||||
|
protected void SelectByName(string name) |
||||||
|
{ |
||||||
|
var loc = allItems.IndexOf(name); |
||||||
|
SetEventHandlerOperation operation = new SetEventHandlerOperation(); |
||||||
|
operation.block = block; |
||||||
|
operation.eventHandlerType = eventHandlerTypes[loc]; |
||||||
|
OnSelectEventHandler(operation); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,11 @@ |
|||||||
|
fileFormatVersion: 2 |
||||||
|
guid: f9ca5de337e96bf4c8a414c5c374d629 |
||||||
|
MonoImporter: |
||||||
|
externalObjects: {} |
||||||
|
serializedVersion: 2 |
||||||
|
defaultReferences: [] |
||||||
|
executionOrder: 0 |
||||||
|
icon: {instanceID: 0} |
||||||
|
userData: |
||||||
|
assetBundleName: |
||||||
|
assetBundleVariant: |
Loading…
Reference in new issue