rgc_chart/models/generic/
timing_points.rs1use crate::wasm_bindgen;
2use crate::models::common::TimingChangeType;
3
4#[derive(Debug, Clone, Copy)]
5pub struct TimingChange {
6 pub change_type: TimingChangeType,
7 pub value: f32,
8}
9
10#[derive(Debug, Clone)]
11pub struct TimingPoint {
12 pub time: i32,
13 pub beat: f32,
14 pub change: TimingChange,
15}
16
17#[wasm_bindgen]
19#[repr(C)]
20#[derive(Debug, Clone)]
21pub struct TimingPoints {
22 #[wasm_bindgen(skip)]
23 pub points: Vec<TimingPoint>,
24}
25
26impl From<Vec<TimingPoint>> for TimingPoints {
27 fn from(points: Vec<TimingPoint>) -> Self {
28 Self { points }
29 }
30}
31
32impl TimingPoints {
33 pub fn with_capacity(capacity: usize) -> Self {
34 Self {
35 points: Vec::with_capacity(capacity),
36 }
37 }
38
39 pub fn new(points: Vec<TimingPoint>) -> Self {
40 Self { points }
41 }
42
43 pub fn add(&mut self, time: i32, beat: f32, change: TimingChange) {
44 self.points.push(TimingPoint {
45 time,
46 beat,
47 change,
48 });
49 }
50
51 pub fn iter(&self) -> impl Iterator<Item = &TimingPoint> {
52 self.points.iter()
53 }
54
55 pub fn iter_mut(&mut self) -> impl Iterator<Item = &mut TimingPoint> {
56 self.points.iter_mut()
57 }
58
59 pub fn bpm_changes(&self) -> impl Iterator<Item = &TimingPoint> + '_ {
60 self.points
61 .iter()
62 .filter(|p| matches!(p.change.change_type, TimingChangeType::Bpm))
63 }
64
65 pub fn sv_changes(&self) -> impl Iterator<Item = &TimingPoint> + '_ {
66 self.points
67 .iter()
68 .filter(|p| matches!(p.change.change_type, TimingChangeType::Sv))
69 }
70
71 pub fn is_bpms_empty(&self) -> bool {
72 !self.points
73 .iter()
74 .any(|p| matches!(p.change.change_type, TimingChangeType::Bpm))
75 }
76
77 pub fn is_sv_empty(&self) -> bool {
78 !self.points
79 .iter()
80 .any(|p| matches!(p.change.change_type, TimingChangeType::Sv))
81 }
82
83 pub fn bpms(&self) -> Vec<f32> {
84 self.points
85 .iter()
86 .filter(|p| matches!(p.change.change_type, TimingChangeType::Bpm))
87 .map(|p| p.change.value)
88 .collect()
89 }
90
91 pub fn bpms_times(&self) -> Vec<i32> {
92 self.points
93 .iter()
94 .filter(|p| matches!(p.change.change_type, TimingChangeType::Bpm))
95 .map(|p| p.time)
96 .collect()
97 }
98
99 pub fn sv(&self) -> Vec<f32> {
100 self.points
101 .iter()
102 .filter(|p| matches!(p.change.change_type, TimingChangeType::Sv))
103 .map(|p| p.change.value)
104 .collect()
105 }
106}