diff --git a/addons/GodotDI/Editor/Plugin.cs b/addons/GodotDI/Editor/Plugin.cs index 9a7a084..5541c5a 100644 --- a/addons/GodotDI/Editor/Plugin.cs +++ b/addons/GodotDI/Editor/Plugin.cs @@ -1,8 +1,9 @@ #if TOOLS +using System; using System.Linq; using System.Reflection; using Godot; -using Godot.Collections; +using Array = Godot.Collections.Array; namespace GodotHostTest.GodotDI.Editor; @@ -18,9 +19,10 @@ public partial class Plugin : EditorPlugin BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic; private ScopeInspectorPlugin? _plugin; - private SceneTreeTimer? _sceneTreeTimer; + private readonly object _sceneTreeTimerLock = new(); + private bool _treeChangesRegistered; public override void _EnterTree() @@ -54,7 +56,7 @@ public partial class Plugin : EditorPlugin OnSceneChanged(root); } - private void OnSceneChanged(Node? sceneRoot) + private async void OnSceneChanged(Node? sceneRoot) { // register to tree changes, in case the registration wasn't possible before RegisterTreeChanges(); @@ -63,15 +65,25 @@ public partial class Plugin : EditorPlugin if (sceneRoot == null) return; // apply debounce - if (_sceneTreeTimer != null) - { - _sceneTreeTimer.SetTimeLeft(DebounceDelay); - return; - } + var editedSceneRoot = EditorInterface.Singleton.GetEditedSceneRoot(); - _sceneTreeTimer = - EditorInterface.Singleton.GetEditedSceneRoot().GetTree().CreateTimer(DebounceDelay); - _sceneTreeTimer.Timeout += () => ActualOnSceneChanged(sceneRoot); + if (!editedSceneRoot.IsInsideTree()) await ToSignal(editedSceneRoot, Node.SignalName.TreeEntered); + + var tree = editedSceneRoot.GetTree(); + if (tree == null) + throw new InvalidOperationException("editedSceneRoot.GetTree() was null even after TreeEntered"); + + lock (_sceneTreeTimerLock) + { + if (_sceneTreeTimer != null) + { + _sceneTreeTimer.SetTimeLeft(DebounceDelay); + return; + } + + _sceneTreeTimer = tree.CreateTimer(DebounceDelay); + _sceneTreeTimer.Timeout += () => ActualOnSceneChanged(sceneRoot); + } } private void ActualOnSceneChanged(Node sceneRoot)