Skip to main content

rgc_chart/models/generic/
hitobjects.rs

1use crate::wasm_bindgen;
2use crate::models::common::{Key, KeyType};
3use crate::models::generic::sound::{KeySound};
4
5#[derive(Debug, Clone)]
6pub struct HitObject {
7    pub time: i32,
8    pub beat: f32,
9    pub keysound: KeySound,
10    pub key: Key,
11    pub lane: u8,
12}
13
14// TODO: add wasm bindings for HitObject
15// TODO: add row and object count
16#[wasm_bindgen]
17#[repr(C)]
18#[derive(Debug, Clone)]
19pub struct HitObjects {
20    #[wasm_bindgen(skip)]
21    pub objects: Vec<HitObject>,
22}
23
24impl From<Vec<HitObject>> for HitObjects {
25    fn from(objects: Vec<HitObject>) -> Self {
26        Self { objects }
27    }
28}
29
30impl HitObjects {
31    pub fn with_capacity(capacity: usize) -> Self {
32        Self {
33            objects: Vec::with_capacity(capacity),
34        }
35    }
36
37    pub fn new(objects: Vec<HitObject>) -> Self {
38        Self { objects }
39    }
40
41    #[inline]
42    pub fn add_hitobject(
43        &mut self,
44        time: i32,
45        beat: f32,
46        keysound: KeySound,
47        key: Key,
48        lane: u8
49    ) {
50        if key.key_type == KeyType::Empty {
51            return;
52        }
53        self.objects.push(HitObject {
54            time,
55            beat,
56            keysound,
57            key,
58            lane,
59        });
60    }
61
62    #[inline]
63    pub fn add_hitobject_sorted(&mut self, object: HitObject) {
64        let len = self.objects.len();
65        
66        if len == 0 || object.time >= self.objects[len - 1].time {
67            self.objects.push(object);
68            return;
69        }
70
71        let pos = self.objects.binary_search_by(|obj| 
72            obj.time.cmp(&object.time)
73        ).unwrap_or_else(|pos| pos);
74        
75        self.objects.insert(pos, object);
76    }
77
78    pub fn iter(&self) -> impl Iterator<Item = &HitObject> {
79        self.objects.iter()
80    }
81}