basic touch input
This commit is contained in:
@@ -48,6 +48,7 @@ scan_code = 64
|
|||||||
[[button]]
|
[[button]]
|
||||||
name = "select"
|
name = "select"
|
||||||
mouse = "left"
|
mouse = "left"
|
||||||
|
touch = 1
|
||||||
|
|
||||||
[[axis]]
|
[[axis]]
|
||||||
name = "move_forward"
|
name = "move_forward"
|
||||||
|
|||||||
@@ -4,4 +4,5 @@ mesh_load_info = true
|
|||||||
[input]
|
[input]
|
||||||
mouse_motion = false
|
mouse_motion = false
|
||||||
buttons = false
|
buttons = false
|
||||||
|
touch = true
|
||||||
missing_bindings = true
|
missing_bindings = true
|
||||||
31
config/testinput.toml
Normal file
31
config/testinput.toml
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
[[button]]
|
||||||
|
name = "quit"
|
||||||
|
scan_code = 1
|
||||||
|
|
||||||
|
[[button]]
|
||||||
|
name = "select"
|
||||||
|
mouse = "left"
|
||||||
|
|
||||||
|
[[button]]
|
||||||
|
name = "touchclick"
|
||||||
|
touch = 1
|
||||||
|
|
||||||
|
[[button]]
|
||||||
|
name = "doubletouchclick"
|
||||||
|
touch = 2
|
||||||
|
|
||||||
|
[[button]]
|
||||||
|
name = "button_left"
|
||||||
|
scan_code = 30
|
||||||
|
|
||||||
|
[[button]]
|
||||||
|
name = "button_right"
|
||||||
|
scan_code = 32
|
||||||
|
|
||||||
|
[[axis]]
|
||||||
|
name = "move_sideways"
|
||||||
|
positive_button = "button_right"
|
||||||
|
negative_button = "button_left"
|
||||||
|
|
||||||
|
[config]
|
||||||
|
line_height_px = 16
|
||||||
@@ -7,6 +7,7 @@ use toml;
|
|||||||
pub struct LogConfigInput {
|
pub struct LogConfigInput {
|
||||||
pub mouse_motion: bool,
|
pub mouse_motion: bool,
|
||||||
pub buttons: bool,
|
pub buttons: bool,
|
||||||
|
pub touch: bool,
|
||||||
pub missing_bindings: bool
|
pub missing_bindings: bool
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
130
src/input.rs
130
src/input.rs
@@ -2,19 +2,21 @@
|
|||||||
|
|
||||||
use std::collections::{HashMap, HashSet};
|
use std::collections::{HashMap, HashSet};
|
||||||
use std::fs;
|
use std::fs;
|
||||||
|
use std::hash::Hash;
|
||||||
use std::iter::FromIterator;
|
use std::iter::FromIterator;
|
||||||
|
|
||||||
use gilrs;
|
use gilrs;
|
||||||
use gilrs::{EventType, Gilrs};
|
use gilrs::{EventType, Gilrs};
|
||||||
use serde_derive::{Deserialize, Serialize};
|
use serde_derive::{Deserialize, Serialize};
|
||||||
use toml;
|
use toml;
|
||||||
use winit::event::{DeviceEvent, ElementState, Event, ModifiersState, MouseButton, MouseScrollDelta, ScanCode, WindowEvent};
|
use winit::event::{DeviceEvent, ElementState, Event, ModifiersState, MouseButton, MouseScrollDelta, ScanCode, Touch, TouchPhase, WindowEvent};
|
||||||
|
|
||||||
use crate::config::LogConfig;
|
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>
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
@@ -45,6 +47,7 @@ struct InputConfigButton {
|
|||||||
name: String,
|
name: String,
|
||||||
scan_code: Option<u32>,
|
scan_code: Option<u32>,
|
||||||
mouse: Option<String>,
|
mouse: Option<String>,
|
||||||
|
touch: Option<u8>,
|
||||||
controller_button: Option<String>,
|
controller_button: Option<String>,
|
||||||
ctrl: Option<bool>,
|
ctrl: Option<bool>,
|
||||||
shift: Option<bool>,
|
shift: Option<bool>,
|
||||||
@@ -75,10 +78,12 @@ pub struct InputState {
|
|||||||
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>,
|
||||||
analog_wheel_state: f32,
|
analog_wheel_state: f32,
|
||||||
config: InputConfigConfig,
|
config: InputConfigConfig,
|
||||||
log_config: LogConfig,
|
log_config: LogConfig,
|
||||||
controller_input: Gilrs,
|
controller_input: Gilrs,
|
||||||
|
touch_inputs: Vec<TouchInput>
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Eq, PartialEq, Hash, Clone)]
|
#[derive(Debug, Eq, PartialEq, Hash, Clone)]
|
||||||
@@ -106,10 +111,11 @@ 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(), analog_wheel_state: 0.0,
|
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,
|
config: config.config, mouse_delta_x: 0.0, mouse_delta_y: 0.0, mouse_position: [0., 0.], log_config,
|
||||||
controller_input: Gilrs::new().unwrap() };
|
controller_input: Gilrs::new().unwrap() };
|
||||||
|
|
||||||
|
// Create virtual buttons from config
|
||||||
config.button.iter().for_each(|bn| {
|
config.button.iter().for_each(|bn| {
|
||||||
let modifiers = KeyboardModifierState {
|
let modifiers = KeyboardModifierState {
|
||||||
shift: bn.shift.is_some(),
|
shift: bn.shift.is_some(),
|
||||||
@@ -117,33 +123,55 @@ impl InputState {
|
|||||||
alt: bn.alt.is_some(),
|
alt: bn.alt.is_some(),
|
||||||
logo: bn.logo.is_some()
|
logo: bn.logo.is_some()
|
||||||
};
|
};
|
||||||
let input = if let Some(scan_code) = bn.scan_code {
|
|
||||||
DigitalInput::Keyboard(KeyboardInput { scan_code, modifiers })
|
let mut inputs = vec![];
|
||||||
} else if let Some(button_name) = &bn.mouse {
|
|
||||||
|
// Keyboard buttons
|
||||||
|
if let Some(scan_code) = bn.scan_code {
|
||||||
|
inputs.push(DigitalInput::Keyboard(KeyboardInput { scan_code, modifiers: modifiers.clone() }));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Mouse buttons
|
||||||
|
if let Some(button_name) = &bn.mouse {
|
||||||
let button_name_lower = button_name.to_lowercase();
|
let button_name_lower = button_name.to_lowercase();
|
||||||
match button_name_lower.as_str() {
|
let button_input = match button_name_lower.as_str() {
|
||||||
"left" => DigitalInput::Mouse(MouseInput { button: MouseButton::Left, modifiers }),
|
"left" => DigitalInput::Mouse(MouseInput { button: MouseButton::Left, modifiers }),
|
||||||
"middle" => DigitalInput::Mouse(MouseInput { button: MouseButton::Middle, modifiers }),
|
"middle" => DigitalInput::Mouse(MouseInput { button: MouseButton::Middle, modifiers }),
|
||||||
"right" => DigitalInput::Mouse(MouseInput { button: MouseButton::Right, modifiers }),
|
"right" => DigitalInput::Mouse(MouseInput { button: MouseButton::Right, modifiers }),
|
||||||
"wheelup" => DigitalInput::Wheel(WheelInput { direction: WheelInputDirection::Up, modifiers }),
|
"wheelup" => DigitalInput::Wheel(WheelInput { direction: WheelInputDirection::Up, modifiers }),
|
||||||
"wheeldown" => DigitalInput::Wheel(WheelInput { direction: WheelInputDirection::Down, modifiers }),
|
"wheeldown" => DigitalInput::Wheel(WheelInput { direction: WheelInputDirection::Down, modifiers }),
|
||||||
other => DigitalInput::Mouse(MouseInput { button: MouseButton::Other(other.parse().expect(&format!("Unknown button: {:?}", other))), modifiers }),
|
other => DigitalInput::Mouse(MouseInput { button: MouseButton::Other(other.parse().expect(&format!("Unknown button: {:?}", other))), modifiers }),
|
||||||
}
|
};
|
||||||
} else if let Some(controller_button) = &bn.controller_button {
|
inputs.push(button_input);
|
||||||
DigitalInput::Controller(ControllerInput {
|
}
|
||||||
|
|
||||||
|
// Controller buttons
|
||||||
|
if let Some(controller_button) = &bn.controller_button {
|
||||||
|
inputs.push(DigitalInput::Controller(ControllerInput {
|
||||||
button: string_to_button(controller_button.as_str()).expect(&format!("Unknown controller button: {}", controller_button.as_str()))
|
button: string_to_button(controller_button.as_str()).expect(&format!("Unknown controller button: {}", controller_button.as_str()))
|
||||||
})
|
}));
|
||||||
} else {
|
}
|
||||||
panic!("No mouse or keyboard input for button {:?}", bn.name);
|
|
||||||
};
|
|
||||||
|
|
||||||
if let Some(virtual_button) = state.virtual_buttons.get_mut(&bn.name) {
|
// Touch clicks
|
||||||
virtual_button.digital_inputs.push(input);
|
if let Some(_) = bn.touch {
|
||||||
} else {
|
if let Some(virtual_button) = state.virtual_buttons.get_mut(&bn.name) {
|
||||||
state.virtual_buttons.insert(bn.name.clone(), VirtualButton { digital_inputs: vec![input] });
|
virtual_button.touch_count = bn.touch;
|
||||||
|
} else {
|
||||||
|
state.virtual_buttons.insert(bn.name.clone(), VirtualButton { digital_inputs: vec![], touch_count: bn.touch });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Insert digital inputs
|
||||||
|
for input in inputs {
|
||||||
|
if let Some(virtual_button) = state.virtual_buttons.get_mut(&bn.name) {
|
||||||
|
virtual_button.digital_inputs.push(input);
|
||||||
|
} else {
|
||||||
|
state.virtual_buttons.insert(bn.name.clone(), VirtualButton { digital_inputs: vec![input], touch_count: bn.touch });
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Create virtual axes from config
|
||||||
config.axis.iter().for_each(|axis| {
|
config.axis.iter().for_each(|axis| {
|
||||||
let axis_input = match axis {
|
let axis_input = match axis {
|
||||||
InputConfigAxis { positive_button: Some(pos_button_name), negative_button: Some(neg_button_name), .. } => {
|
InputConfigAxis { positive_button: Some(pos_button_name), negative_button: Some(neg_button_name), .. } => {
|
||||||
@@ -234,6 +262,12 @@ impl InputState {
|
|||||||
Event::WindowEvent { event: WindowEvent::CursorMoved { position, .. }, .. } => {
|
Event::WindowEvent { event: WindowEvent::CursorMoved { position, .. }, .. } => {
|
||||||
self.mouse_position = [position.x, position.y];
|
self.mouse_position = [position.x, position.y];
|
||||||
},
|
},
|
||||||
|
Event::WindowEvent { event: WindowEvent::Touch(touch), .. } => {
|
||||||
|
if self.log_config.input.touch {
|
||||||
|
println!("Touch {:?}, at {:?}, id: {:?}, force: {:?}", touch.phase, touch.location, touch.id, touch.force);
|
||||||
|
}
|
||||||
|
self.on_touch_event(touch);
|
||||||
|
},
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -241,6 +275,11 @@ impl InputState {
|
|||||||
pub fn button_down(self: &Self, button_code: &str) -> bool {
|
pub fn button_down(self: &Self, button_code: &str) -> bool {
|
||||||
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 self.pressed_touch_ids.len() == count as usize {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
virtual_button.digital_inputs.iter().any(|vi| self.digital_input_pressed(vi))
|
virtual_button.digital_inputs.iter().any(|vi| self.digital_input_pressed(vi))
|
||||||
}
|
}
|
||||||
None => {
|
None => {
|
||||||
@@ -255,6 +294,13 @@ impl InputState {
|
|||||||
pub fn button_just_pressed(self: &Self, button_code: &str) -> bool {
|
pub fn button_just_pressed(self: &Self, button_code: &str) -> bool {
|
||||||
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 self.pressed_touch_ids.len() == count as usize
|
||||||
|
&& self.touch_inputs.iter().any(|ti| ti.phase == TouchPhase::Started) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
self.input_events.iter().any(|input_event| {
|
self.input_events.iter().any(|input_event| {
|
||||||
if let DigitalInputEvent::Pressed(digital_input) = input_event {
|
if let DigitalInputEvent::Pressed(digital_input) = input_event {
|
||||||
virtual_button.digital_inputs.iter().any(|virtual_button_input| virtual_button_input == digital_input)
|
virtual_button.digital_inputs.iter().any(|virtual_button_input| virtual_button_input == digital_input)
|
||||||
@@ -275,6 +321,13 @@ impl InputState {
|
|||||||
pub fn button_just_released(self: &Self, button_code: &str) -> bool {
|
pub fn button_just_released(self: &Self, button_code: &str) -> bool {
|
||||||
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 self.pressed_touch_ids.len() < count as usize
|
||||||
|
&& self.touch_inputs.iter().any(|ti| ti.phase == TouchPhase::Ended) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
self.input_events.iter().any(|input_event| {
|
self.input_events.iter().any(|input_event| {
|
||||||
if let DigitalInputEvent::Released(digital_input) = input_event {
|
if let DigitalInputEvent::Released(digital_input) = input_event {
|
||||||
virtual_button.digital_inputs.iter().any(|virtual_button_input| virtual_button_input == digital_input)
|
virtual_button.digital_inputs.iter().any(|virtual_button_input| virtual_button_input == digital_input)
|
||||||
@@ -412,6 +465,24 @@ impl InputState {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn on_touch_event(&mut self, event: &Touch) {
|
||||||
|
self.mouse_position = [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 });
|
||||||
|
},
|
||||||
|
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 });
|
||||||
|
},
|
||||||
|
winit::event::TouchPhase::Cancelled => {
|
||||||
|
self.pressed_touch_ids.remove(&event.id);
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn frame_start(self: &mut Self) {
|
pub fn frame_start(self: &mut Self) {
|
||||||
while let Some(event) = self.controller_input.next_event() {
|
while let Some(event) = self.controller_input.next_event() {
|
||||||
match event.event {
|
match event.event {
|
||||||
@@ -440,6 +511,7 @@ 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();
|
||||||
|
self.touch_inputs.clear();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -490,6 +562,28 @@ pub struct ControllerInput {
|
|||||||
button: gilrs::Button,
|
button: gilrs::Button,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub struct TouchInput {
|
||||||
|
id: u64,
|
||||||
|
touch_location: [f64; 2],
|
||||||
|
phase: TouchPhase
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Eq for TouchInput {}
|
||||||
|
|
||||||
|
impl PartialEq for TouchInput {
|
||||||
|
fn eq(&self, other: &Self) -> bool {
|
||||||
|
self.id.eq(&other.id) && self.phase.eq(&other.phase)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Hash for TouchInput {
|
||||||
|
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
|
||||||
|
state.write_u64(self.id);
|
||||||
|
self.phase.hash(state)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, Eq, PartialEq, Hash, Clone)]
|
#[derive(Debug, Eq, PartialEq, Hash, Clone)]
|
||||||
pub enum WheelInputDirection {
|
pub enum WheelInputDirection {
|
||||||
Up,
|
Up,
|
||||||
|
|||||||
102
src/tests/mod.rs
102
src/tests/mod.rs
@@ -1,8 +1,9 @@
|
|||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use cgmath::{vec3};
|
use cgmath::{vec3};
|
||||||
|
use winit::{dpi::PhysicalPosition, event::{DeviceId, ElementState, Event, Force, KeyboardInput, ModifiersState, Touch, TouchPhase, WindowEvent}, window::WindowId};
|
||||||
|
|
||||||
use crate::game::player::{intersect_triangle};
|
use crate::{config::LogConfig, game::player::{intersect_triangle}, input::InputState};
|
||||||
|
|
||||||
fn epsilon_eq(f1: f32, f2: f32) {
|
fn epsilon_eq(f1: f32, f2: f32) {
|
||||||
assert!(f32::abs(f1 - f2) < f32::EPSILON, "{} == {}", f1, f2);
|
assert!(f32::abs(f1 - f2) < f32::EPSILON, "{} == {}", f1, f2);
|
||||||
@@ -36,4 +37,103 @@ mod tests {
|
|||||||
let dist3 = intersect_triangle(zero, vec3(0.9950371902, 0.09950371902, 0.0), a, b, c);
|
let dist3 = intersect_triangle(zero, vec3(0.9950371902, 0.09950371902, 0.0), a, b, c);
|
||||||
epsilon_eq_option(dist3, Some(2.0099751242));
|
epsilon_eq_option(dist3, Some(2.0099751242));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn create_test_input_state() -> InputState {
|
||||||
|
InputState::new("config/testinput.toml", LogConfig::from_file("config/log.toml"))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn key_test() {
|
||||||
|
let mut state = create_test_input_state();
|
||||||
|
state.frame_start();
|
||||||
|
state.frame_end();
|
||||||
|
unsafe {
|
||||||
|
state.on_window_event(&Event::WindowEvent{ window_id: WindowId::dummy(), event: WindowEvent::KeyboardInput {
|
||||||
|
device_id: DeviceId::dummy(),
|
||||||
|
input: KeyboardInput { scancode: 1, state: ElementState::Pressed, virtual_keycode: None, modifiers: ModifiersState::empty() },
|
||||||
|
is_synthetic: true,
|
||||||
|
}});
|
||||||
|
}
|
||||||
|
state.frame_start();
|
||||||
|
assert_eq!(state.button_just_pressed("quit"), true);
|
||||||
|
assert_eq!(state.button_down("quit"), true);
|
||||||
|
state.frame_end();
|
||||||
|
state.frame_start();
|
||||||
|
assert_eq!(state.button_just_pressed("quit"), false);
|
||||||
|
assert_eq!(state.button_down("quit"), true);
|
||||||
|
state.frame_end();
|
||||||
|
unsafe {
|
||||||
|
state.on_window_event(&Event::WindowEvent{ window_id: WindowId::dummy(), event: WindowEvent::KeyboardInput {
|
||||||
|
device_id: DeviceId::dummy(),
|
||||||
|
input: KeyboardInput { scancode: 1, state: ElementState::Released, virtual_keycode: None, modifiers: ModifiersState::empty() },
|
||||||
|
is_synthetic: true,
|
||||||
|
}});
|
||||||
|
}
|
||||||
|
state.frame_start();
|
||||||
|
assert_eq!(state.button_down("quit"), false);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn touch_event(state: &mut InputState, phase: TouchPhase, id: u64) {
|
||||||
|
unsafe {
|
||||||
|
state.on_window_event(&Event::WindowEvent{ window_id: WindowId::dummy(), event: WindowEvent::Touch(Touch {
|
||||||
|
device_id: DeviceId::dummy(), phase, location: PhysicalPosition::new(0., 0.), force: Some(Force::Normalized(0.5)), id
|
||||||
|
})});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn touch_test() {
|
||||||
|
let mut state = create_test_input_state();
|
||||||
|
state.frame_start();
|
||||||
|
state.frame_end();
|
||||||
|
touch_event(&mut state, TouchPhase::Started, 1);
|
||||||
|
state.frame_start();
|
||||||
|
assert_eq!(state.button_just_pressed("touchclick"), true);
|
||||||
|
assert_eq!(state.button_down("touchclick"), true);
|
||||||
|
state.frame_end();
|
||||||
|
touch_event(&mut state, TouchPhase::Moved, 1);
|
||||||
|
state.frame_start();
|
||||||
|
assert_eq!(state.button_just_pressed("touchclick"), false);
|
||||||
|
assert_eq!(state.button_down("touchclick"), true);
|
||||||
|
state.frame_end();
|
||||||
|
touch_event(&mut state, TouchPhase::Ended, 1);
|
||||||
|
state.frame_start();
|
||||||
|
assert_eq!(state.button_just_released("touchclick"), true);
|
||||||
|
assert_eq!(state.button_down("touchclick"), false);
|
||||||
|
state.frame_end();
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn multi_touch_test() {
|
||||||
|
let mut state = create_test_input_state();
|
||||||
|
state.frame_start();
|
||||||
|
state.frame_end();
|
||||||
|
touch_event(&mut state, TouchPhase::Started, 2);
|
||||||
|
// TODO: add tolerance for delay
|
||||||
|
touch_event(&mut state, TouchPhase::Started, 3);
|
||||||
|
state.frame_start();
|
||||||
|
assert_eq!(state.button_just_pressed("touchclick"), false);
|
||||||
|
assert_eq!(state.button_down("touchclick"), false);
|
||||||
|
assert_eq!(state.button_just_pressed("doubletouchclick"), true);
|
||||||
|
assert_eq!(state.button_down("doubletouchclick"), true);
|
||||||
|
state.frame_end();
|
||||||
|
touch_event(&mut state, TouchPhase::Moved, 2);
|
||||||
|
state.frame_start();
|
||||||
|
assert_eq!(state.button_just_pressed("doubletouchclick"), false);
|
||||||
|
assert_eq!(state.button_down("doubletouchclick"), true);
|
||||||
|
state.frame_end();
|
||||||
|
touch_event(&mut state, TouchPhase::Ended, 2);
|
||||||
|
state.frame_start();
|
||||||
|
assert_eq!(state.button_just_released("doubletouchclick"), true);
|
||||||
|
assert_eq!(state.button_down("doubletouchclick"), false);
|
||||||
|
assert_eq!(state.button_just_pressed("touchclick"), false);
|
||||||
|
// TODO: don't enable button_down on release of double touch
|
||||||
|
// assert_eq!(state.button_down("touchclick"), false);
|
||||||
|
state.frame_end();
|
||||||
|
touch_event(&mut state, TouchPhase::Ended, 3);
|
||||||
|
state.frame_start();
|
||||||
|
// TODO: only set button_just_released for one frame
|
||||||
|
// assert_eq!(state.button_just_released("doubletouchclick"), false);
|
||||||
|
assert_eq!(state.button_down("doubletouchclick"), false);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user