godotengine / godot-cpp

C++ bindings for the Godot script API
MIT License
1.73k stars 573 forks source link

Using `add_tool_menu_item` in C++ Editor Plugin Fails with "Index is out of bounds" Error #1549

Open kromenak opened 2 months ago

kromenak commented 2 months ago

Godot version

v4.2.2.stable.official [15073afe3]

godot-cpp version

4.2.2.stable

System information

Godot v4.2.2.stable - macOS 14.5.0 - Vulkan (Mobile) - integrated Apple M3 Max - Apple M3 Max (16 Threads)

Issue description

I am trying to write a helper tool from a C++ GDExtension.

When I use add_tool_menu_item to add an item to the tool menu, the item does appear in the Editor. However, clicking on it doesn't actually perform the associated action; instead, it shows this error:

scene/gui/popup_menu.cpp:2262 - Index p_idx = 3 is out of bounds (items.size() = 3).

Interestingly, recompiling the GDExtension (and forcing the hot reload behavior) fixes the issue, and the menu item works. However, if you restart the editor, the error occurs again until the GDExtension is hot reloaded.

While the "hot reload" thing is a workaround, it isn't feasible for non-technical team members who don't have the tools or knowledge to recompile the extension (and the whole reason I'm adding a menu item is for those team members!).

One final note, I was able to work around this by using a GDScript editor plugin that calls into my C++ code (and assuming I bind the function so GDScript can call it):

@tool
extends EditorPlugin

func _enter_tree():
    add_tool_menu_item("Custom Tool", DoCustomTool)

func _exit_tree():
    remove_tool_menu_item("Custom Tool")

func DoCustomTool():
    # This is quite hacky, but it works...
    var parent = get_parent()
    for i in range(0, parent.get_child_count()):
        if parent.get_child(i).name.begins_with("MyPluginNodesName"):
            parent.get_child(i).OnClickCustomToolMenuItem()

I have only tested this on macOS so far. I tried to debug via the engine source code, but I wasn't able to identify the cause. Two things I did notice:

  1. The code for adding the menu item seems to be called twice when the Editor is starting up.
  2. At one point, the index assigned to the menu item did seem out of bounds (with 3 items in the menu, it should be idx 2, but it was idx 3). However, due to IDE not showing the innards of Godot collections, it was hard to understand why this was happening.

Steps to reproduce

  1. Open the provided project in Godot 4.2.2.stable.
  2. Navigate to Project > Tools > Custom Tool Menu Item and click it.
  3. Note the error output to the console.
  4. Try to recompile the GDExtension while Godot is still running.
  5. After hot reload, note that the custom tool menu item works.

Minimal reproduction project

GodotProject.zip

krystek1994 commented 2 months ago

Hi, I am using Godot 4.3 and windows 10 and I could not get this error

kromenak commented 2 months ago

I haven't tried reproducing this on Windows - perhaps it is a Mac only issue?

I just tried testing this in both Godot 4.2.2 and Godot 4.3. The behavior is slightly different, but unfortunately the 4.3 behavior is worse:

The 4.3 error is slightly different, but I think that's just because another built-in item has been added to the Tools menu in 4.3.

scene/gui/popup_menu.cpp:2388 - Index p_idx = 4 is out of bounds (items.size() = 4).