rosu_map/section/hit_objects/slider/
event.rs1#[derive(Copy, Clone, Debug, PartialEq, Eq)]
3pub enum SliderEventType {
4 Head,
5 Tick,
6 Repeat,
7 LastTick,
8 Tail,
9}
10
11#[derive(Clone, Debug, PartialEq)]
15pub struct SliderEvent {
16 pub kind: SliderEventType,
17 pub span_idx: i32,
18 pub span_start_time: f64,
19 pub time: f64,
20 pub path_progress: f64,
21}
22
23#[derive(Debug, PartialEq)]
27pub struct SliderEventsIter<'ticks_buf> {
28 start_time: f64,
29 span_duration: f64,
30 min_dist_from_end: f64,
31 tick_dist: f64,
32 len: f64,
33 span_count: i32,
34 ticks: &'ticks_buf mut Vec<SliderEvent>,
35 state: SliderEventsIterState,
36}
37
38impl<'ticks_buf> SliderEventsIter<'ticks_buf> {
39 const MAX_LEN: f64 = 100_000.0;
40 const TAIL_LENIENCY: f64 = -36.0;
41
42 pub fn new(
47 start_time: f64,
48 span_duration: f64,
49 velocity: f64,
50 mut tick_dist: f64,
51 total_dist: f64,
52 span_count: i32,
53 ticks: &'ticks_buf mut Vec<SliderEvent>,
54 ) -> Self {
55 let len = Self::MAX_LEN.min(total_dist);
56 tick_dist = tick_dist.clamp(0.0, len);
57 ticks.clear();
58
59 Self {
60 start_time,
61 span_duration,
62 min_dist_from_end: velocity * 10.0,
63 tick_dist,
64 len,
65 span_count,
66 ticks,
67 state: SliderEventsIterState::Head,
68 }
69 }
70}
71
72impl Iterator for SliderEventsIter<'_> {
73 type Item = SliderEvent;
74
75 fn next(&mut self) -> Option<Self::Item> {
76 loop {
77 match self.state {
78 SliderEventsIterState::Head => {
79 self.state = SliderEventsIterState::Ticks { span: 0 };
80
81 return Some(SliderEvent {
82 kind: SliderEventType::Head,
83 span_idx: 0,
84 span_start_time: self.start_time,
85 time: self.start_time,
86 path_progress: 0.0,
87 });
88 }
89 SliderEventsIterState::Ticks { ref mut span } => {
90 if let Some(event) = self.ticks.pop() {
91 return Some(event);
92 }
93
94 if *span == self.span_count {
95 self.state = SliderEventsIterState::LastTick;
96 } else {
97 let curr_span = *span;
98 *span += 1;
99 generate_ticks(self, curr_span);
100 }
101 }
102 SliderEventsIterState::LastTick => {
103 let total_duration = f64::from(self.span_count) * self.span_duration;
104 let final_span_idx = self.span_count - 1;
105 let final_span_start_time =
106 self.start_time + f64::from(final_span_idx) * self.span_duration;
107 let last_tick_time = (self.start_time + total_duration / 2.0)
108 .max((final_span_start_time + self.span_duration) + Self::TAIL_LENIENCY);
109 let mut last_tick_progress =
110 (last_tick_time - final_span_start_time) / self.span_duration;
111
112 if self.span_count % 2 == 0 {
113 last_tick_progress = 1.0 - last_tick_progress;
114 }
115
116 self.state = SliderEventsIterState::Tail;
117
118 return Some(SliderEvent {
119 kind: SliderEventType::LastTick,
120 span_idx: final_span_idx,
121 span_start_time: final_span_start_time,
122 time: last_tick_time,
123 path_progress: last_tick_progress,
124 });
125 }
126 SliderEventsIterState::Tail => {
127 let total_duration = f64::from(self.span_count) * self.span_duration;
128 let final_span_idx = self.span_count - 1;
129
130 self.state = SliderEventsIterState::Done;
131
132 return Some(SliderEvent {
133 kind: SliderEventType::Tail,
134 span_idx: final_span_idx,
135 span_start_time: self.start_time
136 + f64::from(self.span_count - 1) * self.span_duration,
137 time: self.start_time + total_duration,
138 path_progress: f64::from(self.span_count % 2),
139 });
140 }
141 SliderEventsIterState::Done => return None,
142 }
143 }
144 }
145
146 fn size_hint(&self) -> (usize, Option<usize>) {
147 match self.state {
148 SliderEventsIterState::Head => (3, None),
149 SliderEventsIterState::Ticks { .. } => (2 + self.ticks.len(), None),
150 SliderEventsIterState::LastTick => (2, Some(2)),
151 SliderEventsIterState::Tail => (1, Some(1)),
152 SliderEventsIterState::Done => (0, Some(0)),
153 }
154 }
155}
156
157#[derive(Copy, Clone, Debug, PartialEq, Eq)]
158enum SliderEventsIterState {
159 Head,
160 Ticks { span: i32 },
161 LastTick,
162 Tail,
163 Done,
164}
165
166fn generate_ticks(iter: &mut SliderEventsIter<'_>, span: i32) {
167 let reversed = span % 2 == 1;
168 let span_start_time = iter.start_time + f64::from(span) * iter.span_duration;
169 let with_repeat = span < iter.span_count - 1;
170
171 if reversed && with_repeat {
172 let repeat = new_repeat_point(span, span_start_time, iter.span_duration);
173 iter.ticks.push(repeat);
174 }
175
176 let mut d = iter.tick_dist;
177
178 if d > 0.0 {
179 while d <= iter.len {
180 if d >= iter.len - iter.min_dist_from_end {
181 break;
182 }
183
184 let path_progress = d / iter.len;
185
186 let time_progres = if reversed {
187 1.0 - path_progress
188 } else {
189 path_progress
190 };
191
192 let tick = SliderEvent {
193 kind: SliderEventType::Tick,
194 span_idx: span,
195 span_start_time,
196 time: span_start_time + time_progres * iter.span_duration,
197 path_progress,
198 };
199
200 iter.ticks.push(tick);
201 d += iter.tick_dist;
202 }
203 }
204
205 if !reversed {
207 if with_repeat {
208 let repeat = new_repeat_point(span, span_start_time, iter.span_duration);
209 iter.ticks.push(repeat);
210 }
211
212 iter.ticks.reverse();
213 }
214}
215
216fn new_repeat_point(span: i32, span_start_time: f64, span_duration: f64) -> SliderEvent {
217 SliderEvent {
218 kind: SliderEventType::Repeat,
219 span_idx: span,
220 span_start_time,
221 time: span_start_time + span_duration,
222 path_progress: f64::from((span + 1) % 2),
223 }
224}
225
226#[cfg(test)]
227mod tests {
228 use super::*;
229
230 const START_TIME: f64 = 0.0;
231 const SPAN_DURATION: f64 = 1000.0;
232
233 #[test]
234 fn single_span() {
235 let mut buf = Vec::new();
236
237 let events: Vec<_> = SliderEventsIter::new(
238 START_TIME,
239 SPAN_DURATION,
240 1.0,
241 SPAN_DURATION / 2.0,
242 SPAN_DURATION,
243 1,
244 &mut buf,
245 )
246 .collect();
247
248 assert_eq!(events[0].kind, SliderEventType::Head);
249 assert!((events[0].time - START_TIME).abs() < f64::EPSILON);
250
251 assert_eq!(events[1].kind, SliderEventType::Tick);
252 assert!((events[1].time - (SPAN_DURATION / 2.0)).abs() < f64::EPSILON);
253
254 assert_eq!(events[3].kind, SliderEventType::Tail);
255 assert!((events[3].time - SPAN_DURATION).abs() < f64::EPSILON);
256 }
257
258 #[test]
259 fn repeat() {
260 let mut buf = Vec::new();
261
262 let events: Vec<_> = SliderEventsIter::new(
263 START_TIME,
264 SPAN_DURATION,
265 1.0,
266 SPAN_DURATION / 2.0,
267 SPAN_DURATION,
268 2,
269 &mut buf,
270 )
271 .collect();
272
273 assert_eq!(events[0].kind, SliderEventType::Head);
274 assert!((events[0].time - START_TIME).abs() < f64::EPSILON);
275
276 assert_eq!(events[1].kind, SliderEventType::Tick);
277 assert!((events[1].time - (SPAN_DURATION / 2.0)).abs() < f64::EPSILON);
278
279 assert_eq!(events[2].kind, SliderEventType::Repeat);
280 assert!((events[2].time - SPAN_DURATION).abs() < f64::EPSILON);
281
282 assert_eq!(events[3].kind, SliderEventType::Tick);
283 assert!((events[3].time - (SPAN_DURATION + SPAN_DURATION / 2.0)).abs() < f64::EPSILON);
284
285 assert_eq!(events[5].kind, SliderEventType::Tail);
286 assert!((events[5].time - (2.0 * SPAN_DURATION)).abs() < f64::EPSILON);
287 }
288
289 #[test]
290 fn non_even_ticks() {
291 let mut buf = Vec::new();
292
293 let events: Vec<_> = SliderEventsIter::new(
294 START_TIME,
295 SPAN_DURATION,
296 1.0,
297 300.0,
298 SPAN_DURATION,
299 2,
300 &mut buf,
301 )
302 .collect();
303
304 assert_eq!(events[0].kind, SliderEventType::Head);
305 assert!((events[0].time - START_TIME).abs() < f64::EPSILON);
306
307 assert_eq!(events[1].kind, SliderEventType::Tick);
308 assert!((events[1].time - 300.0).abs() < f64::EPSILON);
309
310 assert_eq!(events[2].kind, SliderEventType::Tick);
311 assert!((events[2].time - 600.0).abs() < f64::EPSILON);
312
313 assert_eq!(events[3].kind, SliderEventType::Tick);
314 assert!((events[3].time - 900.0).abs() < f64::EPSILON);
315
316 assert_eq!(events[4].kind, SliderEventType::Repeat);
317 assert!((events[4].time - SPAN_DURATION).abs() < f64::EPSILON);
318
319 assert_eq!(events[5].kind, SliderEventType::Tick);
320 assert!((events[5].time - 1100.0).abs() < f64::EPSILON);
321
322 assert_eq!(events[6].kind, SliderEventType::Tick);
323 assert!((events[6].time - 1400.0).abs() < f64::EPSILON);
324
325 assert_eq!(events[7].kind, SliderEventType::Tick);
326 assert!((events[7].time - 1700.0).abs() < f64::EPSILON);
327
328 assert_eq!(events[9].kind, SliderEventType::Tail);
329 assert!((events[9].time - (2.0 * SPAN_DURATION)).abs() < f64::EPSILON);
330 }
331
332 #[test]
333 fn last_tick_offset() {
334 let mut buf = Vec::new();
335
336 let last_tick = SliderEventsIter::new(
337 START_TIME,
338 SPAN_DURATION,
339 1.0,
340 SPAN_DURATION / 2.0,
341 SPAN_DURATION,
342 1,
343 &mut buf,
344 )
345 .nth(2)
346 .unwrap();
347
348 assert_eq!(last_tick.kind, SliderEventType::LastTick);
349 assert!(
350 (last_tick.time - (SPAN_DURATION + SliderEventsIter::TAIL_LENIENCY)).abs()
351 < f64::EPSILON
352 );
353 }
354
355 #[test]
356 fn min_tick_dist() {
357 const VELOCITY: f64 = 5.0;
358 const MIN_DIST: f64 = VELOCITY * 10.0;
359
360 let mut buf = Vec::new();
361
362 let events = SliderEventsIter::new(
363 START_TIME,
364 SPAN_DURATION,
365 VELOCITY,
366 VELOCITY,
367 SPAN_DURATION,
368 2,
369 &mut buf,
370 );
371
372 for event in events {
373 if event.kind == SliderEventType::Tick {
374 assert!(
375 event.time < SPAN_DURATION - MIN_DIST || event.time > SPAN_DURATION + MIN_DIST
376 );
377 }
378 }
379 }
380}