diff --git a/osu.Android.props b/osu.Android.props
index 0b43fd73f5..aa4d9fa4ee 100644
--- a/osu.Android.props
+++ b/osu.Android.props
@@ -52,6 +52,6 @@
-
+
diff --git a/osu.Desktop/OsuGameDesktop.cs b/osu.Desktop/OsuGameDesktop.cs
index 0feab9a717..62d8c17058 100644
--- a/osu.Desktop/OsuGameDesktop.cs
+++ b/osu.Desktop/OsuGameDesktop.cs
@@ -59,7 +59,7 @@ namespace osu.Desktop
try
{
using (RegistryKey key = Registry.ClassesRoot.OpenSubKey("osu"))
- stableInstallPath = key?.OpenSubKey(@"shell\open\command")?.GetValue(string.Empty).ToString()?.Split('"')[1].Replace("osu!.exe", "");
+ stableInstallPath = key?.OpenSubKey(@"shell\open\command")?.GetValue(string.Empty)?.ToString()?.Split('"')[1].Replace("osu!.exe", "");
if (checkExists(stableInstallPath))
return stableInstallPath;
@@ -138,7 +138,7 @@ namespace osu.Desktop
break;
// SDL2 DesktopWindow
- case DesktopWindow desktopWindow:
+ case SDL2DesktopWindow desktopWindow:
desktopWindow.CursorState |= CursorState.Hidden;
desktopWindow.SetIconFromStream(iconStream);
desktopWindow.Title = Name;
diff --git a/osu.Desktop/Program.cs b/osu.Desktop/Program.cs
index 285a813d97..6ca7079654 100644
--- a/osu.Desktop/Program.cs
+++ b/osu.Desktop/Program.cs
@@ -22,9 +22,9 @@ namespace osu.Desktop
{
// Back up the cwd before DesktopGameHost changes it
var cwd = Environment.CurrentDirectory;
- bool useSdl = args.Contains("--sdl");
+ bool useOsuTK = args.Contains("--tk");
- using (DesktopGameHost host = Host.GetSuitableHost(@"osu", true, useSdl: useSdl))
+ using (DesktopGameHost host = Host.GetSuitableHost(@"osu", true, useOsuTK: useOsuTK))
{
host.ExceptionThrown += handleException;
diff --git a/osu.Desktop/osu.Desktop.csproj b/osu.Desktop/osu.Desktop.csproj
index 62e8f7c518..7b80ca64d0 100644
--- a/osu.Desktop/osu.Desktop.csproj
+++ b/osu.Desktop/osu.Desktop.csproj
@@ -28,7 +28,7 @@
-
+
diff --git a/osu.Game.Rulesets.Catch/UI/Catcher.cs b/osu.Game.Rulesets.Catch/UI/Catcher.cs
index 0f0b9df76e..11b6916a4c 100644
--- a/osu.Game.Rulesets.Catch/UI/Catcher.cs
+++ b/osu.Game.Rulesets.Catch/UI/Catcher.cs
@@ -9,6 +9,7 @@ using osu.Framework.Bindables;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Animations;
using osu.Framework.Graphics.Containers;
+using osu.Framework.Graphics.Pooling;
using osu.Framework.Input.Bindings;
using osu.Framework.Utils;
using osu.Game.Beatmaps;
@@ -107,6 +108,9 @@ namespace osu.Game.Rulesets.Catch.UI
private float hyperDashTargetPosition;
private Bindable hitLighting;
+ private DrawablePool hitExplosionPool;
+ private Container hitExplosionContainer;
+
public Catcher([NotNull] Container trailsTarget, BeatmapDifficulty difficulty = null)
{
this.trailsTarget = trailsTarget;
@@ -127,6 +131,7 @@ namespace osu.Game.Rulesets.Catch.UI
InternalChildren = new Drawable[]
{
+ hitExplosionPool = new DrawablePool(10),
caughtFruitContainer,
catcherIdle = new CatcherSprite(CatcherAnimationState.Idle)
{
@@ -142,7 +147,12 @@ namespace osu.Game.Rulesets.Catch.UI
{
Anchor = Anchor.TopCentre,
Alpha = 0,
- }
+ },
+ hitExplosionContainer = new Container
+ {
+ Anchor = Anchor.TopCentre,
+ Origin = Anchor.BottomCentre,
+ },
};
trails = new CatcherTrailDisplay(this);
@@ -209,11 +219,11 @@ namespace osu.Game.Rulesets.Catch.UI
if (hitLighting.Value)
{
- AddInternal(new HitExplosion(fruit)
- {
- X = fruit.X,
- Scale = new Vector2(fruit.HitObject.Scale)
- });
+ HitExplosion hitExplosion = hitExplosionPool.Get();
+ hitExplosion.X = fruit.X;
+ hitExplosion.Scale = new Vector2(fruit.HitObject.Scale);
+ hitExplosion.ObjectColour = fruit.AccentColour.Value;
+ hitExplosionContainer.Add(hitExplosion);
}
}
diff --git a/osu.Game.Rulesets.Catch/UI/HitExplosion.cs b/osu.Game.Rulesets.Catch/UI/HitExplosion.cs
index 04a86f83be..24ca778248 100644
--- a/osu.Game.Rulesets.Catch/UI/HitExplosion.cs
+++ b/osu.Game.Rulesets.Catch/UI/HitExplosion.cs
@@ -5,35 +5,43 @@ using osu.Framework.Extensions.Color4Extensions;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Effects;
+using osu.Framework.Graphics.Pooling;
using osu.Framework.Utils;
-using osu.Game.Rulesets.Catch.Objects.Drawables;
using osuTK;
using osuTK.Graphics;
namespace osu.Game.Rulesets.Catch.UI
{
- public class HitExplosion : CompositeDrawable
+ public class HitExplosion : PoolableDrawable
{
- private readonly CircularContainer largeFaint;
+ private Color4 objectColour;
- public HitExplosion(DrawableCatchHitObject fruit)
+ public Color4 ObjectColour
+ {
+ get => objectColour;
+ set
+ {
+ if (objectColour == value) return;
+
+ objectColour = value;
+ onColourChanged();
+ }
+ }
+
+ private readonly CircularContainer largeFaint;
+ private readonly CircularContainer smallFaint;
+ private readonly CircularContainer directionalGlow1;
+ private readonly CircularContainer directionalGlow2;
+
+ public HitExplosion()
{
Size = new Vector2(20);
Anchor = Anchor.TopCentre;
Origin = Anchor.BottomCentre;
- Color4 objectColour = fruit.AccentColour.Value;
-
// scale roughly in-line with visual appearance of notes
-
- const float angle_variangle = 15; // should be less than 45
-
- const float roundness = 100;
-
const float initial_height = 10;
- var colour = Interpolation.ValueAt(0.4f, objectColour, Color4.White, 0, 1);
-
InternalChildren = new Drawable[]
{
largeFaint = new CircularContainer
@@ -42,33 +50,17 @@ namespace osu.Game.Rulesets.Catch.UI
Origin = Anchor.Centre,
RelativeSizeAxes = Axes.Both,
Masking = true,
- // we want our size to be very small so the glow dominates it.
- Size = new Vector2(0.8f),
Blending = BlendingParameters.Additive,
- EdgeEffect = new EdgeEffectParameters
- {
- Type = EdgeEffectType.Glow,
- Colour = Interpolation.ValueAt(0.1f, objectColour, Color4.White, 0, 1).Opacity(0.3f),
- Roundness = 160,
- Radius = 200,
- },
},
- new CircularContainer
+ smallFaint = new CircularContainer
{
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
RelativeSizeAxes = Axes.Both,
Masking = true,
Blending = BlendingParameters.Additive,
- EdgeEffect = new EdgeEffectParameters
- {
- Type = EdgeEffectType.Glow,
- Colour = Interpolation.ValueAt(0.6f, objectColour, Color4.White, 0, 1),
- Roundness = 20,
- Radius = 50,
- },
},
- new CircularContainer
+ directionalGlow1 = new CircularContainer
{
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
@@ -76,16 +68,8 @@ namespace osu.Game.Rulesets.Catch.UI
Masking = true,
Size = new Vector2(0.01f, initial_height),
Blending = BlendingParameters.Additive,
- Rotation = RNG.NextSingle(-angle_variangle, angle_variangle),
- EdgeEffect = new EdgeEffectParameters
- {
- Type = EdgeEffectType.Glow,
- Colour = colour,
- Roundness = roundness,
- Radius = 40,
- },
},
- new CircularContainer
+ directionalGlow2 = new CircularContainer
{
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
@@ -93,30 +77,57 @@ namespace osu.Game.Rulesets.Catch.UI
Masking = true,
Size = new Vector2(0.01f, initial_height),
Blending = BlendingParameters.Additive,
- Rotation = RNG.NextSingle(-angle_variangle, angle_variangle),
- EdgeEffect = new EdgeEffectParameters
- {
- Type = EdgeEffectType.Glow,
- Colour = colour,
- Roundness = roundness,
- Radius = 40,
- },
}
};
}
- protected override void LoadComplete()
+ protected override void PrepareForUse()
{
- base.LoadComplete();
+ base.PrepareForUse();
const double duration = 400;
+ // we want our size to be very small so the glow dominates it.
+ largeFaint.Size = new Vector2(0.8f);
largeFaint
.ResizeTo(largeFaint.Size * new Vector2(5, 1), duration, Easing.OutQuint)
.FadeOut(duration * 2);
+ const float angle_variangle = 15; // should be less than 45
+ directionalGlow1.Rotation = RNG.NextSingle(-angle_variangle, angle_variangle);
+ directionalGlow2.Rotation = RNG.NextSingle(-angle_variangle, angle_variangle);
+
this.FadeInFromZero(50).Then().FadeOut(duration, Easing.Out);
Expire(true);
}
+
+ private void onColourChanged()
+ {
+ const float roundness = 100;
+
+ largeFaint.EdgeEffect = new EdgeEffectParameters
+ {
+ Type = EdgeEffectType.Glow,
+ Colour = Interpolation.ValueAt(0.1f, objectColour, Color4.White, 0, 1).Opacity(0.3f),
+ Roundness = 160,
+ Radius = 200,
+ };
+
+ smallFaint.EdgeEffect = new EdgeEffectParameters
+ {
+ Type = EdgeEffectType.Glow,
+ Colour = Interpolation.ValueAt(0.6f, objectColour, Color4.White, 0, 1),
+ Roundness = 20,
+ Radius = 50,
+ };
+
+ directionalGlow1.EdgeEffect = directionalGlow2.EdgeEffect = new EdgeEffectParameters
+ {
+ Type = EdgeEffectType.Glow,
+ Colour = Interpolation.ValueAt(0.4f, objectColour, Color4.White, 0, 1),
+ Roundness = roundness,
+ Radius = 40,
+ };
+ }
}
}
diff --git a/osu.Game.Rulesets.Osu.Tests/Mods/OsuModTestScene.cs b/osu.Game.Rulesets.Osu.Tests/Mods/OsuModTestScene.cs
index 7697f46160..d3cb3bcf59 100644
--- a/osu.Game.Rulesets.Osu.Tests/Mods/OsuModTestScene.cs
+++ b/osu.Game.Rulesets.Osu.Tests/Mods/OsuModTestScene.cs
@@ -5,7 +5,7 @@ using osu.Game.Tests.Visual;
namespace osu.Game.Rulesets.Osu.Tests.Mods
{
- public class OsuModTestScene : ModTestScene
+ public abstract class OsuModTestScene : ModTestScene
{
protected override Ruleset CreatePlayerRuleset() => new OsuRuleset();
}
diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs
index 14bcefde0a..611a0337a4 100644
--- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs
+++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs
@@ -255,7 +255,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
if (userTriggered || Time.Current < HitObject.EndTime)
return;
- ApplyResult(r => r.Type = r.Judgement.MaxResult);
+ ApplyResult(r => r.Type = NestedHitObjects.Any(h => h.Result.IsHit) ? r.Judgement.MaxResult : r.Judgement.MinResult);
}
public override void PlaySamples()
diff --git a/osu.Game.Tests/Visual/SongSelect/TestScenePlaySongSelect.cs b/osu.Game.Tests/Visual/SongSelect/TestScenePlaySongSelect.cs
index aa531ba106..35c6d62cb7 100644
--- a/osu.Game.Tests/Visual/SongSelect/TestScenePlaySongSelect.cs
+++ b/osu.Game.Tests/Visual/SongSelect/TestScenePlaySongSelect.cs
@@ -643,6 +643,55 @@ namespace osu.Game.Tests.Visual.SongSelect
AddAssert("Selected beatmap correct", () => songSelect.Carousel.SelectedBeatmap == filteredBeatmap);
}
+ [Test]
+ public void TestChangingRulesetOnMultiRulesetBeatmap()
+ {
+ int changeCount = 0;
+
+ AddStep("change convert setting", () => config.Set(OsuSetting.ShowConvertedBeatmaps, false));
+ AddStep("bind beatmap changed", () =>
+ {
+ Beatmap.ValueChanged += onChange;
+ changeCount = 0;
+ });
+
+ changeRuleset(0);
+
+ createSongSelect();
+
+ AddStep("import multi-ruleset map", () =>
+ {
+ var usableRulesets = rulesets.AvailableRulesets.Where(r => r.ID != 2).ToArray();
+ manager.Import(createTestBeatmapSet(usableRulesets)).Wait();
+ });
+
+ int previousSetID = 0;
+
+ AddUntilStep("wait for selection", () => !Beatmap.IsDefault);
+
+ AddStep("record set ID", () => previousSetID = Beatmap.Value.BeatmapSetInfo.ID);
+ AddAssert("selection changed once", () => changeCount == 1);
+
+ AddAssert("Check ruleset is osu!", () => Ruleset.Value.ID == 0);
+
+ changeRuleset(3);
+
+ AddUntilStep("Check ruleset changed to mania", () => Ruleset.Value.ID == 3);
+
+ AddUntilStep("selection changed", () => changeCount > 1);
+
+ AddAssert("Selected beatmap still same set", () => Beatmap.Value.BeatmapSetInfo.ID == previousSetID);
+ AddAssert("Selected beatmap is mania", () => Beatmap.Value.BeatmapInfo.Ruleset.ID == 3);
+
+ AddAssert("selection changed only fired twice", () => changeCount == 2);
+
+ AddStep("unbind beatmap changed", () => Beatmap.ValueChanged -= onChange);
+ AddStep("change convert setting", () => config.Set(OsuSetting.ShowConvertedBeatmaps, true));
+
+ // ReSharper disable once AccessToModifiedClosure
+ void onChange(ValueChangedEvent valueChangedEvent) => changeCount++;
+ }
+
[Test]
public void TestDifficultyIconSelectingForDifferentRuleset()
{
diff --git a/osu.Game.Tournament/IPC/FileBasedIPC.cs b/osu.Game.Tournament/IPC/FileBasedIPC.cs
index 999ce61ac8..71417d1cc6 100644
--- a/osu.Game.Tournament/IPC/FileBasedIPC.cs
+++ b/osu.Game.Tournament/IPC/FileBasedIPC.cs
@@ -243,7 +243,7 @@ namespace osu.Game.Tournament.IPC
string stableInstallPath;
using (RegistryKey key = Registry.ClassesRoot.OpenSubKey("osu"))
- stableInstallPath = key?.OpenSubKey(@"shell\open\command")?.GetValue(string.Empty).ToString().Split('"')[1].Replace("osu!.exe", "");
+ stableInstallPath = key?.OpenSubKey(@"shell\open\command")?.GetValue(string.Empty)?.ToString()?.Split('"')[1].Replace("osu!.exe", "");
if (ipcFileExistsInDirectory(stableInstallPath))
return stableInstallPath;
diff --git a/osu.Game.Tournament/osu.Game.Tournament.csproj b/osu.Game.Tournament/osu.Game.Tournament.csproj
index 9cce40c9d3..b049542bb0 100644
--- a/osu.Game.Tournament/osu.Game.Tournament.csproj
+++ b/osu.Game.Tournament/osu.Game.Tournament.csproj
@@ -9,6 +9,6 @@
-
+
\ No newline at end of file
diff --git a/osu.Game/Configuration/OsuConfigManager.cs b/osu.Game/Configuration/OsuConfigManager.cs
index 89a6ee8b07..a07e446d2e 100644
--- a/osu.Game/Configuration/OsuConfigManager.cs
+++ b/osu.Game/Configuration/OsuConfigManager.cs
@@ -184,7 +184,7 @@ namespace osu.Game.Configuration
return new TrackedSettings
{
new TrackedSetting(OsuSetting.MouseDisableButtons, v => new SettingDescription(!v, "gameplay mouse buttons", v ? "disabled" : "enabled", LookupKeyBindings(GlobalAction.ToggleGameplayMouseButtons))),
- new TrackedSetting(OsuSetting.HUDVisibilityMode, m => new SettingDescription(m, "HUD Visibility", m.GetDescription(), $"cycle: shift-tab quick view: {LookupKeyBindings(GlobalAction.HoldForHUD)}")),
+ new TrackedSetting(OsuSetting.HUDVisibilityMode, m => new SettingDescription(m, "HUD Visibility", m.GetDescription(), $"cycle: {LookupKeyBindings(GlobalAction.ToggleInGameInterface)} quick view: {LookupKeyBindings(GlobalAction.HoldForHUD)}")),
new TrackedSetting(OsuSetting.Scaling, m => new SettingDescription(m, "scaling", m.GetDescription())),
new TrackedSetting(OsuSetting.Skin, m =>
{
diff --git a/osu.Game/Input/Bindings/GlobalActionContainer.cs b/osu.Game/Input/Bindings/GlobalActionContainer.cs
index 74eb2b0126..f4a4813b94 100644
--- a/osu.Game/Input/Bindings/GlobalActionContainer.cs
+++ b/osu.Game/Input/Bindings/GlobalActionContainer.cs
@@ -68,6 +68,7 @@ namespace osu.Game.Input.Bindings
new KeyBinding(new[] { InputKey.Control, InputKey.Tilde }, GlobalAction.QuickExit),
new KeyBinding(new[] { InputKey.Control, InputKey.Plus }, GlobalAction.IncreaseScrollSpeed),
new KeyBinding(new[] { InputKey.Control, InputKey.Minus }, GlobalAction.DecreaseScrollSpeed),
+ new KeyBinding(new[] { InputKey.Shift, InputKey.Tab }, GlobalAction.ToggleInGameInterface),
new KeyBinding(InputKey.MouseMiddle, GlobalAction.PauseGameplay),
new KeyBinding(InputKey.Space, GlobalAction.TogglePauseReplay),
new KeyBinding(InputKey.Control, GlobalAction.HoldForHUD),
@@ -200,5 +201,8 @@ namespace osu.Game.Input.Bindings
[Description("Pause / resume replay")]
TogglePauseReplay,
+
+ [Description("Toggle in-game interface")]
+ ToggleInGameInterface,
}
}
diff --git a/osu.Game/Overlays/Settings/Sections/Graphics/LayoutSettings.cs b/osu.Game/Overlays/Settings/Sections/Graphics/LayoutSettings.cs
index 14b8dbfac0..62dc1dc806 100644
--- a/osu.Game/Overlays/Settings/Sections/Graphics/LayoutSettings.cs
+++ b/osu.Game/Overlays/Settings/Sections/Graphics/LayoutSettings.cs
@@ -208,7 +208,7 @@ namespace osu.Game.Overlays.Settings.Sections.Graphics
private IReadOnlyList getResolutions()
{
var resolutions = new List { new Size(9999, 9999) };
- var currentDisplay = game.Window?.CurrentDisplay.Value;
+ var currentDisplay = game.Window?.CurrentDisplayBindable.Value;
if (currentDisplay != null)
{
diff --git a/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineTickDisplay.cs b/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineTickDisplay.cs
index 724256af8b..fb11b859a7 100644
--- a/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineTickDisplay.cs
+++ b/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineTickDisplay.cs
@@ -25,6 +25,9 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline
[Resolved]
private BindableBeatDivisor beatDivisor { get; set; }
+ [Resolved(CanBeNull = true)]
+ private IEditorChangeHandler changeHandler { get; set; }
+
[Resolved]
private OsuColour colours { get; set; }
@@ -38,7 +41,16 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline
[BackgroundDependencyLoader]
private void load()
{
- beatDivisor.BindValueChanged(_ => tickCache.Invalidate());
+ beatDivisor.BindValueChanged(_ => invalidateTicks());
+
+ if (changeHandler != null)
+ // currently this is the best way to handle any kind of timing changes.
+ changeHandler.OnStateChange += invalidateTicks;
+ }
+
+ private void invalidateTicks()
+ {
+ tickCache.Invalidate();
}
///
@@ -165,5 +177,13 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline
return point;
}
}
+
+ protected override void Dispose(bool isDisposing)
+ {
+ base.Dispose(isDisposing);
+
+ if (changeHandler != null)
+ changeHandler.OnStateChange -= invalidateTicks;
+ }
}
}
diff --git a/osu.Game/Screens/Edit/Setup/DifficultySection.cs b/osu.Game/Screens/Edit/Setup/DifficultySection.cs
index aa1d57db31..897ddc6955 100644
--- a/osu.Game/Screens/Edit/Setup/DifficultySection.cs
+++ b/osu.Game/Screens/Edit/Setup/DifficultySection.cs
@@ -37,8 +37,8 @@ namespace osu.Game.Screens.Edit.Setup
Current = new BindableFloat(Beatmap.Value.BeatmapInfo.BaseDifficulty.CircleSize)
{
Default = BeatmapDifficulty.DEFAULT_DIFFICULTY,
- MinValue = 2,
- MaxValue = 7,
+ MinValue = 0,
+ MaxValue = 10,
Precision = 0.1f,
}
},
diff --git a/osu.Game/Screens/Play/HUDOverlay.cs b/osu.Game/Screens/Play/HUDOverlay.cs
index e83dded075..50195d571c 100644
--- a/osu.Game/Screens/Play/HUDOverlay.cs
+++ b/osu.Game/Screens/Play/HUDOverlay.cs
@@ -9,7 +9,6 @@ using osu.Framework.Extensions.IEnumerableExtensions;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Framework.Input.Bindings;
-using osu.Framework.Input.Events;
using osu.Game.Configuration;
using osu.Game.Input.Bindings;
using osu.Game.Overlays;
@@ -19,7 +18,6 @@ using osu.Game.Rulesets.Scoring;
using osu.Game.Rulesets.UI;
using osu.Game.Screens.Play.HUD;
using osuTK;
-using osuTK.Input;
namespace osu.Game.Screens.Play
{
@@ -181,7 +179,7 @@ namespace osu.Game.Screens.Play
notificationOverlay?.Post(new SimpleNotification
{
- Text = @"The score overlay is currently disabled. You can toggle this by pressing Shift+Tab."
+ Text = $"The score overlay is currently disabled. You can toggle this by pressing {config.LookupKeyBindings(GlobalAction.ToggleInGameInterface)}."
});
}
@@ -273,37 +271,6 @@ namespace osu.Game.Screens.Play
Progress.BindDrawableRuleset(drawableRuleset);
}
- protected override bool OnKeyDown(KeyDownEvent e)
- {
- if (e.Repeat) return false;
-
- if (e.ShiftPressed)
- {
- switch (e.Key)
- {
- case Key.Tab:
- switch (configVisibilityMode.Value)
- {
- case HUDVisibilityMode.Never:
- configVisibilityMode.Value = HUDVisibilityMode.HideDuringGameplay;
- break;
-
- case HUDVisibilityMode.HideDuringGameplay:
- configVisibilityMode.Value = HUDVisibilityMode.Always;
- break;
-
- case HUDVisibilityMode.Always:
- configVisibilityMode.Value = HUDVisibilityMode.Never;
- break;
- }
-
- return true;
- }
- }
-
- return base.OnKeyDown(e);
- }
-
protected virtual SkinnableAccuracyCounter CreateAccuracyCounter() => new SkinnableAccuracyCounter();
protected virtual SkinnableScoreCounter CreateScoreCounter() => new SkinnableScoreCounter();
@@ -377,6 +344,24 @@ namespace osu.Game.Screens.Play
holdingForHUD = true;
updateVisibility();
return true;
+
+ case GlobalAction.ToggleInGameInterface:
+ switch (configVisibilityMode.Value)
+ {
+ case HUDVisibilityMode.Never:
+ configVisibilityMode.Value = HUDVisibilityMode.HideDuringGameplay;
+ break;
+
+ case HUDVisibilityMode.HideDuringGameplay:
+ configVisibilityMode.Value = HUDVisibilityMode.Always;
+ break;
+
+ case HUDVisibilityMode.Always:
+ configVisibilityMode.Value = HUDVisibilityMode.Never;
+ break;
+ }
+
+ return true;
}
return false;
diff --git a/osu.Game/Screens/Select/SongSelect.cs b/osu.Game/Screens/Select/SongSelect.cs
index b55c0694ef..f32011a27a 100644
--- a/osu.Game/Screens/Select/SongSelect.cs
+++ b/osu.Game/Screens/Select/SongSelect.cs
@@ -376,7 +376,7 @@ namespace osu.Game.Screens.Select
if (selectionChangedDebounce?.Completed == false)
{
selectionChangedDebounce.RunTask();
- selectionChangedDebounce.Cancel(); // cancel the already scheduled task.
+ selectionChangedDebounce?.Cancel(); // cancel the already scheduled task.
selectionChangedDebounce = null;
}
@@ -465,19 +465,30 @@ namespace osu.Game.Screens.Select
void run()
{
+ // clear pending task immediately to track any potential nested debounce operation.
+ selectionChangedDebounce = null;
+
Logger.Log($"updating selection with beatmap:{beatmap?.ID.ToString() ?? "null"} ruleset:{ruleset?.ID.ToString() ?? "null"}");
if (transferRulesetValue())
{
Mods.Value = Array.Empty();
- // transferRulesetValue() may trigger a refilter. If the current selection does not match the new ruleset, we want to switch away from it.
+ // transferRulesetValue() may trigger a re-filter. If the current selection does not match the new ruleset, we want to switch away from it.
// The default logic on WorkingBeatmap change is to switch to a matching ruleset (see workingBeatmapChanged()), but we don't want that here.
// We perform an early selection attempt and clear out the beatmap selection to avoid a second ruleset change (revert).
if (beatmap != null && !Carousel.SelectBeatmap(beatmap, false))
beatmap = null;
}
+ if (selectionChangedDebounce != null)
+ {
+ // a new nested operation was started; switch to it for further selection.
+ // this avoids having two separate debounces trigger from the same source.
+ selectionChangedDebounce.RunTask();
+ return;
+ }
+
// We may be arriving here due to another component changing the bindable Beatmap.
// In these cases, the other component has already loaded the beatmap, so we don't need to do so again.
if (!EqualityComparer.Default.Equals(beatmap, Beatmap.Value.BeatmapInfo))
diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj
index e201383d51..88af0e2138 100644
--- a/osu.Game/osu.Game.csproj
+++ b/osu.Game/osu.Game.csproj
@@ -26,7 +26,7 @@
-
+
diff --git a/osu.iOS.props b/osu.iOS.props
index e5f7581404..06b0ec8a13 100644
--- a/osu.iOS.props
+++ b/osu.iOS.props
@@ -70,7 +70,7 @@
-
+
@@ -88,7 +88,7 @@
-
+