Beatsaber Rust Utilities: A Beatsaber V3 parsing library.
beatsaber beatmap
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

at dev 165 lines 5.6 kB view raw
1//! Events that control the rotation of objects. 2 3use crate::difficulty::lightshow::easing::Easing; 4use crate::difficulty::lightshow::filter::Filter; 5use crate::difficulty::lightshow::group::EventData; 6use crate::difficulty::lightshow::{DistributionType, EventAxis, TransitionType}; 7use crate::loose_bool::LooseBool; 8use crate::{impl_event_box, impl_event_group, impl_timed}; 9use loose_enum::loose_enum; 10use serde::{Deserialize, Serialize}; 11 12/// A collection of [`RotationEventGroup`]s that share the same group ID and beat. 13#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] 14#[cfg_attr( 15 feature = "bevy_reflect", 16 derive(bevy_reflect::Reflect), 17 reflect(Debug, Clone, PartialEq) 18)] 19pub struct RotationEventBox { 20 /// The time the event takes place. 21 #[serde(rename = "b")] 22 pub beat: f32, 23 /// The ID of the collection of objects that this event effects. 24 #[serde(rename = "g")] 25 pub group_id: i32, 26 #[serde(rename = "e")] 27 pub groups: Vec<RotationEventGroup>, 28} 29 30impl Default for RotationEventBox { 31 fn default() -> Self { 32 Self { 33 beat: 0.0, 34 group_id: 0, 35 groups: vec![RotationEventGroup::default()], 36 } 37 } 38} 39 40impl_timed!(RotationEventBox::beat); 41impl_event_box!(RotationEventBox, RotationEventGroup, RotationEventData); 42 43/// A collection of [`RotationEventData`] that share the same [`EventAxis`], [`Filter`], and distribution. 44#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] 45#[cfg_attr( 46 feature = "bevy_reflect", 47 derive(bevy_reflect::Reflect), 48 reflect(Debug, Clone, PartialEq) 49)] 50pub struct RotationEventGroup { 51 #[serde(rename = "f")] 52 pub filter: Filter, 53 #[serde(rename = "d")] 54 pub beat_dist_type: DistributionType, 55 /// The strength of the beat distribution. Dependent on the [distribution type](Self::beat_dist_type). 56 /// 57 /// A value of zero will have no effect. 58 #[serde(rename = "w")] 59 pub beat_dist_value: f32, 60 #[serde(rename = "t")] 61 pub rotation_dist_type: DistributionType, 62 /// The strength of the rotation distribution. Dependent on the [distribution type](Self::rotation_dist_type). 63 /// 64 /// A value of zero will have no effect. 65 #[serde(rename = "s")] 66 pub rotation_dist_value: f32, 67 /// Whether the first [`RotationEventData`] of the group will be effected by rotation distribution. 68 #[serde(rename = "b")] 69 pub rotation_dist_effect_first: LooseBool, 70 /// > Only present in difficulty file V3.2 or higher. 71 #[serde(rename = "i")] 72 pub rotation_dist_easing: Option<Easing>, 73 #[serde(rename = "a")] 74 pub axis: EventAxis, 75 /// If true, the rotation will be mirrored. 76 #[serde(rename = "r")] 77 pub invert_axis: LooseBool, 78 #[serde(rename = "l")] 79 pub data: Vec<RotationEventData>, 80} 81 82impl Default for RotationEventGroup { 83 fn default() -> Self { 84 Self { 85 filter: Default::default(), 86 beat_dist_type: Default::default(), 87 beat_dist_value: 0.0, 88 rotation_dist_type: Default::default(), 89 rotation_dist_value: 0.0, 90 rotation_dist_effect_first: LooseBool::True, 91 rotation_dist_easing: Some(Easing::Linear), 92 axis: Default::default(), 93 invert_axis: Default::default(), 94 data: vec![RotationEventData::default()], 95 } 96 } 97} 98 99impl_event_group!(RotationEventGroup::get_rotation_offset, RotationEventData); 100 101impl RotationEventGroup { 102 /// Returns the number of degrees that the event will be offset for a given light ID. 103 /// # Panics 104 /// Will panic if the light ID is greater than or equal to the group size. 105 #[deprecated(note = "Experimental. Does not consider random in filter calculations.")] 106 #[allow(deprecated)] 107 pub fn get_rotation_offset(&self, light_id: i32, group_size: i32) -> f32 { 108 self.rotation_dist_type.compute_value_offset( 109 light_id, 110 group_size, 111 &self.filter, 112 self.rotation_dist_value, 113 self.data.last().map(|data| data.beat_offset), 114 self.rotation_dist_easing, 115 ) 116 } 117} 118 119/// The lowest-level group event type, which determines the base rotation of the event. 120#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)] 121#[cfg_attr( 122 feature = "bevy_reflect", 123 derive(bevy_reflect::Reflect), 124 reflect(Debug, Clone, PartialEq) 125)] 126pub struct RotationEventData { 127 /// The number of beats the event will be offset from the [`RotationEventBox`]'s beat. 128 #[serde(rename = "b")] 129 pub beat_offset: f32, 130 #[serde(rename = "p")] 131 pub transition_type: TransitionType, 132 #[serde(rename = "e")] 133 pub easing: Easing, 134 /// The base number of degrees the event will rotate objects by. 135 #[serde(rename = "r")] 136 pub degrees: f32, 137 #[serde(rename = "o")] 138 pub direction: RotationDirection, 139 /// Extends the rotation by 360 degrees in the [`RotationDirection`]. 140 #[serde(rename = "l")] 141 pub loops: i32, 142} 143 144impl EventData for RotationEventData { 145 fn get_beat_offset(&self) -> f32 { 146 self.beat_offset 147 } 148} 149 150loose_enum! { 151 /// Determines the direction that the rotation event will rotate. 152 /// Automatic will choose the shortest distance. 153 #[derive(Default, Debug, Clone, Copy, Eq, PartialEq, Hash)] 154 #[cfg_attr( 155 feature = "bevy_reflect", 156 derive(bevy_reflect::Reflect), 157 reflect(Debug, Clone, PartialEq) 158 )] 159 pub enum RotationDirection: i32 { 160 #[default] 161 Automatic = 0, 162 Clockwise = 1, 163 CounterClockwise = 2, 164 } 165}