mirror of
https://github.com/ppy/osu.git
synced 2024-12-13 05:22:54 +08:00
Rewrite implementation
This commit is contained in:
parent
9045ec24ab
commit
63406b6feb
@ -93,25 +93,25 @@ namespace osu.Game.Tests.Visual.SongSelect
|
|||||||
createSongSelect();
|
createSongSelect();
|
||||||
changeMods();
|
changeMods();
|
||||||
|
|
||||||
AddStep("decrease speed", () => songSelect?.ChangeSpeed(-0.05));
|
decreaseModSpeed();
|
||||||
AddAssert("half time activated at 0.95x", () => songSelect!.Mods.Value.OfType<ModHalfTime>().Single().SpeedChange.Value, () => Is.EqualTo(0.95).Within(0.005));
|
AddAssert("half time activated at 0.95x", () => songSelect!.Mods.Value.OfType<ModHalfTime>().Single().SpeedChange.Value, () => Is.EqualTo(0.95).Within(0.005));
|
||||||
|
|
||||||
AddStep("decrease speed", () => songSelect?.ChangeSpeed(-0.05));
|
decreaseModSpeed();
|
||||||
AddAssert("half time speed changed to 0.9x", () => songSelect!.Mods.Value.OfType<ModHalfTime>().Single().SpeedChange.Value, () => Is.EqualTo(0.9).Within(0.005));
|
AddAssert("half time speed changed to 0.9x", () => songSelect!.Mods.Value.OfType<ModHalfTime>().Single().SpeedChange.Value, () => Is.EqualTo(0.9).Within(0.005));
|
||||||
|
|
||||||
AddStep("increase speed", () => songSelect?.ChangeSpeed(0.05));
|
increaseModSpeed();
|
||||||
AddAssert("half time speed changed to 0.95x", () => songSelect!.Mods.Value.OfType<ModHalfTime>().Single().SpeedChange.Value, () => Is.EqualTo(0.95).Within(0.005));
|
AddAssert("half time speed changed to 0.95x", () => songSelect!.Mods.Value.OfType<ModHalfTime>().Single().SpeedChange.Value, () => Is.EqualTo(0.95).Within(0.005));
|
||||||
|
|
||||||
AddStep("increase speed", () => songSelect?.ChangeSpeed(0.05));
|
increaseModSpeed();
|
||||||
AddAssert("no mods selected", () => songSelect!.Mods.Value.Count == 0);
|
AddAssert("no mods selected", () => songSelect!.Mods.Value.Count == 0);
|
||||||
|
|
||||||
AddStep("increase speed", () => songSelect?.ChangeSpeed(0.05));
|
increaseModSpeed();
|
||||||
AddAssert("double time activated at 1.05x", () => songSelect!.Mods.Value.OfType<ModDoubleTime>().Single().SpeedChange.Value, () => Is.EqualTo(1.05).Within(0.005));
|
AddAssert("double time activated at 1.05x", () => songSelect!.Mods.Value.OfType<ModDoubleTime>().Single().SpeedChange.Value, () => Is.EqualTo(1.05).Within(0.005));
|
||||||
|
|
||||||
AddStep("increase speed", () => songSelect?.ChangeSpeed(0.05));
|
increaseModSpeed();
|
||||||
AddAssert("double time speed changed to 1.1x", () => songSelect!.Mods.Value.OfType<ModDoubleTime>().Single().SpeedChange.Value, () => Is.EqualTo(1.1).Within(0.005));
|
AddAssert("double time speed changed to 1.1x", () => songSelect!.Mods.Value.OfType<ModDoubleTime>().Single().SpeedChange.Value, () => Is.EqualTo(1.1).Within(0.005));
|
||||||
|
|
||||||
AddStep("decrease speed", () => songSelect?.ChangeSpeed(-0.05));
|
decreaseModSpeed();
|
||||||
AddAssert("double time speed changed to 1.05x", () => songSelect!.Mods.Value.OfType<ModDoubleTime>().Single().SpeedChange.Value, () => Is.EqualTo(1.05).Within(0.005));
|
AddAssert("double time speed changed to 1.05x", () => songSelect!.Mods.Value.OfType<ModDoubleTime>().Single().SpeedChange.Value, () => Is.EqualTo(1.05).Within(0.005));
|
||||||
|
|
||||||
OsuModNightcore nc = new OsuModNightcore
|
OsuModNightcore nc = new OsuModNightcore
|
||||||
@ -119,22 +119,23 @@ namespace osu.Game.Tests.Visual.SongSelect
|
|||||||
SpeedChange = { Value = 1.05 }
|
SpeedChange = { Value = 1.05 }
|
||||||
};
|
};
|
||||||
changeMods(nc);
|
changeMods(nc);
|
||||||
AddStep("increase speed", () => songSelect?.ChangeSpeed(0.05));
|
|
||||||
|
increaseModSpeed();
|
||||||
AddAssert("nightcore speed changed to 1.1x", () => songSelect!.Mods.Value.OfType<ModNightcore>().Single().SpeedChange.Value, () => Is.EqualTo(1.1).Within(0.005));
|
AddAssert("nightcore speed changed to 1.1x", () => songSelect!.Mods.Value.OfType<ModNightcore>().Single().SpeedChange.Value, () => Is.EqualTo(1.1).Within(0.005));
|
||||||
|
|
||||||
AddStep("decrease speed", () => songSelect?.ChangeSpeed(-0.05));
|
decreaseModSpeed();
|
||||||
AddAssert("nightcore speed changed to 1.05x", () => songSelect!.Mods.Value.OfType<ModNightcore>().Single().SpeedChange.Value, () => Is.EqualTo(1.05).Within(0.005));
|
AddAssert("nightcore speed changed to 1.05x", () => songSelect!.Mods.Value.OfType<ModNightcore>().Single().SpeedChange.Value, () => Is.EqualTo(1.05).Within(0.005));
|
||||||
|
|
||||||
AddStep("decrease speed", () => songSelect?.ChangeSpeed(-0.05));
|
decreaseModSpeed();
|
||||||
AddAssert("no mods selected", () => songSelect!.Mods.Value.Count == 0);
|
AddAssert("no mods selected", () => songSelect!.Mods.Value.Count == 0);
|
||||||
|
|
||||||
AddStep("decrease speed", () => songSelect?.ChangeSpeed(-0.05));
|
decreaseModSpeed();
|
||||||
AddAssert("daycore activated at 0.95x", () => songSelect!.Mods.Value.OfType<ModDaycore>().Single().SpeedChange.Value, () => Is.EqualTo(0.95).Within(0.005));
|
AddAssert("daycore activated at 0.95x", () => songSelect!.Mods.Value.OfType<ModDaycore>().Single().SpeedChange.Value, () => Is.EqualTo(0.95).Within(0.005));
|
||||||
|
|
||||||
AddStep("decrease speed", () => songSelect?.ChangeSpeed(-0.05));
|
decreaseModSpeed();
|
||||||
AddAssert("daycore activated at 0.95x", () => songSelect!.Mods.Value.OfType<ModDaycore>().Single().SpeedChange.Value, () => Is.EqualTo(0.9).Within(0.005));
|
AddAssert("daycore activated at 0.95x", () => songSelect!.Mods.Value.OfType<ModDaycore>().Single().SpeedChange.Value, () => Is.EqualTo(0.9).Within(0.005));
|
||||||
|
|
||||||
AddStep("increase speed", () => songSelect?.ChangeSpeed(0.05));
|
increaseModSpeed();
|
||||||
AddAssert("daycore activated at 0.95x", () => songSelect!.Mods.Value.OfType<ModDaycore>().Single().SpeedChange.Value, () => Is.EqualTo(0.95).Within(0.005));
|
AddAssert("daycore activated at 0.95x", () => songSelect!.Mods.Value.OfType<ModDaycore>().Single().SpeedChange.Value, () => Is.EqualTo(0.95).Within(0.005));
|
||||||
|
|
||||||
OsuModDoubleTime dt = new OsuModDoubleTime
|
OsuModDoubleTime dt = new OsuModDoubleTime
|
||||||
@ -143,7 +144,8 @@ namespace osu.Game.Tests.Visual.SongSelect
|
|||||||
AdjustPitch = { Value = true },
|
AdjustPitch = { Value = true },
|
||||||
};
|
};
|
||||||
changeMods(dt);
|
changeMods(dt);
|
||||||
AddStep("decrease speed", () => songSelect?.ChangeSpeed(-0.05));
|
|
||||||
|
decreaseModSpeed();
|
||||||
AddAssert("half time activated at 0.97x", () => songSelect!.Mods.Value.OfType<ModHalfTime>().Single().SpeedChange.Value, () => Is.EqualTo(0.97).Within(0.005));
|
AddAssert("half time activated at 0.97x", () => songSelect!.Mods.Value.OfType<ModHalfTime>().Single().SpeedChange.Value, () => Is.EqualTo(0.97).Within(0.005));
|
||||||
AddAssert("adjust pitch preserved", () => songSelect!.Mods.Value.OfType<ModHalfTime>().Single().AdjustPitch.Value, () => Is.True);
|
AddAssert("adjust pitch preserved", () => songSelect!.Mods.Value.OfType<ModHalfTime>().Single().AdjustPitch.Value, () => Is.True);
|
||||||
|
|
||||||
@ -154,19 +156,34 @@ namespace osu.Game.Tests.Visual.SongSelect
|
|||||||
};
|
};
|
||||||
Mod[] modlist = { ht, new OsuModHardRock(), new OsuModHidden() };
|
Mod[] modlist = { ht, new OsuModHardRock(), new OsuModHidden() };
|
||||||
changeMods(modlist);
|
changeMods(modlist);
|
||||||
AddStep("decrease speed", () => songSelect?.ChangeSpeed(0.05));
|
|
||||||
|
increaseModSpeed();
|
||||||
AddAssert("double time activated at 1.02x", () => songSelect!.Mods.Value.OfType<ModDoubleTime>().Single().SpeedChange.Value, () => Is.EqualTo(1.02).Within(0.005));
|
AddAssert("double time activated at 1.02x", () => songSelect!.Mods.Value.OfType<ModDoubleTime>().Single().SpeedChange.Value, () => Is.EqualTo(1.02).Within(0.005));
|
||||||
AddAssert("double time activated at 1.02x", () => songSelect!.Mods.Value.OfType<ModDoubleTime>().Single().AdjustPitch.Value, () => Is.True);
|
AddAssert("double time activated at 1.02x", () => songSelect!.Mods.Value.OfType<ModDoubleTime>().Single().AdjustPitch.Value, () => Is.True);
|
||||||
AddAssert("HD still enabled", () => songSelect!.Mods.Value.OfType<ModHidden>().SingleOrDefault(), () => Is.Not.Null);
|
AddAssert("HD still enabled", () => songSelect!.Mods.Value.OfType<ModHidden>().SingleOrDefault(), () => Is.Not.Null);
|
||||||
AddAssert("HR still enabled", () => songSelect!.Mods.Value.OfType<ModHardRock>().SingleOrDefault(), () => Is.Not.Null);
|
AddAssert("HR still enabled", () => songSelect!.Mods.Value.OfType<ModHardRock>().SingleOrDefault(), () => Is.Not.Null);
|
||||||
|
|
||||||
changeMods(new ModWindUp());
|
changeMods(new ModWindUp());
|
||||||
AddStep("windup active, trying to change speed", () => songSelect?.ChangeSpeed(0.05));
|
increaseModSpeed();
|
||||||
AddAssert("windup still active", () => songSelect!.Mods.Value.First() is ModWindUp);
|
AddAssert("windup still active", () => songSelect!.Mods.Value.First() is ModWindUp);
|
||||||
|
|
||||||
changeMods(new ModAdaptiveSpeed());
|
changeMods(new ModAdaptiveSpeed());
|
||||||
AddStep("adaptive speed active, trying to change speed", () => songSelect?.ChangeSpeed(0.05));
|
increaseModSpeed();
|
||||||
AddAssert("adaptive speed still active", () => songSelect!.Mods.Value.First() is ModAdaptiveSpeed);
|
AddAssert("adaptive speed still active", () => songSelect!.Mods.Value.First() is ModAdaptiveSpeed);
|
||||||
|
|
||||||
|
void increaseModSpeed() => AddStep("increase mod speed", () =>
|
||||||
|
{
|
||||||
|
InputManager.PressKey(Key.ControlLeft);
|
||||||
|
InputManager.Key(Key.Up);
|
||||||
|
InputManager.ReleaseKey(Key.ControlLeft);
|
||||||
|
});
|
||||||
|
|
||||||
|
void decreaseModSpeed() => AddStep("decrease mod speed", () =>
|
||||||
|
{
|
||||||
|
InputManager.PressKey(Key.ControlLeft);
|
||||||
|
InputManager.Key(Key.Down);
|
||||||
|
InputManager.ReleaseKey(Key.ControlLeft);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
|
@ -64,9 +64,6 @@ namespace osu.Game.Overlays.Mods
|
|||||||
|
|
||||||
private Func<Mod, bool> isValidMod = _ => true;
|
private Func<Mod, bool> isValidMod = _ => true;
|
||||||
|
|
||||||
[Resolved]
|
|
||||||
private SongSelect? songSelect { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// A function determining whether each mod in the column should be displayed.
|
/// A function determining whether each mod in the column should be displayed.
|
||||||
/// A return value of <see langword="true"/> means that the mod is not filtered and therefore its corresponding panel should be displayed.
|
/// A return value of <see langword="true"/> means that the mod is not filtered and therefore its corresponding panel should be displayed.
|
||||||
@ -138,6 +135,7 @@ namespace osu.Game.Overlays.Mods
|
|||||||
private FillFlowContainer<ShearedButton> footerButtonFlow = null!;
|
private FillFlowContainer<ShearedButton> footerButtonFlow = null!;
|
||||||
private FillFlowContainer footerContentFlow = null!;
|
private FillFlowContainer footerContentFlow = null!;
|
||||||
private DeselectAllModsButton deselectAllModsButton = null!;
|
private DeselectAllModsButton deselectAllModsButton = null!;
|
||||||
|
private ModSpeedHotkeyHandler modSpeedHotkeyHandler = null!;
|
||||||
|
|
||||||
private Container aboveColumnsContent = null!;
|
private Container aboveColumnsContent = null!;
|
||||||
private RankingInformationDisplay? rankingInformationDisplay;
|
private RankingInformationDisplay? rankingInformationDisplay;
|
||||||
@ -190,7 +188,8 @@ namespace osu.Game.Overlays.Mods
|
|||||||
Anchor = Anchor.BottomCentre,
|
Anchor = Anchor.BottomCentre,
|
||||||
Origin = Anchor.BottomCentre,
|
Origin = Anchor.BottomCentre,
|
||||||
Height = 0
|
Height = 0
|
||||||
}
|
},
|
||||||
|
modSpeedHotkeyHandler = new ModSpeedHotkeyHandler(),
|
||||||
});
|
});
|
||||||
|
|
||||||
MainAreaContent.AddRange(new Drawable[]
|
MainAreaContent.AddRange(new Drawable[]
|
||||||
@ -758,11 +757,11 @@ namespace osu.Game.Overlays.Mods
|
|||||||
}
|
}
|
||||||
|
|
||||||
case GlobalAction.IncreaseModSpeed:
|
case GlobalAction.IncreaseModSpeed:
|
||||||
songSelect?.ChangeSpeed(0.05);
|
modSpeedHotkeyHandler.ChangeSpeed(0.05, AllAvailableMods.Where(state => state.ValidForSelection.Value).Select(state => state.Mod));
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
case GlobalAction.DecreaseModSpeed:
|
case GlobalAction.DecreaseModSpeed:
|
||||||
songSelect?.ChangeSpeed(-0.05);
|
modSpeedHotkeyHandler.ChangeSpeed(-0.05, AllAvailableMods.Where(state => state.ValidForSelection.Value).Select(state => state.Mod));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
105
osu.Game/Screens/Select/ModSpeedHotkeyHandler.cs
Normal file
105
osu.Game/Screens/Select/ModSpeedHotkeyHandler.cs
Normal file
@ -0,0 +1,105 @@
|
|||||||
|
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||||
|
// See the LICENCE file in the repository root for full licence text.
|
||||||
|
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using osu.Framework.Allocation;
|
||||||
|
using osu.Framework.Bindables;
|
||||||
|
using osu.Framework.Graphics;
|
||||||
|
using osu.Framework.Utils;
|
||||||
|
using osu.Game.Configuration;
|
||||||
|
using osu.Game.Overlays;
|
||||||
|
using osu.Game.Overlays.OSD;
|
||||||
|
using osu.Game.Rulesets.Mods;
|
||||||
|
using osu.Game.Utils;
|
||||||
|
|
||||||
|
namespace osu.Game.Screens.Select
|
||||||
|
{
|
||||||
|
public partial class ModSpeedHotkeyHandler : Component
|
||||||
|
{
|
||||||
|
[Resolved]
|
||||||
|
private Bindable<IReadOnlyList<Mod>> selectedMods { get; set; } = null!;
|
||||||
|
|
||||||
|
[Resolved]
|
||||||
|
private OsuConfigManager config { get; set; } = null!;
|
||||||
|
|
||||||
|
[Resolved]
|
||||||
|
private OnScreenDisplay? onScreenDisplay { get; set; }
|
||||||
|
|
||||||
|
private ModRateAdjust? lastActiveRateAdjustMod;
|
||||||
|
|
||||||
|
protected override void LoadComplete()
|
||||||
|
{
|
||||||
|
base.LoadComplete();
|
||||||
|
|
||||||
|
selectedMods.BindValueChanged(val =>
|
||||||
|
{
|
||||||
|
lastActiveRateAdjustMod = val.NewValue.OfType<ModRateAdjust>().SingleOrDefault() ?? lastActiveRateAdjustMod;
|
||||||
|
}, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool ChangeSpeed(double delta, IEnumerable<Mod> availableMods)
|
||||||
|
{
|
||||||
|
double targetSpeed = (selectedMods.Value.OfType<ModRateAdjust>().SingleOrDefault()?.SpeedChange.Value ?? 1) + delta;
|
||||||
|
|
||||||
|
if (Precision.AlmostEquals(targetSpeed, 1, 0.005))
|
||||||
|
{
|
||||||
|
selectedMods.Value = selectedMods.Value.Where(m => m is not ModRateAdjust).ToList();
|
||||||
|
onScreenDisplay?.Display(new SpeedChangeToast(config, targetSpeed));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
ModRateAdjust? targetMod;
|
||||||
|
|
||||||
|
if (lastActiveRateAdjustMod is ModDaycore || lastActiveRateAdjustMod is ModNightcore)
|
||||||
|
{
|
||||||
|
targetMod = targetSpeed < 1
|
||||||
|
? availableMods.OfType<ModDaycore>().SingleOrDefault()
|
||||||
|
: availableMods.OfType<ModNightcore>().SingleOrDefault();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
targetMod = targetSpeed < 1
|
||||||
|
? availableMods.OfType<ModHalfTime>().SingleOrDefault()
|
||||||
|
: availableMods.OfType<ModDoubleTime>().SingleOrDefault();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (targetMod == null)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// preserve other settings from latest rate adjust mod instance seen
|
||||||
|
if (lastActiveRateAdjustMod != null)
|
||||||
|
{
|
||||||
|
foreach (var (_, sourceProperty) in lastActiveRateAdjustMod.GetSettingsSourceProperties())
|
||||||
|
{
|
||||||
|
if (sourceProperty.Name == nameof(ModRateAdjust.SpeedChange))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
var targetProperty = targetMod.GetType().GetProperty(sourceProperty.Name);
|
||||||
|
|
||||||
|
if (targetProperty == null)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
var targetBindable = (IBindable)targetProperty.GetValue(targetMod)!;
|
||||||
|
var sourceBindable = (IBindable)sourceProperty.GetValue(lastActiveRateAdjustMod)!;
|
||||||
|
|
||||||
|
if (targetBindable.GetType() != sourceBindable.GetType())
|
||||||
|
continue;
|
||||||
|
|
||||||
|
lastActiveRateAdjustMod.CopyAdjustedSetting(targetBindable, sourceBindable);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
targetMod.SpeedChange.Value = targetSpeed;
|
||||||
|
|
||||||
|
var intendedMods = selectedMods.Value.Where(m => m is not ModRateAdjust).Append(targetMod).ToList();
|
||||||
|
|
||||||
|
if (!ModUtils.CheckCompatibleSet(intendedMods))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
selectedMods.Value = intendedMods;
|
||||||
|
onScreenDisplay?.Display(new SpeedChangeToast(config, targetMod.SpeedChange.Value));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -30,7 +30,6 @@ using osu.Game.Graphics.UserInterface;
|
|||||||
using osu.Game.Input.Bindings;
|
using osu.Game.Input.Bindings;
|
||||||
using osu.Game.Overlays;
|
using osu.Game.Overlays;
|
||||||
using osu.Game.Overlays.Mods;
|
using osu.Game.Overlays.Mods;
|
||||||
using osu.Game.Overlays.OSD;
|
|
||||||
using osu.Game.Rulesets;
|
using osu.Game.Rulesets;
|
||||||
using osu.Game.Rulesets.Mods;
|
using osu.Game.Rulesets.Mods;
|
||||||
using osu.Game.Screens.Backgrounds;
|
using osu.Game.Screens.Backgrounds;
|
||||||
@ -40,6 +39,7 @@ using osu.Game.Screens.Play;
|
|||||||
using osu.Game.Screens.Select.Details;
|
using osu.Game.Screens.Select.Details;
|
||||||
using osu.Game.Screens.Select.Options;
|
using osu.Game.Screens.Select.Options;
|
||||||
using osu.Game.Skinning;
|
using osu.Game.Skinning;
|
||||||
|
using osu.Game.Utils;
|
||||||
using osuTK;
|
using osuTK;
|
||||||
using osuTK.Graphics;
|
using osuTK.Graphics;
|
||||||
using osuTK.Input;
|
using osuTK.Input;
|
||||||
@ -137,6 +137,7 @@ namespace osu.Game.Screens.Select
|
|||||||
private double audioFeedbackLastPlaybackTime;
|
private double audioFeedbackLastPlaybackTime;
|
||||||
|
|
||||||
private IDisposable? modSelectOverlayRegistration;
|
private IDisposable? modSelectOverlayRegistration;
|
||||||
|
private ModSpeedHotkeyHandler modSpeedHotkeyHandler = null!;
|
||||||
|
|
||||||
private AdvancedStats advancedStats = null!;
|
private AdvancedStats advancedStats = null!;
|
||||||
|
|
||||||
@ -148,16 +149,6 @@ namespace osu.Game.Screens.Select
|
|||||||
|
|
||||||
private Bindable<bool> configBackgroundBlur = null!;
|
private Bindable<bool> configBackgroundBlur = null!;
|
||||||
|
|
||||||
private bool lastPitchState;
|
|
||||||
|
|
||||||
private bool usedPitchMods;
|
|
||||||
|
|
||||||
[Resolved]
|
|
||||||
private OnScreenDisplay? onScreenDisplay { get; set; }
|
|
||||||
|
|
||||||
[Resolved]
|
|
||||||
private OsuConfigManager config { get; set; } = null!;
|
|
||||||
|
|
||||||
[BackgroundDependencyLoader(true)]
|
[BackgroundDependencyLoader(true)]
|
||||||
private void load(AudioManager audio, OsuColour colours, ManageCollectionsDialog? manageCollectionsDialog, DifficultyRecommender? recommender, OsuConfigManager config)
|
private void load(AudioManager audio, OsuColour colours, ManageCollectionsDialog? manageCollectionsDialog, DifficultyRecommender? recommender, OsuConfigManager config)
|
||||||
{
|
{
|
||||||
@ -333,6 +324,7 @@ namespace osu.Game.Screens.Select
|
|||||||
{
|
{
|
||||||
RelativeSizeAxes = Axes.Both,
|
RelativeSizeAxes = Axes.Both,
|
||||||
},
|
},
|
||||||
|
modSpeedHotkeyHandler = new ModSpeedHotkeyHandler(),
|
||||||
});
|
});
|
||||||
|
|
||||||
if (ShowFooter)
|
if (ShowFooter)
|
||||||
@ -823,140 +815,6 @@ namespace osu.Game.Screens.Select
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
private Mod getRateMod(ModType modType, Type type)
|
|
||||||
{
|
|
||||||
var modList = game.AvailableMods.Value[modType];
|
|
||||||
var multiMod = (MultiMod)modList.First(mod => mod is MultiMod multiMod && multiMod.Mods.Count(mod2 => mod2.GetType().IsSubclassOf(type)) > 0);
|
|
||||||
var mod = multiMod.Mods.First(mod => mod.GetType().IsSubclassOf(type));
|
|
||||||
return mod;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void ChangeSpeed(double delta)
|
|
||||||
{
|
|
||||||
ModNightcore modNc = (ModNightcore)getRateMod(ModType.DifficultyIncrease, typeof(ModNightcore));
|
|
||||||
ModDoubleTime modDt = (ModDoubleTime)getRateMod(ModType.DifficultyIncrease, typeof(ModDoubleTime));
|
|
||||||
ModDaycore modDc = (ModDaycore)getRateMod(ModType.DifficultyReduction, typeof(ModDaycore));
|
|
||||||
ModHalfTime modHt = (ModHalfTime)getRateMod(ModType.DifficultyReduction, typeof(ModHalfTime));
|
|
||||||
bool rateModActive = selectedMods.Value.Count(mod => mod is ModRateAdjust) > 0;
|
|
||||||
bool incompatibleModActive = selectedMods.Value.Count(mod => modDt.IncompatibleMods.Count(incompatibleMod => (mod.GetType().IsSubclassOf(incompatibleMod) || mod.GetType() == incompatibleMod) && incompatibleMod != typeof(ModRateAdjust)) > 0) > 0;
|
|
||||||
double newRate = Math.Round(1d + delta, 2);
|
|
||||||
bool isPositive = delta > 0;
|
|
||||||
|
|
||||||
if (incompatibleModActive)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (!rateModActive)
|
|
||||||
{
|
|
||||||
onScreenDisplay?.Display(new SpeedChangeToast(config, newRate));
|
|
||||||
|
|
||||||
// If no ModRateAdjust is active, activate one
|
|
||||||
ModRateAdjust? newMod = null;
|
|
||||||
|
|
||||||
if (isPositive && !usedPitchMods)
|
|
||||||
newMod = modDt;
|
|
||||||
|
|
||||||
if (isPositive && usedPitchMods)
|
|
||||||
newMod = modNc;
|
|
||||||
|
|
||||||
if (!isPositive && !usedPitchMods)
|
|
||||||
newMod = modHt;
|
|
||||||
|
|
||||||
if (!isPositive && usedPitchMods)
|
|
||||||
newMod = modDc;
|
|
||||||
|
|
||||||
if (!usedPitchMods && newMod is ModDoubleTime newModDt)
|
|
||||||
newModDt.AdjustPitch.Value = lastPitchState;
|
|
||||||
|
|
||||||
if (!usedPitchMods && newMod is ModHalfTime newModHt)
|
|
||||||
newModHt.AdjustPitch.Value = lastPitchState;
|
|
||||||
|
|
||||||
newMod!.SpeedChange.Value = newRate;
|
|
||||||
selectedMods.Value = selectedMods.Value.Append(newMod).ToList();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
ModRateAdjust mod = (ModRateAdjust)selectedMods.Value.First(mod => mod is ModRateAdjust);
|
|
||||||
newRate = Math.Round(mod.SpeedChange.Value + delta, 2);
|
|
||||||
|
|
||||||
// Disable RateAdjustMods if newRate is 1
|
|
||||||
if (newRate == 1.0)
|
|
||||||
{
|
|
||||||
lastPitchState = false;
|
|
||||||
usedPitchMods = false;
|
|
||||||
|
|
||||||
if (mod is ModDoubleTime dtmod && dtmod.AdjustPitch.Value)
|
|
||||||
lastPitchState = true;
|
|
||||||
|
|
||||||
if (mod is ModHalfTime htmod && htmod.AdjustPitch.Value)
|
|
||||||
lastPitchState = true;
|
|
||||||
|
|
||||||
if (mod is ModNightcore || mod is ModDaycore)
|
|
||||||
usedPitchMods = true;
|
|
||||||
|
|
||||||
//Disable RateAdjustMods
|
|
||||||
selectedMods.Value = selectedMods.Value.Where(search => search is not ModRateAdjust).ToList();
|
|
||||||
|
|
||||||
onScreenDisplay?.Display(new SpeedChangeToast(config, newRate));
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool overMaxRateLimit = (mod is ModHalfTime || mod is ModDaycore) && newRate > mod.SpeedChange.MaxValue;
|
|
||||||
bool underMinRateLimit = (mod is ModDoubleTime || mod is ModNightcore) && newRate < mod.SpeedChange.MinValue;
|
|
||||||
|
|
||||||
// Swap mod to opposite mod if newRate exceeds max/min speed values
|
|
||||||
if (overMaxRateLimit || underMinRateLimit)
|
|
||||||
{
|
|
||||||
bool adjustPitch = (mod is ModDoubleTime dtmod && dtmod.AdjustPitch.Value) || (mod is ModHalfTime htmod && htmod.AdjustPitch.Value);
|
|
||||||
|
|
||||||
//Disable RateAdjustMods
|
|
||||||
selectedMods.Value = selectedMods.Value.Where(search => search is not ModRateAdjust).ToList();
|
|
||||||
|
|
||||||
ModRateAdjust? oppositeMod = null;
|
|
||||||
|
|
||||||
switch (mod)
|
|
||||||
{
|
|
||||||
case ModDoubleTime:
|
|
||||||
modHt.AdjustPitch.Value = adjustPitch;
|
|
||||||
oppositeMod = modHt;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case ModHalfTime:
|
|
||||||
modDt.AdjustPitch.Value = adjustPitch;
|
|
||||||
oppositeMod = modDt;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case ModNightcore:
|
|
||||||
oppositeMod = modDc;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case ModDaycore:
|
|
||||||
oppositeMod = modNc;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (oppositeMod == null) return;
|
|
||||||
|
|
||||||
oppositeMod.SpeedChange.Value = newRate;
|
|
||||||
selectedMods.Value = selectedMods.Value.Append(oppositeMod).ToList();
|
|
||||||
|
|
||||||
onScreenDisplay?.Display(new SpeedChangeToast(config, newRate));
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Cap newRate to max/min values and change rate of current active mod
|
|
||||||
if (newRate > mod.SpeedChange.MaxValue && (mod is ModDoubleTime || mod is ModNightcore))
|
|
||||||
newRate = mod.SpeedChange.MaxValue;
|
|
||||||
|
|
||||||
if (newRate < mod.SpeedChange.MinValue && (mod is ModHalfTime || mod is ModDaycore))
|
|
||||||
newRate = mod.SpeedChange.MinValue;
|
|
||||||
|
|
||||||
mod.SpeedChange.Value = newRate;
|
|
||||||
|
|
||||||
onScreenDisplay?.Display(new SpeedChangeToast(config, newRate));
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override void Dispose(bool isDisposing)
|
protected override void Dispose(bool isDisposing)
|
||||||
{
|
{
|
||||||
base.Dispose(isDisposing);
|
base.Dispose(isDisposing);
|
||||||
@ -1160,11 +1018,11 @@ namespace osu.Game.Screens.Select
|
|||||||
switch (e.Action)
|
switch (e.Action)
|
||||||
{
|
{
|
||||||
case GlobalAction.IncreaseModSpeed:
|
case GlobalAction.IncreaseModSpeed:
|
||||||
ChangeSpeed(0.05);
|
modSpeedHotkeyHandler.ChangeSpeed(0.05, ModUtils.FlattenMods(game.AvailableMods.Value.SelectMany(kv => kv.Value)));
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
case GlobalAction.DecreaseModSpeed:
|
case GlobalAction.DecreaseModSpeed:
|
||||||
ChangeSpeed(-0.05);
|
modSpeedHotkeyHandler.ChangeSpeed(-0.05, ModUtils.FlattenMods(game.AvailableMods.Value.SelectMany(kv => kv.Value)));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user