Skip to content

Commit

Permalink
added VirtualJoystickAction
Browse files Browse the repository at this point in the history
  • Loading branch information
clinuxrulz committed Mar 23, 2024
1 parent e2d25c1 commit e1d827e
Show file tree
Hide file tree
Showing 12 changed files with 161 additions and 33 deletions.
1 change: 1 addition & 0 deletions examples/invisible.rs
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ fn create_scene(mut cmd: Commands, asset_server: Res<AssetServer>) {
..default()
},
(JoystickInvisible, JoystickFloating),
NoAction,
);
}

Expand Down
2 changes: 2 additions & 0 deletions examples/multiple.rs
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ fn create_scene(mut cmd: Commands, asset_server: Res<AssetServer>) {
..default()
},
(JoystickFixed, JoystickHorizontalOnly),
NoAction,
);

// Spawn Virtual Joystick on Right
Expand All @@ -87,6 +88,7 @@ fn create_scene(mut cmd: Commands, asset_server: Res<AssetServer>) {
..default()
},
(JoystickFixed, JoystickVerticalOnly),
NoAction,
);
}

Expand Down
1 change: 1 addition & 0 deletions examples/multiple_joysticks_mobile/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,7 @@ fn create_scene(mut cmd: Commands, asset_server: Res<AssetServer>) {
..default()
},
(JoystickFixed, JoystickVerticalOnly),
NoAction,
);
}

Expand Down
1 change: 1 addition & 0 deletions examples/simple.rs
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ fn create_scene(mut cmd: Commands, asset_server: Res<AssetServer>) {
..default()
},
(JoystickFloating),
NoAction
);
}

Expand Down
1 change: 1 addition & 0 deletions examples/simple_mobile/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ fn create_scene(mut cmd: Commands, asset_server: Res<AssetServer>) {
..default()
},
(JoystickFloating),
NoAction,
);
}

