Editor Plugin - Is it possible to prevent instancing being cleared when saving a Packed Scene?

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

I am working on an editor plugin for my game which takes chunks created in blender and converts them to editable scenes within Godot.

Everything is working just fine, except for each scene doesn’t keep the reference to the base scene I am instantiating from.

I first instantiate the base level with this code:

sceneInstance = load(newLevelPath).instance()

I then apply any properties, changing collision meshes etc…
After I apply any properties, I save the scene by using the PackedScene.Pack() function:

var packedScene = PackedScene.new()
packedScene.pack(sceneInstance)
ResourceSaver.save(newLevelPath, packedScene)

This results in new scenes being created properly, but doesn’t save the node it was instanced from.

For example; when I right click on a tscn file in the file system I am able to select “New Inherited Scene” resulting in a scene which saves a reference to the base. I am then able to change the base scene, propagating those changes to each inherited scene.

This does not work the same way when using PackedScene.pack(). Does anyone know of a way to force this functionality through gdscript?

:bust_in_silhouette: Reply From: rossunger

There are two things that need to be happening:
Every node in the scene you’re saving needs to have “owner” set to be node that is the root of the scene you’re saving.

To maintain that instancing connection, you need to set the “filename” property of the scene that’s currently in your tree to be the path to the PackedScene you just saved.

I battled with this just last week! I couldn’t believe how simple it is.

I’m not sure I completely understand.

Do I have to recursively loop through all the nodes in the tree I am saving to set the owner as the root node?

It doesn’t seem to do anything when I set the filename. I checked within the tscn files and for the files that do work (Not my generated levels), they have this at the top:

[ext_resource path="res://Objects/Items/Item.tscn" type="PackedScene" id=1]

and the root node has an added attribute:

instance=ExtResource( 1 )

I’m not sure how you got it to work. Here is what I’ve tried with the file name which doesn’t maintain the reference:

sceneInstance = load(baseLevelPath).instance()
sceneInstance.filename = newLevelPath

NocturnalWisp | 2022-02-02 22:12

re: owner - yes! you have to recursively set all the children’s owner to be the node that you’re saving.

You should be able to set any node’s filename to be a path to a packedScene an it should become an instance of that packedScene… have you tried closing and reopening the scene in the editor after you do this? I think there might be an issue of the scene tree not updating…

What I was doing was duplicating the a node (with all it’s children), saving it as a packedScene, and then adding it back into the tree… and this was working fine for me…

get_editor_interface().get_edited_scene_root().add_child(duplicatedScene) duplicatedScene.owner = get_editor_interface().get_edited_scene_root()

rossunger | 2022-02-02 22:49

Thank you, but this doesn’t seem to be what I am looking for. I’ve added a link to the issue that I am really facing, apparently it is currently still open.

Thankfully it is just an editor plugin, so not make or break. I suppose I can always work around it.

NocturnalWisp | 2022-02-03 00:03

:bust_in_silhouette: Reply From: NocturnalWisp

Unfortunately, the issue that I am facing is a problem rooted in how ScenePacker.Pack() works and has been noted on the engine github page.

Here is the link to the issue: ResourceSaver.save() discards instanciation of inherited scenes · Issue #27243 · godotengine/godot · GitHub