Pass joystick axis information

This commit is contained in:
hodasemi 2025-03-12 08:19:59 +01:00
parent cf3d4f142a
commit 7d8f24a463
5 changed files with 104 additions and 47 deletions

View file

@ -20,7 +20,7 @@ pub enum EngineEvent<'a> {
JoystickButtonDown(&'a Joystick), JoystickButtonDown(&'a Joystick),
JoystickButtonUp(&'a Joystick), JoystickButtonUp(&'a Joystick),
JoystickAxis(&'a Joystick), JoystickAxis(&'a Joystick, u8, i16),
JoystickAdded(&'a Joystick), JoystickAdded(&'a Joystick),
JoystickRemoved(&'a Joystick), JoystickRemoved(&'a Joystick),
@ -91,9 +91,10 @@ impl Engine {
Self::controller_removed(world, consumer, controller)? Self::controller_removed(world, consumer, controller)?
} }
Event::JoystickAxis(joystick) => { Event::JoystickAxis(joystick, axis_index, value) => consumer.event(
consumer.event(world, EngineEvent::JoystickAxis(joystick))? world,
} EngineEvent::JoystickAxis(joystick, axis_index, value),
)?,
Event::JoystickButtonDown(joystick) => { Event::JoystickButtonDown(joystick) => {
consumer.event(world, EngineEvent::JoystickButtonDown(joystick))? consumer.event(world, EngineEvent::JoystickButtonDown(joystick))?
} }

View file

