0.1.0: Added favorites window

This commit is contained in:
Anders Ejlersen 2021-02-14 11:14:16 +01:00
parent 80499f0a7e
commit dea60c6e4a
37 changed files with 1129 additions and 0 deletions

View 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;
}
}
}
}
}

View file

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 7ec45414bdf74e81800f8ffaf95f26ec
timeCreated: 1613162445

View 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;
}
}
}

View file

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: a964d9decf5f4d619caccf91a2448661
timeCreated: 1613211223

View 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);
}
}
}

View file

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 892d63101f6a41ecb789405dc0d7576a
timeCreated: 1613210854