309 lines
8.4 KiB
C#
309 lines
8.4 KiB
C#
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;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
} |