feat: Enhance selection and grid functionality in sandbox stage and gizmos
This commit is contained in:
@@ -81,6 +81,7 @@ var _status_label: Label
|
||||
var _grid_check: CheckBox
|
||||
var _snap_check: CheckBox
|
||||
var _grid_size_spin: SpinBox
|
||||
var _grid_size_label: Label
|
||||
|
||||
var _grid_size: float = DEFAULT_GRID_SIZE
|
||||
var _snap_enabled: bool = false
|
||||
@@ -140,7 +141,13 @@ func _physics_process(_delta: float) -> void:
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
func _input(event: InputEvent) -> void:
|
||||
if event is InputEventMouseButton:
|
||||
if event is InputEventMagnifyGesture:
|
||||
# Touchpad pinch zoom.
|
||||
_set_zoom(_camera.zoom.x * (event as InputEventMagnifyGesture).factor)
|
||||
elif event is InputEventPanGesture:
|
||||
# Touchpad two-finger pan (delta is screen px; ×3 for speed parity).
|
||||
_camera.position -= (event as InputEventPanGesture).delta * 3.0 / _camera.zoom.x
|
||||
elif event is InputEventMouseButton:
|
||||
_handle_mouse_button(event)
|
||||
elif event is InputEventMouseMotion:
|
||||
_handle_mouse_motion(event)
|
||||
@@ -249,12 +256,16 @@ func _enter_edit_mode() -> void:
|
||||
# so re-assert the authored transform on the next few physics frames.
|
||||
_restore_frames_left = 3
|
||||
_gizmos.set_enabled(true)
|
||||
_apply_grid_settings()
|
||||
_set_build_controls_visible(true)
|
||||
|
||||
|
||||
func _enter_play_mode() -> void:
|
||||
_gizmos.set_enabled(false)
|
||||
_selection.clear_selection()
|
||||
set_placement_mode("")
|
||||
_apply_grid_settings()
|
||||
_set_build_controls_visible(false)
|
||||
for node: Node2D in _world_children_selectable():
|
||||
if node is RigidBody2D:
|
||||
(node as RigidBody2D).freeze = false
|
||||
@@ -384,6 +395,9 @@ func _begin_click_select(world_pos: Vector2, shift: bool) -> void:
|
||||
_selection.toggle_selection(hit)
|
||||
if _selection.is_selected(hit):
|
||||
_gizmos.begin_translate_drag(hit, world_pos)
|
||||
elif _selection.is_selected(hit):
|
||||
# Already selected: keep the whole selection and drag it together.
|
||||
_gizmos.begin_translate_drag(hit, world_pos)
|
||||
else:
|
||||
_selection.select_only(hit)
|
||||
_gizmos.begin_translate_drag(hit, world_pos)
|
||||
@@ -482,9 +496,9 @@ func _build_ui() -> void:
|
||||
_snap_check.toggled.connect(_on_snap_toggled)
|
||||
hbox.add_child(_snap_check)
|
||||
|
||||
var grid_label := Label.new()
|
||||
grid_label.text = "Size"
|
||||
hbox.add_child(grid_label)
|
||||
_grid_size_label = Label.new()
|
||||
_grid_size_label.text = "Size"
|
||||
hbox.add_child(_grid_size_label)
|
||||
|
||||
_grid_size_spin = SpinBox.new()
|
||||
_grid_size_spin.min_value = MIN_GRID_SIZE
|
||||
@@ -555,8 +569,8 @@ func _on_grid_size_changed(value: float) -> void:
|
||||
_save_settings()
|
||||
|
||||
|
||||
func _on_selection_changed(nodes: Array) -> void:
|
||||
_gizmos.set_target(_selection.get_primary())
|
||||
func _on_selection_changed(nodes: Array[Node2D]) -> void:
|
||||
_gizmos.set_targets(nodes)
|
||||
if nodes.is_empty():
|
||||
object_deselected.emit()
|
||||
else:
|
||||
@@ -568,8 +582,9 @@ func _on_hover_changed(node: Node2D) -> void:
|
||||
_gizmos.set_hover(node)
|
||||
|
||||
|
||||
func _on_transform_committed(node: Node2D) -> void:
|
||||
_save_object_state(node)
|
||||
func _on_transform_committed(nodes: Array[Node2D]) -> void:
|
||||
for node: Node2D in nodes:
|
||||
_save_object_state(node)
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Helpers
|
||||
@@ -577,7 +592,12 @@ func _on_transform_committed(node: Node2D) -> void:
|
||||
|
||||
func _set_zoom(value: float) -> void:
|
||||
var z := clampf(value, min_zoom, max_zoom)
|
||||
var old_zoom := _camera.zoom.x
|
||||
if is_equal_approx(z, old_zoom):
|
||||
return
|
||||
var mouse_world := _camera.get_global_mouse_position()
|
||||
_camera.zoom = Vector2(z, z)
|
||||
_camera.position = mouse_world - (mouse_world - _camera.position) * (old_zoom / z)
|
||||
|
||||
|
||||
func _is_mouse_over_ui() -> bool:
|
||||
@@ -594,10 +614,24 @@ func _apply_grid_settings() -> void:
|
||||
if _grid != null:
|
||||
_grid.grid_size = _grid_size
|
||||
_grid.enabled = _show_grid
|
||||
_grid.visible = _show_grid and current_mode == StageMode.EDIT
|
||||
if _gizmos != null:
|
||||
_gizmos.snap_size = _grid_size if _snap_enabled else 0.0
|
||||
|
||||
|
||||
func _set_build_controls_visible(visible: bool) -> void:
|
||||
for btn: Button in _palette_buttons.values():
|
||||
btn.visible = visible
|
||||
if _grid_check != null:
|
||||
_grid_check.visible = visible
|
||||
if _snap_check != null:
|
||||
_snap_check.visible = visible
|
||||
if _grid_size_spin != null:
|
||||
_grid_size_spin.visible = visible
|
||||
if _grid_size_label != null:
|
||||
_grid_size_label.visible = visible
|
||||
|
||||
|
||||
## Direct Node2D children of World, excluding the ragdoll body container.
|
||||
func _world_children_selectable() -> Array[Node2D]:
|
||||
var result: Array[Node2D] = []
|
||||
|
||||
Reference in New Issue
Block a user