@ -44,6 +44,10 @@ pub struct FreeSpaceControl {
rotation: Vector3<Deg<f32>>, rotation: Vector3<Deg<f32>>,
position: Vector3<f32>, position: Vector3<f32>,
current_translation: Matrix4<f32>,
current_rotation: Matrix3<f32>,
current_transform: Matrix4<f32>,
/// (yaw, pitch, roll) /// (yaw, pitch, roll)
input_rotation: Vector3<f32>, input_rotation: Vector3<f32>,
/// (forward, sideward, upward) /// (forward, sideward, upward)
@ -60,6 +64,10 @@ impl FreeSpaceControl {
rotation: vec3(Deg(0.0), Deg(0.0), Deg(0.0)), rotation: vec3(Deg(0.0), Deg(0.0), Deg(0.0)),
position: Vector3::zero(), position: Vector3::zero(),
current_translation: Matrix4::one(),
current_rotation: Matrix3::one(),
current_transform: Matrix4::one(),
input_rotation: Vector3::zero(), input_rotation: Vector3::zero(),
input_position: Vector3::zero(), input_position: Vector3::zero(),
@ -125,12 +133,12 @@ impl FreeSpaceControl {
* Matrix3::from_angle_x(self.rotation.z) * Matrix3::from_angle_x(self.rotation.z)
} }
pub fn update(&mut self, now: Duration) -> Option<Matrix4<f32>> { pub fn update(&mut self, now: Duration) {
let diff = match self.last_update { let diff = match self.last_update {
Some(last_update) => now - last_update, Some(last_update) => now - last_update,
None => { None => {
self.last_update = Some(now); self.last_update = Some(now);
return None; return;
} }
}; };
@ -140,7 +148,21 @@ impl FreeSpaceControl {
self.add_rotation(rotation_changes); self.add_rotation(rotation_changes);
self.position += rotated_position_changes; self.position += rotated_position_changes;
Some(Matrix4::from_translation(self.position) * Matrix4::from(self.rotation_matrix())) self.current_translation = Matrix4::from_translation(self.position);
self.current_rotation = self.rotation_matrix();
self.current_transform = self.current_translation * Matrix4::from(self.current_rotation);
}
pub fn translation(&self) -> Matrix4<f32> {
self.current_translation
}
pub fn rotation(&self) -> Matrix3<f32> {
self.current_rotation
}
pub fn transform(&self) -> Matrix4<f32> {
self.current_transform
} }
#[rustfmt::skip] #[rustfmt::skip]

View file

@ -65,7 +65,7 @@ void main()
if (pay_load.distance == -1.0) { if (pay_load.distance == -1.0) {
position = vec3(INFINITY); position = vec3(INFINITY);
} else { } else if (pay_load.color.w > 0.0) {
position = origin.xyz + pay_load.distance * direction.xyz; position = origin.xyz + pay_load.distance * direction.xyz;
imageStore(output_image, ivec2(gl_LaunchIDEXT.xy), vec4(pay_load.color.xyz, 1.0)); imageStore(output_image, ivec2(gl_LaunchIDEXT.xy), vec4(pay_load.color.xyz, 1.0));
} }

View file

@ -3,7 +3,10 @@ use std::collections::HashMap;
use anyhow::Result; use anyhow::Result;
use ecs::*; use ecs::*;
use engine::prelude::*; use engine::prelude::{
cgmath::{Vector3, Vector4},
*,
};
#[derive(Clone, Copy, Debug)] #[derive(Clone, Copy, Debug)]
struct PlayerEntity(Entity); struct PlayerEntity(Entity);
@ -33,35 +36,35 @@ enum Control {
} }
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
struct ControllerSettings { struct InputSettings {
mappings: HashMap<(String, Input), Control>, mappings: HashMap<(String, Input), Control>,
} }
impl Default for ControllerSettings { impl Default for InputSettings {
fn default() -> Self { fn default() -> Self {
Self { Self {
mappings: [ mappings: [
( (
("Controller 1".to_string(), Input::Axis(0)), ("Joystick 1".to_string(), Input::Axis(0)),
Control::Throttle, Control::Throttle,
), ),
( (
("Controller 1".to_string(), Input::Axis(1)), ("Joystick 1".to_string(), Input::Axis(1)),
Control::StrafeHorizontal, Control::StrafeHorizontal,
), ),
( (
("Controller 1".to_string(), Input::Axis(2)), ("Joystick 1".to_string(), Input::Axis(2)),
Control::StrafeVertical, Control::StrafeVertical,
), ),
(("Controller 1".to_string(), Input::Axis(3)), Control::Pitch), (("Joystick 1".to_string(), Input::Axis(3)), Control::Pitch),
( (
("Controller 1".to_string(), Input::Button(Button::One)), ("Joystick 1".to_string(), Input::Button(Button::One)),
Control::PrimaryWeapon, Control::PrimaryWeapon,
), ),
(("Controller 2".to_string(), Input::Axis(1)), Control::Yaw), (("Joystick 2".to_string(), Input::Axis(1)), Control::Yaw),
(("Controller 2".to_string(), Input::Axis(0)), Control::Roll), (("Joystick 2".to_string(), Input::Axis(0)), Control::Roll),
( (
("Controller 2".to_string(), Input::Button(Button::One)), ("Joystick 2".to_string(), Input::Button(Button::One)),
Control::SecondaryWeapon, Control::SecondaryWeapon,
), ),
] ]
@ -71,14 +74,10 @@ impl Default for ControllerSettings {
} }
} }
impl ControllerSettings { impl InputSettings {
pub fn map_axis( pub fn map_axis(&self, device_name: impl ToString, axis: u8) -> Option<Control> {
&self,
controller_name: impl ToString,
axes: ControllerAxis,
) -> Vec<(Control, f32)> {
self.mappings self.mappings
.get(&controller_name.to_string()) .get(&(device_name.to_string(), Input::Axis(axis)))
.map(|control| *control) .map(|control| *control)
} }
} }
@ -92,26 +91,30 @@ impl Game {
pub fn event(&mut self, world: &mut World, event: EngineEvent<'_>) -> Result<()> { pub fn event(&mut self, world: &mut World, event: EngineEvent<'_>) -> Result<()> {
let player = world.resources.get::<PlayerEntity>(); let player = world.resources.get::<PlayerEntity>();
let fighter_object = world.entity_mut(player.0)?; let (fighter_object, resources) = world.entity_resources(player.0)?;
match event { match event {
EngineEvent::MouseButtonDown(MouseButton::Left) => { EngineEvent::JoystickAxis(joystick, axis_index, value) => {
let camera_control = world.resources.get_mut::<FreeCameraControl>(); let normalized = value as f32 * (i16::MAX as f32).recip();
camera_control.mouse_down(); let input_settings = resources.get::<InputSettings>();
} let player_control = fighter_object.get_component_mut::<FreeSpaceControl>()?;
EngineEvent::MouseButtonUp(MouseButton::Left) => {
let camera_control = world.resources.get_mut::<FreeCameraControl>();
camera_control.mouse_release();
}
EngineEvent::MouseMotion(x, y) => {
let mut resources = world.resources.multi_mut();
let scene = resources.get::<Scene>();
let camera_control = resources.get::<FreeCameraControl>();
camera_control.mouse_move(x, y, scene.view_mut())?; if let Some(control) = input_settings.map_axis(joystick.name(), axis_index) {
match control {
Control::Throttle => player_control.set_throttle(normalized),
Control::StrafeHorizontal => {
player_control.set_left_right_strafe(normalized)
} }
Control::StrafeVertical => player_control.set_up_down_strafe(normalized),
Control::Yaw => player_control.set_yaw(normalized),
Control::Pitch => player_control.set_pitch(normalized),
Control::Roll => player_control.set_roll(normalized),
EngineEvent::ControllerAxis(controller, axis) => {} Control::PrimaryWeapon => (),
Control::SecondaryWeapon => (),
}
}
}
_ => (), _ => (),
} }
@ -129,6 +132,8 @@ impl Game {
EmptyFilter, EmptyFilter,
)?; )?;
world_builder.add_update("camera_position", 1_000, Self::camera_update, EmptyFilter)?;
Ok(()) Ok(())
} }
@ -138,6 +143,7 @@ impl Game {
let player = PlayerEntity(world.add_entity(fighter)?); let player = PlayerEntity(world.add_entity(fighter)?);
world.resources.insert(player); world.resources.insert(player);
world.resources.insert(InputSettings::default());
world.commit_entity_changes() world.commit_entity_changes()
} }
@ -151,10 +157,23 @@ impl Game {
draw: &mut Draw, draw: &mut Draw,
control: &mut FreeSpaceControl, control: &mut FreeSpaceControl,
) -> Result<()> { ) -> Result<()> {
if let Some(transform) = control.update(world.now()) { control.update(world.now());
draw.set_transform(transform)?; draw.set_transform(control.transform())
} }
Ok(()) fn camera_update(
world: &mut World,
_entity: Entity,
control: &mut FreeSpaceControl,
) -> Result<()> {
let scene = world.resources.get_mut::<Scene>();
let view = scene.view_mut();
view.camera_mut()
.set_center((control.translation() * Vector4::unit_w()).truncate());
view.camera_mut()
.set_eye_dir(control.rotation() * Vector3::unit_y());
view.update_buffer()
} }
} }

