Skip to content

DRAFT: Add EditorCanvasItemGizmoPlugin for 2D (similar to 3D's Node3DEditorGizmoPlugin) #112979

Draft
derkork wants to merge 26 commits into
godotengine:masterfrom
derkork:proposal-1910
Draft

DRAFT: Add EditorCanvasItemGizmoPlugin for 2D (similar to 3D's Node3DEditorGizmoPlugin) #112979
derkork wants to merge 26 commits into
godotengine:masterfrom
derkork:proposal-1910

Conversation

@derkork
Copy link
Copy Markdown

@derkork derkork commented Nov 20, 2025

This adds Gizmo plugins for canvas items similar to what the Spatial Editor Gizmo plugin can do (see godotengine/godot-proposals#1910). This is intended to simplify building editor extensions for 2D objects, which currently has a lot of limitations.

Right now, this is still a draft. It's nowhere near finished, but I still wanted to put it up here so I could get some early feedback. Just to avoid running into the wrong direction for a long time, and then it's a big mess to clean everything up.

If that is not the correct way to do this, please let me know, and I will close this and reopen the merge request once I think it is in a state that I would consider finished.

My plan of attack right now is:

  • Implement the functionality of the Gizmo plugins so that add-ons and GD extensions can use them to create their own editor integrations that have a similar level of integration that we currently get with the 3D stuff.
  • Follow the style, approach and naming of the existing Node3D editor gizmo system as closely as possible to make it easy for engine developers to maintain both systems because they work in a consistent way.
  • I would keep the editors for the existing 2D nodes as they are right now. I'm hoping that with this approach we can get this feature into the engine quicker and with less risk of breaking mission-critical stuff.
  • Eventually, there would be a second pull request that migrates all the existing 2D editors to the new gizmo system and removes the plumbing that is currently used by the 2D editors, like all the _edit_* methods.

What is currently working:

  • You can register new canvas item gizmo plugins to GDScript.
  • You can draw stuff over nodes.
  • You can define picking collision shapes which are used to pick nodes with a single mouse click and rectangle selection.
  • You can define handles.
  • You can move handles.
  • You can define subgizmos.
  • You can select subgizmos (single pick and rectangle selection).
  • Gizmos can be shown and hidden in the gizmo menu.
  • You can define a boundary and a pivot and edit them (equivalent of _edit_get/set/has_rect and _edit/get/set/has/_pivot).
  • You can transform subgizmos (move/rotate/scale, supports temporary pivots).
  • Undo/redo fully works.
  • Documentation and demo project

What's still missing:

  • Polish, quite a bit of it.

@derkork derkork requested a review from a team as a code owner November 20, 2025 07:03
@derkork derkork requested review from a team November 20, 2025 07:03
@derkork derkork marked this pull request as draft November 20, 2025 07:04
@derkork derkork changed the title DRAFT: Add EditorCanvasGizmoPlugin for 2D (similar to 3D's SpatialEditorGizmoPlugin) DRAFT: Add EditorCanvasGizmoPlugin for 2D (similar to 3D's Node3DEditorGizmoPlugin) Nov 20, 2025
@AThousandShips AThousandShips added this to the 4.x milestone Nov 20, 2025
@AThousandShips
Copy link
Copy Markdown
Member

Please set up pre-commit hooks to make sure your PR is formatted correctly

@derkork
Copy link
Copy Markdown
Author

derkork commented Nov 28, 2025

Will do, thanks for the heads up!

Comment thread editor/scene/2d/canvas_item_editor_gizmos.h Outdated
Comment thread editor/scene/2d/canvas_item_editor_gizmos.cpp Outdated
Comment thread editor/scene/2d/canvas_item_editor_gizmos.cpp Outdated
Comment thread editor/scene/2d/canvas_item_editor_gizmos.cpp Outdated
Comment thread editor/scene/2d/canvas_item_editor_gizmos.cpp Outdated
Comment thread editor/scene/2d/canvas_item_editor_gizmos.cpp Outdated
Comment thread editor/scene/2d/canvas_item_editor_gizmos.cpp Outdated
Comment thread editor/scene/2d/canvas_item_editor_gizmos.cpp Outdated
Comment thread editor/scene/2d/canvas_item_editor_gizmos.cpp Outdated
Comment thread editor/scene/2d/canvas_item_editor_gizmos.cpp Outdated
@derkork
Copy link
Copy Markdown
Author

derkork commented Nov 28, 2025

Awesome, thanks a lot for the first once-over! I'll fix these up and try not make the same mistakes again.

@derkork derkork force-pushed the proposal-1910 branch 2 times, most recently from f597bf5 to 47778b3 Compare December 9, 2025 06:46
Comment thread editor/scene/canvas_item_editor_plugin.h Outdated
Comment thread editor/scene/canvas_item_editor_plugin.cpp Outdated
Comment thread editor/scene/canvas_item_editor_plugin.cpp Outdated
Comment thread editor/scene/canvas_item_editor_plugin.cpp Outdated
Comment thread editor/scene/2d/canvas_item_editor_gizmos.cpp Outdated
Comment thread editor/scene/2d/canvas_item_editor_gizmos.cpp Outdated
Comment thread editor/scene/2d/canvas_item_editor_gizmos.cpp Outdated
Comment thread editor/scene/2d/canvas_item_editor_gizmos.cpp Outdated
@derkork
Copy link
Copy Markdown
Author

derkork commented Dec 16, 2025

@AThousandShips thanks again for your review. Just to make your life easier, should i mark things as resolved manually or do you just ignore review items that GitHub marks as outdated?

@AThousandShips
Copy link
Copy Markdown
Member

AThousandShips commented Dec 16, 2025

You go ahead and mark them as resolved when you've made the changes, thank you for checking!

@derkork derkork force-pushed the proposal-1910 branch 2 times, most recently from 351dd87 to b66d493 Compare December 30, 2025 09:03
@derkork derkork force-pushed the proposal-1910 branch 2 times, most recently from 7de20cf to 3be9751 Compare January 13, 2026 21:15
@derkork derkork changed the title DRAFT: Add EditorCanvasGizmoPlugin for 2D (similar to 3D's Node3DEditorGizmoPlugin) DRAFT: Add EditorCanvasItemGizmoPlugin for 2D (similar to 3D's Node3DEditorGizmoPlugin) Mar 17, 2026
@derkork
Copy link
Copy Markdown
Author

derkork commented Mar 17, 2026

So I have now created an example project and also a documentation section for how to use all of this, which hopefully makes it a bit easier to review the whole thing because you can see how it's actually supposed to work - and we need this anyway. There are a few things I'm not super happy with, and I would appreciate some feedback/direction here:

Different ways of handling undo and redo

Currently, there are three different ways of handling undo and redo for sections of your Gizmo plugins:

  • Changes to the transforms are automatically handled by the editor.
  • Changes to handles and sub gizmos will need to be handled by having to create undo and redo actions by the users themselves.
  • Changes to the pivot require you to override the _edit_get_state/_edit_set_state methods. And then the editor will do the undo and redo for you.

This is mostly because I needed some way of keeping the legacy behavior without breaking too much stuff, while at the same time allowing for some freedom for the users to implement whatever they need. In the 3D Gizmos, there is a similar problem; however, they don't have the pivot issue, so they can get away with two different ways here.

The _redraw method requires proxying the draw API

Right now, when you want to draw any kind of shape inside of the redraw method, you need to call some drawing functions on the Gizmo. These basically are just for what it calls to the drawing API, which means whenever the drawing API changes or gets extended, I would need to add new methods there.

func _redraw(gizmo:EditorCanvasItemGizmo) -> void: 
    # this internally forwards draw_polygon when the editor is redrawn
    gizmo.add_polygon(polygon, Color(0.39215687, 0.58431375, 0.92941177, 0.8))

Even right now, it's not supporting all the methods of the drawing API because I'm not sure if that is really a good, sustainable design.

The gizmo may be doing too much

I tried to mimic the structure of the 3D gizmos as much as possible, as to not introduce too many new concepts here; however, 2D nodes have a lot of 2D-specific things, like the scaling rectangular outlines and the pivot support. In the internal nodes, this is all kind of mixed into the node code itself, with nodes having functions like _edit_get_rect or _edit_has_pivot. So the node implementation and the editor support for the node live in one class, basically.

With the gizmos, there is some divide where you have the editor support mostly in the gizmos, and the node class will focus on providing what is needed at runtime. I think I like that part; however, in order to make it work with the legacy system, I had to introduce these _edit_* methods to the Gizmo because they are the way how 2D specific constructs are handled. And this also adds some ambiguity, because actually only the first gizmo that is declared for any node will have a chance of overriding these methods, and the others will be ignored. On the other hand, I can't think of any good use case where you need more than one gizmo for a single node.

Currently only positive collision shapes are supported

Right now, you can only define positive collision shapes for picking. If you have something like a donut shape that has holes, you can only use a circle shape to approximate that, or you have to divy it up into sub-shapes that have no holes. I think ultimately, if we want to make any 2D shape pickable, we would need to have support for negative collision shapes as well. I think they are not super difficult to add. One could add a default boolean to the add_collision_* methods that indicates that the shape is negative, e.g.:

add_collision_rect(some_rect, true)  # the rect is a cutout

or maybe go with a second set of methods:

subtract_collision_rect(some_rect)

2D shape picking is currently not implemented anywhere in the editor, so before I spend time on that, I would like to ask if this is the right way to go or if we should do it in a different way.

@nubels
Copy link
Copy Markdown
Contributor

nubels commented Apr 11, 2026

Really looking forward to this feature, thank you very much for taking on the work! If I'm not mistaken, this would make it possible to implement this recently added feature for 2D as well.

#99569

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants