Skip to main content

pfx_input/
record.rs

1use serde::{Deserialize, Serialize};
2
3use crate::backend::Backend;
4use crate::device::{MouseButton, PadId};
5use crate::event::InputEvent;
6use crate::rumble::MotorCommand;
7use crate::state::{ActionState, Active};
8
9pub const RECORDING_VERSION: u32 = 1;
10
11#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
12pub struct Start {
13    pub events: Vec<InputEvent>,
14    pub states: Vec<ActionState>,
15    pub active: Active,
16    pub last_pad: Option<PadId>,
17    pub anchor: Option<[f32; 2]>,
18    #[serde(default, skip_serializing_if = "Vec::is_empty")]
19    pub outside: Vec<MouseButton>,
20}
21
22#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
23pub struct Recording {
24    pub version: u32,
25    pub step_us: u32,
26    pub start: Start,
27    pub steps: Vec<Vec<InputEvent>>,
28}
29
30impl Recording {
31    pub fn new(step_us: u32, start: Start) -> Self {
32        Self {
33            version: RECORDING_VERSION,
34            step_us,
35            start,
36            steps: Vec::new(),
37        }
38    }
39
40    pub fn len(&self) -> usize {
41        self.steps.len()
42    }
43
44    pub fn is_empty(&self) -> bool {
45        self.steps.is_empty()
46    }
47
48    pub fn player(&self) -> Player<'_> {
49        Player {
50            recording: self,
51            at: 0,
52            motors: Vec::new(),
53        }
54    }
55}
56
57#[derive(Clone, Debug)]
58pub struct Player<'a> {
59    recording: &'a Recording,
60    at: usize,
61    pub motors: Vec<MotorCommand>,
62}
63
64impl Player<'_> {
65    pub fn at(&self) -> usize {
66        self.at
67    }
68
69    pub fn finished(&self) -> bool {
70        self.at >= self.recording.steps.len()
71    }
72}
73
74impl Backend for Player<'_> {
75    fn poll(&mut self, events: &mut Vec<InputEvent>) {
76        if let Some(step) = self.recording.steps.get(self.at) {
77            events.extend(step.iter().cloned());
78        }
79        self.at += 1;
80    }
81
82    fn set_motors(&mut self, command: &MotorCommand) -> bool {
83        self.motors.push(*command);
84        false
85    }
86}