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