Files
agame/addons/surface_snap/plugin.gd
T
2026-10-02 03:40:31 +08:00

61 lines
1.7 KiB
GDScript

@tool
extends EditorPlugin
## Snaps a 3D object against the surface of another collidable object.
##
## Usage: Select a single Node3D, hold Alt
## and drag with the left mouse button over a collidable surface. Releasing
## the button confirms the move (registered in the editor's Undo/Redo).
##
## Configuration: Project Settings -> "surface_snap/collision_mask" controls
## which physics layers count as a valid snap surface.
var _snap_tool: SurfaceSnapTool = SurfaceSnapTool.new()
func _enter_tree() -> void:
_register_project_settings()
func _exit_tree() -> void:
if _snap_tool.is_dragging():
_snap_tool.cancel_drag()
func _handles(object: Object) -> bool:
return object is Node3D
func _edit(object: Object) -> void:
pass
func _forward_3d_gui_input(camera: Camera3D, event: InputEvent) -> int:
var selected_nodes: Array[Node] = EditorInterface.get_selection().get_selected_nodes()
var target: Node3D = null
if selected_nodes.size() == 1 and selected_nodes[0] is Node3D:
target = selected_nodes[0] as Node3D
var consumed: bool = _snap_tool.handle_input(camera, event, target, get_undo_redo())
if consumed:
return EditorPlugin.AFTER_GUI_INPUT_STOP
return EditorPlugin.AFTER_GUI_INPUT_PASS
func _register_project_settings() -> void:
var setting_name: String = SurfaceSnapTool.SETTING_COLLISION_MASK
var default_value: int = SurfaceSnapTool.DEFAULT_COLLISION_MASK
if not ProjectSettings.has_setting(setting_name):
ProjectSettings.set_setting(setting_name, default_value)
ProjectSettings.set_initial_value(setting_name, default_value)
ProjectSettings.add_property_info({
"name": setting_name,
"type": TYPE_INT,
"hint": PROPERTY_HINT_LAYERS_3D_PHYSICS,
})