0.1.0: Added favorites window
This commit is contained in:
parent
80499f0a7e
commit
dea60c6e4a
8
Editor.meta
Normal file
8
Editor.meta
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 3404f03e41295794998e14f145cc0000
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
8
Editor/Favorites.meta
Normal file
8
Editor/Favorites.meta
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 22b00eaff1a81a44ea0fcf0c016bd2e2
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
8
Editor/Favorites/Enums.meta
Normal file
8
Editor/Favorites/Enums.meta
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 1b77a50e79274018aac89e7a4f0c185d
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
16
Editor/Favorites/Enums/EManipulatingState.cs
Normal file
16
Editor/Favorites/Enums/EManipulatingState.cs
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
namespace Game.NavigationTool.Editor
|
||||
{
|
||||
public enum EManipulatingState : byte
|
||||
{
|
||||
None,
|
||||
BeginClick,
|
||||
PerformedClick,
|
||||
EndClick,
|
||||
BeginContextClick,
|
||||
PerformedContextClick,
|
||||
EndContextClick,
|
||||
BeginDrag,
|
||||
PerformedDrag,
|
||||
EndDrag
|
||||
}
|
||||
}
|
||||
3
Editor/Favorites/Enums/EManipulatingState.cs.meta
Normal file
3
Editor/Favorites/Enums/EManipulatingState.cs.meta
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
fileFormatVersion: 2
|
||||
guid: a166f7a5dc6042dcae04bf352b8144ce
|
||||
timeCreated: 1613213516
|
||||
3
Editor/Favorites/Utilities.meta
Normal file
3
Editor/Favorites/Utilities.meta
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
fileFormatVersion: 2
|
||||
guid: feac89e79687422296585bfe2a8a4ebc
|
||||
timeCreated: 1613162380
|
||||
309
Editor/Favorites/Utilities/Favorites.cs
Normal file
309
Editor/Favorites/Utilities/Favorites.cs
Normal file
|
|
@ -0,0 +1,309 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
using Object = UnityEngine.Object;
|
||||
|
||||
namespace Game.NavigationTool.Editor
|
||||
{
|
||||
[Serializable]
|
||||
internal sealed class Favorites : ISerializationCallbackReceiver
|
||||
{
|
||||
public static readonly string PREF_ID = "PREF_FAVORITE_LIST";
|
||||
|
||||
public List<Entry> entries;
|
||||
|
||||
public Favorites()
|
||||
{
|
||||
entries = new List<Entry>();
|
||||
string json = EditorPrefs.GetString(PREF_ID);
|
||||
|
||||
if (!string.IsNullOrEmpty(json))
|
||||
EditorJsonUtility.FromJsonOverwrite(json, this);
|
||||
}
|
||||
|
||||
void ISerializationCallbackReceiver.OnBeforeSerialize()
|
||||
{
|
||||
}
|
||||
|
||||
void ISerializationCallbackReceiver.OnAfterDeserialize()
|
||||
{
|
||||
var guidToEntry = new Dictionary<string, Entry>(entries.Count);
|
||||
|
||||
for (var i = 0; i < entries.Count; i++)
|
||||
{
|
||||
Entry e = entries[i];
|
||||
guidToEntry.Add(e.guid, e);
|
||||
}
|
||||
|
||||
for (var i = 0; i < entries.Count; i++)
|
||||
{
|
||||
Entry e = entries[i];
|
||||
|
||||
if (e.isAsset)
|
||||
continue;
|
||||
|
||||
for (int j = e.children.Count - 1; j >= 0; j--)
|
||||
{
|
||||
Entry c = guidToEntry[e.children[j].guid];
|
||||
|
||||
if (c != null)
|
||||
{
|
||||
e.children[j].entry = c;
|
||||
c.parent = e;
|
||||
}
|
||||
else
|
||||
{
|
||||
e.children.RemoveAt(j);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void Add(string guid, Entry toParent = null)
|
||||
{
|
||||
if (InternalAddEntry(Entry.CreateAsset(guid), toParent))
|
||||
Save();
|
||||
}
|
||||
|
||||
public void AddFolder(string name, Entry toParent = null)
|
||||
{
|
||||
if (InternalAddEntry(Entry.CreateFolder(name), toParent))
|
||||
Save();
|
||||
}
|
||||
|
||||
private bool InternalAddEntry(Entry e, Entry toParent)
|
||||
{
|
||||
e.Refresh();
|
||||
|
||||
if (!e.valid)
|
||||
return false;
|
||||
|
||||
entries.Add(e);
|
||||
|
||||
if (toParent != null)
|
||||
{
|
||||
e.parent = toParent;
|
||||
e.indentLevel = toParent.indentLevel + 1;
|
||||
toParent.AddChild(e);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public void AddRange(string[] guids, Entry toParent = null)
|
||||
{
|
||||
var isDirty = false;
|
||||
|
||||
for (var i = 0; i < guids.Length; i++)
|
||||
{
|
||||
if (InternalAddEntry(Entry.CreateAsset(guids[i]), toParent))
|
||||
isDirty = true;
|
||||
}
|
||||
|
||||
if (isDirty)
|
||||
Save();
|
||||
}
|
||||
|
||||
public void AddRangeByPath(string[] paths, Entry toParent = null)
|
||||
{
|
||||
var isDirty = false;
|
||||
|
||||
for (var i = 0; i < paths.Length; i++)
|
||||
{
|
||||
string guid = AssetDatabase.AssetPathToGUID(paths[i]);
|
||||
|
||||
if (InternalAddEntry(Entry.CreateAsset(guid), toParent))
|
||||
isDirty = true;
|
||||
}
|
||||
|
||||
if (isDirty)
|
||||
Save();
|
||||
}
|
||||
|
||||
public void Remove(Entry e)
|
||||
{
|
||||
if (InternalRemove(e))
|
||||
Save();
|
||||
}
|
||||
|
||||
private bool InternalRemove(Entry e)
|
||||
{
|
||||
if (!entries.Remove(e))
|
||||
return false;
|
||||
|
||||
e.parent?.RemoveChild(e);
|
||||
|
||||
if (!e.isAsset)
|
||||
{
|
||||
for (var i = 0; i < e.children.Count; i++)
|
||||
{
|
||||
InternalRemove(e.children[i].entry);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public void Move(Entry e, Entry toParent)
|
||||
{
|
||||
InternalMove(e, toParent);
|
||||
Save();
|
||||
}
|
||||
|
||||
private void InternalMove(Entry e, Entry toParent)
|
||||
{
|
||||
if (e.parent != null)
|
||||
{
|
||||
e.parent.RemoveChild(e);
|
||||
e.parent = null;
|
||||
e.indentLevel = 0;
|
||||
}
|
||||
|
||||
if (toParent != null && toParent.isAsset)
|
||||
toParent = toParent.parent;
|
||||
|
||||
if (toParent != null)
|
||||
{
|
||||
toParent.AddChild(e);
|
||||
e.parent = toParent;
|
||||
e.indentLevel = e.parent.indentLevel + 1;
|
||||
}
|
||||
|
||||
InternalMoveIndentLevel(e);
|
||||
}
|
||||
|
||||
private void InternalMoveIndentLevel(Entry parent)
|
||||
{
|
||||
if (parent.isAsset)
|
||||
return;
|
||||
|
||||
for (var i = 0; i < parent.children.Count; i++)
|
||||
{
|
||||
parent.children[i].entry.indentLevel = parent.indentLevel + 1;
|
||||
InternalMoveIndentLevel(parent.children[i].entry);
|
||||
}
|
||||
}
|
||||
|
||||
public Object GetObject(Entry entry)
|
||||
{
|
||||
string path = AssetDatabase.GUIDToAssetPath(entry.assetGuid);
|
||||
return AssetDatabase.LoadMainAssetAtPath(path);
|
||||
}
|
||||
|
||||
public void Save()
|
||||
{
|
||||
string json = EditorJsonUtility.ToJson(this, false);
|
||||
EditorPrefs.SetString(PREF_ID, json);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Class: Entry
|
||||
/// </summary>
|
||||
[Serializable]
|
||||
public sealed class Entry : ISerializationCallbackReceiver
|
||||
{
|
||||
public string guid;
|
||||
public string assetGuid;
|
||||
public string name;
|
||||
public bool isAsset;
|
||||
public bool expanded;
|
||||
public int indentLevel;
|
||||
public List<Child> children;
|
||||
|
||||
[NonSerialized]
|
||||
public bool valid;
|
||||
[NonSerialized]
|
||||
public Entry parent;
|
||||
[NonSerialized]
|
||||
public GUIContent content;
|
||||
[NonSerialized]
|
||||
public string lowerName;
|
||||
|
||||
private Entry(string assetGuid, string name, bool isAsset)
|
||||
{
|
||||
guid = Guid.NewGuid().ToString();
|
||||
this.assetGuid = assetGuid;
|
||||
this.name = name;
|
||||
this.isAsset = isAsset;
|
||||
|
||||
if (!isAsset)
|
||||
{
|
||||
expanded = true;
|
||||
children = new List<Child>();
|
||||
}
|
||||
}
|
||||
|
||||
void ISerializationCallbackReceiver.OnBeforeSerialize()
|
||||
{
|
||||
}
|
||||
|
||||
void ISerializationCallbackReceiver.OnAfterDeserialize()
|
||||
{
|
||||
if (isAsset)
|
||||
children = null;
|
||||
|
||||
Refresh();
|
||||
}
|
||||
|
||||
public void Refresh()
|
||||
{
|
||||
if (isAsset)
|
||||
{
|
||||
string path = AssetDatabase.GUIDToAssetPath(assetGuid);
|
||||
name = Path.GetFileNameWithoutExtension(path);
|
||||
lowerName = name.ToLower();
|
||||
valid = !string.IsNullOrEmpty(path);
|
||||
content = new GUIContent(name, FavoritesGUIUtility.GetIcon(path), path);
|
||||
}
|
||||
else
|
||||
{
|
||||
valid = true;
|
||||
content = new GUIContent(name, FavoritesGUIUtility.GetFolderIcon());
|
||||
}
|
||||
}
|
||||
|
||||
public void AddChild(Entry entry)
|
||||
{
|
||||
children.Add(new Child(entry));
|
||||
}
|
||||
|
||||
public void RemoveChild(Entry entry)
|
||||
{
|
||||
for (int i = children.Count - 1; i >= 0; i--)
|
||||
{
|
||||
if (children[i].entry == entry)
|
||||
children.RemoveAt(i);
|
||||
}
|
||||
}
|
||||
|
||||
public static Entry CreateFolder(string name)
|
||||
{
|
||||
return new Entry(string.Empty, name, false);
|
||||
}
|
||||
|
||||
public static Entry CreateAsset(string assetGuid)
|
||||
{
|
||||
return new Entry(assetGuid, string.Empty, true);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Class: Entry child
|
||||
/// </summary>
|
||||
[Serializable]
|
||||
public sealed class Child
|
||||
{
|
||||
public string guid;
|
||||
[NonSerialized]
|
||||
public Entry entry;
|
||||
|
||||
public Child(Entry entry)
|
||||
{
|
||||
guid = entry.guid;
|
||||
this.entry = entry;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
3
Editor/Favorites/Utilities/Favorites.cs.meta
Normal file
3
Editor/Favorites/Utilities/Favorites.cs.meta
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 7ec45414bdf74e81800f8ffaf95f26ec
|
||||
timeCreated: 1613162445
|
||||
112
Editor/Favorites/Utilities/FavoritesGUIUtility.cs
Normal file
112
Editor/Favorites/Utilities/FavoritesGUIUtility.cs
Normal file
|
|
@ -0,0 +1,112 @@
|
|||
using UnityEditor;
|
||||
using UnityEditorInternal;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Game.NavigationTool.Editor
|
||||
{
|
||||
internal static class FavoritesGUIUtility
|
||||
{
|
||||
private static readonly int ENTRY_HASH = "DrawEntry".GetHashCode();
|
||||
|
||||
public static Favorites.Entry manipulatingEntry;
|
||||
public static EManipulatingState manipulatingState;
|
||||
public static Favorites.Entry hoverEntry;
|
||||
|
||||
public static void DrawEntry(Rect rect, Favorites.Entry entry, Styles styles, bool ignoreIndentLevel = false)
|
||||
{
|
||||
int id = GUIUtility.GetControlID(ENTRY_HASH, FocusType.Passive, rect);
|
||||
bool on = manipulatingEntry == entry;
|
||||
bool intersects = rect.Contains(Event.current.mousePosition);
|
||||
|
||||
if (intersects)
|
||||
hoverEntry = entry;
|
||||
else if (hoverEntry == entry)
|
||||
hoverEntry = null;
|
||||
|
||||
switch (Event.current.type)
|
||||
{
|
||||
case EventType.MouseDown:
|
||||
if (intersects)
|
||||
{
|
||||
SetManipulating(entry, Event.current.button == 0 ? EManipulatingState.BeginClick : EManipulatingState.BeginContextClick);
|
||||
Event.current.Use();
|
||||
}
|
||||
break;
|
||||
case EventType.MouseUp:
|
||||
if (manipulatingEntry == entry)
|
||||
{
|
||||
if (manipulatingState == EManipulatingState.BeginClick)
|
||||
{
|
||||
if (intersects && Event.current.button == 0)
|
||||
SetManipulating(entry, EManipulatingState.PerformedClick);
|
||||
else
|
||||
SetManipulating(entry, EManipulatingState.EndClick);
|
||||
}
|
||||
else if (manipulatingState == EManipulatingState.BeginContextClick)
|
||||
{
|
||||
if (intersects && Event.current.button == 1)
|
||||
SetManipulating(entry, EManipulatingState.PerformedContextClick);
|
||||
else
|
||||
SetManipulating(entry, EManipulatingState.EndContextClick);
|
||||
}
|
||||
|
||||
Event.current.Use();
|
||||
}
|
||||
break;
|
||||
case EventType.MouseDrag:
|
||||
if (manipulatingEntry == entry)
|
||||
Event.current.Use();
|
||||
break;
|
||||
case EventType.KeyDown:
|
||||
break;
|
||||
case EventType.KeyUp:
|
||||
break;
|
||||
case EventType.Repaint:
|
||||
if (!ignoreIndentLevel)
|
||||
{
|
||||
rect.x += entry.indentLevel * 15.0f;
|
||||
rect.width -= entry.indentLevel * 15.0f;
|
||||
}
|
||||
|
||||
if (!entry.isAsset)
|
||||
entry.content.image = entry.expanded ? styles.foldoutOut : styles.foldoutIn;
|
||||
|
||||
styles.entry.Draw(rect, entry.content, id, on, intersects);
|
||||
break;
|
||||
case EventType.DragUpdated:
|
||||
break;
|
||||
case EventType.DragPerform:
|
||||
break;
|
||||
case EventType.DragExited:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public static Texture2D GetIcon(string path)
|
||||
{
|
||||
var texture = AssetDatabase.GetCachedIcon(path) as Texture2D;
|
||||
|
||||
if (texture == null)
|
||||
texture = InternalEditorUtility.GetIconForFile(path);
|
||||
|
||||
return texture;
|
||||
}
|
||||
|
||||
public static Texture2D GetFolderIcon()
|
||||
{
|
||||
return AssetDatabase.GetCachedIcon("Assets") as Texture2D;
|
||||
}
|
||||
|
||||
private static void SetManipulating(Favorites.Entry entry, EManipulatingState state)
|
||||
{
|
||||
manipulatingEntry = entry;
|
||||
manipulatingState = state;
|
||||
}
|
||||
|
||||
public static void ClearManipulating()
|
||||
{
|
||||
SetManipulating(null, EManipulatingState.None);
|
||||
hoverEntry = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
3
Editor/Favorites/Utilities/FavoritesGUIUtility.cs.meta
Normal file
3
Editor/Favorites/Utilities/FavoritesGUIUtility.cs.meta
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
fileFormatVersion: 2
|
||||
guid: a964d9decf5f4d619caccf91a2448661
|
||||
timeCreated: 1613211223
|
||||
26
Editor/Favorites/Utilities/FavoritesUtility.cs
Normal file
26
Editor/Favorites/Utilities/FavoritesUtility.cs
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
using UnityEditor;
|
||||
|
||||
namespace Game.NavigationTool.Editor
|
||||
{
|
||||
internal static class FavoritesUtility
|
||||
{
|
||||
private static Favorites FAVORITES;
|
||||
|
||||
static FavoritesUtility()
|
||||
{
|
||||
FAVORITES = null;
|
||||
}
|
||||
|
||||
public static Favorites GetFavorites()
|
||||
{
|
||||
return FAVORITES ?? (FAVORITES = new Favorites());
|
||||
}
|
||||
|
||||
[MenuItem("Tools/Utilities/Favorites/Delete")]
|
||||
public static void DeleteAll()
|
||||
{
|
||||
FAVORITES = null;
|
||||
EditorPrefs.DeleteKey(Favorites.PREF_ID);
|
||||
}
|
||||
}
|
||||
}
|
||||
3
Editor/Favorites/Utilities/FavoritesUtility.cs.meta
Normal file
3
Editor/Favorites/Utilities/FavoritesUtility.cs.meta
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 892d63101f6a41ecb789405dc0d7576a
|
||||
timeCreated: 1613210854
|
||||
3
Editor/Favorites/Window.meta
Normal file
3
Editor/Favorites/Window.meta
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
fileFormatVersion: 2
|
||||
guid: f365d80e29254040a54189ce0a22f29f
|
||||
timeCreated: 1613211006
|
||||
|
|
@ -0,0 +1,47 @@
|
|||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Game.NavigationTool.Editor
|
||||
{
|
||||
internal sealed class EditorFavoritesPopupWindowAddFolder : PopupWindowContent
|
||||
{
|
||||
private readonly Favorites.Entry toParent;
|
||||
private string inputStr = string.Empty;
|
||||
|
||||
public static void Show(Vector2 mousePosition, Favorites.Entry toParent)
|
||||
{
|
||||
var rect = new Rect(mousePosition.x - 200.0f, mousePosition.y, 0.0f, 0.0f);
|
||||
PopupWindow.Show(rect, new EditorFavoritesPopupWindowAddFolder(toParent));
|
||||
}
|
||||
|
||||
private EditorFavoritesPopupWindowAddFolder(Favorites.Entry toParent)
|
||||
{
|
||||
this.toParent = toParent;
|
||||
}
|
||||
|
||||
public override void OnGUI(Rect rect)
|
||||
{
|
||||
bool isReturn = Event.current.type == EventType.KeyDown && Event.current.keyCode == KeyCode.Return;
|
||||
bool isEscape = Event.current.type == EventType.KeyDown && Event.current.keyCode == KeyCode.Escape;
|
||||
|
||||
GUI.SetNextControlName("TextField");
|
||||
inputStr = GUI.TextField(rect, inputStr);
|
||||
GUI.FocusControl("TextField");
|
||||
|
||||
if (isReturn && !string.IsNullOrEmpty(inputStr))
|
||||
{
|
||||
Favorites favorites = FavoritesUtility.GetFavorites();
|
||||
favorites.AddFolder(inputStr, toParent);
|
||||
editorWindow.Close();
|
||||
}
|
||||
|
||||
if (isEscape)
|
||||
editorWindow.Close();
|
||||
}
|
||||
|
||||
public override Vector2 GetWindowSize()
|
||||
{
|
||||
return new Vector2(200.0f, EditorGUIUtility.singleLineHeight);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 645cd8d4c1164fc491789d22763f6167
|
||||
timeCreated: 1613252500
|
||||
|
|
@ -0,0 +1,93 @@
|
|||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Game.NavigationTool.Editor
|
||||
{
|
||||
internal sealed class EditorFavoritesPopupWindowContextMenu : PopupWindowContent
|
||||
{
|
||||
private readonly Favorites.Entry entry;
|
||||
private readonly Option[] options;
|
||||
private readonly Styles styles;
|
||||
|
||||
public static void Show(Vector2 mousePosition, Favorites.Entry entry)
|
||||
{
|
||||
var rect = new Rect(mousePosition.x, mousePosition.y, 0.0f, 0.0f);
|
||||
PopupWindow.Show(rect, new EditorFavoritesPopupWindowContextMenu(entry));
|
||||
}
|
||||
|
||||
private EditorFavoritesPopupWindowContextMenu(Favorites.Entry entry)
|
||||
{
|
||||
this.entry = entry;
|
||||
styles = new Styles();
|
||||
|
||||
options = new[]
|
||||
{
|
||||
new Option("Add Folder", OnAddFolder, () => entry == null || !entry.isAsset),
|
||||
new Option("Rename Folder", OnRenameFolder, () => entry != null && !entry.isAsset),
|
||||
new Option("Remove", OnRemove, () => entry != null)
|
||||
};
|
||||
}
|
||||
|
||||
public override void OnGUI(Rect rect)
|
||||
{
|
||||
styles.Initialize(GUI.skin);
|
||||
var entryRect = new Rect(0.0f, 0.0f, rect.width, EditorGUIUtility.singleLineHeight);
|
||||
|
||||
for (var i = 0; i < options.Length; i++)
|
||||
{
|
||||
GUI.enabled = options[i].criteria.Invoke();
|
||||
|
||||
if (GUI.Button(entryRect, options[i].name, styles.contextOption))
|
||||
options[i].action.Invoke();
|
||||
|
||||
entryRect.y += EditorGUIUtility.singleLineHeight;
|
||||
}
|
||||
|
||||
GUI.enabled = true;
|
||||
}
|
||||
|
||||
public override Vector2 GetWindowSize()
|
||||
{
|
||||
return new Vector2(200.0f, options.Length * EditorGUIUtility.singleLineHeight + 6.0f);
|
||||
}
|
||||
|
||||
private void OnAddFolder()
|
||||
{
|
||||
editorWindow.Close();
|
||||
EditorFavoritesPopupWindowAddFolder.Show(new Vector2(0.0f, 0.0f), entry);
|
||||
}
|
||||
|
||||
private void OnRenameFolder()
|
||||
{
|
||||
editorWindow.Close();
|
||||
EditorFavoritesPopupWindowRenameFolder.Show(new Vector2(0.0f, 0.0f), entry);
|
||||
}
|
||||
|
||||
private void OnRemove()
|
||||
{
|
||||
Favorites favorites = FavoritesUtility.GetFavorites();
|
||||
favorites.Remove(entry);
|
||||
editorWindow.Close();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Class: Option in drop down menu
|
||||
/// </summary>
|
||||
private sealed class Option
|
||||
{
|
||||
public delegate void DoAction();
|
||||
public delegate bool DoActionCriteria();
|
||||
|
||||
public readonly string name;
|
||||
public readonly DoAction action;
|
||||
public readonly DoActionCriteria criteria;
|
||||
|
||||
public Option(string name, DoAction action, DoActionCriteria criteria = null)
|
||||
{
|
||||
this.name = name;
|
||||
this.action = action;
|
||||
this.criteria = criteria;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 476b6add28b14bde9fe51db4ba9497ff
|
||||
timeCreated: 1613218094
|
||||
|
|
@ -0,0 +1,53 @@
|
|||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Game.NavigationTool.Editor
|
||||
{
|
||||
internal sealed class EditorFavoritesPopupWindowRenameFolder : PopupWindowContent
|
||||
{
|
||||
private readonly Favorites.Entry entry;
|
||||
private string inputStr;
|
||||
|
||||
public static void Show(Vector2 mousePosition, Favorites.Entry entry)
|
||||
{
|
||||
var rect = new Rect(mousePosition.x - 200.0f, mousePosition.y, 0.0f, 0.0f);
|
||||
PopupWindow.Show(rect, new EditorFavoritesPopupWindowRenameFolder(entry));
|
||||
}
|
||||
|
||||
private EditorFavoritesPopupWindowRenameFolder(Favorites.Entry entry)
|
||||
{
|
||||
this.entry = entry;
|
||||
inputStr = entry.name;
|
||||
}
|
||||
|
||||
public override void OnGUI(Rect rect)
|
||||
{
|
||||
bool isReturn = Event.current.type == EventType.KeyDown && Event.current.keyCode == KeyCode.Return;
|
||||
bool isEscape = Event.current.type == EventType.KeyDown && Event.current.keyCode == KeyCode.Escape;
|
||||
|
||||
GUI.SetNextControlName("TextField");
|
||||
inputStr = GUI.TextField(rect, inputStr);
|
||||
GUI.FocusControl("TextField");
|
||||
|
||||
if (isReturn && !string.IsNullOrEmpty(inputStr))
|
||||
{
|
||||
entry.name = inputStr;
|
||||
entry.lowerName = inputStr.ToLower();
|
||||
entry.content.text = inputStr;
|
||||
|
||||
Favorites favorites = FavoritesUtility.GetFavorites();
|
||||
favorites.Save();
|
||||
|
||||
editorWindow.Close();
|
||||
}
|
||||
|
||||
if (isEscape)
|
||||
editorWindow.Close();
|
||||
}
|
||||
|
||||
public override Vector2 GetWindowSize()
|
||||
{
|
||||
return new Vector2(200.0f, EditorGUIUtility.singleLineHeight);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 0c7a514e1c6b4846857dcc980b42485d
|
||||
timeCreated: 1613291517
|
||||
128
Editor/Favorites/Window/EditorFavoritesWindow.cs
Normal file
128
Editor/Favorites/Window/EditorFavoritesWindow.cs
Normal file
|
|
@ -0,0 +1,128 @@
|
|||
using System;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Game.NavigationTool.Editor
|
||||
{
|
||||
internal sealed class EditorFavoritesWindow : EditorWindow
|
||||
{
|
||||
[NonSerialized]
|
||||
private Styles styles;
|
||||
[SerializeField]
|
||||
public EditorFavoritesViewTools viewTools;
|
||||
[SerializeField]
|
||||
private EditorFavoritesViewTreeList viewTreeList;
|
||||
[SerializeField]
|
||||
private EditorFavoritesViewSearchList viewSearchList;
|
||||
|
||||
[MenuItem("Tools/Windows/Favorites")]
|
||||
public static void Open()
|
||||
{
|
||||
var window = GetWindow<EditorFavoritesWindow>();
|
||||
window.titleContent = new GUIContent("Favorites");
|
||||
window.Show();
|
||||
}
|
||||
|
||||
private void OnEnable()
|
||||
{
|
||||
if (styles == null)
|
||||
styles = new Styles();
|
||||
if (viewTools == null)
|
||||
viewTools = new EditorFavoritesViewTools();
|
||||
if (viewTreeList == null)
|
||||
viewTreeList = new EditorFavoritesViewTreeList();
|
||||
if (viewSearchList == null)
|
||||
viewSearchList = new EditorFavoritesViewSearchList();
|
||||
}
|
||||
|
||||
private void OnGUI()
|
||||
{
|
||||
if (Event.current.type == EventType.Layout)
|
||||
return;
|
||||
|
||||
styles.Initialize(GUI.skin);
|
||||
var rectTools = new Rect(0.0f, 0.0f, position.width, EditorGUIUtility.singleLineHeight);
|
||||
var rectList = new Rect(0.0f, rectTools.yMax, position.width, position.height - rectTools.height);
|
||||
|
||||
viewTools.Initialize();
|
||||
viewTools.Draw(this, rectTools, styles);
|
||||
|
||||
if (viewTools.IsSearching())
|
||||
{
|
||||
viewSearchList.Initialize();
|
||||
viewSearchList.Draw(this, rectList, styles);
|
||||
}
|
||||
else
|
||||
{
|
||||
viewTreeList.Initialize();
|
||||
viewTreeList.Draw(this, rectList, styles);
|
||||
}
|
||||
|
||||
HandleDragAndDropEvents();
|
||||
HandleManipulatedEntry();
|
||||
}
|
||||
|
||||
private void HandleDragAndDropEvents()
|
||||
{
|
||||
Favorites favorites = FavoritesUtility.GetFavorites();
|
||||
|
||||
if (Event.current.type == EventType.DragUpdated)
|
||||
{
|
||||
DragAndDrop.visualMode = DragAndDropVisualMode.Generic;
|
||||
}
|
||||
else if (Event.current.type == EventType.DragPerform)
|
||||
{
|
||||
Favorites.Entry toParent = null;
|
||||
|
||||
if (!viewTools.IsSearching())
|
||||
toParent = FavoritesGUIUtility.hoverEntry;
|
||||
|
||||
favorites.AddRangeByPath(DragAndDrop.paths, toParent);
|
||||
}
|
||||
}
|
||||
|
||||
private static void HandleManipulatedEntry()
|
||||
{
|
||||
Favorites favorites = FavoritesUtility.GetFavorites();
|
||||
Favorites.Entry entry = FavoritesGUIUtility.manipulatingEntry;
|
||||
|
||||
switch (FavoritesGUIUtility.manipulatingState)
|
||||
{
|
||||
case EManipulatingState.BeginClick:
|
||||
break;
|
||||
case EManipulatingState.PerformedClick:
|
||||
if (entry.isAsset)
|
||||
{
|
||||
Selection.activeObject = favorites.GetObject(entry);
|
||||
EditorGUIUtility.PingObject(Selection.activeObject);
|
||||
}
|
||||
else
|
||||
{
|
||||
entry.expanded = !entry.expanded;
|
||||
favorites.Save();
|
||||
}
|
||||
|
||||
FavoritesGUIUtility.ClearManipulating();
|
||||
break;
|
||||
case EManipulatingState.EndClick:
|
||||
FavoritesGUIUtility.ClearManipulating();
|
||||
break;
|
||||
case EManipulatingState.BeginDrag:
|
||||
break;
|
||||
case EManipulatingState.PerformedDrag:
|
||||
FavoritesGUIUtility.ClearManipulating();
|
||||
break;
|
||||
case EManipulatingState.EndDrag:
|
||||
FavoritesGUIUtility.ClearManipulating();
|
||||
break;
|
||||
case EManipulatingState.PerformedContextClick:
|
||||
FavoritesGUIUtility.ClearManipulating();
|
||||
EditorFavoritesPopupWindowContextMenu.Show(Event.current.mousePosition, entry);
|
||||
break;
|
||||
case EManipulatingState.EndContextClick:
|
||||
FavoritesGUIUtility.ClearManipulating();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
11
Editor/Favorites/Window/EditorFavoritesWindow.cs.meta
Normal file
11
Editor/Favorites/Window/EditorFavoritesWindow.cs.meta
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: ba47d77c4aeba1543bc1f55d25236caa
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
3
Editor/Favorites/Window/Styles.meta
Normal file
3
Editor/Favorites/Window/Styles.meta
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 15b0d6cd0e064f94bf81f3738a36ff85
|
||||
timeCreated: 1613211891
|
||||
47
Editor/Favorites/Window/Styles/Styles.cs
Normal file
47
Editor/Favorites/Window/Styles/Styles.cs
Normal file
|
|
@ -0,0 +1,47 @@
|
|||
using UnityEngine;
|
||||
|
||||
namespace Game.NavigationTool.Editor
|
||||
{
|
||||
internal sealed class Styles
|
||||
{
|
||||
public GUIStyle toolbox;
|
||||
public GUIStyle buttonAddFolder;
|
||||
|
||||
public GUIStyle entry;
|
||||
public Texture2D foldoutIn;
|
||||
public Texture2D foldoutOut;
|
||||
|
||||
public GUIStyle contextOption;
|
||||
|
||||
private GUISkin skin;
|
||||
|
||||
public void Initialize(GUISkin skin)
|
||||
{
|
||||
if (this.skin == skin)
|
||||
return;
|
||||
|
||||
toolbox = new GUIStyle(skin.box);
|
||||
|
||||
buttonAddFolder = new GUIStyle(skin.button);
|
||||
buttonAddFolder.padding = new RectOffset(4, 0, 0, 4);
|
||||
|
||||
entry = new GUIStyle(skin.label);
|
||||
entry.hover.textColor = entry.onHover.textColor = Color.white;
|
||||
entry.active.textColor = entry.onActive.textColor = Color.yellow;
|
||||
|
||||
GUIStyle style = skin.FindStyle("Foldout");
|
||||
|
||||
if (style != null)
|
||||
{
|
||||
foldoutIn = style.normal.scaledBackgrounds[0];
|
||||
foldoutOut = style.onNormal.scaledBackgrounds[0];
|
||||
}
|
||||
|
||||
contextOption = new GUIStyle(skin.label);
|
||||
contextOption.hover.textColor = contextOption.onHover.textColor = Color.white;
|
||||
contextOption.hover.scaledBackgrounds = contextOption.onHover.scaledBackgrounds = skin.box.normal.scaledBackgrounds;
|
||||
contextOption.active.textColor = contextOption.onActive.textColor = Color.yellow;
|
||||
contextOption.active.scaledBackgrounds = contextOption.onActive.scaledBackgrounds = skin.box.normal.scaledBackgrounds;
|
||||
}
|
||||
}
|
||||
}
|
||||
3
Editor/Favorites/Window/Styles/Styles.cs.meta
Normal file
3
Editor/Favorites/Window/Styles/Styles.cs.meta
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 6d7dcc40bb3d471d91439071d6157a8f
|
||||
timeCreated: 1613211898
|
||||
3
Editor/Favorites/Window/Views.meta
Normal file
3
Editor/Favorites/Window/Views.meta
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 8d38858044174890af932bea10cfbb9d
|
||||
timeCreated: 1613211112
|
||||
10
Editor/Favorites/Window/Views/AbstractEditorFavoritesView.cs
Normal file
10
Editor/Favorites/Window/Views/AbstractEditorFavoritesView.cs
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
using UnityEngine;
|
||||
|
||||
namespace Game.NavigationTool.Editor
|
||||
{
|
||||
internal abstract class AbstractEditorFavoritesView
|
||||
{
|
||||
public abstract void Initialize();
|
||||
public abstract void Draw(EditorFavoritesWindow window, Rect rect, Styles styles);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 1d16482b17fb430fa905dea21ec2fdab
|
||||
timeCreated: 1613211130
|
||||
|
|
@ -0,0 +1,51 @@
|
|||
using System;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Game.NavigationTool.Editor
|
||||
{
|
||||
[Serializable]
|
||||
internal sealed class EditorFavoritesViewSearchList : AbstractEditorFavoritesView
|
||||
{
|
||||
[SerializeField]
|
||||
private Vector2 scrollPosition;
|
||||
|
||||
[NonSerialized]
|
||||
private Favorites favorites;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
favorites = FavoritesUtility.GetFavorites();
|
||||
}
|
||||
|
||||
public override void Draw(EditorFavoritesWindow window, Rect rect, Styles styles)
|
||||
{
|
||||
float entryHeight = EditorGUIUtility.singleLineHeight;
|
||||
float height = entryHeight * favorites.entries.Count;
|
||||
string lowerSearchStr = window.viewTools.searchStr.ToLower();
|
||||
|
||||
GUI.BeginGroup(rect);
|
||||
{
|
||||
var position = new Rect(0.0f, 0.0f, rect.width, rect.height);
|
||||
var viewRect = new Rect(0.0f, 0.0f, position.height > height ? position.width : position.width - 14.0f, height);
|
||||
var entryRect = new Rect(0.0f, 0.0f, viewRect.width, entryHeight);
|
||||
|
||||
scrollPosition = GUI.BeginScrollView(position, scrollPosition, viewRect);
|
||||
{
|
||||
for (var i = 0; i < favorites.entries.Count; i++)
|
||||
{
|
||||
Favorites.Entry e = favorites.entries[i];
|
||||
|
||||
if (!e.isAsset || !e.lowerName.Contains(lowerSearchStr))
|
||||
continue;
|
||||
|
||||
FavoritesGUIUtility.DrawEntry(entryRect, favorites.entries[i], styles, true);
|
||||
entryRect.y += entryHeight;
|
||||
}
|
||||
}
|
||||
GUI.EndScrollView();
|
||||
}
|
||||
GUI.EndGroup();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 65d3b26a5050438c8d995b3c383c474f
|
||||
timeCreated: 1613211189
|
||||
38
Editor/Favorites/Window/Views/EditorFavoritesViewTools.cs
Normal file
38
Editor/Favorites/Window/Views/EditorFavoritesViewTools.cs
Normal file
|
|
@ -0,0 +1,38 @@
|
|||
using System;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Game.NavigationTool.Editor
|
||||
{
|
||||
[Serializable]
|
||||
internal sealed class EditorFavoritesViewTools : AbstractEditorFavoritesView
|
||||
{
|
||||
public string searchStr;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
}
|
||||
|
||||
public override void Draw(EditorFavoritesWindow window, Rect rect, Styles styles)
|
||||
{
|
||||
float dim = rect.height;
|
||||
|
||||
GUI.BeginGroup(rect, styles.toolbox);
|
||||
{
|
||||
var r0 = new Rect(0.0f, 0.0f, rect.width - dim, dim);
|
||||
var r1 = new Rect(rect.width - r0.height, 0.0f, dim, dim);
|
||||
|
||||
searchStr = EditorGUI.TextField(r0, searchStr);
|
||||
|
||||
if (GUI.Button(r1, "+", styles.buttonAddFolder))
|
||||
EditorFavoritesPopupWindowAddFolder.Show(new Vector2(r1.xMax, dim), null);
|
||||
}
|
||||
GUI.EndGroup();
|
||||
}
|
||||
|
||||
public bool IsSearching()
|
||||
{
|
||||
return !string.IsNullOrEmpty(searchStr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
fileFormatVersion: 2
|
||||
guid: b597a5bc0de34d96accec02ef9cb80ed
|
||||
timeCreated: 1613211779
|
||||
61
Editor/Favorites/Window/Views/EditorFavoritesViewTreeList.cs
Normal file
61
Editor/Favorites/Window/Views/EditorFavoritesViewTreeList.cs
Normal file
|
|
@ -0,0 +1,61 @@
|
|||
using System;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Game.NavigationTool.Editor
|
||||
{
|
||||
[Serializable]
|
||||
internal sealed class EditorFavoritesViewTreeList : AbstractEditorFavoritesView
|
||||
{
|
||||
[SerializeField]
|
||||
private Vector2 scrollPosition;
|
||||
|
||||
[NonSerialized]
|
||||
private Favorites favorites;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
favorites = FavoritesUtility.GetFavorites();
|
||||
}
|
||||
|
||||
public override void Draw(EditorFavoritesWindow window, Rect rect, Styles styles)
|
||||
{
|
||||
float entryHeight = EditorGUIUtility.singleLineHeight;
|
||||
float height = entryHeight * favorites.entries.Count;
|
||||
|
||||
GUI.BeginGroup(rect);
|
||||
{
|
||||
var position = new Rect(0.0f, 0.0f, rect.width, rect.height);
|
||||
var viewRect = new Rect(0.0f, 0.0f, position.height > height ? position.width : position.width - 14.0f, height);
|
||||
var entryRect = new Rect(0.0f, 0.0f, viewRect.width, entryHeight);
|
||||
|
||||
scrollPosition = GUI.BeginScrollView(position, scrollPosition, viewRect);
|
||||
{
|
||||
for (var i = 0; i < favorites.entries.Count; i++)
|
||||
{
|
||||
Favorites.Entry e = favorites.entries[i];
|
||||
|
||||
if (e.indentLevel == 0)
|
||||
DrawEntry(e, ref entryRect, entryHeight, styles);
|
||||
}
|
||||
}
|
||||
GUI.EndScrollView();
|
||||
}
|
||||
GUI.EndGroup();
|
||||
}
|
||||
|
||||
private void DrawEntry(Favorites.Entry entry, ref Rect entryRect, float entryHeight, Styles styles)
|
||||
{
|
||||
FavoritesGUIUtility.DrawEntry(entryRect, entry, styles);
|
||||
entryRect.y += entryHeight;
|
||||
|
||||
if (entry.isAsset || !entry.expanded)
|
||||
return;
|
||||
|
||||
for (var i = 0; i < entry.children.Count; i++)
|
||||
{
|
||||
DrawEntry(entry.children[i].entry, ref entryRect, entryHeight, styles);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: eb65c37d7ed60d14daa08e98eb9ee334
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
15
Editor/Game.NavigationTool.Editor.asmdef
Normal file
15
Editor/Game.NavigationTool.Editor.asmdef
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
{
|
||||
"name": "Game.NavigationTool.Editor",
|
||||
"references": [],
|
||||
"includePlatforms": [
|
||||
"Editor"
|
||||
],
|
||||
"excludePlatforms": [],
|
||||
"allowUnsafeCode": false,
|
||||
"overrideReferences": false,
|
||||
"precompiledReferences": [],
|
||||
"autoReferenced": true,
|
||||
"defineConstraints": [],
|
||||
"versionDefines": [],
|
||||
"noEngineReferences": false
|
||||
}
|
||||
7
Editor/Game.NavigationTool.Editor.asmdef.meta
Normal file
7
Editor/Game.NavigationTool.Editor.asmdef.meta
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 8339b3ce77cb32f489776d81010ad36c
|
||||
AssemblyDefinitionImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
18
package.json
Normal file
18
package.json
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
{
|
||||
"name": "com.module.navigationtool",
|
||||
"version": "0.1.0",
|
||||
"displayName": "Module.NavigationTool",
|
||||
"description": "Support for navigation tools",
|
||||
"unity": "2019.2",
|
||||
"unityRelease": "17f1",
|
||||
"dependencies": {
|
||||
},
|
||||
"keywords": [
|
||||
"navigation"
|
||||
],
|
||||
"author": {
|
||||
"name": "Anders Ejlersen",
|
||||
"email": "anders@ejlersen.info",
|
||||
"url": "https://www.ejlersen.info"
|
||||
}
|
||||
}
|
||||
7
package.json.meta
Normal file
7
package.json.meta
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 6896738deb10ff34e8931d5e91ac5f8a
|
||||
PackageManifestImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
Loading…
Reference in a new issue