|
|
|
@tool
|
|
|
|
extends EditorPlugin
|
|
|
|
|
|
|
|
func _handles(obj: Object) -> bool:
|
|
|
|
return obj is Node
|
|
|
|
|
|
|
|
func _forward_3d_gui_input(camera: Camera3D, event: InputEvent) -> int:
|
|
|
|
var root := EditorInterface.get_edited_scene_root() as Node3D
|
|
|
|
|
|
|
|
var viewport := root.get_viewport()
|
|
|
|
# Don't know about any negative effect of changing these and leaving them like that.
|
|
|
|
viewport.gui_disable_input = false # Re-enable input, required for `push_input` to work at all.
|
|
|
|
viewport.handle_input_locally = true # Let sub-viewport handle its own input, makes `set_input_as_handled` work as expected?
|
|
|
|
|
|
|
|
# This will propagate input events into the edited scene,
|
|
|
|
# including regular, GUI, shortcut, unhandled key and unhandled.
|
|
|
|
viewport.push_input(event)
|
|
|
|
|
|
|
|
# Enabling `physics_object_picking` causes `is_input_handled()` to always
|
|
|
|
# return true, and object picking isn't immediate anyway, so let's just
|
|
|
|
# do it ourselves. This doesn't support touch input, though.
|
|
|
|
if !viewport.is_input_handled() and event is InputEventMouse:
|
|
|
|
# Ray is cast from the editor camera's view.
|
|
|
|
var from := camera.project_ray_origin(event.position)
|
|
|
|
var to := from + camera.project_ray_normal(event.position) * camera.far
|
|
|
|
|
|
|
|
# Actual collision is done in the edited scene though.
|
|
|
|
var space := root.get_world_3d().direct_space_state
|
|
|
|
var query := PhysicsRayQueryParameters3D.create(from, to)
|
|
|
|
|
|
|
|
var result := space.intersect_ray(query)
|
|
|
|
# The collider object isn't necessarily a `CollisionObject3D`.
|
|
|
|
var obj := result.get("collider") as CollisionObject3D
|
|
|
|
if obj and obj.visible:
|
|
|
|
obj._input_event(camera, event, result["position"], result["normal"], result["shape"])
|
|
|
|
|
|
|
|
# If any node calls `set_input_as_handled()`, the event is not passed on to other editor gizmos / plugins.
|
|
|
|
return AfterGUIInput.AFTER_GUI_INPUT_STOP if viewport.is_input_handled() else AfterGUIInput.AFTER_GUI_INPUT_PASS
|