61 lines
1.7 KiB
GDScript
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,
|
|
})
|