Fix SceneExplorer not properly detecting scene changes sometimes

This commit is contained in:
Sinai 2021-05-27 19:30:19 +10:00
parent 365269b0dd
commit 14105785f0
2 changed files with 22 additions and 27 deletions

View File

@ -39,7 +39,7 @@ namespace UnityExplorer.UI.ObjectExplorer
private GameObject refreshRow; private GameObject refreshRow;
private Dropdown sceneDropdown; private Dropdown sceneDropdown;
private readonly Dictionary<int, Dropdown.OptionData> sceneToDropdownOption = new Dictionary<int, Dropdown.OptionData>(); private readonly Dictionary<Scene, Dropdown.OptionData> sceneToDropdownOption = new Dictionary<Scene, Dropdown.OptionData>();
private IEnumerable<GameObject> GetRootEntries() => SceneHandler.CurrentRootObjects; private IEnumerable<GameObject> GetRootEntries() => SceneHandler.CurrentRootObjects;
@ -70,7 +70,7 @@ namespace UnityExplorer.UI.ObjectExplorer
var go = transform.gameObject; var go = transform.gameObject;
if (SceneHandler.SelectedScene != go.scene) if (SceneHandler.SelectedScene != go.scene)
{ {
int idx = sceneDropdown.options.IndexOf(sceneToDropdownOption[go.scene.handle]); int idx = sceneDropdown.options.IndexOf(sceneToDropdownOption[go.scene]);
sceneDropdown.value = idx; sceneDropdown.value = idx;
} }
@ -91,12 +91,12 @@ namespace UnityExplorer.UI.ObjectExplorer
private void SceneHandler_OnInspectedSceneChanged(Scene scene) private void SceneHandler_OnInspectedSceneChanged(Scene scene)
{ {
if (!sceneToDropdownOption.ContainsKey(scene.handle)) if (!sceneToDropdownOption.ContainsKey(scene))
PopulateSceneDropdown(); PopulateSceneDropdown();
if (sceneToDropdownOption.ContainsKey(scene.handle)) if (sceneToDropdownOption.ContainsKey(scene))
{ {
var opt = sceneToDropdownOption[scene.handle]; var opt = sceneToDropdownOption[scene];
int idx = sceneDropdown.options.IndexOf(opt); int idx = sceneDropdown.options.IndexOf(opt);
if (sceneDropdown.value != idx) if (sceneDropdown.value != idx)
sceneDropdown.value = idx; sceneDropdown.value = idx;
@ -134,7 +134,7 @@ namespace UnityExplorer.UI.ObjectExplorer
var option = new Dropdown.OptionData(name); var option = new Dropdown.OptionData(name);
sceneDropdown.options.Add(option); sceneDropdown.options.Add(option);
sceneToDropdownOption.Add(scene.handle, option); sceneToDropdownOption.Add(scene, option);
} }
} }

View File

