godotengine / godot

Godot Engine – Multi-platform 2D and 3D game engine
https://godotengine.org
MIT License
87.25k stars 19.61k forks source link

Game (DEBUG) immediately Crashes when calling AddLines() on an EditorNode3DGizmo #92900

Open mads-fs opened 1 month ago

mads-fs commented 1 month ago

Tested versions

Using v4.2.2 stable, mono, win64 it appears that no matter what I pass to the AddLines() method, it crashes the game.

System information

Windows 10 - v4.2.2.stable (mono) - Vulkan (Forward+)

Issue description

I'm trying to draw some lines on screen using an EditorNode3DGizmo however when the code reaches the AddLines() method inside the _Redraw() call, the game crashes with an Access Violation Exception in Godots own code. image 1

Steps to reproduce

  1. Make a 3D Scene.
  2. Add a Camera3D node to the scene.
  3. Make a class that inherits from the Camera3D node and attach it to the Camera3D node.
  4. Inside that class make an internal class of type EditorNode3DGizmo
  5. Override the _Redraw() method and include a call to AddLines(). Even leaving the lines array empty will cause this bug to appear.
  6. In the parent class, instantiate the gizmo in _Ready().

It should now crash the game immediately on start.

Minimal reproduction project (MRP)

MinimumReproductionProject-AddLines.zip

raulsntos commented 1 month ago

I get this stacktrace when running the MRP in v4.3.beta.mono.custom_build [5833f5978]:

