Switch to a scene already loaded before by Resource Interactive Loader

:information_source: Attention Topic was automatically imported from the old Question2Answer platform.
:bust_in_silhouette: Asked By goodymind

So I followed the Background Loading Tutorial and managed to make it work in C#.
but when I try to change scenes like this
Main Menu > Simulation > Main Menu >(error) X Simulation

I was not able to get to the simulation for the second time, and this shows up in the error menu…


E 0:00:45.260   load_interactive: Resource: 'simulation.tscn' is already being loaded. Cyclic reference?

I don’t have a reference to the simulation, just a dictionary with its name and path. Any help?

This is in C#

The Autoload/Simulation Selector

using Godot;
using System;
namespace PhySim.simulations
{
    public class SimulationSelector : Node
    {

        ResourceInteractiveLoader loader;
        int wait_frames;
        ulong time_max = 100; //ms;
        public Node CurrentScene;
        public override void _Ready()
        {
            SetProcess(false);
        }
        public void Return()
        {
            //the name of the root node of the simulation is Node
            if (CurrentScene.Name == "Node")
            {
                GoToScene("res://MainMenu.tscn");
            }
            else
            {
                GetTree().Quit();
            }
        }
        public override void _Input(InputEvent @event)
        {
            if (@event.IsActionPressed("ui_cancel"))
            {
                Return();
            }
        }
        public void GoToScene(string path)
        {
            loader = ResourceLoader.LoadInteractive(path);
            if (loader == null)
            {

                GD.Print("error");
                return;
            }
            SetProcess(true);
            CurrentScene.QueueFree();
            GetNode<AnimationPlayer>("AnimationPlayer").Play("loading");
            wait_frames = 10;
        }
        public override void _Process(float delta)
        {
            if (loader == null)
            {
                SetProcess(false);
                return;
            }
            if (wait_frames > 0)
            {
                wait_frames -= 1;
                return;
            }
            var t = OS.GetTicksMsec();
            while (OS.GetTicksMsec() < t + time_max)
            {
                var err = loader.Poll();
                if (err == Error.FileEof)
                {
                    var resource = loader.GetResource();
                    loader = null;
                    SetNewScene(resource);
                    break;
                }
                if (err == Error.Ok)
                {
                    UpdateProgress();
                }
                else
                {
                    GetTree().Quit();
                    loader = null;
                    break;
                }
            }
        }
        private void SetNewScene(Resource resource)
        {
            GetNode<AnimationPlayer>("AnimationPlayer").Stop();
            GetNode<Control>("CanvasLayer/Control").Visible = false;
            CurrentScene = (resource as PackedScene).Instance();
            GetNode("/root").AddChild(CurrentScene);
        }
        private void UpdateProgress()
        {

        }

    }
}

And the Main Menu Scene

using Godot;
using PhySim.simulations;
using System.Collections.Generic;
namespace PhySim
{
    public class MainMenu : Control
    {
        private SimulationSelector SimSelector => GetNodeOrNull<SimulationSelector>("/root/SimulationSelector");

        [Export(PropertyHint.MultilineText)] private Dictionary<string, string> Simulations;
        private Dictionary<int, string> IDToPath;
        private ItemList SimulationList => GetNodeOrNull<ItemList>("SimulationList");
        public override void _Ready()
        {
            SimSelector.CurrentScene = this;
            IDToPath = new Dictionary<int, string>();
            int id = 0;
            foreach(var pair in Simulations)
            {
                SimulationList.AddItem(pair.Key);
                IDToPath.Add(id, pair.Value);
                id++;
            }
        }
        private void SimulationSelected(int index)
        {
            string path = IDToPath[index];
            SimSelector.GoToScene(path);
        }
    }
}

goodymind | 2022-11-25 06:06

:bust_in_silhouette: Reply From: goodymind

Ok I figured this out, basically I saved the loaded scenes in a dictionary called Loaded Scenes with their paths as keys, and I check that dictionary to see if i had loaded it before and it is in memory.