Skip to content
This repository was archived by the owner on May 9, 2023. It is now read-only.

Commit 36f23b7

Browse files
committed
Move SceneHandler.cs
1 parent b51b743 commit 36f23b7

File tree

1 file changed

+177
-0
lines changed

1 file changed

+177
-0
lines changed
Lines changed: 177 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,177 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Collections.ObjectModel;
4+
using System.Linq;
5+
using System.Text;
6+
using UnityEngine;
7+
using UnityEngine.SceneManagement;
8+
9+
namespace UnityExplorer.UI.ObjectExplorer
10+
{
11+
public static class SceneHandler
12+
{
13+
/// <summary>
14+
/// The currently inspected Scene.
15+
/// </summary>
16+
public static Scene? SelectedScene
17+
{
18+
get => m_selectedScene;
19+
internal set
20+
{
21+
if (m_selectedScene != null && m_selectedScene?.handle == value?.handle)
22+
return;
23+
m_selectedScene = value;
24+
OnInspectedSceneChanged?.Invoke((Scene)m_selectedScene);
25+
}
26+
}
27+
private static Scene? m_selectedScene;
28+
29+
/// <summary>
30+
/// The GameObjects in the currently inspected scene.
31+
/// </summary>
32+
public static ReadOnlyCollection<GameObject> CurrentRootObjects => new ReadOnlyCollection<GameObject>(rootObjects);
33+
private static GameObject[] rootObjects = new GameObject[0];
34+
35+
/// <summary>
36+
/// All currently loaded Scenes.
37+
/// </summary>
38+
public static ReadOnlyCollection<Scene> LoadedScenes => new ReadOnlyCollection<Scene>(allLoadedScenes);
39+
private static readonly List<Scene> allLoadedScenes = new List<Scene>();
40+
41+
/// <summary>
42+
/// The names of all scenes in the build settings, if they could be retrieved.
43+
/// </summary>
44+
public static ReadOnlyCollection<string> AllSceneNames => new ReadOnlyCollection<string>(allScenesInBuild);
45+
private static readonly List<string> allScenesInBuild = new List<string>();
46+
47+
/// <summary>
48+
/// Whether or not we successfuly retrieved the names of the scenes in the build settings.
49+
/// </summary>
50+
public static bool WasAbleToGetScenesInBuild => gotAllScenesInBuild;
51+
private static bool gotAllScenesInBuild = true;
52+
53+
/// <summary>
54+
/// Invoked when the currently inspected Scene changes. The argument is the new scene.
55+
/// </summary>
56+
public static event Action<Scene> OnInspectedSceneChanged;
57+
58+
/// <summary>
59+
/// Invoked whenever the list of currently loaded Scenes changes. The argument contains all loaded scenes after the change.
60+
/// </summary>
61+
public static event Action<ReadOnlyCollection<Scene>> OnLoadedScenesChanged;
62+
63+
/// <summary>
64+
/// Equivalent to <see cref="SceneManager.sceneCount"/> + 2, to include 'DontDestroyOnLoad'.
65+
/// </summary>
66+
public static int LoadedSceneCount => SceneManager.sceneCount + 2;
67+
68+
internal static Scene DontDestroyScene => DontDestroyMe.scene;
69+
internal static int DontDestroyHandle => DontDestroyScene.handle;
70+
71+
internal static GameObject DontDestroyMe
72+
{
73+
get
74+
{
75+
if (!dontDestroyObject)
76+
{
77+
dontDestroyObject = new GameObject("DontDestroyMe");
78+
GameObject.DontDestroyOnLoad(dontDestroyObject);
79+
}
80+
return dontDestroyObject;
81+
}
82+
}
83+
private static GameObject dontDestroyObject;
84+
85+
public static bool InspectingAssetScene => !SelectedScene?.IsValid() ?? false;
86+
87+
internal static void Init()
88+
{
89+
// Try to get all scenes in the build settings. This may not work.
90+
try
91+
{
92+
Type sceneUtil = ReflectionUtility.GetTypeByName("UnityEngine.SceneManagement.SceneUtility");
93+
if (sceneUtil == null)
94+
throw new Exception("This version of Unity does not ship with the 'SceneUtility' class, or it was not unstripped.");
95+
96+
var method = sceneUtil.GetMethod("GetScenePathByBuildIndex", ReflectionUtility.FLAGS);
97+
int sceneCount = SceneManager.sceneCountInBuildSettings;
98+
for (int i = 0; i < sceneCount; i++)
99+
{
100+
var scenePath = (string)method.Invoke(null, new object[] { i });
101+
allScenesInBuild.Add(scenePath);
102+
}
103+
}
104+
catch (Exception ex)
105+
{
106+
gotAllScenesInBuild = false;
107+
ExplorerCore.LogWarning($"Unable to generate list of all Scenes in the build: {ex}");
108+
}
109+
}
110+
111+
internal static void Update()
112+
{
113+
int curHandle = SelectedScene?.handle ?? -1;
114+
// DontDestroyOnLoad always exists, so default to true if our curHandle is that handle.
115+
// otherwise we will check while iterating.
116+
bool inspectedExists = curHandle == DontDestroyHandle || curHandle == 0;
117+
118+
// Quick sanity check if the loaded scenes changed
119+
bool anyChange = LoadedSceneCount != allLoadedScenes.Count;
120+
// otherwise keep a lookup table of the previous handles to check if the list changed at all.
121+
HashSet<int> previousHandles = null;
122+
if (!anyChange)
123+
previousHandles = new HashSet<int>(allLoadedScenes.Select(it => it.handle));
124+
125+
allLoadedScenes.Clear();
126+
127+
for (int i = 0; i < SceneManager.sceneCount; i++)
128+
{
129+
Scene scene = SceneManager.GetSceneAt(i);
130+
if (scene == default || !scene.isLoaded)
131+
continue;
132+
133+
// If no changes yet, ensure the previous list contained this handle.
134+
if (!anyChange && !previousHandles.Contains(scene.handle))
135+
anyChange = true;
136+
137+
// If we have not yet confirmed inspectedExists, check if this scene is our currently inspected one.
138+
if (curHandle != -1 && !inspectedExists && scene.handle == curHandle)
139+
inspectedExists = true;
140+
141+
allLoadedScenes.Add(scene);
142+
}
143+
144+
// Always add the DontDestroyOnLoad scene and the "none" scene.
145+
allLoadedScenes.Add(DontDestroyScene);
146+
allLoadedScenes.Add(default);
147+
148+
// Default to first scene if none selected or previous selection no longer exists.
149+
if (!inspectedExists)
150+
{
151+
SelectedScene = allLoadedScenes.First();
152+
}
153+
154+
// Notify on the list changing at all
155+
if (anyChange)
156+
{
157+
OnLoadedScenesChanged?.Invoke(LoadedScenes);
158+
}
159+
160+
// Finally, update the root objects list.
161+
if (SelectedScene != null && ((Scene)SelectedScene).IsValid())
162+
rootObjects = RuntimeProvider.Instance.GetRootGameObjects((Scene)SelectedScene);
163+
else
164+
{
165+
var allObjects = RuntimeProvider.Instance.FindObjectsOfTypeAll(typeof(GameObject));
166+
var list = new List<GameObject>();
167+
foreach (var obj in allObjects)
168+
{
169+
var go = obj.TryCast<GameObject>();
170+
if (go.transform.parent == null && !go.scene.IsValid())
171+
list.Add(go);
172+
}
173+
rootObjects = list.ToArray();
174+
}
175+
}
176+
}
177+
}

0 commit comments

Comments
 (0)