diff --git a/Editor/Toolbar/Settings/IToolbarProjectSettings.cs b/Editor/Toolbar/Settings/IToolbarProjectSettings.cs new file mode 100644 index 0000000..46fab65 --- /dev/null +++ b/Editor/Toolbar/Settings/IToolbarProjectSettings.cs @@ -0,0 +1,12 @@ +namespace Module.NavigationTool.Editor.Toolbar +{ + public interface IToolbarProjectSettings + { + string Title { get; } + bool IsSettingsDirty { get; } + + void Initialize(ToolbarProjectSettings projectSettings); + void Draw(); + void SetSettingsValue(); + } +} \ No newline at end of file diff --git a/Editor/Toolbar/Settings/IToolbarProjectSettings.cs.meta b/Editor/Toolbar/Settings/IToolbarProjectSettings.cs.meta new file mode 100644 index 0000000..b7a6036 --- /dev/null +++ b/Editor/Toolbar/Settings/IToolbarProjectSettings.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: a45b77fff4244ae4a1271208dcb3bc9c +timeCreated: 1693423025 \ No newline at end of file diff --git a/Editor/Toolbar/Settings/ToolbarProjectSettings.cs b/Editor/Toolbar/Settings/ToolbarProjectSettings.cs new file mode 100644 index 0000000..e3d2367 --- /dev/null +++ b/Editor/Toolbar/Settings/ToolbarProjectSettings.cs @@ -0,0 +1,113 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Text; +using UnityEngine; + +namespace Module.NavigationTool.Editor.Toolbar +{ + [Serializable] + public sealed class ToolbarProjectSettings + { + [SerializeField] + private List keys = new(); + [SerializeField] + private List values = new(); + + public const string RELATIVE_PATH = "ProjectSettings/ToolbarProjectSettings.asset"; + + public void Load() + { + try + { + string path = GetAbsolutePath(); + + if (File.Exists(path)) + { + string json = File.ReadAllText(path); + JsonUtility.FromJsonOverwrite(json, this); + } + else + { + keys.Clear(); + values.Clear(); + } + } + catch (Exception e) + { + Debug.LogException(e); + } + } + + public void Save() + { + try + { + string path = GetAbsolutePath(); + string json = JsonUtility.ToJson(this, true); + File.WriteAllText(path, json, Encoding.Unicode); + } + catch (Exception e) + { + Debug.LogException(e); + } + } + + public T GetValueAs() where T : new() + { + try + { + string key = typeof(T).FullName; + int index = keys.IndexOf(key); + + if (index == -1) + { + var t = new T(); + keys.Add(key); + values.Add(JsonUtility.ToJson(t)); + return t; + } + + string json = values[index]; + return JsonUtility.FromJson(json); + } + catch (Exception e) + { + Debug.LogException(e); + return new T(); + } + } + + public void SetValue(T value) where T : new() + { + try + { + string key = typeof(T).FullName; + string json = JsonUtility.ToJson(value); + int index = keys.IndexOf(key); + + if (index != -1) + { + values[index] = json; + } + else + { + keys.Add(key); + values.Add(json); + } + } + catch (Exception e) + { + Debug.LogException(e); + } + } + + private string GetAbsolutePath() + { + string path = Application.dataPath; + path = path.Substring(0, Application.dataPath.Length - 6); + path += RELATIVE_PATH; + return path; + } + } +} \ No newline at end of file diff --git a/Editor/Toolbar/Settings/ToolbarProjectSettings.cs.meta b/Editor/Toolbar/Settings/ToolbarProjectSettings.cs.meta new file mode 100644 index 0000000..c2c1e02 --- /dev/null +++ b/Editor/Toolbar/Settings/ToolbarProjectSettings.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: a5fbb83f9c104775ae07b33244e133d2 +timeCreated: 1693466538 \ No newline at end of file diff --git a/Editor/Toolbar/Settings/ToolbarProjectSettingsProvider.cs b/Editor/Toolbar/Settings/ToolbarProjectSettingsProvider.cs new file mode 100644 index 0000000..b3daf42 --- /dev/null +++ b/Editor/Toolbar/Settings/ToolbarProjectSettingsProvider.cs @@ -0,0 +1,110 @@ +using System; +using System.Collections.Generic; +using UnityEditor; +using UnityEngine; + +namespace Module.NavigationTool.Editor.Toolbar +{ + internal static class ToolbarProjectSettingsProvider + { + private static Styles STYLES; + private static IToolbarProjectSettings[] SETTINGS; + private static ToolbarProjectSettings PROJECT_SETTINGS; + private const string PREF_FOLDOUT_STATE = "ToolbarFoldout_{0}"; + + [SettingsProvider] + public static SettingsProvider GetProvider() + { + Initialize(); + var keywords = new List { "Toolbar" }; + + for (var i = 0; i < SETTINGS.Length; i++) + { + keywords.Add(SETTINGS[i].Title); + } + + return new SettingsProvider("Module/Toolbar", SettingsScope.Project) + { + label = "Toolbar", + keywords = keywords.ToArray(), + guiHandler = OnGui + }; + } + + private static void Initialize() + { + if (STYLES == null) + STYLES = new Styles(); + + if (PROJECT_SETTINGS == null) + { + PROJECT_SETTINGS = new ToolbarProjectSettings(); + PROJECT_SETTINGS.Load(); + } + + if (SETTINGS == null) + SETTINGS = ToolbarSettingsUtility.GetAllProjectSettings(PROJECT_SETTINGS); + } + + private static void OnGui(string searchContext) + { + Initialize(); + STYLES.Initialize(GUI.skin); + var isSettingsDirty = false; + + EditorGUILayout.BeginVertical(STYLES.settingsGroup); + { + for (var i = 0; i < SETTINGS.Length; i++) + { + IToolbarProjectSettings settings = SETTINGS[i]; + + try + { + bool foldoutState = GetFoldoutState(settings); + bool newFoldoutState = EditorGUILayout.BeginFoldoutHeaderGroup(foldoutState, settings.Title, EditorStyles.foldoutHeader); + + if (newFoldoutState) + { + EditorGUI.indentLevel++; + settings.Draw(); + + if (settings.IsSettingsDirty) + { + isSettingsDirty = true; + settings.SetSettingsValue(); + } + + EditorGUI.indentLevel--; + } + + EditorGUILayout.EndFoldoutHeaderGroup(); + EditorGUILayout.Space(); + + if (newFoldoutState != foldoutState) + SetFoldoutState(settings, newFoldoutState); + } + catch (Exception e) + { + EditorGUILayout.LabelField(e.Message); + } + } + + if (isSettingsDirty) + PROJECT_SETTINGS.Save(); + } + EditorGUILayout.EndVertical(); + } + + private static bool GetFoldoutState(IToolbarProjectSettings settings) + { + string key = string.Format(PREF_FOLDOUT_STATE, settings.GetType().FullName); + return EditorPrefs.GetBool(key, true); + } + + private static void SetFoldoutState(IToolbarProjectSettings settings, bool foldout) + { + string key = string.Format(PREF_FOLDOUT_STATE, settings.GetType().FullName); + EditorPrefs.SetBool(key, foldout); + } + } +} diff --git a/Editor/Toolbar/Settings/ToolbarProjectSettingsProvider.cs.meta b/Editor/Toolbar/Settings/ToolbarProjectSettingsProvider.cs.meta new file mode 100644 index 0000000..55afd32 --- /dev/null +++ b/Editor/Toolbar/Settings/ToolbarProjectSettingsProvider.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 7e21927d181c41f1acdbecc9f5fc3e26 +timeCreated: 1693423048 \ No newline at end of file diff --git a/Editor/Toolbar/Settings/ToolbarSettingsProvider.cs b/Editor/Toolbar/Settings/ToolbarSettingsProvider.cs index 086d25b..fad50dc 100644 --- a/Editor/Toolbar/Settings/ToolbarSettingsProvider.cs +++ b/Editor/Toolbar/Settings/ToolbarSettingsProvider.cs @@ -36,7 +36,7 @@ namespace Module.NavigationTool.Editor.Toolbar if (STYLES == null) STYLES = new Styles(); if (SETTINGS == null) - SETTINGS = ToolbarSettingsUtility.GetAllSettings(); + SETTINGS = ToolbarSettingsUtility.GetAllUserSettings(); } private static void OnGui(string searchContext) diff --git a/Editor/Toolbar/Tools/ScenePickerObjects.meta b/Editor/Toolbar/Tools/ScenePickerObjects.meta new file mode 100644 index 0000000..39e4e23 --- /dev/null +++ b/Editor/Toolbar/Tools/ScenePickerObjects.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: cf9c741582d646d5ab02533554680715 +timeCreated: 1693390703 \ No newline at end of file diff --git a/Editor/Toolbar/Tools/ScenePickerObjects/ESceneGroupFilterType.cs b/Editor/Toolbar/Tools/ScenePickerObjects/ESceneGroupFilterType.cs new file mode 100644 index 0000000..e86b3b1 --- /dev/null +++ b/Editor/Toolbar/Tools/ScenePickerObjects/ESceneGroupFilterType.cs @@ -0,0 +1,9 @@ +namespace Module.NavigationTool.Editor.Toolbar +{ + public enum ESceneGroupFilterType + { + AssetLabels, + NameContains, + PathContains + } +} \ No newline at end of file diff --git a/Editor/Toolbar/Tools/ScenePickerObjects/ESceneGroupFilterType.cs.meta b/Editor/Toolbar/Tools/ScenePickerObjects/ESceneGroupFilterType.cs.meta new file mode 100644 index 0000000..7a0645d --- /dev/null +++ b/Editor/Toolbar/Tools/ScenePickerObjects/ESceneGroupFilterType.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 6cf395ccc24c46b18597cfbf6d4e32fd +timeCreated: 1693390754 \ No newline at end of file diff --git a/Editor/Toolbar/Tools/ScenePickerObjects/SceneGroup.cs b/Editor/Toolbar/Tools/ScenePickerObjects/SceneGroup.cs new file mode 100644 index 0000000..031cae5 --- /dev/null +++ b/Editor/Toolbar/Tools/ScenePickerObjects/SceneGroup.cs @@ -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 filters = new(); + } +} \ No newline at end of file diff --git a/Editor/Toolbar/Tools/ScenePickerObjects/SceneGroup.cs.meta b/Editor/Toolbar/Tools/ScenePickerObjects/SceneGroup.cs.meta new file mode 100644 index 0000000..4232c5e --- /dev/null +++ b/Editor/Toolbar/Tools/ScenePickerObjects/SceneGroup.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 4b0f8e524da24c2e8d0d6c3d0a446059 +timeCreated: 1693390715 \ No newline at end of file diff --git a/Editor/Toolbar/Tools/ScenePickerObjects/SceneGroupArray.cs b/Editor/Toolbar/Tools/ScenePickerObjects/SceneGroupArray.cs new file mode 100644 index 0000000..35fc7cc --- /dev/null +++ b/Editor/Toolbar/Tools/ScenePickerObjects/SceneGroupArray.cs @@ -0,0 +1,14 @@ +using System; +using System.Collections.Generic; + +namespace Module.NavigationTool.Editor.Toolbar +{ + [Serializable] + public sealed class SceneGroupArray + { + public List groups = new(); + + public int Count => groups.Count; + public SceneGroup this[int index] => groups[index]; + } +} \ No newline at end of file diff --git a/Editor/Toolbar/Tools/ScenePickerObjects/SceneGroupArray.cs.meta b/Editor/Toolbar/Tools/ScenePickerObjects/SceneGroupArray.cs.meta new file mode 100644 index 0000000..b19e39a --- /dev/null +++ b/Editor/Toolbar/Tools/ScenePickerObjects/SceneGroupArray.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 59bece5e9d5f4b539434937529afb0e7 +timeCreated: 1693390710 \ No newline at end of file diff --git a/Editor/Toolbar/Tools/ScenePickerObjects/ScenePickerList.cs b/Editor/Toolbar/Tools/ScenePickerObjects/ScenePickerList.cs new file mode 100644 index 0000000..f93beae --- /dev/null +++ b/Editor/Toolbar/Tools/ScenePickerObjects/ScenePickerList.cs @@ -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 scenes = new List(); + public readonly List selected = new List(); + + public void Refresh() + { + scenes.Clear(); + selected.Clear(); + + var projectSettings = new ToolbarProjectSettings(); + projectSettings.Load(); + var settings = projectSettings.GetValueAs(); + + List assets = GetWorkingSet(); + FetchAllScenesFromBuildSettings(assets); + FetchAllScenesFromLabels(assets, settings.labels); + FetchAllScenesFromSceneGroups(assets, settings.sceneGroups); + FetchAllRemainingScenes(assets); + + FetchAllLabels(); + FetchAllSelectedIndices(); + } + + private void FetchAllScenesFromBuildSettings(List 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 assets, List labels) + { + List 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 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 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 assets) + { + List 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 FilterToUniques(List list) + { + var uniques = new List(list.Count); + + for (var i = 0; i < list.Count; i++) + { + if (!uniques.Contains(list[i])) + uniques.Add(list[i]); + } + + return uniques; + } + + private static List FilterAllExcept(List list, List except, bool includeGroups = false) + { + var filtered = new List(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 GetAllWorkingSetScenesWithLabels(List assets, List labels) + { + var list = new List(); + + for (var i = 0; i < labels.Count; i++) + { + list.AddRange(GetAllWorkingSetScenesWithLabel(assets, labels[i])); + } + + return list; + } + + private static List GetAllWorkingSetScenesWithLabel(List assets, string label) + { + var list = new List(); + + for (var i = 0; i < assets.Count; i++) + { + if (assets[i].labels.Contains(label)) + list.Add(assets[i]); + } + + return list; + } + + private static List GetAllWorkingSetScenesWithNameContaining(List assets, List filters) + { + var list = new List(); + + 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 GetAllWorkingSetScenesWithPathContaining(List assets, List filters) + { + var list = new List(); + + 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(path) != null; + } + + public int IndexOfPath(string path, bool includeGroups) + { + return IndexOfPath(scenes, path, includeGroups); + } + + private static int IndexOfPath(List 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 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 GetWorkingSet() + { + var workingSet = new List(); + 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(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 paths = new List(); + } + + private sealed class WorkingSetScene + { + public string path; + public string name; + public string shortname; + public string[] labels; + public bool inBuildSettings; + } + } +} \ No newline at end of file diff --git a/Editor/Toolbar/Tools/ScenePickerObjects/ScenePickerList.cs.meta b/Editor/Toolbar/Tools/ScenePickerObjects/ScenePickerList.cs.meta new file mode 100644 index 0000000..a799735 --- /dev/null +++ b/Editor/Toolbar/Tools/ScenePickerObjects/ScenePickerList.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: d336bd910c0049c8ab47f94d9924baf3 +timeCreated: 1693405779 \ No newline at end of file diff --git a/Editor/Toolbar/Tools/Settings/ToolbarScenePickerProjectSettings.cs b/Editor/Toolbar/Tools/Settings/ToolbarScenePickerProjectSettings.cs new file mode 100644 index 0000000..5336768 --- /dev/null +++ b/Editor/Toolbar/Tools/Settings/ToolbarScenePickerProjectSettings.cs @@ -0,0 +1,48 @@ +using System; +using System.Collections.Generic; + +namespace Module.NavigationTool.Editor.Toolbar +{ + internal sealed class ToolbarScenePickerProjectSettings : IToolbarProjectSettings + { + public string Title => "Scene"; + public bool IsSettingsDirty { get; private set; } + + private StringReordableListDrawer assetLabelList; + private SceneGroupReordableListDrawer sceneGroupList; + + private ToolbarProjectSettings projectSettings; + private Settings settings; + + public void Initialize(ToolbarProjectSettings projectSettings) + { + this.projectSettings = projectSettings; + settings = projectSettings.GetValueAs(); + + assetLabelList = new StringReordableListDrawer(settings.labels, "Scene sorting by Asset label"); + assetLabelList.onChanged += ToolScenePicker.SetAsDirty; + + sceneGroupList = new SceneGroupReordableListDrawer(settings.sceneGroups.groups, "Scene groups"); + sceneGroupList.onChanged += ToolScenePicker.SetAsDirty; + } + + public void Draw() + { + assetLabelList.DoLayoutList(); + sceneGroupList.DoLayoutList(); + IsSettingsDirty = assetLabelList.IsDirty || sceneGroupList.IsDirty; + } + + public void SetSettingsValue() + { + projectSettings.SetValue(settings); + } + + [Serializable] + public sealed class Settings + { + public List labels = new(); + public SceneGroupArray sceneGroups = new(); + } + } +} \ No newline at end of file diff --git a/Editor/Toolbar/Tools/Settings/ToolbarScenePickerProjectSettings.cs.meta b/Editor/Toolbar/Tools/Settings/ToolbarScenePickerProjectSettings.cs.meta new file mode 100644 index 0000000..152790d --- /dev/null +++ b/Editor/Toolbar/Tools/Settings/ToolbarScenePickerProjectSettings.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 3dd46bde8e5b4cca9c95d051862f5817 +timeCreated: 1693466453 \ No newline at end of file diff --git a/Editor/Toolbar/Tools/Settings/ToolbarScenePickerSettings.cs b/Editor/Toolbar/Tools/Settings/ToolbarScenePickerSettings.cs index 867b740..285282b 100644 --- a/Editor/Toolbar/Tools/Settings/ToolbarScenePickerSettings.cs +++ b/Editor/Toolbar/Tools/Settings/ToolbarScenePickerSettings.cs @@ -1,9 +1,4 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using UnityEditor; -using UnityEditorInternal; -using UnityEngine; +using UnityEditor; namespace Module.NavigationTool.Editor.Toolbar { @@ -12,7 +7,6 @@ namespace Module.NavigationTool.Editor.Toolbar public string Title => "Scene"; private const string PREF_IS_SCENE_ENABLED = "ToolbarSettings_IsSceneEnabled"; - private const string PREF_SCENE_ASSET_LABELS = "ToolbarSettings_SceneAssetLabels"; private const string PREF_SCENE_PICKER_LOAD_SET_AS_ADDITIVE_KEY = "ToolbarSettings_ScenePickerLoadSetAsAdditive"; public static bool IsSceneEnabled @@ -21,78 +15,19 @@ namespace Module.NavigationTool.Editor.Toolbar private set => EditorPrefs.SetBool(PREF_IS_SCENE_ENABLED, value); } - public static List SceneAssetLabels - { - get => EditorPrefs.GetString(PREF_SCENE_ASSET_LABELS).Split(',').ToList(); - private set => EditorPrefs.SetString(PREF_SCENE_ASSET_LABELS, string.Join(",", value)); - } - public static bool IsScenePickerSetAsAdditive { get => EditorPrefs.GetBool(PREF_SCENE_PICKER_LOAD_SET_AS_ADDITIVE_KEY, false); set => EditorPrefs.SetBool(PREF_SCENE_PICKER_LOAD_SET_AS_ADDITIVE_KEY, value); } - private ReorderableList assetLabelList; - private List assetLabels; - public void Initialize() { - assetLabels = SceneAssetLabels.ToList(); - assetLabelList = new ReorderableList(assetLabels, typeof(string), true, true, true, true); - assetLabelList.drawElementCallback += OnAssetLabelListDrawElement; - assetLabelList.drawHeaderCallback += OnAssetLabelListDrawHeader; - assetLabelList.onAddCallback += OnAssetLabelListAddedElement; - assetLabelList.onRemoveCallback += OnAssetLabelListRemovedElement; - assetLabelList.onReorderCallback += OnAssetLabelListReorder; } public void Draw() { IsSceneEnabled = EditorGUILayout.Toggle("Enable Scene picker", IsSceneEnabled); - - if (assetLabelList == null) - return; - - assetLabelList.DoLayoutList(); - SceneAssetLabels = assetLabels; - } - - private static void OnAssetLabelListDrawHeader(Rect rect) - { - EditorGUI.LabelField(rect, "Scene sorting by Asset label"); - } - - private void OnAssetLabelListDrawElement(Rect rect, int index, bool isActive, bool isFocused) - { - rect.height -= 2; - rect.y += 1; - - string text = assetLabels[index]; - string temp = EditorGUI.TextField(rect, text); - - if (string.Equals(text, temp, StringComparison.Ordinal)) - return; - - assetLabels[index] = temp; - ToolScenePicker.SetAsDirty(); - } - - private void OnAssetLabelListAddedElement(ReorderableList list) - { - assetLabels.Add(string.Empty); - ToolScenePicker.SetAsDirty(); - } - - private void OnAssetLabelListRemovedElement(ReorderableList list) - { - assetLabels.RemoveAt(list.index); - ToolScenePicker.SetAsDirty(); - } - - private void OnAssetLabelListReorder(ReorderableList list) - { - ToolScenePicker.SetAsDirty(); } } } \ No newline at end of file diff --git a/Editor/Toolbar/Tools/ToolScenePicker.cs b/Editor/Toolbar/Tools/ToolScenePicker.cs index 0782f37..88235cb 100644 --- a/Editor/Toolbar/Tools/ToolScenePicker.cs +++ b/Editor/Toolbar/Tools/ToolScenePicker.cs @@ -1,7 +1,4 @@ using System; -using System.Collections.Generic; -using System.IO; -using System.Runtime.CompilerServices; using System.Text; using JetBrains.Annotations; using UnityEditor; @@ -18,134 +15,22 @@ namespace Module.NavigationTool.Editor.Toolbar public override bool Enabled => !EditorApplication.isPlaying && !EditorApplication.isPlayingOrWillChangePlaymode; public override EToolbarPlacement Placement => EToolbarPlacement.Right; public override int Priority => (int)EToolbarPriority.Medium; - - private static readonly List SELECTED_INDICES = new List(); - private static readonly StringBuilder STRING_BUILDER = new StringBuilder(); - private static string SCENE_LABEL = string.Empty; - private static string[] SCENE_NAMES = new string[0]; - private static string[] SCENE_SHORT_NAMES = new string[0]; - private static string[] SCENE_PATHS = new string[0]; - private static readonly GUIContent LABEL_SCENE_ADDITIVE = new GUIContent(string.Empty, "Additive scene loading (toogle to Single)"); - private static readonly GUIContent LABEL_SCENE_SINGLE = new GUIContent(string.Empty, "Single scene loading (toggle to Additive)"); - private static readonly GUIContent LABEL_SCENE_CREATE = new GUIContent(string.Empty, "Create a new scene"); - private const float BUTTON_WIDTH = 24.0f; + private static readonly StringBuilder STRING_BUILDER = new StringBuilder(); + private static readonly ScenePickerList SCENE_LIST = new ScenePickerList(); + private static string SCENE_LABEL = string.Empty; private static bool IS_DIRTY = true; - + private static void Initialize() { if (!IS_DIRTY) return; - SELECTED_INDICES.Clear(); - var listNames = new List(); - var listShortNames = new List(); - var listPaths = new List(); - - InitializeBuildSettingsScenes(listNames, listShortNames, listPaths); - InitializeRemainingScenes(listNames, listShortNames, listPaths); - - for (var i = 0; i < SceneManager.sceneCount; i++) - { - Scene scene = SceneManager.GetSceneAt(i); - - if (string.IsNullOrEmpty(scene.path)) - continue; - - int index = listPaths.IndexOf(scene.path); - - if (index != -1) - SELECTED_INDICES.Add(index); - } - - SCENE_NAMES = listNames.ToArray(); - SCENE_SHORT_NAMES = listShortNames.ToArray(); - SCENE_PATHS = listPaths.ToArray(); + SCENE_LIST.Refresh(); RefreshSceneLabel(); IS_DIRTY = false; } - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private static void InitializeBuildSettingsScenes(List listNames, List listShortNames, List listPaths) - { - EditorBuildSettingsScene[] scenes = EditorBuildSettings.scenes; - - for (int i = 0, added = 0; i < scenes.Length; i++) - { - string path = scenes[i].path; - - if (string.IsNullOrEmpty(path)) - continue; - if (AssetDatabase.LoadAssetAtPath(path) == null) - continue; - - listNames.Add(Path.GetFileNameWithoutExtension(path)); - listShortNames.Add(listNames[added]); - listPaths.Add(path); - added++; - } - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private static void InitializeRemainingScenes(List listNames, List listShortNames, List listPaths) - { - List sortByAssetLabels = ToolbarScenePickerSettings.SceneAssetLabels; - var assetLabelToScenes = new SceneSortElement[sortByAssetLabels.Count + 1]; - string[] guids = AssetDatabase.FindAssets("t:scene"); - - for (var i = 0; i < guids.Length; i++) - { - string path = AssetDatabase.GUIDToAssetPath(guids[i]); - - if (listPaths.Contains(path) || !path.StartsWith("Assets")) - continue; - - var scene = AssetDatabase.LoadAssetAtPath(path); - - if (scene == null) - continue; - - string sceneName = path.Substring(7, path.Length - 13) - .Replace('/', '\\'); - - string[] assetLabels = AssetDatabase.GetLabels(scene); - int index = -1; - - for (var j = 0; j < assetLabels.Length; j++) - { - index = sortByAssetLabels.IndexOf(assetLabels[j]); - - if (index != -1) - break; - } - - if (index == -1) - index = sortByAssetLabels.Count; - if (assetLabelToScenes[index] == null) - assetLabelToScenes[index] = new SceneSortElement(); - - assetLabelToScenes[index].names.Add(sceneName); - assetLabelToScenes[index].shortNames.Add(Path.GetFileName(sceneName)); - assetLabelToScenes[index].paths.Add(path); - } - - for (var i = 0; i < assetLabelToScenes.Length; i++) - { - SceneSortElement e = assetLabelToScenes[i]; - - if (e == null) - continue; - - listNames.Add(string.Empty); - listShortNames.Add(string.Empty); - listPaths.Add(string.Empty); - - listNames.AddRange(e.names); - listShortNames.AddRange(e.shortNames); - listPaths.AddRange(e.paths); - } - } - public override void Update() { Initialize(); @@ -155,9 +40,9 @@ namespace Module.NavigationTool.Editor.Toolbar { Initialize(); - var rect0 = new Rect(rect.x, rect.y, rect.width - BUTTON_WIDTH * 2.0f, rect.height); - var rect1 = new Rect(rect0.xMax, rect.y, BUTTON_WIDTH, rect.height); - var rect2 = new Rect(rect1.xMax, rect.y, BUTTON_WIDTH, rect.height); + var rect0 = new Rect(rect.x, rect.y, rect.width - Styles.BUTTON_WIDTH * 2.0f, rect.height); + var rect1 = new Rect(rect0.xMax, rect.y, Styles.BUTTON_WIDTH, rect.height); + var rect2 = new Rect(rect1.xMax, rect.y, Styles.BUTTON_WIDTH, rect.height); DrawSceneDropDown(rect0); DrawSceneLoadToggle(rect1); DrawSceneAddButton(rect2); @@ -177,12 +62,12 @@ namespace Module.NavigationTool.Editor.Toolbar if (tempIsAdditive) { GUI.Label(rect, styles.iconSceneAdditive, styles.labelCenter); - GUI.Label(rect, LABEL_SCENE_ADDITIVE, styles.labelCenter); + GUI.Label(rect, Styles.LABEL_SCENE_ADDITIVE, styles.labelCenter); } else { GUI.Label(rect, styles.iconSceneSingle, styles.labelCenter); - GUI.Label(rect, LABEL_SCENE_SINGLE, styles.labelCenter); + GUI.Label(rect, Styles.LABEL_SCENE_SINGLE, styles.labelCenter); } if (tempIsAdditive != isScenePickerSetAsAdditive) @@ -211,17 +96,17 @@ namespace Module.NavigationTool.Editor.Toolbar } } - GUI.Label(rect, LABEL_SCENE_CREATE, styles.labelCenter); + GUI.Label(rect, Styles.LABEL_SCENE_CREATE, styles.labelCenter); } private static void ShowDropDown(Rect rect) { var menu = new GenericMenu(); - for (var i = 0; i < SCENE_NAMES.Length; i++) + for (var i = 0; i < SCENE_LIST.labels.Length; i++) { int sceneIndex = i; - menu.AddItem(new GUIContent(SCENE_NAMES[i]), SELECTED_INDICES.Contains(i), () => SelectScene(sceneIndex)); + menu.AddItem(SCENE_LIST.labels[i], SCENE_LIST.selected.Contains(i), () => SelectScene(sceneIndex)); } menu.DropDown(rect); @@ -231,30 +116,59 @@ namespace Module.NavigationTool.Editor.Toolbar { try { - string path = SCENE_PATHS[index]; - Scene scene = SceneManager.GetSceneByPath(path); + ScenePickerList.SceneElement scenes = SCENE_LIST.scenes[index]; bool isScenePickerSetAsAdditive = ToolbarScenePickerSettings.IsScenePickerSetAsAdditive; - - if (scene.isLoaded) - { - if (SceneManager.sceneCount == 1) - return; - EditorSceneManager.CloseScene(scene, true); - SELECTED_INDICES.Remove(index); - } - else if (isScenePickerSetAsAdditive) + for (var i = 0; i < scenes.paths.Count; i++) { - EditorSceneManager.OpenScene(SCENE_PATHS[index], OpenSceneMode.Additive); - SELECTED_INDICES.Add(index); + string path = scenes.paths[i]; + Scene scene = SceneManager.GetSceneByPath(path); + + if (scenes.isGroup) + { + if (isScenePickerSetAsAdditive || i != 0) + { + EditorSceneManager.OpenScene(path, OpenSceneMode.Additive); + int sceneIndex = SCENE_LIST.IndexOfPath(path, false); + + if (sceneIndex != -1) + SCENE_LIST.selected.Add(sceneIndex); + } + else + { + EditorSceneManager.OpenScene(path, OpenSceneMode.Single); + int sceneIndex = SCENE_LIST.IndexOfPath(path, false); + + SCENE_LIST.selected.Clear(); + + if (sceneIndex != -1) + SCENE_LIST.selected.Add(index); + } + } + else + { + if (scene.isLoaded) + { + if (SceneManager.sceneCount == 1) + return; + + EditorSceneManager.CloseScene(scene, true); + SCENE_LIST.selected.Remove(index); + } + else if (isScenePickerSetAsAdditive) + { + EditorSceneManager.OpenScene(path, OpenSceneMode.Additive); + SCENE_LIST.selected.Add(index); + } + else + { + EditorSceneManager.OpenScene(path, OpenSceneMode.Single); + SCENE_LIST.selected.Clear(); + SCENE_LIST.selected.Add(index); + } + } } - else - { - EditorSceneManager.OpenScene(SCENE_PATHS[index], OpenSceneMode.Single); - SELECTED_INDICES.Clear(); - SELECTED_INDICES.Add(index); - } - + RefreshSceneLabel(); } catch (Exception e) @@ -267,14 +181,14 @@ namespace Module.NavigationTool.Editor.Toolbar { STRING_BUILDER.Clear(); - if (SELECTED_INDICES.Count != 0) + if (SCENE_LIST.selected.Count != 0) { - for (var i = 0; i < SELECTED_INDICES.Count; i++) + for (var i = 0; i < SCENE_LIST.selected.Count; i++) { if (i > 0) STRING_BUILDER.Append(", "); - STRING_BUILDER.Append(SCENE_SHORT_NAMES[SELECTED_INDICES[i]]); + STRING_BUILDER.Append(SCENE_LIST.scenes[SCENE_LIST.selected[i]].shortname); } } else @@ -287,19 +201,20 @@ namespace Module.NavigationTool.Editor.Toolbar public override float CalculateWidth() { - return 100.0f + BUTTON_WIDTH * 2.0f; + return 100.0f + Styles.BUTTON_WIDTH * 2.0f; } public static void SetAsDirty() { IS_DIRTY = true; } - - private sealed class SceneSortElement + + private static class Styles { - public readonly List names = new List(); - public readonly List shortNames = new List(); - public readonly List paths = new List(); + public static readonly GUIContent LABEL_SCENE_ADDITIVE = new GUIContent(string.Empty, "Additive scene loading (toogle to Single)"); + public static readonly GUIContent LABEL_SCENE_SINGLE = new GUIContent(string.Empty, "Single scene loading (toggle to Additive)"); + public static readonly GUIContent LABEL_SCENE_CREATE = new GUIContent(string.Empty, "Create a new scene"); + public const float BUTTON_WIDTH = 24.0f; } } } \ No newline at end of file diff --git a/Editor/Toolbar/Utilities/ReordableList.meta b/Editor/Toolbar/Utilities/ReordableList.meta new file mode 100644 index 0000000..27e0bcc --- /dev/null +++ b/Editor/Toolbar/Utilities/ReordableList.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: cf2b6dd510df4e818247e29339e154bc +timeCreated: 1693333131 \ No newline at end of file diff --git a/Editor/Toolbar/Utilities/ReordableList/AbstractReordableListDrawer.cs b/Editor/Toolbar/Utilities/ReordableList/AbstractReordableListDrawer.cs new file mode 100644 index 0000000..e9b9254 --- /dev/null +++ b/Editor/Toolbar/Utilities/ReordableList/AbstractReordableListDrawer.cs @@ -0,0 +1,76 @@ +using System; +using System.Collections.Generic; +using UnityEditor; +using UnityEditorInternal; +using UnityEngine; + +namespace Module.NavigationTool.Editor.Toolbar +{ + internal abstract class AbstractReordableListDrawer + { + public readonly List list; + + private readonly ReorderableList reorderableList; + public event Action onChanged; + + public bool IsDirty { get; private set; } + + protected AbstractReordableListDrawer(List list, string header) + { + this.list = list; + + reorderableList = new ReorderableList(list, typeof(string), true, true, true, true); + reorderableList.drawElementCallback += (rect, index, isActive, isFocused) => + { + EditorGUI.BeginChangeCheck(); + OnDrawElement(rect, index, isActive, isFocused); + + if (EditorGUI.EndChangeCheck()) + IsDirty = true; + }; + reorderableList.drawHeaderCallback += rect => EditorGUI.LabelField(rect, header); + reorderableList.onAddCallback += _ => + { + OnAddElementToList(); + InvokeChanged(); + }; + reorderableList.onRemoveCallback += rl => + { + list.RemoveAt(rl.index); + OnRemovedElementFromList(rl.index); + InvokeChanged(); + }; + reorderableList.onReorderCallback += _ => InvokeChanged();; + reorderableList.elementHeightCallback += OnElementHeight; + } + + public void DoList(Rect rect) + { + IsDirty = false; + reorderableList.DoList(rect); + } + + public void DoLayoutList() + { + IsDirty = false; + reorderableList.DoLayoutList(); + } + + protected abstract void OnDrawElement(Rect rect, int index, bool isActive, bool isFocused); + protected abstract void OnAddElementToList(); + + protected virtual void OnRemovedElementFromList(int index) + { + } + + protected virtual float OnElementHeight(int index) + { + return EditorGUIUtility.singleLineHeight; + } + + protected void InvokeChanged() + { + onChanged?.Invoke(); + } + } +} \ No newline at end of file diff --git a/Editor/Toolbar/Utilities/ReordableList/AbstractReordableListDrawer.cs.meta b/Editor/Toolbar/Utilities/ReordableList/AbstractReordableListDrawer.cs.meta new file mode 100644 index 0000000..df5f144 --- /dev/null +++ b/Editor/Toolbar/Utilities/ReordableList/AbstractReordableListDrawer.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: ad769ac53dd3476b82e6a2b62117c2d3 +timeCreated: 1693332886 \ No newline at end of file diff --git a/Editor/Toolbar/Utilities/ReordableList/SceneGroupReordableListDrawer.cs b/Editor/Toolbar/Utilities/ReordableList/SceneGroupReordableListDrawer.cs new file mode 100644 index 0000000..072375e --- /dev/null +++ b/Editor/Toolbar/Utilities/ReordableList/SceneGroupReordableListDrawer.cs @@ -0,0 +1,81 @@ +using System.Collections.Generic; +using UnityEditor; +using UnityEngine; + +namespace Module.NavigationTool.Editor.Toolbar +{ + internal sealed class SceneGroupReordableListDrawer : AbstractReordableListDrawer + { + private readonly List elements = new List(); + + public SceneGroupReordableListDrawer(List list, string header) + : base(list, header) + { + for (var i = 0; i < list.Count; i++) + { + elements.Add(new StringReordableListDrawer(list[i].filters, "Filters")); + } + } + + protected override void OnDrawElement(Rect rect, int index, bool isActive, bool isFocused) + { + rect.height -= 2; + rect.y += 1; + + SceneGroup group = list[index]; + var rectName = new Rect(rect.x, rect.y, rect.width, EditorGUIUtility.singleLineHeight); + var rectType = new Rect(rect.x, rectName.yMax + 2f, rect.width, EditorGUIUtility.singleLineHeight); + var rectOptional = new Rect(rect.x, rectType.yMax + 2f, rect.width - 80f, EditorGUIUtility.singleLineHeight); + var rectOptionalBtn = new Rect(rectOptional.xMax, rectType.yMax + 2f, 80f, EditorGUIUtility.singleLineHeight); + var rectLabels = new Rect(rect.x, rectOptional.yMax + 2f, rect.width, rect.height - (rectName.y - rectOptional.yMax) - 4f); + + EditorGUI.BeginChangeCheck(); + group.name = EditorGUI.TextField(rectName, "Name", group.name); + group.optionalMainScenePath = EditorGUI.TextField(rectOptional, "Optional Main Scene Path", group.optionalMainScenePath); + + if (GUI.Button(rectOptionalBtn, "Find")) + { + string mainScenePath = EditorUtility.OpenFilePanel("Scene", "Assets", "unity"); + + if (!string.IsNullOrEmpty(mainScenePath)) + { + mainScenePath = mainScenePath.Substring(Application.dataPath.Length - 6); + group.optionalMainScenePath = mainScenePath; + } + } + + group.filterType = (ESceneGroupFilterType)EditorGUI.EnumPopup(rectType, "Filter Type", group.filterType); + elements[index].DoList(rectLabels); + + if (EditorGUI.EndChangeCheck()) + InvokeChanged(); + } + + protected override void OnAddElementToList() + { + var filters = new List(); + + list.Add(new SceneGroup + { + name = "New Scene Group", + filters = filters + }); + + elements.Add(new StringReordableListDrawer(filters, "Filters")); + } + + protected override void OnRemovedElementFromList(int index) + { + elements.RemoveAt(index); + } + + protected override float OnElementHeight(int index) + { + int labelCount = list[index].filters.Count; + + return base.OnElementHeight(index) * 3f + + Mathf.Max(0, labelCount - 1) * (EditorGUIUtility.singleLineHeight + 2f) + + 78f; + } + } +} \ No newline at end of file diff --git a/Editor/Toolbar/Utilities/ReordableList/SceneGroupReordableListDrawer.cs.meta b/Editor/Toolbar/Utilities/ReordableList/SceneGroupReordableListDrawer.cs.meta new file mode 100644 index 0000000..d947680 --- /dev/null +++ b/Editor/Toolbar/Utilities/ReordableList/SceneGroupReordableListDrawer.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 4923054c7113444ab1b696d769cdae00 +timeCreated: 1693333828 \ No newline at end of file diff --git a/Editor/Toolbar/Utilities/ReordableList/StringReordableListDrawer.cs b/Editor/Toolbar/Utilities/ReordableList/StringReordableListDrawer.cs new file mode 100644 index 0000000..1bba6f5 --- /dev/null +++ b/Editor/Toolbar/Utilities/ReordableList/StringReordableListDrawer.cs @@ -0,0 +1,35 @@ +using System; +using System.Collections.Generic; +using UnityEditor; +using UnityEngine; + +namespace Module.NavigationTool.Editor.Toolbar +{ + internal sealed class StringReordableListDrawer : AbstractReordableListDrawer + { + public StringReordableListDrawer(List list, string header) + : base(list, header) + { + } + + protected override void OnDrawElement(Rect rect, int index, bool isActive, bool isFocused) + { + rect.height -= 2; + rect.y += 1; + + string text = list[index]; + string temp = EditorGUI.TextField(rect, text); + + if (string.Equals(text, temp, StringComparison.Ordinal)) + return; + + list[index] = temp; + InvokeChanged(); + } + + protected override void OnAddElementToList() + { + list.Add(string.Empty); + } + } +} \ No newline at end of file diff --git a/Editor/Toolbar/Utilities/ReordableList/StringReordableListDrawer.cs.meta b/Editor/Toolbar/Utilities/ReordableList/StringReordableListDrawer.cs.meta new file mode 100644 index 0000000..0ef9e2b --- /dev/null +++ b/Editor/Toolbar/Utilities/ReordableList/StringReordableListDrawer.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: e4b2250a66d548f1aacb916c7b5b6204 +timeCreated: 1693333142 \ No newline at end of file diff --git a/Editor/Toolbar/Utilities/ToolbarSettingsUtility.cs b/Editor/Toolbar/Utilities/ToolbarSettingsUtility.cs index 788a0fe..4299214 100644 --- a/Editor/Toolbar/Utilities/ToolbarSettingsUtility.cs +++ b/Editor/Toolbar/Utilities/ToolbarSettingsUtility.cs @@ -7,7 +7,7 @@ namespace Module.NavigationTool.Editor.Toolbar { internal static class ToolbarSettingsUtility { - public static IToolbarSettings[] GetAllSettings() + public static IToolbarSettings[] GetAllUserSettings() { var list = new List(8); @@ -43,5 +43,42 @@ namespace Module.NavigationTool.Editor.Toolbar return list.ToArray(); } + + public static IToolbarProjectSettings[] GetAllProjectSettings(ToolbarProjectSettings settings) + { + var list = new List(8); + + try + { + Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies(); + Type iType = typeof(IToolbarProjectSettings); + + for (var i = 0; i < assemblies.Length; i++) + { + Assembly assembly = assemblies[i]; + Type[] types = assembly.GetTypes(); + + for (var j = 0; j < types.Length; j++) + { + Type type = types[j]; + + if (type.IsInterface || type.IsAbstract || !iType.IsAssignableFrom(type)) + continue; + + var toolbar = (IToolbarProjectSettings)FormatterServices.GetUninitializedObject(type); + toolbar.Initialize(settings); + list.Add(toolbar); + } + } + + list.Sort((s0, s1) => string.Compare(s0.Title, s1.Title, StringComparison.Ordinal)); + } + catch (Exception) + { + // Fail silently + } + + return list.ToArray(); + } } } \ No newline at end of file