* thread #1, name = 'godot.linuxbsd.', stop reason = signal SIGSEGV: address not mapped to object (fault address: 0xdf0)
  * frame #0: 0x000055555d36fda8 godot.linuxbsd.editor.dev.x86_64.llvm.mono`Node3DEditor::is_current_selected_gizmo(this=0x0000000000000000, p_gizmo=0x0000555562aed2f0) at node_3d_editor_plugin.cpp:7896:33
    frame #1: 0x000055555d36fd65 godot.linuxbsd.editor.dev.x86_64.llvm.mono`EditorNode3DGizmo::redraw(this=0x0000555562aed2f0) at node_3d_editor_gizmos.cpp:84:37
    frame #2: 0x000055555e592121 godot.linuxbsd.editor.dev.x86_64.llvm.mono`Node3D::add_gizmo(this=0x00005555647511d0, p_gizmo=Ref<Node3DGizmo> @ 0x00007fffffffc630) at node_3d.cpp:618:13
    frame #3: 0x000055555e75e47e godot.linuxbsd.editor.dev.x86_64.llvm.mono`void call_with_ptr_args_helper<__UnexistingClass, Ref<Node3DGizmo>, 0ul>(p_instance=0x00005555647511d0, p_method=(godot.linuxbsd.editor.dev.x86_64.llvm.mono`Node3D::add_gizmo(Ref<Node3DGizmo>) at node_3d.cpp:607), p_args=0x00007fffffffc8d0, (null)=IndexSequence<0UL> @ 0x00007fffffffc658) at binder_common.h:325:2
    frame #4: 0x000055555e75e3cd godot.linuxbsd.editor.dev.x86_64.llvm.mono`void call_with_ptr_args<__UnexistingClass, Ref<Node3DGizmo>>(p_instance=0x00005555647511d0, p_method=(godot.linuxbsd.editor.dev.x86_64.llvm.mono`Node3D::add_gizmo(Ref<Node3DGizmo>) at node_3d.cpp:607), p_args=0x00007fffffffc8d0) at binder_common.h:573:2
    frame #5: 0x000055555e75dee6 godot.linuxbsd.editor.dev.x86_64.llvm.mono`MethodBindT<Ref<Node3DGizmo>>::ptrcall(this=0x000055556394fdf0, p_object=0x00005555647511d0, p_args=0x00007fffffffc8d0, r_ret=0x0000000000000000) const at method_bind.h:368:3
    frame #6: 0x000055555ba1307e godot.linuxbsd.editor.dev.x86_64.llvm.mono`godotsharp_method_bind_ptrcall(p_method_bind=0x000055556394fdf0, p_instance=0x00005555647511d0, p_args=0x00007fffffffc8d0, p_ret=0x0000000000000000) at runtime_interop.cpp:567:17
    frame #7: 0x00007fff3b45960b
    frame #8: 0x00007fff3b459511
    frame #9: 0x00007fff3b4660a7
    frame #10: 0x00007fff3b4634ce
    frame #11: 0x00007fff3b459176
    frame #12: 0x00007fff3b45027d
    frame #13: 0x00007fff3b44f6fc
    frame #14: 0x00007fff3b44f67c
    frame #15: 0x00007fff3b44f3b4
    frame #16: 0x00007fff3b44f12c
    frame #17: 0x000055555b9f2ca6 godot.linuxbsd.editor.dev.x86_64.llvm.mono`CSharpInstance::callp(this=0x0000555564897bb0, p_method=0x0000555564751540, p_args=0x0000000000000000, p_argcount=0, r_error=0x00007fffffffcf98) at csharp_script.cpp:1647:2
    frame #18: 0x000055555ddba484 godot.linuxbsd.editor.dev.x86_64.llvm.mono`bool Node::_gdvirtual__ready_call<false>(this=0x00005555647511d0) at node.h:355:2
    frame #19: 0x000055555dcef7b1 godot.linuxbsd.editor.dev.x86_64.llvm.mono`Node::_notification(this=0x00005555647511d0, p_notification=13) at node.cpp:211:4
    frame #20: 0x000055555afb6841 godot.linuxbsd.editor.dev.x86_64.llvm.mono`Node::_notificationv(this=0x00005555647511d0, p_notification=13, p_reversed=false) at node.h:50:2
    frame #21: 0x000055555afb670c godot.linuxbsd.editor.dev.x86_64.llvm.mono`Node3D::_notificationv(this=0x00005555647511d0, p_notification=13, p_reversed=false) at node_3d.h:52:2
    frame #22: 0x000055555e676c8c godot.linuxbsd.editor.dev.x86_64.llvm.mono`Camera3D::_notificationv(this=0x00005555647511d0, p_notification=13, p_reversed=false) at camera_3d.h:41:2
    frame #23: 0x0000555560f75e72 godot.linuxbsd.editor.dev.x86_64.llvm.mono`Object::notification(this=0x00005555647511d0, p_notification=13, p_reversed=false) at object.cpp:903:3
    frame #24: 0x000055555dcf10b3 godot.linuxbsd.editor.dev.x86_64.llvm.mono`Node::_propagate_ready(this=0x00005555647511d0) at node.cpp:266:3
    frame #25: 0x000055555dcf1047 godot.linuxbsd.editor.dev.x86_64.llvm.mono`Node::_propagate_ready(this=0x0000555564750cb0) at node.cpp:257:12
    frame #26: 0x000055555dcf1047 godot.linuxbsd.editor.dev.x86_64.llvm.mono`Node::_propagate_ready(this=0x00005555646e1150) at node.cpp:257:12
    frame #27: 0x000055555dcf7e81 godot.linuxbsd.editor.dev.x86_64.llvm.mono`Node::_set_tree(this=0x00005555646e1150, p_tree=0x00005555646e0c50) at node.cpp:3160:4
    frame #28: 0x000055555dd18558 godot.linuxbsd.editor.dev.x86_64.llvm.mono`SceneTree::initialize(this=0x00005555646e0c50) at scene_tree.cpp:448:8
    frame #29: 0x000055555ac5994b godot.linuxbsd.editor.dev.x86_64.llvm.mono`OS_LinuxBSD::run(this=0x00007fffffffd4d8) at os_linuxbsd.cpp:950:13
    frame #30: 0x000055555ac4d995 godot.linuxbsd.editor.dev.x86_64.llvm.mono`main(argc=3, argv=0x00007fffffffdaf8) at godot_linuxbsd.cpp:85:6
    frame #31: 0x00007ffff7c29d90 libc.so.6`__libc_start_call_main(main=(godot.linuxbsd.editor.dev.x86_64.llvm.mono`main at godot_linuxbsd.cpp:56), argc=3, argv=0x00007fffffffdaf8) at libc_start_call_main.h:58:16
    frame #32: 0x00007ffff7c29e40 libc.so.6`__libc_start_main_impl(main=<unavailable>, argc=3, argv=<unavailable>, init=<unavailable>, fini=<unavailable>, rtld_fini=<unavailable>, stack_end=0x00007fffffffdae8) at libc-start.c:392:3
    frame #33: 0x000055555ac4d6e5 godot.linuxbsd.editor.dev.x86_64.llvm.mono`_start + 37

It looks like Node3DEditor::get_singleton() is null, because we are outside the editor so EditorNode is never instantiated, see:

https://github.com/godotengine/godot/blob/5833f597865c773fae3ee09fc4e31d4a243f812d/main/main.cpp#L3727-L3730

You should probably implement EditorNode3DGizmoPlugin instead, or use Engine.IsEditorHint() to check if we're in the editor. That said the engine should print an error instead of crashing.

I also ported the MRP to GDScript:

MRP-AddLines-GDScript.zip

I get this error:

SCRIPT ERROR: Parse Error: Class "Camera.gd::EditorNode3DGizmoDrawMouseBoundary" cannot be constructed as it is based on abstract native class "EditorNode3DGizmo".

Related: