godot: Godot errors/crashes after inspecting two different objects handled by the same plugin
Godot version
Godot 4 rc2
System information
Windows 10 64 bits NVIDIA GeForce GTX 1060
Issue description
I was trying to reproduce a nasty error I started having since stuff got changed in some areas of editor plugins, but in RC2 instead of reproducing my issue, I ended up finding this crash. So I thought I’d report it…
I wrote a simple test plugin that adds a bottom panel with two buttons:
- “Edit Sprite”: edits the last selected sprite
- “Edit Texture”: edits the texture of the last selected sprite
This plugin handles BOTH Sprite2D and Texture2D.
Steps to reproduce
After testing the plugin a bit, I turned it off, then clicked on the Script tab: Godot crashes. No information popup or logs, just shuts down.
Minimal reproduction project
EditorPluginEditAnotherHandled.zip
This project has the plugin enabled by default.
- Open the main scene and go to the 2D view
- Select the sprite
- In the bottom bar, click “Test plugin” to show the custom panel
- In the custom panel, click “Edit Texture” and “Edit Sprite” alternatively a bunch of times
- Go to Project Settings and turn off the plugin: Godot might crash already.
- If no crash occurred, click on the “Script” tab: observe crash.
Secondary note:
I was told that one of the changes to EditorPlugin was that _edit(null) can be called when “there is no longer any selected object handled by this plugin” (seen in the doc). But if you look in the console while alternating the two buttons (which ask the editor to inspect two different objects handled by the plugin), you will notice that edit(null) occurs half of the time, I dont understand why.
Third note: When testing this repro in master 9c960a8c2494eb826a557a7ffc96dd4547f9d31e, if I select the sprite and then click on the “Edit Texture” button, I get an error:
ERROR: Condition "plugins_list.has(p_plugin)" is true.
at: EditorPluginList::add_plugin (editor\editor_node.cpp:8119)
Which I dont understand either.
About this issue
- Original URL
- State: closed
- Created a year ago
- Comments: 29 (24 by maintainers)
Commits related to this issue
- Fix Godot error caused by the terrain plugin handling more than one type. This was causing multiple plugins to handle the same object, which Godot is not expecting by design. (https://github.com/godo... — committed to Zylann/godot_voxel by Zylann 6 months ago
- Fix Godot error caused by the terrain plugin handling more than one type. This was causing multiple plugins to handle the same object, which Godot is not expecting by design. (https://github.com/godo... — committed to Piratux/godot_voxel by Zylann 6 months ago
Well that error appears when you try to edit multiple objects by the same plugin within the same editor context, which is very likely to happen when your plugin handles any resource.
@Zylann mentioned this error occurs when handling the same object by two different plugins, but I have the exact same error when handling subresources with just one plugin.
In my plugin I override
_handles(object)like so:But whenever I select a subresource in the inspector, I get:
What’s more, the subresource closes in the inspector, preventing me to edit it any further.
Had a look at the patch, it really looks like a hack. Seeing stuff like this in those functions makes things confusing compared to what they are meant for. Notably
handles, which in theory should only depend on the passed object, and not some state of the plugin, which now results in race conditions. The hack inmake_visibleis now also a source of race conditions. Everytime there is acall_deferred, it opens the door for more problems in the future. I wouldn’t have come up with this idea because it goes against what the methods are meant to do and seems to rather exploit Godot’s implementation details (which I’m not much aware of, I dont often inspect the editor’s core logic).I feel like Godot should have cleaner ways to code things for contextes like this. It constantly happens for me and it’s tiring to keep adding hacks because it feels like I’m loosing control and could break some random day. But not sure what would have to change… as I described earlier, the logic seems too restrictive, partially ill-formed or unclear (both in docs and error messages). Because even though the API could still assume only one “thing” is edited at a time, in practice it doesn’t always exist alone in a void, and may be nested in related resources, nodes or objects, which may be part of a whole context with interacting UIs. The sole fact you can have a node selected in the scene tree and a different object edited in the inspector is an example of this, but it goes beyond that of course.
I gave your patch a try, and seems to work when I select a graph resource in a terrain. Although I suppose the same hack must be added in other places as well: errors keep happening after I select nodes of the graph: clicking on a node uses the inspector to “edit” a custom object representing it (mostly because we can’t have extra inspectors). Then clicking on the background is supposed to “edit” the graph resource itself in the inspector. But when the graph gets edited that way, the error occurs everytime
editor\editor_node.cpp:8240 - Condition "plugins_list.has(p_plugin)" is true.. I suppose that’s because the graph editor plugin has to handle both graph resource and graph nodes to function properly but Godot doesnt like that (no idea why tho), but again I’m really confused about how else to cleanly handle that without messing up all the UIs that are supposed to be shown in this nested editing context.Actually, that second case I just described is indirectly triggered by my own code, which simply needs to use the inspector to edit a specific “sub-object” of my graph resource, while keeping the graph editing context: https://github.com/Zylann/godot_voxel/blob/cee2a86af4e6e9d76398856c868a20cf27b7052f/editor/graph/voxel_graph_editor_plugin.cpp#L195
Therefore, there might be a simpler solution than your hack here. I noticed this had a parameter
p_inspector_only, which the doc describes:Which sounds like it would solve this specific case, and I would be able to remove this sub-object class from
handles, getting rid of the error I had before. But when I providetrue, it makes no difference…edit(null)andmake_visible(false)are still called, so selecting a graph node now hides the whole graph editor (so plugins are NOT ignored), which defeats the whole point for me. Though in this case I could workardound with this:Which luckily seems to be working because neither
editnormake_visibleare deferred calls. (but of course using inspector prev/next arrows still break and hide the editor)No longer crashes on master. I guess the issue is resolved? You can’t handle the same object by two plugins at the same time, this is expected limitation.