Skip to content

Commit

Permalink
fix: prevent code duplicated
Browse files Browse the repository at this point in the history
  • Loading branch information
SergioRibera committed Jun 26, 2023
1 parent 1d209f3 commit 16670c8
Show file tree
Hide file tree
Showing 2 changed files with 94 additions and 116 deletions.
202 changes: 89 additions & 113 deletions src/input.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,12 @@ use crate::{
VirtualJoystickNode, VirtualJoystickType,
};

pub enum InputEvent {
StartDrag { id: u64, pos: Vec2 },
Dragging { id: u64, pos: Vec2 },
EndDrag { id: u64, pos: Vec2 },
}

pub fn run_if_pc() -> bool {
!["android", "ios"].contains(&std::env::consts::OS)
}
Expand All @@ -18,21 +24,17 @@ fn is_some_and<T>(opt: Option<T>, cb: impl FnOnce(T) -> bool) -> bool {
false
}

pub fn update_joystick<S: Hash + Sync + Send + Clone + Default + Reflect + 'static>(
mut touch_events: EventReader<TouchInput>,
pub fn update_input<S: Hash + Sync + Send + Clone + Default + Reflect + 'static>(
mut input_events: EventReader<InputEvent>,
mut send_values: EventWriter<VirtualJoystickEvent<S>>,
mut joysticks: Query<(&VirtualJoystickNode<S>, &mut VirtualJoystickKnob)>,
) {
let touches = touch_events
.iter()
.map(|e| (e.id, e.phase, e.position))
.collect::<Vec<(u64, TouchPhase, Vec2)>>();
let input_events = input_events.iter().collect::<Vec<&InputEvent>>();

for (node, mut knob) in joysticks.iter_mut() {
for (id, phase, pos) in &touches {
match phase {
// Start drag
TouchPhase::Started => {
for event in &input_events {
match event {
InputEvent::StartDrag { id, pos } => {
if knob.interactable_zone_rect.contains(*pos) && knob.id_drag.is_none()
|| is_some_and(knob.id_drag, |i| i != *id)
&& knob.interactable_zone_rect.contains(*pos)
Expand All @@ -50,47 +52,47 @@ pub fn update_joystick<S: Hash + Sync + Send + Clone + Default + Reflect + 'stat
});
}
}
// Dragging
TouchPhase::Moved => {
if is_some_and(knob.id_drag, |i| i == *id) {
knob.current_pos = *pos;
let half = knob.interactable_zone_rect.half_size();
if node.behaviour == VirtualJoystickType::Dynamic {
knob.base_pos = *pos;
let to_knob = knob.current_pos - knob.start_pos;
let distance_to_knob = to_knob.length();
if distance_to_knob > half.x {
let excess_distance = distance_to_knob - half.x;
knob.start_pos += to_knob.normalize() * excess_distance;
}
InputEvent::Dragging { id, pos } => {
if !is_some_and(knob.id_drag, |i| i == *id) {
continue;
}
knob.current_pos = *pos;
let half = knob.interactable_zone_rect.half_size();
if node.behaviour == VirtualJoystickType::Dynamic {
knob.base_pos = *pos;
let to_knob = knob.current_pos - knob.start_pos;
let distance_to_knob = to_knob.length();
if distance_to_knob > half.x {
let excess_distance = distance_to_knob - half.x;
knob.start_pos += to_knob.normalize() * excess_distance;
}
// knob.delta = (knob.start_pos - knob.current_pos).normalize_or_zero();
let d = (knob.start_pos - knob.current_pos) / half;
knob.delta = Vec2::new(
d.x.signum() * d.x.abs().min(1.),
d.y.signum() * d.y.abs().min(1.),
);
}
let d = (knob.start_pos - knob.current_pos) / half;
knob.delta = Vec2::new(
d.x.signum() * d.x.abs().min(1.),
d.y.signum() * d.y.abs().min(1.),
);
}
// End drag
TouchPhase::Ended | TouchPhase::Cancelled => {
if is_some_and(knob.id_drag, |i| i == *id) {
knob.id_drag = None;
knob.base_pos = Vec2::ZERO;
knob.start_pos = Vec2::ZERO;
knob.current_pos = Vec2::ZERO;
knob.delta = Vec2::ZERO;
send_values.send(VirtualJoystickEvent {
id: node.id.clone(),
event: VirtualJoystickEventType::Up,
value: Vec2::ZERO,
delta: Vec2::ZERO,
axis: node.axis,
});
InputEvent::EndDrag { id, pos: _ } => {
if !is_some_and(knob.id_drag, |i| i == *id) {
continue;
}
knob.id_drag = None;
knob.base_pos = Vec2::ZERO;
knob.start_pos = Vec2::ZERO;
knob.current_pos = Vec2::ZERO;
knob.delta = Vec2::ZERO;
send_values.send(VirtualJoystickEvent {
id: node.id.clone(),
event: VirtualJoystickEventType::Up,
value: Vec2::ZERO,
delta: Vec2::ZERO,
axis: node.axis,
});
}
}
}

// Send event
if (knob.delta.x.abs() >= knob.dead_zone || knob.delta.y.abs() >= knob.dead_zone)
&& knob.id_drag.is_some()
Expand All @@ -106,11 +108,37 @@ pub fn update_joystick<S: Hash + Sync + Send + Clone + Default + Reflect + 'stat
}
}

pub fn update_joystick_by_mouse<S: Hash + Sync + Send + Clone + Default + Reflect + 'static>(
pub fn update_joystick(
mut touch_events: EventReader<TouchInput>,
mut send_values: EventWriter<InputEvent>,
) {
let touches = touch_events
.iter()
.map(|e| (e.id, e.phase, e.position))
.collect::<Vec<(u64, TouchPhase, Vec2)>>();

for (id, phase, pos) in &touches {
match phase {
// Start drag
TouchPhase::Started => {
send_values.send(InputEvent::StartDrag { id: *id, pos: *pos });
}
// Dragging
TouchPhase::Moved => {
send_values.send(InputEvent::Dragging { id: *id, pos: *pos });
}
// End drag
TouchPhase::Ended | TouchPhase::Cancelled => {
send_values.send(InputEvent::EndDrag { id: *id, pos: *pos });
}
}
}
}

pub fn update_joystick_by_mouse(
mouse_button_input: Res<Input<MouseButton>>,
mut cursor_evr: EventReader<CursorMoved>,
mut send_values: EventWriter<VirtualJoystickEvent<S>>,
mut joysticks: Query<(&VirtualJoystickNode<S>, &mut VirtualJoystickKnob)>,
mut send_values: EventWriter<InputEvent>,
windows: Query<&Window>,
) {
let window = windows.single();
Expand All @@ -119,75 +147,23 @@ pub fn update_joystick_by_mouse<S: Hash + Sync + Send + Clone + Default + Reflec
.map(|e| Vec2::new(e.position.x, window.height() - e.position.y))
.collect::<Vec<Vec2>>();

for (node, mut knob) in joysticks.iter_mut() {
// End drag
if mouse_button_input.just_released(MouseButton::Left)
&& is_some_and(knob.id_drag, |i| i == 0)
{
knob.id_drag = None;
knob.start_pos = Vec2::ZERO;
knob.current_pos = Vec2::ZERO;
knob.delta = Vec2::ZERO;
send_values.send(VirtualJoystickEvent {
id: node.id.clone(),
event: VirtualJoystickEventType::Up,
value: Vec2::ZERO,
delta: Vec2::ZERO,
axis: node.axis,
});
}

for pos in &mouse_positions {
// Start drag
if mouse_button_input.just_pressed(MouseButton::Left)
&& knob.id_drag.is_none()
&& knob.interactable_zone_rect.contains(*pos)
{
knob.id_drag = Some(0);
knob.start_pos = *pos;
send_values.send(VirtualJoystickEvent {
id: node.id.clone(),
event: VirtualJoystickEventType::Press,
value: Vec2::ZERO,
delta: Vec2::ZERO,
axis: node.axis,
});
}
// End drag
if mouse_button_input.just_released(MouseButton::Left) {
send_values.send(InputEvent::EndDrag {
id: 0,
pos: Vec2::ZERO,
});
}

// Dragging
if mouse_button_input.pressed(MouseButton::Left)
&& is_some_and(knob.id_drag, |i| i == 0)
{
knob.current_pos = *pos;
let half = knob.interactable_zone_rect.half_size();
if node.behaviour == VirtualJoystickType::Dynamic {
knob.base_pos = *pos;
let to_knob = knob.current_pos - knob.start_pos;
let distance_to_knob = to_knob.length();
if distance_to_knob > half.x {
let excess_distance = distance_to_knob - half.x;
knob.start_pos += to_knob.normalize() * excess_distance;
}
}
let d = (knob.start_pos - knob.current_pos) / half;
knob.delta = Vec2::new(
d.x.signum() * d.x.abs().min(1.),
d.y.signum() * d.y.abs().min(1.),
);
}
for pos in &mouse_positions {
// Start drag
if mouse_button_input.just_pressed(MouseButton::Left) {
send_values.send(InputEvent::StartDrag { id: 0, pos: *pos });
}

// Send event
if (knob.delta.x.abs() >= knob.dead_zone || knob.delta.y.abs() >= knob.dead_zone)
&& knob.id_drag.is_some()
{
send_values.send(VirtualJoystickEvent {
id: node.id.clone(),
event: VirtualJoystickEventType::Drag,
value: node.axis.handle_xy(-knob.current_pos.x, knob.current_pos.y),
delta: node.axis.handle_xy(-knob.delta.x, knob.delta.y),
axis: node.axis,
});
// Dragging
if mouse_button_input.pressed(MouseButton::Left) {
send_values.send(InputEvent::Dragging { id: 0, pos: *pos });
}
}
}
8 changes: 5 additions & 3 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ mod input;
mod joystick;

pub use behaviour::{VirtualJoystickAxis, VirtualJoystickType};
use input::{run_if_pc, update_joystick, update_joystick_by_mouse};
use input::{run_if_pc, update_input, update_joystick, update_joystick_by_mouse, InputEvent};
pub use joystick::{
TintColor, VirtualJoystickBundle, VirtualJoystickInteractionArea, VirtualJoystickNode,
};
Expand All @@ -35,13 +35,15 @@ impl<S: Hash + Sync + Send + Clone + Default + Reflect + 'static> Plugin
.register_type::<VirtualJoystickType>()
.register_type::<VirtualJoystickEventType>()
.add_event::<VirtualJoystickEvent<S>>()
.add_event::<InputEvent>()
.add_systems((
update_joystick::<S>
update_joystick
.run_if(not(run_if_pc))
.in_base_set(CoreSet::PreUpdate),
update_joystick_by_mouse::<S>
update_joystick_by_mouse
.run_if(run_if_pc)
.in_base_set(CoreSet::PreUpdate),
update_input::<S>.in_base_set(CoreSet::PreUpdate),
joystick_image_node_system::<S>
.before(UiSystem::Flex)
.in_base_set(CoreSet::PostUpdate),
Expand Down

0 comments on commit 16670c8

Please sign in to comment.