Expand Down
51 changes: 37 additions & 14 deletions examples/tint.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,18 +17,43 @@ fn main() {
// Player with velocity
struct Player(pub f32);

struct TintBehavior {
struct TintAction {
down: Color,
up: Color
}

impl Behavior for TintBehavior {
fn update(&self, world: &mut World, entity: Entity) {
let is_down: bool;
impl VirtualJoystickAction<String> for TintAction {
fn on_start_drag(
&self,
_id: String,
_data: VirtualJoystickState,
world: &mut World,
entity: Entity,
) {
let mut child_entities: Vec<Entity> = Vec::new();
{
let Some(virtual_joystick_state) = world.get::<VirtualJoystickState>(entity) else { return; };
is_down = virtual_joystick_state.touch_state.is_some();
let Some(children) = world.get::<Children>(entity) else { return; };
for &child in children.iter() {
child_entities.push(child);
}
}
for &child in &child_entities {
let is_base_or_knob: bool;
{
is_base_or_knob = world.get::<VirtualJoystickUIBackground>(entity).is_some() || world.get::<VirtualJoystickUIKnob>(entity).is_some();
}
let Some(mut bg_color) = world.get_mut::<BackgroundColor>(child) else { continue; };
bg_color.0 = self.down;
}
}

fn on_end_drag(
&self,
_id: String,
_data: VirtualJoystickState,
world: &mut World,
entity: Entity,
) {
let mut child_entities: Vec<Entity> = Vec::new();
{
let Some(children) = world.get::<Children>(entity) else { return; };
Expand All @@ -42,7 +67,7 @@ impl Behavior for TintBehavior {
is_base_or_knob = world.get::<VirtualJoystickUIBackground>(entity).is_some() || world.get::<VirtualJoystickUIKnob>(entity).is_some();
}
let Some(mut bg_color) = world.get_mut::<BackgroundColor>(child) else { continue; };
bg_color.0 = if is_down { self.down } else { self.up };
bg_color.0 = self.up;
}
}
}
Expand Down Expand Up @@ -87,13 +112,11 @@ fn create_scene(mut cmd: Commands, asset_server: Res<AssetServer>) {
bottom: Val::Percent(15.),
..default()
},
(
JoystickFloating,
TintBehavior {
down: Color::RED.with_a(1.0),
up: Color::GREEN.with_a(0.5),
}
),
JoystickFloating,
TintAction {
down: Color::RED.with_a(1.0),
up: Color::GREEN.with_a(0.5),
}
);
}

Expand Down
37 changes: 37 additions & 0 deletions src/action.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
use std::marker::PhantomData;

use bevy::ecs::{all_tuples, entity::Entity, world::World};

use crate::VirtualJoystickState;

pub trait VirtualJoystickAction<I>: Send + Sync + 'static {
fn on_start_drag(
&self,
_id: I,
_data: VirtualJoystickState,
_world: &mut World,
_entity: Entity,
) {
}
fn on_drag(
&self,
_id: I,
_data: VirtualJoystickState,
_world: &mut World,
_entity: Entity,
) {
}
fn on_end_drag(
&self,
_id: I,
_data: VirtualJoystickState,
_world: &mut World,
_entity: Entity,
) {
}
}

#[derive(Default)]
pub struct NoAction;

impl<I> VirtualJoystickAction<I> for NoAction {}
20 changes: 10 additions & 10 deletions src/behavior.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,13 @@ use bevy::{ecs::{all_tuples, entity::Entity, world::World}, hierarchy::Children,

use crate::{components::VirtualJoystickState, VirtualJoystickUIBackground};

pub trait Behavior: Send + Sync + 'static {
pub trait VirtualJoystickBehavior: Send + Sync + 'static {
fn update_at_delta_stage(&self, _world: &mut World, _entity: Entity) {}
fn update_at_constraint_stage(&self, _world: &mut World, _entity: Entity) {}
fn update(&self, _world: &mut World, _entity: Entity) {}
}

impl<A: Behavior + Clone> Behavior for Arc<A> {
impl<A: VirtualJoystickBehavior + Clone> VirtualJoystickBehavior for Arc<A> {
fn update_at_delta_stage(&self, world: &mut World, entity: Entity) {
(**self).update_at_delta_stage(world, entity);
}
Expand All @@ -24,7 +24,7 @@ impl<A: Behavior + Clone> Behavior for Arc<A> {

macro_rules! impl_behavior_sets {
($($set: ident),*) => {
impl<$($set: Behavior),*> Behavior for ($($set,)*)
impl<$($set: VirtualJoystickBehavior),*> VirtualJoystickBehavior for ($($set,)*)
{
#[allow(non_snake_case)]
fn update_at_delta_stage(&self, world: &mut World, entity: Entity) {
Expand Down Expand Up @@ -68,7 +68,7 @@ pub struct JoystickFloating;
#[derive(Clone, Copy, Debug, Default, Reflect)]
pub struct JoystickDynamic;

impl Behavior for JoystickDeadZone {
impl VirtualJoystickBehavior for JoystickDeadZone {
fn update_at_constraint_stage(&self, world: &mut World, entity: Entity) {
let Some(mut joystick_state) = world.get_mut::<VirtualJoystickState>(entity) else { return; };
let dead_zone = self.0;
Expand All @@ -81,21 +81,21 @@ impl Behavior for JoystickDeadZone {
}
}

impl Behavior for JoystickHorizontalOnly {
impl VirtualJoystickBehavior for JoystickHorizontalOnly {
fn update_at_constraint_stage(&self, world: &mut World, entity: Entity) {
let Some(mut joystick_state) = world.get_mut::<VirtualJoystickState>(entity) else { return; };
joystick_state.delta.y = 0.0;
}
}

impl Behavior for JoystickVerticalOnly {
impl VirtualJoystickBehavior for JoystickVerticalOnly {
fn update_at_constraint_stage(&self, world: &mut World, entity: Entity) {
let Some(mut joystick_state) = world.get_mut::<VirtualJoystickState>(entity) else { return; };
joystick_state.delta.x = 0.0;
}
}

impl Behavior for JoystickInvisible {
impl VirtualJoystickBehavior for JoystickInvisible {
fn update(&self, world: &mut World, entity: Entity) {
let joystick_state = world.get::<VirtualJoystickState>(entity).map(|x| x.clone());
let Some(joystick_state) = joystick_state else { return; };
Expand All @@ -111,7 +111,7 @@ impl Behavior for JoystickInvisible {
}
}

impl Behavior for JoystickFixed {
impl VirtualJoystickBehavior for JoystickFixed {
fn update_at_delta_stage(&self, world: &mut World, entity: Entity) {
let mut children_entities: Vec<Entity> = Vec::new();
{
Expand Down Expand Up @@ -145,7 +145,7 @@ impl Behavior for JoystickFixed {
}
}

impl Behavior for JoystickFloating {
impl VirtualJoystickBehavior for JoystickFloating {
fn update_at_delta_stage(&self, world: &mut World, entity: Entity) {
let mut children_entities: Vec<Entity> = Vec::new();
{
Expand Down Expand Up @@ -196,7 +196,7 @@ impl Behavior for JoystickFloating {
}
}

impl Behavior for JoystickDynamic {
impl VirtualJoystickBehavior for JoystickDynamic {
fn update_at_delta_stage(&self, world: &mut World, entity: Entity) {
let joystick_rect: Rect;
{
Expand Down
15 changes: 11 additions & 4 deletions src/components.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ use bevy_inspector_egui::prelude::ReflectInspectorOptions;
#[cfg(feature = "inspect")]
use bevy_inspector_egui::InspectorOptions;

use crate::{behavior::JoystickFloating, Behavior, VirtualJoystickID};
use crate::{action::NoAction, behavior::JoystickFloating, VirtualJoystickAction, VirtualJoystickBehavior, VirtualJoystickID};

#[derive(Component, Copy, Clone, Debug, Default, Reflect)]
#[reflect(Component, Default)]
Expand All @@ -29,12 +29,14 @@ pub struct VirtualJoystickUIBackground;
pub struct VirtualJoystickNode<S: VirtualJoystickID> {
pub id: S,
#[reflect(ignore)]
pub behavior: Arc<dyn Behavior + Send + Sync + 'static>,
pub behavior: Arc<dyn VirtualJoystickBehavior>,
#[reflect(ignore)]
pub action: Arc<dyn VirtualJoystickAction<S>>
}

impl<S: VirtualJoystickID> Default for VirtualJoystickNode<S> {
fn default() -> Self {
Self { id: Default::default(), behavior: Arc::new(JoystickFloating), }
Self { id: Default::default(), behavior: Arc::new(JoystickFloating), action: Arc::new(NoAction::default()), }
}
}

Expand All @@ -59,10 +61,15 @@ impl<S: VirtualJoystickID> VirtualJoystickNode<S> {
self
}

pub fn with_behavior(mut self, behavior: impl Behavior) -> Self {
pub fn with_behavior(mut self, behavior: impl VirtualJoystickBehavior) -> Self {
self.behavior = Arc::new(behavior);
self
}

pub fn with_action(mut self, action: impl VirtualJoystickAction<S>) -> Self {
self.action = Arc::new(action);
self
}
}

#[derive(Clone, Debug, Default, Reflect)]
Expand Down
8 changes: 5 additions & 3 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,20 +2,22 @@ use std::{hash::Hash, marker::PhantomData};

use bevy::{ecs::schedule::ScheduleLabel, prelude::*, reflect::TypePath};

mod action;
mod behavior;
mod bundles;
mod components;
mod systems;
mod utils;

pub use behavior::{Behavior, JoystickDeadZone, JoystickHorizontalOnly, JoystickVerticalOnly, JoystickInvisible, JoystickFixed, JoystickFloating, JoystickDynamic};
pub use action::{NoAction, VirtualJoystickAction};
pub use behavior::{VirtualJoystickBehavior, JoystickDeadZone, JoystickHorizontalOnly, JoystickVerticalOnly, JoystickInvisible, JoystickFixed, JoystickFloating, JoystickDynamic};
pub use bundles::VirtualJoystickBundle;
pub use components::{
VirtualJoystickNode, VirtualJoystickState, VirtualJoystickUIBackground,
VirtualJoystickUIKnob,
};
use systems::{
update_behavior, update_behavior_constraints, update_behavior_knob_delta, update_fire_events, update_input, update_missing_state, update_ui
update_action, update_behavior, update_behavior_constraints, update_behavior_knob_delta, update_fire_events, update_input, update_missing_state, update_ui
};
pub use utils::create_joystick;

Expand Down Expand Up @@ -72,7 +74,7 @@ impl<S: VirtualJoystickID> Plugin for VirtualJoystickPlugin<S> {
update_behavior_constraints::<S>,
)
.add_systems(FireEvents, update_fire_events::<S>)
.add_systems(UpdateUI, (update_behavior::<S>, update_ui))
.add_systems(UpdateUI, (update_behavior::<S>, update_action::<S>, update_ui))
.add_systems(Update, |world: &mut World| {
world.run_schedule(UpdateKnobDelta);
world.run_schedule(ConstrainKnobDelta);
Expand Down
51 changes: 51 additions & 0 deletions src/systems.rs
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,57 @@ pub fn update_behavior<S: VirtualJoystickID>(world: &mut World) {
}
}

pub fn update_action<S: VirtualJoystickID>(world: &mut World) {
let mut joysticks = world.query::<(Entity,&VirtualJoystickNode<S>,&mut VirtualJoystickState)>();
let mut joystick_entities: Vec<Entity> = Vec::new();
for (joystick_entity, _, _) in joysticks.iter(world) {
joystick_entities.push(joystick_entity);
}
enum DragAction {
OnStartDrag,
OnDrag,
OnEndDrag,
}
for joystick_entity in joystick_entities {
let drag_action: Option<DragAction>;
{
let Some(joystick_state) = world.get::<VirtualJoystickState>(joystick_entity) else { continue; };
if joystick_state.just_released {
drag_action = Some(DragAction::OnEndDrag);
} else if let Some(touch_state) = &joystick_state.touch_state {
if touch_state.just_pressed {
drag_action = Some(DragAction::OnStartDrag);
} else {
drag_action = Some(DragAction::OnDrag);
}
} else {
drag_action = None;
}
}
let Some(drag_action) = drag_action else { continue; };
let id;
let action;
let joystick_state;
{
let Ok((_, virtual_joystick_node, joystick_state_2)) = joysticks.get_mut(world, joystick_entity) else { continue; };
id = virtual_joystick_node.id.clone();
action = Arc::clone(&virtual_joystick_node.action);
joystick_state = joystick_state_2.clone();
}
match drag_action {
DragAction::OnStartDrag => {
action.on_start_drag(id, joystick_state, world, joystick_entity);
},
DragAction::OnDrag => {
action.on_drag(id, joystick_state, world, joystick_entity);
},
DragAction::OnEndDrag => {
action.on_end_drag(id, joystick_state, world, joystick_entity);
},
}
}
}

pub fn update_fire_events<S: VirtualJoystickID>(
joysticks: Query<(&VirtualJoystickNode<S>,&VirtualJoystickState)>,
mut send_values: EventWriter<VirtualJoystickEvent<S>>,
Expand Down
Loading

0 comments on commit e1d827e

Please sign in to comment.