void TestAddToNode()
{
GD.Print("1");
// Test Case 1: Adding a valid .obj file to a node
Node scene = LoadSceneInstance("res://TestStuff/TestScene.tscn");
Node childNode = scene.FindChild("TestNode1", true, false);
GD.Print("2");
Node scene2 = LoadSceneInstance("res://TestStuff/TestScene2.tscn");
Node childNode2 = scene2.FindChild("TestNode2", true, false);
GD.Print($"(TestAddMeshToNode) scene: {scene} childNode: {childNode} scene2: {scene2} childNode2: {childNode2}");
// Call the method to add an empty MeshInstance3D
//AddMesh3DToNode(parentNode);
AddNodeToNodeInSceneFile(childNode, childNode2.Name, "res://TestStuff/TestScene2.tscn");
//AddMeshToNode(objPath, parentNode);
}
public void AddNodeToNodeInSceneFile(Node childNode, string parentNode, string scenePath)
{
GD.Print("3");
if (childNode == null || parentNode == null)
{
GD.PrintErr($"(AddNodeToScene) Node {childNode} is null.");
return;
}
if (scenePath == null)
{
GD.PrintErr($"(AddNodeToScene) Scene path {scenePath} is null.");
return;
}
GD.Print("4");
var packedScene = GD.Load<PackedScene>(scenePath);
if (packedScene != null)
{
//create scene file instance
var sceneRoot = packedScene.Instantiate();
var editorInterface = GetEditorInterface();
GD.Print("5");
if (sceneRoot is Node sceneNode)
{
var foundParentNode = sceneRoot.FindChild(parentNode, true, false);
Node dupliChildNode = childNode.Duplicate();
dupliChildNode.Reparent(sceneRoot, true);
foundParentNode.AddChild(dupliChildNode, true);
childNode.Owner = sceneRoot; //needs to be after the AddChild()
GD.Print("6");
packedScene.Pack(sceneRoot);
ResourceSaver.Save(packedScene, scenePath);
var openedScenes = editorInterface.GetOpenScenes();
if (openedScenes.Contains(scenePath))
{
GD.Print($"AddNodeToScene) Reloading scene");
editorInterface.ReloadSceneFromPath(scenePath);
}
GD.Print($"(AddNodeToScene) Node added to the scene successfully.");
}
else
{
GD.PrintErr("(AddNodeToScene) Loaded scene is not of type 'Node'.");
}
}
else
{
GD.PrintErr("(AddNodeToScene) Failed to load the scene.");
}
}
console:
--- Debugging process stopped ---
Node needs a parent to be reparented.
Invalid owner. Owner must be an ancestor in the tree.
_Run Started:
1
2
(TestAddMeshToNode) scene: <Node3D#4465188992609> childNode: <Node#4465205768368> scene2: <Node3D#4465256100034> childNode2: <Node#4465272878591>
3
4
5
AddNodeToScene) Reloading scene
(AddNodeToScene) Node added to the scene successfully.
Sadly the errors are moved to the top and there is no info on what produces them. I’ve tried using prints which don’t work as the errors are move to the top and breakpoints in codium but that also doesn’t work.
I have no idea why this is happening or how to fix it and the users in the godot discord didn’t either.
For those wondering why I’m trying to create a function like this, I’m trying to automate things and I need this function to replace nodes with other nodes when I want to update them with newer version in all scenes for example. I can make and test the node in a scene and then after the test I can apply it to all other scenes via a tag system or a list of node with ID.
Node needs a parent to be reparented.
Invalid owner. Owner must be an ancestor in the tree.
The error message you’re encountering in Godot indicates that you’re trying to reparent a node, but the new parent you’re assigning is not a valid owner. In Godot, the owner of a node must be an ancestor in the scene tree.
Does that mean I can’t copy/move a node from one scene to another because they have different ancestors or different scene trees? Or do I have two active scene trees if two tabs are open? Or is it just one active scene tree for the node that is being edited in the selected tab?
your error is happens somewhere else before your prints, put your code
to “comment”, method calls or bodies of methods and and start looking where is error. And refactor your code.
if (packedScene == null){
GD.PrintErr("(AddNodeToScene) Failed to load the scene.");
return;
}
You will get one less inner block and one less else like you did before
I don’t think use FindChild() is good too, is better use GetNode() or GetNode<>()
specially when you trying move things betweens nodes
The error ( Invalid owner. Owner must be an ancestor in the tree.) came from: childNode.Owner = sceneRoot; had to change it to dupliChildNode.Owner = sceneRoot; So the error does not happen before the prints.
public void AddNodeToNodeInSceneFile(Node childNode, string parentNode, string scenePath)
{
GD.Print("3");
if (childNode == null || parentNode == null)
{
GD.PrintErr($"(AddNodeToScene) Node {childNode} is null.");
return;
}
if (scenePath == null)
{
GD.PrintErr($"(AddNodeToScene) Scene path {scenePath} is null.");
return;
}
GD.Print("4");
var packedScene = GD.Load<PackedScene>(scenePath);
if (packedScene == null)
{
GD.PrintErr("(AddNodeToScene) Failed to load the scene.");
return;
}
//create scene file instance
var sceneRoot = packedScene.Instantiate();
var editorInterface = GetEditorInterface();
GD.Print("5");
if (sceneRoot is Node sceneNode)
{
var foundParentNode = sceneRoot.FindChild(parentNode, true, false);
Node dupliChildNode = childNode.Duplicate();
//dupliChildNode.Reparent(sceneRoot, true);
childNode.GetParent().RemoveChild(dupliChildNode); //aka old_parent.remove_child(node)
foundParentNode.AddChild(dupliChildNode, true); //aka selected_node.add_child(node)
dupliChildNode.Owner = sceneRoot; //needs to be after the AddChild()
GD.Print("6");
packedScene.Pack(sceneRoot);
ResourceSaver.Save(packedScene, scenePath);
var openedScenes = editorInterface.GetOpenScenes();
if (openedScenes.Contains(scenePath))
{
GD.Print($"AddNodeToScene) Reloading scene");
editorInterface.ReloadSceneFromPath(scenePath);
}
GD.Print($"(AddNodeToScene) Node added to the scene successfully.");
}
else
{
GD.PrintErr("(AddNodeToScene) Loaded scene is not of type 'Node'.");
}
}
But now I get scene/main/node.cpp:1425 - Condition "p_child->data.parent != this" is true.
If I change it to: dupliChildNode.GetParent().RemoveChild(dupliChildNode); Both have the same scene as a parent.
I get:
modules/mono/glue/runtime_interop.cpp:1324 - System.NullReferenceException: Object reference not set to an instance of an object.
at ManifestReader2.AddNodeToNodeInSceneFile(Node childNode, String parentNode, String scenePath) in /ManifestReader2.cs:line 822
at ManifestReader2.TestAddToNode() in /ManifestReader2.cs:line 58
at ManifestReader2._Run() in /ManifestReader2.cs:line 26
at Godot.EditorScript.InvokeGodotClassMethod(godot_string_name& method, NativeVariantPtrArgs args, godot_variant& ret) in /root/godot/modules/mono/glue/GodotSharp/GodotSharpEditor/Generated/GodotObjects/EditorScript.cs:line 98
at ManifestReader2.InvokeGodotClassMethod(godot_string_name& method, NativeVariantPtrArgs args, godot_variant& ret) in /Godot.SourceGenerators/Godot.SourceGenerators.ScriptMethodsGenerator/ManifestReader2_ScriptMethods.generated.cs:line 262
at Godot.Bridge.CSharpInstanceBridge.Call(IntPtr godotObjectGCHandle, godot_string_name* method, godot_variant** args, Int32 argCount, godot_variant_call_error* refCallError, godot_variant* ret) in /root/godot/modules/mono/glue/GodotSharp/GodotSharp/Core/Bridge/CSharpInstanceBridge.cs:line 24
public void AddNodeToNodeInSceneFile(Node childNode, string parentNode, string scenePath1, string scenePath)
{
GD.Print("3");
if (childNode == null || parentNode == null)
{
GD.PrintErr($"(AddNodeToScene) Node {childNode} is null.");
return;
}
if (scenePath == null)
{
GD.PrintErr($"(AddNodeToScene) Scene path {scenePath} is null.");
return;
}
GD.Print("4");
var packedScene = GD.Load<PackedScene>(scenePath);
if (packedScene == null)
{
GD.PrintErr("(AddNodeToScene) Failed to load the scene.");
return;
}
//create scene file instance
var sceneRoot = packedScene.Instantiate();
var editorInterface = GetEditorInterface();
GD.Print("5");
if (sceneRoot is Node sceneNode)
{
var foundParentNode = sceneRoot.FindChild(parentNode, true, false);
Node dupliChildNode = childNode.Duplicate();
//dupliChildNode.Reparent(sceneRoot, true);
//dupliChildNode.GetParent().RemoveChild(dupliChildNode); //aka old_parent.remove_child(node)
foundParentNode.AddChild(dupliChildNode, true); //aka selected_node.add_child(node)
dupliChildNode.Owner = sceneRoot; //needs to be after the AddChild()
GD.Print("6");
packedScene.Pack(sceneRoot);
ResourceSaver.Save(packedScene, scenePath);
var openedScenes = editorInterface.GetOpenScenes();
if (openedScenes.Contains(scenePath))
{
GD.Print($"AddNodeToScene) Reloading scene");
editorInterface.ReloadSceneFromPath(scenePath);
}
GD.Print($"(AddNodeToScene) Node added to the scene successfully.");
}
else
{
GD.PrintErr("(AddNodeToScene) Loaded scene is not of type 'Node'.");
}
}
It looks like when a node is duplicated it has no owner so dupliChildNode.GetParent().RemoveChild(dupliChildNode);
Did output these errors.