rgc_chart/models/quaver/
hitobjects.rs1use serde::{Deserialize, Serialize};
2use crate::models::quaver::sound::KeySound;
3use crate::models::generic::sound;
4use crate::utils::serde::trim_float;
5
6#[derive(Debug, Deserialize, Serialize)]
7pub struct HitObject {
8 #[serde(rename = "StartTime", serialize_with = "trim_float")]
9 pub start_time: f32,
10
11 #[serde(rename = "Lane")]
12 pub lane: u8,
13
14 #[serde(rename = "EndTime", skip_serializing_if = "Option::is_none")]
15 pub endtime: Option<f32>,
16
17 #[serde(rename = "HitSound", skip_serializing_if = "Option::is_none")]
18 pub hit_sound: Option<String>,
19
20 #[serde(rename = "KeySounds")]
21 pub key_sounds: Vec<KeySound>,
22}
23
24impl Default for HitObject {
25 fn default() -> Self {
26 Self {
27 start_time: 0.0,
28 lane: 0,
29 endtime: None,
30 hit_sound: None,
31 key_sounds: Vec::new()
32 }
33 }
34}
35
36impl HitObject {
37 pub fn start_time(&self) -> f32 {
38 self.start_time
39 }
40
41 pub fn end_time(&self) -> Option<f32> {
42 self.endtime
43 }
44
45 pub fn lane(&self) -> u8 {
46 self.lane
47 }
48
49 pub fn is_ln(&self) -> bool {
50 self.end_time().is_some()
51 }
52
53 pub fn key_sounds(&self) -> &Vec<KeySound> {
54 &self.key_sounds
55 }
56
57 pub fn hit_sound(&self) -> Option<&str> {
58 self.hit_sound.as_deref()
59 }
60
61 pub fn get_generic_keysound(&self) -> sound::KeySound {
62 let hitsound_type = match self.hit_sound().unwrap_or("").to_lowercase().as_str() {
63 "clap" => sound::HitSoundType::Clap,
64 "whistle" => sound::HitSoundType::Whistle,
65 "finish" => sound::HitSoundType::Finish,
66 _ => sound::HitSoundType::Normal,
67 };
68
69 if self.key_sounds().is_empty() {
70 sound::KeySound::of_type(100, hitsound_type)
71 } else {
72 let key_sound = self.key_sounds().first().unwrap();
73 sound::KeySound::with_custom(key_sound.volume.clamp(0, 100), key_sound.sample, Some(hitsound_type))
74 }
75 }
76}