module-navigation-tool/Editor/Favorites/Utilities/Favorites.cs

343 lines
9.5 KiB
C#

using System;
using System.Collections.Generic;
using System.IO;
using UnityEditor;
using UnityEngine;
using Object = UnityEngine.Object;
namespace Game.NavigationTool.Editor.Favorite
{
[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);
}
}
}
for (var i = 0; i < entries.Count; i++)
{
Entry e = entries[i];
if (e.indentLevel != 0 && e.parent == null)
e.indentLevel = 0;
}
}
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 && toParent.isAsset)
toParent = toParent.parent;
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 (int i = e.children.Count - 1; i >= 0; 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);
}
private void Sort()
{
entries.Sort((e0, e1) =>
{
int compare = e0.isAsset.CompareTo(e1.isAsset);
if (compare == 0)
compare = string.Compare(e0.lowerName, e1.lowerName, StringComparison.Ordinal);
return compare;
});
}
public void Save()
{
Sort();
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 = AssetDatabase.LoadMainAssetAtPath(path) != null;
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));
children.Sort((c0, c1) =>
{
int compare = c0.entry.isAsset.CompareTo(c1.entry.isAsset);
if (compare == 0)
compare = string.Compare(c0.entry.lowerName, c1.entry.lowerName, StringComparison.Ordinal);
return compare;
});
}
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;
}
}
}
}
}