diff --git a/config/input.toml b/config/input.toml index c6eb1fe..1463bdf 100644 --- a/config/input.toml +++ b/config/input.toml @@ -8,21 +8,38 @@ scan_code = 19 ctrl = true [[button]] -name = "FORWARD" +name = "w" scan_code = 17 [[button]] -name = "BACK" +name = "s" scan_code = 31 -[[axis]] -name = "FORWARD_AXIS" -positive_button = "FORWARD" -negative_button = "BACK" +[[button]] +name = "a" +scan_code = 30 + +[[button]] +name = "d" +scan_code = 32 [[axis]] -name = "FORWARD_AXIS" -mouse_wheel = true +name = "move_forward" +positive_button = "w" +negative_button = "s" + +[[axis]] +name = "move_sideways" +positive_button = "d" +negative_button = "a" + +[[axis]] +name = "look_horizontal" +mouse_axis = "x" + +[[axis]] +name = "look_vertical" +mouse_axis = "y" [config] line_height_px = 16 \ No newline at end of file diff --git a/config/log.toml b/config/log.toml index 893e4a0..93cad95 100644 --- a/config/log.toml +++ b/config/log.toml @@ -1,2 +1,2 @@ -input = false +input = true vulkan_validation_layers = true \ No newline at end of file diff --git a/src/input.rs b/src/input.rs index ea43795..635b576 100644 --- a/src/input.rs +++ b/src/input.rs @@ -52,7 +52,7 @@ struct InputConfigAxis { name: String, positive_button: Option, negative_button: Option, - mouse_wheel: Option, + mouse_axis: Option, ctrl: Option, shift: Option, alt: Option, @@ -63,6 +63,8 @@ struct InputConfigAxis { pub struct InputState { pub virtual_buttons: HashMap, pub virtual_axes: HashMap, + pub mouse_delta_x: f64, + pub mouse_delta_y: f64, input_events: HashSet, pressed_scan_codes: HashSet, pressed_mouse_buttons: HashSet, @@ -77,7 +79,7 @@ impl InputState { let mut state = InputState { virtual_buttons: HashMap::new(), virtual_axes: HashMap::new(), input_events: HashSet::new(), pressed_scan_codes: HashSet::new(), pressed_mouse_buttons: HashSet::new(), analog_wheel_state: 0.0, - config: config.config }; + config: config.config, mouse_delta_x: 0.0, mouse_delta_y: 0.0 }; config.button.iter().for_each(|bn| { let modifiers = ModifiersState { @@ -109,34 +111,39 @@ impl InputState { } }); - config.axis.iter().for_each(|a| { - let axis_input = match a { + config.axis.iter().for_each(|axis| { + let axis_input = match axis { InputConfigAxis { positive_button: Some(pos_button_name), negative_button: Some(neg_button_name), .. } => { let positive_button = state.virtual_buttons.get(pos_button_name) - .expect(&format!("Button {:?} of axis {:?} not found!", a.positive_button, a.name)) + .expect(&format!("Button {:?} of axis {:?} not found!", axis.positive_button, axis.name)) .clone(); let negative_button = state.virtual_buttons.get(neg_button_name) - .expect(&format!("Button {:?} of axis {:?} not found!", a.positive_button, a.name)) + .expect(&format!("Button {:?} of axis {:?} not found!", axis.positive_button, axis.name)) .clone(); AxisInput::Digital(positive_button, negative_button) }, - InputConfigAxis { mouse_wheel: Some(true), .. } => { + InputConfigAxis { mouse_axis: Some(axis_name), .. } => { let modifiers = ModifiersState { - shift: a.shift.is_some(), - ctrl: a.ctrl.is_some(), - alt: a.alt.is_some(), - logo: a.logo.is_some() + shift: axis.shift.is_some(), + ctrl: axis.ctrl.is_some(), + alt: axis.alt.is_some(), + logo: axis.logo.is_some(), }; - AxisInput::Wheel(modifiers) + match axis_name.to_lowercase().as_str() { + "wheel" => AxisInput::Wheel(modifiers), + "x" => AxisInput::MouseMove(MouseMoveDirection::X, modifiers), + "y" => AxisInput::MouseMove(MouseMoveDirection::Y, modifiers), + other => panic!("Axis {:?} has unknown mouse axis name {:?}!", axis_name, other), + } }, other => panic!("Axis {:?} needs either positive_button and negative_button or mouse_wheel must be set to true!", other.name) }; - if let Some(virtual_axis) = state.virtual_axes.get_mut(&a.name) { + if let Some(virtual_axis) = state.virtual_axes.get_mut(&axis.name) { virtual_axis.axis_inputs.push(axis_input); } else { - state.virtual_axes.insert(a.name.clone(), VirtualAxis { axis_inputs: vec![axis_input] }); + state.virtual_axes.insert(axis.name.clone(), VirtualAxis { axis_inputs: vec![axis_input] }); } }); @@ -195,8 +202,22 @@ impl InputState { if let Some(axis) = self.virtual_axes.get(axis_code) { axis.axis_inputs.iter().map(|item| { match item { - AxisInput::Wheel(modifiers) => if self.modifiers_are_pressed(*modifiers) { self.analog_wheel_state } else { 0.0 }, - AxisInput::Digital(positive_button, negative_button) => self.virtual_button_to_float(positive_button) - self.virtual_button_to_float(negative_button), + AxisInput::Wheel(modifiers) => { + if self.modifiers_are_pressed(*modifiers) { self.analog_wheel_state } else { 0.0 } + }, + AxisInput::MouseMove(direction, modifiers) => { + if self.modifiers_are_pressed(*modifiers) { + match direction { + MouseMoveDirection::X => self.mouse_delta_x as f32, + MouseMoveDirection::Y => self.mouse_delta_y as f32, + } + } else { + 0.0 + } + }, + AxisInput::Digital(positive_button, negative_button) => { + self.virtual_button_to_float(positive_button) - self.virtual_button_to_float(negative_button) + }, } }).fold(0.0, |fold, it| if f32::abs(it) > f32::abs(fold) { it } else { fold }) } else { @@ -288,6 +309,8 @@ impl InputState { pub fn frame_end(self: &mut Self) { self.analog_wheel_state = 0.0; + self.mouse_delta_x = 0.0; + self.mouse_delta_y = 0.0; self.input_events.clear(); } } @@ -303,6 +326,7 @@ pub fn mods_to_string(modifiers: &ModifiersState) -> String { #[derive(Debug)] pub enum AxisInput { Wheel(ModifiersState), + MouseMove(MouseMoveDirection, ModifiersState), Digital(VirtualButton, VirtualButton), } @@ -337,6 +361,12 @@ pub enum WheelInputDirection { Down, } +#[derive(Debug, Eq, PartialEq, Hash, Clone)] +pub enum MouseMoveDirection { + X, + Y, +} + #[derive(Debug, PartialEq, Clone)] pub struct AnalogWheelInput { value: f32, diff --git a/src/main.rs b/src/main.rs index 9e24edc..15a9781 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,5 +1,5 @@ -use winit::{Event, WindowEvent}; -use cgmath::{Matrix4, Rad, Point3, Vector3, Deg}; +use winit::{Event, WindowEvent, DeviceEvent}; +use cgmath::{Matrix4, Rad, Point3, Vector3, Deg, SquareMatrix, Quaternion, Rotation3, One, Rotation}; mod vulkan; use crate::vulkan::{GameData, Game, LinePoint}; @@ -12,7 +12,8 @@ use crate::config::LogConfig; struct TestGame { input: InputState, - cam_pos: Point3, + cam_position: Vector3, + cam_rotation: Quaternion, log_config: LogConfig, } @@ -22,6 +23,8 @@ impl Game for TestGame { } fn update(self: &mut Self, game_data: &mut GameData) { + game_data.push_constants.time = game_data.start_time.elapsed().unwrap().as_millis() as f32 / 1000.0; + // User interaction if self.input.button_just_released("QUIT") { game_data.shutdown = true; @@ -31,18 +34,17 @@ impl Game for TestGame { game_data.recreate_pipeline = true; } - self.cam_pos.x += self.input.get_axis("FORWARD_AXIS") * 0.01; + self.cam_rotation = self.cam_rotation * Quaternion::from_angle_z(Deg(self.input.get_axis("look_horizontal") * 0.05)); + self.cam_rotation = Quaternion::from_angle_x(Deg(self.input.get_axis("look_vertical") * 0.05)) * self.cam_rotation; + self.cam_position += self.cam_rotation.invert().rotate_vector(Vector3::new( + self.input.get_axis("move_sideways") * -0.05, + 0.0, + self.input.get_axis("move_forward") * 0.05)); // Move game objects - game_data.push_constants.time = game_data.start_time.elapsed().unwrap().as_millis() as f32 / 1000.0; - let model = Matrix4::from_angle_z(Rad::from(Deg(game_data.push_constants.time * 100.0))); - let view = Matrix4::look_at( - self.cam_pos, - Point3::new(0.0, 0.0, 0.0), - Vector3::new(0.0, 0.0, 1.0) - ); + let view = Matrix4::from(self.cam_rotation) * Matrix4::from_translation(self.cam_position); let mut proj = cgmath::perspective( Rad::from(Deg(45.0)), @@ -99,6 +101,13 @@ impl Game for TestGame { } self.input.on_mouse_wheel_event(&delta, &modifiers); + }, + Event::DeviceEvent { device_id, event: DeviceEvent::MouseMotion { delta: (delta_x, delta_y) } } => { + if self.log_config.input { + println!("MouseMotion {:?}, ({:?},{:?})", device_id, delta_x, delta_y); + } + self.input.mouse_delta_x += *delta_x; + self.input.mouse_delta_y += *delta_y; } _ => {} } @@ -108,7 +117,8 @@ impl Game for TestGame { fn main() { let mut game = TestGame { input: InputState::new("config/input.toml"), - cam_pos: Point3::new(2.0, 2.0, 2.0), + cam_rotation: Quaternion::one(), + cam_position: Vector3::new(0.0, 0.0, -10.0), log_config: LogConfig::from_file("config/log.toml"), };