Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

'Already has parent' error adding or selecting NavigationObstacle3D #84050

Closed
rcorre opened this issue Oct 27, 2023 · 4 comments · Fixed by #84055
Closed

'Already has parent' error adding or selecting NavigationObstacle3D #84050

rcorre opened this issue Oct 27, 2023 · 4 comments · Fixed by #84055
Assignees
Milestone

Comments

@rcorre
Copy link
Contributor

rcorre commented Oct 27, 2023

Godot version

4.2.beta.custom_build.50d17f6b8

System information

Linux

Issue description

When adding a NavigationObstacle3D, or selecting one after another node has been selected, the editor prints an error:

ERROR: Can't add child '@MeshInstance3D@18824' to 'NavigationObstacle3D', already has a parent 'NavigationObstacle3D'.

The simple fix is something like this:

diff --git a/editor/plugins/navigation_obstacle_3d_editor_plugin.cpp b/editor/plugins/navigation_obstacle_3d_editor_plugin.cpp
index 9747ef4d48..32ee1bc198 100644
--- a/editor/plugins/navigation_obstacle_3d_editor_plugin.cpp
+++ b/editor/plugins/navigation_obstacle_3d_editor_plugin.cpp
@@ -503,7 +503,9 @@ void NavigationObstacle3DEditor::edit(Node *p_node) {
                wip.clear();
                wip_active = false;
                edited_point = -1;
-               p_node->add_child(point_lines_meshinstance);
+               if (point_lines_meshinstance->get_parent() != p_node) {
+                       p_node->add_child(point_lines_meshinstance);
+               }
                _polygon_draw();
 
        } else {

However, I'm not sure if this is the true fix. NavigationObstacle3DEditor::edit seems to assume that it will only be called once per node. Is that reasonable?

Currently, NavigationObstacle3DEditor::edit is called twice (with the same node argument) when creating a node:

Thread 1 "godot.linuxbsd." hit Breakpoint 4, NavigationObstacle3DEditor::edit (this=0x55556c738f50, p_node=0x555569a5e9f0) at editor/plugins/navigation_obstacle_3d_editor_plugin.cpp:495
495     void NavigationObstacle3DEditor::edit(Node *p_node) {
(gdb) bt
#0  NavigationObstacle3DEditor::edit (this=0x55556c738f50, p_node=0x555569a5e9f0) at editor/plugins/navigation_obstacle_3d_editor_plugin.cpp:495
#1  0x0000555558882294 in EditorNode::_plugin_over_edit (this=<optimized out>, p_object=<optimized out>, p_plugin=<optimized out>) at editor/editor_node.cpp:847
#2  EditorNode::edit_item (this=<optimized out>, p_object=<optimized out>, p_editing_owner=<optimized out>) at editor/editor_node.cpp:2184
#3  0x0000555558898d63 in EditorNode::_edit_current (this=0x5555600cb760, p_skip_foreign=<optimized out>) at editor/editor_node.cpp:2470
#4  0x0000555558b1294d in EditorNode::push_node_item (p_node=<optimized out>, this=<optimized out>) at editor/editor_node.cpp:2191
#5  SceneTreeDock::_push_item (this=0x55556573d280, p_object=0x555569a5e9f0) at editor/scene_tree_dock.cpp:1495
#6  0x0000555558b5e282 in SceneTreeDock::_do_create (this=this@entry=0x55556573d280, p_parent=0x55557bc46eb0) at editor/scene_tree_dock.cpp:2388
#7  0x0000555558b75766 in SceneTreeDock::_create (this=0x55556573d280) at editor/scene_tree_dock.cpp:2428
#8  0x000055555b1e617e in Object::emit_signalp (this=<optimized out>, p_name=..., p_args=0x0, p_argcount=0) at core/object/object.cpp:1126
#9  0x00005555586a58ea in Object::emit_signal<>(StringName const&) (p_name=..., this=0x5555658588b0) at ./core/object/object.h:920
#10 CreateDialog::_confirmed (this=0x5555658588b0) at editor/create_dialog.cpp:431
#11 0x000055555b1e617e in Object::emit_signalp (this=<optimized out>, p_name=..., p_args=0x0, p_argcount=0) at core/object/object.cpp:1126
#12 0x00005555596a28b2 in Object::emit_signal<>(StringName const&) (p_name=..., this=0x5555658588b0) at ./core/object/object.h:920
#13 AcceptDialog::_ok_pressed (this=0x5555658588b0) at scene/gui/dialogs.cpp:120
#14 0x00005555596f30ec in call_with_variant_args_helper<AcceptDialog, String const&, 0ul> (r_error=..., p_args=<optimized out>, p_method=<optimized out>, p_instance=<optimized out>) at ./core/variant/binder_common.h:303
#15 call_with_variant_args<AcceptDialog, String const&> (r_error=..., p_argcount=<optimized out>, p_args=<optimized out>, p_method=<optimized out>, p_instance=<optimized out>) at ./core/variant/binder_common.h:417
#16 CallableCustomMethodPointer<AcceptDialog, String const&>::call (this=<optimized out>, p_arguments=<optimized out>, p_argcount=<optimized out>, r_return_value=..., r_call_error=...) at ./core/object/callable_method_pointer.h:104
#17 0x000055555b1e617e in Object::emit_signalp (this=<optimized out>, p_name=..., p_args=0x7fffffffc9e0, p_argcount=1) at core/object/object.cpp:1126
#18 0x0000555557e722c2 in Object::emit_signal<String> (this=<optimized out>, p_name=...) at ./core/object/object.h:917
#19 0x00005555597ddf36 in LineEdit::gui_input (this=0x5555658bea60, p_event=...) at scene/gui/line_edit.cpp:479
#20 0x00005555595ec24c in Viewport::_gui_input_event (this=<optimized out>, p_event=...) at scene/main/viewport.cpp:2233
#21 0x00005555595ec62d in Viewport::push_input (this=0x5555658588b0, p_event=..., p_local_coords=p_local_coords@entry=false) at scene/main/viewport.cpp:3185
#22 0x00005555595edcb5 in Window::_window_input (this=<optimized out>, p_ev=...) at scene/main/window.cpp:1551
#23 0x00005555595ecb5c in Viewport::_sub_windows_forward_input (p_event=..., this=0x55556005bdb0) at scene/main/viewport.cpp:2985
#24 Viewport::push_input (this=0x55556005bdb0, p_event=..., p_local_coords=<optimized out>) at scene/main/viewport.cpp:3169
#25 0x00005555595fd785 in call_with_variant_args_helper<Window, Ref<InputEvent> const&, 0ul> (r_error=..., p_args=<optimized out>, p_method=<optimized out>, p_instance=<optimized out>) at ./core/variant/binder_common.h:303
#26 call_with_variant_args<Window, Ref<InputEvent> const&> (r_error=..., p_argcount=<optimized out>, p_args=<optimized out>, p_method=<optimized out>, p_instance=<optimized out>) at ./core/variant/binder_common.h:417
#27 CallableCustomMethodPointer<Window, Ref<InputEvent> const&>::call (this=<optimized out>, p_arguments=<optimized out>, p_argcount=<optimized out>, r_return_value=..., r_call_error=...) at ./core/object/callable_method_pointer.h:104
#28 0x000055555b8578a7 in Callable::call<Ref<InputEvent> >(Ref<InputEvent>) const [clone .isra.0] (this=0x7fffffffcfc0) at ./core/variant/variant.h:846
#29 0x00005555577e2552 in DisplayServerX11::_dispatch_input_event (p_event=..., this=0x55555c400060) at platform/linuxbsd/x11/display_server_x11.cpp:4001
#30 DisplayServerX11::_dispatch_input_events (p_event=...) at platform/linuxbsd/x11/display_server_x11.cpp:3977
#31 0x000055555af2beb5 in Input::_parse_input_event_impl (this=<optimized out>, p_event=..., p_is_emulated=<optimized out>) at core/input/input.cpp:749
#32 0x000055555af2d44d in Input::flush_buffered_events (this=0x55555c320f20) at core/input/input.cpp:1011
#33 0x00005555577e6828 in DisplayServerX11::process_events (this=0x55555c400060) at core/input/input.cpp:84
#34 0x00005555577fb18c in OS_LinuxBSD::run (this=0x7fffffffd500) at platform/linuxbsd/os_linuxbsd.cpp:929
#35 OS_LinuxBSD::run (this=0x7fffffffd500) at platform/linuxbsd/os_linuxbsd.cpp:916
#36 main (argc=<optimized out>, argv=<optimized out>) at platform/linuxbsd/godot_linuxbsd.cpp:74
(gdb) c
Continuing.

Thread 1 "godot.linuxbsd." hit Breakpoint 4, NavigationObstacle3DEditor::edit (this=0x55556c738f50, p_node=0x555569a5e9f0) at editor/plugins/navigation_obstacle_3d_editor_plugin.cpp:495
495     void NavigationObstacle3DEditor::edit(Node *p_node) {
(gdb) bt
#0  NavigationObstacle3DEditor::edit (this=0x55556c738f50, p_node=0x555569a5e9f0) at editor/plugins/navigation_obstacle_3d_editor_plugin.cpp:495
#1  0x0000555558882294 in EditorNode::_plugin_over_edit (this=<optimized out>, p_object=<optimized out>, p_plugin=<optimized out>) at editor/editor_node.cpp:847
#2  EditorNode::edit_item (this=<optimized out>, p_object=<optimized out>, p_editing_owner=<optimized out>) at editor/editor_node.cpp:2184
#3  0x0000555558898d63 in EditorNode::_edit_current (this=0x5555600cb760, p_skip_foreign=<optimized out>) at editor/editor_node.cpp:2470
#4  0x0000555558b1294d in EditorNode::push_node_item (p_node=<optimized out>, this=<optimized out>) at editor/editor_node.cpp:2191
#5  SceneTreeDock::_push_item (this=0x55556573d280, p_object=0x555569a5e9f0) at editor/scene_tree_dock.cpp:1495
#6  0x0000555558b745ca in SceneTreeDock::_selection_changed (this=0x55556573d280) at editor/scene_tree_dock.cpp:2348
#7  0x000055555b1e617e in Object::emit_signalp (this=<optimized out>, p_name=..., p_args=0x0, p_argcount=0) at core/object/object.cpp:1126
#8  0x0000555558730c52 in Object::emit_signal<>(StringName const&) (p_name=..., this=0x7fffac002170) at ./core/object/object.h:920
#9  EditorSelection::_emit_change (this=0x7fffac002170) at editor/editor_data.cpp:1298
#10 0x00005555578ea509 in call_with_variant_args_helper<__UnexistingClass>(__UnexistingClass*, void (__UnexistingClass::*)(), Variant const**, Callable::CallError&, IndexSequence<>) (p_args=<synthetic pointer>, r_error=..., p_method=<optimized out>, 
    p_instance=<optimized out>) at ./core/variant/binder_common.h:303
#11 call_with_variant_args_dv<__UnexistingClass> (default_values=..., r_error=..., p_argcount=<optimized out>, p_args=<optimized out>, p_method=<optimized out>, p_instance=<optimized out>) at ./core/variant/binder_common.h:450
#12 MethodBindT<>::call(Object*, Variant const**, int, Callable::CallError&) const (this=<optimized out>, p_object=<optimized out>, p_args=<optimized out>, p_arg_count=<optimized out>, r_error=...) at ./core/object/method_bind.h:335
#13 0x000055555b18e697 in Object::callp (this=0x7fffac002170, p_method=..., p_args=0x0, p_argcount=<optimized out>, r_error=...) at core/object/object.cpp:774
#14 0x000055555af38444 in Callable::callp (this=0x55555ff0b6a0, p_arguments=0x0, p_argcount=0, r_return_value=..., r_call_error=...) at core/variant/callable.cpp:69
#15 0x000055555b6774f2 in CallQueue::_call_function(Callable const&, Variant const*, int, bool) [clone .isra.0] (p_callable=..., p_args=<optimized out>, p_argcount=0, p_show_error=false, this=<optimized out>) at core/object/message_queue.cpp:219
#16 0x000055555b1e2ed7 in CallQueue::flush (this=0x55555bfe2d10) at core/object/message_queue.cpp:324
#17 0x0000555559550441 in SceneTree::process (this=0x55556005b8a0, p_time=0.14383166666669212) at scene/main/scene_tree.cpp:511
#18 0x00005555577bdf60 in Main::iteration () at main/main.cpp:3613
#19 0x00005555577fb19e in OS_LinuxBSD::run (this=0x7fffffffd500) at platform/linuxbsd/os_linuxbsd.cpp:933
#20 OS_LinuxBSD::run (this=0x7fffffffd500) at platform/linuxbsd/os_linuxbsd.cpp:916
#21 main (argc=<optimized out>, argv=<optimized out>) at platform/linuxbsd/godot_linuxbsd.cpp:74

It is also called twice when selecting a node:

Thread 1 "godot.linuxbsd." hit Breakpoint 4, NavigationObstacle3DEditor::edit (this=0x55556c738f50, p_node=0x555569a5e9f0) at editor/plugins/navigation_obstacle_3d_editor_plugin.cpp:495
495     void NavigationObstacle3DEditor::edit(Node *p_node) {
(gdb) bt
#0  NavigationObstacle3DEditor::edit (this=0x55556c738f50, p_node=0x555569a5e9f0) at editor/plugins/navigation_obstacle_3d_editor_plugin.cpp:495
#1  0x0000555558882294 in EditorNode::_plugin_over_edit (this=<optimized out>, p_object=<optimized out>, p_plugin=<optimized out>) at editor/editor_node.cpp:847
#2  EditorNode::edit_item (this=<optimized out>, p_object=<optimized out>, p_editing_owner=<optimized out>) at editor/editor_node.cpp:2184
#3  0x0000555558898d63 in EditorNode::_edit_current (this=0x5555600cb760, p_skip_foreign=<optimized out>) at editor/editor_node.cpp:2470
#4  0x0000555558b1294d in EditorNode::push_node_item (p_node=<optimized out>, this=<optimized out>) at editor/editor_node.cpp:2191
#5  SceneTreeDock::_push_item (this=0x55556573d280, p_object=0x555569a5e9f0) at editor/scene_tree_dock.cpp:1495
#6  0x000055555b6774f2 in CallQueue::_call_function(Callable const&, Variant const*, int, bool) [clone .isra.0] (p_callable=..., p_args=<optimized out>, p_argcount=0, p_show_error=true, this=<optimized out>) at core/object/message_queue.cpp:219
#7  0x000055555b1e2ed7 in CallQueue::flush (this=0x55555bfe2d10) at core/object/message_queue.cpp:324
#8  0x0000555559543b10 in SceneTree::physics_process (this=0x55556005b8a0, p_time=0.016666666666666666) at scene/main/scene_tree.cpp:471
#9  0x00005555577bdaf0 in Main::iteration () at main/main.cpp:3575
#10 0x00005555577fb19e in OS_LinuxBSD::run (this=0x7fffffffd500) at platform/linuxbsd/os_linuxbsd.cpp:933
#11 OS_LinuxBSD::run (this=0x7fffffffd500) at platform/linuxbsd/os_linuxbsd.cpp:916
#12 main (argc=<optimized out>, argv=<optimized out>) at platform/linuxbsd/godot_linuxbsd.cpp:74
(gdb) c
Continuing.

Thread 1 "godot.linuxbsd." hit Breakpoint 4, NavigationObstacle3DEditor::edit (this=0x55556c738f50, p_node=0x555569a5e9f0) at editor/plugins/navigation_obstacle_3d_editor_plugin.cpp:495
495     void NavigationObstacle3DEditor::edit(Node *p_node) {
(gdb) bt
#0  NavigationObstacle3DEditor::edit (this=0x55556c738f50, p_node=0x555569a5e9f0) at editor/plugins/navigation_obstacle_3d_editor_plugin.cpp:495
#1  0x0000555558882294 in EditorNode::_plugin_over_edit (this=<optimized out>, p_object=<optimized out>, p_plugin=<optimized out>) at editor/editor_node.cpp:847
#2  EditorNode::edit_item (this=<optimized out>, p_object=<optimized out>, p_editing_owner=<optimized out>) at editor/editor_node.cpp:2184
#3  0x0000555558898d63 in EditorNode::_edit_current (this=0x5555600cb760, p_skip_foreign=<optimized out>) at editor/editor_node.cpp:2470
#4  0x0000555558b1294d in EditorNode::push_node_item (p_node=<optimized out>, this=<optimized out>) at editor/editor_node.cpp:2191
#5  SceneTreeDock::_push_item (this=0x55556573d280, p_object=0x555569a5e9f0) at editor/scene_tree_dock.cpp:1495
#6  0x0000555558b745ca in SceneTreeDock::_selection_changed (this=0x55556573d280) at editor/scene_tree_dock.cpp:2348
#7  0x000055555b1e617e in Object::emit_signalp (this=<optimized out>, p_name=..., p_args=0x0, p_argcount=0) at core/object/object.cpp:1126
#8  0x0000555558730c52 in Object::emit_signal<>(StringName const&) (p_name=..., this=0x7fffac002170) at ./core/object/object.h:920
#9  EditorSelection::_emit_change (this=0x7fffac002170) at editor/editor_data.cpp:1298
#10 0x00005555578ea509 in call_with_variant_args_helper<__UnexistingClass>(__UnexistingClass*, void (__UnexistingClass::*)(), Variant const**, Callable::CallError&, IndexSequence<>) (p_args=<synthetic pointer>, r_error=..., p_method=<optimized out>, 
    p_instance=<optimized out>) at ./core/variant/binder_common.h:303
#11 call_with_variant_args_dv<__UnexistingClass> (default_values=..., r_error=..., p_argcount=<optimized out>, p_args=<optimized out>, p_method=<optimized out>, p_instance=<optimized out>) at ./core/variant/binder_common.h:450
#12 MethodBindT<>::call(Object*, Variant const**, int, Callable::CallError&) const (this=<optimized out>, p_object=<optimized out>, p_args=<optimized out>, p_arg_count=<optimized out>, r_error=...) at ./core/object/method_bind.h:335
#13 0x000055555b18e697 in Object::callp (this=0x7fffac002170, p_method=..., p_args=0x0, p_argcount=<optimized out>, r_error=...) at core/object/object.cpp:774
#14 0x000055555af38444 in Callable::callp (this=0x55555ff0b670, p_arguments=0x0, p_argcount=0, r_return_value=..., r_call_error=...) at core/variant/callable.cpp:69
#15 0x000055555b6774f2 in CallQueue::_call_function(Callable const&, Variant const*, int, bool) [clone .isra.0] (p_callable=..., p_args=<optimized out>, p_argcount=0, p_show_error=false, this=<optimized out>) at core/object/message_queue.cpp:219
#16 0x000055555b1e2ed7 in CallQueue::flush (this=0x55555bfe2d10) at core/object/message_queue.cpp:324
#17 0x0000555559550441 in SceneTree::process (this=0x55556005b8a0, p_time=0.10056433333330747) at scene/main/scene_tree.cpp:511
#18 0x00005555577bdf60 in Main::iteration () at main/main.cpp:3613
#19 0x00005555577fb19e in OS_LinuxBSD::run (this=0x7fffffffd500) at platform/linuxbsd/os_linuxbsd.cpp:933
#20 OS_LinuxBSD::run (this=0x7fffffffd500) at platform/linuxbsd/os_linuxbsd.cpp:916
#21 main (argc=<optimized out>, argv=<optimized out>) at platform/linuxbsd/godot_linuxbsd.cpp:74

So I'm not sure if the bug is just in NavigationObstacle3DEditor::edit, or the fact that edit is being double-called.

Steps to reproduce

  1. Add a NavigationObstacle3D to a scene.

Minimal reproduction project

N/A

@smix8
Copy link
Contributor

smix8 commented Oct 27, 2023

The obstacle editor plugin code is a copy of the polygon 3d editor plugin.

The polygon 3d plugin received fix #73726 that the obstacle plugin is missing.

@rcorre
Copy link
Contributor Author

rcorre commented Oct 27, 2023

Is it expected that NavigationObstacle3DEditor::edit is called twice with the same argument when selecting or adding a node?

@smix8
Copy link
Contributor

smix8 commented Oct 27, 2023

@rcorre Do you have a tool script running in the Editor? Because I only ever get a single edit() call.

@rcorre
Copy link
Contributor Author

rcorre commented Oct 28, 2023

@smix8 I don't. I can repro this on a brand new empty project. If I add a NavigationObstacle3D, edit is called twice. If I click on another node, then click on the NavigationObstacle3D again, edit is called twice (specifically twice when I click on the NavigationObstacle3D, both with that same node as the argument).

In the first case, it seems that SceneTreeDock::_do_create is called on creating an object, and that calls edit, but you also get a SceneTreeDock::_selection_changed triggering a second call to edit.

Maybe it's not a huge deal, and plugins should handle duplicate calls to ::edit properly, but I just wanted to call that out.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants