bevy_buttplug/
lib.rs

1use bevy::time::FixedTimestep;
2use bevy::{ecs::component, prelude::*};
3use bevy_tokio_tasks::*;
4use buttplug::client::{ButtplugClient, ButtplugClientDevice, ScalarValueCommand};
5use buttplug::util::in_process_client;
6use std::sync::{mpsc::*, Arc};
7pub struct VibePlugin;
8
9#[derive(Component, Deref, DerefMut, Clone)]
10struct VibeClient(pub Arc<ButtplugClient>);
11pub enum VibeEvent {
12    Scan(bool),
13    Devices,
14    Vibe(u32, f32),
15    Stop(u32),
16}
17#[derive(Debug)]
18pub enum VibeResponse {
19    Devices(Vec<Arc<ButtplugClientDevice>>),
20}
21
22impl Plugin for VibePlugin {
23    fn build(&self, app: &mut App) {
24        app.add_plugin(bevy_tokio_tasks::TokioTasksPlugin::default())
25            .add_event::<VibeEvent>()
26            .add_event::<VibeResponse>()
27            .add_startup_system(start_server)
28            .add_system(scan)
29            .add_system(poll);
30    }
31}
32fn start_server(mut cmds: Commands, rt: ResMut<TokioTasksRuntime>) {
33    rt.spawn_background_task::<_, Result<(), ()>, _>(|mut ctx| async move {
34        let client = in_process_client("client", false).await;
35        ctx.run_on_main_thread(|ctx| {
36            ctx.world.spawn(VibeClient(Arc::new(client)));
37        })
38        .await;
39        Ok(())
40    });
41}
42fn poll(mut er: EventReader<VibeEvent>, rt: ResMut<TokioTasksRuntime>) {
43    for e in er.iter() {
44        match e {
45            VibeEvent::Scan(state) => {
46                let state = state.clone();
47                rt.spawn_background_task::<_, Result<(), ()>, _>(move |mut ctx| async move {
48                    let c = ctx
49                        .run_on_main_thread(move |ctx| {
50                            let mut c = ctx.world.query::<&VibeClient>();
51                            let c = c.get_single(ctx.world).unwrap().to_owned();
52                            Box::new(Arc::new(c))
53                        })
54                        .await;
55                    if state {
56                        info!("Started Scanning for devices");
57                        c.start_scanning().await;
58                    } else {
59                        info!("Stopped Scanning for devices");
60                        c.stop_scanning().await;
61                    }
62                    Ok(())
63                });
64            }
65            VibeEvent::Devices => {
66                rt.spawn_background_task::<_, Result<(), ()>, _>(|mut ctx| async move {
67                    let c = ctx
68                        .run_on_main_thread(move |ctx| {
69                            let mut c = ctx.world.query::<&VibeClient>();
70                            let c = c.get_single(ctx.world).unwrap().to_owned();
71                            ctx.world.send_event(VibeResponse::Devices(c.devices()));
72                        })
73                        .await;
74                    Ok(())
75                });
76            }
77            VibeEvent::Vibe(id, force) => {
78                let id = id.clone();
79                let force = force.clone();
80                rt.spawn_background_task::<_, Result<(), ()>, _>(move |mut ctx| async move {
81                    let c = ctx
82                        .run_on_main_thread(move |ctx| {
83                            let mut c = ctx.world.query::<&VibeClient>();
84                            let c = c.get_single(ctx.world).unwrap().to_owned();
85                            Box::new(Arc::new(c))
86                        })
87                        .await;
88                    for device in c.devices().into_iter() {
89                        if !device.index().eq(&id) {
90                            continue;
91                        }
92                        device.vibrate(&ScalarValueCommand::ScalarValue(force.into())).await;
93                    }
94                    Ok(())
95                });
96            }
97            VibeEvent::Stop(id) => {
98                let id = id.clone();
99                rt.spawn_background_task::<_, Result<(), ()>, _>(move |mut ctx| async move{
100                    let c = ctx
101                        .run_on_main_thread(move |ctx| {
102                            let mut c = ctx.world.query::<&VibeClient>();
103                            let c = c.get_single(ctx.world).unwrap().to_owned();
104                            Box::new(Arc::new(c))
105                        })
106                        .await;
107                    for device in c.devices().into_iter() {
108                        if !device.index().eq(&id) {
109                            continue;
110                        }
111                        device.stop().await;
112                    }
113                        Ok(())
114                });
115            }
116            _ => todo!(),
117        }
118    }
119}
120
121fn scan(
122    input: Res<Input<KeyCode>>,
123    rt: ResMut<TokioTasksRuntime>,
124    mut ew: EventWriter<VibeEvent>,
125    mut er: EventReader<VibeResponse>,
126) {
127    if input.just_pressed(KeyCode::T) {
128        ew.send(VibeEvent::Scan(true));
129    }
130    if input.just_pressed(KeyCode::Y) {
131        ew.send(VibeEvent::Scan(false));
132    }
133    if input.just_pressed(KeyCode::V) {
134        ew.send(VibeEvent::Vibe(0, 0.25));
135    } else if input.just_released(KeyCode::V){
136        ew.send(VibeEvent::Stop(0));
137    }
138}