diff --git a/config/input.toml b/config/input.toml index 685cee0..e77c6ce 100644 --- a/config/input.toml +++ b/config/input.toml @@ -80,6 +80,10 @@ mouse_axis = "x" name = "look_horizontal" controller_axis = "RightStickX" +[[axis]] +name = "look_horizontal" +touch_axis = "horizontal" + [[axis]] name = "look_vertical" mouse_axis = "y" @@ -88,5 +92,9 @@ mouse_axis = "y" name = "look_vertical" controller_axis = "RightStickY" +[[axis]] +name = "look_vertical" +touch_axis = "vertical" + [config] line_height_px = 16 \ No newline at end of file diff --git a/config/log.toml b/config/log.toml index e4e7397..ff52a44 100644 --- a/config/log.toml +++ b/config/log.toml @@ -1,8 +1,8 @@ -vulkan_validation_layers = true -mesh_load_info = true +vulkan_validation_layers = false +mesh_load_info = false [input] mouse_motion = false buttons = false -touch = true +touch = false missing_bindings = true \ No newline at end of file diff --git a/config/testinput.toml b/config/testinput.toml index 11b3021..ce1abf7 100644 --- a/config/testinput.toml +++ b/config/testinput.toml @@ -27,5 +27,9 @@ name = "move_sideways" positive_button = "button_right" negative_button = "button_left" +[[axis]] +name = "touch_drag" +touch_axis = "horizontal" + [config] line_height_px = 16 \ No newline at end of file diff --git a/src/game/player.rs b/src/game/player.rs index 57375a3..217a3dd 100644 --- a/src/game/player.rs +++ b/src/game/player.rs @@ -1,4 +1,4 @@ -use cgmath::{Deg, InnerSpace, Matrix4, One, Quaternion, Rad, Rotation, Rotation3, SquareMatrix, Vector3, Vector4, vec3, vec4}; +use cgmath::{Deg, InnerSpace, Matrix4, One, Quaternion, Rad, Rotation, Rotation3, SquareMatrix, Vector2, Vector3, Vector4, vec3, vec4}; use vulkano::buffer::TypedBufferAccess; use crate::game::player::PlayerMovementMode::{FirstPerson, Flying}; @@ -52,9 +52,9 @@ impl Camera { renderer.game_data.line_push_constants.projection = self.proj.into(); } - pub fn viewport_pos_to_ray_direction(&self, viewport_pos: [f64; 2], viewport_dimensions: [u32; 2]) -> Option> { - let normalized_x = 2. * (viewport_pos[0] as f32 / viewport_dimensions[0] as f32) - 1.; - let normalized_y = 2. * (viewport_pos[1] as f32 / viewport_dimensions[1] as f32) - 1.; + pub fn viewport_pos_to_ray_direction(&self, viewport_pos: Vector2, viewport_dimensions: [u32; 2]) -> Option> { + let normalized_x = 2. * (viewport_pos.x as f32 / viewport_dimensions[0] as f32) - 1.; + let normalized_y = 2. * (viewport_pos.y as f32 / viewport_dimensions[1] as f32) - 1.; let click_start_screen = vec4(normalized_x, normalized_y, -1.0, 1.0); let click_end_screen = vec4(normalized_x, normalized_y, 0.0, 1.0); diff --git a/src/input.rs b/src/input.rs index 7fe496a..9a2b6ca 100644 --- a/src/input.rs +++ b/src/input.rs @@ -5,6 +5,7 @@ use std::fs; use std::hash::Hash; use std::iter::FromIterator; +use cgmath::{InnerSpace, Vector2, Zero, vec2}; use gilrs; use gilrs::{EventType, Gilrs}; use serde_derive::{Deserialize, Serialize}; @@ -16,12 +17,12 @@ use crate::config::LogConfig; #[derive(Debug, Clone)] pub struct VirtualButton { pub digital_inputs: Vec, - pub touch_count: Option + pub touch_count: Option, } #[derive(Debug)] pub struct VirtualAxis { - pub axis_inputs: Vec + pub axis_inputs: Vec, } #[derive(Debug, PartialEq, Eq, Hash)] @@ -62,6 +63,7 @@ struct InputConfigAxis { negative_button: Option, mouse_axis: Option, controller_axis: Option, + touch_axis: Option, ctrl: Option, shift: Option, alt: Option, @@ -74,11 +76,11 @@ pub struct InputState { pub virtual_axes: HashMap, pub mouse_delta_x: f64, pub mouse_delta_y: f64, - pub mouse_position: [f64; 2], + pub mouse_position: Vector2, input_events: HashSet, pressed_scan_codes: HashSet, pressed_mouse_buttons: HashSet, - pressed_touch_ids: HashSet, + pressed_touch_positions: HashMap>, analog_wheel_state: f32, config: InputConfigConfig, log_config: LogConfig, @@ -111,8 +113,8 @@ 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(), pressed_touch_ids: HashSet::new(), touch_inputs: vec![], analog_wheel_state: 0.0, - config: config.config, mouse_delta_x: 0.0, mouse_delta_y: 0.0, mouse_position: [0., 0.], log_config, + pressed_mouse_buttons: HashSet::new(), pressed_touch_positions: HashMap::new(), touch_inputs: vec![], analog_wheel_state: 0.0, + config: config.config, mouse_delta_x: 0.0, mouse_delta_y: 0.0, mouse_position: Vector2::zero(), log_config, controller_input: Gilrs::new().unwrap() }; // Create virtual buttons from config @@ -201,7 +203,14 @@ impl InputState { InputConfigAxis { controller_axis: Some(controller_axis_name), .. } => { AxisInput::Controller(AnalogControllerInput { axis: string_to_axis(controller_axis_name).expect(&format!("Unknown controller axis: {}", controller_axis_name)) }) }, - other => panic!("Axis {:?} needs either positive_button and negative_button or mouse_wheel or controller_axis must be set to true!", other.name) + InputConfigAxis { touch_axis: Some(touch_axis_name), .. } => { + if let Some(axis) = string_to_touch_axis(touch_axis_name) { + AxisInput::Touch(axis) + } else { + panic!("Unknown touch axis {:?}", touch_axis_name); + } + }, + other => panic!("Axis {:?} needs either (positive_button and negative_button) or (touch_axis) or (mouse_wheel) or (controller_axis must be set to true)", other.name) }; if let Some(virtual_axis) = state.virtual_axes.get_mut(&axis.name) { @@ -260,7 +269,7 @@ impl InputState { self.mouse_delta_y += *delta_y; }, Event::WindowEvent { event: WindowEvent::CursorMoved { position, .. }, .. } => { - self.mouse_position = [position.x, position.y]; + self.mouse_position = vec2(position.x, position.y); }, Event::WindowEvent { event: WindowEvent::Touch(touch), .. } => { if self.log_config.input.touch { @@ -276,7 +285,7 @@ impl InputState { match self.virtual_buttons.get(button_code) { Some(virtual_button) => { if let Some(count) = virtual_button.touch_count { - if self.pressed_touch_ids.len() == count as usize { + if self.pressed_touch_positions.len() == count as usize { return true; } } @@ -295,7 +304,7 @@ impl InputState { match self.virtual_buttons.get(button_code) { Some(virtual_button) => { if let Some(count) = virtual_button.touch_count { - if self.pressed_touch_ids.len() == count as usize + if self.pressed_touch_positions.len() == count as usize && self.touch_inputs.iter().any(|ti| ti.phase == TouchPhase::Started) { return true; } @@ -322,7 +331,7 @@ impl InputState { match self.virtual_buttons.get(button_code) { Some(virtual_button) => { if let Some(count) = virtual_button.touch_count { - if self.pressed_touch_ids.len() < count as usize + if self.pressed_touch_positions.len() < count as usize && self.touch_inputs.iter().any(|ti| ti.phase == TouchPhase::Ended) { return true; } @@ -348,7 +357,7 @@ impl InputState { pub fn get_axis(self: &Self, axis_code: &str) -> f32 { if let Some(axis) = self.virtual_axes.get(axis_code) { axis.axis_inputs.iter().map(|item| { - match item { + match &item { AxisInput::Wheel(modifiers) => { if self.modifiers_are_pressed(modifiers) { self.analog_wheel_state } else { 0.0 } }, @@ -369,7 +378,59 @@ impl InputState { self.controller_input.gamepads() .map(|(_id, gamepad)| gamepad.value(controller_input.axis)) .fold(0.0, fold_axis_value) - } + }, + &AxisInput::Touch(touch_axis) => { + match touch_axis { + TouchAxis::Horizontal => { + if let Some(old_pos) = self.pressed_touch_positions.values().next() { + if let Some(newest_input) = self.touch_inputs.last() { + (newest_input.touch_location.x - old_pos.x) as f32 + } else { + 0.0 + } + } else { + 0.0 + } + }, + TouchAxis::Vertical => { + if let Some(old_pos) = self.pressed_touch_positions.values().next() { + if let Some(newest_input) = self.touch_inputs.last() { + (newest_input.touch_location.y - old_pos.y) as f32 + } else { + 0.0 + } + } else { + 0.0 + } + }, + TouchAxis::Rotate => { + if self.pressed_touch_positions.len() == 2 { + let mut positions = self.pressed_touch_positions.iter(); + let (id_1, pos_1) = positions.next().unwrap(); + let (id_2, pos_2) = positions.next().unwrap(); + let mut vec_1 = None; + let mut vec_2 = None; + for input in &self.touch_inputs { + if input.id == *id_1 { vec_1 = Some(input.touch_location - pos_1) } + if input.id == *id_2 { vec_2 = Some(input.touch_location - pos_2) } + } + match (vec_1, vec_2) { + (Some(v1), Some(v2)) => { + let movement_length = (v1.magnitude() + v2.magnitude()) / 2.0; + let opposing = f64::abs(-v1.dot(v2)); + let rotating = 1.0; + (movement_length * opposing * rotating) as f32 + }, + (Some(v1), None) => v1.magnitude() as f32, + (None, Some(v2)) => v2.magnitude() as f32, + (None, None) => 0.0 + } + } else { + 0.0 + } + }, + } + }, } }).fold(0.0, fold_axis_value) } else { @@ -466,24 +527,27 @@ impl InputState { } pub fn on_touch_event(&mut self, event: &Touch) { - self.mouse_position = [event.location.x, event.location.y]; + self.mouse_position = vec2(event.location.x, event.location.y); match event.phase { winit::event::TouchPhase::Started => { - self.pressed_touch_ids.insert(event.id); - self.touch_inputs.push(TouchInput { id: event.id, touch_location: [event.location.x, event.location.y], phase: event.phase }); + self.pressed_touch_positions.insert(event.id, self.mouse_position); + self.touch_inputs.push(TouchInput { id: event.id, touch_location: self.mouse_position, phase: event.phase }); + }, + winit::event::TouchPhase::Moved => { + self.touch_inputs.push(TouchInput { id: event.id, touch_location: self.mouse_position, phase: event.phase }); }, - winit::event::TouchPhase::Moved => {}, winit::event::TouchPhase::Ended => { - self.pressed_touch_ids.remove(&event.id); - self.touch_inputs.push(TouchInput { id: event.id, touch_location: [event.location.x, event.location.y], phase: event.phase }); + self.pressed_touch_positions.remove(&event.id); + self.touch_inputs.push(TouchInput { id: event.id, touch_location: self.mouse_position, phase: event.phase }); }, winit::event::TouchPhase::Cancelled => { - self.pressed_touch_ids.remove(&event.id); + self.pressed_touch_positions.remove(&event.id); }, } } pub fn frame_start(self: &mut Self) { + // Read out all controller events while let Some(event) = self.controller_input.next_event() { match event.event { EventType::ButtonPressed(button, _) => { @@ -511,6 +575,11 @@ impl InputState { self.mouse_delta_x = 0.0; self.mouse_delta_y = 0.0; self.input_events.clear(); + + // Store final touch positions as base for next frame + for touch_input in &mut self.touch_inputs { + self.pressed_touch_positions.get_mut(&touch_input.id).map(|pos| *pos = touch_input.touch_location); + } self.touch_inputs.clear(); } } @@ -529,6 +598,7 @@ pub enum AxisInput { MouseMove(MouseMoveDirection, KeyboardModifierState), Digital(VirtualButton, VirtualButton), Controller(AnalogControllerInput), + Touch(TouchAxis) } #[derive(Debug, Eq, PartialEq, Hash, Clone)] @@ -565,7 +635,7 @@ pub struct ControllerInput { #[derive(Debug, Clone)] pub struct TouchInput { id: u64, - touch_location: [f64; 2], + touch_location: Vector2, phase: TouchPhase } @@ -584,6 +654,13 @@ impl Hash for TouchInput { } } +#[derive(Debug, Eq, PartialEq, Hash, Clone)] +pub enum TouchAxis { + Horizontal, + Vertical, + Rotate +} + #[derive(Debug, Eq, PartialEq, Hash, Clone)] pub enum WheelInputDirection { Up, @@ -653,4 +730,13 @@ fn string_to_axis(axis_name: &str) -> Option { "DPadY" => Some(gilrs::Axis::DPadY), _ => None, } +} + +fn string_to_touch_axis(touch_axis_name: &str) -> Option { + match touch_axis_name { + "horizontal" => Some(TouchAxis::Horizontal), + "vertical" => Some(TouchAxis::Vertical), + "rotate" => Some(TouchAxis::Rotate), + _ => None, + } } \ No newline at end of file