using System; using System.Text; using JetBrains.Annotations; using UnityEditor; using UnityEditor.SceneManagement; using UnityEngine; using UnityEngine.SceneManagement; namespace Module.NavigationTool.Editor.Toolbar { [UsedImplicitly] internal sealed class ToolScenePicker : AbstractToolbarDrawer { public override bool Visible => ToolbarScenePickerSettings.IsSceneEnabled; public override bool Enabled => !EditorApplication.isPlaying && !EditorApplication.isPlayingOrWillChangePlaymode; public override EToolbarPlacement Placement => EToolbarPlacement.Right; public override int Priority => (int)EToolbarPriority.Medium; 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; SCENE_LIST.Refresh(); RefreshSceneLabel(); IS_DIRTY = false; } public override void Update() { Initialize(); } protected override void Draw(Rect rect) { Initialize(); 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); } private void DrawSceneDropDown(Rect rect) { if (GUI.Button(rect, SCENE_LABEL, styles.popup)) ShowDropDown(rect); } private void DrawSceneLoadToggle(Rect rect) { bool isScenePickerSetAsAdditive = ToolbarScenePickerSettings.IsScenePickerSetAsAdditive; bool tempIsAdditive = EditorGUI.Toggle(rect, isScenePickerSetAsAdditive, styles.button); if (tempIsAdditive) { #if !UNITY_6000_0_OR_NEWER GUI.Label(rect, styles.iconSceneAdditive, styles.labelCenter); #endif GUI.Label(rect, Styles.LABEL_SCENE_ADDITIVE, styles.labelCenter); } else { #if !UNITY_6000_0_OR_NEWER GUI.Label(rect, styles.iconSceneSingle, styles.labelCenter); #endif GUI.Label(rect, Styles.LABEL_SCENE_SINGLE, styles.labelCenter); } if (tempIsAdditive != isScenePickerSetAsAdditive) ToolbarScenePickerSettings.IsScenePickerSetAsAdditive = tempIsAdditive; } private void DrawSceneAddButton(Rect rect) { if (GUI.Button(rect, styles.iconPlusSmall, styles.button)) { try { int selection = EditorUtility.DisplayDialogComplex("Create new scene", "How do you want to add the scene?", "Single", "Additive", "Cancel"); if (selection == 2) return; Scene scene = EditorSceneManager.NewScene(NewSceneSetup.EmptyScene, selection == 0 ? NewSceneMode.Single : NewSceneMode.Additive); if (EditorUtility.DisplayDialog("Create new scene", "Save scene to disk?", "Yes", "No")) EditorSceneManager.SaveScene(scene); } catch (Exception e) { EditorUtility.DisplayDialog("Failed to add scene", e.Message, "Ok"); } } 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_LIST.labels.Length; i++) { int sceneIndex = i; menu.AddItem(SCENE_LIST.labels[i], SCENE_LIST.selected.Contains(i), () => SelectScene(sceneIndex)); } menu.DropDown(rect); } private static void SelectScene(int index) { try { if (!EditorSceneManager.SaveCurrentModifiedScenesIfUserWantsTo()) return; ScenePickerList.SceneElement scenes = SCENE_LIST.scenes[index]; bool isScenePickerSetAsAdditive = ToolbarScenePickerSettings.IsScenePickerSetAsAdditive; for (var i = 0; i < scenes.paths.Count; i++) { 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); } } } RefreshSceneLabel(); } catch (Exception e) { Debug.LogException(e); } } private static void RefreshSceneLabel() { STRING_BUILDER.Clear(); if (SCENE_LIST.selected.Count != 0) { for (var i = 0; i < SCENE_LIST.selected.Count; i++) { if (i > 0) STRING_BUILDER.Append(", "); STRING_BUILDER.Append(SCENE_LIST.scenes[SCENE_LIST.selected[i]].shortname); } } else { STRING_BUILDER.Append("Unsaved scene(s)"); } SCENE_LABEL = STRING_BUILDER.ToString(); } public override float CalculateWidth() { return 100.0f + Styles.BUTTON_WIDTH * 2.0f; } public static void SetAsDirty() { IS_DIRTY = true; } private static class Styles { #if UNITY_6000_0_OR_NEWER public static readonly GUIContent LABEL_SCENE_ADDITIVE = new GUIContent("A", "Additive scene loading (toogle to Single)"); public static readonly GUIContent LABEL_SCENE_SINGLE = new GUIContent("S", "Single scene loading (toggle to Additive)"); #else 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)"); #endif public static readonly GUIContent LABEL_SCENE_CREATE = new GUIContent(string.Empty, "Create a new scene"); public const float BUTTON_WIDTH = 24.0f; } } }