feat: support horizontal flipping
This commit is contained in:
+45
-1
@@ -179,7 +179,7 @@ impl_has_mod! {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl GameMods {
|
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 {
|
match self.inner {
|
||||||
GameModsInner::Lazer(ref mods) => mods
|
GameModsInner::Lazer(ref mods) => mods
|
||||||
.iter()
|
.iter()
|
||||||
@@ -196,6 +196,42 @@ impl GameMods {
|
|||||||
GameModsInner::Legacy(_) => !lazer,
|
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 {
|
impl Default for GameMods {
|
||||||
@@ -244,3 +280,11 @@ impl From<u32> for GameMods {
|
|||||||
GameModsLegacy::from_bits(bits).into()
|
GameModsLegacy::from_bits(bits).into()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
|
||||||
|
pub enum Reflection {
|
||||||
|
None,
|
||||||
|
Vertical,
|
||||||
|
Horizontal,
|
||||||
|
Both,
|
||||||
|
}
|
||||||
|
|||||||
+12
-6
@@ -3,6 +3,7 @@ use rosu_map::section::{general::GameMode, hit_objects::CurveBuffers};
|
|||||||
use crate::model::{
|
use crate::model::{
|
||||||
beatmap::{Beatmap, Converted},
|
beatmap::{Beatmap, Converted},
|
||||||
mode::ConvertStatus,
|
mode::ConvertStatus,
|
||||||
|
mods::Reflection,
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::{
|
use super::{
|
||||||
@@ -30,7 +31,7 @@ pub fn try_convert(map: &mut Beatmap) -> ConvertStatus {
|
|||||||
pub fn convert_objects(
|
pub fn convert_objects(
|
||||||
converted: &OsuBeatmap<'_>,
|
converted: &OsuBeatmap<'_>,
|
||||||
scaling_factor: &ScalingFactor,
|
scaling_factor: &ScalingFactor,
|
||||||
hr: bool,
|
reflection: Reflection,
|
||||||
time_preempt: f64,
|
time_preempt: f64,
|
||||||
mut take: usize,
|
mut take: usize,
|
||||||
attrs: &mut OsuDifficultyAttributes,
|
attrs: &mut OsuDifficultyAttributes,
|
||||||
@@ -63,12 +64,17 @@ pub fn convert_objects(
|
|||||||
})
|
})
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
if hr {
|
match reflection {
|
||||||
osu_objects
|
Reflection::None => osu_objects.iter_mut().for_each(OsuObject::finalize_nested),
|
||||||
|
Reflection::Vertical => osu_objects
|
||||||
.iter_mut()
|
.iter_mut()
|
||||||
.for_each(OsuObject::reflect_vertically);
|
.for_each(OsuObject::reflect_vertically),
|
||||||
} else {
|
Reflection::Horizontal => osu_objects
|
||||||
osu_objects.iter_mut().for_each(OsuObject::finalize_nested);
|
.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);
|
let stack_threshold = time_preempt * f64::from(converted.stack_leniency);
|
||||||
|
|||||||
@@ -84,7 +84,7 @@ impl OsuGradualDifficulty {
|
|||||||
let osu_objects = convert_objects(
|
let osu_objects = convert_objects(
|
||||||
converted,
|
converted,
|
||||||
&scaling_factor,
|
&scaling_factor,
|
||||||
mods.hr(),
|
mods.reflection(),
|
||||||
time_preempt,
|
time_preempt,
|
||||||
converted.hit_objects.len(),
|
converted.hit_objects.len(),
|
||||||
&mut attrs,
|
&mut attrs,
|
||||||
|
|||||||
@@ -114,7 +114,7 @@ impl DifficultyValues {
|
|||||||
let mut osu_objects = convert_objects(
|
let mut osu_objects = convert_objects(
|
||||||
converted,
|
converted,
|
||||||
&scaling_factor,
|
&scaling_factor,
|
||||||
mods.hr(),
|
mods.reflection(),
|
||||||
time_preempt,
|
time_preempt,
|
||||||
take,
|
take,
|
||||||
&mut attrs,
|
&mut attrs,
|
||||||
|
|||||||
@@ -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) {
|
pub fn finalize_nested(&mut self) {
|
||||||
if let OsuObjectKind::Slider(ref mut slider) = self.kind {
|
if let OsuObjectKind::Slider(ref mut slider) = self.kind {
|
||||||
for nested in slider.nested_objects.iter_mut() {
|
for nested in slider.nested_objects.iter_mut() {
|
||||||
|
|||||||
Reference in New Issue
Block a user