Orbit Gizmo

The Orbit Gizmo is a common GUI element that is used to visualize the current orientation of the 3D viewport and to select and drag nodes of this Gizmo to rotate the view.

orbit gizmo

We may click on circle node parts of the Gizmo to flip between pre-defined view orientations where a particular axis or its inverse faces the camera.

Clicking and dragging on it results in rotation controlled by mouse movements until the left mouse button is released.

orbit gizmo

I copied the basic style of this tool as it is in Blender but configured the axes to be as per Godot orientation.

I based the rotations on X and Y axes which is not exactly how it is done in Blender since they always rotate about the y (actually z, but I am translating to Godot orientation) and x/z axes. The plan is to re-visit how I do this or have it customizable in the future.

My implementation involved having a Node2D as a scene root node with a TexRect node as a child.

So, this scene will be instantiated in the 3D view and its position controlled by code since it is likely to sit in the top right corner of the Viewport.

The choice of TexRect for the content node is because I want to display images and respond to user inputs such as mouse events in the area of the image.

I do almost everything in code such as generating the images for circles and adding extra TexRect nodes for the inner circles.

Also, I created a shader to render a circle that may be solid, highlighted or contain a ring around it (for items to the rear).

To display text for the axis labels, I added child Label nodes to each of the inner circle nodes. I considered including text rendering in the shader, but that seemed to be quite difficult and messy compared to using Label nodes that produce nice results such as anti-aliased text and the ability to apply a theme etc.

The nodes of the Gizmo are added in order of how deep they are in the scene. Basically, there are 3 small circles at the back, connecting lines in the middle and 3 small circles at the front.

The script logic keeps track of what each circle represents as the Gizmo is rotated and clicked on. And it updates the text and shader parameters accordingly.

To draw axis lines I used the canvas draw features of Godot. But they are rendered before anything else, yet I have some circles in the rear. But thankfully we may check the show behind parent property of the canvas item to fix this issue without resorting to implementing a special node just to draw the lines between sibling nodes.

One thing to note is that this Gizmo represents a 3D widget but only uses 2D to do so. I am carrying this idea over to my implementation of the main scene 3D Gizmo tool.

I also implemented a draggable button based on this to mimic the buttons that we have in Blender below this Gizmo for Zoom and Move operations via dragging the mouse after clicking the buttons.

The state management of highlighting the background circle and the mouse events were one of the challenges here. One cool feature was that I could warp the hidden mouse cursor back to where it started dragging out from. This kind of thing would have been at least tricky to do without it being a built-in feature I think.

One more feature that I want to add to this Gizmo later is a click zone to frame the current object in the view after it has been lost such as zooming or panning too far away from it like is done in FreeCAD.

So this was a fun but challenging feature to add, more to follow …

More Blog posts

Most recent first