touch axis
This commit is contained in:
@@ -80,6 +80,10 @@ mouse_axis = "x"
|
|||||||
name = "look_horizontal"
|
name = "look_horizontal"
|
||||||
controller_axis = "RightStickX"
|
controller_axis = "RightStickX"
|
||||||
|
|
||||||
|
[[axis]]
|
||||||
|
name = "look_horizontal"
|
||||||
|
touch_axis = "horizontal"
|
||||||
|
|
||||||
[[axis]]
|
[[axis]]
|
||||||
name = "look_vertical"
|
name = "look_vertical"
|
||||||
mouse_axis = "y"
|
mouse_axis = "y"
|
||||||
@@ -88,5 +92,9 @@ mouse_axis = "y"
|
|||||||
name = "look_vertical"
|
name = "look_vertical"
|
||||||
controller_axis = "RightStickY"
|
controller_axis = "RightStickY"
|
||||||
|
|
||||||
|
[[axis]]
|
||||||
|
name = "look_vertical"
|
||||||
|
touch_axis = "vertical"
|
||||||
|
|
||||||
[config]
|
[config]
|
||||||
line_height_px = 16
|
line_height_px = 16
|
||||||
@@ -1,8 +1,8 @@
|
|||||||
vulkan_validation_layers = true
|
vulkan_validation_layers = false
|
||||||
mesh_load_info = true
|
mesh_load_info = false
|
||||||
|
|
||||||
[input]
|
[input]
|
||||||
mouse_motion = false
|
mouse_motion = false
|
||||||
buttons = false
|
buttons = false
|
||||||
touch = true
|
touch = false
|
||||||
missing_bindings = true
|
missing_bindings = true
|
||||||
@@ -27,5 +27,9 @@ name = "move_sideways"
|
|||||||
positive_button = "button_right"
|
positive_button = "button_right"
|
||||||
negative_button = "button_left"
|
negative_button = "button_left"
|
||||||
|
|
||||||
|
[[axis]]
|
||||||
|
name = "touch_drag"
|
||||||
|
touch_axis = "horizontal"
|
||||||
|
|
||||||
[config]
|
[config]
|
||||||
line_height_px = 16
|
line_height_px = 16
|
||||||
@@ -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 vulkano::buffer::TypedBufferAccess;
|
||||||
|
|
||||||
use crate::game::player::PlayerMovementMode::{FirstPerson, Flying};
|
use crate::game::player::PlayerMovementMode::{FirstPerson, Flying};
|
||||||
@@ -52,9 +52,9 @@ impl Camera {
|
|||||||
renderer.game_data.line_push_constants.projection = self.proj.into();
|
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>> {
|
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[0] as f32 / viewport_dimensions[0] as f32) - 1.;
|
let normalized_x = 2. * (viewport_pos.x as f32 / viewport_dimensions[0] as f32) - 1.;
|
||||||
let normalized_y = 2. * (viewport_pos[1] as f32 / viewport_dimensions[1] 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_start_screen = vec4(normalized_x, normalized_y, -1.0, 1.0);
|
||||||
let click_end_screen = vec4(normalized_x, normalized_y, 0.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::hash::Hash;
|
||||||
use std::iter::FromIterator;
|
use std::iter::FromIterator;
|
||||||
|
|
||||||
|
use cgmath::{InnerSpace, Vector2, Zero, vec2};
|
||||||
use gilrs;
|
use gilrs;
|
||||||
use gilrs::{EventType, Gilrs};
|
use gilrs::{EventType, Gilrs};
|
||||||
use serde_derive::{Deserialize, Serialize};
|
use serde_derive::{Deserialize, Serialize};
|
||||||
@@ -16,12 +17,12 @@ use crate::config::LogConfig;
|
|||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct VirtualButton {
|
pub struct VirtualButton {
|
||||||
pub digital_inputs: Vec<DigitalInput>,
|
pub digital_inputs: Vec<DigitalInput>,
|
||||||
pub touch_count: Option<u8>
|
pub touch_count: Option<u8>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct VirtualAxis {
|
pub struct VirtualAxis {
|
||||||
pub axis_inputs: Vec<AxisInput>
|
pub axis_inputs: Vec<AxisInput>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, PartialEq, Eq, Hash)]
|
#[derive(Debug, PartialEq, Eq, Hash)]
|
||||||
@@ -62,6 +63,7 @@ struct InputConfigAxis {
|
|||||||
negative_button: Option<String>,
|
negative_button: Option<String>,
|
||||||
mouse_axis: Option<String>,
|
mouse_axis: Option<String>,
|
||||||
controller_axis: Option<String>,
|
controller_axis: Option<String>,
|
||||||
|
touch_axis: Option<String>,
|
||||||
ctrl: Option<bool>,
|
ctrl: Option<bool>,
|
||||||
shift: Option<bool>,
|
shift: Option<bool>,
|
||||||
alt: Option<bool>,
|
alt: Option<bool>,
|
||||||
@@ -74,11 +76,11 @@ pub struct InputState {
|
|||||||
pub virtual_axes: HashMap<String, VirtualAxis>,
|
pub virtual_axes: HashMap<String, VirtualAxis>,
|
||||||
pub mouse_delta_x: f64,
|
pub mouse_delta_x: f64,
|
||||||
pub mouse_delta_y: f64,
|
pub mouse_delta_y: f64,
|
||||||
pub mouse_position: [f64; 2],
|
pub mouse_position: Vector2<f64>,
|
||||||
input_events: HashSet<DigitalInputEvent>,
|
input_events: HashSet<DigitalInputEvent>,
|
||||||
pressed_scan_codes: HashSet<ScanCode>,
|
pressed_scan_codes: HashSet<ScanCode>,
|
||||||
pressed_mouse_buttons: HashSet<MouseButton>,
|
pressed_mouse_buttons: HashSet<MouseButton>,
|
||||||
pressed_touch_ids: HashSet<u64>,
|
pressed_touch_positions: HashMap<u64, Vector2<f64>>,
|
||||||
analog_wheel_state: f32,
|
analog_wheel_state: f32,
|
||||||
config: InputConfigConfig,
|
config: InputConfigConfig,
|
||||||
log_config: LogConfig,
|
log_config: LogConfig,
|
||||||
@@ -111,8 +113,8 @@ impl InputState {
|
|||||||
|
|
||||||
let mut state = InputState { virtual_buttons: HashMap::new(), virtual_axes: HashMap::new(),
|
let mut state = InputState { virtual_buttons: HashMap::new(), virtual_axes: HashMap::new(),
|
||||||
input_events: HashSet::new(), pressed_scan_codes: HashSet::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,
|
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: [0., 0.], log_config,
|
config: config.config, mouse_delta_x: 0.0, mouse_delta_y: 0.0, mouse_position: Vector2::zero(), log_config,
|
||||||
controller_input: Gilrs::new().unwrap() };
|
controller_input: Gilrs::new().unwrap() };
|
||||||
|
|
||||||
// Create virtual buttons from config
|
// Create virtual buttons from config
|
||||||
@@ -201,7 +203,14 @@ impl InputState {
|
|||||||
InputConfigAxis { controller_axis: Some(controller_axis_name), .. } => {
|
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)) })
|
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) {
|
if let Some(virtual_axis) = state.virtual_axes.get_mut(&axis.name) {
|
||||||
@@ -260,7 +269,7 @@ impl InputState {
|
|||||||
self.mouse_delta_y += *delta_y;
|
self.mouse_delta_y += *delta_y;
|
||||||
},
|
},
|
||||||
Event::WindowEvent { event: WindowEvent::CursorMoved { position, .. }, .. } => {
|
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), .. } => {
|
Event::WindowEvent { event: WindowEvent::Touch(touch), .. } => {
|
||||||
if self.log_config.input.touch {
|
if self.log_config.input.touch {
|
||||||
@@ -276,7 +285,7 @@ impl InputState {
|
|||||||
match self.virtual_buttons.get(button_code) {
|
match self.virtual_buttons.get(button_code) {
|
||||||
Some(virtual_button) => {
|
Some(virtual_button) => {
|
||||||
if let Some(count) = virtual_button.touch_count {
|
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;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -295,7 +304,7 @@ impl InputState {
|
|||||||
match self.virtual_buttons.get(button_code) {
|
match self.virtual_buttons.get(button_code) {
|
||||||
Some(virtual_button) => {
|
Some(virtual_button) => {
|
||||||
if let Some(count) = virtual_button.touch_count {
|
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) {
|
&& self.touch_inputs.iter().any(|ti| ti.phase == TouchPhase::Started) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -322,7 +331,7 @@ impl InputState {
|
|||||||
match self.virtual_buttons.get(button_code) {
|
match self.virtual_buttons.get(button_code) {
|
||||||
Some(virtual_button) => {
|
Some(virtual_button) => {
|
||||||
if let Some(count) = virtual_button.touch_count {
|
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) {
|
&& self.touch_inputs.iter().any(|ti| ti.phase == TouchPhase::Ended) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -348,7 +357,7 @@ impl InputState {
|
|||||||
pub fn get_axis(self: &Self, axis_code: &str) -> f32 {
|
pub fn get_axis(self: &Self, axis_code: &str) -> f32 {
|
||||||
if let Some(axis) = self.virtual_axes.get(axis_code) {
|
if let Some(axis) = self.virtual_axes.get(axis_code) {
|
||||||
axis.axis_inputs.iter().map(|item| {
|
axis.axis_inputs.iter().map(|item| {
|
||||||
match item {
|
match &item {
|
||||||
AxisInput::Wheel(modifiers) => {
|
AxisInput::Wheel(modifiers) => {
|
||||||
if self.modifiers_are_pressed(modifiers) { self.analog_wheel_state } else { 0.0 }
|
if self.modifiers_are_pressed(modifiers) { self.analog_wheel_state } else { 0.0 }
|
||||||
},
|
},
|
||||||
@@ -369,7 +378,59 @@ impl InputState {
|
|||||||
self.controller_input.gamepads()
|
self.controller_input.gamepads()
|
||||||
.map(|(_id, gamepad)| gamepad.value(controller_input.axis))
|
.map(|(_id, gamepad)| gamepad.value(controller_input.axis))
|
||||||
.fold(0.0, fold_axis_value)
|
.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)
|
}).fold(0.0, fold_axis_value)
|
||||||
} else {
|
} else {
|
||||||
@@ -466,24 +527,27 @@ impl InputState {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn on_touch_event(&mut self, event: &Touch) {
|
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 {
|
match event.phase {
|
||||||
winit::event::TouchPhase::Started => {
|
winit::event::TouchPhase::Started => {
|
||||||
self.pressed_touch_ids.insert(event.id);
|
self.pressed_touch_positions.insert(event.id, self.mouse_position);
|
||||||
self.touch_inputs.push(TouchInput { id: event.id, touch_location: [event.location.x, event.location.y], phase: event.phase });
|
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 => {
|
winit::event::TouchPhase::Ended => {
|
||||||
self.pressed_touch_ids.remove(&event.id);
|
self.pressed_touch_positions.remove(&event.id);
|
||||||
self.touch_inputs.push(TouchInput { id: event.id, touch_location: [event.location.x, event.location.y], phase: event.phase });
|
self.touch_inputs.push(TouchInput { id: event.id, touch_location: self.mouse_position, phase: event.phase });
|
||||||
},
|
},
|
||||||
winit::event::TouchPhase::Cancelled => {
|
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) {
|
pub fn frame_start(self: &mut Self) {
|
||||||
|
// Read out all controller events
|
||||||
while let Some(event) = self.controller_input.next_event() {
|
while let Some(event) = self.controller_input.next_event() {
|
||||||
match event.event {
|
match event.event {
|
||||||
EventType::ButtonPressed(button, _) => {
|
EventType::ButtonPressed(button, _) => {
|
||||||
@@ -511,6 +575,11 @@ impl InputState {
|
|||||||
self.mouse_delta_x = 0.0;
|
self.mouse_delta_x = 0.0;
|
||||||
self.mouse_delta_y = 0.0;
|
self.mouse_delta_y = 0.0;
|
||||||
self.input_events.clear();
|
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();
|
self.touch_inputs.clear();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -529,6 +598,7 @@ pub enum AxisInput {
|
|||||||
MouseMove(MouseMoveDirection, KeyboardModifierState),
|
MouseMove(MouseMoveDirection, KeyboardModifierState),
|
||||||
Digital(VirtualButton, VirtualButton),
|
Digital(VirtualButton, VirtualButton),
|
||||||
Controller(AnalogControllerInput),
|
Controller(AnalogControllerInput),
|
||||||
|
Touch(TouchAxis)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Eq, PartialEq, Hash, Clone)]
|
#[derive(Debug, Eq, PartialEq, Hash, Clone)]
|
||||||
@@ -565,7 +635,7 @@ pub struct ControllerInput {
|
|||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct TouchInput {
|
pub struct TouchInput {
|
||||||
id: u64,
|
id: u64,
|
||||||
touch_location: [f64; 2],
|
touch_location: Vector2<f64>,
|
||||||
phase: TouchPhase
|
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)]
|
#[derive(Debug, Eq, PartialEq, Hash, Clone)]
|
||||||
pub enum WheelInputDirection {
|
pub enum WheelInputDirection {
|
||||||
Up,
|
Up,
|
||||||
@@ -653,4 +730,13 @@ fn string_to_axis(axis_name: &str) -> Option<gilrs::Axis> {
|
|||||||
"DPadY" => Some(gilrs::Axis::DPadY),
|
"DPadY" => Some(gilrs::Axis::DPadY),
|
||||||
_ => None,
|
_ => 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