Scene picker: Added option to add groups of scenes to open
This commit is contained in:
parent
41604b98e7
commit
a86f76904e
28 changed files with 1052 additions and 225 deletions
|
|
@ -0,0 +1,9 @@
|
|||
namespace Module.NavigationTool.Editor.Toolbar
|
||||
{
|
||||
public enum ESceneGroupFilterType
|
||||
{
|
||||
AssetLabels,
|
||||
NameContains,
|
||||
PathContains
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 6cf395ccc24c46b18597cfbf6d4e32fd
|
||||
timeCreated: 1693390754
|
||||
14
Editor/Toolbar/Tools/ScenePickerObjects/SceneGroup.cs
Normal file
14
Editor/Toolbar/Tools/ScenePickerObjects/SceneGroup.cs
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Module.NavigationTool.Editor.Toolbar
|
||||
{
|
||||
[Serializable]
|
||||
public sealed class SceneGroup
|
||||
{
|
||||
public string name;
|
||||
public ESceneGroupFilterType filterType;
|
||||
public string optionalMainScenePath;
|
||||
public List<string> filters = new();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 4b0f8e524da24c2e8d0d6c3d0a446059
|
||||
timeCreated: 1693390715
|
||||
14
Editor/Toolbar/Tools/ScenePickerObjects/SceneGroupArray.cs
Normal file
14
Editor/Toolbar/Tools/ScenePickerObjects/SceneGroupArray.cs
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Module.NavigationTool.Editor.Toolbar
|
||||
{
|
||||
[Serializable]
|
||||
public sealed class SceneGroupArray
|
||||
{
|
||||
public List<SceneGroup> groups = new();
|
||||
|
||||
public int Count => groups.Count;
|
||||
public SceneGroup this[int index] => groups[index];
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 59bece5e9d5f4b539434937529afb0e7
|
||||
timeCreated: 1693390710
|
||||
389
Editor/Toolbar/Tools/ScenePickerObjects/ScenePickerList.cs
Normal file
389
Editor/Toolbar/Tools/ScenePickerObjects/ScenePickerList.cs
Normal file
|
|
@ -0,0 +1,389 @@
|
|||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
using UnityEngine.SceneManagement;
|
||||
|
||||
namespace Module.NavigationTool.Editor.Toolbar
|
||||
{
|
||||
internal sealed class ScenePickerList
|
||||
{
|
||||
public GUIContent[] labels = new GUIContent[0];
|
||||
public readonly List<SceneElement> scenes = new List<SceneElement>();
|
||||
public readonly List<int> selected = new List<int>();
|
||||
|
||||
public void Refresh()
|
||||
{
|
||||
scenes.Clear();
|
||||
selected.Clear();
|
||||
|
||||
var projectSettings = new ToolbarProjectSettings();
|
||||
projectSettings.Load();
|
||||
var settings = projectSettings.GetValueAs<ToolbarScenePickerProjectSettings.Settings>();
|
||||
|
||||
List<WorkingSetScene> assets = GetWorkingSet();
|
||||
FetchAllScenesFromBuildSettings(assets);
|
||||
FetchAllScenesFromLabels(assets, settings.labels);
|
||||
FetchAllScenesFromSceneGroups(assets, settings.sceneGroups);
|
||||
FetchAllRemainingScenes(assets);
|
||||
|
||||
FetchAllLabels();
|
||||
FetchAllSelectedIndices();
|
||||
}
|
||||
|
||||
private void FetchAllScenesFromBuildSettings(List<WorkingSetScene> assets)
|
||||
{
|
||||
for (var i = 0; i < assets.Count; i++)
|
||||
{
|
||||
WorkingSetScene asset = assets[i];
|
||||
|
||||
if (!asset.inBuildSettings)
|
||||
continue;
|
||||
|
||||
scenes.Add(new SceneElement
|
||||
{
|
||||
name = asset.name,
|
||||
shortname = asset.shortname,
|
||||
paths = { asset.path }
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private void FetchAllScenesFromLabels(List<WorkingSetScene> assets, List<string> labels)
|
||||
{
|
||||
List<WorkingSetScene> filteredScenes = GetAllWorkingSetScenesWithLabels(assets, labels);
|
||||
filteredScenes = FilterToUniques(filteredScenes);
|
||||
filteredScenes = FilterAllExcept(filteredScenes, scenes);
|
||||
|
||||
if (filteredScenes.Count != 0)
|
||||
scenes.Add(new SceneElement{ includeAsSelectable = false });
|
||||
|
||||
for (var i = 0; i < filteredScenes.Count; i++)
|
||||
{
|
||||
scenes.Add(new SceneElement
|
||||
{
|
||||
name = filteredScenes[i].name,
|
||||
shortname = filteredScenes[i].shortname,
|
||||
paths = { filteredScenes[i].path }
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private void FetchAllScenesFromSceneGroups(List<WorkingSetScene> assets, SceneGroupArray sceneGroups)
|
||||
{
|
||||
if (sceneGroups.Count != 0)
|
||||
scenes.Add(new SceneElement{ includeAsSelectable = false });
|
||||
|
||||
for (var i = 0; i < sceneGroups.Count; i++)
|
||||
{
|
||||
SceneGroup sceneGroup = sceneGroups[i];
|
||||
string name = sceneGroup.name;
|
||||
List<WorkingSetScene> filteredScenes;
|
||||
|
||||
if (sceneGroup.filterType == ESceneGroupFilterType.AssetLabels)
|
||||
{
|
||||
filteredScenes = GetAllWorkingSetScenesWithLabels(assets, sceneGroup.filters);
|
||||
}
|
||||
else if (sceneGroup.filterType == ESceneGroupFilterType.NameContains)
|
||||
{
|
||||
filteredScenes = GetAllWorkingSetScenesWithNameContaining(assets, sceneGroup.filters);
|
||||
}
|
||||
else
|
||||
{
|
||||
filteredScenes = GetAllWorkingSetScenesWithPathContaining(assets, sceneGroup.filters);
|
||||
name = sceneGroup.name.Replace("/", "\\");
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(sceneGroup.optionalMainScenePath))
|
||||
SetWorkingSceneAsFirst(filteredScenes, sceneGroup.optionalMainScenePath);
|
||||
|
||||
filteredScenes = FilterToUniques(filteredScenes);
|
||||
|
||||
var scene = new SceneElement
|
||||
{
|
||||
name = name,
|
||||
shortname = name,
|
||||
isGroup = true
|
||||
};
|
||||
|
||||
for (var j = 0; j < filteredScenes.Count; j++)
|
||||
{
|
||||
scene.paths.Add(filteredScenes[j].path);
|
||||
}
|
||||
|
||||
scene.name += $" ({scene.paths.Count})";
|
||||
scenes.Add(scene);
|
||||
}
|
||||
}
|
||||
|
||||
private void FetchAllRemainingScenes(List<WorkingSetScene> assets)
|
||||
{
|
||||
List<WorkingSetScene> filteredScenes = FilterAllExcept(assets, scenes);
|
||||
|
||||
if (filteredScenes.Count != 0)
|
||||
scenes.Add(new SceneElement{ includeAsSelectable = false });
|
||||
|
||||
for (var i = 0; i < filteredScenes.Count; i++)
|
||||
{
|
||||
scenes.Add(new SceneElement
|
||||
{
|
||||
name = filteredScenes[i].name,
|
||||
shortname = filteredScenes[i].shortname,
|
||||
paths = { filteredScenes[i].path }
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private static List<WorkingSetScene> FilterToUniques(List<WorkingSetScene> list)
|
||||
{
|
||||
var uniques = new List<WorkingSetScene>(list.Count);
|
||||
|
||||
for (var i = 0; i < list.Count; i++)
|
||||
{
|
||||
if (!uniques.Contains(list[i]))
|
||||
uniques.Add(list[i]);
|
||||
}
|
||||
|
||||
return uniques;
|
||||
}
|
||||
|
||||
private static List<WorkingSetScene> FilterAllExcept(List<WorkingSetScene> list, List<SceneElement> except, bool includeGroups = false)
|
||||
{
|
||||
var filtered = new List<WorkingSetScene>(list.Count);
|
||||
|
||||
for (var i = 0; i < list.Count; i++)
|
||||
{
|
||||
var contains = false;
|
||||
|
||||
for (var j = 0; j < except.Count; j++)
|
||||
{
|
||||
if (except[j].isGroup && !includeGroups)
|
||||
continue;
|
||||
if (!except[j].paths.Contains(list[i].path))
|
||||
continue;
|
||||
|
||||
contains = true;
|
||||
break;
|
||||
}
|
||||
|
||||
if (!contains)
|
||||
filtered.Add(list[i]);
|
||||
}
|
||||
|
||||
return filtered;
|
||||
}
|
||||
|
||||
private void FetchAllLabels()
|
||||
{
|
||||
labels = new GUIContent[scenes.Count];
|
||||
|
||||
for (var i = 0; i < scenes.Count; i++)
|
||||
{
|
||||
labels[i] = new GUIContent(scenes[i].name);
|
||||
}
|
||||
}
|
||||
|
||||
private void FetchAllSelectedIndices()
|
||||
{
|
||||
for (var i = 0; i < SceneManager.sceneCount; i++)
|
||||
{
|
||||
Scene scene = SceneManager.GetSceneAt(i);
|
||||
|
||||
if (string.IsNullOrEmpty(scene.path))
|
||||
continue;
|
||||
|
||||
int index = IndexOfPath(scenes, scene.path, false);
|
||||
|
||||
if (index != -1)
|
||||
selected.Add(index);
|
||||
}
|
||||
}
|
||||
|
||||
private static List<WorkingSetScene> GetAllWorkingSetScenesWithLabels(List<WorkingSetScene> assets, List<string> labels)
|
||||
{
|
||||
var list = new List<WorkingSetScene>();
|
||||
|
||||
for (var i = 0; i < labels.Count; i++)
|
||||
{
|
||||
list.AddRange(GetAllWorkingSetScenesWithLabel(assets, labels[i]));
|
||||
}
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
private static List<WorkingSetScene> GetAllWorkingSetScenesWithLabel(List<WorkingSetScene> assets, string label)
|
||||
{
|
||||
var list = new List<WorkingSetScene>();
|
||||
|
||||
for (var i = 0; i < assets.Count; i++)
|
||||
{
|
||||
if (assets[i].labels.Contains(label))
|
||||
list.Add(assets[i]);
|
||||
}
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
private static List<WorkingSetScene> GetAllWorkingSetScenesWithNameContaining(List<WorkingSetScene> assets, List<string> filters)
|
||||
{
|
||||
var list = new List<WorkingSetScene>();
|
||||
|
||||
for (var i = 0; i < assets.Count; i++)
|
||||
{
|
||||
for (var j = 0; j < filters.Count; j++)
|
||||
{
|
||||
if (!assets[i].shortname.Contains(filters[j]))
|
||||
continue;
|
||||
|
||||
list.Add(assets[i]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
private static List<WorkingSetScene> GetAllWorkingSetScenesWithPathContaining(List<WorkingSetScene> assets, List<string> filters)
|
||||
{
|
||||
var list = new List<WorkingSetScene>();
|
||||
|
||||
for (var i = 0; i < assets.Count; i++)
|
||||
{
|
||||
for (var j = 0; j < filters.Count; j++)
|
||||
{
|
||||
if (!PathContains(assets[i].path, filters[j]))
|
||||
continue;
|
||||
|
||||
list.Add(assets[i]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
private static bool IsValidScene(string path)
|
||||
{
|
||||
if (string.IsNullOrEmpty(path))
|
||||
return false;
|
||||
if (!path.StartsWith("Assets"))
|
||||
return false;
|
||||
|
||||
return AssetDatabase.LoadAssetAtPath<SceneAsset>(path) != null;
|
||||
}
|
||||
|
||||
public int IndexOfPath(string path, bool includeGroups)
|
||||
{
|
||||
return IndexOfPath(scenes, path, includeGroups);
|
||||
}
|
||||
|
||||
private static int IndexOfPath(List<SceneElement> list, string path, bool includeGroups)
|
||||
{
|
||||
for (var i = 0; i < list.Count; i++)
|
||||
{
|
||||
if (!includeGroups && list[i].isGroup)
|
||||
continue;
|
||||
if (!list[i].includeAsSelectable)
|
||||
continue;
|
||||
|
||||
if (list[i].paths.IndexOf(path) != -1)
|
||||
return i;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
private static bool PathContains(string path, string subpath)
|
||||
{
|
||||
path = path.Replace("\\", "/");
|
||||
subpath = subpath.Replace("\\", "/");
|
||||
return path.Contains(subpath);
|
||||
}
|
||||
|
||||
private static bool PathEquals(string path, string subpath)
|
||||
{
|
||||
path = path.Replace("\\", "/");
|
||||
subpath = subpath.Replace("\\", "/");
|
||||
return path.Equals(subpath);
|
||||
}
|
||||
|
||||
private static void SetWorkingSceneAsFirst(List<WorkingSetScene> scenes, string path)
|
||||
{
|
||||
int index = -1;
|
||||
|
||||
for (var i = 0; i < scenes.Count; i++)
|
||||
{
|
||||
if (!PathEquals(scenes[i].path, path))
|
||||
continue;
|
||||
|
||||
index = i;
|
||||
break;
|
||||
}
|
||||
|
||||
if (index == -1)
|
||||
return;
|
||||
|
||||
WorkingSetScene temp = scenes[0];
|
||||
scenes[0] = scenes[index];
|
||||
scenes[index] = temp;
|
||||
}
|
||||
|
||||
private static List<WorkingSetScene> GetWorkingSet()
|
||||
{
|
||||
var workingSet = new List<WorkingSetScene>();
|
||||
string[] guids = AssetDatabase.FindAssets("t:scene");
|
||||
EditorBuildSettingsScene[] buildSettingsScenes = EditorBuildSettings.scenes;
|
||||
|
||||
for (var i = 0; i < guids.Length; i++)
|
||||
{
|
||||
string path = AssetDatabase.GUIDToAssetPath(guids[i]);
|
||||
|
||||
if (!IsValidScene(path))
|
||||
continue;
|
||||
|
||||
var asset = AssetDatabase.LoadAssetAtPath<SceneAsset>(path);
|
||||
string sceneName = path.Substring(7, path.Length - 13).Replace('/', '\\');
|
||||
var inBuildSettings = false;
|
||||
|
||||
for (var j = 0; j < buildSettingsScenes.Length; j++)
|
||||
{
|
||||
if (!buildSettingsScenes[j].path.Equals(path))
|
||||
continue;
|
||||
|
||||
inBuildSettings = true;
|
||||
break;
|
||||
}
|
||||
|
||||
workingSet.Add(new WorkingSetScene
|
||||
{
|
||||
path = path,
|
||||
name = sceneName,
|
||||
shortname = Path.GetFileNameWithoutExtension(path),
|
||||
labels = AssetDatabase.GetLabels(asset),
|
||||
inBuildSettings = inBuildSettings
|
||||
});
|
||||
}
|
||||
|
||||
return workingSet;
|
||||
}
|
||||
|
||||
public sealed class SceneElement
|
||||
{
|
||||
public string name;
|
||||
public string shortname;
|
||||
public bool includeAsSelectable = true;
|
||||
public bool isGroup;
|
||||
public readonly List<string> paths = new List<string>();
|
||||
}
|
||||
|
||||
private sealed class WorkingSetScene
|
||||
{
|
||||
public string path;
|
||||
public string name;
|
||||
public string shortname;
|
||||
public string[] labels;
|
||||
public bool inBuildSettings;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
fileFormatVersion: 2
|
||||
guid: d336bd910c0049c8ab47f94d9924baf3
|
||||
timeCreated: 1693405779
|
||||
Loading…
Add table
Add a link
Reference in a new issue