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 326 lines 11 kB view raw
1//! The interactable objects of a difficulty. 2 3use crate::{impl_duration, impl_timed}; 4use loose_enum::loose_enum; 5use serde::{Deserialize, Serialize}; 6 7/// The standard block/note that a player cuts. 8#[doc(alias = "Block")] 9#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)] 10#[cfg_attr( 11 feature = "bevy_reflect", 12 derive(bevy_reflect::Reflect), 13 reflect(Debug, Clone, PartialEq) 14)] 15pub struct Note { 16 /// The position of the object in time. 17 #[serde(rename = "b")] 18 pub beat: f32, 19 /// A value representing the vertical position of the object. 20 /// In the range 0..2 inclusive, with zero being the bottom and two being the top row. 21 #[serde(rename = "y")] 22 pub row: i32, 23 /// A value representing the horizontal position of the object. 24 /// In the range 0..3 inclusive, with zero being the far left and three being the far right column. 25 #[serde(rename = "x")] 26 pub col: i32, 27 /// The color that determines which saber should be used to cut the note. 28 #[serde(rename = "c")] 29 pub color: NoteColor, 30 /// The direction the note should be cut. 31 #[serde(rename = "d")] 32 pub direction: CutDirection, 33 /// The number of degrees counter-clockwise to offset the object by. 34 #[serde(rename = "a")] 35 pub angle_offset: f32, 36} 37 38impl_timed!(Note::beat); 39 40loose_enum! { 41 /// The color of a note, which determines which saber should be used to cut it. 42 #[derive(Default, Debug, Clone, Copy, Eq, PartialEq, Hash)] 43 #[cfg_attr( 44 feature = "bevy_reflect", 45 derive(bevy_reflect::Reflect), 46 reflect(Debug, Clone, PartialEq) 47 )] 48 pub enum NoteColor: i32 { 49 #[default] 50 Left = 0, 51 Right = 1, 52 } 53} 54 55loose_enum! { 56 /// The direction a note should be cut. 57 #[derive(Default, Debug, Clone, Copy, Eq, PartialEq, Hash)] 58 #[cfg_attr( 59 feature = "bevy_reflect", 60 derive(bevy_reflect::Reflect), 61 reflect(Debug, Clone, PartialEq) 62 )] 63 pub enum CutDirection: i32 { 64 #[default] 65 Up = 0, 66 Down = 1, 67 Left = 2, 68 Right = 3, 69 UpLeft = 4, 70 UpRight = 5, 71 DownLeft = 6, 72 DownRight = 7, 73 #[doc(alias = "Dot")] 74 Any = 8, 75 } 76} 77 78impl CutDirection { 79 /// Returns the number of degrees a note is rotated, with zero degrees being a downward note. 80 /// 81 /// Returns zero if the cut direction is undefined/any. 82 pub fn get_degrees(&self) -> f32 { 83 match self { 84 CutDirection::Up => 180.0, 85 CutDirection::Down => 0.0, 86 CutDirection::Left => -90.0, 87 CutDirection::Right => 90.0, 88 CutDirection::UpLeft => -135.0, 89 CutDirection::UpRight => 135.0, 90 CutDirection::DownLeft => -45.0, 91 CutDirection::DownRight => 45.0, 92 CutDirection::Any => 0.0, 93 CutDirection::Undefined(_) => 0.0, 94 } 95 } 96} 97 98/// The spiked bombs that players avoid hitting with their sabers. 99#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)] 100#[cfg_attr( 101 feature = "bevy_reflect", 102 derive(bevy_reflect::Reflect), 103 reflect(Debug, Clone, PartialEq) 104)] 105pub struct Bomb { 106 /// The position of the object in time. 107 #[serde(rename = "b")] 108 pub beat: f32, 109 /// A value representing the vertical position of the object. 110 /// In the range 0..2 inclusive, with zero being the bottom and two being the top row. 111 #[serde(rename = "y")] 112 pub row: i32, 113 /// A value representing the horizontal position of the object. 114 /// In the range 0..3 inclusive, with zero being the far left and three being the far right column. 115 #[serde(rename = "x")] 116 pub col: i32, 117} 118 119impl_timed!(Bomb::beat); 120 121/// A wall/obstacle that players avoid running into. 122#[doc(alias = "Obstacle")] 123#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] 124#[cfg_attr( 125 feature = "bevy_reflect", 126 derive(bevy_reflect::Reflect), 127 reflect(Debug, Clone, PartialEq) 128)] 129pub struct Wall { 130 /// The start position of the object in time. 131 #[serde(rename = "b")] 132 pub beat: f32, 133 /// The length (in beats) that an object takes place. 134 #[serde(rename = "d")] 135 pub duration: f32, 136 /// A value representing the vertical position of the object. 137 /// In the range 0..2 inclusive, with zero being the bottom and two being the top row. 138 #[serde(rename = "y")] 139 pub row: i32, 140 /// A value representing the horizontal position of the object. 141 /// In the range 0..3 inclusive, with zero being the far left and three being the far right column. 142 #[serde(rename = "x")] 143 pub col: i32, 144 /// The number of columns that the wall will take up. 145 #[serde(rename = "w")] 146 pub width: i32, 147 /// The number of rows that the wall will take up. 148 /// 149 /// A standard wall has a height of five while a crouch wall has a height of three. 150 #[serde(rename = "h")] 151 pub height: i32, 152} 153 154impl Default for Wall { 155 fn default() -> Self { 156 Self { 157 beat: 0.0, 158 duration: 1.0, 159 row: 0, 160 col: 0, 161 width: 1, 162 height: 5, 163 } 164 } 165} 166 167impl_duration!(Wall::beat, duration: duration); 168 169/// A glowing line that guides the player's saber. 170#[doc(alias = "Slider")] 171#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] 172#[cfg_attr( 173 feature = "bevy_reflect", 174 derive(bevy_reflect::Reflect), 175 reflect(Debug, Clone, PartialEq) 176)] 177pub struct Arc { 178 /// The start position of the object in time. 179 #[serde(rename = "b")] 180 pub beat: f32, 181 /// A value representing the vertical starting position of the object. 182 /// In the range 0..2 inclusive, with zero being the bottom and two being the top row. 183 #[serde(rename = "y")] 184 pub row: i32, 185 /// A value representing the horizontal starting position of the object. 186 /// In the range 0..3 inclusive, with zero being the far left and three being the far right column. 187 #[serde(rename = "x")] 188 pub col: i32, 189 /// The color of the arc. 190 #[serde(rename = "c")] 191 pub color: NoteColor, 192 /// The direction the arc moves in at the start. 193 #[serde(rename = "d")] 194 pub direction: CutDirection, 195 /// Controls how far away the starting bezier control point is in [cut direction](Self::direction). 196 #[serde(rename = "mu")] 197 pub control_point: f32, 198 199 /// The end position of the object in time. 200 #[serde(rename = "tb")] 201 pub tail_beat: f32, 202 /// A value representing the vertical ending position of the object. 203 /// In the range 0..2 inclusive, with zero being the bottom and two being the top row. 204 #[serde(rename = "ty")] 205 pub tail_row: i32, 206 /// A value representing the horizontal ending position of the object. 207 /// In the range 0..3 inclusive, with zero being the far left and three being the far right column. 208 #[serde(rename = "tx")] 209 pub tail_col: i32, 210 /// The direction the arc moves in at the end. 211 #[serde(rename = "tc")] 212 pub tail_direction: CutDirection, 213 /// Controls how far away the ending bezier control point is in [tail cut direction](Self::tail_direction). 214 #[serde(rename = "tmu")] 215 pub tail_control_point: f32, 216 217 /// Controls how the arc curves from its head to its tail. 218 #[serde(rename = "m")] 219 pub mid_anchor_mode: MidAnchorMode, 220} 221 222impl Default for Arc { 223 fn default() -> Self { 224 Self { 225 beat: 0.0, 226 row: 0, 227 col: 0, 228 color: Default::default(), 229 direction: Default::default(), 230 control_point: 1.0, 231 tail_beat: 1.0, 232 tail_row: 0, 233 tail_col: 0, 234 tail_direction: Default::default(), 235 tail_control_point: 1.0, 236 mid_anchor_mode: Default::default(), 237 } 238 } 239} 240 241impl_duration!(Arc::beat, end: tail_beat); 242 243loose_enum! { 244 /// Controls how an arc curves from its head to its tail. 245 #[derive(Default, Debug, Clone, Copy, Eq, PartialEq, Hash)] 246 #[cfg_attr( 247 feature = "bevy_reflect", 248 derive(bevy_reflect::Reflect), 249 reflect(Debug, Clone, PartialEq) 250 )] 251 pub enum MidAnchorMode: i32 { 252 #[default] 253 Straight = 0, 254 Clockwise = 1, 255 CounterClockwise = 2, 256 } 257} 258 259/// A chain/burst of mini-notes. 260#[doc(alias = "BurstSlider")] 261#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] 262#[cfg_attr( 263 feature = "bevy_reflect", 264 derive(bevy_reflect::Reflect), 265 reflect(Debug, Clone, PartialEq) 266)] 267pub struct Chain { 268 /// The start position of the object in time. 269 #[serde(rename = "b")] 270 pub beat: f32, 271 /// A value representing the vertical starting position of the object. 272 /// In the range 0..2 inclusive, with zero being the bottom and two being the top row. 273 #[serde(rename = "y")] 274 pub row: i32, 275 /// A value representing the horizontal starting position of the object. 276 /// In the range 0..3 inclusive, with zero being the far left and three being the far right column. 277 #[serde(rename = "x")] 278 pub col: i32, 279 /// The color that determines which saber should be used to cut the chain links. 280 #[serde(rename = "c")] 281 pub color: NoteColor, 282 /// The direction the start of the chain should be cut. 283 #[serde(rename = "d")] 284 pub direction: CutDirection, 285 286 /// The end position of the object in time. 287 #[serde(rename = "tb")] 288 pub tail_beat: f32, 289 /// A value representing the vertical ending position of the object. 290 /// In the range 0..2 inclusive, with zero being the bottom and two being the top row. 291 #[serde(rename = "ty")] 292 pub tail_row: i32, 293 /// A value representing the horizontal ending position of the object. 294 /// In the range 0..3 inclusive, with zero being the far left and three being the far right column. 295 #[serde(rename = "tx")] 296 pub tail_col: i32, 297 298 /// The number of links the chain has, including the connected [`Note`]. 299 #[serde(rename = "sc")] 300 pub link_count: i32, 301 /// The percent of the path (from head to tail) that will be used, usually in the range 0..1 inclusive. 302 /// Smaller values will result in the chain links bunching up near the head. 303 /// 304 /// Setting this to zero will crash the game. 305 #[serde(rename = "s")] 306 pub link_squish: f32, 307} 308 309impl Default for Chain { 310 fn default() -> Self { 311 Self { 312 beat: 0.0, 313 row: 1, 314 col: 0, 315 color: Default::default(), 316 direction: Default::default(), 317 tail_beat: 0.0, 318 tail_row: 0, 319 tail_col: 0, 320 link_count: 3, 321 link_squish: 1.0, 322 } 323 } 324} 325 326impl_duration!(Chain::beat, end: tail_beat);