Can't instance scene from tool mode

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

Just started using the engine so i don’t know if im dumb or this is a bug

I have a script with a class_name and in tool mode that I intend to use as a custom node, the code in _ready() runs when I add it through the editor. It checks if there’s a canvas layer and if the scene i want to add (Interface.tscn) is in that canvas layer. If not, it creates them.

tool
extends Node
class_name Holder

func _ready():	
    if !has_node("CanvasLayer"):
		var canvas = CanvasLayer.new()
		get_tree().get_edited_scene_root().add_child(canvas)
		canvas.set_owner(get_tree().get_edited_scene_root())
	
    if !has_node("CanvasLayer/Interface"):
	    var interface = load("res://Scenes/Interface.tscn").instance()
	    var canvas = get_tree().get_edited_scene_root().get_node("CanvasLayer")
	   canvas.add_child( interface )
	   interface.set_owner( canvas )

The canvas layer works as intended, but the scene doesn’t get added no matter what i do. It even appears in the viewport but not in the Scene tree panel. When I reload the scene it’s not anywhere. There are no errors in the console.

It only works properly when I add the scene in the root node like the CanvasLayer

I also tried simply doing it like in-game code:

var canvas = get_node("CanvasLayer")
	canvas.add_child(interface)
	interface.set_owner(canvas)

But It just gives me “Node not found: CanvasLayer.” in the console

And using “get_tree().get_root()” like:

var canvas = get_tree().get_root().get_node("CanvasLayer")
	canvas.add_child( interface )
	interface.set_owner( canvas )

Adds the interface scene to the editor itself

I’d try preloading the scene into an onready var first and then instance that. Or, use call_deferred for adding the child inside of _ready(). From memory: call_deferred(“add_child”, child_node) - something like that.

Macryc | 2020-06-07 09:54

I tried using preload onready and:

func _ready():
  if !root_node.has_node("CanvasLayer/Interface"):
	print("no interface")
	var interface = preload("res://Scenes/Interface.tscn").instance()
	var canvas = root_node.get_node("CanvasLayer")
	canvas.call_deferred("add_child", interface)
	interface.call_deferred("set_owner", canvas)

Same result on both (and combined), the scene “Interface” appears on the viewport but not in the scene tree, and when I reload the scene it’s on the same state or just simply gone

pox | 2020-06-08 01:50

I just had the same problem when trying to make an editor plugin. Did you find a solution or should we raise an issue on GitHub?

Benjamin Navarro | 2020-06-30 15:38

Nope, I gave up long ago, I made my custom node not interact with anything. I don’t really plan to use this anymore but it would be pretty neat to have all the necessary nodes automatically appear to avoid problems, but I realised you can have them all in one tscn if you really need it…

pox | 2020-08-01 10:00

:bust_in_silhouette: Reply From: Wakatta

Funny enough knew the answer having read the docs, yet still got stumped. So leaving this answer for future reference.

var canvas = get_node("./CanvasLayer")
canvas.add_child( interface )
interface.set_owner(get_tree().edited_scene_root())

Documented Here

Yeah I also found it way too late, forgot about this post I made. Basically I made the mistake of thinking that “owner” is the same as “parent”, owner is the root node of the scene.

Also, if you want to always have a node or scene present, you should make it an autoload, not this crap I was trying to do

pox | 2022-07-12 07:55

Especially if you do scene changing allot.
You live you learn right.

Wakatta | 2022-07-12 08:08