#if TOOLS [Tool] public partial class ReceiveInputInEditorPlugin : EditorPlugin { public override bool _Handles(GodotObject obj) => obj is Node; public override int _Forward3DGuiInput(Camera3D camera, InputEvent ev) { var root = (Node3D)EditorInterface.Singleton.GetEditedSceneRoot(); var viewport = root.GetViewport(); // Don't know about any negative effect of changing these and leaving them like that. viewport.GuiDisableInput = false; // Re-enable input, required for `PushInput` to work at all. viewport.HandleInputLocally = true; // Let sub-viewport handle its own input, makes `SetInputAsHandled` work as expected? // This will propagate input events into the edited scene, // including regular, GUI, shortcut, unhandled key and unhandled. viewport.PushInput(ev); // Enabling `PhysicsObjectPicking` causes `IsInputHandled()` 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.IsInputHandled() && (ev is InputEventMouse { Position: var mouse })) { // Ray is cast from the editor camera's view. var from = camera.ProjectRayOrigin(mouse); var to = from + camera.ProjectRayNormal(mouse) * camera.Far; // Actual collision is done in the edited scene though. var space = root.GetWorld3D().DirectSpaceState; var query = PhysicsRayQueryParameters3D.Create(from, to); var result = space.IntersectRay(query); // The collider object isn't necessarily a `CollisionObject3D`. var collider = (GodotObject)result.GetValueOrDefault("collider"); if (collider is CollisionObject3D { Visible: true } obj) { var pos = (Vector3)result["position"]; var normal = (Vector3)result["normal"]; var shape = (int)result["shape"]; obj._InputEvent(camera, ev, pos, normal, shape); } } // If any node calls `SetInputAsHandled()`, the event is not passed on to other editor gizmos / plugins. return viewport.IsInputHandled() ? (int)AfterGuiInput.Stop : (int)AfterGuiInput.Pass; } } #endif