touch axis
This commit is contained in:
@@ -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<Vector3<f32>> {
|
||||
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<f64>, viewport_dimensions: [u32; 2]) -> Option<Vector3<f32>> {
|
||||
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);
|
||||
|
||||
128
src/input.rs
128
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<DigitalInput>,
|
||||
pub touch_count: Option<u8>
|
||||
pub touch_count: Option<u8>,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct VirtualAxis {
|
||||
pub axis_inputs: Vec<AxisInput>
|
||||
pub axis_inputs: Vec<AxisInput>,
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Eq, Hash)]
|
||||
@@ -62,6 +63,7 @@ struct InputConfigAxis {
|
||||
negative_button: Option<String>,
|
||||
mouse_axis: Option<String>,
|
||||
controller_axis: Option<String>,
|
||||
touch_axis: Option<String>,
|
||||
ctrl: Option<bool>,
|
||||
shift: Option<bool>,
|
||||
alt: Option<bool>,
|
||||
@@ -74,11 +76,11 @@ pub struct InputState {
|
||||
pub virtual_axes: HashMap<String, VirtualAxis>,
|
||||
pub mouse_delta_x: f64,
|
||||
pub mouse_delta_y: f64,
|
||||
pub mouse_position: [f64; 2],
|
||||
pub mouse_position: Vector2<f64>,
|
||||
input_events: HashSet<DigitalInputEvent>,
|
||||
pressed_scan_codes: HashSet<ScanCode>,
|
||||
pressed_mouse_buttons: HashSet<MouseButton>,
|
||||
pressed_touch_ids: HashSet<u64>,
|
||||
pressed_touch_positions: HashMap<u64, Vector2<f64>>,
|
||||
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<f64>,
|
||||
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<gilrs::Axis> {
|
||||
"DPadY" => Some(gilrs::Axis::DPadY),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
fn string_to_touch_axis(touch_axis_name: &str) -> Option<TouchAxis> {
|
||||
match touch_axis_name {
|
||||
"horizontal" => Some(TouchAxis::Horizontal),
|
||||
"vertical" => Some(TouchAxis::Vertical),
|
||||
"rotate" => Some(TouchAxis::Rotate),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user