-
-
Notifications
You must be signed in to change notification settings - Fork 97
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Implement a way for EditorPlugins to get 2D Editor Grid Snap #10529
Implement a way for EditorPlugins to get 2D Editor Grid Snap #10529
Comments
You can hack it around by finding the snap dialog in scene tree and reading its values. |
This is a good temporary solution and I thank you for it, but it's still a needless hack considering how common this use case is for 2D plugins. |
For anyone who comes across this in future and wants to use this, here's a version of the code working in Godot 4.3.0 var snap_enabled: bool = false
var snap_dimensions: Vector2 = Vector2.ZERO
var snap_offset: Vector2 = Vector2.ZERO
func _ready() -> void:
connect_to_snap()
func connect_to_snap() -> void:
if not Engine.is_editor_hint():
return
var snap: Node = EditorInterface.get_editor_main_screen()\
.get_child(0).get_child(2).get_child(0).get_child(0)
# this is a terrible line of code but I don't have a better way to do it
var snaptoggle: Button = EditorInterface.get_editor_main_screen().\
get_child(0).get_child(0).get_child(0).get_child(0).get_child(12)
snap_enabled = snaptoggle.button_pressed
snaptoggle.toggled.connect(func(tog: bool) -> void: snap_enabled = tog)
# grid offset x
snap.get_child(1).value_changed.connect(func(val: float) -> void: snap_offset.x = val)
# grid offset y
snap.get_child(2).value_changed.connect(func(val: float) -> void: snap_offset.y = val)
snap_offset = Vector2(snap.get_child(1).value, snap.get_child(2).value)
# grid snap x
snap.get_child(7).value_changed.connect(func(val: float) -> void: snap_dimensions.y = val)
# grid snap y
snap.get_child(8).value_changed.connect(func(val: float) -> void: snap_dimensions.y = val)
snap_dimensions = Vector2(snap.get_child(7).value, snap.get_child(8).value) This code will break if any of the relevant nodes are offset in the tree, but this is the only way I could find to do it without being dependent on using |
Finding base controls can be more reliable: func nice_find_child(parent: Node, child: String) -> Node:
return parent.find_child("*%s*" % child, true, false)
func connect_to_snap() -> void:
var snap := nice_find_child(EditorInterface.get_base_control(), "SnapDialog") # SnapDialog
snap = nice_find_child(snap_grid, "GridContainer") # SpinBox container.
var snap_toggle := nice_find_child(EditorInterface.get_base_control(), "CanvasItemEditor") # 2D editor.
snap_toggle = nice_find_child(snap_toggle, "HBoxContainer") # Toolbar.
snap_toggle = snap_toggle.get_child(12) # Snap button. You can also avoid While it's still a hack, it's a bit more resilient to hierarchy changes. |
I actually started out by using Again, while it's good to have a method to do so, something this important for 2D editor plugins shouldn't be so hacky. |
I found my way back here again as I'm trying to also make a set of handles for the editor I made various helpers inspired by code found here. The methods all aimed to make it more obvious if a Editor's tree changed. You can find them all here:
Using these methods (loaded into the var helpers = load(<wherever you put the code I linked above>).new()
var found_all_editor_controls = false
var snap_enabled: bool = false
var snap_step : Vector2 = Vector2.ZERO
var snap_offset: Vector2 = Vector2.ZERO
var editor_controls = {
dialog = null,
grid_offset_x = null,
grid_offset_y = null,
grid_snap_x = null,
grid_snap_y = null,
snap_toggle = null
}
func _init():
if(Engine.is_editor_hint()):
setup_controls()
update_values_from_editor()
func setup_controls():
var main_screen = EditorInterface.get_editor_main_screen()
editor_controls.snap_toggle = helpers.safe_get_descendant(main_screen, ["HBoxContainer", 12], Button)
var snap_dia_grid_container = helpers.safe_get_descendant(main_screen, ["SnapDialog", "GridContainer"], GridContainer)
editor_controls.grid_offset_x = helpers.safe_get_child(snap_dia_grid_container, 1, SpinBox)
editor_controls.grid_offset_y = helpers.safe_get_child(snap_dia_grid_container, 2, SpinBox)
editor_controls.grid_snap_x = helpers.safe_get_child(snap_dia_grid_container, 4, SpinBox)
editor_controls.grid_snap_y = helpers.safe_get_child(snap_dia_grid_container, 5, SpinBox)
editor_controls.dialog = helpers.find_child_with_name_containing(main_screen, "SnapDialog", ConfirmationDialog)
if(null in editor_controls.values()):
push_error("One or more Editor Controls could not be found.")
return
else:
found_all_editor_controls = true
editor_controls.snap_toggle.toggled.connect(func(tog: bool) -> void: snap_enabled = tog)
editor_controls.dialog.get_ok_button().pressed.connect(update_values_from_editor)
func update_values_from_editor():
if(!found_all_editor_controls):
return
snap_enabled = editor_controls.snap_toggle.button_pressed
snap_offset.x = editor_controls.grid_offset_x.value
snap_offset.y = editor_controls.grid_offset_y.value
snap_step.x = editor_controls.grid_snap_x.value
snap_step.y = editor_controls.grid_snap_y.value |
I was looking for this feature back in Godot's 3rd version. Years have passed, I've moved on to version 4, and I find myself searching for a solution to this for the third time. I don’t understand why it’s made so inaccessible, at least on the EditorPlugin side. It’s a significant shortcoming. Edit: I should also mention that the hacks shared above don’t always work reliably. |
Describe the project you are working on
A plugin with a node that has custom handles for scaling/moving in the editor.
Describe the problem or limitation you are having in your project
There is no way to access grid snap to force the item to snap to the grid by default
Describe the feature / enhancement and how it helps to overcome the problem or limitation
Implement some sort of
get_grid_snap()
function on EditorPlugin, EditorInterface, or the otherwise most relevant class.Describe how your proposal will work, with code, pseudo-code, mock-ups, and/or diagrams
You would call a function to get the snapping intervals, as well as whether snap is enabled/disabled.
If this enhancement will not be used often, can it be worked around with a few lines of script?
Nope, you need to implement an entire grid system yourself, which is generally much more confusing to people using the plugin.
Is there a reason why this should be core and not an add-on in the asset library?
Core editor functionality.
The text was updated successfully, but these errors were encountered: