pub mod backend;
mod stub;
#[cfg(feature = "dualsense")]
mod dualsense;
pub use backend::{
MotionBackend, MotionData, TouchpadBackend, TouchpadData as BackendTouchpadData,
};
pub use stub::StubBackend;
#[cfg(feature = "dualsense")]
pub use dualsense::DualSenseBackend;
use bevy::prelude::*;
#[derive(Resource)]
pub struct ActiveMotionBackend {
backend: Box<dyn MotionBackend + Send + Sync>,
}
impl Default for ActiveMotionBackend {
fn default() -> Self {
Self {
backend: Box::new(StubBackend::new()),
}
}
}
impl ActiveMotionBackend {
pub fn new<B: MotionBackend + Send + Sync + 'static>(backend: B) -> Self {
Self {
backend: Box::new(backend),
}
}
pub fn poll(&mut self) -> Option<MotionData> {
self.backend.poll()
}
#[must_use]
pub fn is_connected(&self) -> bool {
self.backend.is_connected()
}
}
#[derive(Resource)]
pub struct ActiveTouchpadBackend {
backend: Box<dyn TouchpadBackend + Send + Sync>,
}
impl Default for ActiveTouchpadBackend {
fn default() -> Self {
Self {
backend: Box::new(StubBackend::new()),
}
}
}
impl ActiveTouchpadBackend {
pub fn new<B: TouchpadBackend + Send + Sync + 'static>(backend: B) -> Self {
Self {
backend: Box::new(backend),
}
}
pub fn poll(&mut self) -> Option<BackendTouchpadData> {
self.backend.poll()
}
}
pub fn update_motion_from_backend(
mut backend: ResMut<ActiveMotionBackend>,
mut gyro_query: Query<&mut crate::gyro::GyroData>,
mut accel_query: Query<&mut crate::gyro::AccelData>,
) {
if let Some(data) = backend.poll() {
for mut gyro in &mut gyro_query {
gyro.set_raw(data.gyro_pitch, data.gyro_yaw, data.gyro_roll);
}
for mut accel in &mut accel_query {
accel.set_raw(data.accel_x, data.accel_y, data.accel_z);
}
}
}
pub fn update_touchpad_from_backend(
mut backend: ResMut<ActiveTouchpadBackend>,
mut touchpad_query: Query<&mut crate::touchpad::TouchpadData>,
) {
if let Some(data) = backend.poll() {
for mut touchpad in &mut touchpad_query {
touchpad.set_finger(0, data.finger1.x, data.finger1.y, data.finger1.active);
touchpad.set_finger(1, data.finger2.x, data.finger2.y, data.finger2.active);
touchpad.button_pressed = data.button_pressed;
}
}
}
#[expect(
dead_code,
reason = "called from plugin when motion-backends feature is enabled"
)]
pub(crate) fn register_motion_backend(app: &mut App) {
app.init_resource::<ActiveMotionBackend>()
.init_resource::<ActiveTouchpadBackend>();
}
#[expect(
dead_code,
reason = "called from plugin when motion-backends feature is enabled"
)]
pub(crate) fn add_motion_backend_systems(app: &mut App) {
app.add_systems(
Update,
(update_motion_from_backend, update_touchpad_from_backend),
);
}