using Cirno.Scripts.Resources; using Godot; public partial class GlobalState : Node { public static GlobalState Instance { get; private set; } public Node CurrentScene { get; set; } public override void _Ready() { Instance = this; Viewport root = GetTree().Root; // Using a negative index counts from the end, so this gets the last child node of `root`. CurrentScene = root.GetChild(-1); } public void GotoScene(string path) { // This function will usually be called from a signal callback, // or some other function from the current scene. // Deleting the current scene at this point is // a bad idea, because it may still be executing code. // This will result in a crash or unexpected behavior. // The solution is to defer the load to a later time, when // we can be sure that no code from the current scene is running: CallDeferred(MethodName.DeferredGotoScene, path); } public void GoToScene(string path, MapStartDataResource startData) { // TODO: Implement startdata usage CallDeferred(MethodName.DeferredGotoScene, path, startData); } private void DeferredGotoScene(string path, MapStartDataResource startData = null) { // It is now safe to remove the current scene. CurrentScene.Free(); // Load a new scene. var nextScene = GD.Load(path); // Instance the new scene. CurrentScene = nextScene.Instantiate(); // Add it to the active scene, as child of root. GetTree().Root.AddChild(CurrentScene); // Optionally, to make it compatible with the SceneTree.change_scene_to_file() API. GetTree().CurrentScene = CurrentScene; if (startData is not null) { // Call deferred if it gives issues DeferredAddStartDataToGameManager(startData); } } private void DeferredAddStartDataToGameManager(MapStartDataResource resource) { GameManager.Instance.ApplyMapStartData(resource); } }