private static void DrawOpenSubScenes(SubScene[] subScenes)
        {
            int numOpen = 0;

            for (int i = 0; i < subScenes.Length; i++)
            {
                if (subScenes[i].IsLoaded)
                {
                    numOpen++;
                }
            }

            if (numOpen > 0)
            {
                GUILayout.Space(EditorGUIUtility.singleLineHeight);
                GUILayout.BeginHorizontal();
                GUILayout.Label(Content.OpenSubScenesLabel, EditorStyles.boldLabel);
                GUILayout.FlexibleSpace();
                GUILayout.Label($"{numOpen}");
                GUILayout.EndHorizontal();

                for (int i = 0; i < subScenes.Length; i++)
                {
                    var scene = subScenes[i];
                    if (!scene.IsLoaded)
                    {
                        continue;
                    }

                    s_TmpContent.text    = scene.SceneName;
                    s_TmpContent.tooltip = scene.EditableScenePath;
                    var buttonRect = DrawButtonGridLabelAndGetFirstButtonRect(s_TmpContent, 3, out var spacing);

                    // add empty space space so buttons are right-aligned
                    buttonRect.x += buttonRect.width + spacing;
                    using (new EditorGUI.DisabledScope(!scene.EditingScene.isDirty))
                    {
                        if (GUI.Button(buttonRect, Content.SaveLabel))
                        {
                            SubSceneInspectorUtility.SaveScene(scene);
                        }
                    }
                    buttonRect.x += buttonRect.width + spacing;
                    if (GUI.Button(buttonRect, Content.CloseLabel))
                    {
                        SubSceneInspectorUtility.CloseAndAskSaveIfUserWantsTo(scene);
                    }
                }
            }
        }
 static void DrawSubsceneBounds(SubScene scene, GizmoType gizmoType)
 {
     SubSceneInspectorUtility.DrawSubsceneBounds(scene);
 }
        Bounds OnGetFrameBounds()
        {
            AABB aabb = SubSceneInspectorUtility.GetActiveWorldMinMax(World.DefaultGameObjectInjectionWorld, targets);

            return(new Bounds(aabb.Center, aabb.Size));
        }
 // Invoked by Unity magically for FrameSelect command.
 // Frames the whole sub scene in scene view
 bool HasFrameBounds()
 {
     return(!SubSceneInspectorUtility.GetActiveWorldMinMax(World.DefaultGameObjectInjectionWorld, targets).Equals(MinMaxAABB.Empty));
 }
        public override void OnInspectorGUI()
        {
            var subScene = target as SubScene;

            if (!subScene.IsInMainStage())
            {
                // In Prefab Mode and when selecting a Prefab Asset in the Project Browser we only show the inspector of data of the
                // SubScene, and not the load/unload/edit/close buttons.
                base.OnInspectorGUI();

                EditorGUILayout.HelpBox($"Only Sub Scenes in the Main Stage can be loaded and unloaded.", MessageType.Info, true);
                EditorGUILayout.Space();
                return;
            }

            var prevColor = subScene.HierarchyColor;

            CachePreviousSceneAssetReferences();

            base.OnInspectorGUI();

            HandleChangedSceneAssetReferences();

            if (subScene.HierarchyColor != prevColor)
            {
                SceneHierarchyHooks.ReloadAllSceneHierarchies();
            }

            var targetsArray = targets;
            var subscenes    = new SubScene[targetsArray.Length];

            targetsArray.CopyTo(subscenes, 0);

            GUILayout.BeginHorizontal();
            if (!SubSceneInspectorUtility.IsEditingAll(subscenes))
            {
                GUI.enabled = SubSceneInspectorUtility.CanEditScene(subscenes);
                if (GUILayout.Button("Edit"))
                {
                    SubSceneInspectorUtility.EditScene(subscenes);
                }
            }
            else
            {
                GUI.enabled = true;
                if (GUILayout.Button("Close"))
                {
                    SubSceneInspectorUtility.CloseAndAskSaveIfUserWantsTo(subscenes);
                }
            }

            GUI.enabled = SubSceneInspectorUtility.IsDirty(subscenes);
            if (GUILayout.Button("Save"))
            {
                SubSceneInspectorUtility.SaveScene(subscenes);
            }
            GUI.enabled = true;

            GUILayout.EndHorizontal();

            var scenes = SubSceneInspectorUtility.GetLoadableScenes(subscenes);

            GUILayout.Space(10);

            if (World.DefaultGameObjectInjectionWorld != null)
            {
                var entityManager = World.DefaultGameObjectInjectionWorld.EntityManager;

                foreach (var scene in scenes)
                {
                    if (!entityManager.HasComponent <RequestSceneLoaded>(scene.Scene))
                    {
                        if (GUILayout.Button($"Load '{scene.Name}'"))
                        {
                            entityManager.AddComponentData(scene.Scene, new RequestSceneLoaded());
                            EditorUpdateUtility.EditModeQueuePlayerLoopUpdate();
                        }
                    }
                    else
                    {
                        if (GUILayout.Button($"Unload '{scene.Name}'"))
                        {
                            entityManager.RemoveComponent <RequestSceneLoaded>(scene.Scene);
                            EditorUpdateUtility.EditModeQueuePlayerLoopUpdate();
                        }
                    }
                }
            }

    #if false
            // @TODO: TEMP for debugging
            if (GUILayout.Button("ClearWorld"))
            {
                World.DisposeAllWorlds();
                DefaultWorldInitialization.Initialize("Default World", !Application.isPlaying);

                var scenes = FindObjectsOfType <SubScene>();
                foreach (var scene in scenes)
                {
                    var oldEnabled = scene.enabled;
                    scene.enabled = false;
                    scene.enabled = oldEnabled;
                }

                EditorUpdateUtility.EditModeQueuePlayerLoopUpdate();
            }
    #endif

            bool hasDuplicates = subScene.SceneAsset != null && (SubScene.AllSubScenes.Count(s => (s.SceneAsset == subScene.SceneAsset)) > 1);
            if (hasDuplicates)
            {
                EditorGUILayout.HelpBox($"The Scene Asset '{subScene.EditableScenePath}' is used mutiple times and this is not supported. Clear the reference.", MessageType.Warning, true);
                if (GUILayout.Button("Clear"))
                {
                    subScene.SceneAsset = null;
                    SceneHierarchyHooks.ReloadAllSceneHierarchies();
                }
                EditorGUILayout.Space();
            }

            var uncleanHierarchyObject = SubSceneInspectorUtility.GetUncleanHierarchyObject(subscenes);
            if (uncleanHierarchyObject != null)
            {
                EditorGUILayout.HelpBox($"Scene transform values are not applied to scenes child transforms. But {uncleanHierarchyObject.name} has an offset Transform.", MessageType.Warning, true);
                if (GUILayout.Button("Clear"))
                {
                    foreach (var scene in subscenes)
                    {
                        scene.transform.localPosition = Vector3.zero;
                        scene.transform.localRotation = Quaternion.identity;
                        scene.transform.localScale    = Vector3.one;
                    }
                }
                EditorGUILayout.Space();
            }
            if (SubSceneInspectorUtility.HasChildren(subscenes))
            {
                EditorGUILayout.HelpBox($"SubScenes can not have child game objects. Close the scene and delete the child game objects.", MessageType.Warning, true);
            }

            GUILayout.Space(10);
            if (CheckConversionLog(subScene))
            {
                GUILayout.Label("Importing...");
                Repaint();
            }
            else
            {
                if (!SubSceneInspectorUtility.IsEditingAll(subscenes))
                {
                    if (GUILayout.Button("Reimport"))
                    {
                        SubSceneInspectorUtility.ForceReimport(subscenes);
                    }
                }
            }
            if (m_ConversionLog.Length != 0)
            {
                GUILayout.Space(10);

                GUILayout.Label("Conversion Log");
                GUILayout.TextArea(m_ConversionLog);
            }
        }
        public override void OnInspectorGUI()
        {
            var subScene = target as SubScene;

            var prevSceneAsset = subScene.SceneAsset;
            var prevColor      = subScene.HierarchyColor;

            base.OnInspectorGUI();

            if (subScene.SceneAsset != prevSceneAsset || subScene.HierarchyColor != prevColor)
            {
                SceneHierarchyHooks.ReloadAllSceneHierarchies();
            }

            var targetsArray = targets;
            var subscenes    = new SubScene[targetsArray.Length];

            targetsArray.CopyTo(subscenes, 0);


            EditorGUILayout.TextArea("", GUI.skin.horizontalSlider);

            GUILayout.BeginHorizontal();
            if (!SubSceneInspectorUtility.IsEditingAll(subscenes))
            {
                GUI.enabled = SubSceneInspectorUtility.CanEditScene(subscenes);
                if (GUILayout.Button("Edit"))
                {
                    SubSceneInspectorUtility.EditScene(subscenes);
                }
            }
            else
            {
                GUI.enabled = true;
                if (GUILayout.Button("Close"))
                {
                    SubSceneInspectorUtility.CloseAndAskSaveIfUserWantsTo(subscenes);
                }
            }


            GUI.enabled = SubSceneInspectorUtility.IsDirty(subscenes);
            if (GUILayout.Button("Save"))
            {
                SubSceneInspectorUtility.SaveScene(subscenes);
            }
            GUI.enabled = true;

            GUILayout.EndHorizontal();

            var scenes = SubSceneInspectorUtility.GetLoadableScenes(subscenes);

            EditorGUILayout.TextArea("", GUI.skin.horizontalSlider);

            GUILayout.Space(10);

            if (World.DefaultGameObjectInjectionWorld != null)
            {
                var entityManager = World.DefaultGameObjectInjectionWorld.EntityManager;

                foreach (var scene in scenes)
                {
                    if (!entityManager.HasComponent <RequestSceneLoaded>(scene.Scene))
                    {
                        if (GUILayout.Button($"Load '{scene.Name}'"))
                        {
                            entityManager.AddComponentData(scene.Scene, new RequestSceneLoaded());
                            EditorUpdateUtility.EditModeQueuePlayerLoopUpdate();
                        }
                    }
                    else
                    {
                        if (GUILayout.Button($"Unload '{scene.Name}'"))
                        {
                            entityManager.RemoveComponent <RequestSceneLoaded>(scene.Scene);
                            EditorUpdateUtility.EditModeQueuePlayerLoopUpdate();
                        }
                    }
                }
            }


    #if false
            // @TODO: TEMP for debugging
            if (GUILayout.Button("ClearWorld"))
            {
                World.DisposeAllWorlds();
                DefaultWorldInitialization.Initialize("Default World", !Application.isPlaying);

                var scenes = FindObjectsOfType <SubScene>();
                foreach (var scene in scenes)
                {
                    var oldEnabled = scene.enabled;
                    scene.enabled = false;
                    scene.enabled = oldEnabled;
                }

                EditorUpdateUtility.EditModeQueuePlayerLoopUpdate();
            }
    #endif

            var uncleanHierarchyObject = SubSceneInspectorUtility.GetUncleanHierarchyObject(subscenes);
            if (uncleanHierarchyObject != null)
            {
                EditorGUILayout.HelpBox($"Scene transform values are not applied to scenes child transforms. But {uncleanHierarchyObject.name} has an offset Transform.", MessageType.Warning, true);
                if (GUILayout.Button("Clear"))
                {
                    foreach (var scene in subscenes)
                    {
                        scene.transform.localPosition = Vector3.zero;
                        scene.transform.localRotation = Quaternion.identity;
                        scene.transform.localScale    = Vector3.one;
                    }
                }
            }
            if (SubSceneInspectorUtility.HasChildren(subscenes))
            {
                EditorGUILayout.HelpBox($"SubScenes can not have child game objects. Close the scene and delete the child game objects.", MessageType.Warning, true);
            }

            if (CheckConversionLog(subScene))
            {
                GUILayout.Space(10);
                GUILayout.Label("Importing...");
                Repaint();
            }
            if (m_ConversionLog.Length != 0)
            {
                GUILayout.Space(10);

                GUILayout.Label("Conversion Log");
                GUILayout.TextArea(m_ConversionLog);
            }
        }
        public override void OnInspectorGUI()
        {
            var subScene = target as SubScene;

            if (!subScene.IsInMainStage())
            {
                // In Prefab Mode and when selecting a Prefab Asset in the Project Browser we only show the inspector of data of the
                // SubScene, and not the load/unload/edit/close buttons.
                base.OnInspectorGUI();

                EditorGUILayout.HelpBox($"Only Sub Scenes in the Main Stage can be loaded and unloaded.", MessageType.Info, true);
                EditorGUILayout.Space();
                return;
            }

            var prevColor = subScene.HierarchyColor;

            CachePreviousSceneAssetReferences();

            base.OnInspectorGUI();

            HandleChangedSceneAssetReferences();

            if (subScene.HierarchyColor != prevColor)
            {
                SceneHierarchyHooks.ReloadAllSceneHierarchies();
            }

            DrawOpenSubScenes(_selectedSubscenes);
            var loadableScenes = SubSceneInspectorUtility.GetLoadableScenes(_selectedSubscenes);

            if (DrawClosedSubScenes(loadableScenes, _selectedSubscenes))
            {
                Repaint();
            }

#if false
            // @TODO: TEMP for debugging
            if (GUILayout.Button("ClearWorld"))
            {
                World.DisposeAllWorlds();
                DefaultWorldInitialization.Initialize("Default World", !Application.isPlaying);

                var scenes = FindObjectsOfType <SubScene>();
                foreach (var scene in scenes)
                {
                    var oldEnabled = scene.enabled;
                    scene.enabled = false;
                    scene.enabled = oldEnabled;
                }

                EditorUpdateUtility.EditModeQueuePlayerLoopUpdate();
            }
    #endif

            bool hasDuplicates = subScene.SceneAsset != null && (SubScene.AllSubScenes.Count(s => (s.SceneAsset == subScene.SceneAsset)) > 1);
            if (hasDuplicates)
            {
                EditorGUILayout.HelpBox($"The Scene Asset '{subScene.EditableScenePath}' is used mutiple times and this is not supported. Clear the reference.", MessageType.Warning, true);
                if (GUILayout.Button("Clear"))
                {
                    subScene.SceneAsset = null;
                    SceneHierarchyHooks.ReloadAllSceneHierarchies();
                }
                EditorGUILayout.Space();
            }

            var uncleanHierarchyObject = SubSceneInspectorUtility.GetUncleanHierarchyObject(_selectedSubscenes);
            if (uncleanHierarchyObject != null)
            {
                EditorGUILayout.HelpBox($"Scene transform values are not applied to scenes child transforms. But {uncleanHierarchyObject.name} has an offset Transform.", MessageType.Warning, true);
                if (GUILayout.Button("Clear"))
                {
                    foreach (var scene in _selectedSubscenes)
                    {
                        scene.transform.localPosition = Vector3.zero;
                        scene.transform.localRotation = Quaternion.identity;
                        scene.transform.localScale    = Vector3.one;
                    }
                }
                EditorGUILayout.Space();
            }
            if (SubSceneInspectorUtility.HasChildren(_selectedSubscenes))
            {
                EditorGUILayout.HelpBox($"SubScenes can not have child game objects. Close the scene and delete the child game objects.", MessageType.Warning, true);
            }

            if (targets.Length == 1)
            {
                GUILayout.Space(EditorGUIUtility.singleLineHeight);
                if (CheckConversionLog(subScene))
                {
                    GUILayout.Label("Importing...");
                    Repaint();
                }

                if (m_ConversionLog.Length != 0)
                {
                    GUILayout.Space(EditorGUIUtility.singleLineHeight);

                    GUILayout.Label("Conversion Log", EditorStyles.boldLabel);
                    GUILayout.TextArea(m_ConversionLog);
                }
            }
        }
        private static bool DrawClosedSubScenes(SubSceneInspectorUtility.LoadableScene[] loadableScenes, SubScene[] subscenes)
        {
            if (World.DefaultGameObjectInjectionWorld != null && loadableScenes.Length != 0)
            {
                GUILayout.Space(EditorGUIUtility.singleLineHeight);
                var entityManager = World.DefaultGameObjectInjectionWorld.EntityManager;

                {
                    int numScenesLoaded   = 0;
                    int numScenesImported = 0;
                    foreach (var scene in loadableScenes)
                    {
                        if (entityManager.HasComponent <RequestSceneLoaded>(scene.Scene))
                        {
                            numScenesLoaded++;
                        }
                        if (IsSubsceneImported(scene.SubScene))
                        {
                            numScenesImported++;
                        }
                    }

                    if (EditorGUIUtility.wideMode)
                    {
                        GUILayout.BeginHorizontal();
                        GUILayout.Label(Content.ClosedSubScenesLabel, EditorStyles.boldLabel);
                        GUILayout.FlexibleSpace();
                        GUILayout.Label(string.Format(Content.ClosedStatusString, numScenesLoaded, loadableScenes.Length, numScenesImported));
                        GUILayout.EndHorizontal();
                    }
                    else
                    {
                        GUILayout.Label(Content.ClosedSubScenesLabel, EditorStyles.boldLabel);
                        GUILayout.BeginHorizontal();
                        GUILayout.FlexibleSpace();
                        GUILayout.Label(string.Format(Content.ClosedStatusString, numScenesLoaded, loadableScenes.Length, numScenesImported));
                        GUILayout.EndHorizontal();
                    }
                }

                if (loadableScenes.Length > 1)
                {
                    GUILayout.BeginHorizontal();
                    bool reimportRequested = GUILayout.Button(Content.ReimportAllLabel);

                    if (GUILayout.Button(Content.LoadAllLabel))
                    {
                        foreach (var scene in loadableScenes)
                        {
                            if (!entityManager.HasComponent <RequestSceneLoaded>(scene.Scene))
                            {
                                entityManager.AddComponentData(scene.Scene, new RequestSceneLoaded());
                            }
                        }

                        EditorUpdateUtility.EditModeQueuePlayerLoopUpdate();
                    }

                    if (GUILayout.Button(Content.UnloadAllLabel))
                    {
                        foreach (var scene in loadableScenes)
                        {
                            if (entityManager.HasComponent <RequestSceneLoaded>(scene.Scene))
                            {
                                entityManager.RemoveComponent <RequestSceneLoaded>(scene.Scene);
                            }
                        }
                        EditorUpdateUtility.EditModeQueuePlayerLoopUpdate();
                    }

                    GUILayout.EndHorizontal();

                    if (reimportRequested && EditorUtility.DisplayDialog(Content.ReimportAllSubScenes, Content.ReimportAllSubScenesDetails, Content.Yes, Content.No))
                    {
                        SubSceneInspectorUtility.ForceReimport(subscenes);
                    }

                    GUILayout.Space(EditorGUIUtility.standardVerticalSpacing);
                }

                bool needsRepaint = false;
                foreach (var scene in loadableScenes)
                {
                    s_TmpContent.text    = scene.Name;
                    s_TmpContent.tooltip = scene.SubScene.EditableScenePath;

                    var buttonRect = DrawButtonGridLabelAndGetFirstButtonRect(s_TmpContent, 3, out var spacing);

                    if (!IsSubsceneImported(scene.SubScene))
                    {
                        GUI.Label(buttonRect, Content.ImportingLabel);
                        needsRepaint = true;
                    }
                    else if (GUI.Button(buttonRect, Content.ReimportLabel))
                    {
                        SubSceneInspectorUtility.ForceReimport(scene.SubScene);
                    }

                    buttonRect.x += buttonRect.width + spacing;
                    if (!entityManager.HasComponent <RequestSceneLoaded>(scene.Scene))
                    {
                        if (GUI.Button(buttonRect, Content.LoadLabel))
                        {
                            entityManager.AddComponentData(scene.Scene, new RequestSceneLoaded());
                            EditorUpdateUtility.EditModeQueuePlayerLoopUpdate();
                        }
                    }
                    else
                    {
                        if (GUI.Button(buttonRect, Content.UnloadLabel))
                        {
                            entityManager.RemoveComponent <RequestSceneLoaded>(scene.Scene);
                            EditorUpdateUtility.EditModeQueuePlayerLoopUpdate();
                        }
                    }

                    buttonRect.x += buttonRect.width + spacing;
                    using (new EditorGUI.DisabledScope(!SubSceneInspectorUtility.CanEditScene(scene.SubScene)))
                    {
                        if (GUI.Button(buttonRect, Content.OpenLabel))
                        {
                            SubSceneInspectorUtility.EditScene(scene.SubScene);
                        }
                    }
                }

                return(needsRepaint);
            }

            return(false);
        }