godotengine / godot-proposals

Godot Improvement Proposals (GIPs)
MIT License
1.16k stars 97 forks source link

Expose `CanvasItem::_edit_xxx()` methods to GDExtensions #10985

Open badlogic opened 1 month ago

badlogic commented 1 month ago

Describe the project you are working on

I'm building a GDExtension variant of spine-godot, in order to be able to make distribution simpler, not require a custom engine build, and target consoles as well. spine-godot has so far been implemented as an engine module.

Describe the problem or limitation you are having in your project

spine-godot features a SpineSprite class deriving from Node2D and thus CanvasItem. When compiling the engine module for use with the editor (TOOLS_ENABLED), SpineSprite implements the CanvasItem::_edit_use_rect() and CanvasItem::_edit_get_rect() methods so that CanvasItemEditor can derrive a bounding box to be manipulated with gizmos in the 2D viewport. Many other "base types" in Godot, like Sprite2D, implement this part of the CanvasItem interface as well to get gizmo support.

These two methods can not be overriden in GDExtension when deriving from Node2D, so subclasses of Node2D written using GDExtension will not interact well with CanvasItemEditor. This is not ideal from a user experience point of view.

In engine module "mode", a SpineSprite is shown in the 2D viewport with a bounding box that can be used both for selection via mouse click, and scaling.

Screenshot 2024-10-17 at 10 27 19

In GDExtension, a SpineSprite is only selectable in the scene tree to the left, or by precisely clicking the cross-hair gizmo. It can not be scaled via handles either.

Screenshot 2024-10-17 at 11 00 24

Describe the feature / enhancement and how it helps to overcome the problem or limitation

godot-cpp exposes the CanvasItem::_edit_xxx() methods. This would allow GDExtensions to implement CanvasItem subclasses the nicely interact with CanvasItemEditor.

Describe how your proposal will work, with code, pseudo-code, mock-ups, and/or diagrams

The CanvasItem::_edit_xxx() need to be exposed to GDExtension by declaring them using the appropriate GDVIRTUAL macro. They also need to be added to the extension_api.json generated by Godot and found in godot-cpp. Finally, engine "base types" that override the CanvasItem::__edit_xxx() classes, like Sprite2D, need to be adjusted due to GDVIRTUAL.

If this enhancement will not be used often, can it be worked around with a few lines of script?

There is no work around, as CanvasItemEditor relies on the CanvasItem::_edit_xxx() methods to perform its task. The only alternative would be for every GDExtension to basically duplicate what CanvasItemEditor does with its own editor plugin. It's unclear how that would work in combination with an active CanvasItemEditor. Ideally, there shouldn't be a need to re-implement CanvasItemEditor in every GDExtension that wants 2D gizmos for its own CanvasItem subclasses.

Is there a reason why this should be core and not an add-on in the asset library?

Exposing the CanvasItem::_edit_xxx() methods to GDExtension requires to change them to use GDVIRTUAL in order for them to be overrideable by a GDExtension.

Many "base types" in Godot, like Sprite2D implement the CanvasItem::_edit_xxx() methods. When using GDVIRTUAL in CanvasItem, these classes also need to be adjusted accordingly.

sockeye-d commented 1 month ago

Exposing them to GDExtension will also expose them to GDScript, right?