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}