View file

@ -74,7 +74,7 @@ pub enum Event<'a> {
ControllerRemoved(&'a Controller), ControllerRemoved(&'a Controller),
// joystick events // joystick events
JoystickAxis(&'a Joystick), JoystickAxis(&'a Joystick, u8, i16),
JoystickButtonDown(&'a Joystick), JoystickButtonDown(&'a Joystick),
JoystickButtonUp(&'a Joystick), JoystickButtonUp(&'a Joystick),
JoystickAdded(&'a Joystick), JoystickAdded(&'a Joystick),
@ -349,6 +349,21 @@ impl EventSystem {
event_callback(Event::JoystickAdded(&joystick))?; event_callback(Event::JoystickAdded(&joystick))?;
self.connected_joysticks.insert(joystick.id(), joystick); self.connected_joysticks.insert(joystick.id(), joystick);
} }
SdlEvent::JoyDeviceRemoved { which, .. } => {
if let Some(joysticks) = self.connected_joysticks.remove(&which) {
event_callback(Event::JoystickRemoved(&joysticks))?;
}
}
SdlEvent::JoyAxisMotion {
which,
axis_idx,
value,
..
} => {
if let Some(joysticks) = self.connected_joysticks.get(&which) {
event_callback(Event::JoystickAxis(&joysticks, axis_idx, value))?;
}
}
SdlEvent::DropFile { filename, .. } => { SdlEvent::DropFile { filename, .. } => {
event_callback(Event::FileDrop(filename))?; event_callback(Event::FileDrop(filename))?;
} }