mirrored slider parsing from osu!lazer
This commit is contained in:
@@ -340,7 +340,7 @@ pub fn strains(map: &Beatmap, mods: impl Mods) -> Strains {
|
||||
|
||||
#[test]
|
||||
fn custom_osu() {
|
||||
let file = std::fs::File::open("E:Games/osu!/beatmaps/2753127_.osu").unwrap();
|
||||
let file = std::fs::File::open("E:Games/osu!/beatmaps/2753127.osu").unwrap();
|
||||
// let file = std::fs::File::open("E:Games/osu!/beatmaps/2571051.osu").unwrap();
|
||||
let map = Beatmap::parse(file).unwrap();
|
||||
|
||||
@@ -350,6 +350,7 @@ fn custom_osu() {
|
||||
let iters = 500;
|
||||
let accum = start.elapsed();
|
||||
|
||||
// * Tiny benchmark
|
||||
// let mut accum = accum;
|
||||
|
||||
// for _ in 0..iters {
|
||||
|
||||
@@ -8,6 +8,7 @@ use crate::{
|
||||
};
|
||||
|
||||
const LEGACY_LAST_TICK_OFFSET: f32 = 36.0;
|
||||
const BASE_SCORING_DISTANCE: f32 = 100.0;
|
||||
|
||||
pub(crate) struct OsuObject {
|
||||
pub(crate) time: f32,
|
||||
@@ -47,7 +48,6 @@ impl OsuObject {
|
||||
pixel_len,
|
||||
repeats,
|
||||
curve_points,
|
||||
path_type,
|
||||
} => {
|
||||
// Key values which are computed here
|
||||
let mut lazy_end_pos = h.pos;
|
||||
@@ -56,21 +56,26 @@ impl OsuObject {
|
||||
// Responsible for timing point values
|
||||
slider_state.update(h.start_time);
|
||||
|
||||
let span_count = (*repeats + 1) as f32;
|
||||
|
||||
let approx_follow_circle_radius = radius * 3.0;
|
||||
let mut tick_distance = 100.0 * map.sv / map.tick_rate;
|
||||
let mut tick_dist = 100.0 * map.slider_mult / map.tick_rate;
|
||||
|
||||
if map.version >= 8 {
|
||||
tick_distance /=
|
||||
(100.0 / slider_state.speed_mult).max(10.0).min(1000.0) / 100.0;
|
||||
tick_dist /=
|
||||
(100.0 / slider_state.slider_velocity).max(10.0).min(1000.0) / 100.0;
|
||||
}
|
||||
|
||||
let duration = *repeats as f32 * slider_state.beat_len * pixel_len
|
||||
/ (map.sv * slider_state.speed_mult)
|
||||
/ 100.0;
|
||||
let span_duration = duration / *repeats as f32;
|
||||
|
||||
// Build the curve w.r.t. the curve points
|
||||
let curve = Curve::new(curve_points, *path_type, *pixel_len);
|
||||
let curve = Curve::new(curve_points, *pixel_len);
|
||||
|
||||
let velocity =
|
||||
(BASE_SCORING_DISTANCE * map.slider_mult * slider_state.slider_velocity)
|
||||
/ slider_state.beat_len;
|
||||
|
||||
let end_time = h.start_time + span_count * curve.dist() / velocity;
|
||||
let duration = end_time - h.start_time;
|
||||
let span_duration = duration / span_count;
|
||||
|
||||
// Called on each slider object except for the head.
|
||||
// Increases combo and adjusts `end_pos` and `travel_dist`
|
||||
@@ -86,25 +91,23 @@ impl OsuObject {
|
||||
progress %= 1.0;
|
||||
}
|
||||
|
||||
let curr_dist = pixel_len * progress;
|
||||
let curr_pos = curve.point_at_distance(curr_dist);
|
||||
|
||||
let diff = curr_pos - lazy_end_pos;
|
||||
let curr_pos = curve.position_at(progress);
|
||||
let diff = h.pos + curr_pos - lazy_end_pos;
|
||||
let mut dist = diff.length();
|
||||
|
||||
if dist > approx_follow_circle_radius {
|
||||
// * The cursor would be outside the follow circle, we need to move it
|
||||
dist -= approx_follow_circle_radius;
|
||||
lazy_end_pos += diff.normalize() * dist;
|
||||
|
||||
travel_dist += dist;
|
||||
}
|
||||
};
|
||||
|
||||
let mut current_distance = tick_distance;
|
||||
let time_add = duration * (tick_distance / (pixel_len * *repeats as f32));
|
||||
let mut current_distance = tick_dist;
|
||||
let time_add = duration * (tick_dist / (pixel_len * span_count));
|
||||
|
||||
let target = pixel_len - tick_distance / 8.0;
|
||||
ticks.reserve((target / tick_distance) as usize);
|
||||
let target = pixel_len - tick_dist / 8.0;
|
||||
ticks.reserve((target / tick_dist) as usize);
|
||||
|
||||
// Tick of the first span
|
||||
if current_distance < target {
|
||||
@@ -112,7 +115,7 @@ impl OsuObject {
|
||||
let time = h.start_time + time_add * tick_idx as f32;
|
||||
compute_vertex(time);
|
||||
ticks.push(time);
|
||||
current_distance += tick_distance;
|
||||
current_distance += tick_dist;
|
||||
|
||||
if current_distance >= target {
|
||||
break;
|
||||
@@ -146,7 +149,7 @@ impl OsuObject {
|
||||
|
||||
ticks.clear();
|
||||
|
||||
let end_pos = curve.point_at_distance(*pixel_len);
|
||||
let end_pos = curve.position_at(1.0); // TODO: what if reversing odd amount?
|
||||
travel_dist *= scaling_factor;
|
||||
|
||||
Self {
|
||||
|
||||
@@ -4,7 +4,7 @@ pub(crate) struct SliderState<'p> {
|
||||
control_points: ControlPointIter<'p>,
|
||||
next: Option<ControlPoint>,
|
||||
pub(crate) beat_len: f32,
|
||||
pub(crate) speed_mult: f32,
|
||||
pub(crate) slider_velocity: f32,
|
||||
}
|
||||
|
||||
impl<'p> SliderState<'p> {
|
||||
@@ -12,9 +12,12 @@ impl<'p> SliderState<'p> {
|
||||
pub(crate) fn new(map: &'p Beatmap) -> Self {
|
||||
let mut control_points = ControlPointIter::new(map);
|
||||
|
||||
let (beat_len, speed_mult) = match control_points.next() {
|
||||
let (beat_len, slider_velocity) = match control_points.next() {
|
||||
Some(ControlPoint::Timing { beat_len, .. }) => (beat_len, 1.0),
|
||||
Some(ControlPoint::Difficulty { speed_mult, .. }) => (1000.0, speed_mult),
|
||||
Some(ControlPoint::Difficulty {
|
||||
slider_velocity: speed_mult,
|
||||
..
|
||||
}) => (1000.0, speed_mult),
|
||||
None => (1000.0, 1.0),
|
||||
};
|
||||
|
||||
@@ -22,7 +25,7 @@ impl<'p> SliderState<'p> {
|
||||
next: control_points.next(),
|
||||
control_points,
|
||||
beat_len,
|
||||
speed_mult,
|
||||
slider_velocity,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -32,9 +35,12 @@ impl<'p> SliderState<'p> {
|
||||
match next {
|
||||
ControlPoint::Timing { beat_len, .. } => {
|
||||
self.beat_len = *beat_len;
|
||||
self.speed_mult = 1.0;
|
||||
self.slider_velocity = 1.0;
|
||||
}
|
||||
ControlPoint::Difficulty { speed_mult, .. } => self.speed_mult = *speed_mult,
|
||||
ControlPoint::Difficulty {
|
||||
slider_velocity: speed_mult,
|
||||
..
|
||||
} => self.slider_velocity = *speed_mult,
|
||||
}
|
||||
|
||||
self.next = self.control_points.next();
|
||||
@@ -88,10 +94,10 @@ mod test {
|
||||
|
||||
state.update(3.0);
|
||||
assert_eq!(state.beat_len, 20.0);
|
||||
assert_eq!(state.speed_mult, 1.0);
|
||||
assert_eq!(state.slider_velocity, 1.0);
|
||||
|
||||
state.update(5.0);
|
||||
assert_eq!(state.beat_len, 30.0);
|
||||
assert_eq!(state.speed_mult, 45.0);
|
||||
assert_eq!(state.slider_velocity, 45.0);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user