Mouse Input
Mouse input is usually used to control a camera rotation, to pick objects in game world, etc. Let's take a look at the most common use cases.
Mouse Motion
The following example shows how to use raw mouse events to rotate an object. It could also be used to rotate a camera in your game (with slight modifications).
#![allow(unused)] fn main() { #[derive(Clone, Debug, Reflect, Visit, TypeUuidProvider, ComponentProvider)] #[type_uuid(id = "abbad54c-e267-4d7e-a3cd-e125a7e87ff0")] #[visit(optional)] pub struct Player { yaw: f32, pitch: f32, } impl ScriptTrait for Player { fn on_os_event(&mut self, event: &Event<()>, _ctx: &mut ScriptContext) { // We'll listen to MouseMotion raw device event to rotate an object. It provides // offsets only. if let Event::DeviceEvent { event: DeviceEvent::MouseMotion { delta: (dx, dy), .. }, .. } = event { self.pitch = (self.pitch + *dy as f32) .clamp(-std::f32::consts::FRAC_PI_2, std::f32::consts::FRAC_PI_2); self.yaw += *dx as f32; } } fn on_update(&mut self, ctx: &mut ScriptContext) { let node = &mut ctx.scene.graph[ctx.handle]; let transform = node.local_transform_mut(); transform.set_rotation( UnitQuaternion::from_axis_angle(&Vector3::x_axis(), self.pitch) * UnitQuaternion::from_axis_angle(&Vector3::y_axis(), self.yaw), ); } } }
This example consists of two main parts - on_os_event
and on_update
methods. The first one is called when some
event comes to the main window, and we need to check if this event is DeviceEvent::MouseMotion
. After that, we're taking
relative offsets (dx
, dy
) and modifying the pitch
, yaw
variables accordingly. on_update
method is called
every frame and it is used to apply pitch
and yaw
values to the scene node the script is assigned to.
Mouse Buttons
The following example shows how to handle events from mouse buttons.
#![allow(unused)] fn main() { #[derive(Clone, Debug, Reflect, Visit, TypeUuidProvider, ComponentProvider)] #[type_uuid(id = "abbad54c-e267-4d7e-a3cd-e125a7e87ff1")] #[visit(optional)] pub struct Clicker { counter: i32, } impl ScriptTrait for Clicker { fn on_os_event(&mut self, event: &Event<()>, _ctx: &mut ScriptContext) { if let Event::WindowEvent { event: WindowEvent::MouseInput { button, state, .. }, .. } = event { if *state == ElementState::Pressed { match *button { MouseButton::Left => { self.counter -= 1; } MouseButton::Right => { self.counter += 1; } _ => (), } } } } } }
At first, we're checking for WindowEvent::MouseInput
and creating respective bindings to its internals (button
, state
)
and then all we need to do, is to check if the button was pressed and if so, which one.