0.2.0: Added drag and drop between entries in list and fixed some bugs

This commit is contained in:
Anders Ejlersen 2021-02-14 13:01:59 +01:00
parent dea60c6e4a
commit 1e1736f94a
8 changed files with 150 additions and 38 deletions

View file

@ -59,6 +59,14 @@ namespace Game.NavigationTool.Editor
} }
} }
} }
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) public void Add(string guid, Entry toParent = null)
@ -82,6 +90,9 @@ namespace Game.NavigationTool.Editor
entries.Add(e); entries.Add(e);
if (toParent != null && toParent.isAsset)
toParent = toParent.parent;
if (toParent != null) if (toParent != null)
{ {
e.parent = toParent; e.parent = toParent;
@ -137,7 +148,7 @@ namespace Game.NavigationTool.Editor
if (!e.isAsset) if (!e.isAsset)
{ {
for (var i = 0; i < e.children.Count; i++) for (int i = e.children.Count - 1; i >= 0; i--)
{ {
InternalRemove(e.children[i].entry); InternalRemove(e.children[i].entry);
} }
@ -191,9 +202,23 @@ namespace Game.NavigationTool.Editor
string path = AssetDatabase.GUIDToAssetPath(entry.assetGuid); string path = AssetDatabase.GUIDToAssetPath(entry.assetGuid);
return AssetDatabase.LoadMainAssetAtPath(path); 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() public void Save()
{ {
Sort();
string json = EditorJsonUtility.ToJson(this, false); string json = EditorJsonUtility.ToJson(this, false);
EditorPrefs.SetString(PREF_ID, json); EditorPrefs.SetString(PREF_ID, json);
} }
@ -254,7 +279,7 @@ namespace Game.NavigationTool.Editor
string path = AssetDatabase.GUIDToAssetPath(assetGuid); string path = AssetDatabase.GUIDToAssetPath(assetGuid);
name = Path.GetFileNameWithoutExtension(path); name = Path.GetFileNameWithoutExtension(path);
lowerName = name.ToLower(); lowerName = name.ToLower();
valid = !string.IsNullOrEmpty(path); valid = AssetDatabase.LoadMainAssetAtPath(path) != null;
content = new GUIContent(name, FavoritesGUIUtility.GetIcon(path), path); content = new GUIContent(name, FavoritesGUIUtility.GetIcon(path), path);
} }
else else
@ -267,6 +292,15 @@ namespace Game.NavigationTool.Editor
public void AddChild(Entry entry) public void AddChild(Entry entry)
{ {
children.Add(new Child(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) public void RemoveChild(Entry entry)

View file

@ -10,8 +10,11 @@ namespace Game.NavigationTool.Editor
public static Favorites.Entry manipulatingEntry; public static Favorites.Entry manipulatingEntry;
public static EManipulatingState manipulatingState; public static EManipulatingState manipulatingState;
public static Favorites.Entry hoverEntry; public static Vector2 manipulatingMouseOffset;
public static Rect manipulatingRect;
public static Favorites.Entry hoverEntry;
public static void DrawEntry(Rect rect, Favorites.Entry entry, Styles styles, bool ignoreIndentLevel = false) public static void DrawEntry(Rect rect, Favorites.Entry entry, Styles styles, bool ignoreIndentLevel = false)
{ {
int id = GUIUtility.GetControlID(ENTRY_HASH, FocusType.Passive, rect); int id = GUIUtility.GetControlID(ENTRY_HASH, FocusType.Passive, rect);
@ -20,15 +23,14 @@ namespace Game.NavigationTool.Editor
if (intersects) if (intersects)
hoverEntry = entry; hoverEntry = entry;
else if (hoverEntry == entry)
hoverEntry = null;
switch (Event.current.type) switch (Event.current.type)
{ {
case EventType.MouseDown: case EventType.MouseDown:
if (intersects) if (intersects)
{ {
SetManipulating(entry, Event.current.button == 0 ? EManipulatingState.BeginClick : EManipulatingState.BeginContextClick); SetManipulating(rect, entry, Event.current.button == 0 ? EManipulatingState.BeginClick : EManipulatingState.BeginContextClick);
manipulatingMouseOffset = Event.current.mousePosition - rect.position;
Event.current.Use(); Event.current.Use();
} }
break; break;
@ -38,16 +40,23 @@ namespace Game.NavigationTool.Editor
if (manipulatingState == EManipulatingState.BeginClick) if (manipulatingState == EManipulatingState.BeginClick)
{ {
if (intersects && Event.current.button == 0) if (intersects && Event.current.button == 0)
SetManipulating(entry, EManipulatingState.PerformedClick); SetManipulating(rect, entry, EManipulatingState.PerformedClick);
else else
SetManipulating(entry, EManipulatingState.EndClick); SetManipulating(rect, entry, EManipulatingState.EndClick);
} }
else if (manipulatingState == EManipulatingState.BeginContextClick) else if (manipulatingState == EManipulatingState.BeginContextClick)
{ {
if (intersects && Event.current.button == 1) if (intersects && Event.current.button == 1)
SetManipulating(entry, EManipulatingState.PerformedContextClick); SetManipulating(rect, entry, EManipulatingState.PerformedContextClick);
else else
SetManipulating(entry, EManipulatingState.EndContextClick); SetManipulating(rect, entry, EManipulatingState.EndContextClick);
}
else if (manipulatingState == EManipulatingState.BeginDrag)
{
if (intersects)
SetManipulating(rect, entry, EManipulatingState.EndDrag);
else
SetManipulating(rect, entry, EManipulatingState.PerformedDrag);
} }
Event.current.Use(); Event.current.Use();
@ -55,11 +64,10 @@ namespace Game.NavigationTool.Editor
break; break;
case EventType.MouseDrag: case EventType.MouseDrag:
if (manipulatingEntry == entry) if (manipulatingEntry == entry)
{
SetManipulating(rect, entry, EManipulatingState.BeginDrag);
Event.current.Use(); Event.current.Use();
break; }
case EventType.KeyDown:
break;
case EventType.KeyUp:
break; break;
case EventType.Repaint: case EventType.Repaint:
if (!ignoreIndentLevel) if (!ignoreIndentLevel)
@ -67,20 +75,36 @@ namespace Game.NavigationTool.Editor
rect.x += entry.indentLevel * 15.0f; rect.x += entry.indentLevel * 15.0f;
rect.width -= entry.indentLevel * 15.0f; rect.width -= entry.indentLevel * 15.0f;
} }
if (!entry.isAsset) if (!entry.isAsset)
entry.content.image = entry.expanded ? styles.foldoutOut : styles.foldoutIn; entry.content.image = entry.expanded ? styles.foldoutOut : styles.foldoutIn;
styles.entry.Draw(rect, entry.content, id, on, intersects); GUIStyle style = entry.valid ? styles.entry : styles.invalidEntry;
break; style.Draw(rect, entry.content, id, on, intersects);
case EventType.DragUpdated:
break;
case EventType.DragPerform:
break;
case EventType.DragExited:
break; break;
} }
} }
public static void DrawShadowEntry(Rect rect, Favorites.Entry entry, Styles styles)
{
if (Event.current.type != EventType.Repaint)
return;
if (!entry.isAsset)
entry.content.image = entry.expanded ? styles.foldoutOut : styles.foldoutIn;
int id = GUIUtility.GetControlID(ENTRY_HASH, FocusType.Passive, rect);
GUIStyle style = entry.valid ? styles.entry : styles.invalidEntry;
GUI.enabled = false;
style.Draw(rect, entry.content, id, false, false);
GUI.enabled = true;
}
public static void EndDraw()
{
hoverEntry = null;
}
public static Texture2D GetIcon(string path) public static Texture2D GetIcon(string path)
{ {
@ -97,15 +121,16 @@ namespace Game.NavigationTool.Editor
return AssetDatabase.GetCachedIcon("Assets") as Texture2D; return AssetDatabase.GetCachedIcon("Assets") as Texture2D;
} }
private static void SetManipulating(Favorites.Entry entry, EManipulatingState state) private static void SetManipulating(Rect rect, Favorites.Entry entry, EManipulatingState state)
{ {
manipulatingRect = rect;
manipulatingEntry = entry; manipulatingEntry = entry;
manipulatingState = state; manipulatingState = state;
} }
public static void ClearManipulating() public static void ClearManipulating()
{ {
SetManipulating(null, EManipulatingState.None); SetManipulating(Rect.zero, null, EManipulatingState.None);
hoverEntry = null; hoverEntry = null;
} }
} }

View file

@ -0,0 +1,17 @@
using UnityEditor;
namespace Game.NavigationTool.Editor
{
internal sealed class FavoritesPostProcess : AssetPostprocessor
{
private static void OnPostprocessAllAssets(string[] importedAssets, string[] deletedAssets, string[] movedAssets, string[] movedFromAssetPaths)
{
bool isDirty = deletedAssets.Length != 0 ||
movedAssets.Length != 0 ||
movedFromAssetPaths.Length != 0;
if (isDirty && FavoritesUtility.IsLoaded())
FavoritesUtility.RefreshAll();
}
}
}

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 522178e7e28db4e4b8bad3b9ae7d1ff4
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -1,4 +1,5 @@
using UnityEditor; using System.Collections.Generic;
using UnityEditor;
namespace Game.NavigationTool.Editor namespace Game.NavigationTool.Editor
{ {
@ -16,6 +17,24 @@ namespace Game.NavigationTool.Editor
return FAVORITES ?? (FAVORITES = new Favorites()); return FAVORITES ?? (FAVORITES = new Favorites());
} }
public static bool IsLoaded()
{
return FAVORITES != null;
}
public static void RefreshAll()
{
if (FAVORITES == null)
return;
List<Favorites.Entry> entries = FAVORITES.entries;
for (var i = 0; i < entries.Count; i++)
{
entries[i].Refresh();
}
}
[MenuItem("Tools/Utilities/Favorites/Delete")] [MenuItem("Tools/Utilities/Favorites/Delete")]
public static void DeleteAll() public static void DeleteAll()
{ {

View file

@ -59,9 +59,10 @@ namespace Game.NavigationTool.Editor
} }
HandleDragAndDropEvents(); HandleDragAndDropEvents();
HandleManipulatedEntry(); HandleManipulatedEntry(styles);
FavoritesGUIUtility.EndDraw();
} }
private void HandleDragAndDropEvents() private void HandleDragAndDropEvents()
{ {
Favorites favorites = FavoritesUtility.GetFavorites(); Favorites favorites = FavoritesUtility.GetFavorites();
@ -76,20 +77,18 @@ namespace Game.NavigationTool.Editor
if (!viewTools.IsSearching()) if (!viewTools.IsSearching())
toParent = FavoritesGUIUtility.hoverEntry; toParent = FavoritesGUIUtility.hoverEntry;
favorites.AddRangeByPath(DragAndDrop.paths, toParent); favorites.AddRangeByPath(DragAndDrop.paths, toParent);
} }
} }
private static void HandleManipulatedEntry() private static void HandleManipulatedEntry(Styles styles)
{ {
Favorites favorites = FavoritesUtility.GetFavorites(); Favorites favorites = FavoritesUtility.GetFavorites();
Favorites.Entry entry = FavoritesGUIUtility.manipulatingEntry; Favorites.Entry entry = FavoritesGUIUtility.manipulatingEntry;
switch (FavoritesGUIUtility.manipulatingState) switch (FavoritesGUIUtility.manipulatingState)
{ {
case EManipulatingState.BeginClick:
break;
case EManipulatingState.PerformedClick: case EManipulatingState.PerformedClick:
if (entry.isAsset) if (entry.isAsset)
{ {
@ -102,23 +101,23 @@ namespace Game.NavigationTool.Editor
favorites.Save(); favorites.Save();
} }
FavoritesGUIUtility.ClearManipulating();
break;
case EManipulatingState.EndClick:
FavoritesGUIUtility.ClearManipulating(); FavoritesGUIUtility.ClearManipulating();
break; break;
case EManipulatingState.BeginDrag: case EManipulatingState.BeginDrag:
Rect rect = FavoritesGUIUtility.manipulatingRect;
rect.position = Event.current.mousePosition - FavoritesGUIUtility.manipulatingMouseOffset;
FavoritesGUIUtility.DrawShadowEntry(rect, entry, styles);
break; break;
case EManipulatingState.PerformedDrag: case EManipulatingState.PerformedDrag:
FavoritesGUIUtility.ClearManipulating(); favorites.Move(entry, FavoritesGUIUtility.hoverEntry);
break;
case EManipulatingState.EndDrag:
FavoritesGUIUtility.ClearManipulating(); FavoritesGUIUtility.ClearManipulating();
break; break;
case EManipulatingState.PerformedContextClick: case EManipulatingState.PerformedContextClick:
FavoritesGUIUtility.ClearManipulating(); FavoritesGUIUtility.ClearManipulating();
EditorFavoritesPopupWindowContextMenu.Show(Event.current.mousePosition, entry); EditorFavoritesPopupWindowContextMenu.Show(Event.current.mousePosition, entry);
break; break;
case EManipulatingState.EndClick:
case EManipulatingState.EndDrag:
case EManipulatingState.EndContextClick: case EManipulatingState.EndContextClick:
FavoritesGUIUtility.ClearManipulating(); FavoritesGUIUtility.ClearManipulating();
break; break;

View file

@ -8,6 +8,7 @@ namespace Game.NavigationTool.Editor
public GUIStyle buttonAddFolder; public GUIStyle buttonAddFolder;
public GUIStyle entry; public GUIStyle entry;
public GUIStyle invalidEntry;
public Texture2D foldoutIn; public Texture2D foldoutIn;
public Texture2D foldoutOut; public Texture2D foldoutOut;
@ -20,6 +21,7 @@ namespace Game.NavigationTool.Editor
if (this.skin == skin) if (this.skin == skin)
return; return;
this.skin = skin;
toolbox = new GUIStyle(skin.box); toolbox = new GUIStyle(skin.box);
buttonAddFolder = new GUIStyle(skin.button); buttonAddFolder = new GUIStyle(skin.button);
@ -29,6 +31,11 @@ namespace Game.NavigationTool.Editor
entry.hover.textColor = entry.onHover.textColor = Color.white; entry.hover.textColor = entry.onHover.textColor = Color.white;
entry.active.textColor = entry.onActive.textColor = Color.yellow; entry.active.textColor = entry.onActive.textColor = Color.yellow;
invalidEntry = new GUIStyle(entry);
invalidEntry.normal.textColor = Color.red;
invalidEntry.hover.textColor = invalidEntry.onHover.textColor = new Color(1.0f, 0.3f, 0.3f);
invalidEntry.active.textColor = invalidEntry.onActive.textColor = new Color(1.0f, 0.0f, 0.5f);
GUIStyle style = skin.FindStyle("Foldout"); GUIStyle style = skin.FindStyle("Foldout");
if (style != null) if (style != null)

View file

@ -1,6 +1,6 @@
{ {
"name": "com.module.navigationtool", "name": "com.module.navigationtool",
"version": "0.1.0", "version": "0.2.0",
"displayName": "Module.NavigationTool", "displayName": "Module.NavigationTool",
"description": "Support for navigation tools", "description": "Support for navigation tools",
"unity": "2019.2", "unity": "2019.2",