Skip to main content

rgc_chart/models/
common.rs

1use std::fmt;
2use crate::{def_varied_type_enum, wasm_bindgen};
3
4def_varied_type_enum!(pub ChartDefaults {
5    TITLE: &'static str => "Unknown Title",
6    ALT_TITLE: &'static str => "Unknown Title",
7    ARTIST: &'static str => "Unknown Artist",
8    ALT_ARTIST: &'static str => "Unknown Artist",
9    CREATOR: &'static str => "Unknown Creator",
10    GENRE: &'static str => "Unknown Genre",
11    SOURCE: &'static str => "Unknown Source",
12    TAGS: Vec<String> => Vec::<String>::new(),
13
14    BPM: &'static f32 => &0.0,
15    DIFFICULTY_NAME: &'static str => "Unknown Difficulty",
16    BG_PATH: &'static str => "Unknown Background Path",
17    SONG_PATH: &'static str => "Unknown Song File Path",
18    AUDIO_OFFSET: &'static i32 => &0,
19    PREVIEW_TIME: &'static i32 => &0,
20    OVERALL_DIFFICULTY: &'static f32 => &7.2,
21    KEY_COUNT: &'static u8 => &4,
22    
23    RAW_NOTES: &'static str => "No Note Data",
24    RAW_BPMS: &'static str => "No BPM Data",
25    RAW_STOPS: &'static str => "No STOPS Data",
26    RAW_SV: &'static str => "No SV Data",
27
28    HITSOUND: [u8; 4] => [0, 0, 0, 0],
29});
30
31#[derive(Clone)]
32pub struct HitObjectRow {
33    pub time: i32,
34    pub beat: f32,
35    pub keys: Vec<Key>
36}
37
38impl HitObjectRow {
39    pub fn empty(time: i32, beat: f32, key_count: usize) -> Self {
40        HitObjectRow {
41            time,
42            beat,
43            keys: vec![Key::empty(); key_count]
44        }
45    }
46}
47
48pub type Measure = Vec<HitObjectRow>;
49
50#[wasm_bindgen]
51#[derive(Debug, Clone, Copy, PartialEq)]
52pub enum TimingChangeType {
53    Bpm,
54    Sv,
55    Stop
56}
57
58#[allow(unused)]
59#[non_exhaustive]
60#[derive(Debug, PartialEq, Eq, PartialOrd, Ord)]
61pub enum GameMode {
62    Mania,
63    Taiko,
64    Catch,
65    OsuStandard
66}
67
68impl fmt::Display for GameMode {
69    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
70        match self {
71            Self::Mania => write!(f, "mania"),
72            Self::Taiko => write!(f, "taiko"),
73            Self::Catch => write!(f, "catch"),
74            Self::OsuStandard => write!(f, "osu! standard"),
75        }
76    }
77}
78
79pub trait HitObject {
80    fn game_mode(&self) -> GameMode;
81}
82
83#[wasm_bindgen]
84#[derive(Debug, Clone, Copy, PartialEq, Eq)]
85pub enum KeyType { 
86    Empty,
87    Normal,
88    SliderStart,
89    SliderEnd,
90    Mine,
91    Fake,
92    Unknown,
93}
94
95#[wasm_bindgen]
96#[derive(Debug, Clone, Copy, PartialEq, Eq)]
97pub struct Key {
98    #[wasm_bindgen(getter_with_clone)]
99    pub key_type: KeyType,
100    #[wasm_bindgen(getter_with_clone)]
101    pub slider_end_time: Option<i32>,
102}
103
104impl HitObject for Key { 
105    fn game_mode(&self) -> GameMode {
106        GameMode::Mania
107    }
108}
109
110#[wasm_bindgen]
111impl Key {
112    #[wasm_bindgen]
113    pub fn empty() -> Self {
114        Self {
115            key_type: KeyType::Empty,
116            slider_end_time: None,
117        }
118    }
119
120    #[wasm_bindgen]
121    pub fn normal() -> Self {
122        Self {
123            key_type: KeyType::Normal,
124            slider_end_time: None,
125        }
126    }
127
128    #[wasm_bindgen]
129    pub fn slider_start(value: Option<i32>) -> Self {
130        Self {
131            key_type: KeyType::SliderStart,
132            slider_end_time: value,
133        }
134    }
135
136    #[wasm_bindgen]
137    pub fn slider_end() -> Self {
138        Self {
139            key_type: KeyType::SliderEnd,
140            slider_end_time: None,
141        }
142    }
143
144    #[wasm_bindgen]
145    pub fn mine() -> Self {
146        Self {
147            key_type: KeyType::Mine,
148            slider_end_time: None,
149        }
150    }
151
152    #[wasm_bindgen]
153    pub fn fake() -> Self {
154        Self {
155            key_type: KeyType::Fake,
156            slider_end_time: None,
157        }
158    }
159
160    #[wasm_bindgen]
161    pub fn unknown() -> Self {
162        Self {
163            key_type: KeyType::Unknown,
164            slider_end_time: None,
165        }
166    }
167
168    #[wasm_bindgen]
169    pub fn slider_end_time(&self) -> Option<i32> {
170        self.slider_end_time
171    }
172}
173
174#[wasm_bindgen]
175#[derive(Debug, Clone, Copy, PartialEq, Eq)]
176pub enum TaikoHitobjectType {
177    Empty,
178    Don,
179    Kat,
180    BonusDon,
181    BonusKat,
182    DrumRoll,
183    BonusDrumRoll,
184    Balloon,
185    Unknown,
186}
187
188#[wasm_bindgen]
189#[derive(Debug, Clone, Copy, PartialEq, Eq)]
190pub struct TaikoHitobject {
191    #[wasm_bindgen(getter_with_clone)]
192    pub note_type: TaikoHitobjectType,
193    #[wasm_bindgen(getter_with_clone)]
194    pub end_time: Option<i32>,
195}
196
197impl HitObject for TaikoHitobject {
198    fn game_mode(&self) -> GameMode {
199        GameMode::Taiko
200    }
201}
202
203#[wasm_bindgen]
204impl TaikoHitobject {
205    #[wasm_bindgen]
206    pub fn empty() -> Self {
207        Self {
208            note_type: TaikoHitobjectType::Empty,
209            end_time: None,
210        }
211    }
212
213    #[wasm_bindgen]
214    pub fn don() -> Self {
215        Self {
216            note_type: TaikoHitobjectType::Don,
217            end_time: None,
218        }
219    }
220
221    #[wasm_bindgen]
222    pub fn kat() -> Self {
223        Self {
224            note_type: TaikoHitobjectType::Kat,
225            end_time: None,
226        }
227    }
228
229    #[wasm_bindgen]
230    pub fn bonus_don() -> Self {
231        Self {
232            note_type: TaikoHitobjectType::BonusDon,
233            end_time: None,
234        }
235    }
236
237    #[wasm_bindgen]
238    pub fn bonus_kat() -> Self {
239        Self {
240            note_type: TaikoHitobjectType::BonusKat,
241            end_time: None,
242        }
243    }
244
245    #[wasm_bindgen]
246    pub fn drum_roll(end_time: i32) -> Self {
247        Self {
248            note_type: TaikoHitobjectType::DrumRoll,
249            end_time: Some(end_time),
250        }
251    }
252
253    #[wasm_bindgen]
254    pub fn bonus_drum_roll(end_time: i32) -> Self {
255        Self {
256            note_type: TaikoHitobjectType::BonusDrumRoll,
257            end_time: Some(end_time),
258        }
259    }
260
261    #[wasm_bindgen]
262    pub fn balloon(end_time: i32) -> Self {
263        Self {
264            note_type: TaikoHitobjectType::Balloon,
265            end_time: Some(end_time),
266        }
267    }
268
269    #[wasm_bindgen]
270    pub fn unknown() -> Self {
271        Self {
272            note_type: TaikoHitobjectType::Unknown,
273            end_time: None,
274        }
275    }
276
277    #[wasm_bindgen]
278    pub fn end_time(&self) -> Option<i32> {
279        self.end_time
280    }
281}
282
283#[wasm_bindgen]
284#[derive(Debug, Clone, Copy, PartialEq, Eq)]
285pub enum CatchHitobjectType {
286    Empty,
287    Fruit,
288    Juice,
289    Banana,
290    Hyperfruit,
291    Unknown,
292}
293
294#[wasm_bindgen]
295#[derive(Debug, Clone, Copy, PartialEq)]
296pub struct CatchHitobject {
297    #[wasm_bindgen(getter_with_clone)]
298    pub object_type: CatchHitobjectType,
299    #[wasm_bindgen(getter_with_clone)]
300    pub x_position: i32,
301    #[wasm_bindgen(getter_with_clone)]
302    pub end_time: Option<i32>,
303    #[wasm_bindgen(getter_with_clone)]
304    pub hyperdash: bool,
305}
306
307impl HitObject for CatchHitobject {
308    fn game_mode(&self) -> GameMode {
309        GameMode::Catch
310    }
311}
312
313#[wasm_bindgen]
314impl CatchHitobject {
315    #[wasm_bindgen]
316    pub fn empty() -> Self {
317        Self {
318            object_type: CatchHitobjectType::Empty,
319            x_position: 0,
320            end_time: None,
321            hyperdash: false,
322        }
323    }
324
325    #[wasm_bindgen]
326    pub fn fruit(x_position: i32) -> Self {
327        Self {
328            object_type: CatchHitobjectType::Fruit,
329            x_position,
330            end_time: None,
331            hyperdash: false,
332        }
333    }
334
335    #[wasm_bindgen]
336    pub fn juice(x_position: i32) -> Self {
337        Self {
338            object_type: CatchHitobjectType::Juice,
339            x_position,
340            end_time: None,
341            hyperdash: false,
342        }
343    }
344
345    #[wasm_bindgen]
346    pub fn banana(x_position: i32, end_time: i32) -> Self {
347        Self {
348            object_type: CatchHitobjectType::Banana,
349            x_position,
350            end_time: Some(end_time),
351            hyperdash: false,
352        }
353    }
354
355    #[wasm_bindgen]
356    pub fn hyperfruit(x_position: i32) -> Self {
357        Self {
358            object_type: CatchHitobjectType::Hyperfruit,
359            x_position,
360            end_time: None,
361            hyperdash: true,
362        }
363    }
364
365    #[wasm_bindgen]
366    pub fn unknown() -> Self {
367        Self {
368            object_type: CatchHitobjectType::Unknown,
369            x_position: 0,
370            end_time: None,
371            hyperdash: false,
372        }
373    }
374
375    #[wasm_bindgen]
376    pub fn end_time(&self) -> Option<i32> {
377        self.end_time
378    }
379
380    #[wasm_bindgen]
381    pub fn is_hyperdash(&self) -> bool {
382        self.hyperdash
383    }
384}
385
386
387// This is only a dummy for osu standard
388#[wasm_bindgen]
389#[derive(Debug, Clone, Copy, PartialEq, Eq)]
390pub enum OsuHitobjectType {
391    Empty,
392    HitCircle,
393    Slider,
394    Spinner,
395    Unknown,
396}
397
398#[wasm_bindgen]
399#[derive(Debug, Clone, Copy, PartialEq)]
400pub struct OsuHitobject {
401    #[wasm_bindgen(getter_with_clone)]
402    pub object_type: OsuHitobjectType,
403    #[wasm_bindgen(getter_with_clone)]
404    pub x: i32,
405    #[wasm_bindgen(getter_with_clone)]
406    pub y: i32,
407     #[wasm_bindgen(getter_with_clone)]
408    pub end_time: Option<i32>,
409    #[wasm_bindgen(getter_with_clone)]
410    pub new_combo: bool,
411    #[wasm_bindgen(getter_with_clone)]
412    pub combo_skip: u8,
413}
414
415impl HitObject for OsuHitobject {
416    fn game_mode(&self) -> GameMode {
417        GameMode::OsuStandard
418    }
419}
420
421#[wasm_bindgen]
422impl OsuHitobject {
423    #[wasm_bindgen]
424    pub fn empty() -> Self {
425        Self {
426            object_type: OsuHitobjectType::Empty,
427            x: 0,
428            y: 0,
429            end_time: None,
430            new_combo: false,
431            combo_skip: 0,
432        }
433    }
434
435    #[wasm_bindgen]
436    pub fn hit_circle(x: i32, y: i32) -> Self {
437        Self {
438            object_type: OsuHitobjectType::HitCircle,
439            x,
440            y,
441            end_time: None,
442            new_combo: false,
443            combo_skip: 0,
444        }
445    }
446
447    #[wasm_bindgen]
448    pub fn slider(x: i32, y: i32) -> Self {
449        Self {
450            object_type: OsuHitobjectType::Slider,
451            x,
452            y,
453            end_time: None,
454            new_combo: false,
455            combo_skip: 0,
456        }
457    }
458
459    #[wasm_bindgen]
460    pub fn spinner(end_time: i32) -> Self {
461        Self {
462            object_type: OsuHitobjectType::Spinner,
463            x: 256,
464            y: 192,
465            end_time: Some(end_time),
466            new_combo: false,
467            combo_skip: 0,
468        }
469    }
470
471    #[wasm_bindgen]
472    pub fn unknown() -> Self {
473        Self {
474            object_type: OsuHitobjectType::Unknown,
475            x: 0,
476            y: 0,
477            end_time: None,
478            new_combo: false,
479            combo_skip: 0,
480        }
481    }
482
483    #[wasm_bindgen]
484    pub fn with_new_combo(mut self) -> Self {
485        self.new_combo = true;
486        self
487    }
488
489    #[wasm_bindgen]
490    pub fn with_combo_skip(mut self, skip: u8) -> Self {
491        self.combo_skip = skip;
492        self
493    }
494
495    #[wasm_bindgen]
496    pub fn end_time(&self) -> Option<i32> {
497        self.end_time
498    }
499
500    #[wasm_bindgen]
501    pub fn is_new_combo(&self) -> bool {
502        self.new_combo
503    }
504
505    #[wasm_bindgen]
506    pub fn combo_skip(&self) -> u8 {
507        self.combo_skip
508    }
509}