Transform Visibility in Editor

Godot Version

4.3

Question

Greetings -

I have a question from our designer that I don’t have a good answer for, so I thought I’d ask here.

We’ve shipped a game in Unity and are working in Godot for our next game. We’ve been at it for a while, and have pretty good progress, but she’s finding Godot is somewhat less productive than Unity, and I’m trying to understand why.

The biggest pain point she’s mentioned is that the transform for a node, something that she’s working with constantly, isn’t always visible by default when she opens a scene or clicks a node, so it’s “open scene, click Layout, click Transform” to see or edit the coordinates, over and over.

Is there a better way to do this? As a design tool, she’d really like to be always have easy access to the Layout controls.

Anyone else run into this? What’s a good workflow?

Thanks

  • Steve
1 Like

I think it is not a big problem, as you said that you are working on 2d. In every engines you need to open multi scenes as necessary, just the thing is you need to go to layout > transform to change the position or you can also change it with the moving tool or arrow keys. After some practice, it can be a regular things, your hands can almost automatically do it. Just need some practice, it is not a problem at all.

It’s a problem for our designer; telling her to get used to it isn’t really what I’m looking for. She’s been working with Godot for months now, and this is her #1 complaint.

Some things that would help:

  • An add-on that always shows the coordinates?
  • A way of “pinning” some parts of the inspector so they’re always open?

You can just search “position” in the search bar of nodes properties, then if you change nodes, the search bar does not change so you can easily change the position.

If it is important then please can you give me an example on what you mean?

That works for Position specifically, but if I search for Transform, when I switch nodes, requires that I expand the Transform node to see the Position, Size and Scale.

To a developer, easy access to the script editor is important, and Godot offers lots of shortcuts to do that. To our designer, easy access to the positioning is important, and it’s awkward to get to. It’s a workflow paper cut - having to click extra buttons to get to the info you want every time.

Unity, for example, keeps this stuff visible at the top of the inspector. As a developer I understand how nodes work and why the transform is where it is. But I do agree that for a designer the visual properties that are important can get buried in the inspector.

By pinning I meant a way to mark a section of the inspector as “always open” as you switch objects. I think that could be generally useful.

I’m not familiar with Godot’s addons infrastructure but is this something that could be implemented in an add-on?

2 Likes

I did not find anything on it.

It is possible through an addon, you probably want to use add_control_to_container(CustomControlContainer.CONTAINER_CANVAS_EDITOR_MENU) for 2d

To try it out I made a little toolbar addon in my addons/ez_transform2d folder. All the following files should be placed in the same path.

plugin.cfg
[plugin]

name="ez transform2d"
description="Shows 2D node position and scale in the toolbar"
author="Garrett Hale"
version=""
script="ez_transform2d.gd"
ez_transform2d.gd
@tool
extends EditorPlugin

var toolbar2d: Control

func _enter_tree() -> void:
	var toolbar2d_prefab: PackedScene = load("res://addons/ez_transform2d/toolbar_2d.tscn")
	toolbar2d = toolbar2d_prefab.instantiate()
	toolbar2d.hide()
	toolbar2d.ur = get_undo_redo()
	add_control_to_container(CustomControlContainer.CONTAINER_CANVAS_EDITOR_MENU, toolbar2d)
	var selection := EditorInterface.get_selection()
	selection.selection_changed.connect(new_selection)


func new_selection() -> void:
	var selection := EditorInterface.get_selection().get_selected_nodes()
	if selection.size() == 1:
		toolbar2d.read_node(selection[0] as Node2D)
	else:
		toolbar2d.read_node(null)


func _exit_tree() -> void:
	remove_control_from_container(CustomControlContainer.CONTAINER_CANVAS_EDITOR_MENU, toolbar2d)
toolbar_2d.tscn
[gd_scene load_steps=2 format=3 uid="uid://cqiw7j52x7aq5"]

[ext_resource type="Script" path="res://addons/ez_transform2d/toolbar_2d.gd" id="1_4007g"]

[node name="Control" type="HBoxContainer"]
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 2
script = ExtResource("1_4007g")

[node name="position_x" type="SpinBox" parent="."]
layout_mode = 2
min_value = -9999.0
max_value = 9999.0
allow_greater = true
allow_lesser = true
suffix = "x"

[node name="position_y" type="SpinBox" parent="."]
layout_mode = 2
min_value = -9999.0
max_value = 9999.0
allow_greater = true
allow_lesser = true
suffix = "y"

[node name="VSeparator" type="VSeparator" parent="."]
layout_mode = 2

[node name="scale_x" type="SpinBox" parent="."]
layout_mode = 2
max_value = 9.5
allow_greater = true
allow_lesser = true
suffix = "x"

[node name="scale_y" type="SpinBox" parent="."]
layout_mode = 2
max_value = 9.5
allow_greater = true
allow_lesser = true
suffix = "y"

[node name="CommitDebounce" type="Timer" parent="."]
wait_time = 0.6
one_shot = true

[connection signal="timeout" from="CommitDebounce" to="." method="_on_commit_debounce_timeout"]

toolbar_2d.gd
@tool
extends HBoxContainer

var ur: EditorUndoRedoManager
var target: Node2D

@onready var timer: Timer = $CommitDebounce


func read_node(new_node: Node2D) -> void:
	target = new_node
	if target:
		$position_x.set_value_no_signal(target.position.x)
		$position_y.set_value_no_signal(target.position.y)

		$scale_x.set_value_no_signal(target.scale.x)
		$scale_y.set_value_no_signal(target.scale.y)
	visible = target != null


func _ready() -> void:
	for child in get_children():
		if child is Range:
			var name_as_property := child.name.replace("_", ":")
			child.value_changed.connect(update_value.bind(name_as_property))


var commit_property: String
var commit_original: float

func update_value(val: float, vname: String) -> void:
	if commit_property != "" and commit_property != vname:
		_on_commit_debounce_timeout()

	if commit_property == "":
		commit_original = target.get_indexed(vname)
		commit_property = vname

	target.set_indexed(vname, val)
	timer.start(0.6)


func _on_commit_debounce_timeout() -> void:
	if commit_property != "":
		ur.create_action("%s %s" % [commit_property, target.name])
		ur.add_do_method(target, "set_indexed", commit_property, target.get_indexed(commit_property))
		ur.add_undo_method(target, "set_indexed", commit_property, commit_original)
		ur.commit_action()
		commit_property = ""

Apologies, I did go for more clever solutions, especially in toolbar_2d.gd it changes properties using the name of the toolbar’s nodes. The EditorUndoRedoManager is a great feature that’s easy to forget when making an addon.

Here’s what the basic toolbar looks like

2024-10-28-141457_465x379_scrot

3 Likes

I think this is the solution to the problem!

Wow that looks great - thank you. I will try it out!

1 Like

Looks like pinned properties is coming in 4.4!

2 Likes

That’s great news!

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.