Implemented most buttons and threaded force feedback
parent
4b87e6c013
commit
fe162b60ff
|
@ -1 +1,2 @@
|
||||||
/target
|
/target
|
||||||
|
/logs
|
110
logs/latest.log
110
logs/latest.log
|
@ -1,110 +0,0 @@
|
||||||
2024-10-18T22:01:48.001029Z INFO src/gamepad_manager.rs:33: Selected gamepad changed to: Some(
|
|
||||||
GamepadId(
|
|
||||||
0,
|
|
||||||
),
|
|
||||||
)
|
|
||||||
2024-10-18T22:01:48.001150Z INFO src/gamepad_manager.rs:33: Selected gamepad changed to: Some(
|
|
||||||
GamepadId(
|
|
||||||
0,
|
|
||||||
),
|
|
||||||
)
|
|
||||||
2024-10-18T22:01:48.474890Z INFO src/gamepad_manager.rs:33: Selected gamepad changed to: Some(
|
|
||||||
GamepadId(
|
|
||||||
0,
|
|
||||||
),
|
|
||||||
)
|
|
||||||
2024-10-18T22:01:48.474947Z INFO src/gamepad_manager.rs:33: Selected gamepad changed to: Some(
|
|
||||||
GamepadId(
|
|
||||||
0,
|
|
||||||
),
|
|
||||||
)
|
|
||||||
2024-10-18T22:01:48.495298Z INFO src/gamepad_manager.rs:33: Selected gamepad changed to: Some(
|
|
||||||
GamepadId(
|
|
||||||
0,
|
|
||||||
),
|
|
||||||
)
|
|
||||||
2024-10-18T22:01:48.495345Z INFO src/gamepad_manager.rs:33: Selected gamepad changed to: Some(
|
|
||||||
GamepadId(
|
|
||||||
0,
|
|
||||||
),
|
|
||||||
)
|
|
||||||
2024-10-18T22:01:48.618136Z INFO src/gamepad_manager.rs:33: Selected gamepad changed to: Some(
|
|
||||||
GamepadId(
|
|
||||||
0,
|
|
||||||
),
|
|
||||||
)
|
|
||||||
2024-10-18T22:01:48.659732Z INFO src/gamepad_manager.rs:33: Selected gamepad changed to: Some(
|
|
||||||
GamepadId(
|
|
||||||
0,
|
|
||||||
),
|
|
||||||
)
|
|
||||||
2024-10-18T22:01:48.659792Z INFO src/gamepad_manager.rs:33: Selected gamepad changed to: Some(
|
|
||||||
GamepadId(
|
|
||||||
0,
|
|
||||||
),
|
|
||||||
)
|
|
||||||
2024-10-18T22:01:48.743791Z INFO src/gamepad_manager.rs:33: Selected gamepad changed to: Some(
|
|
||||||
GamepadId(
|
|
||||||
0,
|
|
||||||
),
|
|
||||||
)
|
|
||||||
2024-10-18T22:01:48.743851Z INFO src/gamepad_manager.rs:33: Selected gamepad changed to: Some(
|
|
||||||
GamepadId(
|
|
||||||
0,
|
|
||||||
),
|
|
||||||
)
|
|
||||||
2024-10-18T22:01:49.058470Z INFO src/gamepad_manager.rs:33: Selected gamepad changed to: Some(
|
|
||||||
GamepadId(
|
|
||||||
0,
|
|
||||||
),
|
|
||||||
)
|
|
||||||
2024-10-18T22:01:49.058527Z INFO src/gamepad_manager.rs:33: Selected gamepad changed to: Some(
|
|
||||||
GamepadId(
|
|
||||||
0,
|
|
||||||
),
|
|
||||||
)
|
|
||||||
2024-10-18T22:01:49.099680Z INFO src/gamepad_manager.rs:33: Selected gamepad changed to: Some(
|
|
||||||
GamepadId(
|
|
||||||
0,
|
|
||||||
),
|
|
||||||
)
|
|
||||||
2024-10-18T22:01:49.099736Z INFO src/gamepad_manager.rs:33: Selected gamepad changed to: Some(
|
|
||||||
GamepadId(
|
|
||||||
0,
|
|
||||||
),
|
|
||||||
)
|
|
||||||
2024-10-18T22:01:49.579664Z INFO src/gamepad_manager.rs:33: Selected gamepad changed to: Some(
|
|
||||||
GamepadId(
|
|
||||||
0,
|
|
||||||
),
|
|
||||||
)
|
|
||||||
2024-10-18T22:01:49.579721Z INFO src/gamepad_manager.rs:33: Selected gamepad changed to: Some(
|
|
||||||
GamepadId(
|
|
||||||
0,
|
|
||||||
),
|
|
||||||
)
|
|
||||||
2024-10-18T22:01:50.259909Z INFO src/gamepad_manager.rs:33: Selected gamepad changed to: Some(
|
|
||||||
GamepadId(
|
|
||||||
0,
|
|
||||||
),
|
|
||||||
)
|
|
||||||
2024-10-18T22:01:50.259973Z INFO src/gamepad_manager.rs:33: Selected gamepad changed to: Some(
|
|
||||||
GamepadId(
|
|
||||||
0,
|
|
||||||
),
|
|
||||||
)
|
|
||||||
2024-10-18T22:01:50.259992Z INFO src/gamepad_manager.rs:33: Selected gamepad changed to: Some(
|
|
||||||
GamepadId(
|
|
||||||
0,
|
|
||||||
),
|
|
||||||
)
|
|
||||||
2024-10-18T22:01:50.657504Z INFO src/gamepad_manager.rs:33: Selected gamepad changed to: Some(
|
|
||||||
GamepadId(
|
|
||||||
0,
|
|
||||||
),
|
|
||||||
)
|
|
||||||
2024-10-18T22:01:50.657561Z INFO src/gamepad_manager.rs:33: Selected gamepad changed to: Some(
|
|
||||||
GamepadId(
|
|
||||||
0,
|
|
||||||
),
|
|
||||||
)
|
|
196
src/app.rs
196
src/app.rs
|
@ -1,6 +1,6 @@
|
||||||
use std::time::{Duration, Instant};
|
use std::time::{Duration, Instant};
|
||||||
|
|
||||||
use color_eyre::{owo_colors::OwoColorize, Result};
|
use color_eyre::{eyre::eyre, owo_colors::OwoColorize, Result};
|
||||||
use gilrs::{Gamepad, Gilrs};
|
use gilrs::{Gamepad, Gilrs};
|
||||||
use ratatui::{
|
use ratatui::{
|
||||||
buffer::Buffer,
|
buffer::Buffer,
|
||||||
|
@ -78,6 +78,8 @@ impl App {
|
||||||
self.manager.scan_gamepads();
|
self.manager.scan_gamepads();
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
KeyCode::Char('v') => self.manager.test_weak_ff(),
|
||||||
|
KeyCode::Char('V') => self.manager.test_strong_ff(),
|
||||||
KeyCode::Char('q') | KeyCode::Char('Q') | KeyCode::Esc => self.quit(),
|
KeyCode::Char('q') | KeyCode::Char('Q') | KeyCode::Esc => self.quit(),
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
|
@ -94,33 +96,35 @@ impl App {
|
||||||
self.state = AppState::Quitting;
|
self.state = AppState::Quitting;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn render_title(area: Rect, buf: &mut Buffer) {
|
// fn render_title(area: Rect, buf: &mut Buffer) {
|
||||||
Paragraph::new("App Example Title")
|
// Paragraph::new("App Example Title")
|
||||||
.block(
|
// .block(
|
||||||
Block::bordered()
|
// Block::bordered()
|
||||||
.border_type(BorderType::Rounded)
|
// .border_type(BorderType::Rounded)
|
||||||
.padding(Padding::top(1)),
|
// .padding(Padding::top(1)),
|
||||||
)
|
// )
|
||||||
.alignment(Alignment::Center)
|
// .alignment(Alignment::Center)
|
||||||
.render(area, buf);
|
// .render(area, buf);
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
|
// fn render_connected_gamepad(&self, area: Rect, buf: &mut Buffer) {
|
||||||
|
// Paragraph::new(format!(
|
||||||
|
// "{} connected gamepads",
|
||||||
|
// self.manager.connected_gamepads()
|
||||||
|
// ))
|
||||||
|
// .block(
|
||||||
|
// Block::bordered()
|
||||||
|
// .border_type(BorderType::Rounded)
|
||||||
|
// .padding(Padding::top(1)),
|
||||||
|
// )
|
||||||
|
// .alignment(Alignment::Center)
|
||||||
|
// .bold()
|
||||||
|
// .render(area, buf);
|
||||||
|
// }
|
||||||
|
|
||||||
fn render_connected_gamepad(&self, area: Rect, buf: &mut Buffer) {
|
fn render_action_buttons(&self, area: Rect, buf: &mut Buffer) {
|
||||||
Paragraph::new(format!(
|
Block::bordered().render(area, buf);
|
||||||
"{} connected gamepads",
|
|
||||||
self.manager.connected_gamepads()
|
|
||||||
))
|
|
||||||
.block(
|
|
||||||
Block::bordered()
|
|
||||||
.border_type(BorderType::Rounded)
|
|
||||||
.padding(Padding::top(1)),
|
|
||||||
)
|
|
||||||
.alignment(Alignment::Center)
|
|
||||||
.bold()
|
|
||||||
.render(area, buf);
|
|
||||||
}
|
|
||||||
|
|
||||||
fn render_right_buttons(&self, area: Rect, buf: &mut Buffer) {
|
|
||||||
let north_button = self.create_action_button_ui(gilrs::Button::North);
|
let north_button = self.create_action_button_ui(gilrs::Button::North);
|
||||||
let east_button = self.create_action_button_ui(gilrs::Button::East);
|
let east_button = self.create_action_button_ui(gilrs::Button::East);
|
||||||
let south_button = self.create_action_button_ui(gilrs::Button::South);
|
let south_button = self.create_action_button_ui(gilrs::Button::South);
|
||||||
|
@ -144,13 +148,113 @@ impl App {
|
||||||
west_button.render(west, buf);
|
west_button.render(west, buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn render_dpad_buttons(&self, area: Rect, buf: &mut Buffer) {
|
||||||
|
Block::bordered().render(area, buf);
|
||||||
|
|
||||||
|
let up_button = self.create_action_button_ui(gilrs::Button::DPadUp);
|
||||||
|
let right_button = self.create_action_button_ui(gilrs::Button::DPadRight);
|
||||||
|
let down_button = self.create_action_button_ui(gilrs::Button::DPadDown);
|
||||||
|
let left_button = self.create_action_button_ui(gilrs::Button::DPadLeft);
|
||||||
|
|
||||||
|
let layers = Layout::vertical([Fill(1), Fill(1), Fill(1)]);
|
||||||
|
let [top, mid, bot] = layers.areas(area);
|
||||||
|
|
||||||
|
let top_layer = Layout::horizontal([Fill(1), Fill(1), Fill(1)]);
|
||||||
|
let [_, up, _] = top_layer.areas(top);
|
||||||
|
|
||||||
|
let mid_layer = Layout::horizontal([Fill(1), Fill(1), Fill(1)]);
|
||||||
|
let [left, _, right] = mid_layer.areas(mid);
|
||||||
|
|
||||||
|
let bot_layer = Layout::horizontal([Fill(1), Fill(1), Fill(1)]);
|
||||||
|
let [_, down, _] = bot_layer.areas(bot);
|
||||||
|
|
||||||
|
up_button.render(up, buf);
|
||||||
|
right_button.render(right, buf);
|
||||||
|
down_button.render(down, buf);
|
||||||
|
left_button.render(left, buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn render_setting_buttons(&self, area: Rect, buf: &mut Buffer) {
|
||||||
|
Block::bordered().render(area, buf);
|
||||||
|
|
||||||
|
let select_button = self.create_action_button_ui(gilrs::Button::Select);
|
||||||
|
let start_button = self.create_action_button_ui(gilrs::Button::Start);
|
||||||
|
|
||||||
|
let layers = Layout::horizontal([Fill(1), Fill(1), Fill(1), Fill(1), Fill(1)]);
|
||||||
|
let [_, select_area, _, start_area, _] = layers.areas(area);
|
||||||
|
|
||||||
|
let select_layer = Layout::vertical([Fill(1), Fill(1), Fill(1), Fill(1)]);
|
||||||
|
let [_, select, _, _] = select_layer.areas(select_area);
|
||||||
|
|
||||||
|
let start_layer = Layout::vertical([Fill(1), Fill(1), Fill(1), Fill(1)]);
|
||||||
|
let [_, start, _, _] = start_layer.areas(start_area);
|
||||||
|
|
||||||
|
select_button.render(select, buf);
|
||||||
|
start_button.render(start, buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn render_trigger_buttons(&self, area: Rect, buf: &mut Buffer) {
|
||||||
|
Block::bordered().render(area, buf);
|
||||||
|
|
||||||
|
let r1_button = self.create_action_button_ui(gilrs::Button::RightTrigger);
|
||||||
|
let r2_button = self.create_action_button_ui(gilrs::Button::RightTrigger2);
|
||||||
|
let l1_button = self.create_action_button_ui(gilrs::Button::LeftTrigger);
|
||||||
|
let l2_button = self.create_action_button_ui(gilrs::Button::LeftTrigger2);
|
||||||
|
|
||||||
|
let layers = Layout::horizontal([
|
||||||
|
Fill(2),
|
||||||
|
Fill(1),
|
||||||
|
Fill(1),
|
||||||
|
Fill(1),
|
||||||
|
Fill(4),
|
||||||
|
Fill(1),
|
||||||
|
Fill(1),
|
||||||
|
Fill(1),
|
||||||
|
Fill(2),
|
||||||
|
]);
|
||||||
|
let [_, l2_area, _, l1_area, _, r1_area, _, r2_area, _] = layers.areas(area);
|
||||||
|
|
||||||
|
let r1_layer = Layout::vertical([Fill(2), Fill(1), Fill(2)]);
|
||||||
|
let [_, r1, _] = r1_layer.areas(r1_area);
|
||||||
|
|
||||||
|
let r2_layer = Layout::vertical([Fill(1), Fill(3), Fill(1)]);
|
||||||
|
let [_, r2, _] = r2_layer.areas(r2_area);
|
||||||
|
|
||||||
|
let l1_layer = Layout::vertical([Fill(2), Fill(1), Fill(2)]);
|
||||||
|
let [_, l1, _] = l1_layer.areas(l1_area);
|
||||||
|
|
||||||
|
let l2_layer = Layout::vertical([Fill(1), Fill(3), Fill(1)]);
|
||||||
|
let [_, l2, _] = l2_layer.areas(l2_area);
|
||||||
|
|
||||||
|
r1_button.render(r1, buf);
|
||||||
|
r2_button.render(r2, buf);
|
||||||
|
l1_button.render(l1, buf);
|
||||||
|
l2_button.render(l2, buf);
|
||||||
|
|
||||||
|
//TODO: For PS4+ controllers doesn't have dedicated trigger push force
|
||||||
|
// let gauge_percentage = match self.manager.active_gamepad() {
|
||||||
|
// Ok(gamepad) => match gamepad.axis_data(gilrs::Axis::Unknown) {
|
||||||
|
// Some(ad) => ad.value(),
|
||||||
|
// None => 0.0,
|
||||||
|
// },
|
||||||
|
// Err(_) => 0.0,
|
||||||
|
// };
|
||||||
|
// let gauge_percentage = 0;
|
||||||
|
|
||||||
|
// Gauge::default()
|
||||||
|
// .gauge_style(Color::Green)
|
||||||
|
// .bg(Color::DarkGray)
|
||||||
|
// .ratio(gauge_percentage.into())
|
||||||
|
// .render(r2, buf);
|
||||||
|
}
|
||||||
|
|
||||||
fn create_action_button_ui(&self, dir: gilrs::Button) -> Block {
|
fn create_action_button_ui(&self, dir: gilrs::Button) -> Block {
|
||||||
let color = match self.manager.active_gamepad() {
|
let color = match self.manager.active_gamepad() {
|
||||||
Ok(gamepad) => match gamepad.is_pressed(dir) {
|
Ok(gamepad) => match gamepad.is_pressed(dir) {
|
||||||
true => Color::Green,
|
true => Color::Green,
|
||||||
false => Color::Gray,
|
false => Color::DarkGray,
|
||||||
},
|
},
|
||||||
Err(_) => Color::Gray,
|
Err(_) => Color::DarkGray,
|
||||||
};
|
};
|
||||||
|
|
||||||
Block::new().style(Style::default().bg(color))
|
Block::new().style(Style::default().bg(color))
|
||||||
|
@ -159,29 +263,26 @@ impl App {
|
||||||
|
|
||||||
impl Widget for &App {
|
impl Widget for &App {
|
||||||
fn render(self, area: Rect, buf: &mut Buffer) {
|
fn render(self, area: Rect, buf: &mut Buffer) {
|
||||||
let layout = Layout::vertical([Length(5), Min(0), Length(5)]);
|
let layout = Layout::vertical([Percentage(100)]);
|
||||||
let [header_area, inner_area, footer_area] = layout.areas(area);
|
let [inner_area] = layout.areas(area);
|
||||||
|
|
||||||
let header_layout = Layout::horizontal([Fill(1), Fill(4)]);
|
let gamepad_layout = Layout::vertical([Fill(2), Fill(4), Fill(3)]);
|
||||||
let [tabs_area, title_area] = header_layout.areas(header_area);
|
let [triggers, buttons, joysticks] = gamepad_layout.areas(inner_area);
|
||||||
|
|
||||||
let gamepad_layout = Layout::vertical([
|
let buttons_layout = Layout::horizontal([Fill(2), Fill(2), Fill(2)]);
|
||||||
Percentage(10),
|
let [left_buttons, mid_buttons, right_buttons] = buttons_layout.areas(buttons);
|
||||||
Percentage(50),
|
|
||||||
Percentage(30),
|
|
||||||
Percentage(10),
|
|
||||||
]);
|
|
||||||
let [_, buttons, joysticks, _] = gamepad_layout.areas(inner_area);
|
|
||||||
|
|
||||||
let buttons_layout = Layout::horizontal([Fill(1), Fill(2), Fill(2), Fill(2), Fill(1)]);
|
|
||||||
let [_, left_buttons, mid_buttons, right_buttons, _] = buttons_layout.areas(buttons);
|
|
||||||
|
|
||||||
// let details_layout = Layout::horizontal([Fill(2), Fill(2)]);
|
// let details_layout = Layout::horizontal([Fill(2), Fill(2)]);
|
||||||
// let [right_details_area, left_details_area] = details_layout.areas(details_area);
|
// let [right_details_area, left_details_area] = details_layout.areas(details_area);
|
||||||
|
|
||||||
App::render_title(title_area, buf);
|
let mut title_label = Block::bordered();
|
||||||
self.render_connected_gamepad(tabs_area, buf);
|
title_label = match self.manager.active_gamepad() {
|
||||||
Block::bordered().render(inner_area, buf);
|
Ok(gp) => title_label
|
||||||
|
.title(gp.name().to_string())
|
||||||
|
.title_style(Color::Rgb(255, 165, 35)),
|
||||||
|
Err(_) => title_label.title("No active device".to_string()),
|
||||||
|
};
|
||||||
|
title_label.render(inner_area, buf);
|
||||||
|
|
||||||
// Block::bordered()
|
// Block::bordered()
|
||||||
// .style(Style::default().bg(tailwind::GREEN.c900))
|
// .style(Style::default().bg(tailwind::GREEN.c900))
|
||||||
|
@ -191,7 +292,10 @@ impl Widget for &App {
|
||||||
// .style(Style::default().bg(tailwind::YELLOW.c300))
|
// .style(Style::default().bg(tailwind::YELLOW.c300))
|
||||||
// .render(details_area, buf);
|
// .render(details_area, buf);
|
||||||
|
|
||||||
self.render_right_buttons(right_buttons, buf);
|
self.render_dpad_buttons(left_buttons, buf);
|
||||||
|
self.render_setting_buttons(mid_buttons, buf);
|
||||||
|
self.render_action_buttons(right_buttons, buf);
|
||||||
|
self.render_trigger_buttons(triggers, buf);
|
||||||
|
|
||||||
// Block::bordered()
|
// Block::bordered()
|
||||||
// .style(Style::default().bg(tailwind::TEAL.c300))
|
// .style(Style::default().bg(tailwind::TEAL.c300))
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
use std::{thread, time::Duration};
|
||||||
|
|
||||||
use color_eyre::{eyre::eyre, Result};
|
use color_eyre::{eyre::eyre, Result};
|
||||||
use gilrs::{
|
use gilrs::{
|
||||||
ff::{BaseEffect, BaseEffectType, EffectBuilder, Replay, Ticks},
|
ff::{BaseEffect, BaseEffectType, EffectBuilder, Replay, Ticks},
|
||||||
|
@ -24,13 +26,9 @@ impl GamepadManager {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn select_gamepad(&mut self, id: impl Into<Option<GamepadId>>) {
|
pub fn set_active_gamepad(&mut self, id: impl Into<Option<GamepadId>>) {
|
||||||
self.active_gamepad = id.into();
|
self.active_gamepad = id.into();
|
||||||
}
|
// tracing::info!("Selected gamepad changed to: {:#?}", self.active_gamepad);
|
||||||
|
|
||||||
pub fn set_active_gamepad(&mut self, id: GamepadId) {
|
|
||||||
self.active_gamepad = Some(id);
|
|
||||||
tracing::info!("Selected gamepad changed to: {:#?}", self.active_gamepad);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn active_gamepad(&self) -> Result<Gamepad<'_>> {
|
pub fn active_gamepad(&self) -> Result<Gamepad<'_>> {
|
||||||
|
@ -52,7 +50,7 @@ impl GamepadManager {
|
||||||
let mut gamepads = vec![];
|
let mut gamepads = vec![];
|
||||||
|
|
||||||
// Iterate over all connected gamepads
|
// Iterate over all connected gamepads
|
||||||
for (id, gamepad) in self.gilrs.gamepads() {
|
for (id, _) in self.gilrs.gamepads() {
|
||||||
// println!("{} is {:?}", gamepad.name(), gamepad.power_info());
|
// println!("{} is {:?}", gamepad.name(), gamepad.power_info());
|
||||||
// println!("Has Force Feedback Enabled ? {}", gamepad.is_ff_supported());
|
// println!("Has Force Feedback Enabled ? {}", gamepad.is_ff_supported());
|
||||||
// if gamepad.is_ff_supported() {
|
// if gamepad.is_ff_supported() {
|
||||||
|
@ -65,34 +63,69 @@ impl GamepadManager {
|
||||||
self.gamepads = gamepads;
|
self.gamepads = gamepads;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn test_ff(&mut self, gamepad_id: GamepadId) {
|
pub fn test_weak_ff(&mut self) {
|
||||||
let gamepad = self.gilrs.gamepad(gamepad_id);
|
let Some(id) = self.active_gamepad
|
||||||
|
else {
|
||||||
|
tracing::warn!("No active gamepad found!");
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
|
||||||
let duration: u32 = 1000;
|
thread::spawn(move || {
|
||||||
let ff_play_ticks = Ticks::from_ms(duration);
|
let mut gilrs = Gilrs::new().unwrap();
|
||||||
|
let gamepad = gilrs.gamepad(id);
|
||||||
|
|
||||||
|
let duration = Ticks::from_ms(1000);
|
||||||
|
let delay = Ticks::from_ms(500);
|
||||||
let effect = EffectBuilder::new()
|
let effect = EffectBuilder::new()
|
||||||
.add_effect(BaseEffect {
|
|
||||||
kind: BaseEffectType::Strong { magnitude: 40_000 },
|
|
||||||
scheduling: Replay {
|
|
||||||
play_for: ff_play_ticks,
|
|
||||||
with_delay: ff_play_ticks * 2,
|
|
||||||
..Default::default()
|
|
||||||
},
|
|
||||||
envelope: Default::default(),
|
|
||||||
})
|
|
||||||
.add_effect(BaseEffect {
|
.add_effect(BaseEffect {
|
||||||
kind: BaseEffectType::Weak { magnitude: 40_000 },
|
kind: BaseEffectType::Weak { magnitude: 40_000 },
|
||||||
scheduling: Replay {
|
scheduling: Replay {
|
||||||
after: ff_play_ticks,
|
play_for: duration,
|
||||||
play_for: ff_play_ticks,
|
with_delay: delay,
|
||||||
..Default::default()
|
..Default::default()
|
||||||
},
|
},
|
||||||
envelope: Default::default(),
|
envelope: Default::default(),
|
||||||
})
|
})
|
||||||
.add_gamepad(&gamepad)
|
.add_gamepad(&gamepad)
|
||||||
.finish(&mut self.gilrs)
|
.finish(&mut gilrs)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
effect.play().unwrap();
|
effect.play().unwrap();
|
||||||
|
|
||||||
|
thread::sleep(Duration::from_millis(4500));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn test_strong_ff(&mut self) {
|
||||||
|
let Some(id) = self.active_gamepad
|
||||||
|
else {
|
||||||
|
tracing::warn!("No active gamepad found!");
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
|
||||||
|
thread::spawn(move || {
|
||||||
|
let mut gilrs = Gilrs::new().unwrap();
|
||||||
|
let gamepad = gilrs.gamepad(id);
|
||||||
|
|
||||||
|
let duration = Ticks::from_ms(1000);
|
||||||
|
let delay = Ticks::from_ms(500);
|
||||||
|
let effect = EffectBuilder::new()
|
||||||
|
.add_effect(BaseEffect {
|
||||||
|
kind: BaseEffectType::Strong { magnitude: 40_000 },
|
||||||
|
scheduling: Replay {
|
||||||
|
play_for: duration,
|
||||||
|
with_delay: delay,
|
||||||
|
..Default::default()
|
||||||
|
},
|
||||||
|
envelope: Default::default(),
|
||||||
|
})
|
||||||
|
.add_gamepad(&gamepad)
|
||||||
|
.finish(&mut gilrs)
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
effect.play().unwrap();
|
||||||
|
|
||||||
|
thread::sleep(Duration::from_millis(4500));
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue