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.

Started on event boxes.

AlephCubed 6c26b21d fcb1d348

+319 -34
+77
Cargo.lock
··· 3 3 version = 4 4 4 5 5 [[package]] 6 + name = "autocfg" 7 + version = "1.5.0" 8 + source = "registry+https://github.com/rust-lang/crates.io-index" 9 + checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8" 10 + 11 + [[package]] 6 12 name = "bsru" 7 13 version = "0.1.0" 8 14 dependencies = [ 15 + "bsru-legacy", 9 16 "serde", 10 17 "serde_json", 18 + "simple-easing", 11 19 ] 12 20 13 21 [[package]] 22 + name = "bsru-legacy" 23 + version = "0.1.0" 24 + dependencies = [ 25 + "bsru_macro", 26 + "glam", 27 + "num-traits", 28 + "serde", 29 + "serde_derive", 30 + "serde_json", 31 + "serde_repr_plus", 32 + "simple-easing", 33 + ] 34 + 35 + [[package]] 36 + name = "bsru_macro" 37 + version = "0.1.0" 38 + dependencies = [ 39 + "convert_case", 40 + "quote", 41 + "syn", 42 + ] 43 + 44 + [[package]] 45 + name = "convert_case" 46 + version = "0.6.0" 47 + source = "registry+https://github.com/rust-lang/crates.io-index" 48 + checksum = "ec182b0ca2f35d8fc196cf3404988fd8b8c739a4d270ff118a398feb0cbec1ca" 49 + dependencies = [ 50 + "unicode-segmentation", 51 + ] 52 + 53 + [[package]] 54 + name = "glam" 55 + version = "0.30.4" 56 + source = "registry+https://github.com/rust-lang/crates.io-index" 57 + checksum = "50a99dbe56b72736564cfa4b85bf9a33079f16ae8b74983ab06af3b1a3696b11" 58 + 59 + [[package]] 14 60 name = "itoa" 15 61 version = "1.0.15" 16 62 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 21 67 version = "2.7.5" 22 68 source = "registry+https://github.com/rust-lang/crates.io-index" 23 69 checksum = "32a282da65faaf38286cf3be983213fcf1d2e2a58700e808f83f4ea9a4804bc0" 70 + 71 + [[package]] 72 + name = "num-traits" 73 + version = "0.2.19" 74 + source = "registry+https://github.com/rust-lang/crates.io-index" 75 + checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" 76 + dependencies = [ 77 + "autocfg", 78 + ] 24 79 25 80 [[package]] 26 81 name = "proc-macro2" ··· 79 134 ] 80 135 81 136 [[package]] 137 + name = "serde_repr_plus" 138 + version = "0.1.19" 139 + source = "git+https://github.com/AlephCubed/serde-repr-plus#b4145f8557598f00f978219da100863f1f61f7a3" 140 + dependencies = [ 141 + "proc-macro2", 142 + "quote", 143 + "syn", 144 + ] 145 + 146 + [[package]] 147 + name = "simple-easing" 148 + version = "1.0.1" 149 + source = "registry+https://github.com/rust-lang/crates.io-index" 150 + checksum = "832ddd7df0d98d6fd93b973c330b7c8e0742d5cb8f1afc7dea89dba4d2531aa1" 151 + 152 + [[package]] 82 153 name = "syn" 83 154 version = "2.0.104" 84 155 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 94 165 version = "1.0.18" 95 166 source = "registry+https://github.com/rust-lang/crates.io-index" 96 167 checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512" 168 + 169 + [[package]] 170 + name = "unicode-segmentation" 171 + version = "1.12.0" 172 + source = "registry+https://github.com/rust-lang/crates.io-index" 173 + checksum = "f6ccf251212114b54433ec949fd6a7841275f9ada20dddd2f29e9ceea4501493"
+2
Cargo.toml
··· 6 6 [dependencies] 7 7 serde = { version = "1.0.219", features = ["derive"] } 8 8 serde_json = "1.0.140" 9 + simple-easing = "1.0.1" 10 + bsru-legacy = { path = "../BSRU-Legacy" }
+24
src/difficulty/lightshow.rs
··· 1 + use crate::loose_enum; 1 2 use serde::{Deserialize, Serialize}; 2 3 3 4 pub mod color; 5 + mod easing; 4 6 pub mod rotation; 5 7 6 8 #[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)] ··· 17 19 pub l: i32, 18 20 pub d: i32, 19 21 } 22 + 23 + loose_enum! { 24 + /// The distribution value does different things depending on the type. 25 + /// 26 + /// # [Beat Distribution](https://bsmg.wiki/mapping/map-format/lightshow.html#light-color-event-boxes-beat-distribution): 27 + /// ### Wave: 28 + /// The value represents the total time for all steps to complete. 29 + /// ### Step: 30 + /// The value represents the time until the next step is completed. 31 + /// 32 + /// # [Brightness](https://bsmg.wiki/mapping/map-format/lightshow.html#light-color-event-boxes-effect-distribution) and [Rotation Distribution](https://bsmg.wiki/mapping/map-format/lightshow.html#light-rotation-event-boxes-effect-distribution): 33 + /// ### Wave: 34 + /// The value represents the total difference between the first and last step. 35 + /// ### Step: 36 + /// The value represents the different between the current and next step. 37 + #[derive(Default)] 38 + DistributionType { 39 + #[default] 40 + Wave = 1, 41 + Step = 2, 42 + } 43 + }
+43 -12
src/difficulty/lightshow/color.rs
··· 1 - use crate::difficulty::lightshow::Filter; 1 + use crate::difficulty::lightshow::easing::Easing; 2 + use crate::difficulty::lightshow::{DistributionType, Filter}; 3 + use crate::loose_enum; 4 + use crate::macros::LooseBool; 2 5 use serde::{Deserialize, Serialize}; 3 6 4 7 #[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)] ··· 17 20 pub struct ColorEventGroup { 18 21 #[serde(rename = "f")] 19 22 pub filter: Filter, 20 - pub w: f32, 21 - pub d: i32, 22 - pub r: f32, 23 - pub t: i32, 23 + #[serde(rename = "d")] 24 + pub beat_dist_type: DistributionType, 25 + #[serde(rename = "w")] 26 + pub beat_dist_value: f32, 27 + #[serde(rename = "t")] 28 + pub bright_dist_type: DistributionType, 29 + #[serde(rename = "r")] 30 + pub bright_dist_value: f32, 24 31 #[serde(rename = "b")] 25 - pub beat: i32, 26 - pub i: i32, 32 + pub bright_dist_effect_first: LooseBool, 33 + #[serde(rename = "i")] 34 + pub bright_dist_easing: Easing, 27 35 #[serde(rename = "e")] 28 36 pub data: Vec<ColorEventData>, 29 37 } ··· 32 40 #[serde(rename_all = "camelCase")] 33 41 pub struct ColorEventData { 34 42 #[serde(rename = "b")] 35 - pub beat: f32, 36 - pub i: i32, 43 + pub beat_offset: f32, 44 + #[serde(rename = "i")] 45 + pub transition_type: ColorTransitionType, 37 46 #[serde(rename = "c")] 38 - pub color: i32, 39 - pub s: f32, 40 - pub f: i32, 47 + pub color: LightColor, 48 + #[serde(rename = "s")] 49 + pub brightness: f32, 50 + #[serde(rename = "f")] 51 + pub strobe_frequency: i32, 52 + } 53 + 54 + loose_enum! { 55 + #[derive(Default)] 56 + ColorTransitionType { 57 + #[default] 58 + Instant = 0, 59 + Transition = 1, 60 + Extend = 2, 61 + } 62 + } 63 + 64 + loose_enum! { 65 + #[derive(Default)] 66 + LightColor { 67 + #[default] 68 + Primary = 0, 69 + Secondary = 1, 70 + White = 2, 71 + } 41 72 }
+89
src/difficulty/lightshow/easing.rs
··· 1 + use crate::loose_enum; 2 + use simple_easing::*; 3 + 4 + loose_enum! { 5 + #[derive(Default)] 6 + Easing { 7 + Linear = 0, 8 + InQuad = 1, 9 + OutQuad = 2, 10 + InOutQuad = 3, 11 + InSine = 4, 12 + OutSine = 5, 13 + InOutSine = 6, 14 + InCubic = 7, 15 + OutCubic = 8, 16 + InOutCubic = 9, 17 + InQuart = 10, 18 + OutQuart = 11, 19 + InOutQuart = 12, 20 + InQuint = 13, 21 + OutQuint = 14, 22 + InOutQuint = 15, 23 + InExpo = 16, 24 + OutExpo = 17, 25 + InOutExpo = 18, 26 + InCirc = 19, 27 + OutCirc = 20, 28 + InOutCirc = 21, 29 + InBack = 22, 30 + OutBack = 23, 31 + InOutBack = 24, 32 + InElastic = 25, 33 + OutElastic = 26, 34 + InOutElastic = 27, 35 + InBounce = 28, 36 + OutBounce = 29, 37 + InOutBounce = 30, 38 + 39 + #[default] 40 + None = -1, 41 + 42 + BeatSaberInOutBack = 100, 43 + BeatSaberInOutElastic = 101, 44 + BeatSaberInOutBounce = 102, 45 + } 46 + } 47 + 48 + impl Easing { 49 + pub fn ease(&self, num: f32) -> f32 { 50 + match self { 51 + Easing::Linear => linear(num), 52 + Easing::InQuad => quad_in(num), 53 + Easing::OutQuad => quad_out(num), 54 + Easing::InOutQuad => quad_in_out(num), 55 + Easing::InSine => sine_in(num), 56 + Easing::OutSine => sine_out(num), 57 + Easing::InOutSine => sine_in_out(num), 58 + Easing::InCubic => cubic_in(num), 59 + Easing::OutCubic => cubic_out(num), 60 + Easing::InOutCubic => cubic_in_out(num), 61 + Easing::InQuart => quart_in(num), 62 + Easing::OutQuart => quart_out(num), 63 + Easing::InOutQuart => quart_in_out(num), 64 + Easing::InQuint => quint_in(num), 65 + Easing::OutQuint => quint_out(num), 66 + Easing::InOutQuint => quint_in_out(num), 67 + Easing::InExpo => expo_in(num), 68 + Easing::OutExpo => expo_out(num), 69 + Easing::InOutExpo => expo_in_out(num), 70 + Easing::InCirc => circ_in(num), 71 + Easing::OutCirc => circ_out(num), 72 + Easing::InOutCirc => circ_in_out(num), 73 + Easing::InBack => back_in(num), 74 + Easing::OutBack => back_out(num), 75 + Easing::InOutBack => back_in_out(num), 76 + Easing::InElastic => elastic_in(num), 77 + Easing::OutElastic => elastic_out(num), 78 + Easing::InOutElastic => elastic_in_out(num), 79 + Easing::InBounce => bounce_in(num), 80 + Easing::OutBounce => bounce_out(num), 81 + Easing::InOutBounce => bounce_in_out(num), 82 + Easing::None => 0.0, 83 + Easing::BeatSaberInOutBack => back_in_out(num), 84 + Easing::BeatSaberInOutElastic => elastic_in_out(num), 85 + Easing::BeatSaberInOutBounce => bounce_in_out(num), 86 + Easing::Unknown(_) => 0.0, 87 + } 88 + } 89 + }
+68 -15
src/difficulty/lightshow/rotation.rs
··· 1 - use crate::difficulty::lightshow::Filter; 1 + use crate::difficulty::lightshow::easing::Easing; 2 + use crate::difficulty::lightshow::{DistributionType, Filter}; 3 + use crate::loose_enum; 4 + use crate::macros::LooseBool; 2 5 use serde::{Deserialize, Serialize}; 3 6 4 7 #[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)] ··· 15 18 #[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)] 16 19 #[serde(rename_all = "camelCase")] 17 20 pub struct RotationEventGroup { 18 - pub f: Filter, 19 - pub w: f32, 20 - pub d: i32, 21 - pub s: i32, 22 - pub t: i32, 21 + #[serde(rename = "f")] 22 + pub filter: Filter, 23 + #[serde(rename = "d")] 24 + pub beat_dist_type: DistributionType, 25 + #[serde(rename = "w")] 26 + pub beat_dist_value: f32, 27 + #[serde(rename = "t")] 28 + pub rotation_dist_type: DistributionType, 29 + #[serde(rename = "s")] 30 + pub rotation_dist_value: i32, 23 31 #[serde(rename = "b")] 24 - pub beat: i32, 25 - pub a: i32, 26 - pub r: i32, 27 - pub i: i32, 32 + pub rotation_dist_effect_first: LooseBool, 33 + #[serde(rename = "i")] 34 + pub rotation_dist_easing: Easing, 35 + #[serde(rename = "a")] 36 + pub axis: i32, 37 + #[serde(rename = "r")] 38 + pub invert_axis: LooseBool, 28 39 #[serde(rename = "l")] 29 40 pub data: Vec<RotationEventData>, 30 41 } 31 42 43 + loose_enum! { 44 + #[derive(Default)] 45 + Axis { 46 + #[default] 47 + X = 0, 48 + Y = 1, 49 + Z = 2, 50 + } 51 + } 52 + 32 53 #[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)] 33 54 #[serde(rename_all = "camelCase")] 34 55 pub struct RotationEventData { 35 56 #[serde(rename = "b")] 36 57 pub beat: f32, 37 - pub p: i32, 38 - pub e: i32, 39 - pub l: i32, 40 - pub r: i32, 41 - pub o: i32, 58 + #[serde(rename = "p")] 59 + pub transition_type: RotationTransitionType, 60 + #[serde(rename = "e")] 61 + pub easing: Easing, 62 + #[serde(rename = "l")] 63 + pub degrees: i32, 64 + #[serde(rename = "r")] 65 + pub direction: RotationDirection, 66 + #[serde(rename = "o")] 67 + pub loops: i32, 68 + } 69 + 70 + loose_enum! { 71 + /// Controls how the angle is changed from the previous event. 72 + /// - Transition: The angle will slowly move from the previous events angle, using the easing. 73 + /// - Extend: The events rotation will be ignored, 74 + /// and the values from the previous event will be used instead. 75 + /// 76 + /// More info [here](https://bsmg.wiki/mapping/map-format/lightshow.html#light-rotation-events-type). 77 + #[derive(Default)] 78 + RotationTransitionType { 79 + #[default] 80 + Transition = 0, 81 + Extend = 1, 82 + } 83 + } 84 + 85 + loose_enum! { 86 + /// Determines the direction that the rotation event will rotate. 87 + /// Automatic will choose the shortest distance. 88 + #[derive(Default)] 89 + RotationDirection { 90 + #[default] 91 + Automatic = 0, 92 + Clockwise = 1, 93 + CounterClockwise = 2, 94 + } 42 95 }
+3 -3
src/difficulty/playfield.rs
··· 1 1 use crate::loose_enum; 2 - use serde::{Deserialize, Deserializer, Serialize}; 2 + use serde::{Deserialize, Serialize}; 3 3 4 4 #[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)] 5 5 #[serde(rename_all = "camelCase")] ··· 20 20 21 21 loose_enum! { 22 22 #[derive(Default)] 23 - NoteColor, { 23 + NoteColor { 24 24 #[default] 25 25 Left = 0, 26 26 Right = 1, ··· 29 29 30 30 loose_enum! { 31 31 #[derive(Default)] 32 - CutDirection, { 32 + CutDirection { 33 33 #[default] 34 34 Up = 0, 35 35 Down = 1,
+13 -4
src/macros.rs
··· 2 2 macro_rules! loose_enum { 3 3 ( 4 4 $(#[$outer:meta])* 5 - $name:ident, 5 + $name:ident 6 6 { 7 7 $( 8 8 $(#[$meta:meta])* ··· 20 20 Unknown(i32), 21 21 } 22 22 23 - impl<'de> Deserialize<'de> for $name { 23 + impl<'de> serde::Deserialize<'de> for $name { 24 24 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error> 25 25 where 26 - D: Deserializer<'de>, 26 + D: serde::Deserializer<'de>, 27 27 { 28 28 let val = i32::deserialize(deserializer)?; 29 29 Ok(match val { ··· 33 33 } 34 34 } 35 35 36 - impl Serialize for $name { 36 + impl serde::Serialize for $name { 37 37 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> 38 38 where 39 39 S: serde::Serializer, ··· 48 48 } 49 49 }; 50 50 } 51 + 52 + loose_enum! { 53 + #[derive(Default)] 54 + LooseBool { 55 + #[default] 56 + False = 0, 57 + True = 1, 58 + } 59 + }