From 2201e9b4ae00154d14a4b0ccb45b881550c7bdfb Mon Sep 17 00:00:00 2001 From: Fire937 Date: Thu, 9 Apr 2020 18:12:15 +0200 Subject: [PATCH 1/6] Add stereo shifted hitsound playback support There is now a setting in the general settings called "Positional hitsounds". If the setting is enabled, the hitsounds playback will be shifted according to their position on the beatmap. --- osu.Game/Configuration/OsuConfigManager.cs | 2 ++ .../Sections/Gameplay/GeneralSettings.cs | 5 ++++ .../Objects/Drawables/DrawableHitObject.cs | 26 ++++++++++++++++++- 3 files changed, 32 insertions(+), 1 deletion(-) diff --git a/osu.Game/Configuration/OsuConfigManager.cs b/osu.Game/Configuration/OsuConfigManager.cs index 41f6747b74..ab5a652a94 100644 --- a/osu.Game/Configuration/OsuConfigManager.cs +++ b/osu.Game/Configuration/OsuConfigManager.cs @@ -88,6 +88,7 @@ namespace osu.Game.Configuration Set(OsuSetting.ShowProgressGraph, true); Set(OsuSetting.ShowHealthDisplayWhenCantFail, true); Set(OsuSetting.KeyOverlay, false); + Set(OsuSetting.PositionalHitSounds, true); Set(OsuSetting.ScoreMeter, ScoreMeterType.HitErrorBoth); Set(OsuSetting.FloatingComments, false); @@ -176,6 +177,7 @@ namespace osu.Game.Configuration LightenDuringBreaks, ShowStoryboard, KeyOverlay, + PositionalHitSounds, ScoreMeter, FloatingComments, ShowInterface, diff --git a/osu.Game/Overlays/Settings/Sections/Gameplay/GeneralSettings.cs b/osu.Game/Overlays/Settings/Sections/Gameplay/GeneralSettings.cs index 2d2cd42213..ef03c0622a 100644 --- a/osu.Game/Overlays/Settings/Sections/Gameplay/GeneralSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Gameplay/GeneralSettings.cs @@ -57,6 +57,11 @@ namespace osu.Game.Overlays.Settings.Sections.Gameplay LabelText = "Always show key overlay", Bindable = config.GetBindable(OsuSetting.KeyOverlay) }, + new SettingsCheckbox + { + LabelText = "Positional hitsounds", + Bindable = config.GetBindable(OsuSetting.PositionalHitSounds) + }, new SettingsEnumDropdown { LabelText = "Score meter type", diff --git a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs index 0011faefbb..ed9efba89f 100644 --- a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs +++ b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs @@ -12,11 +12,13 @@ using osu.Framework.Extensions.TypeExtensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Primitives; using osu.Framework.Threading; +using osu.Framework.Audio; using osu.Game.Audio; using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Objects.Types; using osu.Game.Rulesets.Scoring; using osu.Game.Skinning; +using osu.Game.Configuration; using osuTK.Graphics; namespace osu.Game.Rulesets.Objects.Drawables @@ -31,6 +33,11 @@ namespace osu.Game.Rulesets.Objects.Drawables /// public readonly Bindable AccentColour = new Bindable(Color4.Gray); + /// + /// The stereo balance of the samples if the Positional hitsounds setting is set. + /// + private readonly BindableDouble positionalSoundAdjustment = new BindableDouble(); + protected SkinnableSound Samples { get; private set; } protected virtual IEnumerable GetSamples() => HitObject.Samples; @@ -84,8 +91,14 @@ namespace osu.Game.Rulesets.Objects.Drawables /// public JudgementResult Result { get; private set; } + /// + /// The stereo balance of the samples played if Positional hitsounds is set. + /// + protected virtual float PositionalSound => (HitObject is IHasXPosition position) ? (position.X / 512f - 0.5f) * 0.8f : 0; + private BindableList samplesBindable; private Bindable startTimeBindable; + private Bindable userPositionalHitSounds; private Bindable comboIndexBindable; public override bool RemoveWhenNotAlive => false; @@ -101,10 +114,11 @@ namespace osu.Game.Rulesets.Objects.Drawables protected DrawableHitObject([NotNull] HitObject hitObject) { HitObject = hitObject ?? throw new ArgumentNullException(nameof(hitObject)); + positionalSoundAdjustment.Value = PositionalSound; } [BackgroundDependencyLoader] - private void load() + private void load(OsuConfigManager config) { var judgement = HitObject.CreateJudgement(); @@ -113,6 +127,16 @@ namespace osu.Game.Rulesets.Objects.Drawables throw new InvalidOperationException($"{GetType().ReadableName()} must provide a {nameof(JudgementResult)} through {nameof(CreateResult)}."); loadSamples(); + + userPositionalHitSounds = config.GetBindable(OsuSetting.PositionalHitSounds); + userPositionalHitSounds.BindValueChanged(positional => + { + if (positional.NewValue) + Samples?.AddAdjustment(AdjustableProperty.Balance, positionalSoundAdjustment); + else + Samples?.RemoveAdjustment(AdjustableProperty.Balance, positionalSoundAdjustment); + }); + userPositionalHitSounds.TriggerChange(); } protected override void LoadComplete() From c17e47026623afde64aaf11b8334b5ebcd221696 Mon Sep 17 00:00:00 2001 From: Fire937 Date: Fri, 10 Apr 2020 00:01:35 +0200 Subject: [PATCH 2/6] Fix PositionalSound calculation implementation The position used to calculate the stereo balance is now the position of the drawable (as opposed to the position specified in the beatmap file previously). --- osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs index ed9efba89f..30a9106ddc 100644 --- a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs +++ b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs @@ -94,7 +94,7 @@ namespace osu.Game.Rulesets.Objects.Drawables /// /// The stereo balance of the samples played if Positional hitsounds is set. /// - protected virtual float PositionalSound => (HitObject is IHasXPosition position) ? (position.X / 512f - 0.5f) * 0.8f : 0; + protected virtual float PositionalSound => (Position.X / 512f - 0.5f) * 0.8f; private BindableList samplesBindable; private Bindable startTimeBindable; @@ -114,7 +114,6 @@ namespace osu.Game.Rulesets.Objects.Drawables protected DrawableHitObject([NotNull] HitObject hitObject) { HitObject = hitObject ?? throw new ArgumentNullException(nameof(hitObject)); - positionalSoundAdjustment.Value = PositionalSound; } [BackgroundDependencyLoader] @@ -377,7 +376,11 @@ namespace osu.Game.Rulesets.Objects.Drawables /// Plays all the hit sounds for this . /// This is invoked automatically when this is hit. /// - public virtual void PlaySamples() => Samples?.Play(); + public virtual void PlaySamples() + { + positionalSoundAdjustment.Value = PositionalSound; + Samples?.Play(); + } protected override void Update() { From f274ec297ce23e79eff1d2a64f745e1396b0c280 Mon Sep 17 00:00:00 2001 From: Fire937 Date: Sun, 12 Apr 2020 01:33:25 +0200 Subject: [PATCH 3/6] Add positional sound support for all rulesets The SamplePlaybackBalance is calculated in a way that the balance remains between -0.4 and 0.4. Positional sound is not supported in osu!taiko. --- .../Drawables/DrawableCatchHitObject.cs | 2 ++ .../Drawables/DrawableManiaHitObject.cs | 16 ++++++++++++ .../Objects/Drawables/DrawableOsuHitObject.cs | 2 ++ .../Objects/Drawables/DrawableHitObject.cs | 26 ++++++------------- 4 files changed, 28 insertions(+), 18 deletions(-) diff --git a/osu.Game.Rulesets.Catch/Objects/Drawables/DrawableCatchHitObject.cs b/osu.Game.Rulesets.Catch/Objects/Drawables/DrawableCatchHitObject.cs index 6844be5941..e726d6eff5 100644 --- a/osu.Game.Rulesets.Catch/Objects/Drawables/DrawableCatchHitObject.cs +++ b/osu.Game.Rulesets.Catch/Objects/Drawables/DrawableCatchHitObject.cs @@ -70,6 +70,8 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawables public float DisplayRadius => DrawSize.X / 2 * Scale.X * HitObject.Scale; + protected override float SamplePlaybackBalance => 0.8f * HitObject.X - 0.4f; + protected DrawableCatchHitObject(CatchHitObject hitObject) : base(hitObject) { diff --git a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableManiaHitObject.cs b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableManiaHitObject.cs index 5bfa07bd14..76e9695855 100644 --- a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableManiaHitObject.cs +++ b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableManiaHitObject.cs @@ -5,8 +5,10 @@ using JetBrains.Annotations; using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.UI.Scrolling; +using osu.Game.Rulesets.Mania.UI; namespace osu.Game.Rulesets.Mania.Objects.Drawables { @@ -24,6 +26,20 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables protected readonly IBindable Direction = new Bindable(); + protected override float SamplePlaybackBalance + { + get + { + CompositeDrawable stage = this; + while (!(stage is Stage)) + stage = stage.Parent; + + var columnCount = ((Stage)stage).Columns.Count; + var columnIndex = HitObject.Column; + return 0.8f * columnIndex / (columnCount - 1) - 0.4f; + } + } + protected DrawableManiaHitObject(ManiaHitObject hitObject) : base(hitObject) { diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuHitObject.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuHitObject.cs index a677cb6a72..c5a4491b2d 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuHitObject.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuHitObject.cs @@ -16,6 +16,8 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables // Must be set to update IsHovered as it's used in relax mdo to detect osu hit objects. public override bool HandlePositionalInput => true; + protected override float SamplePlaybackBalance => (HitObject.X / 512f - 0.5f) * 0.8f; + protected DrawableOsuHitObject(OsuHitObject hitObject) : base(hitObject) { diff --git a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs index 30a9106ddc..ef32dc1560 100644 --- a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs +++ b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs @@ -33,11 +33,6 @@ namespace osu.Game.Rulesets.Objects.Drawables /// public readonly Bindable AccentColour = new Bindable(Color4.Gray); - /// - /// The stereo balance of the samples if the Positional hitsounds setting is set. - /// - private readonly BindableDouble positionalSoundAdjustment = new BindableDouble(); - protected SkinnableSound Samples { get; private set; } protected virtual IEnumerable GetSamples() => HitObject.Samples; @@ -94,7 +89,9 @@ namespace osu.Game.Rulesets.Objects.Drawables /// /// The stereo balance of the samples played if Positional hitsounds is set. /// - protected virtual float PositionalSound => (Position.X / 512f - 0.5f) * 0.8f; + protected virtual float SamplePlaybackBalance => 0; + + private readonly BindableDouble samplePlaybackBalanceAdjustment = new BindableDouble(); private BindableList samplesBindable; private Bindable startTimeBindable; @@ -119,6 +116,7 @@ namespace osu.Game.Rulesets.Objects.Drawables [BackgroundDependencyLoader] private void load(OsuConfigManager config) { + userPositionalHitSounds = config.GetBindable(OsuSetting.PositionalHitSounds); var judgement = HitObject.CreateJudgement(); Result = CreateResult(judgement); @@ -126,16 +124,6 @@ namespace osu.Game.Rulesets.Objects.Drawables throw new InvalidOperationException($"{GetType().ReadableName()} must provide a {nameof(JudgementResult)} through {nameof(CreateResult)}."); loadSamples(); - - userPositionalHitSounds = config.GetBindable(OsuSetting.PositionalHitSounds); - userPositionalHitSounds.BindValueChanged(positional => - { - if (positional.NewValue) - Samples?.AddAdjustment(AdjustableProperty.Balance, positionalSoundAdjustment); - else - Samples?.RemoveAdjustment(AdjustableProperty.Balance, positionalSoundAdjustment); - }); - userPositionalHitSounds.TriggerChange(); } protected override void LoadComplete() @@ -179,7 +167,9 @@ namespace osu.Game.Rulesets.Objects.Drawables + $" This is an indication that {nameof(HitObject.ApplyDefaults)} has not been invoked on {this}."); } - AddInternal(Samples = new SkinnableSound(samples.Select(s => HitObject.SampleControlPoint.ApplyTo(s)))); + Samples = new SkinnableSound(samples.Select(s => HitObject.SampleControlPoint.ApplyTo(s))); + Samples.AddAdjustment(AdjustableProperty.Balance, samplePlaybackBalanceAdjustment); + AddInternal(Samples); } private void onDefaultsApplied() => apply(HitObject); @@ -378,7 +368,7 @@ namespace osu.Game.Rulesets.Objects.Drawables /// public virtual void PlaySamples() { - positionalSoundAdjustment.Value = PositionalSound; + samplePlaybackBalanceAdjustment.Value = userPositionalHitSounds.Value ? SamplePlaybackBalance : 0; Samples?.Play(); } From 65b96079a05f46de50dd1f0f191bed8389cdf62f Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 13 Apr 2020 13:00:03 +0900 Subject: [PATCH 4/6] Move dampening to base implementation and change range to 0..1 --- .../Objects/Drawables/DrawableCatchHitObject.cs | 2 +- .../Objects/Drawables/DrawableManiaHitObject.cs | 2 +- .../Objects/Drawables/DrawableOsuHitObject.cs | 3 ++- .../Objects/Drawables/DrawableHitObject.cs | 16 +++++++++++----- 4 files changed, 15 insertions(+), 8 deletions(-) diff --git a/osu.Game.Rulesets.Catch/Objects/Drawables/DrawableCatchHitObject.cs b/osu.Game.Rulesets.Catch/Objects/Drawables/DrawableCatchHitObject.cs index e726d6eff5..b12cdd4ccb 100644 --- a/osu.Game.Rulesets.Catch/Objects/Drawables/DrawableCatchHitObject.cs +++ b/osu.Game.Rulesets.Catch/Objects/Drawables/DrawableCatchHitObject.cs @@ -70,7 +70,7 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawables public float DisplayRadius => DrawSize.X / 2 * Scale.X * HitObject.Scale; - protected override float SamplePlaybackBalance => 0.8f * HitObject.X - 0.4f; + protected override float SamplePlaybackPosition => HitObject.X; protected DrawableCatchHitObject(CatchHitObject hitObject) : base(hitObject) diff --git a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableManiaHitObject.cs b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableManiaHitObject.cs index 76e9695855..ce56fd222c 100644 --- a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableManiaHitObject.cs +++ b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableManiaHitObject.cs @@ -26,7 +26,7 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables protected readonly IBindable Direction = new Bindable(); - protected override float SamplePlaybackBalance + protected override float SamplePlaybackPosition { get { diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuHitObject.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuHitObject.cs index 068d666c8e..8308c0c576 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuHitObject.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuHitObject.cs @@ -7,6 +7,7 @@ using osu.Framework.Graphics; using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Osu.Judgements; using osu.Game.Graphics.Containers; +using osu.Game.Rulesets.Osu.UI; using osu.Game.Rulesets.Scoring; namespace osu.Game.Rulesets.Osu.Objects.Drawables @@ -18,7 +19,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables // Must be set to update IsHovered as it's used in relax mdo to detect osu hit objects. public override bool HandlePositionalInput => true; - protected override float SamplePlaybackBalance => (HitObject.X / 512f - 0.5f) * 0.8f; + protected override float SamplePlaybackPosition => HitObject.X / OsuPlayfield.BASE_SIZE.X; /// /// Whether this can be hit. diff --git a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs index d6e231424b..b14927bcd5 100644 --- a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs +++ b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs @@ -87,11 +87,15 @@ namespace osu.Game.Rulesets.Objects.Drawables public JudgementResult Result { get; private set; } /// - /// The stereo balance of the samples played if Positional hitsounds is set. + /// The relative X position of this hit object for sample playback balance adjustment. /// - protected virtual float SamplePlaybackBalance => 0; + /// + /// This is a range of 0..1 (0 for far-left, 0.5 for centre, 1 for far-right). + /// Dampening is post-applied to ensure the effect is not too intense. + /// + protected virtual float SamplePlaybackPosition => 0.5f; - private readonly BindableDouble samplePlaybackBalanceAdjustment = new BindableDouble(); + private readonly BindableDouble balanceAdjust = new BindableDouble(); private BindableList samplesBindable; private Bindable startTimeBindable; @@ -168,7 +172,7 @@ namespace osu.Game.Rulesets.Objects.Drawables } Samples = new SkinnableSound(samples.Select(s => HitObject.SampleControlPoint.ApplyTo(s))); - Samples.AddAdjustment(AdjustableProperty.Balance, samplePlaybackBalanceAdjustment); + Samples.AddAdjustment(AdjustableProperty.Balance, balanceAdjust); AddInternal(Samples); } @@ -368,7 +372,9 @@ namespace osu.Game.Rulesets.Objects.Drawables /// public virtual void PlaySamples() { - samplePlaybackBalanceAdjustment.Value = userPositionalHitSounds.Value ? SamplePlaybackBalance : 0; + const float balance_adjust_amount = 0.4f; + + balanceAdjust.Value = balance_adjust_amount * (userPositionalHitSounds.Value ? SamplePlaybackPosition - 0.5f : 0); Samples?.Play(); } From cdff6060d3eccdf3ed36df6ce0d3aa26dc411a17 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 13 Apr 2020 13:01:27 +0900 Subject: [PATCH 5/6] Remove recursive hierarchy traversal for mania sample balance --- .../Objects/Drawables/DrawableManiaHitObject.cs | 16 +++++++++------- osu.Game/Rulesets/UI/Playfield.cs | 1 + 2 files changed, 10 insertions(+), 7 deletions(-) diff --git a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableManiaHitObject.cs b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableManiaHitObject.cs index ce56fd222c..a708adb493 100644 --- a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableManiaHitObject.cs +++ b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableManiaHitObject.cs @@ -5,10 +5,10 @@ using JetBrains.Annotations; using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; -using osu.Framework.Graphics.Containers; using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.UI.Scrolling; using osu.Game.Rulesets.Mania.UI; +using osu.Game.Rulesets.UI; namespace osu.Game.Rulesets.Mania.Objects.Drawables { @@ -26,17 +26,19 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables protected readonly IBindable Direction = new Bindable(); + [Resolved(canBeNull: true)] + private Playfield playfield { get; set; } + protected override float SamplePlaybackPosition { get { - CompositeDrawable stage = this; - while (!(stage is Stage)) - stage = stage.Parent; + var columns = (playfield as ManiaPlayfield)?.TotalColumns; - var columnCount = ((Stage)stage).Columns.Count; - var columnIndex = HitObject.Column; - return 0.8f * columnIndex / (columnCount - 1) - 0.4f; + if (columns == null) + return base.SamplePlaybackPosition; + + return (float)HitObject.Column / columns.Value; } } diff --git a/osu.Game/Rulesets/UI/Playfield.cs b/osu.Game/Rulesets/UI/Playfield.cs index c52183f3f2..fc6906560b 100644 --- a/osu.Game/Rulesets/UI/Playfield.cs +++ b/osu.Game/Rulesets/UI/Playfield.cs @@ -15,6 +15,7 @@ using osuTK; namespace osu.Game.Rulesets.UI { + [Cached] public abstract class Playfield : CompositeDrawable { /// From c51bad0e35e4a08d3e0e159e103884bbf709e85d Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 13 Apr 2020 13:42:21 +0900 Subject: [PATCH 6/6] Cache ManiaPlayfield instead --- .../Objects/Drawables/DrawableManiaHitObject.cs | 9 +++------ osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs | 2 ++ osu.Game/Rulesets/UI/Playfield.cs | 1 - 3 files changed, 5 insertions(+), 7 deletions(-) diff --git a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableManiaHitObject.cs b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableManiaHitObject.cs index a708adb493..88888001b4 100644 --- a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableManiaHitObject.cs +++ b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableManiaHitObject.cs @@ -8,7 +8,6 @@ using osu.Framework.Graphics; using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.UI.Scrolling; using osu.Game.Rulesets.Mania.UI; -using osu.Game.Rulesets.UI; namespace osu.Game.Rulesets.Mania.Objects.Drawables { @@ -27,18 +26,16 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables protected readonly IBindable Direction = new Bindable(); [Resolved(canBeNull: true)] - private Playfield playfield { get; set; } + private ManiaPlayfield playfield { get; set; } protected override float SamplePlaybackPosition { get { - var columns = (playfield as ManiaPlayfield)?.TotalColumns; - - if (columns == null) + if (playfield == null) return base.SamplePlaybackPosition; - return (float)HitObject.Column / columns.Value; + return (float)HitObject.Column / playfield.TotalColumns; } } diff --git a/osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs b/osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs index c2eb48b774..2dec468654 100644 --- a/osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs +++ b/osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs @@ -6,6 +6,7 @@ using osu.Framework.Graphics.Containers; using System; using System.Collections.Generic; using System.Linq; +using osu.Framework.Allocation; using osu.Game.Rulesets.Mania.Beatmaps; using osu.Game.Rulesets.Mania.Objects; using osu.Game.Rulesets.Objects.Drawables; @@ -14,6 +15,7 @@ using osuTK; namespace osu.Game.Rulesets.Mania.UI { + [Cached] public class ManiaPlayfield : ScrollingPlayfield { private readonly List stages = new List(); diff --git a/osu.Game/Rulesets/UI/Playfield.cs b/osu.Game/Rulesets/UI/Playfield.cs index fc6906560b..c52183f3f2 100644 --- a/osu.Game/Rulesets/UI/Playfield.cs +++ b/osu.Game/Rulesets/UI/Playfield.cs @@ -15,7 +15,6 @@ using osuTK; namespace osu.Game.Rulesets.UI { - [Cached] public abstract class Playfield : CompositeDrawable { ///