@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