diff --git a/osu.Android.props b/osu.Android.props
index e5fed09c07..a384ad4c34 100644
--- a/osu.Android.props
+++ b/osu.Android.props
@@ -52,6 +52,6 @@
-
+
diff --git a/osu.Game.Rulesets.Catch.Tests/osu.Game.Rulesets.Catch.Tests.csproj b/osu.Game.Rulesets.Catch.Tests/osu.Game.Rulesets.Catch.Tests.csproj
index 7c0b73e8c3..f9d56dfa78 100644
--- a/osu.Game.Rulesets.Catch.Tests/osu.Game.Rulesets.Catch.Tests.csproj
+++ b/osu.Game.Rulesets.Catch.Tests/osu.Game.Rulesets.Catch.Tests.csproj
@@ -2,7 +2,7 @@
-
+
diff --git a/osu.Game.Rulesets.Mania.Tests/osu.Game.Rulesets.Mania.Tests.csproj b/osu.Game.Rulesets.Mania.Tests/osu.Game.Rulesets.Mania.Tests.csproj
index 972cbec4a2..ed00ed0b4c 100644
--- a/osu.Game.Rulesets.Mania.Tests/osu.Game.Rulesets.Mania.Tests.csproj
+++ b/osu.Game.Rulesets.Mania.Tests/osu.Game.Rulesets.Mania.Tests.csproj
@@ -2,7 +2,7 @@
-
+
diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneSpinnerRotation.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneSpinnerRotation.cs
index b46964e8b7..69857f8ef9 100644
--- a/osu.Game.Rulesets.Osu.Tests/TestSceneSpinnerRotation.cs
+++ b/osu.Game.Rulesets.Osu.Tests/TestSceneSpinnerRotation.cs
@@ -7,6 +7,7 @@ using System.Linq;
using NUnit.Framework;
using osu.Framework.Allocation;
using osu.Framework.Audio;
+using osu.Framework.Bindables;
using osu.Framework.Graphics.Sprites;
using osu.Framework.Testing;
using osu.Framework.Timing;
@@ -69,11 +70,11 @@ namespace osu.Game.Rulesets.Osu.Tests
trackerRotationTolerance = Math.Abs(drawableSpinner.RotationTracker.Rotation * 0.1f);
});
AddAssert("is disc rotation not almost 0", () => !Precision.AlmostEquals(drawableSpinner.RotationTracker.Rotation, 0, 100));
- AddAssert("is disc rotation absolute not almost 0", () => !Precision.AlmostEquals(drawableSpinner.RotationTracker.CumulativeRotation, 0, 100));
+ AddAssert("is disc rotation absolute not almost 0", () => !Precision.AlmostEquals(drawableSpinner.RotationTracker.RateAdjustedRotation, 0, 100));
addSeekStep(0);
AddAssert("is disc rotation almost 0", () => Precision.AlmostEquals(drawableSpinner.RotationTracker.Rotation, 0, trackerRotationTolerance));
- AddAssert("is disc rotation absolute almost 0", () => Precision.AlmostEquals(drawableSpinner.RotationTracker.CumulativeRotation, 0, 100));
+ AddAssert("is disc rotation absolute almost 0", () => Precision.AlmostEquals(drawableSpinner.RotationTracker.RateAdjustedRotation, 0, 100));
}
[Test]
@@ -94,7 +95,7 @@ namespace osu.Game.Rulesets.Osu.Tests
finalSpinnerSymbolRotation = spinnerSymbol.Rotation;
spinnerSymbolRotationTolerance = Math.Abs(finalSpinnerSymbolRotation * 0.05f);
});
- AddStep("retrieve cumulative disc rotation", () => finalCumulativeTrackerRotation = drawableSpinner.RotationTracker.CumulativeRotation);
+ AddStep("retrieve cumulative disc rotation", () => finalCumulativeTrackerRotation = drawableSpinner.RotationTracker.RateAdjustedRotation);
addSeekStep(2500);
AddAssert("disc rotation rewound",
@@ -106,7 +107,7 @@ namespace osu.Game.Rulesets.Osu.Tests
() => Precision.AlmostEquals(spinnerSymbol.Rotation, finalSpinnerSymbolRotation / 2, spinnerSymbolRotationTolerance));
AddAssert("is cumulative rotation rewound",
// cumulative rotation is not damped, so we're treating it as the "ground truth" and allowing a comparatively smaller margin of error.
- () => Precision.AlmostEquals(drawableSpinner.RotationTracker.CumulativeRotation, finalCumulativeTrackerRotation / 2, 100));
+ () => Precision.AlmostEquals(drawableSpinner.RotationTracker.RateAdjustedRotation, finalCumulativeTrackerRotation / 2, 100));
addSeekStep(5000);
AddAssert("is disc rotation almost same",
@@ -114,26 +115,14 @@ namespace osu.Game.Rulesets.Osu.Tests
AddAssert("is symbol rotation almost same",
() => Precision.AlmostEquals(spinnerSymbol.Rotation, finalSpinnerSymbolRotation, spinnerSymbolRotationTolerance));
AddAssert("is cumulative rotation almost same",
- () => Precision.AlmostEquals(drawableSpinner.RotationTracker.CumulativeRotation, finalCumulativeTrackerRotation, 100));
+ () => Precision.AlmostEquals(drawableSpinner.RotationTracker.RateAdjustedRotation, finalCumulativeTrackerRotation, 100));
}
[Test]
public void TestRotationDirection([Values(true, false)] bool clockwise)
{
if (clockwise)
- {
- AddStep("flip replay", () =>
- {
- var drawableRuleset = this.ChildrenOfType().Single();
- var score = drawableRuleset.ReplayScore;
- var scoreWithFlippedReplay = new Score
- {
- ScoreInfo = score.ScoreInfo,
- Replay = flipReplay(score.Replay)
- };
- drawableRuleset.SetReplayScore(scoreWithFlippedReplay);
- });
- }
+ transformReplay(flip);
addSeekStep(5000);
@@ -141,7 +130,7 @@ namespace osu.Game.Rulesets.Osu.Tests
AddAssert("spinner symbol direction correct", () => clockwise ? spinnerSymbol.Rotation > 0 : spinnerSymbol.Rotation < 0);
}
- private Replay flipReplay(Replay scoreReplay) => new Replay
+ private Replay flip(Replay scoreReplay) => new Replay
{
Frames = scoreReplay
.Frames
@@ -164,7 +153,7 @@ namespace osu.Game.Rulesets.Osu.Tests
{
// multipled by 2 to nullify the score multiplier. (autoplay mod selected)
var totalScore = ((ScoreExposedPlayer)Player).ScoreProcessor.TotalScore.Value * 2;
- return totalScore == (int)(drawableSpinner.RotationTracker.CumulativeRotation / 360) * SpinnerTick.SCORE_PER_TICK;
+ return totalScore == (int)(drawableSpinner.RotationTracker.RateAdjustedRotation / 360) * SpinnerTick.SCORE_PER_TICK;
});
addSeekStep(0);
@@ -196,6 +185,49 @@ namespace osu.Game.Rulesets.Osu.Tests
AddAssert("spm still valid", () => Precision.AlmostEquals(drawableSpinner.SpmCounter.SpinsPerMinute, estimatedSpm, 1.0));
}
+ [TestCase(0.5)]
+ [TestCase(2.0)]
+ public void TestSpinUnaffectedByClockRate(double rate)
+ {
+ double expectedProgress = 0;
+ double expectedSpm = 0;
+
+ addSeekStep(1000);
+ AddStep("retrieve spinner state", () =>
+ {
+ expectedProgress = drawableSpinner.Progress;
+ expectedSpm = drawableSpinner.SpmCounter.SpinsPerMinute;
+ });
+
+ addSeekStep(0);
+
+ AddStep("adjust track rate", () => track.AddAdjustment(AdjustableProperty.Tempo, new BindableDouble(rate)));
+ // autoplay replay frames use track time;
+ // if a spin takes 1000ms in track time and we're playing with a 2x rate adjustment, the spin will take 500ms of *real* time.
+ // therefore we need to apply the rate adjustment to the replay itself to change from track time to real time,
+ // as real time is what we care about for spinners
+ // (so we're making the spin take 1000ms in real time *always*, regardless of the track clock's rate).
+ transformReplay(replay => applyRateAdjustment(replay, rate));
+
+ addSeekStep(1000);
+ AddAssert("progress almost same", () => Precision.AlmostEquals(expectedProgress, drawableSpinner.Progress, 0.05));
+ AddAssert("spm almost same", () => Precision.AlmostEquals(expectedSpm, drawableSpinner.SpmCounter.SpinsPerMinute, 2.0));
+ }
+
+ private Replay applyRateAdjustment(Replay scoreReplay, double rate) => new Replay
+ {
+ Frames = scoreReplay
+ .Frames
+ .Cast()
+ .Select(replayFrame =>
+ {
+ var adjustedTime = replayFrame.Time * rate;
+ return new OsuReplayFrame(adjustedTime, replayFrame.Position, replayFrame.Actions.ToArray());
+ })
+ .Cast()
+ .ToList()
+ };
+
private void addSeekStep(double time)
{
AddStep($"seek to {time}", () => track.Seek(time));
@@ -203,6 +235,18 @@ namespace osu.Game.Rulesets.Osu.Tests
AddUntilStep("wait for seek to finish", () => Precision.AlmostEquals(time, Player.DrawableRuleset.FrameStableClock.CurrentTime, 100));
}
+ private void transformReplay(Func replayTransformation) => AddStep("set replay", () =>
+ {
+ var drawableRuleset = this.ChildrenOfType().Single();
+ var score = drawableRuleset.ReplayScore;
+ var transformedScore = new Score
+ {
+ ScoreInfo = score.ScoreInfo,
+ Replay = replayTransformation.Invoke(score.Replay)
+ };
+ drawableRuleset.SetReplayScore(transformedScore);
+ });
+
protected override IBeatmap CreateBeatmap(RulesetInfo ruleset) => new Beatmap
{
HitObjects = new List
diff --git a/osu.Game.Rulesets.Osu.Tests/osu.Game.Rulesets.Osu.Tests.csproj b/osu.Game.Rulesets.Osu.Tests/osu.Game.Rulesets.Osu.Tests.csproj
index d6a68abaf2..f3837ea6b1 100644
--- a/osu.Game.Rulesets.Osu.Tests/osu.Game.Rulesets.Osu.Tests.csproj
+++ b/osu.Game.Rulesets.Osu.Tests/osu.Game.Rulesets.Osu.Tests.csproj
@@ -2,7 +2,7 @@
-
+
diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinner.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinner.cs
index 7363da0de8..f10d11827b 100644
--- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinner.cs
+++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinner.cs
@@ -4,6 +4,7 @@
using System;
using System.Linq;
using osu.Framework.Allocation;
+using osu.Framework.Audio;
using osu.Framework.Bindables;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
@@ -184,7 +185,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
// these become implicitly hit.
return 1;
- return Math.Clamp(RotationTracker.CumulativeRotation / 360 / Spinner.SpinsRequired, 0, 1);
+ return Math.Clamp(RotationTracker.RateAdjustedRotation / 360 / Spinner.SpinsRequired, 0, 1);
}
}
@@ -232,7 +233,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
if (!SpmCounter.IsPresent && RotationTracker.Tracking)
SpmCounter.FadeIn(HitObject.TimeFadeIn);
- SpmCounter.SetRotation(RotationTracker.CumulativeRotation);
+ SpmCounter.SetRotation(RotationTracker.RateAdjustedRotation);
updateBonusScore();
}
@@ -244,7 +245,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
if (ticks.Count == 0)
return;
- int spins = (int)(RotationTracker.CumulativeRotation / 360);
+ int spins = (int)(RotationTracker.RateAdjustedRotation / 360);
if (spins < wholeSpins)
{
diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/DefaultSpinnerDisc.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/DefaultSpinnerDisc.cs
index dfb692eba9..1476fe6010 100644
--- a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/DefaultSpinnerDisc.cs
+++ b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/DefaultSpinnerDisc.cs
@@ -177,7 +177,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces
{
get
{
- int rotations = (int)(drawableSpinner.RotationTracker.CumulativeRotation / 360);
+ int rotations = (int)(drawableSpinner.RotationTracker.RateAdjustedRotation / 360);
if (wholeRotationCount == rotations) return false;
diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SpinnerRotationTracker.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SpinnerRotationTracker.cs
index 0cc6c842f4..f1a782cbb5 100644
--- a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SpinnerRotationTracker.cs
+++ b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SpinnerRotationTracker.cs
@@ -31,17 +31,28 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces
public readonly BindableBool Complete = new BindableBool();
///
- /// The total rotation performed on the spinner disc, disregarding the spin direction.
+ /// The total rotation performed on the spinner disc, disregarding the spin direction,
+ /// adjusted for the track's playback rate.
///
///
+ ///
/// This value is always non-negative and is monotonically increasing with time
/// (i.e. will only increase if time is passing forward, but can decrease during rewind).
+ ///
+ ///
+ /// The rotation from each frame is multiplied by the clock's current playback rate.
+ /// The reason this is done is to ensure that spinners give the same score and require the same number of spins
+ /// regardless of whether speed-modifying mods are applied.
+ ///
///
///
- /// If the spinner is spun 360 degrees clockwise and then 360 degrees counter-clockwise,
+ /// Assuming no speed-modifying mods are active,
+ /// if the spinner is spun 360 degrees clockwise and then 360 degrees counter-clockwise,
/// this property will return the value of 720 (as opposed to 0 for ).
+ /// If Double Time is active instead (with a speed multiplier of 1.5x),
+ /// in the same scenario the property will return 720 * 1.5 = 1080.
///
- public float CumulativeRotation { get; private set; }
+ public float RateAdjustedRotation { get; private set; }
///
/// Whether the spinning is spinning at a reasonable speed to be considered visually spinning.
@@ -113,7 +124,9 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces
}
currentRotation += angle;
- CumulativeRotation += Math.Abs(angle) * Math.Sign(Clock.ElapsedFrameTime);
+ // rate has to be applied each frame, because it's not guaranteed to be constant throughout playback
+ // (see: ModTimeRamp)
+ RateAdjustedRotation += (float)(Math.Abs(angle) * Clock.Rate);
}
}
}
diff --git a/osu.Game.Rulesets.Taiko.Tests/osu.Game.Rulesets.Taiko.Tests.csproj b/osu.Game.Rulesets.Taiko.Tests/osu.Game.Rulesets.Taiko.Tests.csproj
index ada7ac5d74..e896606ee8 100644
--- a/osu.Game.Rulesets.Taiko.Tests/osu.Game.Rulesets.Taiko.Tests.csproj
+++ b/osu.Game.Rulesets.Taiko.Tests/osu.Game.Rulesets.Taiko.Tests.csproj
@@ -2,7 +2,7 @@
-
+
diff --git a/osu.Game.Tests/Visual/Settings/TestSceneKeyBindingPanel.cs b/osu.Game.Tests/Visual/Settings/TestSceneKeyBindingPanel.cs
index 3d335995ac..e06b3a8a7e 100644
--- a/osu.Game.Tests/Visual/Settings/TestSceneKeyBindingPanel.cs
+++ b/osu.Game.Tests/Visual/Settings/TestSceneKeyBindingPanel.cs
@@ -64,5 +64,77 @@ namespace osu.Game.Tests.Visual.Settings
}, 0, true);
});
}
+
+ [Test]
+ public void TestClearButtonOnBindings()
+ {
+ KeyBindingRow backBindingRow = null;
+
+ AddStep("click back binding row", () =>
+ {
+ backBindingRow = panel.ChildrenOfType().ElementAt(10);
+ InputManager.MoveMouseTo(backBindingRow);
+ InputManager.Click(MouseButton.Left);
+ });
+
+ clickClearButton();
+
+ AddAssert("first binding cleared", () => string.IsNullOrEmpty(backBindingRow.ChildrenOfType().First().Text.Text));
+
+ AddStep("click second binding", () =>
+ {
+ var target = backBindingRow.ChildrenOfType().ElementAt(1);
+
+ InputManager.MoveMouseTo(target);
+ InputManager.Click(MouseButton.Left);
+ });
+
+ clickClearButton();
+
+ AddAssert("second binding cleared", () => string.IsNullOrEmpty(backBindingRow.ChildrenOfType().ElementAt(1).Text.Text));
+
+ void clickClearButton()
+ {
+ AddStep("click clear button", () =>
+ {
+ var clearButton = backBindingRow.ChildrenOfType().Single();
+
+ InputManager.MoveMouseTo(clearButton);
+ InputManager.Click(MouseButton.Left);
+ });
+ }
+ }
+
+ [Test]
+ public void TestClickRowSelectsFirstBinding()
+ {
+ KeyBindingRow backBindingRow = null;
+
+ AddStep("click back binding row", () =>
+ {
+ backBindingRow = panel.ChildrenOfType().ElementAt(10);
+ InputManager.MoveMouseTo(backBindingRow);
+ InputManager.Click(MouseButton.Left);
+ });
+
+ AddAssert("first binding selected", () => backBindingRow.ChildrenOfType().First().IsBinding);
+
+ AddStep("click second binding", () =>
+ {
+ var target = backBindingRow.ChildrenOfType().ElementAt(1);
+
+ InputManager.MoveMouseTo(target);
+ InputManager.Click(MouseButton.Left);
+ });
+
+ AddStep("click back binding row", () =>
+ {
+ backBindingRow = panel.ChildrenOfType().ElementAt(10);
+ InputManager.MoveMouseTo(backBindingRow);
+ InputManager.Click(MouseButton.Left);
+ });
+
+ AddAssert("first binding selected", () => backBindingRow.ChildrenOfType().First().IsBinding);
+ }
}
}
diff --git a/osu.Game.Tests/osu.Game.Tests.csproj b/osu.Game.Tests/osu.Game.Tests.csproj
index 4b0506d818..d767973528 100644
--- a/osu.Game.Tests/osu.Game.Tests.csproj
+++ b/osu.Game.Tests/osu.Game.Tests.csproj
@@ -3,7 +3,7 @@
-
+
diff --git a/osu.Game.Tournament.Tests/osu.Game.Tournament.Tests.csproj b/osu.Game.Tournament.Tests/osu.Game.Tournament.Tests.csproj
index f256b8e4e9..95f5deb2cc 100644
--- a/osu.Game.Tournament.Tests/osu.Game.Tournament.Tests.csproj
+++ b/osu.Game.Tournament.Tests/osu.Game.Tournament.Tests.csproj
@@ -5,7 +5,7 @@
-
+
diff --git a/osu.Game/OsuGame.cs b/osu.Game/OsuGame.cs
index b5752214bd..623c677991 100644
--- a/osu.Game/OsuGame.cs
+++ b/osu.Game/OsuGame.cs
@@ -702,6 +702,9 @@ namespace osu.Game
if (state.NewValue == Visibility.Hidden) return;
singleDisplayOverlays.Where(o => o != overlay).ForEach(o => o.Hide());
+
+ if (!overlay.IsPresent)
+ overlayContent.ChangeChildDepth(overlay, (float)-Clock.CurrentTime);
};
}
diff --git a/osu.Game/Overlays/KeyBinding/KeyBindingRow.cs b/osu.Game/Overlays/KeyBinding/KeyBindingRow.cs
index eafb4572ca..b808d49fa2 100644
--- a/osu.Game/Overlays/KeyBinding/KeyBindingRow.cs
+++ b/osu.Game/Overlays/KeyBinding/KeyBindingRow.cs
@@ -48,8 +48,7 @@ namespace osu.Game.Overlays.KeyBinding
public bool FilteringActive { get; set; }
private OsuSpriteText text;
- private Drawable pressAKey;
-
+ private FillFlowContainer cancelAndClearButtons;
private FillFlowContainer buttons;
public IEnumerable FilterTerms => bindings.Select(b => b.KeyCombination.ReadableString()).Prepend((string)text.Text);
@@ -80,7 +79,7 @@ namespace osu.Game.Overlays.KeyBinding
Hollow = true,
};
- Children = new[]
+ Children = new Drawable[]
{
new Box
{
@@ -99,7 +98,7 @@ namespace osu.Game.Overlays.KeyBinding
Anchor = Anchor.TopRight,
Origin = Anchor.TopRight
},
- pressAKey = new FillFlowContainer
+ cancelAndClearButtons = new FillFlowContainer
{
AutoSizeAxes = Axes.Both,
Padding = new MarginPadding(padding) { Top = height + padding * 2 },
@@ -187,7 +186,8 @@ namespace osu.Game.Overlays.KeyBinding
if (bindTarget.IsHovered)
finalise();
- else
+ // prevent updating bind target before clear button's action
+ else if (!cancelAndClearButtons.Any(b => b.IsHovered))
updateBindTarget();
}
@@ -298,8 +298,8 @@ namespace osu.Game.Overlays.KeyBinding
if (HasFocus)
GetContainingInputManager().ChangeFocus(null);
- pressAKey.FadeOut(300, Easing.OutQuint);
- pressAKey.BypassAutoSizeAxes |= Axes.Y;
+ cancelAndClearButtons.FadeOut(300, Easing.OutQuint);
+ cancelAndClearButtons.BypassAutoSizeAxes |= Axes.Y;
}
protected override void OnFocus(FocusEvent e)
@@ -307,8 +307,8 @@ namespace osu.Game.Overlays.KeyBinding
AutoSizeDuration = 500;
AutoSizeEasing = Easing.OutQuint;
- pressAKey.FadeIn(300, Easing.OutQuint);
- pressAKey.BypassAutoSizeAxes &= ~Axes.Y;
+ cancelAndClearButtons.FadeIn(300, Easing.OutQuint);
+ cancelAndClearButtons.BypassAutoSizeAxes &= ~Axes.Y;
updateBindTarget();
base.OnFocus(e);
@@ -320,6 +320,9 @@ namespace osu.Game.Overlays.KeyBinding
base.OnFocusLost(e);
}
+ ///
+ /// Updates the bind target to the currently hovered key button or the first if clicked anywhere else.
+ ///
private void updateBindTarget()
{
if (bindTarget != null) bindTarget.IsBinding = false;
@@ -354,7 +357,7 @@ namespace osu.Game.Overlays.KeyBinding
}
}
- private class KeyButton : Container
+ public class KeyButton : Container
{
public readonly Framework.Input.Bindings.KeyBinding KeyBinding;
diff --git a/osu.Game/Rulesets/RulesetStore.cs b/osu.Game/Rulesets/RulesetStore.cs
index dd43092c0d..5d93f5186b 100644
--- a/osu.Game/Rulesets/RulesetStore.cs
+++ b/osu.Game/Rulesets/RulesetStore.cs
@@ -191,6 +191,11 @@ namespace osu.Game.Rulesets
if (loadedAssemblies.ContainsKey(assembly))
return;
+ // the same assembly may be loaded twice in the same AppDomain (currently a thing in certain Rider versions https://youtrack.jetbrains.com/issue/RIDER-48799).
+ // as a failsafe, also compare by FullName.
+ if (loadedAssemblies.Any(a => a.Key.FullName == assembly.FullName))
+ return;
+
try
{
loadedAssemblies[assembly] = assembly.GetTypes().First(t => t.IsPublic && t.IsSubclassOf(typeof(Ruleset)));
diff --git a/osu.Game/Screens/Multi/Play/TimeshiftPlayer.cs b/osu.Game/Screens/Multi/Play/TimeshiftPlayer.cs
index da082692d7..04da943a10 100644
--- a/osu.Game/Screens/Multi/Play/TimeshiftPlayer.cs
+++ b/osu.Game/Screens/Multi/Play/TimeshiftPlayer.cs
@@ -64,7 +64,7 @@ namespace osu.Game.Screens.Multi.Play
{
failed = true;
- Logger.Error(e, "Failed to retrieve a score submission token.");
+ Logger.Error(e, "Failed to retrieve a score submission token.\n\nThis may happen if you are running an old or non-official release of osu! (ie. you are self-compiling).");
Schedule(() =>
{
diff --git a/osu.Game/Screens/Play/PauseOverlay.cs b/osu.Game/Screens/Play/PauseOverlay.cs
index fa917cda32..97f1d1c91d 100644
--- a/osu.Game/Screens/Play/PauseOverlay.cs
+++ b/osu.Game/Screens/Play/PauseOverlay.cs
@@ -4,6 +4,7 @@
using System;
using System.Linq;
using osu.Framework.Allocation;
+using osu.Framework.Audio;
using osu.Framework.Graphics;
using osu.Game.Audio;
using osu.Game.Graphics;
diff --git a/osu.Game/Skinning/SkinnableSound.cs b/osu.Game/Skinning/SkinnableSound.cs
index f19aaee821..11856fa581 100644
--- a/osu.Game/Skinning/SkinnableSound.cs
+++ b/osu.Game/Skinning/SkinnableSound.cs
@@ -8,16 +8,14 @@ using osu.Framework.Audio;
using osu.Framework.Audio.Track;
using osu.Framework.Bindables;
using osu.Framework.Extensions.IEnumerableExtensions;
-using osu.Framework.Graphics;
using osu.Framework.Graphics.Audio;
using osu.Framework.Graphics.Containers;
-using osu.Framework.Graphics.Transforms;
using osu.Game.Audio;
using osu.Game.Screens.Play;
namespace osu.Game.Skinning
{
- public class SkinnableSound : SkinReloadableDrawable
+ public class SkinnableSound : SkinReloadableDrawable, IAdjustableAudioComponent
{
private readonly ISampleInfo[] hitSamples;
@@ -144,36 +142,17 @@ namespace osu.Game.Skinning
public BindableNumber Tempo => samplesContainer.Tempo;
+ public void AddAdjustment(AdjustableProperty type, BindableNumber adjustBindable)
+ => samplesContainer.AddAdjustment(type, adjustBindable);
+
+ public void RemoveAdjustment(AdjustableProperty type, BindableNumber adjustBindable)
+ => samplesContainer.RemoveAdjustment(type, adjustBindable);
+
+ public void RemoveAllAdjustments(AdjustableProperty type)
+ => samplesContainer.RemoveAllAdjustments(type);
+
public bool IsPlaying => samplesContainer.Any(s => s.Playing);
- ///
- /// Smoothly adjusts over time.
- ///
- /// A to which further transforms can be added.
- public TransformSequence> VolumeTo(double newVolume, double duration = 0, Easing easing = Easing.None) =>
- samplesContainer.VolumeTo(newVolume, duration, easing);
-
- ///
- /// Smoothly adjusts over time.
- ///
- /// A to which further transforms can be added.
- public TransformSequence> BalanceTo(double newBalance, double duration = 0, Easing easing = Easing.None) =>
- samplesContainer.BalanceTo(newBalance, duration, easing);
-
- ///
- /// Smoothly adjusts over time.
- ///
- /// A to which further transforms can be added.
- public TransformSequence> FrequencyTo(double newFrequency, double duration = 0, Easing easing = Easing.None) =>
- samplesContainer.FrequencyTo(newFrequency, duration, easing);
-
- ///
- /// Smoothly adjusts over time.
- ///
- /// A to which further transforms can be added.
- public TransformSequence> TempoTo(double newTempo, double duration = 0, Easing easing = Easing.None) =>
- samplesContainer.TempoTo(newTempo, duration, easing);
-
#endregion
}
}
diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj
index 18c3052ca3..b38ef38ec2 100644
--- a/osu.Game/osu.Game.csproj
+++ b/osu.Game/osu.Game.csproj
@@ -24,7 +24,7 @@
-
+
diff --git a/osu.iOS.props b/osu.iOS.props
index b034253d88..00ddd94d53 100644
--- a/osu.iOS.props
+++ b/osu.iOS.props
@@ -70,7 +70,7 @@
-
+
@@ -80,7 +80,7 @@
-
+