@ -18,7 +18,7 @@ namespace UnityExplorer.UI.ObjectExplorer
get => m_selectedScene; get => m_selectedScene;
internal set internal set
{ {
if (m_selectedScene != null && m_selectedScene?.handle == value?.handle) if (m_selectedScene != null && m_selectedScene == value)
return; return;
m_selectedScene = value; m_selectedScene = value;
OnInspectedSceneChanged?.Invoke((Scene)m_selectedScene); OnInspectedSceneChanged?.Invoke((Scene)m_selectedScene);
@ -37,6 +37,7 @@ namespace UnityExplorer.UI.ObjectExplorer
/// </summary> /// </summary>
public static ReadOnlyCollection<Scene> LoadedScenes => new ReadOnlyCollection<Scene>(allLoadedScenes); public static ReadOnlyCollection<Scene> LoadedScenes => new ReadOnlyCollection<Scene>(allLoadedScenes);
private static readonly List<Scene> allLoadedScenes = new List<Scene>(); private static readonly List<Scene> allLoadedScenes = new List<Scene>();
private static HashSet<Scene> previousLoadedScenes;
/// <summary> /// <summary>
/// The names of all scenes in the build settings, if they could be retrieved. /// The names of all scenes in the build settings, if they could be retrieved.
@ -82,7 +83,7 @@ namespace UnityExplorer.UI.ObjectExplorer
} }
private static GameObject dontDestroyObject; private static GameObject dontDestroyObject;
public static bool InspectingAssetScene => !SelectedScene?.IsValid() ?? false; public static bool InspectingAssetScene => SelectedScene.HasValue && SelectedScene.Value == default;
internal static void Init() internal static void Init()
{ {
@ -110,17 +111,9 @@ namespace UnityExplorer.UI.ObjectExplorer
internal static void Update() internal static void Update()
{ {
int curHandle = SelectedScene?.handle ?? -1; // check if the loaded scenes changed. always confirm DontDestroy / HideAndDontSave
// DontDestroyOnLoad always exists, so default to true if our curHandle is that handle. int confirmedCount = 2;
// otherwise we will check while iterating. bool inspectedExists = SelectedScene == DontDestroyScene || (SelectedScene.HasValue && SelectedScene.Value == default);
bool inspectedExists = curHandle == DontDestroyHandle || curHandle == 0;
// Quick sanity check if the loaded scenes changed
bool anyChange = LoadedSceneCount != allLoadedScenes.Count;
// otherwise keep a lookup table of the previous handles to check if the list changed at all.
HashSet<int> previousHandles = null;
if (!anyChange)
previousHandles = new HashSet<int>(allLoadedScenes.Select(it => it.handle));
allLoadedScenes.Clear(); allLoadedScenes.Clear();
@ -130,20 +123,22 @@ namespace UnityExplorer.UI.ObjectExplorer
if (scene == default || !scene.isLoaded) if (scene == default || !scene.isLoaded)
continue; continue;
// If no changes yet, ensure the previous list contained this handle. // If no changes yet, ensure the previous list contained the scene
if (!anyChange && !previousHandles.Contains(scene.handle)) if (previousLoadedScenes != null && previousLoadedScenes.Contains(scene))
anyChange = true; confirmedCount++;
// If we have not yet confirmed inspectedExists, check if this scene is our currently inspected one. // If we have not yet confirmed inspectedExists, check if this scene is our currently inspected one.
if (curHandle != -1 && !inspectedExists && scene.handle == curHandle) if (!inspectedExists && scene == SelectedScene)
inspectedExists = true; inspectedExists = true;
allLoadedScenes.Add(scene); allLoadedScenes.Add(scene);
} }
// Always add the DontDestroyOnLoad scene and the "none" scene. bool anyChange = confirmedCount != allLoadedScenes.Count;
allLoadedScenes.Add(DontDestroyScene); allLoadedScenes.Add(DontDestroyScene);
allLoadedScenes.Add(default); allLoadedScenes.Add(default);
previousLoadedScenes = new HashSet<Scene>(allLoadedScenes);
// Default to first scene if none selected or previous selection no longer exists. // Default to first scene if none selected or previous selection no longer exists.
if (!inspectedExists) if (!inspectedExists)
@ -163,14 +158,14 @@ namespace UnityExplorer.UI.ObjectExplorer
else else
{ {
var allObjects = RuntimeProvider.Instance.FindObjectsOfTypeAll(typeof(GameObject)); var allObjects = RuntimeProvider.Instance.FindObjectsOfTypeAll(typeof(GameObject));
var list = new List<GameObject>(); var objects = new List<GameObject>();
foreach (var obj in allObjects) foreach (var obj in allObjects)
{ {
var go = obj.TryCast<GameObject>(); var go = obj.TryCast<GameObject>();
if (go.transform.parent == null && !go.scene.IsValid()) if (go.transform.parent == null && !go.scene.IsValid())
list.Add(go); objects.Add(go);
} }
rootObjects = list.ToArray(); rootObjects = objects.ToArray();
} }
} }
} }