Skip to content

Commit

Permalink
feat: support horizontal flipping
Browse files Browse the repository at this point in the history
  • Loading branch information
MaxOhn committed Nov 11, 2024
1 parent 9edad8a commit 757b57b
Show file tree
Hide file tree
Showing 5 changed files with 99 additions and 9 deletions.
46 changes: 45 additions & 1 deletion src/model/mods.rs
Original file line number Diff line number Diff line change
Expand Up @@ -179,7 +179,7 @@ impl_has_mod! {
}

impl GameMods {
pub fn no_slider_head_acc(&self, lazer: bool) -> bool {
pub(crate) fn no_slider_head_acc(&self, lazer: bool) -> bool {
match self.inner {
GameModsInner::Lazer(ref mods) => mods
.iter()
Expand All @@ -196,6 +196,42 @@ impl GameMods {
GameModsInner::Legacy(_) => !lazer,
}
}

pub(crate) fn reflection(&self) -> Reflection {
match self.inner {
GameModsInner::Lazer(ref mods) => {
if mods.contains_intermode(GameModIntermode::HardRock) {
return Reflection::Vertical;
}

mods.iter()
.find_map(|m| match m {
GameMod::MirrorOsu(mirror) => Some(mirror),
_ => None,
})
.map_or(Reflection::None, |mr| match mr.reflection.as_deref() {
Some("Horizontal") | None => Reflection::Horizontal,
Some("Vertical") => Reflection::Vertical,
Some("Both") => Reflection::Both,
Some(_) => Reflection::None,
})
}
GameModsInner::Intermode(ref mods) => {
if mods.contains(GameModIntermode::HardRock) {
Reflection::Vertical
} else {
Reflection::None
}
}
GameModsInner::Legacy(mods) => {
if mods.contains(GameModsLegacy::HardRock) {
Reflection::Vertical
} else {
Reflection::None
}
}
}
}
}

impl Default for GameMods {
Expand Down Expand Up @@ -244,3 +280,11 @@ impl From<u32> for GameMods {
GameModsLegacy::from_bits(bits).into()
}
}

#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub enum Reflection {
None,
Vertical,
Horizontal,
Both,
}
18 changes: 12 additions & 6 deletions src/osu/convert.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ use rosu_map::section::{general::GameMode, hit_objects::CurveBuffers};
use crate::model::{
beatmap::{Beatmap, Converted},
mode::ConvertStatus,
mods::Reflection,
};

use super::{
Expand Down Expand Up @@ -30,7 +31,7 @@ pub fn try_convert(map: &mut Beatmap) -> ConvertStatus {
pub fn convert_objects(
converted: &OsuBeatmap<'_>,
scaling_factor: &ScalingFactor,
hr: bool,
reflection: Reflection,
time_preempt: f64,
mut take: usize,
attrs: &mut OsuDifficultyAttributes,
Expand Down Expand Up @@ -63,12 +64,17 @@ pub fn convert_objects(
})
.collect();

if hr {
osu_objects
match reflection {
Reflection::None => osu_objects.iter_mut().for_each(OsuObject::finalize_nested),
Reflection::Vertical => osu_objects
.iter_mut()
.for_each(OsuObject::reflect_vertically);
} else {
osu_objects.iter_mut().for_each(OsuObject::finalize_nested);
.for_each(OsuObject::reflect_vertically),
Reflection::Horizontal => osu_objects
.iter_mut()
.for_each(OsuObject::reflect_horizontally),
Reflection::Both => osu_objects
.iter_mut()
.for_each(OsuObject::reflect_both_axes),
}

let stack_threshold = time_preempt * f64::from(converted.stack_leniency);
Expand Down
2 changes: 1 addition & 1 deletion src/osu/difficulty/gradual.rs
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ impl OsuGradualDifficulty {
let osu_objects = convert_objects(
converted,
&scaling_factor,
mods.hr(),
mods.reflection(),
time_preempt,
converted.hit_objects.len(),
&mut attrs,
Expand Down
2 changes: 1 addition & 1 deletion src/osu/difficulty/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ impl DifficultyValues {
let mut osu_objects = convert_objects(
converted,
&scaling_factor,
mods.hr(),
mods.reflection(),
time_preempt,
take,
&mut attrs,
Expand Down
40 changes: 40 additions & 0 deletions src/osu/object.rs
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,46 @@ impl OsuObject {
}
}

pub fn reflect_horizontally(&mut self) {
fn reflect_x(x: &mut f32) {
*x = PLAYFIELD_BASE_SIZE.x - *x;
}

reflect_x(&mut self.pos.x);

if let OsuObjectKind::Slider(ref mut slider) = self.kind {
// Requires `stack_offset` so we can't add `h.pos` just yet
slider.lazy_end_pos.x = -slider.lazy_end_pos.x;

for nested in slider.nested_objects.iter_mut() {
let mut nested_pos = self.pos; // already reflected at this point
nested_pos += Pos::new(-nested.pos.x, nested.pos.y);
nested.pos = nested_pos;
}
}
}

pub fn reflect_both_axes(&mut self) {
fn reflect(pos: &mut Pos) {
pos.x = PLAYFIELD_BASE_SIZE.x - pos.x;
pos.y = PLAYFIELD_BASE_SIZE.y - pos.y;
}

reflect(&mut self.pos);

if let OsuObjectKind::Slider(ref mut slider) = self.kind {
// Requires `stack_offset` so we can't add `h.pos` just yet
slider.lazy_end_pos.x = -slider.lazy_end_pos.x;
slider.lazy_end_pos.y = -slider.lazy_end_pos.y;

for nested in slider.nested_objects.iter_mut() {
let mut nested_pos = self.pos; // already reflected at this point
nested_pos += Pos::new(-nested.pos.x, -nested.pos.y);
nested.pos = nested_pos;
}
}
}

pub fn finalize_nested(&mut self) {
if let OsuObjectKind::Slider(ref mut slider) = self.kind {
for nested in slider.nested_objects.iter_mut() {
Expand Down

0 comments on commit 757b57b

Please sign in to comment.