From 730b14b5bb102572c742b769e168c48febd9791c Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 19 Nov 2020 19:51:09 +0900 Subject: [PATCH 001/184] Add initial hit sample pooling --- osu.Game.Rulesets.Catch/Objects/Banana.cs | 13 +- osu.Game/Audio/HitSampleInfo.cs | 15 +- osu.Game/Audio/SampleInfo.cs | 15 +- .../Objects/Drawables/DrawableHitObject.cs | 12 +- .../Objects/Legacy/ConvertHitObjectParser.cs | 29 ++- osu.Game/Rulesets/UI/Playfield.cs | 38 +++- osu.Game/Skinning/PausableSkinnableSound.cs | 8 +- osu.Game/Skinning/SkinReloadableDrawable.cs | 4 +- osu.Game/Skinning/SkinnableSound.cs | 203 +++++++++++++++--- .../Drawables/DrawableStoryboardSample.cs | 4 +- 10 files changed, 283 insertions(+), 58 deletions(-) diff --git a/osu.Game.Rulesets.Catch/Objects/Banana.cs b/osu.Game.Rulesets.Catch/Objects/Banana.cs index 4ecfb7b16d..d61a88b7df 100644 --- a/osu.Game.Rulesets.Catch/Objects/Banana.cs +++ b/osu.Game.Rulesets.Catch/Objects/Banana.cs @@ -1,6 +1,7 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System; using System.Collections.Generic; using osu.Game.Audio; using osu.Game.Rulesets.Catch.Judgements; @@ -26,11 +27,17 @@ namespace osu.Game.Rulesets.Catch.Objects Samples = samples; } - private class BananaHitSampleInfo : HitSampleInfo + private class BananaHitSampleInfo : HitSampleInfo, IEquatable { - private static string[] lookupNames { get; } = { "metronomelow", "catch-banana" }; + private static readonly string[] lookup_names = { "metronomelow", "catch-banana" }; - public override IEnumerable LookupNames => lookupNames; + public override IEnumerable LookupNames => lookup_names; + + public bool Equals(BananaHitSampleInfo other) => true; + + public override bool Equals(object obj) => obj is BananaHitSampleInfo other && Equals(other); + + public override int GetHashCode() => lookup_names.GetHashCode(); } } } diff --git a/osu.Game/Audio/HitSampleInfo.cs b/osu.Game/Audio/HitSampleInfo.cs index 8efaeb3795..46f0abd7b7 100644 --- a/osu.Game/Audio/HitSampleInfo.cs +++ b/osu.Game/Audio/HitSampleInfo.cs @@ -3,6 +3,7 @@ using System; using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; namespace osu.Game.Audio { @@ -10,7 +11,7 @@ namespace osu.Game.Audio /// Describes a gameplay hit sample. /// [Serializable] - public class HitSampleInfo : ISampleInfo + public class HitSampleInfo : ISampleInfo, IEquatable { public const string HIT_WHISTLE = @"hitwhistle"; public const string HIT_FINISH = @"hitfinish"; @@ -57,5 +58,17 @@ namespace osu.Game.Audio } public HitSampleInfo Clone() => (HitSampleInfo)MemberwiseClone(); + + public bool Equals(HitSampleInfo other) + => other != null && Bank == other.Bank && Name == other.Name && Suffix == other.Suffix; + + public override bool Equals(object obj) + => obj is HitSampleInfo other && Equals(other); + + [SuppressMessage("ReSharper", "NonReadonlyMemberInGetHashCode")] // This will have to be addressed eventually + public override int GetHashCode() + { + return HashCode.Combine(Bank, Name, Suffix); + } } } diff --git a/osu.Game/Audio/SampleInfo.cs b/osu.Game/Audio/SampleInfo.cs index 240d70c418..221bc31639 100644 --- a/osu.Game/Audio/SampleInfo.cs +++ b/osu.Game/Audio/SampleInfo.cs @@ -1,14 +1,16 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System; using System.Collections.Generic; +using System.Linq; namespace osu.Game.Audio { /// /// Describes a gameplay sample. /// - public class SampleInfo : ISampleInfo + public class SampleInfo : ISampleInfo, IEquatable { private readonly string[] sampleNames; @@ -20,5 +22,16 @@ namespace osu.Game.Audio public IEnumerable LookupNames => sampleNames; public int Volume { get; } = 100; + + public override int GetHashCode() + { + return HashCode.Combine(sampleNames, Volume); + } + + public bool Equals(SampleInfo other) + => other != null && sampleNames.SequenceEqual(other.sampleNames); + + public override bool Equals(object obj) + => obj is SampleInfo other && Equals(other); } } diff --git a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs index ca49ed9e75..0d97066b35 100644 --- a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs +++ b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs @@ -10,7 +10,6 @@ using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Extensions.TypeExtensions; using osu.Framework.Graphics; -using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Primitives; using osu.Framework.Logging; using osu.Framework.Threading; @@ -139,8 +138,6 @@ namespace osu.Game.Rulesets.Objects.Drawables [Resolved(CanBeNull = true)] private IPooledHitObjectProvider pooledObjectProvider { get; set; } - private Container samplesContainer; - /// /// Creates a new . /// @@ -159,7 +156,7 @@ namespace osu.Game.Rulesets.Objects.Drawables config.BindWith(OsuSetting.PositionalHitSounds, userPositionalHitSounds); // Explicit non-virtual function call. - base.AddInternal(samplesContainer = new Container { RelativeSizeAxes = Axes.Both }); + base.AddInternal(Samples = new PausableSkinnableSound(Array.Empty())); } protected override void LoadAsyncComplete() @@ -269,6 +266,8 @@ namespace osu.Game.Rulesets.Objects.Drawables // In order to stop this needless update, the event is unbound and re-bound as late as possible in Apply(). samplesBindable.CollectionChanged -= onSamplesChanged; + Samples.Samples = Array.Empty(); + if (nestedHitObjects.IsValueCreated) { foreach (var obj in nestedHitObjects.Value) @@ -335,8 +334,7 @@ namespace osu.Game.Rulesets.Objects.Drawables /// protected virtual void LoadSamples() { - samplesContainer.Clear(); - Samples = null; + Samples.Samples = Array.Empty(); var samples = GetSamples().ToArray(); @@ -349,7 +347,7 @@ namespace osu.Game.Rulesets.Objects.Drawables + $" This is an indication that {nameof(HitObject.ApplyDefaults)} has not been invoked on {this}."); } - samplesContainer.Add(Samples = new PausableSkinnableSound(samples.Select(s => HitObject.SampleControlPoint.ApplyTo(s)))); + Samples.Samples = samples.Select(s => HitObject.SampleControlPoint.ApplyTo(s)).Cast().ToArray(); } private void onSamplesChanged(object sender, NotifyCollectionChangedEventArgs e) => LoadSamples(); diff --git a/osu.Game/Rulesets/Objects/Legacy/ConvertHitObjectParser.cs b/osu.Game/Rulesets/Objects/Legacy/ConvertHitObjectParser.cs index 44b22033dc..19d573a55a 100644 --- a/osu.Game/Rulesets/Objects/Legacy/ConvertHitObjectParser.cs +++ b/osu.Game/Rulesets/Objects/Legacy/ConvertHitObjectParser.cs @@ -5,6 +5,7 @@ using osuTK; using osu.Game.Rulesets.Objects.Types; using System; using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; using System.IO; using osu.Game.Beatmaps.Formats; using osu.Game.Audio; @@ -500,7 +501,7 @@ namespace osu.Game.Rulesets.Objects.Legacy public SampleBankInfo Clone() => (SampleBankInfo)MemberwiseClone(); } - public class LegacyHitSampleInfo : HitSampleInfo + public class LegacyHitSampleInfo : HitSampleInfo, IEquatable { private int customSampleBank; @@ -524,9 +525,21 @@ namespace osu.Game.Rulesets.Objects.Legacy /// using the skin config option. /// public bool IsLayered { get; set; } + + public bool Equals(LegacyHitSampleInfo other) + => other != null && base.Equals(other) && CustomSampleBank == other.CustomSampleBank; + + public override bool Equals(object obj) + => obj is LegacyHitSampleInfo other && Equals(other); + + [SuppressMessage("ReSharper", "NonReadonlyMemberInGetHashCode")] // This will have to be addressed eventually + public override int GetHashCode() + { + return HashCode.Combine(base.GetHashCode(), customSampleBank); + } } - private class FileHitSampleInfo : LegacyHitSampleInfo + private class FileHitSampleInfo : LegacyHitSampleInfo, IEquatable { public string Filename; @@ -542,6 +555,18 @@ namespace osu.Game.Rulesets.Objects.Legacy Filename, Path.ChangeExtension(Filename, null) }; + + public bool Equals(FileHitSampleInfo other) + => other != null && Filename == other.Filename; + + public override bool Equals(object obj) + => obj is FileHitSampleInfo other && Equals(other); + + [SuppressMessage("ReSharper", "NonReadonlyMemberInGetHashCode")] // This will have to be addressed eventually + public override int GetHashCode() + { + return HashCode.Combine(Filename); + } } } } diff --git a/osu.Game/Rulesets/UI/Playfield.cs b/osu.Game/Rulesets/UI/Playfield.cs index 82ec653f31..9f3a4c508f 100644 --- a/osu.Game/Rulesets/UI/Playfield.cs +++ b/osu.Game/Rulesets/UI/Playfield.cs @@ -8,19 +8,23 @@ using JetBrains.Annotations; using osu.Framework.Graphics; using osu.Game.Rulesets.Objects.Drawables; using osu.Framework.Allocation; +using osu.Framework.Audio.Track; using osu.Framework.Bindables; using osu.Framework.Extensions.IEnumerableExtensions; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Pooling; +using osu.Game.Audio; using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.Objects; +using osu.Game.Skinning; using osuTK; namespace osu.Game.Rulesets.UI { [Cached(typeof(IPooledHitObjectProvider))] - public abstract class Playfield : CompositeDrawable, IPooledHitObjectProvider + [Cached(typeof(IPooledSampleProvider))] + public abstract class Playfield : CompositeDrawable, IPooledHitObjectProvider, IPooledSampleProvider { /// /// Invoked when a is judged. @@ -80,6 +84,12 @@ namespace osu.Game.Rulesets.UI /// public readonly BindableBool DisplayJudgements = new BindableBool(true); + [Resolved(CanBeNull = true)] + private IReadOnlyList mods { get; set; } + + [Resolved] + private ISampleStore sampleStore { get; set; } + /// /// Creates a new . /// @@ -96,9 +106,6 @@ namespace osu.Game.Rulesets.UI })); } - [Resolved(CanBeNull = true)] - private IReadOnlyList mods { get; set; } - [BackgroundDependencyLoader] private void load() { @@ -336,6 +343,29 @@ namespace osu.Game.Rulesets.UI }); } + private readonly Dictionary> samplePools = new Dictionary>(); + + public PoolableSkinnableSample GetPooledSample(ISampleInfo sampleInfo) + { + if (!samplePools.TryGetValue(sampleInfo, out var existingPool)) + samplePools[sampleInfo] = existingPool = new DrawableSamplePool(sampleInfo, 5); + + return existingPool.Get(); + } + + private class DrawableSamplePool : DrawablePool + { + private readonly ISampleInfo sampleInfo; + + public DrawableSamplePool(ISampleInfo sampleInfo, int initialSize, int? maximumSize = null) + : base(initialSize, maximumSize) + { + this.sampleInfo = sampleInfo; + } + + protected override PoolableSkinnableSample CreateNewDrawable() => base.CreateNewDrawable().With(d => d.Apply(sampleInfo)); + } + #endregion #region Editor logic diff --git a/osu.Game/Skinning/PausableSkinnableSound.cs b/osu.Game/Skinning/PausableSkinnableSound.cs index 4f09aec0b6..758b784649 100644 --- a/osu.Game/Skinning/PausableSkinnableSound.cs +++ b/osu.Game/Skinning/PausableSkinnableSound.cs @@ -14,13 +14,13 @@ namespace osu.Game.Skinning { protected bool RequestedPlaying { get; private set; } - public PausableSkinnableSound(ISampleInfo hitSamples) - : base(hitSamples) + public PausableSkinnableSound(ISampleInfo sample) + : base(sample) { } - public PausableSkinnableSound(IEnumerable hitSamples) - : base(hitSamples) + public PausableSkinnableSound(IEnumerable samples) + : base(samples) { } diff --git a/osu.Game/Skinning/SkinReloadableDrawable.cs b/osu.Game/Skinning/SkinReloadableDrawable.cs index cc9cbf7b59..50b4143375 100644 --- a/osu.Game/Skinning/SkinReloadableDrawable.cs +++ b/osu.Game/Skinning/SkinReloadableDrawable.cs @@ -27,7 +27,7 @@ namespace osu.Game.Skinning /// /// Whether fallback to default skin should be allowed if the custom skin is missing this resource. /// - private bool allowDefaultFallback => allowFallback == null || allowFallback.Invoke(CurrentSkin); + protected bool AllowDefaultFallback => allowFallback == null || allowFallback.Invoke(CurrentSkin); /// /// Create a new @@ -58,7 +58,7 @@ namespace osu.Game.Skinning private void skinChanged() { - SkinChanged(CurrentSkin, allowDefaultFallback); + SkinChanged(CurrentSkin, AllowDefaultFallback); OnSkinChanged?.Invoke(); } diff --git a/osu.Game/Skinning/SkinnableSound.cs b/osu.Game/Skinning/SkinnableSound.cs index ffa0a963ce..8410b7eeae 100644 --- a/osu.Game/Skinning/SkinnableSound.cs +++ b/osu.Game/Skinning/SkinnableSound.cs @@ -1,26 +1,149 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System; using System.Collections.Generic; using System.Linq; +using JetBrains.Annotations; using osu.Framework.Allocation; 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.Game.Audio; namespace osu.Game.Skinning { - public class SkinnableSound : SkinReloadableDrawable, IAdjustableAudioComponent + public interface IPooledSampleProvider { - private readonly ISampleInfo[] hitSamples; + [CanBeNull] + PoolableSkinnableSample GetPooledSample(ISampleInfo sampleInfo); + } + + public class PoolableSkinnableSample : SkinReloadableDrawable, IAggregateAudioAdjustment, IAdjustableAudioComponent + { + private ISampleInfo sampleInfo; + private DrawableSample sample; [Resolved] - private ISampleStore samples { get; set; } + private ISampleStore sampleStore { get; set; } + [Cached] + private readonly AudioAdjustments adjustments = new AudioAdjustments(); + + public PoolableSkinnableSample() + { + } + + public PoolableSkinnableSample(ISampleInfo sampleInfo) + { + Apply(sampleInfo); + } + + public void Apply(ISampleInfo sampleInfo) + { + if (this.sampleInfo != null) + throw new InvalidOperationException($"A {nameof(PoolableSkinnableSample)} cannot be applied multiple {nameof(ISampleInfo)}s."); + + this.sampleInfo = sampleInfo; + + if (LoadState >= LoadState.Ready) + updateSample(); + } + + protected override void SkinChanged(ISkinSource skin, bool allowFallback) + { + base.SkinChanged(skin, allowFallback); + updateSample(); + } + + private void updateSample() + { + ClearInternal(); + + var ch = CurrentSkin.GetSample(sampleInfo); + + if (ch == null && AllowDefaultFallback) + { + foreach (var lookup in sampleInfo.LookupNames) + { + if ((ch = sampleStore.Get(lookup)) != null) + break; + } + } + + if (ch == null) + return; + + AddInternal(sample = new DrawableSample(ch) + { + Looping = Looping, + Volume = { Value = sampleInfo.Volume / 100.0 } + }); + } + + public void Play(bool restart = true) => sample?.Play(restart); + + public void Stop() => sample?.Stop(); + + public bool Playing => sample?.Playing ?? false; + + private bool looping; + + public bool Looping + { + get => looping; + set + { + looping = value; + + if (sample != null) + sample.Looping = value; + } + } + + /// + /// The volume of this component. + /// + public BindableNumber Volume => adjustments.Volume; + + /// + /// The playback balance of this sample (-1 .. 1 where 0 is centered) + /// + public BindableNumber Balance => adjustments.Balance; + + /// + /// Rate at which the component is played back (affects pitch). 1 is 100% playback speed, or default frequency. + /// + public BindableNumber Frequency => adjustments.Frequency; + + /// + /// Rate at which the component is played back (does not affect pitch). 1 is 100% playback speed. + /// + public BindableNumber Tempo => adjustments.Tempo; + + public void AddAdjustment(AdjustableProperty type, BindableNumber adjustBindable) + => adjustments.AddAdjustment(type, adjustBindable); + + public void RemoveAdjustment(AdjustableProperty type, BindableNumber adjustBindable) + => adjustments.RemoveAdjustment(type, adjustBindable); + + public void RemoveAllAdjustments(AdjustableProperty type) => adjustments.RemoveAllAdjustments(type); + + public IBindable AggregateVolume => adjustments.AggregateVolume; + + public IBindable AggregateBalance => adjustments.AggregateBalance; + + public IBindable AggregateFrequency => adjustments.AggregateFrequency; + + public IBindable AggregateTempo => adjustments.AggregateTempo; + } + + public class SkinnableSound : SkinReloadableDrawable, IAdjustableAudioComponent + { public override bool RemoveWhenNotAlive => false; public override bool RemoveCompletedTransforms => false; @@ -34,17 +157,44 @@ namespace osu.Game.Skinning /// protected bool PlayWhenZeroVolume => Looping; - protected readonly AudioContainer SamplesContainer; + protected readonly AudioContainer SamplesContainer; - public SkinnableSound(ISampleInfo hitSamples) - : this(new[] { hitSamples }) + [Resolved] + private ISampleStore sampleStore { get; set; } + + [Resolved(CanBeNull = true)] + private IPooledSampleProvider pooledProvider { get; set; } + + public SkinnableSound(ISampleInfo sample) + : this(new[] { sample }) { } - public SkinnableSound(IEnumerable hitSamples) + public SkinnableSound(IEnumerable samples) { - this.hitSamples = hitSamples.ToArray(); - InternalChild = SamplesContainer = new AudioContainer(); + this.samples = samples.ToArray(); + + InternalChild = SamplesContainer = new AudioContainer(); + } + + private ISampleInfo[] samples; + + public ISampleInfo[] Samples + { + get => samples; + set + { + if (value == null) + throw new ArgumentNullException(nameof(value)); + + if (samples == value) + return; + + samples = value; + + if (LoadState >= LoadState.Ready) + updateSamples(); + } } private bool looping; @@ -77,34 +227,23 @@ namespace osu.Game.Skinning } protected override void SkinChanged(ISkinSource skin, bool allowFallback) + { + // Start playback internally for the new samples if the previous ones were playing beforehand. + if (IsPlaying) + Play(); + } + + private void updateSamples() { bool wasPlaying = IsPlaying; - var channels = hitSamples.Select(s => - { - var ch = skin.GetSample(s); + // Remove all pooled samples (return them to the pool), and dispose the rest. + SamplesContainer.RemoveAll(s => s.IsInPool); + SamplesContainer.Clear(); - if (ch == null && allowFallback) - { - foreach (var lookup in s.LookupNames) - { - if ((ch = samples.Get(lookup)) != null) - break; - } - } + foreach (var s in samples) + SamplesContainer.Add(pooledProvider?.GetPooledSample(s) ?? new PoolableSkinnableSample(s)); - if (ch != null) - { - ch.Looping = looping; - ch.Volume.Value = s.Volume / 100.0; - } - - return ch; - }).Where(c => c != null); - - SamplesContainer.ChildrenEnumerable = channels.Select(c => new DrawableSample(c)); - - // Start playback internally for the new samples if the previous ones were playing beforehand. if (wasPlaying) Play(); } diff --git a/osu.Game/Storyboards/Drawables/DrawableStoryboardSample.cs b/osu.Game/Storyboards/Drawables/DrawableStoryboardSample.cs index 08811b9b8c..b8d212d3c9 100644 --- a/osu.Game/Storyboards/Drawables/DrawableStoryboardSample.cs +++ b/osu.Game/Storyboards/Drawables/DrawableStoryboardSample.cs @@ -37,8 +37,8 @@ namespace osu.Game.Storyboards.Drawables foreach (var mod in mods.Value.OfType()) { - foreach (var sample in SamplesContainer) - mod.ApplyToSample(sample); + // foreach (var sample in SamplesContainer) + // mod.ApplyToSample(sample.Sample); } } From 003fed857c9f35c258f6ad1499d8e5bc4e624827 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 19 Nov 2020 19:52:34 +0900 Subject: [PATCH 002/184] Separate files --- osu.Game/Skinning/IPooledSampleProvider.cs | 14 ++ osu.Game/Skinning/PoolableSkinnableSample.cs | 133 +++++++++++++++++++ osu.Game/Skinning/SkinnableSound.cs | 127 ------------------ 3 files changed, 147 insertions(+), 127 deletions(-) create mode 100644 osu.Game/Skinning/IPooledSampleProvider.cs create mode 100644 osu.Game/Skinning/PoolableSkinnableSample.cs diff --git a/osu.Game/Skinning/IPooledSampleProvider.cs b/osu.Game/Skinning/IPooledSampleProvider.cs new file mode 100644 index 0000000000..3dc0b5375d --- /dev/null +++ b/osu.Game/Skinning/IPooledSampleProvider.cs @@ -0,0 +1,14 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using JetBrains.Annotations; +using osu.Game.Audio; + +namespace osu.Game.Skinning +{ + public interface IPooledSampleProvider + { + [CanBeNull] + PoolableSkinnableSample GetPooledSample(ISampleInfo sampleInfo); + } +} diff --git a/osu.Game/Skinning/PoolableSkinnableSample.cs b/osu.Game/Skinning/PoolableSkinnableSample.cs new file mode 100644 index 0000000000..6ad7345954 --- /dev/null +++ b/osu.Game/Skinning/PoolableSkinnableSample.cs @@ -0,0 +1,133 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System; +using osu.Framework.Allocation; +using osu.Framework.Audio; +using osu.Framework.Audio.Track; +using osu.Framework.Bindables; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Audio; +using osu.Game.Audio; + +namespace osu.Game.Skinning +{ + public class PoolableSkinnableSample : SkinReloadableDrawable, IAggregateAudioAdjustment, IAdjustableAudioComponent + { + private ISampleInfo sampleInfo; + private DrawableSample sample; + + [Resolved] + private ISampleStore sampleStore { get; set; } + + [Cached] + private readonly AudioAdjustments adjustments = new AudioAdjustments(); + + public PoolableSkinnableSample() + { + } + + public PoolableSkinnableSample(ISampleInfo sampleInfo) + { + Apply(sampleInfo); + } + + public void Apply(ISampleInfo sampleInfo) + { + if (this.sampleInfo != null) + throw new InvalidOperationException($"A {nameof(PoolableSkinnableSample)} cannot be applied multiple {nameof(ISampleInfo)}s."); + + this.sampleInfo = sampleInfo; + + if (LoadState >= LoadState.Ready) + updateSample(); + } + + protected override void SkinChanged(ISkinSource skin, bool allowFallback) + { + base.SkinChanged(skin, allowFallback); + updateSample(); + } + + private void updateSample() + { + ClearInternal(); + + var ch = CurrentSkin.GetSample(sampleInfo); + + if (ch == null && AllowDefaultFallback) + { + foreach (var lookup in sampleInfo.LookupNames) + { + if ((ch = sampleStore.Get(lookup)) != null) + break; + } + } + + if (ch == null) + return; + + AddInternal(sample = new DrawableSample(ch) + { + Looping = Looping, + Volume = { Value = sampleInfo.Volume / 100.0 } + }); + } + + public void Play(bool restart = true) => sample?.Play(restart); + + public void Stop() => sample?.Stop(); + + public bool Playing => sample?.Playing ?? false; + + private bool looping; + + public bool Looping + { + get => looping; + set + { + looping = value; + + if (sample != null) + sample.Looping = value; + } + } + + /// + /// The volume of this component. + /// + public BindableNumber Volume => adjustments.Volume; + + /// + /// The playback balance of this sample (-1 .. 1 where 0 is centered) + /// + public BindableNumber Balance => adjustments.Balance; + + /// + /// Rate at which the component is played back (affects pitch). 1 is 100% playback speed, or default frequency. + /// + public BindableNumber Frequency => adjustments.Frequency; + + /// + /// Rate at which the component is played back (does not affect pitch). 1 is 100% playback speed. + /// + public BindableNumber Tempo => adjustments.Tempo; + + public void AddAdjustment(AdjustableProperty type, BindableNumber adjustBindable) + => adjustments.AddAdjustment(type, adjustBindable); + + public void RemoveAdjustment(AdjustableProperty type, BindableNumber adjustBindable) + => adjustments.RemoveAdjustment(type, adjustBindable); + + public void RemoveAllAdjustments(AdjustableProperty type) => adjustments.RemoveAllAdjustments(type); + + public IBindable AggregateVolume => adjustments.AggregateVolume; + + public IBindable AggregateBalance => adjustments.AggregateBalance; + + public IBindable AggregateFrequency => adjustments.AggregateFrequency; + + public IBindable AggregateTempo => adjustments.AggregateTempo; + } +} diff --git a/osu.Game/Skinning/SkinnableSound.cs b/osu.Game/Skinning/SkinnableSound.cs index 8410b7eeae..77ae8f1e16 100644 --- a/osu.Game/Skinning/SkinnableSound.cs +++ b/osu.Game/Skinning/SkinnableSound.cs @@ -4,144 +4,17 @@ using System; using System.Collections.Generic; using System.Linq; -using JetBrains.Annotations; using osu.Framework.Allocation; 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.Game.Audio; namespace osu.Game.Skinning { - public interface IPooledSampleProvider - { - [CanBeNull] - PoolableSkinnableSample GetPooledSample(ISampleInfo sampleInfo); - } - - public class PoolableSkinnableSample : SkinReloadableDrawable, IAggregateAudioAdjustment, IAdjustableAudioComponent - { - private ISampleInfo sampleInfo; - private DrawableSample sample; - - [Resolved] - private ISampleStore sampleStore { get; set; } - - [Cached] - private readonly AudioAdjustments adjustments = new AudioAdjustments(); - - public PoolableSkinnableSample() - { - } - - public PoolableSkinnableSample(ISampleInfo sampleInfo) - { - Apply(sampleInfo); - } - - public void Apply(ISampleInfo sampleInfo) - { - if (this.sampleInfo != null) - throw new InvalidOperationException($"A {nameof(PoolableSkinnableSample)} cannot be applied multiple {nameof(ISampleInfo)}s."); - - this.sampleInfo = sampleInfo; - - if (LoadState >= LoadState.Ready) - updateSample(); - } - - protected override void SkinChanged(ISkinSource skin, bool allowFallback) - { - base.SkinChanged(skin, allowFallback); - updateSample(); - } - - private void updateSample() - { - ClearInternal(); - - var ch = CurrentSkin.GetSample(sampleInfo); - - if (ch == null && AllowDefaultFallback) - { - foreach (var lookup in sampleInfo.LookupNames) - { - if ((ch = sampleStore.Get(lookup)) != null) - break; - } - } - - if (ch == null) - return; - - AddInternal(sample = new DrawableSample(ch) - { - Looping = Looping, - Volume = { Value = sampleInfo.Volume / 100.0 } - }); - } - - public void Play(bool restart = true) => sample?.Play(restart); - - public void Stop() => sample?.Stop(); - - public bool Playing => sample?.Playing ?? false; - - private bool looping; - - public bool Looping - { - get => looping; - set - { - looping = value; - - if (sample != null) - sample.Looping = value; - } - } - - /// - /// The volume of this component. - /// - public BindableNumber Volume => adjustments.Volume; - - /// - /// The playback balance of this sample (-1 .. 1 where 0 is centered) - /// - public BindableNumber Balance => adjustments.Balance; - - /// - /// Rate at which the component is played back (affects pitch). 1 is 100% playback speed, or default frequency. - /// - public BindableNumber Frequency => adjustments.Frequency; - - /// - /// Rate at which the component is played back (does not affect pitch). 1 is 100% playback speed. - /// - public BindableNumber Tempo => adjustments.Tempo; - - public void AddAdjustment(AdjustableProperty type, BindableNumber adjustBindable) - => adjustments.AddAdjustment(type, adjustBindable); - - public void RemoveAdjustment(AdjustableProperty type, BindableNumber adjustBindable) - => adjustments.RemoveAdjustment(type, adjustBindable); - - public void RemoveAllAdjustments(AdjustableProperty type) => adjustments.RemoveAllAdjustments(type); - - public IBindable AggregateVolume => adjustments.AggregateVolume; - - public IBindable AggregateBalance => adjustments.AggregateBalance; - - public IBindable AggregateFrequency => adjustments.AggregateFrequency; - - public IBindable AggregateTempo => adjustments.AggregateTempo; - } - public class SkinnableSound : SkinReloadableDrawable, IAdjustableAudioComponent { public override bool RemoveWhenNotAlive => false; From 8920534a255fe7c182a33d3200a8c23dd177e299 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 19 Nov 2020 20:24:03 +0900 Subject: [PATCH 003/184] Fix pools not being added to hierarchy --- osu.Game/Rulesets/UI/Playfield.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Rulesets/UI/Playfield.cs b/osu.Game/Rulesets/UI/Playfield.cs index 9f3a4c508f..5383c4b2ce 100644 --- a/osu.Game/Rulesets/UI/Playfield.cs +++ b/osu.Game/Rulesets/UI/Playfield.cs @@ -348,7 +348,7 @@ namespace osu.Game.Rulesets.UI public PoolableSkinnableSample GetPooledSample(ISampleInfo sampleInfo) { if (!samplePools.TryGetValue(sampleInfo, out var existingPool)) - samplePools[sampleInfo] = existingPool = new DrawableSamplePool(sampleInfo, 5); + AddInternal(samplePools[sampleInfo] = existingPool = new DrawableSamplePool(sampleInfo, 5)); return existingPool.Get(); } From 812d5d59b1ac12757a86cb44bd6447b9f7d60846 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 19 Nov 2020 20:29:09 +0900 Subject: [PATCH 004/184] Fix looping not being propagated --- osu.Game/Skinning/SkinnableSound.cs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/osu.Game/Skinning/SkinnableSound.cs b/osu.Game/Skinning/SkinnableSound.cs index 77ae8f1e16..eca1b9b03f 100644 --- a/osu.Game/Skinning/SkinnableSound.cs +++ b/osu.Game/Skinning/SkinnableSound.cs @@ -115,7 +115,12 @@ namespace osu.Game.Skinning SamplesContainer.Clear(); foreach (var s in samples) - SamplesContainer.Add(pooledProvider?.GetPooledSample(s) ?? new PoolableSkinnableSample(s)); + { + var sample = pooledProvider?.GetPooledSample(s) ?? new PoolableSkinnableSample(s); + sample.Looping = Looping; + + SamplesContainer.Add(sample); + } if (wasPlaying) Play(); From 70cb1979578e51fda79a41b12f2767777d64cf08 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 19 Nov 2020 20:38:36 +0900 Subject: [PATCH 005/184] Cleanups --- .../Objects/Drawables/DrawableHitObject.cs | 7 +++---- osu.Game/Skinning/PausableSkinnableSound.cs | 11 ++++++++--- osu.Game/Skinning/SkinnableSound.cs | 15 ++++++++++----- 3 files changed, 21 insertions(+), 12 deletions(-) diff --git a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs index 0d97066b35..26d2ffe3ce 100644 --- a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs +++ b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs @@ -156,7 +156,7 @@ namespace osu.Game.Rulesets.Objects.Drawables config.BindWith(OsuSetting.PositionalHitSounds, userPositionalHitSounds); // Explicit non-virtual function call. - base.AddInternal(Samples = new PausableSkinnableSound(Array.Empty())); + base.AddInternal(Samples = new PausableSkinnableSound()); } protected override void LoadAsyncComplete() @@ -266,7 +266,8 @@ namespace osu.Game.Rulesets.Objects.Drawables // In order to stop this needless update, the event is unbound and re-bound as late as possible in Apply(). samplesBindable.CollectionChanged -= onSamplesChanged; - Samples.Samples = Array.Empty(); + // Release the samples for other hitobjects to use. + Samples.Samples = null; if (nestedHitObjects.IsValueCreated) { @@ -334,8 +335,6 @@ namespace osu.Game.Rulesets.Objects.Drawables /// protected virtual void LoadSamples() { - Samples.Samples = Array.Empty(); - var samples = GetSamples().ToArray(); if (samples.Length <= 0) diff --git a/osu.Game/Skinning/PausableSkinnableSound.cs b/osu.Game/Skinning/PausableSkinnableSound.cs index 758b784649..be4664356d 100644 --- a/osu.Game/Skinning/PausableSkinnableSound.cs +++ b/osu.Game/Skinning/PausableSkinnableSound.cs @@ -2,6 +2,7 @@ // See the LICENCE file in the repository root for full licence text. using System.Collections.Generic; +using JetBrains.Annotations; using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Threading; @@ -14,16 +15,20 @@ namespace osu.Game.Skinning { protected bool RequestedPlaying { get; private set; } - public PausableSkinnableSound(ISampleInfo sample) - : base(sample) + public PausableSkinnableSound() { } - public PausableSkinnableSound(IEnumerable samples) + public PausableSkinnableSound([NotNull] IEnumerable samples) : base(samples) { } + public PausableSkinnableSound([NotNull] ISampleInfo sample) + : base(sample) + { + } + private readonly IBindable samplePlaybackDisabled = new Bindable(); private ScheduledDelegate scheduledStart; diff --git a/osu.Game/Skinning/SkinnableSound.cs b/osu.Game/Skinning/SkinnableSound.cs index eca1b9b03f..67d13118d9 100644 --- a/osu.Game/Skinning/SkinnableSound.cs +++ b/osu.Game/Skinning/SkinnableSound.cs @@ -4,6 +4,7 @@ using System; using System.Collections.Generic; using System.Linq; +using JetBrains.Annotations; using osu.Framework.Allocation; using osu.Framework.Audio; using osu.Framework.Audio.Track; @@ -38,18 +39,23 @@ namespace osu.Game.Skinning [Resolved(CanBeNull = true)] private IPooledSampleProvider pooledProvider { get; set; } - public SkinnableSound(ISampleInfo sample) - : this(new[] { sample }) + public SkinnableSound() { } - public SkinnableSound(IEnumerable samples) + public SkinnableSound([NotNull] IEnumerable samples) + : this() { this.samples = samples.ToArray(); InternalChild = SamplesContainer = new AudioContainer(); } + public SkinnableSound([NotNull] ISampleInfo sample) + : this(new[] { sample }) + { + } + private ISampleInfo[] samples; public ISampleInfo[] Samples @@ -57,8 +63,7 @@ namespace osu.Game.Skinning get => samples; set { - if (value == null) - throw new ArgumentNullException(nameof(value)); + value ??= Array.Empty(); if (samples == value) return; From f013928fa3dd7c0293cef09c8c2b651ea2e8e314 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 19 Nov 2020 20:40:01 +0900 Subject: [PATCH 006/184] Set maximum pool size --- osu.Game/Rulesets/UI/Playfield.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Rulesets/UI/Playfield.cs b/osu.Game/Rulesets/UI/Playfield.cs index 5383c4b2ce..6e89f20246 100644 --- a/osu.Game/Rulesets/UI/Playfield.cs +++ b/osu.Game/Rulesets/UI/Playfield.cs @@ -348,7 +348,7 @@ namespace osu.Game.Rulesets.UI public PoolableSkinnableSample GetPooledSample(ISampleInfo sampleInfo) { if (!samplePools.TryGetValue(sampleInfo, out var existingPool)) - AddInternal(samplePools[sampleInfo] = existingPool = new DrawableSamplePool(sampleInfo, 5)); + AddInternal(samplePools[sampleInfo] = existingPool = new DrawableSamplePool(sampleInfo, 1, 30)); return existingPool.Get(); } From 688a04c2ff8e6a931b67ed4a36337508f5555d22 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 19 Nov 2020 20:40:30 +0900 Subject: [PATCH 007/184] Make slider/spinner use pooled samples --- .../Objects/Drawables/DrawableSlider.cs | 17 ++++------- .../Objects/Drawables/DrawableSpinner.cs | 29 +++++++++++-------- 2 files changed, 23 insertions(+), 23 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs index 14c494d909..b62c04eed9 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs @@ -11,6 +11,7 @@ using osu.Game.Rulesets.Osu.Objects.Drawables.Pieces; using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics.Containers; +using osu.Game.Audio; using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Osu.Skinning; using osu.Game.Rulesets.Osu.UI; @@ -40,7 +41,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables private Container tailContainer; private Container tickContainer; private Container repeatContainer; - private Container samplesContainer; + private PausableSkinnableSound slidingSample; public DrawableSlider() : this(null) @@ -69,7 +70,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables Alpha = 0 }, headContainer = new Container { RelativeSizeAxes = Axes.Both }, - samplesContainer = new Container { RelativeSizeAxes = Axes.Both } + slidingSample = new PausableSkinnableSound { Looping = true } }; PositionBindable.BindValueChanged(_ => Position = HitObject.StackedPosition); @@ -100,17 +101,14 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables base.OnFree(hitObject); PathVersion.UnbindFrom(HitObject.Path.Version); - } - private PausableSkinnableSound slidingSample; + slidingSample.Samples = null; + } protected override void LoadSamples() { base.LoadSamples(); - samplesContainer.Clear(); - slidingSample = null; - var firstSample = HitObject.Samples.FirstOrDefault(); if (firstSample != null) @@ -118,10 +116,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables var clone = HitObject.SampleControlPoint.ApplyTo(firstSample); clone.Name = "sliderslide"; - samplesContainer.Add(slidingSample = new PausableSkinnableSound(clone) - { - Looping = true - }); + slidingSample.Samples = new ISampleInfo[] { clone }; } } diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinner.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinner.cs index 2a14a7c975..e5fc717504 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinner.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinner.cs @@ -9,6 +9,7 @@ using osu.Framework.Audio; using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; +using osu.Game.Audio; using osu.Game.Graphics; using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Objects; @@ -33,7 +34,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables private Container ticks; private SpinnerBonusDisplay bonusDisplay; - private Container samplesContainer; + private PausableSkinnableSound spinningSample; private Bindable isSpinning; private bool spinnerFrequencyModulate; @@ -81,7 +82,12 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables Origin = Anchor.Centre, Y = -120, }, - samplesContainer = new Container { RelativeSizeAxes = Axes.Both } + spinningSample = new PausableSkinnableSound + { + Volume = { Value = 0 }, + Looping = true, + Frequency = { Value = spinning_sample_initial_frequency } + } }; PositionBindable.BindValueChanged(pos => Position = pos.NewValue); @@ -95,17 +101,20 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables isSpinning.BindValueChanged(updateSpinningSample); } - private PausableSkinnableSound spinningSample; private const float spinning_sample_initial_frequency = 1.0f; private const float spinning_sample_modulated_base_frequency = 0.5f; + protected override void OnFree(HitObject hitObject) + { + base.OnFree(hitObject); + + spinningSample.Samples = null; + } + protected override void LoadSamples() { base.LoadSamples(); - samplesContainer.Clear(); - spinningSample = null; - var firstSample = HitObject.Samples.FirstOrDefault(); if (firstSample != null) @@ -113,12 +122,8 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables var clone = HitObject.SampleControlPoint.ApplyTo(firstSample); clone.Name = "spinnerspin"; - samplesContainer.Add(spinningSample = new PausableSkinnableSound(clone) - { - Volume = { Value = 0 }, - Looping = true, - Frequency = { Value = spinning_sample_initial_frequency } - }); + spinningSample.Samples = new ISampleInfo[] { clone }; + spinningSample.Frequency.Value = spinning_sample_initial_frequency; } } From 0287269b2fed663d910f9571042accfe3a11d185 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 19 Nov 2020 21:01:38 +0900 Subject: [PATCH 008/184] Fix volume discrepancies --- osu.Game/Skinning/PoolableSkinnableSample.cs | 42 ++++++++++---------- osu.Game/Skinning/SkinnableSound.cs | 4 +- 2 files changed, 22 insertions(+), 24 deletions(-) diff --git a/osu.Game/Skinning/PoolableSkinnableSample.cs b/osu.Game/Skinning/PoolableSkinnableSample.cs index 6ad7345954..ad799dd32e 100644 --- a/osu.Game/Skinning/PoolableSkinnableSample.cs +++ b/osu.Game/Skinning/PoolableSkinnableSample.cs @@ -8,26 +8,28 @@ using osu.Framework.Audio.Track; using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Audio; +using osu.Framework.Graphics.Containers; using osu.Game.Audio; namespace osu.Game.Skinning { public class PoolableSkinnableSample : SkinReloadableDrawable, IAggregateAudioAdjustment, IAdjustableAudioComponent { + private readonly AudioContainer sampleContainer; + private ISampleInfo sampleInfo; private DrawableSample sample; [Resolved] private ISampleStore sampleStore { get; set; } - [Cached] - private readonly AudioAdjustments adjustments = new AudioAdjustments(); - public PoolableSkinnableSample() { + InternalChild = sampleContainer = new AudioContainer { RelativeSizeAxes = Axes.Both }; } public PoolableSkinnableSample(ISampleInfo sampleInfo) + : this() { Apply(sampleInfo); } @@ -39,6 +41,8 @@ namespace osu.Game.Skinning this.sampleInfo = sampleInfo; + Volume.Value = sampleInfo.Volume / 100.0; + if (LoadState >= LoadState.Ready) updateSample(); } @@ -51,7 +55,7 @@ namespace osu.Game.Skinning private void updateSample() { - ClearInternal(); + sampleContainer.Clear(); var ch = CurrentSkin.GetSample(sampleInfo); @@ -67,11 +71,7 @@ namespace osu.Game.Skinning if (ch == null) return; - AddInternal(sample = new DrawableSample(ch) - { - Looping = Looping, - Volume = { Value = sampleInfo.Volume / 100.0 } - }); + sampleContainer.Add(sample = new DrawableSample(ch) { Looping = Looping }); } public void Play(bool restart = true) => sample?.Play(restart); @@ -97,37 +97,35 @@ namespace osu.Game.Skinning /// /// The volume of this component. /// - public BindableNumber Volume => adjustments.Volume; + public BindableNumber Volume => sampleContainer.Volume; /// /// The playback balance of this sample (-1 .. 1 where 0 is centered) /// - public BindableNumber Balance => adjustments.Balance; + public BindableNumber Balance => sampleContainer.Balance; /// /// Rate at which the component is played back (affects pitch). 1 is 100% playback speed, or default frequency. /// - public BindableNumber Frequency => adjustments.Frequency; + public BindableNumber Frequency => sampleContainer.Frequency; /// /// Rate at which the component is played back (does not affect pitch). 1 is 100% playback speed. /// - public BindableNumber Tempo => adjustments.Tempo; + public BindableNumber Tempo => sampleContainer.Tempo; - public void AddAdjustment(AdjustableProperty type, BindableNumber adjustBindable) - => adjustments.AddAdjustment(type, adjustBindable); + public void AddAdjustment(AdjustableProperty type, BindableNumber adjustBindable) => sampleContainer.AddAdjustment(type, adjustBindable); - public void RemoveAdjustment(AdjustableProperty type, BindableNumber adjustBindable) - => adjustments.RemoveAdjustment(type, adjustBindable); + public void RemoveAdjustment(AdjustableProperty type, BindableNumber adjustBindable) => sampleContainer.RemoveAdjustment(type, adjustBindable); - public void RemoveAllAdjustments(AdjustableProperty type) => adjustments.RemoveAllAdjustments(type); + public void RemoveAllAdjustments(AdjustableProperty type) => sampleContainer.RemoveAllAdjustments(type); - public IBindable AggregateVolume => adjustments.AggregateVolume; + public IBindable AggregateVolume => sampleContainer.AggregateVolume; - public IBindable AggregateBalance => adjustments.AggregateBalance; + public IBindable AggregateBalance => sampleContainer.AggregateBalance; - public IBindable AggregateFrequency => adjustments.AggregateFrequency; + public IBindable AggregateFrequency => sampleContainer.AggregateFrequency; - public IBindable AggregateTempo => adjustments.AggregateTempo; + public IBindable AggregateTempo => sampleContainer.AggregateTempo; } } diff --git a/osu.Game/Skinning/SkinnableSound.cs b/osu.Game/Skinning/SkinnableSound.cs index 67d13118d9..8dc3337525 100644 --- a/osu.Game/Skinning/SkinnableSound.cs +++ b/osu.Game/Skinning/SkinnableSound.cs @@ -41,14 +41,13 @@ namespace osu.Game.Skinning public SkinnableSound() { + InternalChild = SamplesContainer = new AudioContainer(); } public SkinnableSound([NotNull] IEnumerable samples) : this() { this.samples = samples.ToArray(); - - InternalChild = SamplesContainer = new AudioContainer(); } public SkinnableSound([NotNull] ISampleInfo sample) @@ -123,6 +122,7 @@ namespace osu.Game.Skinning { var sample = pooledProvider?.GetPooledSample(s) ?? new PoolableSkinnableSample(s); sample.Looping = Looping; + sample.Volume.Value = s.Volume / 100.0; SamplesContainer.Add(sample); } From 7180bfe4ba904507fd944d42bad39296a559dabc Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 19 Nov 2020 21:21:57 +0900 Subject: [PATCH 009/184] Unlimit number of samples per pool --- osu.Game/Rulesets/UI/Playfield.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Rulesets/UI/Playfield.cs b/osu.Game/Rulesets/UI/Playfield.cs index 6e89f20246..460251e595 100644 --- a/osu.Game/Rulesets/UI/Playfield.cs +++ b/osu.Game/Rulesets/UI/Playfield.cs @@ -348,7 +348,7 @@ namespace osu.Game.Rulesets.UI public PoolableSkinnableSample GetPooledSample(ISampleInfo sampleInfo) { if (!samplePools.TryGetValue(sampleInfo, out var existingPool)) - AddInternal(samplePools[sampleInfo] = existingPool = new DrawableSamplePool(sampleInfo, 1, 30)); + AddInternal(samplePools[sampleInfo] = existingPool = new DrawableSamplePool(sampleInfo, 1)); return existingPool.Get(); } From d388c44428c74f2ce32cb48b0a83f900497f46b7 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 19 Nov 2020 22:30:21 +0900 Subject: [PATCH 010/184] Cleanup, refactoring, and restart sample on skin change --- osu.Game/Skinning/PoolableSkinnableSample.cs | 72 ++++++++++++++------ osu.Game/Skinning/SkinnableSound.cs | 7 -- 2 files changed, 52 insertions(+), 27 deletions(-) diff --git a/osu.Game/Skinning/PoolableSkinnableSample.cs b/osu.Game/Skinning/PoolableSkinnableSample.cs index ad799dd32e..e38b309efb 100644 --- a/osu.Game/Skinning/PoolableSkinnableSample.cs +++ b/osu.Game/Skinning/PoolableSkinnableSample.cs @@ -2,6 +2,7 @@ // See the LICENCE file in the repository root for full licence text. using System; +using JetBrains.Annotations; using osu.Framework.Allocation; using osu.Framework.Audio; using osu.Framework.Audio.Track; @@ -13,27 +14,48 @@ using osu.Game.Audio; namespace osu.Game.Skinning { + /// + /// A sample corresponding to an that supports being pooled and responding to skin changes. + /// public class PoolableSkinnableSample : SkinReloadableDrawable, IAggregateAudioAdjustment, IAdjustableAudioComponent { - private readonly AudioContainer sampleContainer; + /// + /// The currently-loaded . + /// + [CanBeNull] + public DrawableSample Sample { get; private set; } + private readonly AudioContainer sampleContainer; private ISampleInfo sampleInfo; - private DrawableSample sample; [Resolved] private ISampleStore sampleStore { get; set; } + /// + /// Creates a new with no applied . + /// An can be applied later via . + /// public PoolableSkinnableSample() { InternalChild = sampleContainer = new AudioContainer { RelativeSizeAxes = Axes.Both }; } + /// + /// Creates a new with an applied . + /// + /// The to attach. public PoolableSkinnableSample(ISampleInfo sampleInfo) : this() { Apply(sampleInfo); } + /// + /// Applies an that describes the sample to retrieve. + /// Only one can ever be applied to a . + /// + /// The to apply. + /// If an has already been applied to this . public void Apply(ISampleInfo sampleInfo) { if (this.sampleInfo != null) @@ -55,6 +77,11 @@ namespace osu.Game.Skinning private void updateSample() { + if (sampleInfo == null) + return; + + bool wasPlaying = Playing; + sampleContainer.Clear(); var ch = CurrentSkin.GetSample(sampleInfo); @@ -71,17 +98,34 @@ namespace osu.Game.Skinning if (ch == null) return; - sampleContainer.Add(sample = new DrawableSample(ch) { Looping = Looping }); + sampleContainer.Add(Sample = new DrawableSample(ch) { Looping = Looping }); + + // Start playback internally for the new sample if the previous one was playing beforehand. + if (wasPlaying) + Play(); } - public void Play(bool restart = true) => sample?.Play(restart); + /// + /// Plays the sample. + /// + /// Whether to play the sample from the beginning. + public void Play(bool restart = true) => Sample?.Play(restart); - public void Stop() => sample?.Stop(); + /// + /// Stops the sample. + /// + public void Stop() => Sample?.Stop(); - public bool Playing => sample?.Playing ?? false; + /// + /// Whether the sample is currently playing. + /// + public bool Playing => Sample?.Playing ?? false; private bool looping; + /// + /// Gets or sets whether the sample should loop on completion. + /// public bool Looping { get => looping; @@ -89,29 +133,17 @@ namespace osu.Game.Skinning { looping = value; - if (sample != null) - sample.Looping = value; + if (Sample != null) + Sample.Looping = value; } } - /// - /// The volume of this component. - /// public BindableNumber Volume => sampleContainer.Volume; - /// - /// The playback balance of this sample (-1 .. 1 where 0 is centered) - /// public BindableNumber Balance => sampleContainer.Balance; - /// - /// Rate at which the component is played back (affects pitch). 1 is 100% playback speed, or default frequency. - /// public BindableNumber Frequency => sampleContainer.Frequency; - /// - /// Rate at which the component is played back (does not affect pitch). 1 is 100% playback speed. - /// public BindableNumber Tempo => sampleContainer.Tempo; public void AddAdjustment(AdjustableProperty type, BindableNumber adjustBindable) => sampleContainer.AddAdjustment(type, adjustBindable); diff --git a/osu.Game/Skinning/SkinnableSound.cs b/osu.Game/Skinning/SkinnableSound.cs index 8dc3337525..0f39784138 100644 --- a/osu.Game/Skinning/SkinnableSound.cs +++ b/osu.Game/Skinning/SkinnableSound.cs @@ -103,13 +103,6 @@ namespace osu.Game.Skinning SamplesContainer.ForEach(c => c.Stop()); } - protected override void SkinChanged(ISkinSource skin, bool allowFallback) - { - // Start playback internally for the new samples if the previous ones were playing beforehand. - if (IsPlaying) - Play(); - } - private void updateSamples() { bool wasPlaying = IsPlaying; From a53848ef9bbc09b8c4c75a044c3db6a543f85dc0 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 19 Nov 2020 22:30:41 +0900 Subject: [PATCH 011/184] Fix storyboard imlpementation --- osu.Game/Storyboards/Drawables/DrawableStoryboardSample.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Storyboards/Drawables/DrawableStoryboardSample.cs b/osu.Game/Storyboards/Drawables/DrawableStoryboardSample.cs index b8d212d3c9..904af730de 100644 --- a/osu.Game/Storyboards/Drawables/DrawableStoryboardSample.cs +++ b/osu.Game/Storyboards/Drawables/DrawableStoryboardSample.cs @@ -37,8 +37,8 @@ namespace osu.Game.Storyboards.Drawables foreach (var mod in mods.Value.OfType()) { - // foreach (var sample in SamplesContainer) - // mod.ApplyToSample(sample.Sample); + foreach (var sample in SamplesContainer) + mod.ApplyToSample(sample.Sample); } } From 8a656f7cee1ac51578420e9e9576c8055a8fde67 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 19 Nov 2020 22:42:44 +0900 Subject: [PATCH 012/184] Fix missing SkinChanged event + safety --- osu.Game/Skinning/SkinnableSound.cs | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/osu.Game/Skinning/SkinnableSound.cs b/osu.Game/Skinning/SkinnableSound.cs index 0f39784138..bb747a2176 100644 --- a/osu.Game/Skinning/SkinnableSound.cs +++ b/osu.Game/Skinning/SkinnableSound.cs @@ -55,7 +55,7 @@ namespace osu.Game.Skinning { } - private ISampleInfo[] samples; + private ISampleInfo[] samples = Array.Empty(); public ISampleInfo[] Samples { @@ -103,6 +103,12 @@ namespace osu.Game.Skinning SamplesContainer.ForEach(c => c.Stop()); } + protected override void SkinChanged(ISkinSource skin, bool allowFallback) + { + base.SkinChanged(skin, allowFallback); + updateSamples(); + } + private void updateSamples() { bool wasPlaying = IsPlaying; From 7c83a27002a033a114b42a6b933c998d8858f5fa Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 19 Nov 2020 22:47:11 +0900 Subject: [PATCH 013/184] Add more xmldocs --- osu.Game/Skinning/PoolableSkinnableSample.cs | 2 +- osu.Game/Skinning/SkinnableSound.cs | 29 ++++++++++++++++++++ 2 files changed, 30 insertions(+), 1 deletion(-) diff --git a/osu.Game/Skinning/PoolableSkinnableSample.cs b/osu.Game/Skinning/PoolableSkinnableSample.cs index e38b309efb..adc58ee94e 100644 --- a/osu.Game/Skinning/PoolableSkinnableSample.cs +++ b/osu.Game/Skinning/PoolableSkinnableSample.cs @@ -124,7 +124,7 @@ namespace osu.Game.Skinning private bool looping; /// - /// Gets or sets whether the sample should loop on completion. + /// Whether the sample should loop on completion. /// public bool Looping { diff --git a/osu.Game/Skinning/SkinnableSound.cs b/osu.Game/Skinning/SkinnableSound.cs index bb747a2176..24dddaf758 100644 --- a/osu.Game/Skinning/SkinnableSound.cs +++ b/osu.Game/Skinning/SkinnableSound.cs @@ -16,6 +16,9 @@ using osu.Game.Audio; namespace osu.Game.Skinning { + /// + /// A sound consisting of one or more samples to be played. + /// public class SkinnableSound : SkinReloadableDrawable, IAdjustableAudioComponent { public override bool RemoveWhenNotAlive => false; @@ -39,17 +42,28 @@ namespace osu.Game.Skinning [Resolved(CanBeNull = true)] private IPooledSampleProvider pooledProvider { get; set; } + /// + /// Creates a new . + /// public SkinnableSound() { InternalChild = SamplesContainer = new AudioContainer(); } + /// + /// Creates a new with some initial samples. + /// + /// The initial samples. public SkinnableSound([NotNull] IEnumerable samples) : this() { this.samples = samples.ToArray(); } + /// + /// Creates a new with an initial sample. + /// + /// The initial sample. public SkinnableSound([NotNull] ISampleInfo sample) : this(new[] { sample }) { @@ -57,6 +71,9 @@ namespace osu.Game.Skinning private ISampleInfo[] samples = Array.Empty(); + /// + /// The samples that should be played. + /// public ISampleInfo[] Samples { get => samples; @@ -76,6 +93,9 @@ namespace osu.Game.Skinning private bool looping; + /// + /// Whether the samples should loop on completion. + /// public bool Looping { get => looping; @@ -89,6 +109,9 @@ namespace osu.Game.Skinning } } + /// + /// Plays the samples. + /// public virtual void Play() { SamplesContainer.ForEach(c => @@ -98,6 +121,9 @@ namespace osu.Game.Skinning }); } + /// + /// Stops the samples. + /// public virtual void Stop() { SamplesContainer.ForEach(c => c.Stop()); @@ -149,6 +175,9 @@ namespace osu.Game.Skinning public void RemoveAllAdjustments(AdjustableProperty type) => SamplesContainer.RemoveAllAdjustments(type); + /// + /// Whether any samples currently playing. + /// public bool IsPlaying => SamplesContainer.Any(s => s.Playing); #endregion From 8080fe942cc19c6c2ea0db0cdcc92e7b0a329881 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 20 Nov 2020 20:38:26 +0900 Subject: [PATCH 014/184] Fix samples being played more than once on skin change --- osu.Game/Skinning/SkinnableSound.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Skinning/SkinnableSound.cs b/osu.Game/Skinning/SkinnableSound.cs index 24dddaf758..a6347fe05a 100644 --- a/osu.Game/Skinning/SkinnableSound.cs +++ b/osu.Game/Skinning/SkinnableSound.cs @@ -152,7 +152,7 @@ namespace osu.Game.Skinning SamplesContainer.Add(sample); } - if (wasPlaying) + if (wasPlaying && !Looping) Play(); } From a3b1d14f178620fd9556efad890a7a4874f4230c Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sun, 22 Nov 2020 14:44:39 +0900 Subject: [PATCH 015/184] Apply similar fix to PoolableSkinnableSound --- osu.Game/Skinning/PoolableSkinnableSample.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Skinning/PoolableSkinnableSample.cs b/osu.Game/Skinning/PoolableSkinnableSample.cs index adc58ee94e..65f97ff909 100644 --- a/osu.Game/Skinning/PoolableSkinnableSample.cs +++ b/osu.Game/Skinning/PoolableSkinnableSample.cs @@ -101,7 +101,7 @@ namespace osu.Game.Skinning sampleContainer.Add(Sample = new DrawableSample(ch) { Looping = Looping }); // Start playback internally for the new sample if the previous one was playing beforehand. - if (wasPlaying) + if (wasPlaying && !Looping) Play(); } From a7194e1bc347a204661c939517067cf931c997b6 Mon Sep 17 00:00:00 2001 From: ekrctb Date: Fri, 27 Nov 2020 15:41:35 +0900 Subject: [PATCH 016/184] add stateless RNG --- osu.Game/Utils/StatelessRNG.cs | 44 ++++++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) create mode 100644 osu.Game/Utils/StatelessRNG.cs diff --git a/osu.Game/Utils/StatelessRNG.cs b/osu.Game/Utils/StatelessRNG.cs new file mode 100644 index 0000000000..8d08b26ca4 --- /dev/null +++ b/osu.Game/Utils/StatelessRNG.cs @@ -0,0 +1,44 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +namespace osu.Game.Utils +{ + /// Provides a fast stateless function that can be used in randomly-looking visual elements. + public static class StatelessRNG + { + private static ulong mix(ulong x) + { + unchecked + { + x ^= x >> 33; + x *= 0xff51afd7ed558ccd; + x ^= x >> 33; + x *= 0xc4ceb9fe1a85ec53; + x ^= x >> 33; + return x; + } + } + + /// Compute an integer from given seed and series number. + /// + /// The seed value of this random number generator. + /// + /// + /// The series number. + /// Different values are computed for the same seed in different series. + /// + public static ulong Get(int seed, int series = 0) => + unchecked(mix(((ulong)(uint)series << 32) | ((uint)seed ^ 0x12345678))); + + /// Compute a floating point value between 0 and 1 (excluding 1) from given seed and series number. + /// + /// The seed value of this random number generator. + /// + /// + /// The series number. + /// Different values are computed for the same seed in different series. + /// + public static float GetSingle(int seed, int series = 0) => + (float)(Get(seed, series) & ((1 << 24) - 1)) / (1 << 24); // float has 24-bit precision + } +} From 3994cf082d835f9cb61dc687c2270bd800af2514 Mon Sep 17 00:00:00 2001 From: Ryan Zmuda Date: Sun, 29 Nov 2020 20:59:02 -0500 Subject: [PATCH 017/184] add keybind for in game overlay --- osu.Game/Configuration/OsuConfigManager.cs | 2 +- .../Input/Bindings/GlobalActionContainer.cs | 4 +++ osu.Game/Screens/Play/HUDOverlay.cs | 31 +++++++++++-------- 3 files changed, 23 insertions(+), 14 deletions(-) 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..a59d69e5b5 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(InputKey.I, GlobalAction.ToggleInGameInterface), new KeyBinding(InputKey.MouseMiddle, GlobalAction.PauseGameplay), new KeyBinding(InputKey.Space, GlobalAction.TogglePauseReplay), new KeyBinding(InputKey.Control, GlobalAction.HoldForHUD), @@ -145,6 +146,9 @@ namespace osu.Game.Input.Bindings [Description("Decrease scroll speed")] DecreaseScrollSpeed, + [Description("Toggle in-game interface")] + ToggleInGameInterface, + [Description("Select")] Select, diff --git a/osu.Game/Screens/Play/HUDOverlay.cs b/osu.Game/Screens/Play/HUDOverlay.cs index e83dded075..964e0d0536 100644 --- a/osu.Game/Screens/Play/HUDOverlay.cs +++ b/osu.Game/Screens/Play/HUDOverlay.cs @@ -282,20 +282,7 @@ namespace osu.Game.Screens.Play 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; } @@ -377,6 +364,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; + } + updateVisibility(); + return true; } return false; From a780a8bbd8db3e3e8bd8737480de1503df6f81b8 Mon Sep 17 00:00:00 2001 From: Ryan Zmuda Date: Sun, 29 Nov 2020 21:52:58 -0500 Subject: [PATCH 018/184] forgot to remove something... sorry --- osu.Game/Screens/Play/HUDOverlay.cs | 18 ------------------ 1 file changed, 18 deletions(-) diff --git a/osu.Game/Screens/Play/HUDOverlay.cs b/osu.Game/Screens/Play/HUDOverlay.cs index 964e0d0536..457706b8f5 100644 --- a/osu.Game/Screens/Play/HUDOverlay.cs +++ b/osu.Game/Screens/Play/HUDOverlay.cs @@ -273,24 +273,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: - - - return true; - } - } - - return base.OnKeyDown(e); - } - protected virtual SkinnableAccuracyCounter CreateAccuracyCounter() => new SkinnableAccuracyCounter(); protected virtual SkinnableScoreCounter CreateScoreCounter() => new SkinnableScoreCounter(); From 6478bed431ec467b5c3579a3d264b8719a6b1f81 Mon Sep 17 00:00:00 2001 From: Ryan Zmuda Date: Sun, 29 Nov 2020 23:14:43 -0500 Subject: [PATCH 019/184] Revert "forgot to remove something... sorry" This reverts commit a780a8bbd8db3e3e8bd8737480de1503df6f81b8. --- osu.Game/Screens/Play/HUDOverlay.cs | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/osu.Game/Screens/Play/HUDOverlay.cs b/osu.Game/Screens/Play/HUDOverlay.cs index 457706b8f5..964e0d0536 100644 --- a/osu.Game/Screens/Play/HUDOverlay.cs +++ b/osu.Game/Screens/Play/HUDOverlay.cs @@ -273,6 +273,24 @@ 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: + + + return true; + } + } + + return base.OnKeyDown(e); + } + protected virtual SkinnableAccuracyCounter CreateAccuracyCounter() => new SkinnableAccuracyCounter(); protected virtual SkinnableScoreCounter CreateScoreCounter() => new SkinnableScoreCounter(); From 9145557522e94e53aa4a0c74f0cc534d23329847 Mon Sep 17 00:00:00 2001 From: Ryan Zmuda Date: Sun, 29 Nov 2020 23:15:12 -0500 Subject: [PATCH 020/184] Revert "Revert "forgot to remove something... sorry"" This reverts commit 6478bed431ec467b5c3579a3d264b8719a6b1f81. --- osu.Game/Screens/Play/HUDOverlay.cs | 18 ------------------ 1 file changed, 18 deletions(-) diff --git a/osu.Game/Screens/Play/HUDOverlay.cs b/osu.Game/Screens/Play/HUDOverlay.cs index 964e0d0536..457706b8f5 100644 --- a/osu.Game/Screens/Play/HUDOverlay.cs +++ b/osu.Game/Screens/Play/HUDOverlay.cs @@ -273,24 +273,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: - - - return true; - } - } - - return base.OnKeyDown(e); - } - protected virtual SkinnableAccuracyCounter CreateAccuracyCounter() => new SkinnableAccuracyCounter(); protected virtual SkinnableScoreCounter CreateScoreCounter() => new SkinnableScoreCounter(); From 731e689f2da41dcaa040b5dde209f02b1306754d Mon Sep 17 00:00:00 2001 From: ekrctb Date: Mon, 30 Nov 2020 18:07:37 +0900 Subject: [PATCH 021/184] Add summary tags to the doc comments --- osu.Game/Utils/StatelessRNG.cs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/osu.Game/Utils/StatelessRNG.cs b/osu.Game/Utils/StatelessRNG.cs index 8d08b26ca4..d78d55cc09 100644 --- a/osu.Game/Utils/StatelessRNG.cs +++ b/osu.Game/Utils/StatelessRNG.cs @@ -3,7 +3,9 @@ namespace osu.Game.Utils { + /// /// Provides a fast stateless function that can be used in randomly-looking visual elements. + /// public static class StatelessRNG { private static ulong mix(ulong x) @@ -19,7 +21,9 @@ namespace osu.Game.Utils } } + /// /// Compute an integer from given seed and series number. + /// /// /// The seed value of this random number generator. /// @@ -30,7 +34,9 @@ namespace osu.Game.Utils public static ulong Get(int seed, int series = 0) => unchecked(mix(((ulong)(uint)series << 32) | ((uint)seed ^ 0x12345678))); + /// /// Compute a floating point value between 0 and 1 (excluding 1) from given seed and series number. + /// /// /// The seed value of this random number generator. /// From afb8eb636ddc4cd589755f796f1b8bad9e5adb30 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 30 Nov 2020 18:40:22 +0900 Subject: [PATCH 022/184] Apply simple PR reviews --- osu.Game/Skinning/IPooledSampleProvider.cs | 10 +++++++++- osu.Game/Skinning/PoolableSkinnableSample.cs | 4 ++++ osu.Game/Skinning/SkinnableSound.cs | 6 +++--- 3 files changed, 16 insertions(+), 4 deletions(-) diff --git a/osu.Game/Skinning/IPooledSampleProvider.cs b/osu.Game/Skinning/IPooledSampleProvider.cs index 3dc0b5375d..5dbbadcc8a 100644 --- a/osu.Game/Skinning/IPooledSampleProvider.cs +++ b/osu.Game/Skinning/IPooledSampleProvider.cs @@ -6,8 +6,16 @@ using osu.Game.Audio; namespace osu.Game.Skinning { - public interface IPooledSampleProvider + /// + /// Provides pooled samples to be used by s. + /// + internal interface IPooledSampleProvider { + /// + /// Retrieves a from a pool. + /// + /// The describing the sample to retrieve.. + /// The . [CanBeNull] PoolableSkinnableSample GetPooledSample(ISampleInfo sampleInfo); } diff --git a/osu.Game/Skinning/PoolableSkinnableSample.cs b/osu.Game/Skinning/PoolableSkinnableSample.cs index adc58ee94e..7e885b20d1 100644 --- a/osu.Game/Skinning/PoolableSkinnableSample.cs +++ b/osu.Game/Skinning/PoolableSkinnableSample.cs @@ -138,6 +138,8 @@ namespace osu.Game.Skinning } } + #region Re-expose AudioContainer + public BindableNumber Volume => sampleContainer.Volume; public BindableNumber Balance => sampleContainer.Balance; @@ -159,5 +161,7 @@ namespace osu.Game.Skinning public IBindable AggregateFrequency => sampleContainer.AggregateFrequency; public IBindable AggregateTempo => sampleContainer.AggregateTempo; + + #endregion } } diff --git a/osu.Game/Skinning/SkinnableSound.cs b/osu.Game/Skinning/SkinnableSound.cs index 24dddaf758..46c2e4b749 100644 --- a/osu.Game/Skinning/SkinnableSound.cs +++ b/osu.Game/Skinning/SkinnableSound.cs @@ -40,7 +40,7 @@ namespace osu.Game.Skinning private ISampleStore sampleStore { get; set; } [Resolved(CanBeNull = true)] - private IPooledSampleProvider pooledProvider { get; set; } + private IPooledSampleProvider samplePool { get; set; } /// /// Creates a new . @@ -145,7 +145,7 @@ namespace osu.Game.Skinning foreach (var s in samples) { - var sample = pooledProvider?.GetPooledSample(s) ?? new PoolableSkinnableSample(s); + var sample = samplePool?.GetPooledSample(s) ?? new PoolableSkinnableSample(s); sample.Looping = Looping; sample.Volume.Value = s.Volume / 100.0; @@ -176,7 +176,7 @@ namespace osu.Game.Skinning => SamplesContainer.RemoveAllAdjustments(type); /// - /// Whether any samples currently playing. + /// Whether any samples are currently playing. /// public bool IsPlaying => SamplesContainer.Any(s => s.Playing); From 51bddd4a0ff00fce883583852a2d225d5b41117c Mon Sep 17 00:00:00 2001 From: ekrctb Date: Mon, 30 Nov 2020 18:46:28 +0900 Subject: [PATCH 023/184] Rename functions, and add NextInt. --- osu.Game/Utils/StatelessRNG.cs | 42 +++++++++++++++++++++++++++++----- 1 file changed, 36 insertions(+), 6 deletions(-) diff --git a/osu.Game/Utils/StatelessRNG.cs b/osu.Game/Utils/StatelessRNG.cs index d78d55cc09..d316f718e3 100644 --- a/osu.Game/Utils/StatelessRNG.cs +++ b/osu.Game/Utils/StatelessRNG.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System; + namespace osu.Game.Utils { /// @@ -22,7 +24,7 @@ namespace osu.Game.Utils } /// - /// Compute an integer from given seed and series number. + /// Generate a random 64-bit unsigned integer from given seed. /// /// /// The seed value of this random number generator. @@ -31,11 +33,39 @@ namespace osu.Game.Utils /// The series number. /// Different values are computed for the same seed in different series. /// - public static ulong Get(int seed, int series = 0) => - unchecked(mix(((ulong)(uint)series << 32) | ((uint)seed ^ 0x12345678))); + public static ulong NextUlong(int seed, int series = 0) + { + unchecked + { + // + var combined = ((ulong)(uint)series << 32) | (uint)seed; + // The xor operation is to not map (0, 0) to 0. + return mix(combined ^ 0x12345678); + } + } /// - /// Compute a floating point value between 0 and 1 (excluding 1) from given seed and series number. + /// Generate a random integer in range [0, maxValue) from given seed. + /// + /// + /// The number of possible results. + /// + /// + /// The seed value of this random number generator. + /// + /// + /// The series number. + /// Different values are computed for the same seed in different series. + /// + public static int NextInt(int maxValue, int seed, int series = 0) + { + if (maxValue <= 0) throw new ArgumentOutOfRangeException(nameof(maxValue)); + + return (int)(NextUlong(seed, series) % (ulong)maxValue); + } + + /// + /// Compute a random floating point value between 0 and 1 (excluding 1) from given seed and series number. /// /// /// The seed value of this random number generator. @@ -44,7 +74,7 @@ namespace osu.Game.Utils /// The series number. /// Different values are computed for the same seed in different series. /// - public static float GetSingle(int seed, int series = 0) => - (float)(Get(seed, series) & ((1 << 24) - 1)) / (1 << 24); // float has 24-bit precision + public static float NextSingle(int seed, int series = 0) => + (float)(NextUlong(seed, series) & ((1 << 24) - 1)) / (1 << 24); // float has 24-bit precision } } From 05aaa377e74078c0e4aa3f591066a0e3644e4e51 Mon Sep 17 00:00:00 2001 From: ekrctb Date: Mon, 30 Nov 2020 19:02:49 +0900 Subject: [PATCH 024/184] Don't use CreateDrawableRepresentation in CatcherArea --- .../TestSceneCatcherArea.cs | 1 - osu.Game.Rulesets.Catch/UI/CatchPlayfield.cs | 1 - osu.Game.Rulesets.Catch/UI/CatcherArea.cs | 17 +++++++++++++---- 3 files changed, 13 insertions(+), 6 deletions(-) diff --git a/osu.Game.Rulesets.Catch.Tests/TestSceneCatcherArea.cs b/osu.Game.Rulesets.Catch.Tests/TestSceneCatcherArea.cs index e055f08dc2..2d46cbdbbd 100644 --- a/osu.Game.Rulesets.Catch.Tests/TestSceneCatcherArea.cs +++ b/osu.Game.Rulesets.Catch.Tests/TestSceneCatcherArea.cs @@ -103,7 +103,6 @@ namespace osu.Game.Rulesets.Catch.Tests { Anchor = Anchor.Centre, Origin = Anchor.TopCentre, - CreateDrawableRepresentation = ((DrawableRuleset)catchRuleset.CreateInstance().CreateDrawableRulesetWith(new CatchBeatmap())).CreateDrawableRepresentation }, }); } diff --git a/osu.Game.Rulesets.Catch/UI/CatchPlayfield.cs b/osu.Game.Rulesets.Catch/UI/CatchPlayfield.cs index 9df32d8d36..bab8356ac4 100644 --- a/osu.Game.Rulesets.Catch/UI/CatchPlayfield.cs +++ b/osu.Game.Rulesets.Catch/UI/CatchPlayfield.cs @@ -42,7 +42,6 @@ namespace osu.Game.Rulesets.Catch.UI CatcherArea = new CatcherArea(difficulty) { - CreateDrawableRepresentation = createDrawableRepresentation, ExplodingFruitTarget = explodingFruitContainer, Anchor = Anchor.BottomLeft, Origin = Anchor.TopLeft, diff --git a/osu.Game.Rulesets.Catch/UI/CatcherArea.cs b/osu.Game.Rulesets.Catch/UI/CatcherArea.cs index ad79a23279..085af79689 100644 --- a/osu.Game.Rulesets.Catch/UI/CatcherArea.cs +++ b/osu.Game.Rulesets.Catch/UI/CatcherArea.cs @@ -10,7 +10,6 @@ using osu.Game.Rulesets.Catch.Objects; using osu.Game.Rulesets.Catch.Objects.Drawables; using osu.Game.Rulesets.Catch.Replays; using osu.Game.Rulesets.Judgements; -using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.Scoring; using osu.Game.Rulesets.UI; using osuTK; @@ -21,8 +20,6 @@ namespace osu.Game.Rulesets.Catch.UI { public const float CATCHER_SIZE = 106.75f; - public Func> CreateDrawableRepresentation; - public readonly Catcher MovableCatcher; private readonly CatchComboDisplay comboDisplay; @@ -72,7 +69,7 @@ namespace osu.Game.Rulesets.Catch.UI if (result.IsHit && hitObject is DrawablePalpableCatchHitObject fruit) { // create a new (cloned) fruit to stay on the plate. the original is faded out immediately. - var caughtFruit = (DrawableCatchHitObject)CreateDrawableRepresentation?.Invoke(fruit.HitObject); + var caughtFruit = createCaughtFruit(fruit); if (caughtFruit == null) return; @@ -127,5 +124,17 @@ namespace osu.Game.Rulesets.Catch.UI comboDisplay.X = MovableCatcher.X; } + + private DrawableCatchHitObject createCaughtFruit(DrawablePalpableCatchHitObject hitObject) + { + return hitObject.HitObject switch + { + Banana banana => new DrawableBanana(banana), + Fruit fruit => new DrawableFruit(fruit), + TinyDroplet tiny => new DrawableTinyDroplet(tiny), + Droplet droplet => new DrawableDroplet(droplet), + _ => null + }; + } } } From 94fd607a7c548289147008dad8b43a14b1e3a62c Mon Sep 17 00:00:00 2001 From: ekrctb Date: Mon, 30 Nov 2020 19:04:09 +0900 Subject: [PATCH 025/184] Use hit object pooling for `Droplet` and `TinyDroplet`. --- .../Objects/Drawables/DrawableDroplet.cs | 8 +++++++- .../Objects/Drawables/DrawableTinyDroplet.cs | 9 ++++++++- osu.Game.Rulesets.Catch/UI/CatchPlayfield.cs | 8 ++++++++ osu.Game.Rulesets.Catch/UI/DrawableCatchRuleset.cs | 6 ------ 4 files changed, 23 insertions(+), 8 deletions(-) diff --git a/osu.Game.Rulesets.Catch/Objects/Drawables/DrawableDroplet.cs b/osu.Game.Rulesets.Catch/Objects/Drawables/DrawableDroplet.cs index 9e76265394..06ecd44488 100644 --- a/osu.Game.Rulesets.Catch/Objects/Drawables/DrawableDroplet.cs +++ b/osu.Game.Rulesets.Catch/Objects/Drawables/DrawableDroplet.cs @@ -1,6 +1,7 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using JetBrains.Annotations; using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Utils; @@ -13,7 +14,12 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawables { public override bool StaysOnPlate => false; - public DrawableDroplet(CatchHitObject h) + public DrawableDroplet() + : this(null) + { + } + + public DrawableDroplet([CanBeNull] CatchHitObject h) : base(h) { } diff --git a/osu.Game.Rulesets.Catch/Objects/Drawables/DrawableTinyDroplet.cs b/osu.Game.Rulesets.Catch/Objects/Drawables/DrawableTinyDroplet.cs index 8c4d821b4a..8f5a04dfda 100644 --- a/osu.Game.Rulesets.Catch/Objects/Drawables/DrawableTinyDroplet.cs +++ b/osu.Game.Rulesets.Catch/Objects/Drawables/DrawableTinyDroplet.cs @@ -1,13 +1,20 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using JetBrains.Annotations; + namespace osu.Game.Rulesets.Catch.Objects.Drawables { public class DrawableTinyDroplet : DrawableDroplet { protected override float ScaleFactor => base.ScaleFactor / 2; - public DrawableTinyDroplet(TinyDroplet h) + public DrawableTinyDroplet() + : this(null) + { + } + + public DrawableTinyDroplet([CanBeNull] TinyDroplet h) : base(h) { } diff --git a/osu.Game.Rulesets.Catch/UI/CatchPlayfield.cs b/osu.Game.Rulesets.Catch/UI/CatchPlayfield.cs index bab8356ac4..da909b49c9 100644 --- a/osu.Game.Rulesets.Catch/UI/CatchPlayfield.cs +++ b/osu.Game.Rulesets.Catch/UI/CatchPlayfield.cs @@ -2,6 +2,7 @@ // See the LICENCE file in the repository root for full licence text. using System; +using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Game.Beatmaps; @@ -56,6 +57,13 @@ namespace osu.Game.Rulesets.Catch.UI }; } + [BackgroundDependencyLoader] + private void load() + { + RegisterPool(1); + RegisterPool(1); + } + protected override void LoadComplete() { base.LoadComplete(); diff --git a/osu.Game.Rulesets.Catch/UI/DrawableCatchRuleset.cs b/osu.Game.Rulesets.Catch/UI/DrawableCatchRuleset.cs index ebe45aa3ab..8534645947 100644 --- a/osu.Game.Rulesets.Catch/UI/DrawableCatchRuleset.cs +++ b/osu.Game.Rulesets.Catch/UI/DrawableCatchRuleset.cs @@ -55,12 +55,6 @@ namespace osu.Game.Rulesets.Catch.UI case BananaShower shower: return new DrawableBananaShower(shower, CreateDrawableRepresentation); - - case TinyDroplet tiny: - return new DrawableTinyDroplet(tiny); - - case Droplet droplet: - return new DrawableDroplet(droplet); } return null; From b76ae525b27d5cf0173a3714f170fbf0844b98c0 Mon Sep 17 00:00:00 2001 From: ekrctb Date: Mon, 30 Nov 2020 19:07:50 +0900 Subject: [PATCH 026/184] Use hit object pooling for `Fruit` and `Banana`. --- osu.Game.Rulesets.Catch.Tests/TestSceneCatcherArea.cs | 2 -- .../Objects/Drawables/DrawableBanana.cs | 8 +++++++- .../Objects/Drawables/DrawableFruit.cs | 8 +++++++- osu.Game.Rulesets.Catch/UI/CatchPlayfield.cs | 2 ++ osu.Game.Rulesets.Catch/UI/DrawableCatchRuleset.cs | 6 ------ 5 files changed, 16 insertions(+), 10 deletions(-) diff --git a/osu.Game.Rulesets.Catch.Tests/TestSceneCatcherArea.cs b/osu.Game.Rulesets.Catch.Tests/TestSceneCatcherArea.cs index 2d46cbdbbd..c12f38723b 100644 --- a/osu.Game.Rulesets.Catch.Tests/TestSceneCatcherArea.cs +++ b/osu.Game.Rulesets.Catch.Tests/TestSceneCatcherArea.cs @@ -10,14 +10,12 @@ using osu.Framework.Testing; using osu.Game.Beatmaps; using osu.Game.Beatmaps.ControlPoints; using osu.Game.Configuration; -using osu.Game.Rulesets.Catch.Beatmaps; using osu.Game.Rulesets.Catch.Judgements; using osu.Game.Rulesets.Catch.Objects; using osu.Game.Rulesets.Catch.Objects.Drawables; using osu.Game.Rulesets.Catch.UI; using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Scoring; -using osu.Game.Rulesets.UI; namespace osu.Game.Rulesets.Catch.Tests { diff --git a/osu.Game.Rulesets.Catch/Objects/Drawables/DrawableBanana.cs b/osu.Game.Rulesets.Catch/Objects/Drawables/DrawableBanana.cs index efb0958a3a..fb982bbdab 100644 --- a/osu.Game.Rulesets.Catch/Objects/Drawables/DrawableBanana.cs +++ b/osu.Game.Rulesets.Catch/Objects/Drawables/DrawableBanana.cs @@ -1,6 +1,7 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using JetBrains.Annotations; using osu.Framework.Graphics; using osu.Framework.Utils; @@ -10,7 +11,12 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawables { protected override FruitVisualRepresentation GetVisualRepresentation(int indexInBeatmap) => FruitVisualRepresentation.Banana; - public DrawableBanana(Banana h) + public DrawableBanana() + : this(null) + { + } + + public DrawableBanana([CanBeNull] Banana h) : base(h) { } diff --git a/osu.Game.Rulesets.Catch/Objects/Drawables/DrawableFruit.cs b/osu.Game.Rulesets.Catch/Objects/Drawables/DrawableFruit.cs index 4338d80345..68cb649b66 100644 --- a/osu.Game.Rulesets.Catch/Objects/Drawables/DrawableFruit.cs +++ b/osu.Game.Rulesets.Catch/Objects/Drawables/DrawableFruit.cs @@ -2,6 +2,7 @@ // See the LICENCE file in the repository root for full licence text. using System; +using JetBrains.Annotations; using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Utils; @@ -16,7 +17,12 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawables protected virtual FruitVisualRepresentation GetVisualRepresentation(int indexInBeatmap) => (FruitVisualRepresentation)(indexInBeatmap % 4); - public DrawableFruit(CatchHitObject h) + public DrawableFruit() + : this(null) + { + } + + public DrawableFruit([CanBeNull] Fruit h) : base(h) { } diff --git a/osu.Game.Rulesets.Catch/UI/CatchPlayfield.cs b/osu.Game.Rulesets.Catch/UI/CatchPlayfield.cs index da909b49c9..7cddec100f 100644 --- a/osu.Game.Rulesets.Catch/UI/CatchPlayfield.cs +++ b/osu.Game.Rulesets.Catch/UI/CatchPlayfield.cs @@ -62,6 +62,8 @@ namespace osu.Game.Rulesets.Catch.UI { RegisterPool(1); RegisterPool(1); + RegisterPool(1); + RegisterPool(1); } protected override void LoadComplete() diff --git a/osu.Game.Rulesets.Catch/UI/DrawableCatchRuleset.cs b/osu.Game.Rulesets.Catch/UI/DrawableCatchRuleset.cs index 8534645947..ecc37549bf 100644 --- a/osu.Game.Rulesets.Catch/UI/DrawableCatchRuleset.cs +++ b/osu.Game.Rulesets.Catch/UI/DrawableCatchRuleset.cs @@ -44,12 +44,6 @@ namespace osu.Game.Rulesets.Catch.UI { switch (h) { - case Banana banana: - return new DrawableBanana(banana); - - case Fruit fruit: - return new DrawableFruit(fruit); - case JuiceStream stream: return new DrawableJuiceStream(stream, CreateDrawableRepresentation); From 9611aaf09eb0c9653b2c79d65a062fa2dfe572d4 Mon Sep 17 00:00:00 2001 From: ekrctb Date: Mon, 30 Nov 2020 19:19:14 +0900 Subject: [PATCH 027/184] Use hit object pooling for `JuiceStream`. - Use `Clear(false)` to not dispose pooled children. - Don't set nested DHO `Origin`. - Simplify the layout (remove custom `Origin`). --- .../TestSceneDrawableHitObjects.cs | 2 +- .../Objects/Drawables/DrawableJuiceStream.cs | 29 +++++-------------- osu.Game.Rulesets.Catch/UI/CatchPlayfield.cs | 1 + .../UI/DrawableCatchRuleset.cs | 3 -- 4 files changed, 9 insertions(+), 26 deletions(-) diff --git a/osu.Game.Rulesets.Catch.Tests/TestSceneDrawableHitObjects.cs b/osu.Game.Rulesets.Catch.Tests/TestSceneDrawableHitObjects.cs index d35f828e28..3e4995482d 100644 --- a/osu.Game.Rulesets.Catch.Tests/TestSceneDrawableHitObjects.cs +++ b/osu.Game.Rulesets.Catch.Tests/TestSceneDrawableHitObjects.cs @@ -136,7 +136,7 @@ namespace osu.Game.Rulesets.Catch.Tests if (juice.NestedHitObjects.Last() is CatchHitObject tail) tail.LastInCombo = true; // usually the (Catch)BeatmapProcessor would do this for us when necessary - addToPlayfield(new DrawableJuiceStream(juice, drawableRuleset.CreateDrawableRepresentation)); + addToPlayfield(new DrawableJuiceStream(juice)); } private void spawnBananas(bool hit = false) diff --git a/osu.Game.Rulesets.Catch/Objects/Drawables/DrawableJuiceStream.cs b/osu.Game.Rulesets.Catch/Objects/Drawables/DrawableJuiceStream.cs index a7a5bfa5ad..a496a35842 100644 --- a/osu.Game.Rulesets.Catch/Objects/Drawables/DrawableJuiceStream.cs +++ b/osu.Game.Rulesets.Catch/Objects/Drawables/DrawableJuiceStream.cs @@ -1,37 +1,33 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -using System; +using JetBrains.Annotations; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; -using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Objects.Drawables; -using osuTK; namespace osu.Game.Rulesets.Catch.Objects.Drawables { public class DrawableJuiceStream : DrawableCatchHitObject { - private readonly Func> createDrawableRepresentation; private readonly Container dropletContainer; - public override Vector2 OriginPosition => base.OriginPosition - new Vector2(0, CatchHitObject.OBJECT_RADIUS); + public DrawableJuiceStream() + : this(null) + { + } - public DrawableJuiceStream(JuiceStream s, Func> createDrawableRepresentation = null) + public DrawableJuiceStream([CanBeNull] JuiceStream s) : base(s) { - this.createDrawableRepresentation = createDrawableRepresentation; RelativeSizeAxes = Axes.X; Origin = Anchor.BottomLeft; - X = 0; AddInternal(dropletContainer = new Container { RelativeSizeAxes = Axes.Both, }); } protected override void AddNestedHitObject(DrawableHitObject hitObject) { - hitObject.Origin = Anchor.BottomCentre; - base.AddNestedHitObject(hitObject); dropletContainer.Add(hitObject); } @@ -39,18 +35,7 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawables protected override void ClearNestedHitObjects() { base.ClearNestedHitObjects(); - dropletContainer.Clear(); - } - - protected override DrawableHitObject CreateNestedHitObject(HitObject hitObject) - { - switch (hitObject) - { - case CatchHitObject catchObject: - return createDrawableRepresentation?.Invoke(catchObject); - } - - throw new ArgumentException($"{nameof(hitObject)} must be of type {nameof(CatchHitObject)}."); + dropletContainer.Clear(false); } } } diff --git a/osu.Game.Rulesets.Catch/UI/CatchPlayfield.cs b/osu.Game.Rulesets.Catch/UI/CatchPlayfield.cs index 7cddec100f..b4d97fdd2b 100644 --- a/osu.Game.Rulesets.Catch/UI/CatchPlayfield.cs +++ b/osu.Game.Rulesets.Catch/UI/CatchPlayfield.cs @@ -64,6 +64,7 @@ namespace osu.Game.Rulesets.Catch.UI RegisterPool(1); RegisterPool(1); RegisterPool(1); + RegisterPool(1); } protected override void LoadComplete() diff --git a/osu.Game.Rulesets.Catch/UI/DrawableCatchRuleset.cs b/osu.Game.Rulesets.Catch/UI/DrawableCatchRuleset.cs index ecc37549bf..beea7980c9 100644 --- a/osu.Game.Rulesets.Catch/UI/DrawableCatchRuleset.cs +++ b/osu.Game.Rulesets.Catch/UI/DrawableCatchRuleset.cs @@ -44,9 +44,6 @@ namespace osu.Game.Rulesets.Catch.UI { switch (h) { - case JuiceStream stream: - return new DrawableJuiceStream(stream, CreateDrawableRepresentation); - case BananaShower shower: return new DrawableBananaShower(shower, CreateDrawableRepresentation); } From f5e8d1d14d47934976b930df6cca83831ce07a6b Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 30 Nov 2020 19:19:24 +0900 Subject: [PATCH 028/184] Lose old reference immediately on updateSample() --- osu.Game/Skinning/PoolableSkinnableSample.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/osu.Game/Skinning/PoolableSkinnableSample.cs b/osu.Game/Skinning/PoolableSkinnableSample.cs index 7e885b20d1..19b96d6c60 100644 --- a/osu.Game/Skinning/PoolableSkinnableSample.cs +++ b/osu.Game/Skinning/PoolableSkinnableSample.cs @@ -83,6 +83,7 @@ namespace osu.Game.Skinning bool wasPlaying = Playing; sampleContainer.Clear(); + Sample = null; var ch = CurrentSkin.GetSample(sampleInfo); From 70628235e36ec7d22e84a885b5ee475cfb88eb6a Mon Sep 17 00:00:00 2001 From: ekrctb Date: Mon, 30 Nov 2020 19:22:40 +0900 Subject: [PATCH 029/184] Use hit object pooling for `BananaShower`. --- .../Objects/Drawables/DrawableBananaShower.cs | 26 ++++++------------- osu.Game.Rulesets.Catch/UI/CatchPlayfield.cs | 1 + .../UI/DrawableCatchRuleset.cs | 12 +-------- 3 files changed, 10 insertions(+), 29 deletions(-) diff --git a/osu.Game.Rulesets.Catch/Objects/Drawables/DrawableBananaShower.cs b/osu.Game.Rulesets.Catch/Objects/Drawables/DrawableBananaShower.cs index bf771f690e..9b2f95e221 100644 --- a/osu.Game.Rulesets.Catch/Objects/Drawables/DrawableBananaShower.cs +++ b/osu.Game.Rulesets.Catch/Objects/Drawables/DrawableBananaShower.cs @@ -1,26 +1,27 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -using System; +using JetBrains.Annotations; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; -using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Objects.Drawables; namespace osu.Game.Rulesets.Catch.Objects.Drawables { public class DrawableBananaShower : DrawableCatchHitObject { - private readonly Func> createDrawableRepresentation; private readonly Container bananaContainer; - public DrawableBananaShower(BananaShower s, Func> createDrawableRepresentation = null) + public DrawableBananaShower() + : this(null) + { + } + + public DrawableBananaShower([CanBeNull] BananaShower s) : base(s) { - this.createDrawableRepresentation = createDrawableRepresentation; RelativeSizeAxes = Axes.X; Origin = Anchor.BottomLeft; - X = 0; AddInternal(bananaContainer = new Container { RelativeSizeAxes = Axes.Both }); } @@ -34,18 +35,7 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawables protected override void ClearNestedHitObjects() { base.ClearNestedHitObjects(); - bananaContainer.Clear(); - } - - protected override DrawableHitObject CreateNestedHitObject(HitObject hitObject) - { - switch (hitObject) - { - case Banana banana: - return createDrawableRepresentation?.Invoke(banana); - } - - return base.CreateNestedHitObject(hitObject); + bananaContainer.Clear(false); } } } diff --git a/osu.Game.Rulesets.Catch/UI/CatchPlayfield.cs b/osu.Game.Rulesets.Catch/UI/CatchPlayfield.cs index b4d97fdd2b..97f33007fe 100644 --- a/osu.Game.Rulesets.Catch/UI/CatchPlayfield.cs +++ b/osu.Game.Rulesets.Catch/UI/CatchPlayfield.cs @@ -65,6 +65,7 @@ namespace osu.Game.Rulesets.Catch.UI RegisterPool(1); RegisterPool(1); RegisterPool(1); + RegisterPool(1); } protected override void LoadComplete() diff --git a/osu.Game.Rulesets.Catch/UI/DrawableCatchRuleset.cs b/osu.Game.Rulesets.Catch/UI/DrawableCatchRuleset.cs index beea7980c9..46733181e3 100644 --- a/osu.Game.Rulesets.Catch/UI/DrawableCatchRuleset.cs +++ b/osu.Game.Rulesets.Catch/UI/DrawableCatchRuleset.cs @@ -8,7 +8,6 @@ using osu.Game.Configuration; using osu.Game.Input.Handlers; using osu.Game.Replays; using osu.Game.Rulesets.Catch.Objects; -using osu.Game.Rulesets.Catch.Objects.Drawables; using osu.Game.Rulesets.Catch.Replays; using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.Objects.Drawables; @@ -40,15 +39,6 @@ namespace osu.Game.Rulesets.Catch.UI protected override PassThroughInputManager CreateInputManager() => new CatchInputManager(Ruleset.RulesetInfo); - public override DrawableHitObject CreateDrawableRepresentation(CatchHitObject h) - { - switch (h) - { - case BananaShower shower: - return new DrawableBananaShower(shower, CreateDrawableRepresentation); - } - - return null; - } + public override DrawableHitObject CreateDrawableRepresentation(CatchHitObject h) => null; } } From f589da43177a1df974bbfc8e59e4596459c22672 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 30 Nov 2020 19:24:38 +0900 Subject: [PATCH 030/184] Fix compilation error --- osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinner.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinner.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinner.cs index e5fc717504..1ba17d9e17 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinner.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinner.cs @@ -104,9 +104,9 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables private const float spinning_sample_initial_frequency = 1.0f; private const float spinning_sample_modulated_base_frequency = 0.5f; - protected override void OnFree(HitObject hitObject) + protected override void OnFree() { - base.OnFree(hitObject); + base.OnFree(); spinningSample.Samples = null; } From c29ad8edf8731bbaf0d3189a2917b00b7f7cde33 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 30 Nov 2020 19:26:25 +0900 Subject: [PATCH 031/184] Better API for dealing with the contained drawable samples --- osu.Game/Skinning/SkinnableSound.cs | 39 +++++++++++-------- .../Drawables/DrawableStoryboardSample.cs | 4 +- 2 files changed, 25 insertions(+), 18 deletions(-) diff --git a/osu.Game/Skinning/SkinnableSound.cs b/osu.Game/Skinning/SkinnableSound.cs index 46c2e4b749..23159e4fe1 100644 --- a/osu.Game/Skinning/SkinnableSound.cs +++ b/osu.Game/Skinning/SkinnableSound.cs @@ -11,6 +11,7 @@ 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.Game.Audio; @@ -34,7 +35,13 @@ namespace osu.Game.Skinning /// protected bool PlayWhenZeroVolume => Looping; - protected readonly AudioContainer SamplesContainer; + /// + /// All raw s contained in this . + /// + [NotNull, ItemNotNull] + protected IEnumerable DrawableSamples => samplesContainer.Select(c => c.Sample).Where(s => s != null); + + private readonly AudioContainer samplesContainer; [Resolved] private ISampleStore sampleStore { get; set; } @@ -47,7 +54,7 @@ namespace osu.Game.Skinning /// public SkinnableSound() { - InternalChild = SamplesContainer = new AudioContainer(); + InternalChild = samplesContainer = new AudioContainer(); } /// @@ -105,7 +112,7 @@ namespace osu.Game.Skinning looping = value; - SamplesContainer.ForEach(c => c.Looping = looping); + samplesContainer.ForEach(c => c.Looping = looping); } } @@ -114,7 +121,7 @@ namespace osu.Game.Skinning /// public virtual void Play() { - SamplesContainer.ForEach(c => + samplesContainer.ForEach(c => { if (PlayWhenZeroVolume || c.AggregateVolume.Value > 0) c.Play(); @@ -126,7 +133,7 @@ namespace osu.Game.Skinning /// public virtual void Stop() { - SamplesContainer.ForEach(c => c.Stop()); + samplesContainer.ForEach(c => c.Stop()); } protected override void SkinChanged(ISkinSource skin, bool allowFallback) @@ -140,8 +147,8 @@ namespace osu.Game.Skinning bool wasPlaying = IsPlaying; // Remove all pooled samples (return them to the pool), and dispose the rest. - SamplesContainer.RemoveAll(s => s.IsInPool); - SamplesContainer.Clear(); + samplesContainer.RemoveAll(s => s.IsInPool); + samplesContainer.Clear(); foreach (var s in samples) { @@ -149,7 +156,7 @@ namespace osu.Game.Skinning sample.Looping = Looping; sample.Volume.Value = s.Volume / 100.0; - SamplesContainer.Add(sample); + samplesContainer.Add(sample); } if (wasPlaying) @@ -158,27 +165,27 @@ namespace osu.Game.Skinning #region Re-expose AudioContainer - public BindableNumber Volume => SamplesContainer.Volume; + public BindableNumber Volume => samplesContainer.Volume; - public BindableNumber Balance => SamplesContainer.Balance; + public BindableNumber Balance => samplesContainer.Balance; - public BindableNumber Frequency => SamplesContainer.Frequency; + public BindableNumber Frequency => samplesContainer.Frequency; - public BindableNumber Tempo => SamplesContainer.Tempo; + public BindableNumber Tempo => samplesContainer.Tempo; public void AddAdjustment(AdjustableProperty type, BindableNumber adjustBindable) - => SamplesContainer.AddAdjustment(type, adjustBindable); + => samplesContainer.AddAdjustment(type, adjustBindable); public void RemoveAdjustment(AdjustableProperty type, BindableNumber adjustBindable) - => SamplesContainer.RemoveAdjustment(type, adjustBindable); + => samplesContainer.RemoveAdjustment(type, adjustBindable); public void RemoveAllAdjustments(AdjustableProperty type) - => SamplesContainer.RemoveAllAdjustments(type); + => samplesContainer.RemoveAllAdjustments(type); /// /// Whether any samples are currently playing. /// - public bool IsPlaying => SamplesContainer.Any(s => s.Playing); + public bool IsPlaying => samplesContainer.Any(s => s.Playing); #endregion } diff --git a/osu.Game/Storyboards/Drawables/DrawableStoryboardSample.cs b/osu.Game/Storyboards/Drawables/DrawableStoryboardSample.cs index 904af730de..218f051bf0 100644 --- a/osu.Game/Storyboards/Drawables/DrawableStoryboardSample.cs +++ b/osu.Game/Storyboards/Drawables/DrawableStoryboardSample.cs @@ -37,8 +37,8 @@ namespace osu.Game.Storyboards.Drawables foreach (var mod in mods.Value.OfType()) { - foreach (var sample in SamplesContainer) - mod.ApplyToSample(sample.Sample); + foreach (var sample in DrawableSamples) + mod.ApplyToSample(sample); } } From 4cd234ea05bb47e6600be35d69a637571d70f315 Mon Sep 17 00:00:00 2001 From: ekrctb Date: Mon, 30 Nov 2020 19:56:12 +0900 Subject: [PATCH 032/184] Fix null reference of LegacyFruitPiece --- osu.Game.Rulesets.Catch/Skinning/LegacyFruitPiece.cs | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/osu.Game.Rulesets.Catch/Skinning/LegacyFruitPiece.cs b/osu.Game.Rulesets.Catch/Skinning/LegacyFruitPiece.cs index 1494ef3888..b8648f46f0 100644 --- a/osu.Game.Rulesets.Catch/Skinning/LegacyFruitPiece.cs +++ b/osu.Game.Rulesets.Catch/Skinning/LegacyFruitPiece.cs @@ -19,7 +19,8 @@ namespace osu.Game.Rulesets.Catch.Skinning { private readonly string lookupName; - private readonly IBindable accentColour = new Bindable(); + private readonly Bindable accentColour = new Bindable(); + private readonly Bindable hyperDash = new Bindable(); private Sprite colouredSprite; public LegacyFruitPiece(string lookupName) @@ -34,6 +35,7 @@ namespace osu.Game.Rulesets.Catch.Skinning var drawableCatchObject = (DrawablePalpableCatchHitObject)drawableObject; accentColour.BindTo(drawableCatchObject.AccentColour); + hyperDash.BindTo(drawableCatchObject.HyperDash); InternalChildren = new Drawable[] { @@ -51,9 +53,9 @@ namespace osu.Game.Rulesets.Catch.Skinning }, }; - if (drawableCatchObject.HitObject.HyperDash) + if (hyperDash.Value) { - var hyperDash = new Sprite + var hyperDashOverlay = new Sprite { Anchor = Anchor.Centre, Origin = Anchor.Centre, @@ -67,7 +69,7 @@ namespace osu.Game.Rulesets.Catch.Skinning Catcher.DEFAULT_HYPER_DASH_COLOUR, }; - AddInternal(hyperDash); + AddInternal(hyperDashOverlay); } } From b5e43144a9be23ee4f2435981ab7f25ea8fcdef0 Mon Sep 17 00:00:00 2001 From: ekrctb Date: Mon, 30 Nov 2020 19:56:32 +0900 Subject: [PATCH 033/184] Add a Player test scene that uses a legacy skin --- .../TestSceneCatchPlayerLegacySkin.cs | 46 +++++++++++++++++++ 1 file changed, 46 insertions(+) create mode 100644 osu.Game.Rulesets.Catch.Tests/TestSceneCatchPlayerLegacySkin.cs diff --git a/osu.Game.Rulesets.Catch.Tests/TestSceneCatchPlayerLegacySkin.cs b/osu.Game.Rulesets.Catch.Tests/TestSceneCatchPlayerLegacySkin.cs new file mode 100644 index 0000000000..47c542374a --- /dev/null +++ b/osu.Game.Rulesets.Catch.Tests/TestSceneCatchPlayerLegacySkin.cs @@ -0,0 +1,46 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using NUnit.Framework; +using osu.Framework.Allocation; +using osu.Framework.Audio; +using osu.Framework.IO.Stores; +using osu.Game.Skinning; +using osu.Game.Tests.Visual; + +namespace osu.Game.Rulesets.Catch.Tests +{ + [TestFixture] + public class TestSceneCatchPlayerLegacySkin : PlayerTestScene + { + private ISkinSource legacySkinSource; + + protected override TestPlayer CreatePlayer(Ruleset ruleset) => new SkinProvidingPlayer(legacySkinSource); + + [BackgroundDependencyLoader] + private void load(AudioManager audio, OsuGameBase game) + { + var legacySkin = new DefaultLegacySkin(new NamespacedResourceStore(game.Resources, "Skins/Legacy"), audio); + legacySkinSource = new SkinProvidingContainer(legacySkin); + } + + protected override Ruleset CreatePlayerRuleset() => new CatchRuleset(); + + public class SkinProvidingPlayer : TestPlayer + { + private readonly ISkinSource skinSource; + + public SkinProvidingPlayer(ISkinSource skinSource) + { + this.skinSource = skinSource; + } + + protected override IReadOnlyDependencyContainer CreateChildDependencies(IReadOnlyDependencyContainer parent) + { + var dependencies = new DependencyContainer(base.CreateChildDependencies(parent)); + dependencies.CacheAs(skinSource); + return dependencies; + } + } + } +} From 2c57deea2bd2724a0a333146f58c2002c18e0c22 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Mon, 30 Nov 2020 19:43:20 +0100 Subject: [PATCH 034/184] Trim double full-stop in xmldoc --- osu.Game/Skinning/IPooledSampleProvider.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Skinning/IPooledSampleProvider.cs b/osu.Game/Skinning/IPooledSampleProvider.cs index 5dbbadcc8a..40193d1a1a 100644 --- a/osu.Game/Skinning/IPooledSampleProvider.cs +++ b/osu.Game/Skinning/IPooledSampleProvider.cs @@ -14,7 +14,7 @@ namespace osu.Game.Skinning /// /// Retrieves a from a pool. /// - /// The describing the sample to retrieve.. + /// The describing the sample to retrieve. /// The . [CanBeNull] PoolableSkinnableSample GetPooledSample(ISampleInfo sampleInfo); From 588a5c2aff768e7139d522b9e3acfe81d111afcf Mon Sep 17 00:00:00 2001 From: ekrctb Date: Tue, 1 Dec 2020 09:35:28 +0900 Subject: [PATCH 035/184] Remove empty comment --- osu.Game/Utils/StatelessRNG.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/osu.Game/Utils/StatelessRNG.cs b/osu.Game/Utils/StatelessRNG.cs index d316f718e3..11d079498a 100644 --- a/osu.Game/Utils/StatelessRNG.cs +++ b/osu.Game/Utils/StatelessRNG.cs @@ -37,7 +37,6 @@ namespace osu.Game.Utils { unchecked { - // var combined = ((ulong)(uint)series << 32) | (uint)seed; // The xor operation is to not map (0, 0) to 0. return mix(combined ^ 0x12345678); From 4f17e3520e3dfef916a194d10fb9c46e4abcf9af Mon Sep 17 00:00:00 2001 From: ekrctb Date: Tue, 1 Dec 2020 09:38:19 +0900 Subject: [PATCH 036/184] Use Cached attribute --- .../TestSceneCatchPlayerLegacySkin.cs | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/osu.Game.Rulesets.Catch.Tests/TestSceneCatchPlayerLegacySkin.cs b/osu.Game.Rulesets.Catch.Tests/TestSceneCatchPlayerLegacySkin.cs index 47c542374a..f9f51ef54a 100644 --- a/osu.Game.Rulesets.Catch.Tests/TestSceneCatchPlayerLegacySkin.cs +++ b/osu.Game.Rulesets.Catch.Tests/TestSceneCatchPlayerLegacySkin.cs @@ -28,19 +28,13 @@ namespace osu.Game.Rulesets.Catch.Tests public class SkinProvidingPlayer : TestPlayer { + [Cached(typeof(ISkinSource))] private readonly ISkinSource skinSource; public SkinProvidingPlayer(ISkinSource skinSource) { this.skinSource = skinSource; } - - protected override IReadOnlyDependencyContainer CreateChildDependencies(IReadOnlyDependencyContainer parent) - { - var dependencies = new DependencyContainer(base.CreateChildDependencies(parent)); - dependencies.CacheAs(skinSource); - return dependencies; - } } } } From 604619ba47c41537cac4e49c9aeb67f2dd3320bb Mon Sep 17 00:00:00 2001 From: ekrctb Date: Tue, 1 Dec 2020 09:49:04 +0900 Subject: [PATCH 037/184] Generalize legacy skin player test. --- .../TestSceneCatchPlayerLegacySkin.cs | 28 +------------- .../Tests/Visual/LegacySkinPlayerTestScene.cs | 38 +++++++++++++++++++ 2 files changed, 39 insertions(+), 27 deletions(-) create mode 100644 osu.Game/Tests/Visual/LegacySkinPlayerTestScene.cs diff --git a/osu.Game.Rulesets.Catch.Tests/TestSceneCatchPlayerLegacySkin.cs b/osu.Game.Rulesets.Catch.Tests/TestSceneCatchPlayerLegacySkin.cs index f9f51ef54a..64695153b5 100644 --- a/osu.Game.Rulesets.Catch.Tests/TestSceneCatchPlayerLegacySkin.cs +++ b/osu.Game.Rulesets.Catch.Tests/TestSceneCatchPlayerLegacySkin.cs @@ -2,39 +2,13 @@ // See the LICENCE file in the repository root for full licence text. using NUnit.Framework; -using osu.Framework.Allocation; -using osu.Framework.Audio; -using osu.Framework.IO.Stores; -using osu.Game.Skinning; using osu.Game.Tests.Visual; namespace osu.Game.Rulesets.Catch.Tests { [TestFixture] - public class TestSceneCatchPlayerLegacySkin : PlayerTestScene + public class TestSceneCatchPlayerLegacySkin : LegacySkinPlayerTestScene { - private ISkinSource legacySkinSource; - - protected override TestPlayer CreatePlayer(Ruleset ruleset) => new SkinProvidingPlayer(legacySkinSource); - - [BackgroundDependencyLoader] - private void load(AudioManager audio, OsuGameBase game) - { - var legacySkin = new DefaultLegacySkin(new NamespacedResourceStore(game.Resources, "Skins/Legacy"), audio); - legacySkinSource = new SkinProvidingContainer(legacySkin); - } - protected override Ruleset CreatePlayerRuleset() => new CatchRuleset(); - - public class SkinProvidingPlayer : TestPlayer - { - [Cached(typeof(ISkinSource))] - private readonly ISkinSource skinSource; - - public SkinProvidingPlayer(ISkinSource skinSource) - { - this.skinSource = skinSource; - } - } } } diff --git a/osu.Game/Tests/Visual/LegacySkinPlayerTestScene.cs b/osu.Game/Tests/Visual/LegacySkinPlayerTestScene.cs new file mode 100644 index 0000000000..054f72400e --- /dev/null +++ b/osu.Game/Tests/Visual/LegacySkinPlayerTestScene.cs @@ -0,0 +1,38 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using NUnit.Framework; +using osu.Framework.Allocation; +using osu.Framework.Audio; +using osu.Framework.IO.Stores; +using osu.Game.Rulesets; +using osu.Game.Skinning; + +namespace osu.Game.Tests.Visual +{ + [TestFixture] + public abstract class LegacySkinPlayerTestScene : PlayerTestScene + { + private ISkinSource legacySkinSource; + + protected override TestPlayer CreatePlayer(Ruleset ruleset) => new SkinProvidingPlayer(legacySkinSource); + + [BackgroundDependencyLoader] + private void load(AudioManager audio, OsuGameBase game) + { + var legacySkin = new DefaultLegacySkin(new NamespacedResourceStore(game.Resources, "Skins/Legacy"), audio); + legacySkinSource = new SkinProvidingContainer(legacySkin); + } + + public class SkinProvidingPlayer : TestPlayer + { + [Cached(typeof(ISkinSource))] + private readonly ISkinSource skinSource; + + public SkinProvidingPlayer(ISkinSource skinSource) + { + this.skinSource = skinSource; + } + } + } +} From d1076778fd3749a25b1d1eb2277255bdaee0aab1 Mon Sep 17 00:00:00 2001 From: ekrctb Date: Tue, 1 Dec 2020 09:50:52 +0900 Subject: [PATCH 038/184] Convert switch expression to switch statement --- osu.Game.Rulesets.Catch/UI/CatcherArea.cs | 23 ++++++++++++++++------- 1 file changed, 16 insertions(+), 7 deletions(-) diff --git a/osu.Game.Rulesets.Catch/UI/CatcherArea.cs b/osu.Game.Rulesets.Catch/UI/CatcherArea.cs index 085af79689..26077aeba4 100644 --- a/osu.Game.Rulesets.Catch/UI/CatcherArea.cs +++ b/osu.Game.Rulesets.Catch/UI/CatcherArea.cs @@ -127,14 +127,23 @@ namespace osu.Game.Rulesets.Catch.UI private DrawableCatchHitObject createCaughtFruit(DrawablePalpableCatchHitObject hitObject) { - return hitObject.HitObject switch + switch (hitObject.HitObject) { - Banana banana => new DrawableBanana(banana), - Fruit fruit => new DrawableFruit(fruit), - TinyDroplet tiny => new DrawableTinyDroplet(tiny), - Droplet droplet => new DrawableDroplet(droplet), - _ => null - }; + case Banana banana: + return new DrawableBanana(banana); + + case Fruit fruit: + return new DrawableFruit(fruit); + + case TinyDroplet tiny: + return new DrawableTinyDroplet(tiny); + + case Droplet droplet: + return new DrawableDroplet(droplet); + + default: + return null; + } } } } From e102f2e8fa390853210038a5b3dd3552997e9cdb Mon Sep 17 00:00:00 2001 From: Ryan Zmuda Date: Mon, 30 Nov 2020 21:38:16 -0500 Subject: [PATCH 039/184] Moved enum to bottom, change defualt bind to Shift-Tab, Fixed Notification --- osu.Game/Input/Bindings/GlobalActionContainer.cs | 8 ++++---- osu.Game/Screens/Play/HUDOverlay.cs | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/osu.Game/Input/Bindings/GlobalActionContainer.cs b/osu.Game/Input/Bindings/GlobalActionContainer.cs index a59d69e5b5..f4a4813b94 100644 --- a/osu.Game/Input/Bindings/GlobalActionContainer.cs +++ b/osu.Game/Input/Bindings/GlobalActionContainer.cs @@ -68,7 +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(InputKey.I, GlobalAction.ToggleInGameInterface), + 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), @@ -146,9 +146,6 @@ namespace osu.Game.Input.Bindings [Description("Decrease scroll speed")] DecreaseScrollSpeed, - [Description("Toggle in-game interface")] - ToggleInGameInterface, - [Description("Select")] Select, @@ -204,5 +201,8 @@ namespace osu.Game.Input.Bindings [Description("Pause / resume replay")] TogglePauseReplay, + + [Description("Toggle in-game interface")] + ToggleInGameInterface, } } diff --git a/osu.Game/Screens/Play/HUDOverlay.cs b/osu.Game/Screens/Play/HUDOverlay.cs index 457706b8f5..96d1e211fd 100644 --- a/osu.Game/Screens/Play/HUDOverlay.cs +++ b/osu.Game/Screens/Play/HUDOverlay.cs @@ -181,7 +181,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)}." }); } From c8c1848bb8f554c022ddfd9b039d9848e1bb0ef9 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 1 Dec 2020 13:46:30 +0900 Subject: [PATCH 040/184] Fix slider control point dragging not correctly accounting for drag deadzone --- .../Blueprints/Sliders/Components/PathControlPointPiece.cs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointPiece.cs b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointPiece.cs index c06904c0c2..c302e8fe99 100644 --- a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointPiece.cs +++ b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointPiece.cs @@ -143,6 +143,8 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components protected override bool OnClick(ClickEvent e) => RequestSelection != null; + private Vector2 dragStartPosition; + protected override bool OnDragStart(DragStartEvent e) { if (RequestSelection == null) @@ -150,6 +152,7 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components if (e.Button == MouseButton.Left) { + dragStartPosition = ControlPoint.Position.Value; changeHandler?.BeginChange(); return true; } @@ -174,7 +177,7 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components slider.Path.ControlPoints[i].Position.Value -= movementDelta; } else - ControlPoint.Position.Value += e.Delta; + ControlPoint.Position.Value = dragStartPosition + (e.MousePosition - e.MouseDownPosition); } protected override void OnDragEnd(DragEndEvent e) => changeHandler?.EndChange(); From 63ff722963bf9762dc3938228e0832ae0a92ad00 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 1 Dec 2020 14:00:54 +0900 Subject: [PATCH 041/184] Fix code formatting --- osu.Game/Screens/Play/HUDOverlay.cs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/osu.Game/Screens/Play/HUDOverlay.cs b/osu.Game/Screens/Play/HUDOverlay.cs index 96d1e211fd..7ab04cf9f9 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 { @@ -362,6 +360,7 @@ namespace osu.Game.Screens.Play configVisibilityMode.Value = HUDVisibilityMode.Never; break; } + updateVisibility(); return true; } From a147b7186d28cbf1299a019b3cc37f99714a4b6b Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 1 Dec 2020 14:01:34 +0900 Subject: [PATCH 042/184] Remove unnecessary call to updateVisibility --- osu.Game/Screens/Play/HUDOverlay.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/osu.Game/Screens/Play/HUDOverlay.cs b/osu.Game/Screens/Play/HUDOverlay.cs index 7ab04cf9f9..50195d571c 100644 --- a/osu.Game/Screens/Play/HUDOverlay.cs +++ b/osu.Game/Screens/Play/HUDOverlay.cs @@ -361,7 +361,6 @@ namespace osu.Game.Screens.Play break; } - updateVisibility(); return true; } From b256c546198b159aae054f79ba585146fe1b5e7e Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 1 Dec 2020 14:17:36 +0900 Subject: [PATCH 043/184] Scale slider control point display in line with circle size --- .../Sliders/Components/PathControlPointPiece.cs | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointPiece.cs b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointPiece.cs index c06904c0c2..41d4d10568 100644 --- a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointPiece.cs +++ b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointPiece.cs @@ -44,6 +44,7 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components private OsuColour colours { get; set; } private IBindable sliderPosition; + private IBindable sliderScale; private IBindable controlPointPosition; public PathControlPointPiece(Slider slider, PathControlPoint controlPoint) @@ -69,13 +70,13 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components { Anchor = Anchor.Centre, Origin = Anchor.Centre, - Size = new Vector2(10), + Size = new Vector2(20), }, markerRing = new CircularContainer { Anchor = Anchor.Centre, Origin = Anchor.Centre, - Size = new Vector2(14), + Size = new Vector2(28), Masking = true, BorderThickness = 2, BorderColour = Color4.White, @@ -102,6 +103,9 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components controlPointPosition = ControlPoint.Position.GetBoundCopy(); controlPointPosition.BindValueChanged(_ => updateMarkerDisplay()); + sliderScale = slider.ScaleBindable.GetBoundCopy(); + sliderScale.BindValueChanged(_ => updateMarkerDisplay()); + IsSelected.BindValueChanged(_ => updateMarkerDisplay()); updateMarkerDisplay(); @@ -194,6 +198,7 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components colour = colour.Lighten(1); marker.Colour = colour; + marker.Scale = new Vector2(slider.Scale); } } } From e8842eed814cec5c1d889515a2075bbbd7ea23d1 Mon Sep 17 00:00:00 2001 From: ekrctb Date: Tue, 1 Dec 2020 14:50:42 +0900 Subject: [PATCH 044/184] Use bigger initial capacity for catch hit object pool --- osu.Game.Rulesets.Catch/UI/CatchPlayfield.cs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/osu.Game.Rulesets.Catch/UI/CatchPlayfield.cs b/osu.Game.Rulesets.Catch/UI/CatchPlayfield.cs index 97f33007fe..820f08d439 100644 --- a/osu.Game.Rulesets.Catch/UI/CatchPlayfield.cs +++ b/osu.Game.Rulesets.Catch/UI/CatchPlayfield.cs @@ -60,12 +60,12 @@ namespace osu.Game.Rulesets.Catch.UI [BackgroundDependencyLoader] private void load() { - RegisterPool(1); - RegisterPool(1); - RegisterPool(1); - RegisterPool(1); - RegisterPool(1); - RegisterPool(1); + RegisterPool(50); + RegisterPool(50); + RegisterPool(100); + RegisterPool(100); + RegisterPool(10); + RegisterPool(2); } protected override void LoadComplete() From 8d101efb24f53f2f4f0549bc1fe734dee18b4815 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 1 Dec 2020 14:56:14 +0900 Subject: [PATCH 045/184] Remove unused proxy layer --- osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs | 2 -- 1 file changed, 2 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs index dd27ac990e..986deccd51 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs @@ -300,8 +300,6 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables this.FadeOut(fade_out_time, Easing.OutQuint).Expire(); } - public Drawable ProxiedLayer => HeadCircle.ProxiedLayer; - public override bool ReceivePositionalInputAt(Vector2 screenSpacePos) => sliderBody?.ReceivePositionalInputAt(screenSpacePos) ?? base.ReceivePositionalInputAt(screenSpacePos); private class DefaultSliderBody : PlaySliderBody From d0852d7f4adcd63a16cce7b7a281f69a305b4f28 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 1 Dec 2020 14:56:41 +0900 Subject: [PATCH 046/184] Hide slider body immediately on successful hit when snaking is enabled --- osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs index 986deccd51..ec653264d0 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs @@ -294,6 +294,8 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables { case ArmedState.Hit: Ball.ScaleTo(HitObject.Scale * 1.4f, fade_out_time, Easing.Out); + if (sliderBody?.SnakingOut.Value == true) + Body.FadeOut(); break; } From f8ef822e73960ab5e80e5747f312c459db058d20 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 1 Dec 2020 15:21:32 +0900 Subject: [PATCH 047/184] Add short fade to better hide transition on default skin --- osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs index ec653264d0..14bcefde0a 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs @@ -295,7 +295,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables case ArmedState.Hit: Ball.ScaleTo(HitObject.Scale * 1.4f, fade_out_time, Easing.Out); if (sliderBody?.SnakingOut.Value == true) - Body.FadeOut(); + Body.FadeOut(40); // short fade to allow for any body colour to smoothly disappear. break; } From dd05c56a08d778d051eadcf4eda7f241336d87c3 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 1 Dec 2020 15:34:19 +0900 Subject: [PATCH 048/184] Fix sliders playing hit animations when completely missed --- osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs index dd27ac990e..b65463f438 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() From 5760e1c1fca35e580b459ad6a05431efc50a975f Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 1 Dec 2020 15:37:51 +0900 Subject: [PATCH 049/184] Make HitSampleInfo immutable --- .../TestSceneAutoJuiceStream.cs | 2 +- osu.Game.Rulesets.Catch/Objects/Banana.cs | 5 + .../Objects/JuiceStream.cs | 7 +- .../TestSceneSlider.cs | 10 +- .../Objects/Drawables/DrawableSlider.cs | 3 +- .../Objects/Drawables/DrawableSpinner.cs | 3 +- osu.Game.Rulesets.Osu/Objects/Slider.cs | 9 +- .../Objects/SpinnerBonusTick.cs | 2 +- .../Objects/Drawables/DrawableHit.cs | 6 +- .../Drawables/DrawableTaikoHitObject.cs | 2 +- .../Editing/LegacyEditorBeatmapPatcherTest.cs | 8 +- osu.Game/Audio/HitSampleInfo.cs | 38 +++++-- .../ControlPoints/SampleControlPoint.cs | 14 +-- .../Beatmaps/Formats/LegacyBeatmapEncoder.cs | 2 +- osu.Game/Beatmaps/Formats/LegacyDecoder.cs | 7 +- .../Objects/Legacy/ConvertHitObjectParser.cs | 101 +++++++----------- .../Components/ComposeBlueprintContainer.cs | 4 +- .../Compose/Components/SelectionHandler.cs | 2 +- osu.Game/Utils/Optional.cs | 45 ++++++++ 19 files changed, 144 insertions(+), 126 deletions(-) create mode 100644 osu.Game/Utils/Optional.cs diff --git a/osu.Game.Rulesets.Catch.Tests/TestSceneAutoJuiceStream.cs b/osu.Game.Rulesets.Catch.Tests/TestSceneAutoJuiceStream.cs index 3c636a5b97..0d57fb7029 100644 --- a/osu.Game.Rulesets.Catch.Tests/TestSceneAutoJuiceStream.cs +++ b/osu.Game.Rulesets.Catch.Tests/TestSceneAutoJuiceStream.cs @@ -43,7 +43,7 @@ namespace osu.Game.Rulesets.Catch.Tests NewCombo = i % 8 == 0, Samples = new List(new[] { - new HitSampleInfo { Bank = "normal", Name = "hitnormal", Volume = 100 } + new HitSampleInfo(HitSampleInfo.HIT_NORMAL, "normal") }) }); } diff --git a/osu.Game.Rulesets.Catch/Objects/Banana.cs b/osu.Game.Rulesets.Catch/Objects/Banana.cs index ccb1fff15b..822db890e2 100644 --- a/osu.Game.Rulesets.Catch/Objects/Banana.cs +++ b/osu.Game.Rulesets.Catch/Objects/Banana.cs @@ -55,6 +55,11 @@ namespace osu.Game.Rulesets.Catch.Objects private static string[] lookupNames { get; } = { "metronomelow", "catch-banana" }; public override IEnumerable LookupNames => lookupNames; + + public BananaHitSampleInfo() + : base(string.Empty) + { + } } } } diff --git a/osu.Game.Rulesets.Catch/Objects/JuiceStream.cs b/osu.Game.Rulesets.Catch/Objects/JuiceStream.cs index e209d012fa..d5819935ad 100644 --- a/osu.Game.Rulesets.Catch/Objects/JuiceStream.cs +++ b/osu.Game.Rulesets.Catch/Objects/JuiceStream.cs @@ -50,12 +50,7 @@ namespace osu.Game.Rulesets.Catch.Objects { base.CreateNestedHitObjects(cancellationToken); - var dropletSamples = Samples.Select(s => new HitSampleInfo - { - Bank = s.Bank, - Name = @"slidertick", - Volume = s.Volume - }).ToList(); + var dropletSamples = Samples.Select(s => s.With(@"slidertick")).ToList(); int nodeIndex = 0; SliderEventDescriptor? lastEvent = null; diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneSlider.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneSlider.cs index c400e2f2ea..d40484f5ed 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestSceneSlider.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneSlider.cs @@ -108,8 +108,8 @@ namespace osu.Game.Rulesets.Osu.Tests AddStep("change samples", () => slider.HitObject.Samples = new[] { - new HitSampleInfo { Name = HitSampleInfo.HIT_CLAP }, - new HitSampleInfo { Name = HitSampleInfo.HIT_WHISTLE }, + new HitSampleInfo(HitSampleInfo.HIT_CLAP), + new HitSampleInfo(HitSampleInfo.HIT_WHISTLE), }); AddAssert("head samples updated", () => assertSamples(slider.HitObject.HeadCircle)); @@ -136,15 +136,15 @@ namespace osu.Game.Rulesets.Osu.Tests slider = (DrawableSlider)createSlider(repeats: 1); for (int i = 0; i < 2; i++) - slider.HitObject.NodeSamples.Add(new List { new HitSampleInfo { Name = HitSampleInfo.HIT_FINISH } }); + slider.HitObject.NodeSamples.Add(new List { new HitSampleInfo(HitSampleInfo.HIT_FINISH) }); Add(slider); }); AddStep("change samples", () => slider.HitObject.Samples = new[] { - new HitSampleInfo { Name = HitSampleInfo.HIT_CLAP }, - new HitSampleInfo { Name = HitSampleInfo.HIT_WHISTLE }, + new HitSampleInfo(HitSampleInfo.HIT_CLAP), + new HitSampleInfo(HitSampleInfo.HIT_WHISTLE), }); AddAssert("head samples not updated", () => assertSamples(slider.HitObject.HeadCircle)); diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs index dd27ac990e..3aa0c9ccb5 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs @@ -115,8 +115,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables if (firstSample != null) { - var clone = HitObject.SampleControlPoint.ApplyTo(firstSample); - clone.Name = "sliderslide"; + var clone = HitObject.SampleControlPoint.ApplyTo(firstSample).With("sliderslide"); samplesContainer.Add(slidingSample = new PausableSkinnableSound(clone) { diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinner.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinner.cs index 2a14a7c975..5a11265a47 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinner.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinner.cs @@ -110,8 +110,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables if (firstSample != null) { - var clone = HitObject.SampleControlPoint.ApplyTo(firstSample); - clone.Name = "spinnerspin"; + var clone = HitObject.SampleControlPoint.ApplyTo(firstSample).With("spinnerspin"); samplesContainer.Add(spinningSample = new PausableSkinnableSound(clone) { diff --git a/osu.Game.Rulesets.Osu/Objects/Slider.cs b/osu.Game.Rulesets.Osu/Objects/Slider.cs index 755ce0866a..1670df24a8 100644 --- a/osu.Game.Rulesets.Osu/Objects/Slider.cs +++ b/osu.Game.Rulesets.Osu/Objects/Slider.cs @@ -221,14 +221,7 @@ namespace osu.Game.Rulesets.Osu.Objects var sampleList = new List(); if (firstSample != null) - { - sampleList.Add(new HitSampleInfo - { - Bank = firstSample.Bank, - Volume = firstSample.Volume, - Name = @"slidertick", - }); - } + sampleList.Add(firstSample.With("slidertick")); foreach (var tick in NestedHitObjects.OfType()) tick.Samples = sampleList; diff --git a/osu.Game.Rulesets.Osu/Objects/SpinnerBonusTick.cs b/osu.Game.Rulesets.Osu/Objects/SpinnerBonusTick.cs index 235dc8710a..2c443cb96b 100644 --- a/osu.Game.Rulesets.Osu/Objects/SpinnerBonusTick.cs +++ b/osu.Game.Rulesets.Osu/Objects/SpinnerBonusTick.cs @@ -11,7 +11,7 @@ namespace osu.Game.Rulesets.Osu.Objects { public SpinnerBonusTick() { - Samples.Add(new HitSampleInfo { Name = "spinnerbonus" }); + Samples.Add(new HitSampleInfo("spinnerbonus")); } public override Judgement CreateJudgement() => new OsuSpinnerBonusTickJudgement(); diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableHit.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableHit.cs index 4a3759794b..29a96a7a40 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableHit.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableHit.cs @@ -79,7 +79,7 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables if (isRimType != rimSamples.Any()) { if (isRimType) - HitObject.Samples.Add(new HitSampleInfo { Name = HitSampleInfo.HIT_CLAP }); + HitObject.Samples.Add(new HitSampleInfo(HitSampleInfo.HIT_CLAP)); else { foreach (var sample in rimSamples) @@ -125,9 +125,7 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables if (s.Name != HitSampleInfo.HIT_FINISH) continue; - var sClone = s.Clone(); - sClone.Name = HitSampleInfo.HIT_WHISTLE; - corrected[i] = sClone; + corrected[i] = s.With(HitSampleInfo.HIT_WHISTLE); } return corrected; diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableTaikoHitObject.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableTaikoHitObject.cs index d8d75a7614..ff5b221273 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableTaikoHitObject.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableTaikoHitObject.cs @@ -169,7 +169,7 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables if (isStrong.Value != strongSamples.Any()) { if (isStrong.Value) - HitObject.Samples.Add(new HitSampleInfo { Name = HitSampleInfo.HIT_FINISH }); + HitObject.Samples.Add(new HitSampleInfo(HitSampleInfo.HIT_FINISH)); else { foreach (var sample in strongSamples) diff --git a/osu.Game.Tests/Editing/LegacyEditorBeatmapPatcherTest.cs b/osu.Game.Tests/Editing/LegacyEditorBeatmapPatcherTest.cs index bb56131b04..44a908b756 100644 --- a/osu.Game.Tests/Editing/LegacyEditorBeatmapPatcherTest.cs +++ b/osu.Game.Tests/Editing/LegacyEditorBeatmapPatcherTest.cs @@ -139,7 +139,7 @@ namespace osu.Game.Tests.Editing HitObjects = { (OsuHitObject)current.HitObjects[0], - new HitCircle { StartTime = 2000, Samples = { new HitSampleInfo { Name = HitSampleInfo.HIT_FINISH } } }, + new HitCircle { StartTime = 2000, Samples = { new HitSampleInfo(HitSampleInfo.HIT_FINISH) } }, (OsuHitObject)current.HitObjects[2], } }; @@ -268,12 +268,12 @@ namespace osu.Game.Tests.Editing HitObjects = { (OsuHitObject)current.HitObjects[0], - new HitCircle { StartTime = 1000, Samples = { new HitSampleInfo { Name = HitSampleInfo.HIT_FINISH } } }, + new HitCircle { StartTime = 1000, Samples = { new HitSampleInfo(HitSampleInfo.HIT_FINISH) } }, (OsuHitObject)current.HitObjects[2], (OsuHitObject)current.HitObjects[3], - new HitCircle { StartTime = 2250, Samples = { new HitSampleInfo { Name = HitSampleInfo.HIT_WHISTLE } } }, + new HitCircle { StartTime = 2250, Samples = { new HitSampleInfo(HitSampleInfo.HIT_WHISTLE) } }, (OsuHitObject)current.HitObjects[5], - new HitCircle { StartTime = 3000, Samples = { new HitSampleInfo { Name = HitSampleInfo.HIT_CLAP } } }, + new HitCircle { StartTime = 3000, Samples = { new HitSampleInfo(HitSampleInfo.HIT_CLAP) } }, (OsuHitObject)current.HitObjects[7], } }; diff --git a/osu.Game/Audio/HitSampleInfo.cs b/osu.Game/Audio/HitSampleInfo.cs index 8efaeb3795..bf4a83e5d7 100644 --- a/osu.Game/Audio/HitSampleInfo.cs +++ b/osu.Game/Audio/HitSampleInfo.cs @@ -1,8 +1,11 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable enable + using System; using System.Collections.Generic; +using osu.Game.Utils; namespace osu.Game.Audio { @@ -22,25 +25,33 @@ namespace osu.Game.Audio /// public static IEnumerable AllAdditions => new[] { HIT_WHISTLE, HIT_CLAP, HIT_FINISH }; - /// - /// The bank to load the sample from. - /// - public string Bank; - /// /// The name of the sample to load. /// - public string Name; + public readonly string Name; + + /// + /// The bank to load the sample from. + /// + public readonly string? Bank; /// /// An optional suffix to provide priority lookup. Falls back to non-suffixed . /// - public string Suffix; + public readonly string? Suffix; /// /// The sample volume. /// - public int Volume { get; set; } + public int Volume { get; } + + public HitSampleInfo(string name, string? bank = null, string? suffix = null, int volume = 100) + { + Name = name; + Bank = bank; + Suffix = suffix; + Volume = volume; + } /// /// Retrieve all possible filenames that can be used as a source, returned in order of preference (highest first). @@ -56,6 +67,15 @@ namespace osu.Game.Audio } } - public HitSampleInfo Clone() => (HitSampleInfo)MemberwiseClone(); + /// + /// Creates a new with overridden values. + /// + /// An optional new sample name. + /// An optional new sample bank. + /// An optional new lookup suffix. + /// An optional new volume. + /// The new . + public virtual HitSampleInfo With(Optional name = default, Optional bank = default, Optional suffix = default, Optional volume = default) + => new HitSampleInfo(name.GetOr(Name), bank.GetOr(Bank), suffix.GetOr(Suffix), volume.GetOr(Volume)); } } diff --git a/osu.Game/Beatmaps/ControlPoints/SampleControlPoint.cs b/osu.Game/Beatmaps/ControlPoints/SampleControlPoint.cs index f57ecfb9e3..8064da1543 100644 --- a/osu.Game/Beatmaps/ControlPoints/SampleControlPoint.cs +++ b/osu.Game/Beatmaps/ControlPoints/SampleControlPoint.cs @@ -58,12 +58,7 @@ namespace osu.Game.Beatmaps.ControlPoints /// /// The name of the same. /// A populated . - public HitSampleInfo GetSampleInfo(string sampleName = HitSampleInfo.HIT_NORMAL) => new HitSampleInfo - { - Bank = SampleBank, - Name = sampleName, - Volume = SampleVolume, - }; + public HitSampleInfo GetSampleInfo(string sampleName = HitSampleInfo.HIT_NORMAL) => new HitSampleInfo(sampleName, SampleBank, volume: SampleVolume); /// /// Applies and to a if necessary, returning the modified . @@ -71,12 +66,7 @@ namespace osu.Game.Beatmaps.ControlPoints /// The . This will not be modified. /// The modified . This does not share a reference with . public virtual HitSampleInfo ApplyTo(HitSampleInfo hitSampleInfo) - { - var newSampleInfo = hitSampleInfo.Clone(); - newSampleInfo.Bank = hitSampleInfo.Bank ?? SampleBank; - newSampleInfo.Volume = hitSampleInfo.Volume > 0 ? hitSampleInfo.Volume : SampleVolume; - return newSampleInfo; - } + => hitSampleInfo.With(bank: hitSampleInfo.Bank ?? SampleBank, volume: hitSampleInfo.Volume > 0 ? hitSampleInfo.Volume : SampleVolume); public override bool IsRedundant(ControlPoint existing) => existing is SampleControlPoint existingSample diff --git a/osu.Game/Beatmaps/Formats/LegacyBeatmapEncoder.cs b/osu.Game/Beatmaps/Formats/LegacyBeatmapEncoder.cs index 7ddb0b4caa..df940e8c8e 100644 --- a/osu.Game/Beatmaps/Formats/LegacyBeatmapEncoder.cs +++ b/osu.Game/Beatmaps/Formats/LegacyBeatmapEncoder.cs @@ -192,7 +192,7 @@ namespace osu.Game.Beatmaps.Formats var effectPoint = beatmap.ControlPointInfo.EffectPointAt(time); // Apply the control point to a hit sample to uncover legacy properties (e.g. suffix) - HitSampleInfo tempHitSample = samplePoint.ApplyTo(new ConvertHitObjectParser.LegacyHitSampleInfo()); + HitSampleInfo tempHitSample = samplePoint.ApplyTo(new ConvertHitObjectParser.LegacyHitSampleInfo(string.Empty)); // Convert effect flags to the legacy format LegacyEffectFlags effectFlags = LegacyEffectFlags.None; diff --git a/osu.Game/Beatmaps/Formats/LegacyDecoder.cs b/osu.Game/Beatmaps/Formats/LegacyDecoder.cs index de4dc8cdc8..9f16180e77 100644 --- a/osu.Game/Beatmaps/Formats/LegacyDecoder.cs +++ b/osu.Game/Beatmaps/Formats/LegacyDecoder.cs @@ -182,11 +182,8 @@ namespace osu.Game.Beatmaps.Formats { var baseInfo = base.ApplyTo(hitSampleInfo); - if (baseInfo is ConvertHitObjectParser.LegacyHitSampleInfo legacy - && legacy.CustomSampleBank == 0) - { - legacy.CustomSampleBank = CustomSampleBank; - } + if (baseInfo is ConvertHitObjectParser.LegacyHitSampleInfo legacy && legacy.CustomSampleBank == 0) + return legacy.With(customSampleBank: CustomSampleBank); return baseInfo; } diff --git a/osu.Game/Rulesets/Objects/Legacy/ConvertHitObjectParser.cs b/osu.Game/Rulesets/Objects/Legacy/ConvertHitObjectParser.cs index 44b22033dc..9b38266400 100644 --- a/osu.Game/Rulesets/Objects/Legacy/ConvertHitObjectParser.cs +++ b/osu.Game/Rulesets/Objects/Legacy/ConvertHitObjectParser.cs @@ -13,6 +13,7 @@ using JetBrains.Annotations; using osu.Framework.Utils; using osu.Game.Beatmaps.Legacy; using osu.Game.Skinning; +using osu.Game.Utils; namespace osu.Game.Rulesets.Objects.Legacy { @@ -427,62 +428,25 @@ namespace osu.Game.Rulesets.Objects.Legacy // Todo: This should return the normal SampleInfos if the specified sample file isn't found, but that's a pretty edge-case scenario if (!string.IsNullOrEmpty(bankInfo.Filename)) { - return new List - { - new FileHitSampleInfo - { - Filename = bankInfo.Filename, - Volume = bankInfo.Volume - } - }; + return new List { new FileHitSampleInfo(bankInfo.Filename, bankInfo.Volume) }; } var soundTypes = new List { - new LegacyHitSampleInfo - { - Bank = bankInfo.Normal, - Name = HitSampleInfo.HIT_NORMAL, - Volume = bankInfo.Volume, - CustomSampleBank = bankInfo.CustomSampleBank, + new LegacyHitSampleInfo(HitSampleInfo.HIT_NORMAL, bankInfo.Normal, bankInfo.Volume, bankInfo.CustomSampleBank, // if the sound type doesn't have the Normal flag set, attach it anyway as a layered sample. // None also counts as a normal non-layered sample: https://osu.ppy.sh/help/wiki/osu!_File_Formats/Osu_(file_format)#hitsounds - IsLayered = type != LegacyHitSoundType.None && !type.HasFlag(LegacyHitSoundType.Normal) - } + type != LegacyHitSoundType.None && !type.HasFlag(LegacyHitSoundType.Normal)) }; if (type.HasFlag(LegacyHitSoundType.Finish)) - { - soundTypes.Add(new LegacyHitSampleInfo - { - Bank = bankInfo.Add, - Name = HitSampleInfo.HIT_FINISH, - Volume = bankInfo.Volume, - CustomSampleBank = bankInfo.CustomSampleBank - }); - } + soundTypes.Add(new LegacyHitSampleInfo(HitSampleInfo.HIT_FINISH, bankInfo.Add, bankInfo.Volume, bankInfo.CustomSampleBank)); if (type.HasFlag(LegacyHitSoundType.Whistle)) - { - soundTypes.Add(new LegacyHitSampleInfo - { - Bank = bankInfo.Add, - Name = HitSampleInfo.HIT_WHISTLE, - Volume = bankInfo.Volume, - CustomSampleBank = bankInfo.CustomSampleBank - }); - } + soundTypes.Add(new LegacyHitSampleInfo(HitSampleInfo.HIT_WHISTLE, bankInfo.Add, bankInfo.Volume, bankInfo.CustomSampleBank)); if (type.HasFlag(LegacyHitSoundType.Clap)) - { - soundTypes.Add(new LegacyHitSampleInfo - { - Bank = bankInfo.Add, - Name = HitSampleInfo.HIT_CLAP, - Volume = bankInfo.Volume, - CustomSampleBank = bankInfo.CustomSampleBank - }); - } + soundTypes.Add(new LegacyHitSampleInfo(HitSampleInfo.HIT_CLAP, bankInfo.Add, bankInfo.Volume, bankInfo.CustomSampleBank)); return soundTypes; } @@ -500,21 +464,11 @@ namespace osu.Game.Rulesets.Objects.Legacy public SampleBankInfo Clone() => (SampleBankInfo)MemberwiseClone(); } +#nullable enable + public class LegacyHitSampleInfo : HitSampleInfo { - private int customSampleBank; - - public int CustomSampleBank - { - get => customSampleBank; - set - { - customSampleBank = value; - - if (value >= 2) - Suffix = value.ToString(); - } - } + public readonly int CustomSampleBank; /// /// Whether this hit sample is layered. @@ -523,18 +477,33 @@ namespace osu.Game.Rulesets.Objects.Legacy /// Layered hit samples are automatically added in all modes (except osu!mania), but can be disabled /// using the skin config option. /// - public bool IsLayered { get; set; } + public readonly bool IsLayered; + + public LegacyHitSampleInfo([NotNull] string name, string? bank = null, int volume = 100, int customSampleBank = 0, bool isLayered = false) + : base(name, bank, customSampleBank >= 2 ? customSampleBank.ToString() : null, volume) + { + CustomSampleBank = customSampleBank; + IsLayered = isLayered; + } + + public override HitSampleInfo With(Optional name = default, Optional bank = default, Optional suffix = default, Optional volume = default) + => With(name, bank, volume); + + public LegacyHitSampleInfo With(Optional name = default, Optional bank = default, Optional volume = default, Optional customSampleBank = default, + Optional isLayered = default) + => new LegacyHitSampleInfo(name.GetOr(Name), bank.GetOr(Bank), volume.GetOr(Volume), customSampleBank.GetOr(CustomSampleBank), isLayered.GetOr(IsLayered)); } private class FileHitSampleInfo : LegacyHitSampleInfo { - public string Filename; + public readonly string Filename; - public FileHitSampleInfo() - { - // Make sure that the LegacyBeatmapSkin does not fall back to the user skin. + public FileHitSampleInfo(string filename, int volume) + // Force CSS=1 to make sure that the LegacyBeatmapSkin does not fall back to the user skin. // Note that this does not change the lookup names, as they are overridden locally. - CustomSampleBank = 1; + : base(string.Empty, customSampleBank: 1, volume: volume) + { + Filename = filename; } public override IEnumerable LookupNames => new[] @@ -542,6 +511,14 @@ namespace osu.Game.Rulesets.Objects.Legacy Filename, Path.ChangeExtension(Filename, null) }; + + public override HitSampleInfo With(Optional name = default, Optional bank = default, Optional suffix = default, Optional volume = default) + => With(volume: volume); + + public FileHitSampleInfo With(Optional filename = default, Optional volume = default) + => new FileHitSampleInfo(filename.GetOr(Filename), volume.GetOr(Volume)); } + +#nullable disable } } diff --git a/osu.Game/Screens/Edit/Compose/Components/ComposeBlueprintContainer.cs b/osu.Game/Screens/Edit/Compose/Components/ComposeBlueprintContainer.cs index 1893366d90..c09b935f28 100644 --- a/osu.Game/Screens/Edit/Compose/Components/ComposeBlueprintContainer.cs +++ b/osu.Game/Screens/Edit/Compose/Components/ComposeBlueprintContainer.cs @@ -101,7 +101,7 @@ namespace osu.Game.Screens.Edit.Compose.Components case TernaryState.True: if (existingSample == null) - samples.Add(new HitSampleInfo { Name = sampleName }); + samples.Add(new HitSampleInfo(sampleName)); break; } } @@ -212,7 +212,7 @@ namespace osu.Game.Screens.Edit.Compose.Components if (blueprint != null) { // doing this post-creations as adding the default hit sample should be the case regardless of the ruleset. - blueprint.HitObject.Samples.Add(new HitSampleInfo { Name = HitSampleInfo.HIT_NORMAL }); + blueprint.HitObject.Samples.Add(new HitSampleInfo(HitSampleInfo.HIT_NORMAL)); placementBlueprintContainer.Child = currentPlacement = blueprint; diff --git a/osu.Game/Screens/Edit/Compose/Components/SelectionHandler.cs b/osu.Game/Screens/Edit/Compose/Components/SelectionHandler.cs index adf22a3370..788b485449 100644 --- a/osu.Game/Screens/Edit/Compose/Components/SelectionHandler.cs +++ b/osu.Game/Screens/Edit/Compose/Components/SelectionHandler.cs @@ -328,7 +328,7 @@ namespace osu.Game.Screens.Edit.Compose.Components if (h.Samples.Any(s => s.Name == sampleName)) continue; - h.Samples.Add(new HitSampleInfo { Name = sampleName }); + h.Samples.Add(new HitSampleInfo(sampleName)); } EditorBeatmap.EndChange(); diff --git a/osu.Game/Utils/Optional.cs b/osu.Game/Utils/Optional.cs new file mode 100644 index 0000000000..9f8a1c2e62 --- /dev/null +++ b/osu.Game/Utils/Optional.cs @@ -0,0 +1,45 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +#nullable enable + +namespace osu.Game.Utils +{ + /// + /// A wrapper over a value and a boolean denoting whether the value is valid. + /// + /// The type of value stored. + public readonly ref struct Optional + { + /// + /// The stored value. + /// + public readonly T Value; + + /// + /// Whether is valid. + /// + /// + /// If is a reference type, null may be valid for . + /// + public readonly bool HasValue; + + private Optional(T value) + { + Value = value; + HasValue = true; + } + + /// + /// Returns if it's valid, or a given fallback value otherwise. + /// + /// + /// Shortcase for: optional.HasValue ? optional.Value : fallback. + /// + /// The fallback value to return if is false. + /// + public T GetOr(T fallback) => HasValue ? Value : fallback; + + public static implicit operator Optional(T value) => new Optional(value); + } +} From 199710b941a396cfed43b989a127c5a355522dfa Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 1 Dec 2020 15:44:16 +0900 Subject: [PATCH 050/184] Implement equality comparers for HitSampleInfo --- osu.Game.Rulesets.Catch/Objects/Banana.cs | 15 ++++++++++++--- osu.Game/Audio/HitSampleInfo.cs | 10 +++++++++- .../Objects/Legacy/ConvertHitObjectParser.cs | 19 +++++++++++++++++-- 3 files changed, 38 insertions(+), 6 deletions(-) diff --git a/osu.Game.Rulesets.Catch/Objects/Banana.cs b/osu.Game.Rulesets.Catch/Objects/Banana.cs index 822db890e2..ec4b67f341 100644 --- a/osu.Game.Rulesets.Catch/Objects/Banana.cs +++ b/osu.Game.Rulesets.Catch/Objects/Banana.cs @@ -1,6 +1,7 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System; using System.Collections.Generic; using osu.Framework.Utils; using osu.Game.Audio; @@ -50,16 +51,24 @@ namespace osu.Game.Rulesets.Catch.Objects } } - private class BananaHitSampleInfo : HitSampleInfo + private class BananaHitSampleInfo : HitSampleInfo, IEquatable { - private static string[] lookupNames { get; } = { "metronomelow", "catch-banana" }; + private static readonly string[] lookup_names = { "metronomelow", "catch-banana" }; - public override IEnumerable LookupNames => lookupNames; + public override IEnumerable LookupNames => lookup_names; public BananaHitSampleInfo() : base(string.Empty) { } + + public bool Equals(BananaHitSampleInfo other) + => other != null; + + public override bool Equals(object obj) + => Equals((BananaHitSampleInfo)obj); + + public override int GetHashCode() => lookup_names.GetHashCode(); } } } diff --git a/osu.Game/Audio/HitSampleInfo.cs b/osu.Game/Audio/HitSampleInfo.cs index bf4a83e5d7..4a0e48749a 100644 --- a/osu.Game/Audio/HitSampleInfo.cs +++ b/osu.Game/Audio/HitSampleInfo.cs @@ -13,7 +13,7 @@ namespace osu.Game.Audio /// Describes a gameplay hit sample. /// [Serializable] - public class HitSampleInfo : ISampleInfo + public class HitSampleInfo : ISampleInfo, IEquatable { public const string HIT_WHISTLE = @"hitwhistle"; public const string HIT_FINISH = @"hitfinish"; @@ -77,5 +77,13 @@ namespace osu.Game.Audio /// The new . public virtual HitSampleInfo With(Optional name = default, Optional bank = default, Optional suffix = default, Optional volume = default) => new HitSampleInfo(name.GetOr(Name), bank.GetOr(Bank), suffix.GetOr(Suffix), volume.GetOr(Volume)); + + public bool Equals(HitSampleInfo? other) + => other != null && Name == other.Name && Bank == other.Bank && Suffix == other.Suffix; + + public override bool Equals(object? obj) + => Equals((HitSampleInfo?)obj); + + public override int GetHashCode() => HashCode.Combine(Name, Bank, Suffix); } } diff --git a/osu.Game/Rulesets/Objects/Legacy/ConvertHitObjectParser.cs b/osu.Game/Rulesets/Objects/Legacy/ConvertHitObjectParser.cs index 9b38266400..931bdb3db7 100644 --- a/osu.Game/Rulesets/Objects/Legacy/ConvertHitObjectParser.cs +++ b/osu.Game/Rulesets/Objects/Legacy/ConvertHitObjectParser.cs @@ -466,7 +466,7 @@ namespace osu.Game.Rulesets.Objects.Legacy #nullable enable - public class LegacyHitSampleInfo : HitSampleInfo + public class LegacyHitSampleInfo : HitSampleInfo, IEquatable { public readonly int CustomSampleBank; @@ -492,9 +492,16 @@ namespace osu.Game.Rulesets.Objects.Legacy public LegacyHitSampleInfo With(Optional name = default, Optional bank = default, Optional volume = default, Optional customSampleBank = default, Optional isLayered = default) => new LegacyHitSampleInfo(name.GetOr(Name), bank.GetOr(Bank), volume.GetOr(Volume), customSampleBank.GetOr(CustomSampleBank), isLayered.GetOr(IsLayered)); + + public bool Equals(LegacyHitSampleInfo? other) + => base.Equals(other) && CustomSampleBank == other.CustomSampleBank && IsLayered == other.IsLayered; + + public override bool Equals(object? obj) => Equals((LegacyHitSampleInfo?)obj); + + public override int GetHashCode() => HashCode.Combine(base.GetHashCode(), CustomSampleBank, IsLayered); } - private class FileHitSampleInfo : LegacyHitSampleInfo + private class FileHitSampleInfo : LegacyHitSampleInfo, IEquatable { public readonly string Filename; @@ -517,6 +524,14 @@ namespace osu.Game.Rulesets.Objects.Legacy public FileHitSampleInfo With(Optional filename = default, Optional volume = default) => new FileHitSampleInfo(filename.GetOr(Filename), volume.GetOr(Volume)); + + public bool Equals(FileHitSampleInfo? other) + => base.Equals(other) && Filename == other.Filename; + + public override bool Equals(object? obj) + => Equals((FileHitSampleInfo?)obj); + + public override int GetHashCode() => HashCode.Combine(base.GetHashCode(), Filename); } #nullable disable From 2b268ee012f5b4ae9d151d3a2b1fb64e07d488b2 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 1 Dec 2020 16:16:26 +0900 Subject: [PATCH 051/184] Fix editor beat snapping not working correctly when starting with a new beatmap --- osu.Game/Screens/Edit/Editor.cs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/osu.Game/Screens/Edit/Editor.cs b/osu.Game/Screens/Edit/Editor.cs index 3d5c0ddad4..8f1cd8e28e 100644 --- a/osu.Game/Screens/Edit/Editor.cs +++ b/osu.Game/Screens/Edit/Editor.cs @@ -109,6 +109,12 @@ namespace osu.Game.Screens.Edit beatDivisor.Value = Beatmap.Value.BeatmapInfo.BeatDivisor; beatDivisor.BindValueChanged(divisor => Beatmap.Value.BeatmapInfo.BeatDivisor = divisor.NewValue); + if (Beatmap.Value is DummyWorkingBeatmap) + { + isNewBeatmap = true; + Beatmap.Value = beatmapManager.CreateNew(Ruleset.Value, api.LocalUser.Value); + } + // Todo: should probably be done at a DrawableRuleset level to share logic with Player. clock = new EditorClock(Beatmap.Value, beatDivisor) { IsCoupled = false }; @@ -122,12 +128,6 @@ namespace osu.Game.Screens.Edit // todo: remove caching of this and consume via editorBeatmap? dependencies.Cache(beatDivisor); - if (Beatmap.Value is DummyWorkingBeatmap) - { - isNewBeatmap = true; - Beatmap.Value = beatmapManager.CreateNew(Ruleset.Value, api.LocalUser.Value); - } - try { playableBeatmap = Beatmap.Value.GetPlayableBeatmap(Beatmap.Value.BeatmapInfo.Ruleset); From 190c6ef45e3fd0cee9581596d85d8ea531160d2a Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 1 Dec 2020 16:44:08 +0900 Subject: [PATCH 052/184] Fix timeline not updating ticks correctly after arbitrary timing control point changes --- .../Timeline/TimelineTickDisplay.cs | 21 ++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineTickDisplay.cs b/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineTickDisplay.cs index 724256af8b..71268a1e69 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] + private IEditorChangeHandler changeHandler { get; set; } + [Resolved] private OsuColour colours { get; set; } @@ -38,7 +41,15 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline [BackgroundDependencyLoader] private void load() { - beatDivisor.BindValueChanged(_ => tickCache.Invalidate()); + beatDivisor.BindValueChanged(_ => invalidateTicks()); + + // currently this is the best way to handle any kind of timing changes. + changeHandler.OnStateChange += invalidateTicks; + } + + private void invalidateTicks() + { + tickCache.Invalidate(); } /// @@ -165,5 +176,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; + } } } From 4900589af4d958c88a0df65a94d647bc06222032 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 1 Dec 2020 17:02:45 +0900 Subject: [PATCH 053/184] Remove unused method --- osu.Game/Rulesets/Objects/Legacy/ConvertHitObjectParser.cs | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/osu.Game/Rulesets/Objects/Legacy/ConvertHitObjectParser.cs b/osu.Game/Rulesets/Objects/Legacy/ConvertHitObjectParser.cs index 931bdb3db7..5895059df5 100644 --- a/osu.Game/Rulesets/Objects/Legacy/ConvertHitObjectParser.cs +++ b/osu.Game/Rulesets/Objects/Legacy/ConvertHitObjectParser.cs @@ -520,10 +520,7 @@ namespace osu.Game.Rulesets.Objects.Legacy }; public override HitSampleInfo With(Optional name = default, Optional bank = default, Optional suffix = default, Optional volume = default) - => With(volume: volume); - - public FileHitSampleInfo With(Optional filename = default, Optional volume = default) - => new FileHitSampleInfo(filename.GetOr(Filename), volume.GetOr(Volume)); + => new FileHitSampleInfo(Filename, volume.GetOr(Volume)); public bool Equals(FileHitSampleInfo? other) => base.Equals(other) && Filename == other.Filename; From b780fdbe4c24efce455c6ebc1b0d53dcc3826eb3 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 1 Dec 2020 18:08:59 +0900 Subject: [PATCH 054/184] Ignore lookup types for JSON serialisation --- osu.Game/Audio/HitSampleInfo.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/osu.Game/Audio/HitSampleInfo.cs b/osu.Game/Audio/HitSampleInfo.cs index 4a0e48749a..27fb5d2f8e 100644 --- a/osu.Game/Audio/HitSampleInfo.cs +++ b/osu.Game/Audio/HitSampleInfo.cs @@ -56,6 +56,7 @@ namespace osu.Game.Audio /// /// Retrieve all possible filenames that can be used as a source, returned in order of preference (highest first). /// + [JsonIgnore] public virtual IEnumerable LookupNames { get From dda4d76d726592aa3fa7c23639611b3e6694b56d Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 1 Dec 2020 18:09:21 +0900 Subject: [PATCH 055/184] Fix bad equality comparer implementations --- osu.Game.Rulesets.Catch/Objects/Banana.cs | 2 +- osu.Game/Audio/HitSampleInfo.cs | 2 +- osu.Game/Rulesets/Objects/Legacy/ConvertHitObjectParser.cs | 5 +++-- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/osu.Game.Rulesets.Catch/Objects/Banana.cs b/osu.Game.Rulesets.Catch/Objects/Banana.cs index ec4b67f341..7734ebed12 100644 --- a/osu.Game.Rulesets.Catch/Objects/Banana.cs +++ b/osu.Game.Rulesets.Catch/Objects/Banana.cs @@ -66,7 +66,7 @@ namespace osu.Game.Rulesets.Catch.Objects => other != null; public override bool Equals(object obj) - => Equals((BananaHitSampleInfo)obj); + => obj is BananaHitSampleInfo other && Equals(other); public override int GetHashCode() => lookup_names.GetHashCode(); } diff --git a/osu.Game/Audio/HitSampleInfo.cs b/osu.Game/Audio/HitSampleInfo.cs index 27fb5d2f8e..9bd34c009b 100644 --- a/osu.Game/Audio/HitSampleInfo.cs +++ b/osu.Game/Audio/HitSampleInfo.cs @@ -83,7 +83,7 @@ namespace osu.Game.Audio => other != null && Name == other.Name && Bank == other.Bank && Suffix == other.Suffix; public override bool Equals(object? obj) - => Equals((HitSampleInfo?)obj); + => obj is HitSampleInfo other && Equals(other); public override int GetHashCode() => HashCode.Combine(Name, Bank, Suffix); } diff --git a/osu.Game/Rulesets/Objects/Legacy/ConvertHitObjectParser.cs b/osu.Game/Rulesets/Objects/Legacy/ConvertHitObjectParser.cs index 64694fb12e..015d6a3dd6 100644 --- a/osu.Game/Rulesets/Objects/Legacy/ConvertHitObjectParser.cs +++ b/osu.Game/Rulesets/Objects/Legacy/ConvertHitObjectParser.cs @@ -496,7 +496,8 @@ namespace osu.Game.Rulesets.Objects.Legacy public bool Equals(LegacyHitSampleInfo? other) => base.Equals(other) && CustomSampleBank == other.CustomSampleBank && IsLayered == other.IsLayered; - public override bool Equals(object? obj) => Equals((LegacyHitSampleInfo?)obj); + public override bool Equals(object? obj) + => obj is LegacyHitSampleInfo other && Equals(other); public override int GetHashCode() => HashCode.Combine(base.GetHashCode(), CustomSampleBank, IsLayered); } @@ -529,7 +530,7 @@ namespace osu.Game.Rulesets.Objects.Legacy => base.Equals(other) && Filename == other.Filename; public override bool Equals(object? obj) - => Equals((FileHitSampleInfo?)obj); + => obj is FileHitSampleInfo other && Equals(other); public override int GetHashCode() => HashCode.Combine(base.GetHashCode(), Filename); } From 17560aeeea75adb03347d31e02a85f2b930b0954 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 1 Dec 2020 18:09:28 +0900 Subject: [PATCH 056/184] Volume should be 0 by default --- osu.Game.Rulesets.Catch.Tests/TestSceneAutoJuiceStream.cs | 2 +- osu.Game/Audio/HitSampleInfo.cs | 3 ++- osu.Game/Rulesets/Objects/Legacy/ConvertHitObjectParser.cs | 2 +- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/osu.Game.Rulesets.Catch.Tests/TestSceneAutoJuiceStream.cs b/osu.Game.Rulesets.Catch.Tests/TestSceneAutoJuiceStream.cs index 0d57fb7029..f552c3c27b 100644 --- a/osu.Game.Rulesets.Catch.Tests/TestSceneAutoJuiceStream.cs +++ b/osu.Game.Rulesets.Catch.Tests/TestSceneAutoJuiceStream.cs @@ -43,7 +43,7 @@ namespace osu.Game.Rulesets.Catch.Tests NewCombo = i % 8 == 0, Samples = new List(new[] { - new HitSampleInfo(HitSampleInfo.HIT_NORMAL, "normal") + new HitSampleInfo(HitSampleInfo.HIT_NORMAL, "normal", volume: 100) }) }); } diff --git a/osu.Game/Audio/HitSampleInfo.cs b/osu.Game/Audio/HitSampleInfo.cs index 9bd34c009b..58b078db71 100644 --- a/osu.Game/Audio/HitSampleInfo.cs +++ b/osu.Game/Audio/HitSampleInfo.cs @@ -5,6 +5,7 @@ using System; using System.Collections.Generic; +using Newtonsoft.Json; using osu.Game.Utils; namespace osu.Game.Audio @@ -45,7 +46,7 @@ namespace osu.Game.Audio /// public int Volume { get; } - public HitSampleInfo(string name, string? bank = null, string? suffix = null, int volume = 100) + public HitSampleInfo(string name, string? bank = null, string? suffix = null, int volume = 0) { Name = name; Bank = bank; diff --git a/osu.Game/Rulesets/Objects/Legacy/ConvertHitObjectParser.cs b/osu.Game/Rulesets/Objects/Legacy/ConvertHitObjectParser.cs index 015d6a3dd6..762edf5a13 100644 --- a/osu.Game/Rulesets/Objects/Legacy/ConvertHitObjectParser.cs +++ b/osu.Game/Rulesets/Objects/Legacy/ConvertHitObjectParser.cs @@ -479,7 +479,7 @@ namespace osu.Game.Rulesets.Objects.Legacy /// public readonly bool IsLayered; - public LegacyHitSampleInfo(string name, string? bank = null, int volume = 100, int customSampleBank = 0, bool isLayered = false) + public LegacyHitSampleInfo(string name, string? bank = null, int volume = 0, int customSampleBank = 0, bool isLayered = false) : base(name, bank, customSampleBank >= 2 ? customSampleBank.ToString() : null, volume) { CustomSampleBank = customSampleBank; From c61f00525dfe57252b43df938671ab75ba29be96 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 1 Dec 2020 18:08:59 +0900 Subject: [PATCH 057/184] Ignore lookup types for JSON serialisation --- osu.Game/Audio/HitSampleInfo.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/osu.Game/Audio/HitSampleInfo.cs b/osu.Game/Audio/HitSampleInfo.cs index 4a0e48749a..27fb5d2f8e 100644 --- a/osu.Game/Audio/HitSampleInfo.cs +++ b/osu.Game/Audio/HitSampleInfo.cs @@ -56,6 +56,7 @@ namespace osu.Game.Audio /// /// Retrieve all possible filenames that can be used as a source, returned in order of preference (highest first). /// + [JsonIgnore] public virtual IEnumerable LookupNames { get From 6b4a6c12c81a8f22a8b1b0cb012b011d1c9f5275 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 1 Dec 2020 18:09:21 +0900 Subject: [PATCH 058/184] Fix bad equality comparer implementations --- osu.Game.Rulesets.Catch/Objects/Banana.cs | 2 +- osu.Game/Audio/HitSampleInfo.cs | 2 +- osu.Game/Rulesets/Objects/Legacy/ConvertHitObjectParser.cs | 5 +++-- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/osu.Game.Rulesets.Catch/Objects/Banana.cs b/osu.Game.Rulesets.Catch/Objects/Banana.cs index ec4b67f341..7734ebed12 100644 --- a/osu.Game.Rulesets.Catch/Objects/Banana.cs +++ b/osu.Game.Rulesets.Catch/Objects/Banana.cs @@ -66,7 +66,7 @@ namespace osu.Game.Rulesets.Catch.Objects => other != null; public override bool Equals(object obj) - => Equals((BananaHitSampleInfo)obj); + => obj is BananaHitSampleInfo other && Equals(other); public override int GetHashCode() => lookup_names.GetHashCode(); } diff --git a/osu.Game/Audio/HitSampleInfo.cs b/osu.Game/Audio/HitSampleInfo.cs index 27fb5d2f8e..9bd34c009b 100644 --- a/osu.Game/Audio/HitSampleInfo.cs +++ b/osu.Game/Audio/HitSampleInfo.cs @@ -83,7 +83,7 @@ namespace osu.Game.Audio => other != null && Name == other.Name && Bank == other.Bank && Suffix == other.Suffix; public override bool Equals(object? obj) - => Equals((HitSampleInfo?)obj); + => obj is HitSampleInfo other && Equals(other); public override int GetHashCode() => HashCode.Combine(Name, Bank, Suffix); } diff --git a/osu.Game/Rulesets/Objects/Legacy/ConvertHitObjectParser.cs b/osu.Game/Rulesets/Objects/Legacy/ConvertHitObjectParser.cs index 5895059df5..a7290401bc 100644 --- a/osu.Game/Rulesets/Objects/Legacy/ConvertHitObjectParser.cs +++ b/osu.Game/Rulesets/Objects/Legacy/ConvertHitObjectParser.cs @@ -496,7 +496,8 @@ namespace osu.Game.Rulesets.Objects.Legacy public bool Equals(LegacyHitSampleInfo? other) => base.Equals(other) && CustomSampleBank == other.CustomSampleBank && IsLayered == other.IsLayered; - public override bool Equals(object? obj) => Equals((LegacyHitSampleInfo?)obj); + public override bool Equals(object? obj) + => obj is LegacyHitSampleInfo other && Equals(other); public override int GetHashCode() => HashCode.Combine(base.GetHashCode(), CustomSampleBank, IsLayered); } @@ -526,7 +527,7 @@ namespace osu.Game.Rulesets.Objects.Legacy => base.Equals(other) && Filename == other.Filename; public override bool Equals(object? obj) - => Equals((FileHitSampleInfo?)obj); + => obj is FileHitSampleInfo other && Equals(other); public override int GetHashCode() => HashCode.Combine(base.GetHashCode(), Filename); } From 284040511289654bf38d18567426edc285f393c5 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 1 Dec 2020 18:09:28 +0900 Subject: [PATCH 059/184] Volume should be 0 by default --- osu.Game.Rulesets.Catch.Tests/TestSceneAutoJuiceStream.cs | 2 +- osu.Game/Audio/HitSampleInfo.cs | 3 ++- osu.Game/Rulesets/Objects/Legacy/ConvertHitObjectParser.cs | 2 +- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/osu.Game.Rulesets.Catch.Tests/TestSceneAutoJuiceStream.cs b/osu.Game.Rulesets.Catch.Tests/TestSceneAutoJuiceStream.cs index 0d57fb7029..f552c3c27b 100644 --- a/osu.Game.Rulesets.Catch.Tests/TestSceneAutoJuiceStream.cs +++ b/osu.Game.Rulesets.Catch.Tests/TestSceneAutoJuiceStream.cs @@ -43,7 +43,7 @@ namespace osu.Game.Rulesets.Catch.Tests NewCombo = i % 8 == 0, Samples = new List(new[] { - new HitSampleInfo(HitSampleInfo.HIT_NORMAL, "normal") + new HitSampleInfo(HitSampleInfo.HIT_NORMAL, "normal", volume: 100) }) }); } diff --git a/osu.Game/Audio/HitSampleInfo.cs b/osu.Game/Audio/HitSampleInfo.cs index 9bd34c009b..58b078db71 100644 --- a/osu.Game/Audio/HitSampleInfo.cs +++ b/osu.Game/Audio/HitSampleInfo.cs @@ -5,6 +5,7 @@ using System; using System.Collections.Generic; +using Newtonsoft.Json; using osu.Game.Utils; namespace osu.Game.Audio @@ -45,7 +46,7 @@ namespace osu.Game.Audio /// public int Volume { get; } - public HitSampleInfo(string name, string? bank = null, string? suffix = null, int volume = 100) + public HitSampleInfo(string name, string? bank = null, string? suffix = null, int volume = 0) { Name = name; Bank = bank; diff --git a/osu.Game/Rulesets/Objects/Legacy/ConvertHitObjectParser.cs b/osu.Game/Rulesets/Objects/Legacy/ConvertHitObjectParser.cs index a7290401bc..2cb72e9e80 100644 --- a/osu.Game/Rulesets/Objects/Legacy/ConvertHitObjectParser.cs +++ b/osu.Game/Rulesets/Objects/Legacy/ConvertHitObjectParser.cs @@ -479,7 +479,7 @@ namespace osu.Game.Rulesets.Objects.Legacy /// public readonly bool IsLayered; - public LegacyHitSampleInfo([NotNull] string name, string? bank = null, int volume = 100, int customSampleBank = 0, bool isLayered = false) + public LegacyHitSampleInfo(string name, string? bank = null, int volume = 0, int customSampleBank = 0, bool isLayered = false) : base(name, bank, customSampleBank >= 2 ? customSampleBank.ToString() : null, volume) { CustomSampleBank = customSampleBank; From 598572195c0f04acdc5c6785a88668464107f108 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 1 Dec 2020 19:57:25 +0900 Subject: [PATCH 060/184] Add playlist length to match settings overlay --- .../Match/Components/MatchSettingsOverlay.cs | 21 +++++++++++++++++++ osu.Game/Tests/Beatmaps/TestBeatmap.cs | 1 + 2 files changed, 22 insertions(+) diff --git a/osu.Game/Screens/Multi/Match/Components/MatchSettingsOverlay.cs b/osu.Game/Screens/Multi/Match/Components/MatchSettingsOverlay.cs index caefc194b1..8bf66b084c 100644 --- a/osu.Game/Screens/Multi/Match/Components/MatchSettingsOverlay.cs +++ b/osu.Game/Screens/Multi/Match/Components/MatchSettingsOverlay.cs @@ -2,7 +2,10 @@ // See the LICENCE file in the repository root for full licence text. using System; +using System.Collections.Specialized; +using System.Linq; using Humanizer; +using Humanizer.Localisation; using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Extensions.Color4Extensions; @@ -69,6 +72,7 @@ namespace osu.Game.Screens.Multi.Match.Components private OsuSpriteText typeLabel; private LoadingLayer loadingLayer; private DrawableRoomPlaylist playlist; + private OsuSpriteText playlistLength; [Resolved(CanBeNull = true)] private IRoomManager manager { get; set; } @@ -229,6 +233,15 @@ namespace osu.Game.Screens.Multi.Match.Components playlist = new DrawableRoomPlaylist(true, true) { RelativeSizeAxes = Axes.Both } }, new Drawable[] + { + playlistLength = new OsuSpriteText + { + Margin = new MarginPadding { Vertical = 5 }, + Colour = colours.Yellow, + Font = OsuFont.GetFont(size: 12), + } + }, + new Drawable[] { new PurpleTriangleButton { @@ -243,6 +256,7 @@ namespace osu.Game.Screens.Multi.Match.Components { new Dimension(), new Dimension(GridSizeMode.AutoSize), + new Dimension(GridSizeMode.AutoSize), } } }, @@ -315,6 +329,7 @@ namespace osu.Game.Screens.Multi.Match.Components Duration.BindValueChanged(duration => DurationField.Current.Value = duration.NewValue, true); playlist.Items.BindTo(Playlist); + Playlist.BindCollectionChanged(onPlaylistChanged, true); } protected override void Update() @@ -324,6 +339,12 @@ namespace osu.Game.Screens.Multi.Match.Components ApplyButton.Enabled.Value = hasValidSettings; } + private void onPlaylistChanged(object sender, NotifyCollectionChangedEventArgs e) + { + double totalLength = Playlist.Select(p => p.Beatmap.Value.Length).Sum(); + playlistLength.Text = $"Length: {totalLength.Milliseconds().Humanize(minUnit: TimeUnit.Second, maxUnit: TimeUnit.Hour, precision: 2)}"; + } + private bool hasValidSettings => RoomID.Value == null && NameField.Text.Length > 0 && Playlist.Count > 0; private void apply() diff --git a/osu.Game/Tests/Beatmaps/TestBeatmap.cs b/osu.Game/Tests/Beatmaps/TestBeatmap.cs index 87b77f4616..035cb64099 100644 --- a/osu.Game/Tests/Beatmaps/TestBeatmap.cs +++ b/osu.Game/Tests/Beatmaps/TestBeatmap.cs @@ -31,6 +31,7 @@ namespace osu.Game.Tests.Beatmaps BeatmapInfo.BeatmapSet.Metadata = BeatmapInfo.Metadata; BeatmapInfo.BeatmapSet.Files = new List(); BeatmapInfo.BeatmapSet.Beatmaps = new List { BeatmapInfo }; + BeatmapInfo.Length = 75000; BeatmapInfo.BeatmapSet.OnlineInfo = new BeatmapSetOnlineInfo { Status = BeatmapSetOnlineStatus.Ranked, From b236c75ac829f2cf76dcfd2f41da6c7f22c89f45 Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Tue, 1 Dec 2020 17:32:24 +0000 Subject: [PATCH 061/184] Bump Microsoft.Win32.Registry from 4.7.0 to 5.0.0 Bumps [Microsoft.Win32.Registry](https://github.com/dotnet/runtime) from 4.7.0 to 5.0.0. - [Release notes](https://github.com/dotnet/runtime/releases) - [Commits](https://github.com/dotnet/runtime/commits) Signed-off-by: dependabot-preview[bot] --- osu.Desktop/osu.Desktop.csproj | 2 +- osu.Game.Tournament/osu.Game.Tournament.csproj | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) 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.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 From 94a8784e04e2bd1157e0bb404fbf616148d82672 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Tue, 1 Dec 2020 20:08:31 +0100 Subject: [PATCH 062/184] Allow editor change handler to be null --- .../Compose/Components/Timeline/TimelineTickDisplay.cs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineTickDisplay.cs b/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineTickDisplay.cs index 71268a1e69..fb11b859a7 100644 --- a/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineTickDisplay.cs +++ b/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineTickDisplay.cs @@ -25,7 +25,7 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline [Resolved] private BindableBeatDivisor beatDivisor { get; set; } - [Resolved] + [Resolved(CanBeNull = true)] private IEditorChangeHandler changeHandler { get; set; } [Resolved] @@ -43,8 +43,9 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline { beatDivisor.BindValueChanged(_ => invalidateTicks()); - // currently this is the best way to handle any kind of timing changes. - changeHandler.OnStateChange += invalidateTicks; + if (changeHandler != null) + // currently this is the best way to handle any kind of timing changes. + changeHandler.OnStateChange += invalidateTicks; } private void invalidateTicks() From 03f5460dd2e269c28ae116df0ebd7317f7df9137 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Tue, 1 Dec 2020 21:57:16 +0100 Subject: [PATCH 063/184] Mark OsuModTestScene as abstract --- osu.Game.Rulesets.Osu.Tests/Mods/OsuModTestScene.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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(); } From c9429632f484516b874a91215213cb0fca970a94 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Tue, 1 Dec 2020 22:39:04 +0100 Subject: [PATCH 064/184] Resolve new NRE inspections --- osu.Desktop/OsuGameDesktop.cs | 2 +- osu.Game.Tournament/IPC/FileBasedIPC.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Desktop/OsuGameDesktop.cs b/osu.Desktop/OsuGameDesktop.cs index c62d2ee99f..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; 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; From 477de1bab0483a6b3e22b82a7fc30eaf4c9610aa Mon Sep 17 00:00:00 2001 From: Pennek <20502902+Pennek@users.noreply.github.com> Date: Wed, 2 Dec 2020 01:11:24 +0100 Subject: [PATCH 065/184] change min/max values --- osu.Game/Screens/Edit/Setup/DifficultySection.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) 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, } }, From a9003466e301abe093880aa36ff97e27d0048e9f Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Wed, 2 Dec 2020 00:56:05 +0000 Subject: [PATCH 066/184] Bump Microsoft.Build.Traversal from 2.2.3 to 3.0.2 Bumps [Microsoft.Build.Traversal](https://github.com/Microsoft/MSBuildSdks) from 2.2.3 to 3.0.2. - [Release notes](https://github.com/Microsoft/MSBuildSdks/releases) - [Changelog](https://github.com/microsoft/MSBuildSdks/blob/master/RELEASE.md) - [Commits](https://github.com/Microsoft/MSBuildSdks/compare/Microsoft.Build.Traversal.2.2.3...Microsoft.Build.Traversal.3.0.2) Signed-off-by: dependabot-preview[bot] --- global.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/global.json b/global.json index 10b61047ac..2c93a533e4 100644 --- a/global.json +++ b/global.json @@ -5,6 +5,6 @@ "version": "3.1.100" }, "msbuild-sdks": { - "Microsoft.Build.Traversal": "2.2.3" + "Microsoft.Build.Traversal": "3.0.2" } } \ No newline at end of file From aac20eef441091e6f91000b7c76951d71ced3827 Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Wed, 2 Dec 2020 00:56:05 +0000 Subject: [PATCH 067/184] Bump System.IO.Packaging from 4.7.0 to 5.0.0 Bumps [System.IO.Packaging](https://github.com/dotnet/runtime) from 4.7.0 to 5.0.0. - [Release notes](https://github.com/dotnet/runtime/releases) - [Commits](https://github.com/dotnet/runtime/commits) Signed-off-by: dependabot-preview[bot] --- osu.Desktop/osu.Desktop.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Desktop/osu.Desktop.csproj b/osu.Desktop/osu.Desktop.csproj index 7b80ca64d0..47c0d805b5 100644 --- a/osu.Desktop/osu.Desktop.csproj +++ b/osu.Desktop/osu.Desktop.csproj @@ -24,7 +24,7 @@ - + From 64dfa9f9285affbb68d027782ec9cd69dad6068e Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Wed, 2 Dec 2020 00:56:06 +0000 Subject: [PATCH 068/184] Bump Dapper from 2.0.35 to 2.0.78 Bumps [Dapper](https://github.com/StackExchange/Dapper) from 2.0.35 to 2.0.78. - [Release notes](https://github.com/StackExchange/Dapper/releases) - [Commits](https://github.com/StackExchange/Dapper/commits) Signed-off-by: dependabot-preview[bot] --- osu.Game/osu.Game.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index 88af0e2138..4de711eb8b 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -18,7 +18,7 @@ - + From 8a65328a6d5914abe07de7eddf0e2a7f234a5113 Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Wed, 2 Dec 2020 00:56:08 +0000 Subject: [PATCH 069/184] Bump DiscordRichPresence from 1.0.150 to 1.0.166 Bumps [DiscordRichPresence](https://github.com/Lachee/discord-rpc-csharp) from 1.0.150 to 1.0.166. - [Release notes](https://github.com/Lachee/discord-rpc-csharp/releases) - [Commits](https://github.com/Lachee/discord-rpc-csharp/commits) Signed-off-by: dependabot-preview[bot] --- osu.Desktop/osu.Desktop.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Desktop/osu.Desktop.csproj b/osu.Desktop/osu.Desktop.csproj index 7b80ca64d0..51300dcef8 100644 --- a/osu.Desktop/osu.Desktop.csproj +++ b/osu.Desktop/osu.Desktop.csproj @@ -29,7 +29,7 @@ - + From 5772a0811c69d8b232a03d712b839a1dd1e870bf Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Wed, 2 Dec 2020 00:56:09 +0000 Subject: [PATCH 070/184] Bump Microsoft.NET.Test.Sdk from 16.7.1 to 16.8.0 Bumps [Microsoft.NET.Test.Sdk](https://github.com/microsoft/vstest) from 16.7.1 to 16.8.0. - [Release notes](https://github.com/microsoft/vstest/releases) - [Commits](https://github.com/microsoft/vstest/compare/v16.7.1...v16.8.0) Signed-off-by: dependabot-preview[bot] --- .../osu.Game.Rulesets.Catch.Tests.csproj | 2 +- .../osu.Game.Rulesets.Mania.Tests.csproj | 2 +- osu.Game.Rulesets.Osu.Tests/osu.Game.Rulesets.Osu.Tests.csproj | 2 +- .../osu.Game.Rulesets.Taiko.Tests.csproj | 2 +- osu.Game.Tests/osu.Game.Tests.csproj | 2 +- osu.Game.Tournament.Tests/osu.Game.Tournament.Tests.csproj | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) 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 dfe3bf8af4..61ecd79e3d 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 892f27d27f..fa7bfd7169 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/osu.Game.Rulesets.Osu.Tests.csproj b/osu.Game.Rulesets.Osu.Tests/osu.Game.Rulesets.Osu.Tests.csproj index 3639c3616f..d6a03da807 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.Taiko.Tests/osu.Game.Rulesets.Taiko.Tests.csproj b/osu.Game.Rulesets.Taiko.Tests/osu.Game.Rulesets.Taiko.Tests.csproj index b59f3a4344..a89645d881 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/osu.Game.Tests.csproj b/osu.Game.Tests/osu.Game.Tests.csproj index c692bcd5e4..83d7b4135a 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 5d55196dcf..bc6b994988 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 @@ - + From 249793d10a3cf8ab5f3ed5242d295097e637aedd Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Wed, 2 Dec 2020 00:56:09 +0000 Subject: [PATCH 071/184] Bump Sentry from 2.1.6 to 2.1.8 Bumps [Sentry](https://github.com/getsentry/sentry-dotnet) from 2.1.6 to 2.1.8. - [Release notes](https://github.com/getsentry/sentry-dotnet/releases) - [Changelog](https://github.com/getsentry/sentry-dotnet/blob/main/CHANGELOG.md) - [Commits](https://github.com/getsentry/sentry-dotnet/compare/2.1.6...2.1.8) Signed-off-by: dependabot-preview[bot] --- osu.Game/osu.Game.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index 88af0e2138..3fa703cf8f 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -28,7 +28,7 @@ - + From 989ddd40b42a0766c773eba11ad8ec7f67ea2c44 Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Wed, 2 Dec 2020 00:56:13 +0000 Subject: [PATCH 072/184] Bump System.ComponentModel.Annotations from 4.7.0 to 5.0.0 Bumps [System.ComponentModel.Annotations](https://github.com/dotnet/runtime) from 4.7.0 to 5.0.0. - [Release notes](https://github.com/dotnet/runtime/releases) - [Commits](https://github.com/dotnet/runtime/commits) Signed-off-by: dependabot-preview[bot] --- osu.Game/osu.Game.csproj | 2 +- osu.iOS.props | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index 88af0e2138..923f8f7866 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -31,6 +31,6 @@ - + diff --git a/osu.iOS.props b/osu.iOS.props index 06b0ec8a13..b32d3f900a 100644 --- a/osu.iOS.props +++ b/osu.iOS.props @@ -92,7 +92,7 @@ - + From e19ef9627a1b0f75b68d184ea5fe5b8d0576dc4d Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 2 Dec 2020 10:54:26 +0900 Subject: [PATCH 073/184] Fix potentially incorrect override --- .../Rulesets/Objects/Legacy/ConvertHitObjectParser.cs | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/osu.Game/Rulesets/Objects/Legacy/ConvertHitObjectParser.cs b/osu.Game/Rulesets/Objects/Legacy/ConvertHitObjectParser.cs index 2cb72e9e80..119c9ccd7c 100644 --- a/osu.Game/Rulesets/Objects/Legacy/ConvertHitObjectParser.cs +++ b/osu.Game/Rulesets/Objects/Legacy/ConvertHitObjectParser.cs @@ -486,11 +486,11 @@ namespace osu.Game.Rulesets.Objects.Legacy IsLayered = isLayered; } - public override HitSampleInfo With(Optional name = default, Optional bank = default, Optional suffix = default, Optional volume = default) + public sealed override HitSampleInfo With(Optional name = default, Optional bank = default, Optional suffix = default, Optional volume = default) => With(name, bank, volume); - public LegacyHitSampleInfo With(Optional name = default, Optional bank = default, Optional volume = default, Optional customSampleBank = default, - Optional isLayered = default) + public virtual LegacyHitSampleInfo With(Optional name = default, Optional bank = default, Optional volume = default, Optional customSampleBank = default, + Optional isLayered = default) => new LegacyHitSampleInfo(name.GetOr(Name), bank.GetOr(Bank), volume.GetOr(Volume), customSampleBank.GetOr(CustomSampleBank), isLayered.GetOr(IsLayered)); public bool Equals(LegacyHitSampleInfo? other) @@ -520,7 +520,8 @@ namespace osu.Game.Rulesets.Objects.Legacy Path.ChangeExtension(Filename, null) }; - public override HitSampleInfo With(Optional name = default, Optional bank = default, Optional suffix = default, Optional volume = default) + public sealed override LegacyHitSampleInfo With(Optional name = default, Optional bank = default, Optional volume = default, Optional customSampleBank = default, + Optional isLayered = default) => new FileHitSampleInfo(Filename, volume.GetOr(Volume)); public bool Equals(FileHitSampleInfo? other) From 2150cf1c52336cc624e7bc13fb4eb78ae18d1bd9 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 2 Dec 2020 10:55:48 +0900 Subject: [PATCH 074/184] Rename parameters --- osu.Game/Audio/HitSampleInfo.cs | 12 ++++++------ .../Beatmaps/ControlPoints/SampleControlPoint.cs | 2 +- osu.Game/Beatmaps/Formats/LegacyDecoder.cs | 2 +- .../Objects/Legacy/ConvertHitObjectParser.cs | 16 ++++++++-------- 4 files changed, 16 insertions(+), 16 deletions(-) diff --git a/osu.Game/Audio/HitSampleInfo.cs b/osu.Game/Audio/HitSampleInfo.cs index 58b078db71..3d90dd0189 100644 --- a/osu.Game/Audio/HitSampleInfo.cs +++ b/osu.Game/Audio/HitSampleInfo.cs @@ -72,13 +72,13 @@ namespace osu.Game.Audio /// /// Creates a new with overridden values. /// - /// An optional new sample name. - /// An optional new sample bank. - /// An optional new lookup suffix. - /// An optional new volume. + /// An optional new sample name. + /// An optional new sample bank. + /// An optional new lookup suffix. + /// An optional new volume. /// The new . - public virtual HitSampleInfo With(Optional name = default, Optional bank = default, Optional suffix = default, Optional volume = default) - => new HitSampleInfo(name.GetOr(Name), bank.GetOr(Bank), suffix.GetOr(Suffix), volume.GetOr(Volume)); + public virtual HitSampleInfo With(Optional newName = default, Optional newBank = default, Optional newSuffix = default, Optional newVolume = default) + => new HitSampleInfo(newName.GetOr(Name), newBank.GetOr(Bank), newSuffix.GetOr(Suffix), newVolume.GetOr(Volume)); public bool Equals(HitSampleInfo? other) => other != null && Name == other.Name && Bank == other.Bank && Suffix == other.Suffix; diff --git a/osu.Game/Beatmaps/ControlPoints/SampleControlPoint.cs b/osu.Game/Beatmaps/ControlPoints/SampleControlPoint.cs index 8064da1543..fd0b496335 100644 --- a/osu.Game/Beatmaps/ControlPoints/SampleControlPoint.cs +++ b/osu.Game/Beatmaps/ControlPoints/SampleControlPoint.cs @@ -66,7 +66,7 @@ namespace osu.Game.Beatmaps.ControlPoints /// The . This will not be modified. /// The modified . This does not share a reference with . public virtual HitSampleInfo ApplyTo(HitSampleInfo hitSampleInfo) - => hitSampleInfo.With(bank: hitSampleInfo.Bank ?? SampleBank, volume: hitSampleInfo.Volume > 0 ? hitSampleInfo.Volume : SampleVolume); + => hitSampleInfo.With(newBank: hitSampleInfo.Bank ?? SampleBank, newVolume: hitSampleInfo.Volume > 0 ? hitSampleInfo.Volume : SampleVolume); public override bool IsRedundant(ControlPoint existing) => existing is SampleControlPoint existingSample diff --git a/osu.Game/Beatmaps/Formats/LegacyDecoder.cs b/osu.Game/Beatmaps/Formats/LegacyDecoder.cs index 9f16180e77..c9d139bdd0 100644 --- a/osu.Game/Beatmaps/Formats/LegacyDecoder.cs +++ b/osu.Game/Beatmaps/Formats/LegacyDecoder.cs @@ -183,7 +183,7 @@ namespace osu.Game.Beatmaps.Formats var baseInfo = base.ApplyTo(hitSampleInfo); if (baseInfo is ConvertHitObjectParser.LegacyHitSampleInfo legacy && legacy.CustomSampleBank == 0) - return legacy.With(customSampleBank: CustomSampleBank); + return legacy.With(newCustomSampleBank: CustomSampleBank); return baseInfo; } diff --git a/osu.Game/Rulesets/Objects/Legacy/ConvertHitObjectParser.cs b/osu.Game/Rulesets/Objects/Legacy/ConvertHitObjectParser.cs index 119c9ccd7c..72025de131 100644 --- a/osu.Game/Rulesets/Objects/Legacy/ConvertHitObjectParser.cs +++ b/osu.Game/Rulesets/Objects/Legacy/ConvertHitObjectParser.cs @@ -486,12 +486,12 @@ namespace osu.Game.Rulesets.Objects.Legacy IsLayered = isLayered; } - public sealed override HitSampleInfo With(Optional name = default, Optional bank = default, Optional suffix = default, Optional volume = default) - => With(name, bank, volume); + public sealed override HitSampleInfo With(Optional newName = default, Optional newBank = default, Optional newSuffix = default, Optional newVolume = default) + => With(newName, newBank, newVolume); - public virtual LegacyHitSampleInfo With(Optional name = default, Optional bank = default, Optional volume = default, Optional customSampleBank = default, - Optional isLayered = default) - => new LegacyHitSampleInfo(name.GetOr(Name), bank.GetOr(Bank), volume.GetOr(Volume), customSampleBank.GetOr(CustomSampleBank), isLayered.GetOr(IsLayered)); + public virtual LegacyHitSampleInfo With(Optional newName = default, Optional newBank = default, Optional newVolume = default, Optional newCustomSampleBank = default, + Optional newIsLayered = default) + => new LegacyHitSampleInfo(newName.GetOr(Name), newBank.GetOr(Bank), newVolume.GetOr(Volume), newCustomSampleBank.GetOr(CustomSampleBank), newIsLayered.GetOr(IsLayered)); public bool Equals(LegacyHitSampleInfo? other) => base.Equals(other) && CustomSampleBank == other.CustomSampleBank && IsLayered == other.IsLayered; @@ -520,9 +520,9 @@ namespace osu.Game.Rulesets.Objects.Legacy Path.ChangeExtension(Filename, null) }; - public sealed override LegacyHitSampleInfo With(Optional name = default, Optional bank = default, Optional volume = default, Optional customSampleBank = default, - Optional isLayered = default) - => new FileHitSampleInfo(Filename, volume.GetOr(Volume)); + public sealed override LegacyHitSampleInfo With(Optional newName = default, Optional newBank = default, Optional newVolume = default, Optional newCustomSampleBank = default, + Optional newIsLayered = default) + => new FileHitSampleInfo(Filename, newVolume.GetOr(Volume)); public bool Equals(FileHitSampleInfo? other) => base.Equals(other) && Filename == other.Filename; From 2de3e655e07ad95dfdd9b25ee5d0a440567d7cb8 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 2 Dec 2020 12:59:45 +0900 Subject: [PATCH 075/184] Rename NextUlong -> NextULong --- osu.Game/Utils/StatelessRNG.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/osu.Game/Utils/StatelessRNG.cs b/osu.Game/Utils/StatelessRNG.cs index 11d079498a..118b08fe30 100644 --- a/osu.Game/Utils/StatelessRNG.cs +++ b/osu.Game/Utils/StatelessRNG.cs @@ -33,7 +33,7 @@ namespace osu.Game.Utils /// The series number. /// Different values are computed for the same seed in different series. /// - public static ulong NextUlong(int seed, int series = 0) + public static ulong NextULong(int seed, int series = 0) { unchecked { @@ -60,7 +60,7 @@ namespace osu.Game.Utils { if (maxValue <= 0) throw new ArgumentOutOfRangeException(nameof(maxValue)); - return (int)(NextUlong(seed, series) % (ulong)maxValue); + return (int)(NextULong(seed, series) % (ulong)maxValue); } /// @@ -74,6 +74,6 @@ namespace osu.Game.Utils /// Different values are computed for the same seed in different series. /// public static float NextSingle(int seed, int series = 0) => - (float)(NextUlong(seed, series) & ((1 << 24) - 1)) / (1 << 24); // float has 24-bit precision + (float)(NextULong(seed, series) & ((1 << 24) - 1)) / (1 << 24); // float has 24-bit precision } } From e84dab858991fdf0363a93b9269789df4208ce00 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 2 Dec 2020 14:36:52 +0900 Subject: [PATCH 076/184] Move new beatmap construction above beat divisor binding --- osu.Game/Screens/Edit/Editor.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/osu.Game/Screens/Edit/Editor.cs b/osu.Game/Screens/Edit/Editor.cs index 8f1cd8e28e..ca7e5fbf20 100644 --- a/osu.Game/Screens/Edit/Editor.cs +++ b/osu.Game/Screens/Edit/Editor.cs @@ -106,15 +106,15 @@ namespace osu.Game.Screens.Edit [BackgroundDependencyLoader] private void load(OsuColour colours, GameHost host, OsuConfigManager config) { - beatDivisor.Value = Beatmap.Value.BeatmapInfo.BeatDivisor; - beatDivisor.BindValueChanged(divisor => Beatmap.Value.BeatmapInfo.BeatDivisor = divisor.NewValue); - if (Beatmap.Value is DummyWorkingBeatmap) { isNewBeatmap = true; Beatmap.Value = beatmapManager.CreateNew(Ruleset.Value, api.LocalUser.Value); } + beatDivisor.Value = Beatmap.Value.BeatmapInfo.BeatDivisor; + beatDivisor.BindValueChanged(divisor => Beatmap.Value.BeatmapInfo.BeatDivisor = divisor.NewValue); + // Todo: should probably be done at a DrawableRuleset level to share logic with Player. clock = new EditorClock(Beatmap.Value, beatDivisor) { IsCoupled = false }; From 946613e803f27025103eb8b0232a4562939877b3 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 2 Dec 2020 15:22:45 +0900 Subject: [PATCH 077/184] Fix bananas not playing sounds --- osu.Game.Rulesets.Catch/Objects/Banana.cs | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/osu.Game.Rulesets.Catch/Objects/Banana.cs b/osu.Game.Rulesets.Catch/Objects/Banana.cs index 7734ebed12..a274f25200 100644 --- a/osu.Game.Rulesets.Catch/Objects/Banana.cs +++ b/osu.Game.Rulesets.Catch/Objects/Banana.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable enable + using System; using System.Collections.Generic; using osu.Framework.Utils; @@ -8,6 +10,7 @@ using osu.Game.Audio; using osu.Game.Rulesets.Catch.Judgements; using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Objects.Types; +using osu.Game.Utils; using osuTK.Graphics; namespace osu.Game.Rulesets.Catch.Objects @@ -53,19 +56,22 @@ namespace osu.Game.Rulesets.Catch.Objects private class BananaHitSampleInfo : HitSampleInfo, IEquatable { - private static readonly string[] lookup_names = { "metronomelow", "catch-banana" }; + private static readonly string[] lookup_names = { "Gameplay/metronomelow", "Gameplay/catch-banana" }; public override IEnumerable LookupNames => lookup_names; - public BananaHitSampleInfo() - : base(string.Empty) + public BananaHitSampleInfo(int volume = 0) + : base(string.Empty, volume: volume) { } - public bool Equals(BananaHitSampleInfo other) + public sealed override HitSampleInfo With(Optional newName = default, Optional newBank = default, Optional newSuffix = default, Optional newVolume = default) + => new BananaHitSampleInfo(newVolume.GetOr(Volume)); + + public bool Equals(BananaHitSampleInfo? other) => other != null; - public override bool Equals(object obj) + public override bool Equals(object? obj) => obj is BananaHitSampleInfo other && Equals(other); public override int GetHashCode() => lookup_names.GetHashCode(); From 32188418f446f4624b7ecb90e1144bfa57923ae4 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 2 Dec 2020 15:28:39 +0900 Subject: [PATCH 078/184] Update resources --- osu.Android.props | 2 +- osu.Game/osu.Game.csproj | 2 +- osu.iOS.props | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/osu.Android.props b/osu.Android.props index aa4d9fa4ee..9d99218f88 100644 --- a/osu.Android.props +++ b/osu.Android.props @@ -51,7 +51,7 @@ - + diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index 53b854caa3..4b931726e0 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -27,7 +27,7 @@ - + diff --git a/osu.iOS.props b/osu.iOS.props index b32d3f900a..3a47b77820 100644 --- a/osu.iOS.props +++ b/osu.iOS.props @@ -71,7 +71,7 @@ - + From e7c0e9834f41f5f52fb3b331a02c4742c84bf342 Mon Sep 17 00:00:00 2001 From: ekrctb Date: Wed, 2 Dec 2020 16:53:01 +0900 Subject: [PATCH 079/184] Introduce RandomSeed in catch DHO --- .../Drawables/DrawableCatchHitObject.cs | 23 +++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/osu.Game.Rulesets.Catch/Objects/Drawables/DrawableCatchHitObject.cs b/osu.Game.Rulesets.Catch/Objects/Drawables/DrawableCatchHitObject.cs index 1faa6a5b0f..eb5f9451b1 100644 --- a/osu.Game.Rulesets.Catch/Objects/Drawables/DrawableCatchHitObject.cs +++ b/osu.Game.Rulesets.Catch/Objects/Drawables/DrawableCatchHitObject.cs @@ -3,10 +3,13 @@ using System; using JetBrains.Annotations; +using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Game.Rulesets.Catch.UI; +using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Objects.Drawables; +using osu.Game.Utils; namespace osu.Game.Rulesets.Catch.Objects.Drawables { @@ -20,12 +23,32 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawables protected override float SamplePlaybackPosition => HitObject.X / CatchPlayfield.WIDTH; + /// + /// The seed value used for visual randomness such as fruit rotation. + /// By default, truncated to an integer is used. + /// + public Bindable RandomSeed = new Bindable(); + protected DrawableCatchHitObject([CanBeNull] CatchHitObject hitObject) : base(hitObject) { Anchor = Anchor.BottomLeft; } + [BackgroundDependencyLoader] + private void load() + { + StartTimeBindable.BindValueChanged(change => + { + RandomSeed.Value = (int)change.NewValue; + }, true); + } + + /// + /// Get a random number in range [0,1) based on seed . + /// + public float RandomSingle(int series) => StatelessRNG.NextSingle(RandomSeed.Value, series); + protected override void OnApply() { base.OnApply(); From 8b6161a51c27fce87f51a171a2a6f4c2e402e212 Mon Sep 17 00:00:00 2001 From: ekrctb Date: Wed, 2 Dec 2020 16:54:18 +0900 Subject: [PATCH 080/184] Use deterministic randomness in catch hit object --- .../Objects/Drawables/DrawableBanana.cs | 20 ++++++++++++++----- .../Objects/Drawables/DrawableDroplet.cs | 3 +-- .../Objects/Drawables/DrawableFruit.cs | 8 +++++--- 3 files changed, 21 insertions(+), 10 deletions(-) diff --git a/osu.Game.Rulesets.Catch/Objects/Drawables/DrawableBanana.cs b/osu.Game.Rulesets.Catch/Objects/Drawables/DrawableBanana.cs index fb982bbdab..4e34dd2b90 100644 --- a/osu.Game.Rulesets.Catch/Objects/Drawables/DrawableBanana.cs +++ b/osu.Game.Rulesets.Catch/Objects/Drawables/DrawableBanana.cs @@ -3,7 +3,6 @@ using JetBrains.Annotations; using osu.Framework.Graphics; -using osu.Framework.Utils; namespace osu.Game.Rulesets.Catch.Objects.Drawables { @@ -21,6 +20,17 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawables { } + protected override void LoadComplete() + { + base.LoadComplete(); + + RandomSeed.BindValueChanged(_ => + { + UpdateComboColour(); + UpdateInitialTransforms(); + }); + } + protected override void UpdateInitialTransforms() { base.UpdateInitialTransforms(); @@ -28,14 +38,14 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawables const float end_scale = 0.6f; const float random_scale_range = 1.6f; - ScaleContainer.ScaleTo(HitObject.Scale * (end_scale + random_scale_range * RNG.NextSingle())) + ScaleContainer.ScaleTo(HitObject.Scale * (end_scale + random_scale_range * RandomSingle(3))) .Then().ScaleTo(HitObject.Scale * end_scale, HitObject.TimePreempt); - ScaleContainer.RotateTo(getRandomAngle()) + ScaleContainer.RotateTo(getRandomAngle(1)) .Then() - .RotateTo(getRandomAngle(), HitObject.TimePreempt); + .RotateTo(getRandomAngle(2), HitObject.TimePreempt); - float getRandomAngle() => 180 * (RNG.NextSingle() * 2 - 1); + float getRandomAngle(int series) => 180 * (RandomSingle(series) * 2 - 1); } public override void PlaySamples() diff --git a/osu.Game.Rulesets.Catch/Objects/Drawables/DrawableDroplet.cs b/osu.Game.Rulesets.Catch/Objects/Drawables/DrawableDroplet.cs index 06ecd44488..b8acea625b 100644 --- a/osu.Game.Rulesets.Catch/Objects/Drawables/DrawableDroplet.cs +++ b/osu.Game.Rulesets.Catch/Objects/Drawables/DrawableDroplet.cs @@ -4,7 +4,6 @@ using JetBrains.Annotations; using osu.Framework.Allocation; using osu.Framework.Graphics; -using osu.Framework.Utils; using osu.Game.Rulesets.Catch.Objects.Drawables.Pieces; using osu.Game.Skinning; @@ -45,7 +44,7 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawables base.UpdateInitialTransforms(); // roughly matches osu-stable - float startRotation = RNG.NextSingle() * 20; + float startRotation = RandomSingle(1) * 20; double duration = HitObject.TimePreempt + 2000; ScaleContainer.RotateTo(startRotation).RotateTo(startRotation + 720, duration); diff --git a/osu.Game.Rulesets.Catch/Objects/Drawables/DrawableFruit.cs b/osu.Game.Rulesets.Catch/Objects/Drawables/DrawableFruit.cs index 68cb649b66..010a3ee08c 100644 --- a/osu.Game.Rulesets.Catch/Objects/Drawables/DrawableFruit.cs +++ b/osu.Game.Rulesets.Catch/Objects/Drawables/DrawableFruit.cs @@ -5,7 +5,6 @@ using System; using JetBrains.Annotations; using osu.Framework.Allocation; using osu.Framework.Bindables; -using osu.Framework.Utils; using osu.Game.Rulesets.Catch.Objects.Drawables.Pieces; using osu.Game.Skinning; @@ -30,8 +29,6 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawables [BackgroundDependencyLoader] private void load() { - ScaleContainer.Rotation = (float)(RNG.NextDouble() - 0.5f) * 40; - IndexInBeatmap.BindValueChanged(change => { VisualRepresentation.Value = GetVisualRepresentation(change.NewValue); @@ -39,6 +36,11 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawables VisualRepresentation.BindValueChanged(_ => updatePiece()); HyperDash.BindValueChanged(_ => updatePiece(), true); + + RandomSeed.BindValueChanged(_ => + { + ScaleContainer.Rotation = (RandomSingle(1) - 0.5f) * 40; + }, true); } private void updatePiece() From 8a78c495f22416e533249ae4173bb2e81b6411c4 Mon Sep 17 00:00:00 2001 From: ekrctb Date: Wed, 2 Dec 2020 16:55:37 +0900 Subject: [PATCH 081/184] Refactor DHO testing logic to the "specimen" class --- .../TestSceneFruitObjects.cs | 34 +++++++++++++------ .../TestSceneFruitVisualChange.cs | 4 +-- 2 files changed, 25 insertions(+), 13 deletions(-) diff --git a/osu.Game.Rulesets.Catch.Tests/TestSceneFruitObjects.cs b/osu.Game.Rulesets.Catch.Tests/TestSceneFruitObjects.cs index 160da75aa9..3a651605d3 100644 --- a/osu.Game.Rulesets.Catch.Tests/TestSceneFruitObjects.cs +++ b/osu.Game.Rulesets.Catch.Tests/TestSceneFruitObjects.cs @@ -3,11 +3,12 @@ using NUnit.Framework; using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Timing; using osu.Game.Beatmaps; using osu.Game.Beatmaps.ControlPoints; using osu.Game.Rulesets.Catch.Objects; using osu.Game.Rulesets.Catch.Objects.Drawables; -using osuTK; namespace osu.Game.Rulesets.Catch.Tests { @@ -37,39 +38,50 @@ namespace osu.Game.Rulesets.Catch.Tests } private Drawable createDrawableFruit(int indexInBeatmap, bool hyperdash = false) => - SetProperties(new DrawableFruit(new Fruit + new TestDrawableCatchHitObjectSpecimen(new DrawableFruit(new Fruit { IndexInBeatmap = indexInBeatmap, HyperDashBindable = { Value = hyperdash } })); private Drawable createDrawableBanana() => - SetProperties(new DrawableBanana(new Banana())); + new TestDrawableCatchHitObjectSpecimen(new DrawableBanana(new Banana())); private Drawable createDrawableDroplet(bool hyperdash = false) => - SetProperties(new DrawableDroplet(new Droplet + new TestDrawableCatchHitObjectSpecimen(new DrawableDroplet(new Droplet { HyperDashBindable = { Value = hyperdash } })); - private Drawable createDrawableTinyDroplet() => SetProperties(new DrawableTinyDroplet(new TinyDroplet())); + private Drawable createDrawableTinyDroplet() => new TestDrawableCatchHitObjectSpecimen(new DrawableTinyDroplet(new TinyDroplet())); + } - protected virtual DrawableCatchHitObject SetProperties(DrawableCatchHitObject d) + public class TestDrawableCatchHitObjectSpecimen : CompositeDrawable + { + public readonly ManualClock ManualClock; + + public TestDrawableCatchHitObjectSpecimen(DrawableCatchHitObject d) { + AutoSizeAxes = Axes.Both; + Anchor = Anchor.Centre; + Origin = Anchor.Centre; + + ManualClock = new ManualClock(); + Clock = new FramedClock(ManualClock); + var hitObject = d.HitObject; - hitObject.ApplyDefaults(new ControlPointInfo(), new BeatmapDifficulty { CircleSize = 0 }); - hitObject.StartTime = 1000000000000; + hitObject.ApplyDefaults(new ControlPointInfo(), new BeatmapDifficulty()); hitObject.Scale = 1.5f; + hitObject.StartTime = 500; d.Anchor = Anchor.Centre; - d.RelativePositionAxes = Axes.None; - d.Position = Vector2.Zero; d.HitObjectApplied += _ => { d.LifetimeStart = double.NegativeInfinity; d.LifetimeEnd = double.PositiveInfinity; }; - return d; + + InternalChild = d; } } } diff --git a/osu.Game.Rulesets.Catch.Tests/TestSceneFruitVisualChange.cs b/osu.Game.Rulesets.Catch.Tests/TestSceneFruitVisualChange.cs index 4448e828e7..125e0c674c 100644 --- a/osu.Game.Rulesets.Catch.Tests/TestSceneFruitVisualChange.cs +++ b/osu.Game.Rulesets.Catch.Tests/TestSceneFruitVisualChange.cs @@ -14,13 +14,13 @@ namespace osu.Game.Rulesets.Catch.Tests protected override void LoadComplete() { - AddStep("fruit changes visual and hyper", () => SetContents(() => SetProperties(new DrawableFruit(new Fruit + AddStep("fruit changes visual and hyper", () => SetContents(() => new TestDrawableCatchHitObjectSpecimen(new DrawableFruit(new Fruit { IndexInBeatmapBindable = { BindTarget = indexInBeatmap }, HyperDashBindable = { BindTarget = hyperDash }, })))); - AddStep("droplet changes hyper", () => SetContents(() => SetProperties(new DrawableDroplet(new Droplet + AddStep("droplet changes hyper", () => SetContents(() => new TestDrawableCatchHitObjectSpecimen(new DrawableDroplet(new Droplet { HyperDashBindable = { BindTarget = hyperDash }, })))); From beda6961e433b7df28f69b898c975035e8ce24ee Mon Sep 17 00:00:00 2001 From: ekrctb Date: Wed, 2 Dec 2020 16:55:58 +0900 Subject: [PATCH 082/184] Add a test for fruit randomness --- .../TestSceneFruitRandomness.cs | 95 +++++++++++++++++++ 1 file changed, 95 insertions(+) create mode 100644 osu.Game.Rulesets.Catch.Tests/TestSceneFruitRandomness.cs diff --git a/osu.Game.Rulesets.Catch.Tests/TestSceneFruitRandomness.cs b/osu.Game.Rulesets.Catch.Tests/TestSceneFruitRandomness.cs new file mode 100644 index 0000000000..449cfac2db --- /dev/null +++ b/osu.Game.Rulesets.Catch.Tests/TestSceneFruitRandomness.cs @@ -0,0 +1,95 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using NUnit.Framework; +using osu.Framework.Bindables; +using osu.Game.Rulesets.Catch.Objects; +using osu.Game.Rulesets.Catch.Objects.Drawables; +using osu.Game.Tests.Visual; + +namespace osu.Game.Rulesets.Catch.Tests +{ + public class TestSceneFruitRandomness : OsuTestScene + { + [Test] + public void TestFruitRandomness() + { + Bindable randomSeed = new Bindable(); + + TestDrawableFruit drawableFruit; + TestDrawableBanana drawableBanana; + + Add(new TestDrawableCatchHitObjectSpecimen(drawableFruit = new TestDrawableFruit(new Fruit()) + { + RandomSeed = { BindTarget = randomSeed } + }) { X = -200 }); + Add(new TestDrawableCatchHitObjectSpecimen(drawableBanana = new TestDrawableBanana(new Banana()) + { + RandomSeed = { BindTarget = randomSeed } + })); + + float fruitRotation = 0; + float bananaRotation = 0; + float bananaScale = 0; + + AddStep("set random seed to 0", () => + { + drawableFruit.HitObject.StartTime = 500; + randomSeed.Value = 0; + + fruitRotation = drawableFruit.InnerRotation; + bananaRotation = drawableBanana.InnerRotation; + bananaScale = drawableBanana.InnerScale; + }); + + AddStep("change random seed", () => + { + randomSeed.Value = 10; + }); + + AddAssert("fruit rotation is changed", () => drawableFruit.InnerRotation != fruitRotation); + AddAssert("banana rotation is changed", () => drawableBanana.InnerRotation != bananaRotation); + AddAssert("banana scale is changed", () => drawableBanana.InnerScale != bananaScale); + + AddStep("reset random seed", () => + { + randomSeed.Value = 0; + }); + + AddAssert("rotation and scale restored", () => + drawableFruit.InnerRotation == fruitRotation && + drawableBanana.InnerRotation == bananaRotation && + drawableBanana.InnerScale == bananaScale); + + AddStep("change start time", () => + { + drawableFruit.HitObject.StartTime = 1000; + }); + + AddAssert("random seed is changed", () => randomSeed.Value == 1000); + + AddSliderStep("random seed", 0, 100, 0, x => randomSeed.Value = x); + } + + private class TestDrawableFruit : DrawableFruit + { + public float InnerRotation => ScaleContainer.Rotation; + + public TestDrawableFruit(Fruit h) + : base(h) + { + } + } + + private class TestDrawableBanana : DrawableBanana + { + public float InnerRotation => ScaleContainer.Rotation; + public float InnerScale => ScaleContainer.Scale.X; + + public TestDrawableBanana(Banana h) + : base(h) + { + } + } + } +} From 08848e49de025022e9ae8ec0338e067987a53b03 Mon Sep 17 00:00:00 2001 From: ekrctb Date: Wed, 2 Dec 2020 17:12:30 +0900 Subject: [PATCH 083/184] Set banana combo colour using random seed --- osu.Game.Rulesets.Catch/Objects/Banana.cs | 13 ++++--------- .../Objects/CatchHitObject.cs | 10 ++++++++++ .../Objects/Drawables/DrawableCatchHitObject.cs | 17 ++--------------- 3 files changed, 16 insertions(+), 24 deletions(-) diff --git a/osu.Game.Rulesets.Catch/Objects/Banana.cs b/osu.Game.Rulesets.Catch/Objects/Banana.cs index 7734ebed12..9fd01b3717 100644 --- a/osu.Game.Rulesets.Catch/Objects/Banana.cs +++ b/osu.Game.Rulesets.Catch/Objects/Banana.cs @@ -3,11 +3,11 @@ using System; using System.Collections.Generic; -using osu.Framework.Utils; using osu.Game.Audio; using osu.Game.Rulesets.Catch.Judgements; using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Objects.Types; +using osu.Game.Utils; using osuTK.Graphics; namespace osu.Game.Rulesets.Catch.Objects @@ -28,17 +28,12 @@ namespace osu.Game.Rulesets.Catch.Objects Samples = samples; } - private Color4? colour; - - Color4 IHasComboInformation.GetComboColour(IReadOnlyList comboColours) - { - // override any external colour changes with banananana - return colour ??= getBananaColour(); - } + // override any external colour changes with banananana + Color4 IHasComboInformation.GetComboColour(IReadOnlyList comboColours) => getBananaColour(); private Color4 getBananaColour() { - switch (RNG.Next(0, 3)) + switch (StatelessRNG.NextInt(3, RandomSeed.Value)) { default: return new Color4(255, 240, 0, 255); diff --git a/osu.Game.Rulesets.Catch/Objects/CatchHitObject.cs b/osu.Game.Rulesets.Catch/Objects/CatchHitObject.cs index a74055bff9..b9c5e42777 100644 --- a/osu.Game.Rulesets.Catch/Objects/CatchHitObject.cs +++ b/osu.Game.Rulesets.Catch/Objects/CatchHitObject.cs @@ -97,6 +97,12 @@ namespace osu.Game.Rulesets.Catch.Objects set => ScaleBindable.Value = value; } + /// + /// The seed value used for visual randomness such as fruit rotation. + /// By default, truncated to an integer is used. + /// + public Bindable RandomSeed = new Bindable(); + protected override void ApplyDefaultsToSelf(ControlPointInfo controlPointInfo, BeatmapDifficulty difficulty) { base.ApplyDefaultsToSelf(controlPointInfo, difficulty); @@ -111,6 +117,10 @@ namespace osu.Game.Rulesets.Catch.Objects protected CatchHitObject() { XBindable.BindValueChanged(x => originalX = x.NewValue - xOffset); + StartTimeBindable.BindValueChanged(change => + { + RandomSeed.Value = (int)change.NewValue; + }, true); } } } diff --git a/osu.Game.Rulesets.Catch/Objects/Drawables/DrawableCatchHitObject.cs b/osu.Game.Rulesets.Catch/Objects/Drawables/DrawableCatchHitObject.cs index eb5f9451b1..510431ff69 100644 --- a/osu.Game.Rulesets.Catch/Objects/Drawables/DrawableCatchHitObject.cs +++ b/osu.Game.Rulesets.Catch/Objects/Drawables/DrawableCatchHitObject.cs @@ -3,11 +3,9 @@ using System; using JetBrains.Annotations; -using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Game.Rulesets.Catch.UI; -using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Utils; @@ -23,10 +21,6 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawables protected override float SamplePlaybackPosition => HitObject.X / CatchPlayfield.WIDTH; - /// - /// The seed value used for visual randomness such as fruit rotation. - /// By default, truncated to an integer is used. - /// public Bindable RandomSeed = new Bindable(); protected DrawableCatchHitObject([CanBeNull] CatchHitObject hitObject) @@ -35,15 +29,6 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawables Anchor = Anchor.BottomLeft; } - [BackgroundDependencyLoader] - private void load() - { - StartTimeBindable.BindValueChanged(change => - { - RandomSeed.Value = (int)change.NewValue; - }, true); - } - /// /// Get a random number in range [0,1) based on seed . /// @@ -54,6 +39,7 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawables base.OnApply(); XBindable.BindTo(HitObject.XBindable); + RandomSeed.BindTo(HitObject.RandomSeed); } protected override void OnFree() @@ -61,6 +47,7 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawables base.OnFree(); XBindable.UnbindFrom(HitObject.XBindable); + RandomSeed.UnbindFrom(HitObject.RandomSeed); } public Func CheckPosition; From ef741a1471170e62edbd34277a17e9966fcf97cf Mon Sep 17 00:00:00 2001 From: ekrctb Date: Wed, 2 Dec 2020 17:16:36 +0900 Subject: [PATCH 084/184] Test banana colour change based on random seed --- osu.Game.Rulesets.Catch.Tests/TestSceneFruitRandomness.cs | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Catch.Tests/TestSceneFruitRandomness.cs b/osu.Game.Rulesets.Catch.Tests/TestSceneFruitRandomness.cs index 449cfac2db..244e2f14f4 100644 --- a/osu.Game.Rulesets.Catch.Tests/TestSceneFruitRandomness.cs +++ b/osu.Game.Rulesets.Catch.Tests/TestSceneFruitRandomness.cs @@ -6,6 +6,7 @@ using osu.Framework.Bindables; using osu.Game.Rulesets.Catch.Objects; using osu.Game.Rulesets.Catch.Objects.Drawables; using osu.Game.Tests.Visual; +using osuTK.Graphics; namespace osu.Game.Rulesets.Catch.Tests { @@ -31,6 +32,7 @@ namespace osu.Game.Rulesets.Catch.Tests float fruitRotation = 0; float bananaRotation = 0; float bananaScale = 0; + Color4 bananaColour = new Color4(); AddStep("set random seed to 0", () => { @@ -40,16 +42,19 @@ namespace osu.Game.Rulesets.Catch.Tests fruitRotation = drawableFruit.InnerRotation; bananaRotation = drawableBanana.InnerRotation; bananaScale = drawableBanana.InnerScale; + bananaColour = drawableBanana.AccentColour.Value; }); AddStep("change random seed", () => { + // Use a seed value such that the banana colour is different (2/3 of the seed values are okay). randomSeed.Value = 10; }); AddAssert("fruit rotation is changed", () => drawableFruit.InnerRotation != fruitRotation); AddAssert("banana rotation is changed", () => drawableBanana.InnerRotation != bananaRotation); AddAssert("banana scale is changed", () => drawableBanana.InnerScale != bananaScale); + AddAssert("banana colour is changed", () => drawableBanana.AccentColour.Value != bananaColour); AddStep("reset random seed", () => { @@ -59,7 +64,8 @@ namespace osu.Game.Rulesets.Catch.Tests AddAssert("rotation and scale restored", () => drawableFruit.InnerRotation == fruitRotation && drawableBanana.InnerRotation == bananaRotation && - drawableBanana.InnerScale == bananaScale); + drawableBanana.InnerScale == bananaScale && + drawableBanana.AccentColour.Value == bananaColour); AddStep("change start time", () => { From 1a6b8e022cba52b12289b2b541effaad186a360e Mon Sep 17 00:00:00 2001 From: ekrctb Date: Wed, 2 Dec 2020 17:20:52 +0900 Subject: [PATCH 085/184] Fix formatting --- .../TestSceneFruitRandomness.cs | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/osu.Game.Rulesets.Catch.Tests/TestSceneFruitRandomness.cs b/osu.Game.Rulesets.Catch.Tests/TestSceneFruitRandomness.cs index 244e2f14f4..38efcd85b8 100644 --- a/osu.Game.Rulesets.Catch.Tests/TestSceneFruitRandomness.cs +++ b/osu.Game.Rulesets.Catch.Tests/TestSceneFruitRandomness.cs @@ -17,17 +17,14 @@ namespace osu.Game.Rulesets.Catch.Tests { Bindable randomSeed = new Bindable(); - TestDrawableFruit drawableFruit; - TestDrawableBanana drawableBanana; + var drawableFruit = new TestDrawableFruit(new Fruit()); + var drawableBanana = new TestDrawableBanana(new Banana()); - Add(new TestDrawableCatchHitObjectSpecimen(drawableFruit = new TestDrawableFruit(new Fruit()) - { - RandomSeed = { BindTarget = randomSeed } - }) { X = -200 }); - Add(new TestDrawableCatchHitObjectSpecimen(drawableBanana = new TestDrawableBanana(new Banana()) - { - RandomSeed = { BindTarget = randomSeed } - })); + drawableFruit.RandomSeed.BindTo(randomSeed); + drawableBanana.RandomSeed.BindTo(randomSeed); + + Add(new TestDrawableCatchHitObjectSpecimen(drawableFruit) { X = -200 }); + Add(new TestDrawableCatchHitObjectSpecimen(drawableBanana)); float fruitRotation = 0; float bananaRotation = 0; From 5936a8ffb4a1ea87720b7436bfdddb31ce47d49d Mon Sep 17 00:00:00 2001 From: ekrctb Date: Wed, 2 Dec 2020 18:06:14 +0900 Subject: [PATCH 086/184] Fix drawables are added multiple times in a test scene --- .../TestSceneFruitRandomness.cs | 21 ++++++++++++------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/osu.Game.Rulesets.Catch.Tests/TestSceneFruitRandomness.cs b/osu.Game.Rulesets.Catch.Tests/TestSceneFruitRandomness.cs index 38efcd85b8..5f7447323f 100644 --- a/osu.Game.Rulesets.Catch.Tests/TestSceneFruitRandomness.cs +++ b/osu.Game.Rulesets.Catch.Tests/TestSceneFruitRandomness.cs @@ -12,13 +12,14 @@ namespace osu.Game.Rulesets.Catch.Tests { public class TestSceneFruitRandomness : OsuTestScene { - [Test] - public void TestFruitRandomness() - { - Bindable randomSeed = new Bindable(); + private readonly Bindable randomSeed = new Bindable(); + private readonly TestDrawableFruit drawableFruit; + private readonly TestDrawableBanana drawableBanana; - var drawableFruit = new TestDrawableFruit(new Fruit()); - var drawableBanana = new TestDrawableBanana(new Banana()); + public TestSceneFruitRandomness() + { + drawableFruit = new TestDrawableFruit(new Fruit()); + drawableBanana = new TestDrawableBanana(new Banana()); drawableFruit.RandomSeed.BindTo(randomSeed); drawableBanana.RandomSeed.BindTo(randomSeed); @@ -26,6 +27,12 @@ namespace osu.Game.Rulesets.Catch.Tests Add(new TestDrawableCatchHitObjectSpecimen(drawableFruit) { X = -200 }); Add(new TestDrawableCatchHitObjectSpecimen(drawableBanana)); + AddSliderStep("random seed", 0, 100, 0, x => randomSeed.Value = x); + } + + [Test] + public void TestFruitRandomness() + { float fruitRotation = 0; float bananaRotation = 0; float bananaScale = 0; @@ -70,8 +77,6 @@ namespace osu.Game.Rulesets.Catch.Tests }); AddAssert("random seed is changed", () => randomSeed.Value == 1000); - - AddSliderStep("random seed", 0, 100, 0, x => randomSeed.Value = x); } private class TestDrawableFruit : DrawableFruit From d5dccbc3d783c5cc5cb7389fcc970a175ea133e6 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 2 Dec 2020 19:02:49 +0900 Subject: [PATCH 087/184] Fix spectator not being thread-safe --- .../Spectator/SpectatorStreamingClient.cs | 33 ++++++++++++++----- 1 file changed, 25 insertions(+), 8 deletions(-) diff --git a/osu.Game/Online/Spectator/SpectatorStreamingClient.cs b/osu.Game/Online/Spectator/SpectatorStreamingClient.cs index 9ba81720d8..08b524087a 100644 --- a/osu.Game/Online/Spectator/SpectatorStreamingClient.cs +++ b/osu.Game/Online/Spectator/SpectatorStreamingClient.cs @@ -36,6 +36,8 @@ namespace osu.Game.Online.Spectator private readonly List watchingUsers = new List(); + private readonly object userLock = new object(); + public IBindableList PlayingUsers => playingUsers; private readonly BindableList playingUsers = new BindableList(); @@ -144,12 +146,19 @@ namespace osu.Game.Online.Spectator await connection.StartAsync(); Logger.Log("Spectator client connected!", LoggingTarget.Network); + // get all the users that were previously being watched + int[] users; + + lock (userLock) + { + users = watchingUsers.ToArray(); + watchingUsers.Clear(); + } + // success isConnected = true; // resubscribe to watched users - var users = watchingUsers.ToArray(); - watchingUsers.Clear(); foreach (var userId in users) WatchUser(userId); @@ -238,21 +247,29 @@ namespace osu.Game.Online.Spectator public virtual void WatchUser(int userId) { - if (watchingUsers.Contains(userId)) - return; + lock (userLock) + { + if (watchingUsers.Contains(userId)) + return; - watchingUsers.Add(userId); + watchingUsers.Add(userId); - if (!isConnected) return; + if (!isConnected) + return; + } connection.SendAsync(nameof(ISpectatorServer.StartWatchingUser), userId); } public void StopWatchingUser(int userId) { - watchingUsers.Remove(userId); + lock (userLock) + { + watchingUsers.Remove(userId); - if (!isConnected) return; + if (!isConnected) + return; + } connection.SendAsync(nameof(ISpectatorServer.EndWatchingUser), userId); } From fdcfa81e4627c129f7bbcfe32280b09556c96914 Mon Sep 17 00:00:00 2001 From: ekrctb Date: Wed, 2 Dec 2020 20:53:47 +0900 Subject: [PATCH 088/184] Make RandomSeed a property, not a bindable --- .../TestSceneFruitRandomness.cs | 35 ++++++++----------- osu.Game.Rulesets.Catch/Objects/Banana.cs | 2 +- .../Objects/CatchHitObject.cs | 8 ++--- .../Objects/Drawables/DrawableBanana.cs | 7 ++-- .../Drawables/DrawableCatchHitObject.cs | 6 ++-- .../Objects/Drawables/DrawableFruit.cs | 10 +++--- 6 files changed, 27 insertions(+), 41 deletions(-) diff --git a/osu.Game.Rulesets.Catch.Tests/TestSceneFruitRandomness.cs b/osu.Game.Rulesets.Catch.Tests/TestSceneFruitRandomness.cs index 5f7447323f..2ffebb7de1 100644 --- a/osu.Game.Rulesets.Catch.Tests/TestSceneFruitRandomness.cs +++ b/osu.Game.Rulesets.Catch.Tests/TestSceneFruitRandomness.cs @@ -2,7 +2,6 @@ // See the LICENCE file in the repository root for full licence text. using NUnit.Framework; -using osu.Framework.Bindables; using osu.Game.Rulesets.Catch.Objects; using osu.Game.Rulesets.Catch.Objects.Drawables; using osu.Game.Tests.Visual; @@ -12,7 +11,6 @@ namespace osu.Game.Rulesets.Catch.Tests { public class TestSceneFruitRandomness : OsuTestScene { - private readonly Bindable randomSeed = new Bindable(); private readonly TestDrawableFruit drawableFruit; private readonly TestDrawableBanana drawableBanana; @@ -21,27 +19,30 @@ namespace osu.Game.Rulesets.Catch.Tests drawableFruit = new TestDrawableFruit(new Fruit()); drawableBanana = new TestDrawableBanana(new Banana()); - drawableFruit.RandomSeed.BindTo(randomSeed); - drawableBanana.RandomSeed.BindTo(randomSeed); - Add(new TestDrawableCatchHitObjectSpecimen(drawableFruit) { X = -200 }); Add(new TestDrawableCatchHitObjectSpecimen(drawableBanana)); - AddSliderStep("random seed", 0, 100, 0, x => randomSeed.Value = x); + AddSliderStep("start time", 500, 600, 0, x => + { + drawableFruit.HitObject.StartTime = drawableBanana.HitObject.StartTime = x; + }); } [Test] public void TestFruitRandomness() { + // Use values such that the banana colour changes (2/3 of the integers are okay) + const int initial_start_time = 500; + const int another_start_time = 501; + float fruitRotation = 0; float bananaRotation = 0; float bananaScale = 0; Color4 bananaColour = new Color4(); - AddStep("set random seed to 0", () => + AddStep("Initialize start time", () => { - drawableFruit.HitObject.StartTime = 500; - randomSeed.Value = 0; + drawableFruit.HitObject.StartTime = drawableBanana.HitObject.StartTime = initial_start_time; fruitRotation = drawableFruit.InnerRotation; bananaRotation = drawableBanana.InnerRotation; @@ -49,10 +50,9 @@ namespace osu.Game.Rulesets.Catch.Tests bananaColour = drawableBanana.AccentColour.Value; }); - AddStep("change random seed", () => + AddStep("change start time", () => { - // Use a seed value such that the banana colour is different (2/3 of the seed values are okay). - randomSeed.Value = 10; + drawableFruit.HitObject.StartTime = drawableBanana.HitObject.StartTime = another_start_time; }); AddAssert("fruit rotation is changed", () => drawableFruit.InnerRotation != fruitRotation); @@ -60,9 +60,9 @@ namespace osu.Game.Rulesets.Catch.Tests AddAssert("banana scale is changed", () => drawableBanana.InnerScale != bananaScale); AddAssert("banana colour is changed", () => drawableBanana.AccentColour.Value != bananaColour); - AddStep("reset random seed", () => + AddStep("reset start time", () => { - randomSeed.Value = 0; + drawableFruit.HitObject.StartTime = drawableBanana.HitObject.StartTime = initial_start_time; }); AddAssert("rotation and scale restored", () => @@ -70,13 +70,6 @@ namespace osu.Game.Rulesets.Catch.Tests drawableBanana.InnerRotation == bananaRotation && drawableBanana.InnerScale == bananaScale && drawableBanana.AccentColour.Value == bananaColour); - - AddStep("change start time", () => - { - drawableFruit.HitObject.StartTime = 1000; - }); - - AddAssert("random seed is changed", () => randomSeed.Value == 1000); } private class TestDrawableFruit : DrawableFruit diff --git a/osu.Game.Rulesets.Catch/Objects/Banana.cs b/osu.Game.Rulesets.Catch/Objects/Banana.cs index 9fd01b3717..3a5e08b3c3 100644 --- a/osu.Game.Rulesets.Catch/Objects/Banana.cs +++ b/osu.Game.Rulesets.Catch/Objects/Banana.cs @@ -33,7 +33,7 @@ namespace osu.Game.Rulesets.Catch.Objects private Color4 getBananaColour() { - switch (StatelessRNG.NextInt(3, RandomSeed.Value)) + switch (StatelessRNG.NextInt(3, RandomSeed)) { default: return new Color4(255, 240, 0, 255); diff --git a/osu.Game.Rulesets.Catch/Objects/CatchHitObject.cs b/osu.Game.Rulesets.Catch/Objects/CatchHitObject.cs index b9c5e42777..b86b3a7496 100644 --- a/osu.Game.Rulesets.Catch/Objects/CatchHitObject.cs +++ b/osu.Game.Rulesets.Catch/Objects/CatchHitObject.cs @@ -99,9 +99,9 @@ namespace osu.Game.Rulesets.Catch.Objects /// /// The seed value used for visual randomness such as fruit rotation. - /// By default, truncated to an integer is used. + /// The value is truncated to an integer. /// - public Bindable RandomSeed = new Bindable(); + public int RandomSeed => (int)StartTime; protected override void ApplyDefaultsToSelf(ControlPointInfo controlPointInfo, BeatmapDifficulty difficulty) { @@ -117,10 +117,6 @@ namespace osu.Game.Rulesets.Catch.Objects protected CatchHitObject() { XBindable.BindValueChanged(x => originalX = x.NewValue - xOffset); - StartTimeBindable.BindValueChanged(change => - { - RandomSeed.Value = (int)change.NewValue; - }, true); } } } diff --git a/osu.Game.Rulesets.Catch/Objects/Drawables/DrawableBanana.cs b/osu.Game.Rulesets.Catch/Objects/Drawables/DrawableBanana.cs index 4e34dd2b90..8e9d80106b 100644 --- a/osu.Game.Rulesets.Catch/Objects/Drawables/DrawableBanana.cs +++ b/osu.Game.Rulesets.Catch/Objects/Drawables/DrawableBanana.cs @@ -24,11 +24,8 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawables { base.LoadComplete(); - RandomSeed.BindValueChanged(_ => - { - UpdateComboColour(); - UpdateInitialTransforms(); - }); + // start time affects the random seed which is used to determine the banana colour + StartTimeBindable.BindValueChanged(_ => UpdateComboColour()); } protected override void UpdateInitialTransforms() diff --git a/osu.Game.Rulesets.Catch/Objects/Drawables/DrawableCatchHitObject.cs b/osu.Game.Rulesets.Catch/Objects/Drawables/DrawableCatchHitObject.cs index 510431ff69..86c1c7d0cd 100644 --- a/osu.Game.Rulesets.Catch/Objects/Drawables/DrawableCatchHitObject.cs +++ b/osu.Game.Rulesets.Catch/Objects/Drawables/DrawableCatchHitObject.cs @@ -21,7 +21,7 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawables protected override float SamplePlaybackPosition => HitObject.X / CatchPlayfield.WIDTH; - public Bindable RandomSeed = new Bindable(); + public int RandomSeed => HitObject?.RandomSeed ?? 0; protected DrawableCatchHitObject([CanBeNull] CatchHitObject hitObject) : base(hitObject) @@ -32,14 +32,13 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawables /// /// Get a random number in range [0,1) based on seed . /// - public float RandomSingle(int series) => StatelessRNG.NextSingle(RandomSeed.Value, series); + public float RandomSingle(int series) => StatelessRNG.NextSingle(RandomSeed, series); protected override void OnApply() { base.OnApply(); XBindable.BindTo(HitObject.XBindable); - RandomSeed.BindTo(HitObject.RandomSeed); } protected override void OnFree() @@ -47,7 +46,6 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawables base.OnFree(); XBindable.UnbindFrom(HitObject.XBindable); - RandomSeed.UnbindFrom(HitObject.RandomSeed); } public Func CheckPosition; diff --git a/osu.Game.Rulesets.Catch/Objects/Drawables/DrawableFruit.cs b/osu.Game.Rulesets.Catch/Objects/Drawables/DrawableFruit.cs index 010a3ee08c..56b9b56372 100644 --- a/osu.Game.Rulesets.Catch/Objects/Drawables/DrawableFruit.cs +++ b/osu.Game.Rulesets.Catch/Objects/Drawables/DrawableFruit.cs @@ -36,11 +36,13 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawables VisualRepresentation.BindValueChanged(_ => updatePiece()); HyperDash.BindValueChanged(_ => updatePiece(), true); + } - RandomSeed.BindValueChanged(_ => - { - ScaleContainer.Rotation = (RandomSingle(1) - 0.5f) * 40; - }, true); + protected override void UpdateInitialTransforms() + { + base.UpdateInitialTransforms(); + + ScaleContainer.Rotation = (RandomSingle(1) - 0.5f) * 40; } private void updatePiece() From bbde1f6b9c755df552ec02c8194866b51f17dbf2 Mon Sep 17 00:00:00 2001 From: Leon Gebler Date: Tue, 1 Dec 2020 22:26:17 +0100 Subject: [PATCH 089/184] Fix MouseHandler not being ignored when raw input is enabled --- .../Settings/Sections/Input/MouseSettings.cs | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/osu.Game/Overlays/Settings/Sections/Input/MouseSettings.cs b/osu.Game/Overlays/Settings/Sections/Input/MouseSettings.cs index f0d51a0d37..b9e9de1200 100644 --- a/osu.Game/Overlays/Settings/Sections/Input/MouseSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Input/MouseSettings.cs @@ -6,6 +6,7 @@ using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Configuration; using osu.Framework.Graphics; +using osu.Framework.Input.Handlers.Mouse; using osu.Game.Configuration; using osu.Game.Graphics.UserInterface; using osu.Game.Input; @@ -18,7 +19,7 @@ namespace osu.Game.Overlays.Settings.Sections.Input private readonly BindableBool rawInputToggle = new BindableBool(); private Bindable sensitivityBindable = new BindableDouble(); - private Bindable ignoredInputHandler; + private Bindable ignoredInputHandlers; [BackgroundDependencyLoader] private void load(OsuConfigManager osuConfig, FrameworkConfigManager config) @@ -75,20 +76,21 @@ namespace osu.Game.Overlays.Settings.Sections.Input { // this is temporary until we support per-handler settings. const string raw_mouse_handler = @"OsuTKRawMouseHandler"; - const string standard_mouse_handler = @"OsuTKMouseHandler"; + const string osutk_standard_mouse_handler = @"OsuTKMouseHandler"; + string standardMouseHandlers = $"{osutk_standard_mouse_handler} {nameof(MouseHandler)}"; - ignoredInputHandler.Value = enabled.NewValue ? standard_mouse_handler : raw_mouse_handler; + ignoredInputHandlers.Value = enabled.NewValue ? standardMouseHandlers : raw_mouse_handler; }; - ignoredInputHandler = config.GetBindable(FrameworkSetting.IgnoredInputHandlers); - ignoredInputHandler.ValueChanged += handler => + ignoredInputHandlers = config.GetBindable(FrameworkSetting.IgnoredInputHandlers); + ignoredInputHandlers.ValueChanged += handler => { bool raw = !handler.NewValue.Contains("Raw"); rawInputToggle.Value = raw; sensitivityBindable.Disabled = !raw; }; - ignoredInputHandler.TriggerChange(); + ignoredInputHandlers.TriggerChange(); } } From a2a10d4e131e3ecbedcec977f86e4ac8a426db79 Mon Sep 17 00:00:00 2001 From: Leon Gebler Date: Wed, 2 Dec 2020 19:45:59 +0100 Subject: [PATCH 090/184] Don't use nameof(MouseHandler) --- osu.Game/Overlays/Settings/Sections/Input/MouseSettings.cs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/osu.Game/Overlays/Settings/Sections/Input/MouseSettings.cs b/osu.Game/Overlays/Settings/Sections/Input/MouseSettings.cs index b9e9de1200..b5d7a1ac0e 100644 --- a/osu.Game/Overlays/Settings/Sections/Input/MouseSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Input/MouseSettings.cs @@ -76,10 +76,9 @@ namespace osu.Game.Overlays.Settings.Sections.Input { // this is temporary until we support per-handler settings. const string raw_mouse_handler = @"OsuTKRawMouseHandler"; - const string osutk_standard_mouse_handler = @"OsuTKMouseHandler"; - string standardMouseHandlers = $"{osutk_standard_mouse_handler} {nameof(MouseHandler)}"; + const string standard_mouse_handlers = @"OsuTKMouseHandler MouseHandler"; - ignoredInputHandlers.Value = enabled.NewValue ? standardMouseHandlers : raw_mouse_handler; + ignoredInputHandlers.Value = enabled.NewValue ? standard_mouse_handlers : raw_mouse_handler; }; ignoredInputHandlers = config.GetBindable(FrameworkSetting.IgnoredInputHandlers); From 7fd385efe60cb117f881be9afa7d4377c2f13aea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Wed, 2 Dec 2020 20:01:56 +0100 Subject: [PATCH 091/184] Remove unused using directive --- osu.Game/Overlays/Settings/Sections/Input/MouseSettings.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/osu.Game/Overlays/Settings/Sections/Input/MouseSettings.cs b/osu.Game/Overlays/Settings/Sections/Input/MouseSettings.cs index b5d7a1ac0e..b54ad9a641 100644 --- a/osu.Game/Overlays/Settings/Sections/Input/MouseSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Input/MouseSettings.cs @@ -6,7 +6,6 @@ using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Configuration; using osu.Framework.Graphics; -using osu.Framework.Input.Handlers.Mouse; using osu.Game.Configuration; using osu.Game.Graphics.UserInterface; using osu.Game.Input; From 2e8195e059d8cd2f17d5477460797c4279eef86c Mon Sep 17 00:00:00 2001 From: ekrctb Date: Thu, 3 Dec 2020 12:13:14 +0900 Subject: [PATCH 092/184] Use transformation to set fruit rotation --- osu.Game.Rulesets.Catch/Objects/Drawables/DrawableFruit.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Catch/Objects/Drawables/DrawableFruit.cs b/osu.Game.Rulesets.Catch/Objects/Drawables/DrawableFruit.cs index 56b9b56372..ef9df02a68 100644 --- a/osu.Game.Rulesets.Catch/Objects/Drawables/DrawableFruit.cs +++ b/osu.Game.Rulesets.Catch/Objects/Drawables/DrawableFruit.cs @@ -5,6 +5,7 @@ using System; using JetBrains.Annotations; using osu.Framework.Allocation; using osu.Framework.Bindables; +using osu.Framework.Graphics; using osu.Game.Rulesets.Catch.Objects.Drawables.Pieces; using osu.Game.Skinning; @@ -42,7 +43,7 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawables { base.UpdateInitialTransforms(); - ScaleContainer.Rotation = (RandomSingle(1) - 0.5f) * 40; + ScaleContainer.RotateTo((RandomSingle(1) - 0.5f) * 40); } private void updatePiece() From 6c46046c2426ef38fc6589f737e180adecea7829 Mon Sep 17 00:00:00 2001 From: ekrctb Date: Thu, 3 Dec 2020 12:32:49 +0900 Subject: [PATCH 093/184] Fix DHO expires while hit sound is playing --- osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs | 2 +- osu.Game/Skinning/PausableSkinnableSound.cs | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs index a922da0aa9..ad96b1caef 100644 --- a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs +++ b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs @@ -453,7 +453,7 @@ namespace osu.Game.Rulesets.Objects.Drawables state.Value = newState; if (LifetimeEnd == double.MaxValue && (state.Value != ArmedState.Idle || HitObject.HitWindows == null)) - Expire(); + LifetimeEnd = Math.Max(LatestTransformEndTime, HitStateUpdateTime + (Samples?.Length ?? 0)); // apply any custom state overrides ApplyCustomUpdateState?.Invoke(this, newState); diff --git a/osu.Game/Skinning/PausableSkinnableSound.cs b/osu.Game/Skinning/PausableSkinnableSound.cs index 4f09aec0b6..7056b2b2ad 100644 --- a/osu.Game/Skinning/PausableSkinnableSound.cs +++ b/osu.Game/Skinning/PausableSkinnableSound.cs @@ -2,6 +2,7 @@ // 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.Threading; @@ -12,6 +13,8 @@ namespace osu.Game.Skinning { public class PausableSkinnableSound : SkinnableSound { + public double Length => SamplesContainer.Children.Count == 0 ? 0 : SamplesContainer.Children.Max(sample => sample.Length); + protected bool RequestedPlaying { get; private set; } public PausableSkinnableSound(ISampleInfo hitSamples) From 897f593b379b10c2765b54ff22618b821c3ad77e Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 3 Dec 2020 13:26:28 +0900 Subject: [PATCH 094/184] Fix beatmap carousel panels getting masked away when out of scroll bounds Regressed in https://github.com/ppy/osu/pull/10973 due to removed masking specification. Closes #11067. --- osu.Game/Screens/Select/BeatmapCarousel.cs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/osu.Game/Screens/Select/BeatmapCarousel.cs b/osu.Game/Screens/Select/BeatmapCarousel.cs index 4ce87927a1..d76f0abb9e 100644 --- a/osu.Game/Screens/Select/BeatmapCarousel.cs +++ b/osu.Game/Screens/Select/BeatmapCarousel.cs @@ -914,6 +914,9 @@ namespace osu.Game.Screens.Select { // size is determined by the carousel itself, due to not all content necessarily being loaded. ScrollContent.AutoSizeAxes = Axes.None; + + // the scroll container may get pushed off-screen by global screen changes, but we still want panels to display outside of the bounds. + Masking = false; } // ReSharper disable once OptionalParameterHierarchyMismatch 2020.3 EAP4 bug. (https://youtrack.jetbrains.com/issue/RSRP-481535?p=RIDER-51910) From e3bbc2b1284ab2b7bdeff55843146ab86b4321b1 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 3 Dec 2020 14:28:37 +0900 Subject: [PATCH 095/184] Rework osu! hidden mod to avoid storing hitobjects --- osu.Game.Rulesets.Osu/Mods/OsuModHidden.cs | 134 +++++++++--------- .../Objects/Drawables/DrawableSliderHead.cs | 17 ++- .../Objects/Drawables/DrawableSliderRepeat.cs | 4 + .../Objects/Drawables/DrawableSliderTail.cs | 12 ++ 4 files changed, 97 insertions(+), 70 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModHidden.cs b/osu.Game.Rulesets.Osu/Mods/OsuModHidden.cs index 7c1dd46c02..78e759f0e0 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModHidden.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModHidden.cs @@ -2,9 +2,10 @@ // See the LICENCE file in the repository root for full licence text. using System; -using System.Collections.Generic; +using System.Diagnostics; using System.Linq; using osu.Framework.Graphics; +using osu.Game.Beatmaps; using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Objects.Drawables; @@ -25,23 +26,19 @@ namespace osu.Game.Rulesets.Osu.Mods protected override bool IsFirstAdjustableObject(HitObject hitObject) => !(hitObject is Spinner); - public override void ApplyToDrawableHitObjects(IEnumerable drawables) + public override void ApplyToBeatmap(IBeatmap beatmap) { - foreach (var d in drawables) - d.HitObjectApplied += applyFadeInAdjustment; + base.ApplyToBeatmap(beatmap); - base.ApplyToDrawableHitObjects(drawables); - } + foreach (var obj in beatmap.HitObjects.OfType()) + applyFadeInAdjustment(obj); - private void applyFadeInAdjustment(DrawableHitObject hitObject) - { - if (!(hitObject is DrawableOsuHitObject d)) - return; - - d.HitObject.TimeFadeIn = d.HitObject.TimePreempt * fade_in_duration_multiplier; - - foreach (var nested in d.NestedHitObjects) - applyFadeInAdjustment(nested); + static void applyFadeInAdjustment(OsuHitObject osuObject) + { + osuObject.TimeFadeIn = osuObject.TimePreempt * fade_in_duration_multiplier; + foreach (var nested in osuObject.NestedHitObjects.OfType()) + applyFadeInAdjustment(nested); + } } protected override void ApplyIncreasedVisibilityState(DrawableHitObject hitObject, ArmedState state) @@ -56,37 +53,27 @@ namespace osu.Game.Rulesets.Osu.Mods applyState(hitObject, false); } - private void applyState(DrawableHitObject drawable, bool increaseVisibility) + private void applyState(DrawableHitObject drawableObject, bool increaseVisibility) { - if (!(drawable is DrawableOsuHitObject d)) + if (!(drawableObject is DrawableOsuHitObject drawableOsuObject)) return; - var h = d.HitObject; + OsuHitObject hitObject = drawableOsuObject.HitObject; - var fadeOutStartTime = h.StartTime - h.TimePreempt + h.TimeFadeIn; - var fadeOutDuration = h.TimePreempt * fade_out_duration_multiplier; + (double startTime, double duration) fadeOut = getFadeOutParameters(drawableOsuObject); - // new duration from completed fade in to end (before fading out) - var longFadeDuration = h.GetEndTime() - fadeOutStartTime; - - switch (drawable) + switch (drawableObject) { - case DrawableSliderTail sliderTail: - // use stored values from head circle to achieve same fade sequence. - var tailFadeOutParameters = getFadeOutParametersFromSliderHead(h); - - using (drawable.BeginAbsoluteSequence(tailFadeOutParameters.startTime, true)) - sliderTail.FadeOut(tailFadeOutParameters.duration); + case DrawableSliderTail _: + using (drawableObject.BeginAbsoluteSequence(fadeOut.startTime, true)) + drawableObject.FadeOut(fadeOut.duration); break; case DrawableSliderRepeat sliderRepeat: - // use stored values from head circle to achieve same fade sequence. - var repeatFadeOutParameters = getFadeOutParametersFromSliderHead(h); - - using (drawable.BeginAbsoluteSequence(repeatFadeOutParameters.startTime, true)) + using (drawableObject.BeginAbsoluteSequence(fadeOut.startTime, true)) // only apply to circle piece – reverse arrow is not affected by hidden. - sliderRepeat.CirclePiece.FadeOut(repeatFadeOutParameters.duration); + sliderRepeat.CirclePiece.FadeOut(fadeOut.duration); break; @@ -101,29 +88,23 @@ namespace osu.Game.Rulesets.Osu.Mods else { // we don't want to see the approach circle - using (circle.BeginAbsoluteSequence(h.StartTime - h.TimePreempt, true)) + using (circle.BeginAbsoluteSequence(hitObject.StartTime - hitObject.TimePreempt, true)) circle.ApproachCircle.Hide(); } - // fade out immediately after fade in. - using (drawable.BeginAbsoluteSequence(fadeOutStartTime, true)) - fadeTarget.FadeOut(fadeOutDuration); + using (drawableObject.BeginAbsoluteSequence(fadeOut.startTime, true)) + fadeTarget.FadeOut(fadeOut.duration); break; case DrawableSlider slider: - associateNestedSliderCirclesWithHead(slider.HitObject); - - using (slider.BeginAbsoluteSequence(fadeOutStartTime, true)) - slider.Body.FadeOut(longFadeDuration, Easing.Out); + using (slider.BeginAbsoluteSequence(fadeOut.startTime, true)) + slider.Body.FadeOut(fadeOut.duration, Easing.Out); break; case DrawableSliderTick sliderTick: - // slider ticks fade out over up to one second - var tickFadeOutDuration = Math.Min(sliderTick.HitObject.TimePreempt - DrawableSliderTick.ANIM_DURATION, 1000); - - using (sliderTick.BeginAbsoluteSequence(sliderTick.HitObject.StartTime - tickFadeOutDuration, true)) - sliderTick.FadeOut(tickFadeOutDuration); + using (sliderTick.BeginAbsoluteSequence(fadeOut.startTime, true)) + sliderTick.FadeOut(fadeOut.duration); break; @@ -131,30 +112,55 @@ namespace osu.Game.Rulesets.Osu.Mods // hide elements we don't care about. // todo: hide background - using (spinner.BeginAbsoluteSequence(fadeOutStartTime + longFadeDuration, true)) - spinner.FadeOut(fadeOutDuration); + using (spinner.BeginAbsoluteSequence(fadeOut.startTime, true)) + spinner.FadeOut(fadeOut.duration); break; } } - private readonly Dictionary correspondingSliderHeadForObject = new Dictionary(); - - private void associateNestedSliderCirclesWithHead(Slider slider) + private (double startTime, double duration) getFadeOutParameters(DrawableOsuHitObject drawableObject) { - var sliderHead = slider.NestedHitObjects.Single(obj => obj is SliderHeadCircle); - - foreach (var nested in slider.NestedHitObjects) + switch (drawableObject) { - if ((nested is SliderRepeat || nested is SliderEndCircle) && !correspondingSliderHeadForObject.ContainsKey(nested)) - correspondingSliderHeadForObject[nested] = (SliderHeadCircle)sliderHead; - } - } + case DrawableSliderTail tail: + // Use the same fade sequence as the slider head. + Debug.Assert(tail.Slider != null); + return getParameters(tail.Slider.HeadCircle); - private (double startTime, double duration) getFadeOutParametersFromSliderHead(OsuHitObject h) - { - var sliderHead = correspondingSliderHeadForObject[h]; - return (sliderHead.StartTime - sliderHead.TimePreempt + sliderHead.TimeFadeIn, sliderHead.TimePreempt * fade_out_duration_multiplier); + case DrawableSliderRepeat repeat: + // Use the same fade sequence as the slider head. + Debug.Assert(repeat.Slider != null); + return getParameters(repeat.Slider.HeadCircle); + + default: + return getParameters(drawableObject.HitObject); + } + + static (double startTime, double duration) getParameters(OsuHitObject hitObject) + { + var fadeOutStartTime = hitObject.StartTime - hitObject.TimePreempt + hitObject.TimeFadeIn; + var fadeOutDuration = hitObject.TimePreempt * fade_out_duration_multiplier; + + // new duration from completed fade in to end (before fading out) + var longFadeDuration = hitObject.GetEndTime() - fadeOutStartTime; + + switch (hitObject) + { + case Slider _: + return (fadeOutStartTime, longFadeDuration); + + case SliderTick _: + var tickFadeOutDuration = Math.Min(hitObject.TimePreempt - DrawableSliderTick.ANIM_DURATION, 1000); + return (hitObject.StartTime - tickFadeOutDuration, tickFadeOutDuration); + + case Spinner _: + return (fadeOutStartTime + longFadeDuration, fadeOutDuration); + + default: + return (fadeOutStartTime, fadeOutDuration); + } + } } } } diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderHead.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderHead.cs index 3a92938d75..e878d61eec 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderHead.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderHead.cs @@ -2,6 +2,8 @@ // See the LICENCE file in the repository root for full licence text. using System; +using System.Diagnostics; +using JetBrains.Annotations; using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Game.Rulesets.Objects.Drawables; @@ -11,14 +13,15 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables { public class DrawableSliderHead : DrawableHitCircle { + [CanBeNull] + public Slider Slider => drawableSlider?.HitObject; + private readonly IBindable pathVersion = new Bindable(); protected override OsuSkinComponents CirclePieceComponent => OsuSkinComponents.SliderHeadHitCircle; private DrawableSlider drawableSlider; - private Slider slider => drawableSlider?.HitObject; - public DrawableSliderHead() { } @@ -58,11 +61,13 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables { base.Update(); - double completionProgress = Math.Clamp((Time.Current - slider.StartTime) / slider.Duration, 0, 1); + Debug.Assert(Slider != null); + + double completionProgress = Math.Clamp((Time.Current - Slider.StartTime) / Slider.Duration, 0, 1); //todo: we probably want to reconsider this before adding scoring, but it looks and feels nice. if (!IsHit) - Position = slider.CurvePositionAt(completionProgress); + Position = Slider.CurvePositionAt(completionProgress); } public Action OnShake; @@ -71,8 +76,8 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables private void updatePosition() { - if (slider != null) - Position = HitObject.Position - slider.Position; + if (Slider != null) + Position = HitObject.Position - Slider.Position; } } } diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderRepeat.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderRepeat.cs index 0735d48ae1..ba503cca6a 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderRepeat.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderRepeat.cs @@ -3,6 +3,7 @@ using System; using System.Collections.Generic; +using JetBrains.Annotations; using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; @@ -18,6 +19,9 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables { public new SliderRepeat HitObject => (SliderRepeat)base.HitObject; + [CanBeNull] + public Slider Slider => drawableSlider?.HitObject; + private double animDuration; public Drawable CirclePiece { get; private set; } diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderTail.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderTail.cs index eff72168ee..3deff55538 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderTail.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderTail.cs @@ -2,6 +2,7 @@ // See the LICENCE file in the repository root for full licence text. using System.Diagnostics; +using JetBrains.Annotations; using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; @@ -15,6 +16,9 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables { public new SliderTailCircle HitObject => (SliderTailCircle)base.HitObject; + [CanBeNull] + public Slider Slider => drawableSlider?.HitObject; + /// /// The judgement text is provided by the . /// @@ -22,6 +26,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables public bool Tracking { get; set; } + private DrawableSlider drawableSlider; private SkinnableDrawable circlePiece; private Container scaleContainer; @@ -59,6 +64,13 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables ScaleBindable.BindValueChanged(scale => scaleContainer.Scale = new Vector2(scale.NewValue)); } + protected override void OnParentReceived(DrawableHitObject parent) + { + base.OnParentReceived(parent); + + drawableSlider = (DrawableSlider)parent; + } + protected override void UpdateInitialTransforms() { base.UpdateInitialTransforms(); From db7e82c5603b8df224a0c933ced3ae255aeac340 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 3 Dec 2020 14:54:02 +0900 Subject: [PATCH 096/184] Add test --- .../Mods/TestSceneOsuModHidden.cs | 24 +++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/osu.Game.Rulesets.Osu.Tests/Mods/TestSceneOsuModHidden.cs b/osu.Game.Rulesets.Osu.Tests/Mods/TestSceneOsuModHidden.cs index 40f1c4a52f..ff308f389f 100644 --- a/osu.Game.Rulesets.Osu.Tests/Mods/TestSceneOsuModHidden.cs +++ b/osu.Game.Rulesets.Osu.Tests/Mods/TestSceneOsuModHidden.cs @@ -92,6 +92,30 @@ namespace osu.Game.Rulesets.Osu.Tests.Mods PassCondition = checkSomeHit }); + [Test] + public void TestWithSliderReuse() => CreateModTest(new ModTestData + { + Mod = new OsuModHidden(), + Autoplay = true, + Beatmap = new Beatmap + { + HitObjects = new List + { + new Slider + { + StartTime = 1000, + Path = new SliderPath(PathType.Linear, new[] { Vector2.Zero, new Vector2(100, 0), }) + }, + new Slider + { + StartTime = 4000, + Path = new SliderPath(PathType.Linear, new[] { Vector2.Zero, new Vector2(100, 0), }) + }, + } + }, + PassCondition = checkSomeHit + }); + private bool checkSomeHit() { return Player.ScoreProcessor.JudgedHits >= 4; From 31f7f7072deb281f1bcf4fc0e3cf6208e8e27d24 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 3 Dec 2020 15:13:20 +0900 Subject: [PATCH 097/184] Fix song select panels not loading if partially offscreen --- .../Select/Carousel/DrawableCarouselBeatmapSet.cs | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/osu.Game/Screens/Select/Carousel/DrawableCarouselBeatmapSet.cs b/osu.Game/Screens/Select/Carousel/DrawableCarouselBeatmapSet.cs index e25c6932cf..b3c5d458d6 100644 --- a/osu.Game/Screens/Select/Carousel/DrawableCarouselBeatmapSet.cs +++ b/osu.Game/Screens/Select/Carousel/DrawableCarouselBeatmapSet.cs @@ -100,8 +100,14 @@ namespace osu.Game.Screens.Select.Carousel background = new DelayedLoadWrapper(() => new SetPanelBackground(manager.GetWorkingBeatmap(beatmapSet.Beatmaps.FirstOrDefault())) { RelativeSizeAxes = Axes.Both, - }, 300), - mainFlow = new DelayedLoadWrapper(() => new SetPanelContent((CarouselBeatmapSet)Item), 100), + }, 300) + { + RelativeSizeAxes = Axes.Both + }, + mainFlow = new DelayedLoadWrapper(() => new SetPanelContent((CarouselBeatmapSet)Item), 100) + { + RelativeSizeAxes = Axes.Both + }, }; background.DelayedLoadComplete += fadeContentIn; From 3550e5b30f93d965265bbf4ab611a588753a23b4 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 3 Dec 2020 16:42:06 +0900 Subject: [PATCH 098/184] Add length display to room screen as well --- .../Online/API/Requests/Responses/APIBeatmap.cs | 1 + .../Online/Multiplayer/PlaylistExtensions.cs | 16 ++++++++++++++++ .../Match/Components/MatchSettingsOverlay.cs | 9 ++------- osu.Game/Screens/Multi/Match/MatchSubScreen.cs | 5 ++++- 4 files changed, 23 insertions(+), 8 deletions(-) create mode 100644 osu.Game/Online/Multiplayer/PlaylistExtensions.cs diff --git a/osu.Game/Online/API/Requests/Responses/APIBeatmap.cs b/osu.Game/Online/API/Requests/Responses/APIBeatmap.cs index ae65ac09b2..7343870dbc 100644 --- a/osu.Game/Online/API/Requests/Responses/APIBeatmap.cs +++ b/osu.Game/Online/API/Requests/Responses/APIBeatmap.cs @@ -75,6 +75,7 @@ namespace osu.Game.Online.API.Requests.Responses StarDifficulty = starDifficulty, OnlineBeatmapID = OnlineBeatmapID, Version = version, + // this is actually an incorrect mapping (Length is calculated as drain length in lazer's import process, see BeatmapManager.calculateLength). Length = TimeSpan.FromSeconds(length).TotalMilliseconds, Status = Status, BeatmapSet = set, diff --git a/osu.Game/Online/Multiplayer/PlaylistExtensions.cs b/osu.Game/Online/Multiplayer/PlaylistExtensions.cs new file mode 100644 index 0000000000..fe3d96e295 --- /dev/null +++ b/osu.Game/Online/Multiplayer/PlaylistExtensions.cs @@ -0,0 +1,16 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System.Linq; +using Humanizer; +using Humanizer.Localisation; +using osu.Framework.Bindables; + +namespace osu.Game.Online.Multiplayer +{ + public static class PlaylistExtensions + { + public static string GetTotalDuration(this BindableList playlist) => + playlist.Select(p => p.Beatmap.Value.Length).Sum().Milliseconds().Humanize(minUnit: TimeUnit.Second, maxUnit: TimeUnit.Hour, precision: 2); + } +} diff --git a/osu.Game/Screens/Multi/Match/Components/MatchSettingsOverlay.cs b/osu.Game/Screens/Multi/Match/Components/MatchSettingsOverlay.cs index 8bf66b084c..668a373d80 100644 --- a/osu.Game/Screens/Multi/Match/Components/MatchSettingsOverlay.cs +++ b/osu.Game/Screens/Multi/Match/Components/MatchSettingsOverlay.cs @@ -3,9 +3,7 @@ using System; using System.Collections.Specialized; -using System.Linq; using Humanizer; -using Humanizer.Localisation; using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Extensions.Color4Extensions; @@ -339,11 +337,8 @@ namespace osu.Game.Screens.Multi.Match.Components ApplyButton.Enabled.Value = hasValidSettings; } - private void onPlaylistChanged(object sender, NotifyCollectionChangedEventArgs e) - { - double totalLength = Playlist.Select(p => p.Beatmap.Value.Length).Sum(); - playlistLength.Text = $"Length: {totalLength.Milliseconds().Humanize(minUnit: TimeUnit.Second, maxUnit: TimeUnit.Hour, precision: 2)}"; - } + private void onPlaylistChanged(object sender, NotifyCollectionChangedEventArgs e) => + playlistLength.Text = $"Length: {Playlist.GetTotalDuration()}"; private bool hasValidSettings => RoomID.Value == null && NameField.Text.Length > 0 && Playlist.Count > 0; diff --git a/osu.Game/Screens/Multi/Match/MatchSubScreen.cs b/osu.Game/Screens/Multi/Match/MatchSubScreen.cs index 2cbe215a39..13a5d89a12 100644 --- a/osu.Game/Screens/Multi/Match/MatchSubScreen.cs +++ b/osu.Game/Screens/Multi/Match/MatchSubScreen.cs @@ -57,6 +57,7 @@ namespace osu.Game.Screens.Multi.Match private IBindable> managerUpdated; private OverlinedHeader participantsHeader; + private OverlinedHeader playlistHeader; public MatchSubScreen(Room room) { @@ -135,7 +136,7 @@ namespace osu.Game.Screens.Multi.Match RelativeSizeAxes = Axes.Both, Content = new[] { - new Drawable[] { new OverlinedHeader("Playlist"), }, + new Drawable[] { playlistHeader = new OverlinedHeader("Playlist"), }, new Drawable[] { new DrawableRoomPlaylistWithResults @@ -243,6 +244,8 @@ namespace osu.Game.Screens.Multi.Match managerUpdated = beatmapManager.ItemUpdated.GetBoundCopy(); managerUpdated.BindValueChanged(beatmapUpdated); + + playlist.BindCollectionChanged((_, __) => playlistHeader.Details.Value = playlist.GetTotalDuration(), true); } public override bool OnExiting(IScreen next) From e5c8e06c4bd44ace592b8a0549d524bc582e41d2 Mon Sep 17 00:00:00 2001 From: ekrctb Date: Wed, 2 Dec 2020 19:28:47 +0900 Subject: [PATCH 099/184] Create children in the constructor --- osu.Game.Rulesets.Catch/UI/Catcher.cs | 33 +++++++++++++-------------- 1 file changed, 16 insertions(+), 17 deletions(-) diff --git a/osu.Game.Rulesets.Catch/UI/Catcher.cs b/osu.Game.Rulesets.Catch/UI/Catcher.cs index 11b6916a4c..d164d2e0ca 100644 --- a/osu.Game.Rulesets.Catch/UI/Catcher.cs +++ b/osu.Game.Rulesets.Catch/UI/Catcher.cs @@ -49,11 +49,7 @@ namespace osu.Game.Rulesets.Catch.UI public Container ExplodingFruitTarget; - private Container caughtFruitContainer { get; } = new Container - { - Anchor = Anchor.TopCentre, - Origin = Anchor.BottomCentre, - }; + private readonly Container caughtFruitContainer; [NotNull] private readonly Container trailsTarget; @@ -92,9 +88,9 @@ namespace osu.Game.Rulesets.Catch.UI /// private readonly float catchWidth; - private CatcherSprite catcherIdle; - private CatcherSprite catcherKiai; - private CatcherSprite catcherFail; + private readonly CatcherSprite catcherIdle; + private readonly CatcherSprite catcherKiai; + private readonly CatcherSprite catcherFail; private CatcherSprite currentCatcher; @@ -108,8 +104,8 @@ namespace osu.Game.Rulesets.Catch.UI private float hyperDashTargetPosition; private Bindable hitLighting; - private DrawablePool hitExplosionPool; - private Container hitExplosionContainer; + private readonly DrawablePool hitExplosionPool; + private readonly Container hitExplosionContainer; public Catcher([NotNull] Container trailsTarget, BeatmapDifficulty difficulty = null) { @@ -122,17 +118,15 @@ namespace osu.Game.Rulesets.Catch.UI Scale = calculateScale(difficulty); catchWidth = CalculateCatchWidth(Scale); - } - - [BackgroundDependencyLoader] - private void load(OsuConfigManager config) - { - hitLighting = config.GetBindable(OsuSetting.HitLighting); InternalChildren = new Drawable[] { hitExplosionPool = new DrawablePool(10), - caughtFruitContainer, + caughtFruitContainer = new Container + { + Anchor = Anchor.TopCentre, + Origin = Anchor.BottomCentre, + }, catcherIdle = new CatcherSprite(CatcherAnimationState.Idle) { Anchor = Anchor.TopCentre, @@ -154,7 +148,12 @@ namespace osu.Game.Rulesets.Catch.UI Origin = Anchor.BottomCentre, }, }; + } + [BackgroundDependencyLoader] + private void load(OsuConfigManager config) + { + hitLighting = config.GetBindable(OsuSetting.HitLighting); trails = new CatcherTrailDisplay(this); updateCatcher(); From af45e8d97b2ff17b05917e6230a3e5353a43e6b4 Mon Sep 17 00:00:00 2001 From: ekrctb Date: Wed, 2 Dec 2020 19:45:34 +0900 Subject: [PATCH 100/184] Don't delay caught fruit loading It is not needed anymore because some code in DCHO is moved from `load` to constructor. --- osu.Game.Rulesets.Catch/UI/CatcherArea.cs | 21 ++------------------- 1 file changed, 2 insertions(+), 19 deletions(-) diff --git a/osu.Game.Rulesets.Catch/UI/CatcherArea.cs b/osu.Game.Rulesets.Catch/UI/CatcherArea.cs index 26077aeba4..467dc4283d 100644 --- a/osu.Game.Rulesets.Catch/UI/CatcherArea.cs +++ b/osu.Game.Rulesets.Catch/UI/CatcherArea.cs @@ -1,7 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -using System; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Game.Beatmaps; @@ -28,8 +27,6 @@ namespace osu.Game.Rulesets.Catch.UI set => MovableCatcher.ExplodingFruitTarget = value; } - private DrawableCatchHitObject lastPlateableFruit; - public CatcherArea(BeatmapDifficulty difficulty = null) { Size = new Vector2(CatchPlayfield.WIDTH, CATCHER_SIZE); @@ -53,19 +50,6 @@ namespace osu.Game.Rulesets.Catch.UI if (!result.Type.IsScorable()) return; - void runAfterLoaded(Action action) - { - if (lastPlateableFruit == null) - return; - - // this is required to make this run after the last caught fruit runs updateState() at least once. - // TODO: find a better alternative - if (lastPlateableFruit.IsLoaded) - action(); - else - lastPlateableFruit.OnLoadComplete += _ => action(); - } - if (result.IsHit && hitObject is DrawablePalpableCatchHitObject fruit) { // create a new (cloned) fruit to stay on the plate. the original is faded out immediately. @@ -84,16 +68,15 @@ namespace osu.Game.Rulesets.Catch.UI caughtFruit.LifetimeEnd = double.MaxValue; MovableCatcher.PlaceOnPlate(caughtFruit); - lastPlateableFruit = caughtFruit; if (!fruit.StaysOnPlate) - runAfterLoaded(() => MovableCatcher.Explode(caughtFruit)); + MovableCatcher.Explode(caughtFruit); } if (hitObject.HitObject.LastInCombo) { if (result.Judgement is CatchJudgement catchJudgement && catchJudgement.ShouldExplodeFor(result)) - runAfterLoaded(() => MovableCatcher.Explode()); + MovableCatcher.Explode(); else MovableCatcher.Drop(); } From a231a4aa6d127c2ebad93b562c45370458837834 Mon Sep 17 00:00:00 2001 From: ekrctb Date: Wed, 2 Dec 2020 19:46:30 +0900 Subject: [PATCH 101/184] Remove unused method --- osu.Game.Rulesets.Catch/UI/CatcherArea.cs | 4 ---- 1 file changed, 4 deletions(-) diff --git a/osu.Game.Rulesets.Catch/UI/CatcherArea.cs b/osu.Game.Rulesets.Catch/UI/CatcherArea.cs index 467dc4283d..a2a4bd5304 100644 --- a/osu.Game.Rulesets.Catch/UI/CatcherArea.cs +++ b/osu.Game.Rulesets.Catch/UI/CatcherArea.cs @@ -87,10 +87,6 @@ namespace osu.Game.Rulesets.Catch.UI public void OnRevertResult(DrawableCatchHitObject fruit, JudgementResult result) => comboDisplay.OnRevertResult(fruit, result); - public void OnReleased(CatchAction action) - { - } - public bool AttemptCatch(CatchHitObject obj) { return MovableCatcher.AttemptCatch(obj); From 8d32cca5d69d7d12ebbbce28b6d9cfc1e8259d04 Mon Sep 17 00:00:00 2001 From: ekrctb Date: Wed, 2 Dec 2020 20:03:13 +0900 Subject: [PATCH 102/184] Use more specific type for caught object --- osu.Game.Rulesets.Catch/UI/Catcher.cs | 12 ++++++------ osu.Game.Rulesets.Catch/UI/CatcherArea.cs | 2 +- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/osu.Game.Rulesets.Catch/UI/Catcher.cs b/osu.Game.Rulesets.Catch/UI/Catcher.cs index d164d2e0ca..da71145004 100644 --- a/osu.Game.Rulesets.Catch/UI/Catcher.cs +++ b/osu.Game.Rulesets.Catch/UI/Catcher.cs @@ -49,7 +49,7 @@ namespace osu.Game.Rulesets.Catch.UI public Container ExplodingFruitTarget; - private readonly Container caughtFruitContainer; + private readonly Container caughtFruitContainer; [NotNull] private readonly Container trailsTarget; @@ -122,7 +122,7 @@ namespace osu.Game.Rulesets.Catch.UI InternalChildren = new Drawable[] { hitExplosionPool = new DrawablePool(10), - caughtFruitContainer = new Container + caughtFruitContainer = new Container { Anchor = Anchor.TopCentre, Origin = Anchor.BottomCentre, @@ -196,7 +196,7 @@ namespace osu.Game.Rulesets.Catch.UI /// Add a caught fruit to the catcher's stack. /// /// The fruit that was caught. - public void PlaceOnPlate(DrawableCatchHitObject fruit) + public void PlaceOnPlate(DrawablePalpableCatchHitObject fruit) { var ourRadius = fruit.DisplayRadius; float theirRadius = 0; @@ -385,7 +385,7 @@ namespace osu.Game.Rulesets.Catch.UI Explode(f); } - public void Drop(DrawableHitObject fruit) + public void Drop(DrawablePalpableCatchHitObject fruit) { removeFromPlateWithTransform(fruit, f => { @@ -394,7 +394,7 @@ namespace osu.Game.Rulesets.Catch.UI }); } - public void Explode(DrawableHitObject fruit) + public void Explode(DrawablePalpableCatchHitObject fruit) { var originalX = fruit.X * Scale.X; @@ -478,7 +478,7 @@ namespace osu.Game.Rulesets.Catch.UI updateCatcher(); } - private void removeFromPlateWithTransform(DrawableHitObject fruit, Action action) + private void removeFromPlateWithTransform(DrawablePalpableCatchHitObject fruit, Action action) { if (ExplodingFruitTarget != null) { diff --git a/osu.Game.Rulesets.Catch/UI/CatcherArea.cs b/osu.Game.Rulesets.Catch/UI/CatcherArea.cs index a2a4bd5304..bb5eaaa438 100644 --- a/osu.Game.Rulesets.Catch/UI/CatcherArea.cs +++ b/osu.Game.Rulesets.Catch/UI/CatcherArea.cs @@ -104,7 +104,7 @@ namespace osu.Game.Rulesets.Catch.UI comboDisplay.X = MovableCatcher.X; } - private DrawableCatchHitObject createCaughtFruit(DrawablePalpableCatchHitObject hitObject) + private DrawablePalpableCatchHitObject createCaughtFruit(DrawablePalpableCatchHitObject hitObject) { switch (hitObject.HitObject) { From 873f2363c1f757e662845c33b015bd096f5de68c Mon Sep 17 00:00:00 2001 From: ekrctb Date: Wed, 2 Dec 2020 20:05:01 +0900 Subject: [PATCH 103/184] Simplify the fruit stacking code It is now more clear that the expression of distance checking is probably unintended (a bug) --- .../Objects/Drawables/DrawableCatchHitObject.cs | 2 -- .../Objects/Drawables/DrawablePalpableCatchHitObject.cs | 2 ++ osu.Game.Rulesets.Catch/UI/Catcher.cs | 3 +-- 3 files changed, 3 insertions(+), 4 deletions(-) diff --git a/osu.Game.Rulesets.Catch/Objects/Drawables/DrawableCatchHitObject.cs b/osu.Game.Rulesets.Catch/Objects/Drawables/DrawableCatchHitObject.cs index 1faa6a5b0f..c3dbfc325f 100644 --- a/osu.Game.Rulesets.Catch/Objects/Drawables/DrawableCatchHitObject.cs +++ b/osu.Game.Rulesets.Catch/Objects/Drawables/DrawableCatchHitObject.cs @@ -16,8 +16,6 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawables protected override double InitialLifetimeOffset => HitObject.TimePreempt; - public float DisplayRadius => DrawSize.X / 2 * Scale.X * HitObject.Scale; - protected override float SamplePlaybackPosition => HitObject.X / CatchPlayfield.WIDTH; protected DrawableCatchHitObject([CanBeNull] CatchHitObject hitObject) diff --git a/osu.Game.Rulesets.Catch/Objects/Drawables/DrawablePalpableCatchHitObject.cs b/osu.Game.Rulesets.Catch/Objects/Drawables/DrawablePalpableCatchHitObject.cs index a3908f94b6..0877b5e248 100644 --- a/osu.Game.Rulesets.Catch/Objects/Drawables/DrawablePalpableCatchHitObject.cs +++ b/osu.Game.Rulesets.Catch/Objects/Drawables/DrawablePalpableCatchHitObject.cs @@ -30,6 +30,8 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawables /// public virtual bool StaysOnPlate => true; + public float DisplayRadius => CatchHitObject.OBJECT_RADIUS * HitObject.Scale * ScaleFactor; + protected readonly Container ScaleContainer; protected DrawablePalpableCatchHitObject([CanBeNull] CatchHitObject h) diff --git a/osu.Game.Rulesets.Catch/UI/Catcher.cs b/osu.Game.Rulesets.Catch/UI/Catcher.cs index da71145004..94383516bd 100644 --- a/osu.Game.Rulesets.Catch/UI/Catcher.cs +++ b/osu.Game.Rulesets.Catch/UI/Catcher.cs @@ -204,8 +204,7 @@ namespace osu.Game.Rulesets.Catch.UI const float allowance = 10; while (caughtFruitContainer.Any(f => - f.LifetimeEnd == double.MaxValue && - Vector2Extensions.Distance(f.Position, fruit.Position) < (ourRadius + (theirRadius = f.DrawSize.X / 2 * f.Scale.X)) / (allowance / 2))) + Vector2Extensions.Distance(f.Position, fruit.Position) < (ourRadius + (theirRadius = CatchHitObject.OBJECT_RADIUS / 2)) / (allowance / 2))) { var diff = (ourRadius + theirRadius) / allowance; fruit.X += (RNG.NextSingle() - 0.5f) * diff * 2; From 2eb2c934ccbd3360c393403dcdbb2cb87c8a0dcb Mon Sep 17 00:00:00 2001 From: ekrctb Date: Wed, 2 Dec 2020 21:23:34 +0900 Subject: [PATCH 104/184] Refactor fruit dropping code - The repeated `Remove` call was quadratic complexity. Now it is linear time. --- .../TestSceneCatcher.cs | 2 +- osu.Game.Rulesets.Catch/UI/CatchPlayfield.cs | 1 - osu.Game.Rulesets.Catch/UI/Catcher.cs | 119 +++++++++--------- osu.Game.Rulesets.Catch/UI/CatcherArea.cs | 7 +- 4 files changed, 65 insertions(+), 64 deletions(-) diff --git a/osu.Game.Rulesets.Catch.Tests/TestSceneCatcher.cs b/osu.Game.Rulesets.Catch.Tests/TestSceneCatcher.cs index 6eeda2c731..cb4aaefa46 100644 --- a/osu.Game.Rulesets.Catch.Tests/TestSceneCatcher.cs +++ b/osu.Game.Rulesets.Catch.Tests/TestSceneCatcher.cs @@ -15,7 +15,7 @@ namespace osu.Game.Rulesets.Catch.Tests [BackgroundDependencyLoader] private void load() { - SetContents(() => new Catcher(new Container()) + SetContents(() => new Catcher(new Container(), new Container()) { RelativePositionAxes = Axes.None, Anchor = Anchor.Centre, diff --git a/osu.Game.Rulesets.Catch/UI/CatchPlayfield.cs b/osu.Game.Rulesets.Catch/UI/CatchPlayfield.cs index 820f08d439..6934dcc1f9 100644 --- a/osu.Game.Rulesets.Catch/UI/CatchPlayfield.cs +++ b/osu.Game.Rulesets.Catch/UI/CatchPlayfield.cs @@ -43,7 +43,6 @@ namespace osu.Game.Rulesets.Catch.UI CatcherArea = new CatcherArea(difficulty) { - ExplodingFruitTarget = explodingFruitContainer, Anchor = Anchor.BottomLeft, Origin = Anchor.TopLeft, }; diff --git a/osu.Game.Rulesets.Catch/UI/Catcher.cs b/osu.Game.Rulesets.Catch/UI/Catcher.cs index 94383516bd..f8ed51bd6f 100644 --- a/osu.Game.Rulesets.Catch/UI/Catcher.cs +++ b/osu.Game.Rulesets.Catch/UI/Catcher.cs @@ -17,7 +17,6 @@ using osu.Game.Configuration; using osu.Game.Rulesets.Catch.Objects; using osu.Game.Rulesets.Catch.Objects.Drawables; using osu.Game.Rulesets.Catch.Skinning; -using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Skinning; using osuTK; using osuTK.Graphics; @@ -47,15 +46,15 @@ namespace osu.Game.Rulesets.Catch.UI /// public const double BASE_SPEED = 1.0; - public Container ExplodingFruitTarget; - - private readonly Container caughtFruitContainer; - [NotNull] private readonly Container trailsTarget; private CatcherTrailDisplay trails; + private readonly Container droppedObjectTarget; + + private readonly Container caughtFruitContainer; + public CatcherAnimationState CurrentState { get; private set; } /// @@ -107,9 +106,10 @@ namespace osu.Game.Rulesets.Catch.UI private readonly DrawablePool hitExplosionPool; private readonly Container hitExplosionContainer; - public Catcher([NotNull] Container trailsTarget, BeatmapDifficulty difficulty = null) + public Catcher([NotNull] Container trailsTarget, [NotNull] Container droppedObjectTarget, BeatmapDifficulty difficulty = null) { this.trailsTarget = trailsTarget; + this.droppedObjectTarget = droppedObjectTarget; Origin = Anchor.TopCentre; @@ -369,41 +369,14 @@ namespace osu.Game.Rulesets.Catch.UI /// /// Drop any fruit off the plate. /// - public void Drop() - { - foreach (var f in caughtFruitContainer.ToArray()) - Drop(f); - } + public void Drop() => clearPlate(DroppedObjectAnimation.Drop); /// /// Explode any fruit off the plate. /// - public void Explode() - { - foreach (var f in caughtFruitContainer.ToArray()) - Explode(f); - } + public void Explode() => clearPlate(DroppedObjectAnimation.Explode); - public void Drop(DrawablePalpableCatchHitObject fruit) - { - removeFromPlateWithTransform(fruit, f => - { - f.MoveToY(f.Y + 75, 750, Easing.InSine); - f.FadeOut(750); - }); - } - - public void Explode(DrawablePalpableCatchHitObject fruit) - { - var originalX = fruit.X * Scale.X; - - removeFromPlateWithTransform(fruit, f => - { - f.MoveToY(f.Y - 50, 250, Easing.OutSine).Then().MoveToY(f.Y + 50, 500, Easing.InSine); - f.MoveToX(f.X + originalX * 6, 1000); - f.FadeOut(750); - }); - } + public void Explode(DrawablePalpableCatchHitObject caughtObject) => removeFromPlate(caughtObject, DroppedObjectAnimation.Explode); protected override void SkinChanged(ISkinSource skin, bool allowFallback) { @@ -477,33 +450,67 @@ namespace osu.Game.Rulesets.Catch.UI updateCatcher(); } - private void removeFromPlateWithTransform(DrawablePalpableCatchHitObject fruit, Action action) + private void clearPlate(DroppedObjectAnimation animation) { - if (ExplodingFruitTarget != null) + var caughtObjects = caughtFruitContainer.Children.ToArray(); + caughtFruitContainer.Clear(false); + + droppedObjectTarget.AddRange(caughtObjects); + + foreach (var caughtObject in caughtObjects) + drop(caughtObject, animation); + } + + private void removeFromPlate(DrawablePalpableCatchHitObject caughtObject, DroppedObjectAnimation animation) + { + if (!caughtFruitContainer.Remove(caughtObject)) + throw new InvalidOperationException("Can only drop a caught object on the plate"); + + droppedObjectTarget.Add(caughtObject); + + drop(caughtObject, animation); + } + + private void drop(Drawable d, DroppedObjectAnimation animation) + { + var originalX = d.X * Scale.X; + + d.Anchor = Anchor.TopLeft; + d.Position = caughtFruitContainer.ToSpaceOfOtherDrawable(d.DrawPosition, droppedObjectTarget); + + animate(d, animation, originalX); + } + + private void animate(Drawable d, DroppedObjectAnimation animation, float originalX) + { + // temporary hack to make sure transforms are not cleared by DHO state update + if (!d.IsLoaded) { - fruit.Anchor = Anchor.TopLeft; - fruit.Position = caughtFruitContainer.ToSpaceOfOtherDrawable(fruit.DrawPosition, ExplodingFruitTarget); - - if (!caughtFruitContainer.Remove(fruit)) - // we may have already been removed by a previous operation (due to the weird OnLoadComplete scheduling). - // this avoids a crash on potentially attempting to Add a fruit to ExplodingFruitTarget twice. - return; - - ExplodingFruitTarget.Add(fruit); + d.OnLoadComplete += _ => animate(d, animation, originalX); + return; } - var actionTime = Clock.CurrentTime; - - fruit.ApplyCustomUpdateState += onFruitOnApplyCustomUpdateState; - onFruitOnApplyCustomUpdateState(fruit, fruit.State.Value); - - void onFruitOnApplyCustomUpdateState(DrawableHitObject o, ArmedState state) + switch (animation) { - using (fruit.BeginAbsoluteSequence(actionTime)) - action(fruit); + case DroppedObjectAnimation.Drop: + d.MoveToY(d.Y + 75, 750, Easing.InSine); + d.FadeOut(750); + break; - fruit.Expire(); + case DroppedObjectAnimation.Explode: + d.MoveToY(d.Y - 50, 250, Easing.OutSine).Then().MoveToY(d.Y + 50, 500, Easing.InSine); + d.MoveToX(d.X + originalX * 6, 1000); + d.FadeOut(750); + break; } + + d.Expire(); } } + + public enum DroppedObjectAnimation + { + Drop, + Explode + } } diff --git a/osu.Game.Rulesets.Catch/UI/CatcherArea.cs b/osu.Game.Rulesets.Catch/UI/CatcherArea.cs index bb5eaaa438..077137a3cb 100644 --- a/osu.Game.Rulesets.Catch/UI/CatcherArea.cs +++ b/osu.Game.Rulesets.Catch/UI/CatcherArea.cs @@ -22,11 +22,6 @@ namespace osu.Game.Rulesets.Catch.UI public readonly Catcher MovableCatcher; private readonly CatchComboDisplay comboDisplay; - public Container ExplodingFruitTarget - { - set => MovableCatcher.ExplodingFruitTarget = value; - } - public CatcherArea(BeatmapDifficulty difficulty = null) { Size = new Vector2(CatchPlayfield.WIDTH, CATCHER_SIZE); @@ -41,7 +36,7 @@ namespace osu.Game.Rulesets.Catch.UI Margin = new MarginPadding { Bottom = 350f }, X = CatchPlayfield.CENTER_X }, - MovableCatcher = new Catcher(this, difficulty) { X = CatchPlayfield.CENTER_X }, + MovableCatcher = new Catcher(this, this, difficulty) { X = CatchPlayfield.CENTER_X }, }; } From 5a5c956cedfda99b3280c9d7bb7933f267fea821 Mon Sep 17 00:00:00 2001 From: ekrctb Date: Thu, 3 Dec 2020 14:44:35 +0900 Subject: [PATCH 105/184] Move more logic to Catcher from CatcherArea --- osu.Game.Rulesets.Catch/UI/Catcher.cs | 74 ++++++++++++++++++----- osu.Game.Rulesets.Catch/UI/CatcherArea.cs | 44 -------------- 2 files changed, 60 insertions(+), 58 deletions(-) diff --git a/osu.Game.Rulesets.Catch/UI/Catcher.cs b/osu.Game.Rulesets.Catch/UI/Catcher.cs index f8ed51bd6f..6d5d25243d 100644 --- a/osu.Game.Rulesets.Catch/UI/Catcher.cs +++ b/osu.Game.Rulesets.Catch/UI/Catcher.cs @@ -245,25 +245,29 @@ namespace osu.Game.Rulesets.Catch.UI catchObjectPosition >= catcherPosition - halfCatchWidth && catchObjectPosition <= catcherPosition + halfCatchWidth; - // only update hyperdash state if we are not catching a tiny droplet. - if (fruit is TinyDroplet) return validCatch; - - if (validCatch && fruit.HyperDash) + // droplet doesn't affect the catcher state + if (!(fruit is TinyDroplet)) { - var target = fruit.HyperDashTarget; - var timeDifference = target.StartTime - fruit.StartTime; - double positionDifference = target.X - catcherPosition; - var velocity = positionDifference / Math.Max(1.0, timeDifference - 1000.0 / 60.0); + if (validCatch && fruit.HyperDash) + { + var target = fruit.HyperDashTarget; + var timeDifference = target.StartTime - fruit.StartTime; + double positionDifference = target.X - catcherPosition; + var velocity = positionDifference / Math.Max(1.0, timeDifference - 1000.0 / 60.0); - SetHyperDashState(Math.Abs(velocity), target.X); + SetHyperDashState(Math.Abs(velocity), target.X); + } + else + SetHyperDashState(); + + if (validCatch) + updateState(fruit.Kiai ? CatcherAnimationState.Kiai : CatcherAnimationState.Idle); + else if (!(fruit is Banana)) + updateState(CatcherAnimationState.Fail); } - else - SetHyperDashState(); if (validCatch) - updateState(fruit.Kiai ? CatcherAnimationState.Kiai : CatcherAnimationState.Idle); - else if (!(fruit is Banana)) - updateState(CatcherAnimationState.Fail); + placeCaughtObject(fruit); return validCatch; } @@ -450,6 +454,48 @@ namespace osu.Game.Rulesets.Catch.UI updateCatcher(); } + private void placeCaughtObject(PalpableCatchHitObject source) + { + var caughtObject = createCaughtObject(source); + if (caughtObject == null) return; + + caughtObject.RelativePositionAxes = Axes.None; + caughtObject.X = source.X - X; + caughtObject.IsOnPlate = true; + + caughtObject.Anchor = Anchor.TopCentre; + caughtObject.Origin = Anchor.Centre; + caughtObject.Scale *= 0.5f; + caughtObject.LifetimeStart = source.StartTime; + caughtObject.LifetimeEnd = double.MaxValue; + + PlaceOnPlate(caughtObject); + + if (!caughtObject.StaysOnPlate) + Explode(caughtObject); + } + + private DrawablePalpableCatchHitObject createCaughtObject(PalpableCatchHitObject source) + { + switch (source) + { + case Banana banana: + return new DrawableBanana(banana); + + case Fruit fruit: + return new DrawableFruit(fruit); + + case TinyDroplet tiny: + return new DrawableTinyDroplet(tiny); + + case Droplet droplet: + return new DrawableDroplet(droplet); + + default: + return null; + } + } + private void clearPlate(DroppedObjectAnimation animation) { var caughtObjects = caughtFruitContainer.Children.ToArray(); diff --git a/osu.Game.Rulesets.Catch/UI/CatcherArea.cs b/osu.Game.Rulesets.Catch/UI/CatcherArea.cs index 077137a3cb..9cd0785b85 100644 --- a/osu.Game.Rulesets.Catch/UI/CatcherArea.cs +++ b/osu.Game.Rulesets.Catch/UI/CatcherArea.cs @@ -45,29 +45,6 @@ namespace osu.Game.Rulesets.Catch.UI if (!result.Type.IsScorable()) return; - if (result.IsHit && hitObject is DrawablePalpableCatchHitObject fruit) - { - // create a new (cloned) fruit to stay on the plate. the original is faded out immediately. - var caughtFruit = createCaughtFruit(fruit); - - if (caughtFruit == null) return; - - caughtFruit.RelativePositionAxes = Axes.None; - caughtFruit.Position = new Vector2(MovableCatcher.ToLocalSpace(hitObject.ScreenSpaceDrawQuad.Centre).X - MovableCatcher.DrawSize.X / 2, 0); - caughtFruit.IsOnPlate = true; - - caughtFruit.Anchor = Anchor.TopCentre; - caughtFruit.Origin = Anchor.Centre; - caughtFruit.Scale *= 0.5f; - caughtFruit.LifetimeStart = caughtFruit.HitObject.StartTime; - caughtFruit.LifetimeEnd = double.MaxValue; - - MovableCatcher.PlaceOnPlate(caughtFruit); - - if (!fruit.StaysOnPlate) - MovableCatcher.Explode(caughtFruit); - } - if (hitObject.HitObject.LastInCombo) { if (result.Judgement is CatchJudgement catchJudgement && catchJudgement.ShouldExplodeFor(result)) @@ -98,26 +75,5 @@ namespace osu.Game.Rulesets.Catch.UI comboDisplay.X = MovableCatcher.X; } - - private DrawablePalpableCatchHitObject createCaughtFruit(DrawablePalpableCatchHitObject hitObject) - { - switch (hitObject.HitObject) - { - case Banana banana: - return new DrawableBanana(banana); - - case Fruit fruit: - return new DrawableFruit(fruit); - - case TinyDroplet tiny: - return new DrawableTinyDroplet(tiny); - - case Droplet droplet: - return new DrawableDroplet(droplet); - - default: - return null; - } - } } } From 1d669cf65ed5c9ee5e398a3cac7e5bc386b5f49a Mon Sep 17 00:00:00 2001 From: ekrctb Date: Thu, 3 Dec 2020 16:40:14 +0900 Subject: [PATCH 106/184] Add more TestSceneCatcher tests Some tests are moved from TestSceneCatcherArea --- .../TestSceneCatcher.cs | 178 +++++++++++++++++- .../TestSceneCatcherArea.cs | 81 +++----- 2 files changed, 195 insertions(+), 64 deletions(-) diff --git a/osu.Game.Rulesets.Catch.Tests/TestSceneCatcher.cs b/osu.Game.Rulesets.Catch.Tests/TestSceneCatcher.cs index cb4aaefa46..f41a16026a 100644 --- a/osu.Game.Rulesets.Catch.Tests/TestSceneCatcher.cs +++ b/osu.Game.Rulesets.Catch.Tests/TestSceneCatcher.cs @@ -1,26 +1,192 @@ // Copyright (c) ppy Pty Ltd . 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 NUnit.Framework; using osu.Framework.Allocation; using osu.Game.Rulesets.Catch.UI; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; +using osu.Framework.Testing; +using osu.Game.Beatmaps; +using osu.Game.Beatmaps.ControlPoints; +using osu.Game.Configuration; +using osu.Game.Rulesets.Catch.Objects; +using osu.Game.Rulesets.Catch.Objects.Drawables; +using osu.Game.Tests.Visual; namespace osu.Game.Rulesets.Catch.Tests { [TestFixture] - public class TestSceneCatcher : CatchSkinnableTestScene + public class TestSceneCatcher : OsuTestScene { - [BackgroundDependencyLoader] - private void load() + [Resolved] + private OsuConfigManager config { get; set; } + + private Container droppedObjectContainer; + + private TestCatcher catcher; + + [SetUp] + public void SetUp() => Schedule(() => { - SetContents(() => new Catcher(new Container(), new Container()) + var difficulty = new BeatmapDifficulty + { + CircleSize = 0, + }; + + var trailContainer = new Container(); + droppedObjectContainer = new Container(); + catcher = new TestCatcher(trailContainer, droppedObjectContainer, difficulty); + + Child = new Container { - RelativePositionAxes = Axes.None, Anchor = Anchor.Centre, - Origin = Anchor.Centre, + Children = new Drawable[] + { + trailContainer, + droppedObjectContainer, + catcher + } + }; + }); + + [Test] + public void TestCatcherCatchWidth() + { + var halfWidth = Catcher.CalculateCatchWidth(new BeatmapDifficulty { CircleSize = 0 }) / 2; + AddStep("catch fruit", () => + { + attemptCatch(new Fruit { X = -halfWidth + 1 }); + attemptCatch(new Fruit { X = halfWidth - 1 }); }); + checkPlate(2); + AddStep("miss fruit", () => + { + attemptCatch(new Fruit { X = -halfWidth - 1 }); + attemptCatch(new Fruit { X = halfWidth + 1 }); + }); + checkPlate(2); + } + + [Test] + public void TestCatcherStateFruit() + { + AddStep("miss fruit", () => attemptCatch(new Fruit { X = 100 })); + checkState(CatcherAnimationState.Fail); + AddStep("catch fruit", () => attemptCatch(new Fruit())); + checkState(CatcherAnimationState.Idle); + AddStep("catch kiai fruit", () => attemptCatch(new TestKiaiFruit())); + checkState(CatcherAnimationState.Kiai); + } + + [Test] + public void TestCatcherStateTinyDroplet() + { + AddStep("catch hyper kiai fruit", () => attemptCatch(new TestKiaiFruit + { + HyperDashTarget = new Fruit { X = 100 } + })); + AddStep("catch tiny droplet", () => attemptCatch(new TinyDroplet())); + AddStep("miss tiny droplet", () => attemptCatch(new TinyDroplet { X = 100 })); + checkState(CatcherAnimationState.Kiai); + checkHyperDash(true); + } + + [Test] + public void TestCatcherStateBanana() + { + AddStep("catch hyper kiai fruit", () => attemptCatch(new TestKiaiFruit + { + HyperDashTarget = new Fruit { X = 100 } + })); + AddStep("miss banana", () => attemptCatch(new Banana())); + checkState(CatcherAnimationState.Idle); + checkHyperDash(false); + } + + [Test] + public void TestCatcherStacking() + { + AddStep("catch fruit", () => attemptCatch(new Fruit())); + checkPlate(1); + AddStep("catch more fruits", () => attemptCatch(new Fruit(), 9)); + checkPlate(10); + AddAssert("caught objects are stacked", () => + catcher.CaughtObjects.All(obj => obj.Y <= 0) && + catcher.CaughtObjects.Any(obj => obj.Y == 0) && + catcher.CaughtObjects.Any(obj => obj.Y < -20)); + } + + [Test] + public void TestCatcherExplosionAndDropping() + { + AddStep("catch fruit", () => attemptCatch(new Fruit())); + AddStep("catch tiny droplet", () => attemptCatch(new TinyDroplet())); + AddAssert("tiny droplet is exploded", () => catcher.CaughtObjects.Count() == 1 && droppedObjectContainer.Count == 1); + AddUntilStep("wait explosion", () => !droppedObjectContainer.Any()); + AddStep("catch more fruits", () => attemptCatch(new Fruit(), 9)); + AddStep("explode", () => catcher.Explode()); + AddAssert("fruits are exploded", () => !catcher.CaughtObjects.Any() && droppedObjectContainer.Count == 10); + AddUntilStep("wait explosion", () => !droppedObjectContainer.Any()); + AddStep("catch fruits", () => attemptCatch(new Fruit(), 10)); + AddStep("drop", () => catcher.Drop()); + AddAssert("fruits are dropped", () => !catcher.CaughtObjects.Any() && droppedObjectContainer.Count == 10); + } + + [Test] + public void TestHyperFruitHyperDash() + { + AddStep("catch hyper fruit", () => attemptCatch(new Fruit + { + HyperDashTarget = new Fruit { X = 100 } + })); + checkHyperDash(true); + AddStep("catch normal fruit", () => attemptCatch(new Fruit())); + checkHyperDash(false); + } + + [TestCase(true)] + [TestCase(false)] + public void TestHitLighting(bool enabled) + { + AddStep($"{(enabled ? "enable" : "disable")} hit lighting", () => config.Set(OsuSetting.HitLighting, enabled)); + AddStep("catch fruit", () => attemptCatch(new Fruit())); + AddAssert("check hit lighting", () => catcher.ChildrenOfType().Any() == enabled); + } + + private void checkPlate(int count) => AddAssert($"{count} objects on the plate", () => catcher.CaughtObjects.Count() == count); + + private void checkState(CatcherAnimationState state) => AddAssert($"catcher state is {state}", () => catcher.CurrentState == state); + + private void checkHyperDash(bool state) => AddAssert($"catcher is {(state ? "" : "not ")}hyper dashing", () => catcher.HyperDashing == state); + + private void attemptCatch(CatchHitObject hitObject, int count = 1) + { + hitObject.ApplyDefaults(new ControlPointInfo(), new BeatmapDifficulty()); + + for (var i = 0; i < count; i++) + catcher.AttemptCatch(hitObject); + } + + public class TestCatcher : Catcher + { + public IEnumerable CaughtObjects => this.ChildrenOfType(); + + public TestCatcher(Container trailsTarget, Container droppedObjectTarget, BeatmapDifficulty difficulty) + : base(trailsTarget, droppedObjectTarget, difficulty) + { + } + } + + public class TestKiaiFruit : Fruit + { + protected override void ApplyDefaultsToSelf(ControlPointInfo controlPointInfo, BeatmapDifficulty difficulty) + { + controlPointInfo.Add(0, new EffectControlPoint { KiaiMode = true }); + base.ApplyDefaultsToSelf(controlPointInfo, difficulty); + } } } } diff --git a/osu.Game.Rulesets.Catch.Tests/TestSceneCatcherArea.cs b/osu.Game.Rulesets.Catch.Tests/TestSceneCatcherArea.cs index c12f38723b..7be6fc92ac 100644 --- a/osu.Game.Rulesets.Catch.Tests/TestSceneCatcherArea.cs +++ b/osu.Game.Rulesets.Catch.Tests/TestSceneCatcherArea.cs @@ -27,73 +27,51 @@ namespace osu.Game.Rulesets.Catch.Tests [Resolved] private OsuConfigManager config { get; set; } - private Catcher catcher => this.ChildrenOfType().First().MovableCatcher; + private Catcher catcher => this.ChildrenOfType().First(); + + private float circleSize; public TestSceneCatcherArea() { - AddSliderStep("CircleSize", 0, 8, 5, createCatcher); - AddToggleStep("Hyperdash", t => - CreatedDrawables.OfType().Select(i => i.Child) - .OfType().ForEach(c => c.ToggleHyperDash(t))); + AddSliderStep("circle size", 0, 8, 5, createCatcher); + AddToggleStep("hyper dash", t => this.ChildrenOfType().ForEach(area => area.ToggleHyperDash(t))); - AddRepeatStep("catch fruit", () => catchFruit(new TestFruit(false) - { - X = catcher.X - }), 20); - AddRepeatStep("catch fruit last in combo", () => catchFruit(new TestFruit(false) - { - X = catcher.X, - LastInCombo = true, - }), 20); - AddRepeatStep("catch kiai fruit", () => catchFruit(new TestFruit(true) - { - X = catcher.X - }), 20); - AddRepeatStep("miss fruit", () => catchFruit(new Fruit - { - X = catcher.X + 100, - LastInCombo = true, - }, true), 20); + AddStep("catch fruit", () => attemptCatch(new Fruit())); + AddStep("catch fruit last in combo", () => attemptCatch(new Fruit { LastInCombo = true })); + AddStep("catch kiai fruit", () => attemptCatch(new TestSceneCatcher.TestKiaiFruit())); + AddStep("miss last in combo", () => attemptCatch(new Fruit { X = 100, LastInCombo = true })); } - [TestCase(true)] - [TestCase(false)] - public void TestHitLighting(bool enable) + private void attemptCatch(Fruit fruit) { - AddStep("create catcher", () => createCatcher(5)); - - AddStep("toggle hit lighting", () => config.Set(OsuSetting.HitLighting, enable)); - AddStep("catch fruit", () => catchFruit(new TestFruit(false) + fruit.X += catcher.X; + fruit.ApplyDefaults(new ControlPointInfo(), new BeatmapDifficulty { - X = catcher.X - })); - AddStep("catch fruit last in combo", () => catchFruit(new TestFruit(false) - { - X = catcher.X, - LastInCombo = true - })); - AddAssert("check hit explosion", () => catcher.ChildrenOfType().Any() == enable); - } + CircleSize = circleSize + }); - private void catchFruit(Fruit fruit, bool miss = false) - { - this.ChildrenOfType().ForEach(area => + foreach (var area in this.ChildrenOfType()) { DrawableFruit drawable = new DrawableFruit(fruit); area.Add(drawable); Schedule(() => { - area.AttemptCatch(fruit); - area.OnNewResult(drawable, new JudgementResult(fruit, new CatchJudgement()) { Type = miss ? HitResult.Miss : HitResult.Great }); + bool caught = area.AttemptCatch(fruit); + area.OnNewResult(drawable, new JudgementResult(fruit, new CatchJudgement()) + { + Type = caught ? HitResult.Great : HitResult.Miss + }); drawable.Expire(); }); - }); + } } private void createCatcher(float size) { + circleSize = size; + SetContents(() => new CatchInputManager(catchRuleset) { RelativeSizeAxes = Axes.Both, @@ -111,17 +89,6 @@ namespace osu.Game.Rulesets.Catch.Tests catchRuleset = rulesets.GetRuleset(2); } - public class TestFruit : Fruit - { - public TestFruit(bool kiai) - { - var kiaiCpi = new ControlPointInfo(); - kiaiCpi.Add(0, new EffectControlPoint { KiaiMode = kiai }); - - ApplyDefaultsToSelf(kiaiCpi, new BeatmapDifficulty()); - } - } - private class TestCatcherArea : CatcherArea { public TestCatcherArea(BeatmapDifficulty beatmapDifficulty) @@ -129,8 +96,6 @@ namespace osu.Game.Rulesets.Catch.Tests { } - public new Catcher MovableCatcher => base.MovableCatcher; - public void ToggleHyperDash(bool status) => MovableCatcher.SetHyperDashState(status ? 2 : 1); } } From c64343c7d719ed8c5c3dc1bfa35934145ab2ffad Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 3 Dec 2020 17:42:41 +0900 Subject: [PATCH 107/184] Update framework --- osu.Android.props | 2 +- osu.Game/osu.Game.csproj | 2 +- osu.iOS.props | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/osu.Android.props b/osu.Android.props index 9d99218f88..9a3d42d6b7 100644 --- a/osu.Android.props +++ b/osu.Android.props @@ -52,6 +52,6 @@ - + diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index 4b931726e0..9d37ceee6c 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 3a47b77820..ab03393836 100644 --- a/osu.iOS.props +++ b/osu.iOS.props @@ -70,7 +70,7 @@ - + @@ -88,7 +88,7 @@ - + From 78c43641d1c6022e1143280843543fec65b678f5 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 3 Dec 2020 17:43:09 +0900 Subject: [PATCH 108/184] Update imagesharp namespaces (and consume System.Drawing types instead) --- osu.Game.Tournament/Models/TournamentMatch.cs | 2 +- osu.Game.Tournament/Screens/Editors/LadderEditorScreen.cs | 2 +- .../Screens/Ladder/Components/DrawableTournamentMatch.cs | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/osu.Game.Tournament/Models/TournamentMatch.cs b/osu.Game.Tournament/Models/TournamentMatch.cs index 8ebcbf4e15..bdfb1728f3 100644 --- a/osu.Game.Tournament/Models/TournamentMatch.cs +++ b/osu.Game.Tournament/Models/TournamentMatch.cs @@ -4,10 +4,10 @@ using System; using System.Collections.Generic; using System.Collections.ObjectModel; +using System.Drawing; using Newtonsoft.Json; using osu.Framework.Bindables; using osu.Game.Tournament.Screens.Ladder.Components; -using SixLabors.Primitives; namespace osu.Game.Tournament.Models { diff --git a/osu.Game.Tournament/Screens/Editors/LadderEditorScreen.cs b/osu.Game.Tournament/Screens/Editors/LadderEditorScreen.cs index efec4cffdd..ca46c3b050 100644 --- a/osu.Game.Tournament/Screens/Editors/LadderEditorScreen.cs +++ b/osu.Game.Tournament/Screens/Editors/LadderEditorScreen.cs @@ -2,6 +2,7 @@ // See the LICENCE file in the repository root for full licence text. using System; +using System.Drawing; using System.Linq; using osu.Framework.Allocation; using osu.Framework.Graphics; @@ -16,7 +17,6 @@ using osu.Game.Tournament.Screens.Ladder; using osu.Game.Tournament.Screens.Ladder.Components; using osuTK; using osuTK.Graphics; -using SixLabors.Primitives; namespace osu.Game.Tournament.Screens.Editors { diff --git a/osu.Game.Tournament/Screens/Ladder/Components/DrawableTournamentMatch.cs b/osu.Game.Tournament/Screens/Ladder/Components/DrawableTournamentMatch.cs index f2065e7e88..1c805bb42e 100644 --- a/osu.Game.Tournament/Screens/Ladder/Components/DrawableTournamentMatch.cs +++ b/osu.Game.Tournament/Screens/Ladder/Components/DrawableTournamentMatch.cs @@ -3,6 +3,7 @@ using System; using System.Collections.Generic; +using System.Drawing; using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; @@ -13,7 +14,6 @@ using osu.Game.Tournament.Models; using osuTK; using osuTK.Graphics; using osuTK.Input; -using SixLabors.Primitives; namespace osu.Game.Tournament.Screens.Ladder.Components { From 3e62da119eca2d34c3e24b1bf61ec68a6eeaddf9 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 3 Dec 2020 17:59:39 +0900 Subject: [PATCH 109/184] Add to inspector also --- .../Components/OverlinedPlaylistHeader.cs | 22 +++++++++++++++++++ .../Multi/Lounge/Components/RoomInspector.cs | 2 +- .../Screens/Multi/Match/MatchSubScreen.cs | 5 +---- 3 files changed, 24 insertions(+), 5 deletions(-) create mode 100644 osu.Game/Screens/Multi/Components/OverlinedPlaylistHeader.cs diff --git a/osu.Game/Screens/Multi/Components/OverlinedPlaylistHeader.cs b/osu.Game/Screens/Multi/Components/OverlinedPlaylistHeader.cs new file mode 100644 index 0000000000..02dbe501b1 --- /dev/null +++ b/osu.Game/Screens/Multi/Components/OverlinedPlaylistHeader.cs @@ -0,0 +1,22 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using osu.Game.Online.Multiplayer; + +namespace osu.Game.Screens.Multi.Components +{ + public class OverlinedPlaylistHeader : OverlinedHeader + { + public OverlinedPlaylistHeader() + : base("Playlist") + { + } + + protected override void LoadComplete() + { + base.LoadComplete(); + + Playlist.BindCollectionChanged((_, __) => Details.Value = Playlist.GetTotalDuration()); + } + } +} diff --git a/osu.Game/Screens/Multi/Lounge/Components/RoomInspector.cs b/osu.Game/Screens/Multi/Lounge/Components/RoomInspector.cs index 77fbd606f4..dfee278e87 100644 --- a/osu.Game/Screens/Multi/Lounge/Components/RoomInspector.cs +++ b/osu.Game/Screens/Multi/Lounge/Components/RoomInspector.cs @@ -67,7 +67,7 @@ namespace osu.Game.Screens.Multi.Lounge.Components } } }, - new Drawable[] { new OverlinedHeader("Playlist"), }, + new Drawable[] { new OverlinedPlaylistHeader(), }, new Drawable[] { new DrawableRoomPlaylist(false, false) diff --git a/osu.Game/Screens/Multi/Match/MatchSubScreen.cs b/osu.Game/Screens/Multi/Match/MatchSubScreen.cs index 13a5d89a12..2f8aad4e65 100644 --- a/osu.Game/Screens/Multi/Match/MatchSubScreen.cs +++ b/osu.Game/Screens/Multi/Match/MatchSubScreen.cs @@ -57,7 +57,6 @@ namespace osu.Game.Screens.Multi.Match private IBindable> managerUpdated; private OverlinedHeader participantsHeader; - private OverlinedHeader playlistHeader; public MatchSubScreen(Room room) { @@ -136,7 +135,7 @@ namespace osu.Game.Screens.Multi.Match RelativeSizeAxes = Axes.Both, Content = new[] { - new Drawable[] { playlistHeader = new OverlinedHeader("Playlist"), }, + new Drawable[] { new OverlinedPlaylistHeader(), }, new Drawable[] { new DrawableRoomPlaylistWithResults @@ -244,8 +243,6 @@ namespace osu.Game.Screens.Multi.Match managerUpdated = beatmapManager.ItemUpdated.GetBoundCopy(); managerUpdated.BindValueChanged(beatmapUpdated); - - playlist.BindCollectionChanged((_, __) => playlistHeader.Details.Value = playlist.GetTotalDuration(), true); } public override bool OnExiting(IScreen next) From 62b1e37f73701a71992d23b4d987f6f5854a7fae Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 3 Dec 2020 18:04:53 +0900 Subject: [PATCH 110/184] Use async overloads --- osu.Game/Graphics/ScreenshotManager.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Graphics/ScreenshotManager.cs b/osu.Game/Graphics/ScreenshotManager.cs index d1f6fd445e..53ee711626 100644 --- a/osu.Game/Graphics/ScreenshotManager.cs +++ b/osu.Game/Graphics/ScreenshotManager.cs @@ -116,13 +116,13 @@ namespace osu.Game.Graphics switch (screenshotFormat.Value) { case ScreenshotFormat.Png: - image.SaveAsPng(stream); + await image.SaveAsPngAsync(stream); break; case ScreenshotFormat.Jpg: const int jpeg_quality = 92; - image.SaveAsJpeg(stream, new JpegEncoder { Quality = jpeg_quality }); + await image.SaveAsJpegAsync(stream, new JpegEncoder { Quality = jpeg_quality }); break; default: From 8245bb85dc93970e584d8b821769fb8eda7b7c5f Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 3 Dec 2020 18:06:55 +0900 Subject: [PATCH 111/184] Invoke on initial bind --- osu.Game/Screens/Multi/Components/OverlinedPlaylistHeader.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Screens/Multi/Components/OverlinedPlaylistHeader.cs b/osu.Game/Screens/Multi/Components/OverlinedPlaylistHeader.cs index 02dbe501b1..5552c1cb72 100644 --- a/osu.Game/Screens/Multi/Components/OverlinedPlaylistHeader.cs +++ b/osu.Game/Screens/Multi/Components/OverlinedPlaylistHeader.cs @@ -16,7 +16,7 @@ namespace osu.Game.Screens.Multi.Components { base.LoadComplete(); - Playlist.BindCollectionChanged((_, __) => Details.Value = Playlist.GetTotalDuration()); + Playlist.BindCollectionChanged((_, __) => Details.Value = Playlist.GetTotalDuration(), true); } } } From be456f9c6be31ea98077263f63d84589009429d0 Mon Sep 17 00:00:00 2001 From: ekrctb Date: Thu, 3 Dec 2020 18:45:38 +0900 Subject: [PATCH 112/184] Make DroppedObjectAnimation private --- osu.Game.Rulesets.Catch/UI/Catcher.cs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/osu.Game.Rulesets.Catch/UI/Catcher.cs b/osu.Game.Rulesets.Catch/UI/Catcher.cs index 6d5d25243d..de2782fa35 100644 --- a/osu.Game.Rulesets.Catch/UI/Catcher.cs +++ b/osu.Game.Rulesets.Catch/UI/Catcher.cs @@ -552,11 +552,11 @@ namespace osu.Game.Rulesets.Catch.UI d.Expire(); } - } - public enum DroppedObjectAnimation - { - Drop, - Explode + private enum DroppedObjectAnimation + { + Drop, + Explode + } } } From 7e66714c2fb50c7dd7527d55e5396fe496809139 Mon Sep 17 00:00:00 2001 From: ekrctb Date: Thu, 3 Dec 2020 18:45:10 +0900 Subject: [PATCH 113/184] Use ApplyCustomUpdateState for dropping transformation We cannot just apply the transforms because DHO clears transforms when state is updated --- osu.Game.Rulesets.Catch/UI/Catcher.cs | 46 +++++++++++++-------------- 1 file changed, 23 insertions(+), 23 deletions(-) diff --git a/osu.Game.Rulesets.Catch/UI/Catcher.cs b/osu.Game.Rulesets.Catch/UI/Catcher.cs index de2782fa35..1101e5b6b4 100644 --- a/osu.Game.Rulesets.Catch/UI/Catcher.cs +++ b/osu.Game.Rulesets.Catch/UI/Catcher.cs @@ -517,40 +517,40 @@ namespace osu.Game.Rulesets.Catch.UI drop(caughtObject, animation); } - private void drop(Drawable d, DroppedObjectAnimation animation) + private void drop(DrawablePalpableCatchHitObject d, DroppedObjectAnimation animation) { var originalX = d.X * Scale.X; + var startTime = Clock.CurrentTime; d.Anchor = Anchor.TopLeft; d.Position = caughtFruitContainer.ToSpaceOfOtherDrawable(d.DrawPosition, droppedObjectTarget); - animate(d, animation, originalX); + // we cannot just apply the transforms because DHO clears transforms when state is updated + d.ApplyCustomUpdateState += (o, state) => animate(o, animation, originalX, startTime); + if (d.IsLoaded) + animate(d, animation, originalX, startTime); } - private void animate(Drawable d, DroppedObjectAnimation animation, float originalX) + private void animate(Drawable d, DroppedObjectAnimation animation, float originalX, double startTime) { - // temporary hack to make sure transforms are not cleared by DHO state update - if (!d.IsLoaded) + using (d.BeginAbsoluteSequence(startTime)) { - d.OnLoadComplete += _ => animate(d, animation, originalX); - return; + switch (animation) + { + case DroppedObjectAnimation.Drop: + d.MoveToY(d.Y + 75, 750, Easing.InSine); + d.FadeOut(750); + break; + + case DroppedObjectAnimation.Explode: + d.MoveToY(d.Y - 50, 250, Easing.OutSine).Then().MoveToY(d.Y + 50, 500, Easing.InSine); + d.MoveToX(d.X + originalX * 6, 1000); + d.FadeOut(750); + break; + } + + d.Expire(); } - - switch (animation) - { - case DroppedObjectAnimation.Drop: - d.MoveToY(d.Y + 75, 750, Easing.InSine); - d.FadeOut(750); - break; - - case DroppedObjectAnimation.Explode: - d.MoveToY(d.Y - 50, 250, Easing.OutSine).Then().MoveToY(d.Y + 50, 500, Easing.InSine); - d.MoveToX(d.X + originalX * 6, 1000); - d.FadeOut(750); - break; - } - - d.Expire(); } private enum DroppedObjectAnimation From 73e99718bc23f52854bbc0eb467dcb63bae10a97 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 3 Dec 2020 19:46:42 +0900 Subject: [PATCH 114/184] Change order of OnParentReceived() --- .../Objects/Drawables/DrawableSliderHead.cs | 5 +++++ .../Objects/Drawables/DrawableSliderRepeat.cs | 5 +++++ .../Objects/Drawables/DrawableSliderTick.cs | 10 +++++++++- .../Objects/Drawables/DrawableSpinnerTick.cs | 1 + .../Objects/Drawables/DrawableHitObject.cs | 16 ++++++++++++---- osu.Game/Rulesets/UI/HitObjectContainer.cs | 2 +- osu.Game/Rulesets/UI/IPooledHitObjectProvider.cs | 3 ++- osu.Game/Rulesets/UI/Playfield.cs | 4 +++- 8 files changed, 38 insertions(+), 8 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderHead.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderHead.cs index 3a92938d75..d1928bd4bb 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderHead.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderHead.cs @@ -47,6 +47,11 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables base.OnParentReceived(parent); drawableSlider = (DrawableSlider)parent; + } + + protected override void OnApply() + { + base.OnApply(); pathVersion.BindTo(drawableSlider.PathVersion); diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderRepeat.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderRepeat.cs index 0735d48ae1..f368615e77 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderRepeat.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderRepeat.cs @@ -65,6 +65,11 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables base.OnParentReceived(parent); drawableSlider = (DrawableSlider)parent; + } + + protected override void OnApply() + { + base.OnApply(); Position = HitObject.Position - drawableSlider.Position; } diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderTick.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderTick.cs index faccf5d4d1..d40b6aea6e 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderTick.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderTick.cs @@ -23,6 +23,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables public override bool DisplayResult => false; private SkinnableDrawable scaleContainer; + private DrawableSlider drawableSlider; public DrawableSliderTick() : base(null) @@ -66,7 +67,14 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables { base.OnParentReceived(parent); - Position = HitObject.Position - ((DrawableSlider)parent).HitObject.Position; + drawableSlider = (DrawableSlider)parent; + } + + protected override void OnApply() + { + base.OnApply(); + + Position = HitObject.Position - drawableSlider.HitObject.Position; } protected override void CheckForResult(bool userTriggered, double timeOffset) diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinnerTick.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinnerTick.cs index f37d933e11..d10c4f7511 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinnerTick.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinnerTick.cs @@ -24,6 +24,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables protected override void OnParentReceived(DrawableHitObject parent) { base.OnParentReceived(parent); + drawableSpinner = (DrawableSpinner)parent; } diff --git a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs index a922da0aa9..37c36ace7b 100644 --- a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs +++ b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs @@ -230,12 +230,12 @@ namespace osu.Game.Rulesets.Objects.Drawables foreach (var h in HitObject.NestedHitObjects) { - var pooledDrawableNested = pooledObjectProvider?.GetPooledDrawableRepresentation(h); + var pooledDrawableNested = pooledObjectProvider?.GetPooledDrawableRepresentation(h, this); var drawableNested = pooledDrawableNested ?? CreateNestedHitObject(h) ?? throw new InvalidOperationException($"{nameof(CreateNestedHitObject)} returned null for {h.GetType().ReadableName()}."); - // Invoke the event only if this nested object is just created by `CreateNestedHitObject`. + // Only invoke the event for non-pooled DHOs, otherwise the event will be fired by the playfield. if (pooledDrawableNested == null) OnNestedDrawableCreated?.Invoke(drawableNested); @@ -243,10 +243,12 @@ namespace osu.Game.Rulesets.Objects.Drawables drawableNested.OnRevertResult += onRevertResult; drawableNested.ApplyCustomUpdateState += onApplyCustomUpdateState; + // ApplyParent() should occur before Apply() in all cases, so it's invoked before the nested DHO is added to the hierarchy below, but after its events are initialised. + if (pooledDrawableNested == null) + drawableNested.ApplyParent(this); + nestedHitObjects.Value.Add(drawableNested); AddNestedHitObject(drawableNested); - - drawableNested.OnParentReceived(this); } StartTimeBindable.BindTo(HitObject.StartTimeBindable); @@ -348,6 +350,12 @@ namespace osu.Game.Rulesets.Objects.Drawables { } + /// + /// Applies a parenting to this . + /// + /// The parenting . + public void ApplyParent(DrawableHitObject parent) => OnParentReceived(parent); + /// /// Invoked when this receives a new parenting . /// diff --git a/osu.Game/Rulesets/UI/HitObjectContainer.cs b/osu.Game/Rulesets/UI/HitObjectContainer.cs index ac5d281ddc..12e39d4fbf 100644 --- a/osu.Game/Rulesets/UI/HitObjectContainer.cs +++ b/osu.Game/Rulesets/UI/HitObjectContainer.cs @@ -105,7 +105,7 @@ namespace osu.Game.Rulesets.UI { Debug.Assert(!drawableMap.ContainsKey(entry)); - var drawable = pooledObjectProvider?.GetPooledDrawableRepresentation(entry.HitObject); + var drawable = pooledObjectProvider?.GetPooledDrawableRepresentation(entry.HitObject, null); if (drawable == null) throw new InvalidOperationException($"A drawable representation could not be retrieved for hitobject type: {entry.HitObject.GetType().ReadableName()}."); diff --git a/osu.Game/Rulesets/UI/IPooledHitObjectProvider.cs b/osu.Game/Rulesets/UI/IPooledHitObjectProvider.cs index 315926dfc6..2d700076d6 100644 --- a/osu.Game/Rulesets/UI/IPooledHitObjectProvider.cs +++ b/osu.Game/Rulesets/UI/IPooledHitObjectProvider.cs @@ -13,8 +13,9 @@ namespace osu.Game.Rulesets.UI /// Attempts to retrieve the poolable representation of a . /// /// The to retrieve the representation of. + /// The parenting , if any. /// The representing , or null if no poolable representation exists. [CanBeNull] - DrawableHitObject GetPooledDrawableRepresentation([NotNull] HitObject hitObject); + DrawableHitObject GetPooledDrawableRepresentation([NotNull] HitObject hitObject, [CanBeNull] DrawableHitObject parent); } } diff --git a/osu.Game/Rulesets/UI/Playfield.cs b/osu.Game/Rulesets/UI/Playfield.cs index a2ac234471..01b25c9717 100644 --- a/osu.Game/Rulesets/UI/Playfield.cs +++ b/osu.Game/Rulesets/UI/Playfield.cs @@ -323,7 +323,7 @@ namespace osu.Game.Rulesets.UI AddInternal(pool); } - DrawableHitObject IPooledHitObjectProvider.GetPooledDrawableRepresentation(HitObject hitObject) + DrawableHitObject IPooledHitObjectProvider.GetPooledDrawableRepresentation(HitObject hitObject, DrawableHitObject parent) { var lookupType = hitObject.GetType(); @@ -359,6 +359,8 @@ namespace osu.Game.Rulesets.UI if (!lifetimeEntryMap.TryGetValue(hitObject, out var entry)) lifetimeEntryMap[hitObject] = entry = CreateLifetimeEntry(hitObject); + if (parent != null) + dho.ApplyParent(parent); dho.Apply(hitObject, entry); }); } From 0bdf99b97a960cd9a5c58e72b4bf3bb0af984ea3 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 3 Dec 2020 20:03:39 +0900 Subject: [PATCH 115/184] Remove OnParentReceived() --- .../Objects/Drawables/DrawableSliderHead.cs | 22 +++++---------- .../Objects/Drawables/DrawableSliderRepeat.cs | 17 ++++-------- .../Objects/Drawables/DrawableSliderTick.cs | 12 +++------ .../Objects/Drawables/DrawableSpinnerTick.cs | 15 +++-------- .../Objects/Drawables/DrawableHitObject.cs | 27 +++++++------------ osu.Game/Rulesets/UI/Playfield.cs | 3 +-- 6 files changed, 29 insertions(+), 67 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderHead.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderHead.cs index d1928bd4bb..f584c9c2d3 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderHead.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderHead.cs @@ -4,20 +4,19 @@ using System; using osu.Framework.Allocation; using osu.Framework.Bindables; -using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.Objects.Types; namespace osu.Game.Rulesets.Osu.Objects.Drawables { public class DrawableSliderHead : DrawableHitCircle { + protected DrawableSlider DrawableSlider => (DrawableSlider)ParentHitObject; + private readonly IBindable pathVersion = new Bindable(); protected override OsuSkinComponents CirclePieceComponent => OsuSkinComponents.SliderHeadHitCircle; - private DrawableSlider drawableSlider; - - private Slider slider => drawableSlider?.HitObject; + private Slider slider => DrawableSlider?.HitObject; public DrawableSliderHead() { @@ -39,24 +38,17 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables { base.OnFree(); - pathVersion.UnbindFrom(drawableSlider.PathVersion); - } - - protected override void OnParentReceived(DrawableHitObject parent) - { - base.OnParentReceived(parent); - - drawableSlider = (DrawableSlider)parent; + pathVersion.UnbindFrom(DrawableSlider.PathVersion); } protected override void OnApply() { base.OnApply(); - pathVersion.BindTo(drawableSlider.PathVersion); + pathVersion.BindTo(DrawableSlider.PathVersion); - OnShake = drawableSlider.Shake; - CheckHittable = (d, t) => drawableSlider.CheckHittable?.Invoke(d, t) ?? true; + OnShake = DrawableSlider.Shake; + CheckHittable = (d, t) => DrawableSlider.CheckHittable?.Invoke(d, t) ?? true; } protected override void Update() diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderRepeat.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderRepeat.cs index f368615e77..2fd9af894d 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderRepeat.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderRepeat.cs @@ -18,6 +18,8 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables { public new SliderRepeat HitObject => (SliderRepeat)base.HitObject; + protected DrawableSlider DrawableSlider => (DrawableSlider)ParentHitObject; + private double animDuration; public Drawable CirclePiece { get; private set; } @@ -26,8 +28,6 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables public override bool DisplayResult => false; - private DrawableSlider drawableSlider; - public DrawableSliderRepeat() : base(null) { @@ -60,24 +60,17 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables ScaleBindable.BindValueChanged(scale => scaleContainer.Scale = new Vector2(scale.NewValue)); } - protected override void OnParentReceived(DrawableHitObject parent) - { - base.OnParentReceived(parent); - - drawableSlider = (DrawableSlider)parent; - } - protected override void OnApply() { base.OnApply(); - Position = HitObject.Position - drawableSlider.Position; + Position = HitObject.Position - DrawableSlider.Position; } protected override void CheckForResult(bool userTriggered, double timeOffset) { if (HitObject.StartTime <= Time.Current) - ApplyResult(r => r.Type = drawableSlider.Tracking.Value ? r.Judgement.MaxResult : r.Judgement.MinResult); + ApplyResult(r => r.Type = DrawableSlider.Tracking.Value ? r.Judgement.MaxResult : r.Judgement.MinResult); } protected override void UpdateInitialTransforms() @@ -119,7 +112,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables if (IsHit) return; bool isRepeatAtEnd = HitObject.RepeatIndex % 2 == 0; - List curve = ((PlaySliderBody)drawableSlider.Body.Drawable).CurrentCurve; + List curve = ((PlaySliderBody)DrawableSlider.Body.Drawable).CurrentCurve; Position = isRepeatAtEnd ? end : start; diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderTick.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderTick.cs index d40b6aea6e..c7bfdb02fb 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderTick.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderTick.cs @@ -22,8 +22,9 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables public override bool DisplayResult => false; + protected DrawableSlider DrawableSlider => (DrawableSlider)ParentHitObject; + private SkinnableDrawable scaleContainer; - private DrawableSlider drawableSlider; public DrawableSliderTick() : base(null) @@ -63,18 +64,11 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables ScaleBindable.BindValueChanged(scale => scaleContainer.Scale = new Vector2(scale.NewValue)); } - protected override void OnParentReceived(DrawableHitObject parent) - { - base.OnParentReceived(parent); - - drawableSlider = (DrawableSlider)parent; - } - protected override void OnApply() { base.OnApply(); - Position = HitObject.Position - drawableSlider.HitObject.Position; + Position = HitObject.Position - DrawableSlider.HitObject.Position; } protected override void CheckForResult(bool userTriggered, double timeOffset) diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinnerTick.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinnerTick.cs index d10c4f7511..726fbd3ea6 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinnerTick.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinnerTick.cs @@ -1,14 +1,14 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -using osu.Game.Rulesets.Objects.Drawables; - namespace osu.Game.Rulesets.Osu.Objects.Drawables { public class DrawableSpinnerTick : DrawableOsuHitObject { public override bool DisplayResult => false; + protected DrawableSpinner DrawableSpinner => (DrawableSpinner)ParentHitObject; + public DrawableSpinnerTick() : base(null) { @@ -19,16 +19,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables { } - private DrawableSpinner drawableSpinner; - - protected override void OnParentReceived(DrawableHitObject parent) - { - base.OnParentReceived(parent); - - drawableSpinner = (DrawableSpinner)parent; - } - - protected override double MaximumJudgementOffset => drawableSpinner.HitObject.Duration; + protected override double MaximumJudgementOffset => DrawableSpinner.HitObject.Duration; /// /// Apply a judgement result. diff --git a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs index 37c36ace7b..94d63e4e68 100644 --- a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs +++ b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs @@ -43,6 +43,12 @@ namespace osu.Game.Rulesets.Objects.Drawables /// public HitObject HitObject { get; private set; } + /// + /// The parenting , if any. + /// + [CanBeNull] + protected internal DrawableHitObject ParentHitObject { get; internal set; } + /// /// The colour used for various elements of this DrawableHitObject. /// @@ -243,9 +249,9 @@ namespace osu.Game.Rulesets.Objects.Drawables drawableNested.OnRevertResult += onRevertResult; drawableNested.ApplyCustomUpdateState += onApplyCustomUpdateState; - // ApplyParent() should occur before Apply() in all cases, so it's invoked before the nested DHO is added to the hierarchy below, but after its events are initialised. - if (pooledDrawableNested == null) - drawableNested.ApplyParent(this); + // This is only necessary for non-pooled DHOs. For pooled DHOs, this is handled inside GetPooledDrawableRepresentation(). + // Must be done before the nested DHO is added to occur before the nested Apply()! + drawableNested.ParentHitObject = this; nestedHitObjects.Value.Add(drawableNested); AddNestedHitObject(drawableNested); @@ -317,6 +323,7 @@ namespace osu.Game.Rulesets.Objects.Drawables OnFree(); HitObject = null; + ParentHitObject = null; Result = null; lifetimeEntry = null; @@ -350,20 +357,6 @@ namespace osu.Game.Rulesets.Objects.Drawables { } - /// - /// Applies a parenting to this . - /// - /// The parenting . - public void ApplyParent(DrawableHitObject parent) => OnParentReceived(parent); - - /// - /// Invoked when this receives a new parenting . - /// - /// The parenting . - protected virtual void OnParentReceived(DrawableHitObject parent) - { - } - /// /// Invoked by the base to populate samples, once on initial load and potentially again on any change to the samples collection. /// diff --git a/osu.Game/Rulesets/UI/Playfield.cs b/osu.Game/Rulesets/UI/Playfield.cs index 01b25c9717..cbf3362ea7 100644 --- a/osu.Game/Rulesets/UI/Playfield.cs +++ b/osu.Game/Rulesets/UI/Playfield.cs @@ -359,8 +359,7 @@ namespace osu.Game.Rulesets.UI if (!lifetimeEntryMap.TryGetValue(hitObject, out var entry)) lifetimeEntryMap[hitObject] = entry = CreateLifetimeEntry(hitObject); - if (parent != null) - dho.ApplyParent(parent); + dho.ParentHitObject = parent; dho.Apply(hitObject, entry); }); } From c25e2c3dd577e7d5dc1ce3765ac0d6bec40aca21 Mon Sep 17 00:00:00 2001 From: Endrik Tombak Date: Thu, 3 Dec 2020 23:13:14 +0200 Subject: [PATCH 116/184] Select recommended beatmap if last selection is filtered --- osu.Game/Screens/Select/Carousel/CarouselBeatmapSet.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Screens/Select/Carousel/CarouselBeatmapSet.cs b/osu.Game/Screens/Select/Carousel/CarouselBeatmapSet.cs index 7935debac7..bf045ed612 100644 --- a/osu.Game/Screens/Select/Carousel/CarouselBeatmapSet.cs +++ b/osu.Game/Screens/Select/Carousel/CarouselBeatmapSet.cs @@ -45,7 +45,7 @@ namespace osu.Game.Screens.Select.Carousel protected override CarouselItem GetNextToSelect() { - if (LastSelected == null) + if (LastSelected == null || LastSelected.Filtered.Value) { if (GetRecommendedBeatmap?.Invoke(Children.OfType().Where(b => !b.Filtered.Value).Select(b => b.Beatmap)) is BeatmapInfo recommended) return Children.OfType().First(b => b.Beatmap == recommended); From 0bc591fef2dc5ee21680b0f361bb3388af35a825 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Thu, 3 Dec 2020 22:38:51 +0100 Subject: [PATCH 117/184] Add failing assertions `GameplayBeatmap` has to be used instead of the normal bindable `Beatmap`, beecause the former uses osu!-specific hitobjects, while the latter returns convert objects (i.e. `ConvertSlider`s). Similarly, the mod has to be fetched from the player instead of the global bindable, as `Player` has its own cloned instance of the mod, to which the beatmap is applied. The global bindable instance does not have `FirstObject` set. --- .../Mods/TestSceneOsuModHidden.cs | 26 ++++++++++++------- 1 file changed, 17 insertions(+), 9 deletions(-) diff --git a/osu.Game.Rulesets.Osu.Tests/Mods/TestSceneOsuModHidden.cs b/osu.Game.Rulesets.Osu.Tests/Mods/TestSceneOsuModHidden.cs index ff308f389f..1ac3ad9194 100644 --- a/osu.Game.Rulesets.Osu.Tests/Mods/TestSceneOsuModHidden.cs +++ b/osu.Game.Rulesets.Osu.Tests/Mods/TestSceneOsuModHidden.cs @@ -2,12 +2,15 @@ // See the LICENCE file in the repository root for full licence text. using System.Collections.Generic; +using System.Linq; using NUnit.Framework; +using osu.Framework.Testing; using osu.Game.Beatmaps; using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Objects.Types; using osu.Game.Rulesets.Osu.Mods; using osu.Game.Rulesets.Osu.Objects; +using osu.Game.Screens.Play; using osuTK; namespace osu.Game.Rulesets.Osu.Tests.Mods @@ -17,15 +20,15 @@ namespace osu.Game.Rulesets.Osu.Tests.Mods [Test] public void TestDefaultBeatmapTest() => CreateModTest(new ModTestData { - Mod = new OsuModHidden(), + Mod = new TestOsuModHidden(), Autoplay = true, - PassCondition = checkSomeHit + PassCondition = () => checkSomeHit() && objectWithIncreasedVisibilityHasIndex(0) }); [Test] public void FirstCircleAfterTwoSpinners() => CreateModTest(new ModTestData { - Mod = new OsuModHidden(), + Mod = new TestOsuModHidden(), Autoplay = true, Beatmap = new Beatmap { @@ -54,13 +57,13 @@ namespace osu.Game.Rulesets.Osu.Tests.Mods } } }, - PassCondition = checkSomeHit + PassCondition = () => checkSomeHit() && objectWithIncreasedVisibilityHasIndex(2) }); [Test] public void FirstSliderAfterTwoSpinners() => CreateModTest(new ModTestData { - Mod = new OsuModHidden(), + Mod = new TestOsuModHidden(), Autoplay = true, Beatmap = new Beatmap { @@ -89,13 +92,13 @@ namespace osu.Game.Rulesets.Osu.Tests.Mods } } }, - PassCondition = checkSomeHit + PassCondition = () => checkSomeHit() && objectWithIncreasedVisibilityHasIndex(2) }); [Test] public void TestWithSliderReuse() => CreateModTest(new ModTestData { - Mod = new OsuModHidden(), + Mod = new TestOsuModHidden(), Autoplay = true, Beatmap = new Beatmap { @@ -116,9 +119,14 @@ namespace osu.Game.Rulesets.Osu.Tests.Mods PassCondition = checkSomeHit }); - private bool checkSomeHit() + private bool checkSomeHit() => Player.ScoreProcessor.JudgedHits >= 4; + + private bool objectWithIncreasedVisibilityHasIndex(int index) + => Player.Mods.Value.OfType().Single().FirstObject == Player.ChildrenOfType().Single().HitObjects[index]; + + private class TestOsuModHidden : OsuModHidden { - return Player.ScoreProcessor.JudgedHits >= 4; + public new HitObject FirstObject => base.FirstObject; } } } From 4d739f11a8352ed16cd7dbb2f499cee9ad6d6240 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Thu, 3 Dec 2020 22:40:30 +0100 Subject: [PATCH 118/184] Fix spinner ticks getting increased visibility state Regressed in #10696. The old `IsFirstHideableObject()` method did not consider nested hitobjects, while its replacement - `IsFirstAdjustableObject()` - did. Therefore, spinner ticks could be considered first adjustable objects, breaking the old logic. There is no need to match over `SpinnerBonusTick`, as it inherits from `SpinnerTick`. --- osu.Game.Rulesets.Osu/Mods/OsuModHidden.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModHidden.cs b/osu.Game.Rulesets.Osu/Mods/OsuModHidden.cs index 78e759f0e0..45f314af7b 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModHidden.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModHidden.cs @@ -24,7 +24,7 @@ namespace osu.Game.Rulesets.Osu.Mods private const double fade_in_duration_multiplier = 0.4; private const double fade_out_duration_multiplier = 0.3; - protected override bool IsFirstAdjustableObject(HitObject hitObject) => !(hitObject is Spinner); + protected override bool IsFirstAdjustableObject(HitObject hitObject) => !(hitObject is Spinner || hitObject is SpinnerTick); public override void ApplyToBeatmap(IBeatmap beatmap) { From 71fa0da7f4dc1b57700e68277e4fed251b22df71 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Thu, 3 Dec 2020 23:13:48 +0100 Subject: [PATCH 119/184] Add failing test cases --- .../Audio/SampleInfoEqualityTest.cs | 78 +++++++++++++++++++ 1 file changed, 78 insertions(+) create mode 100644 osu.Game.Tests/Audio/SampleInfoEqualityTest.cs diff --git a/osu.Game.Tests/Audio/SampleInfoEqualityTest.cs b/osu.Game.Tests/Audio/SampleInfoEqualityTest.cs new file mode 100644 index 0000000000..149096608f --- /dev/null +++ b/osu.Game.Tests/Audio/SampleInfoEqualityTest.cs @@ -0,0 +1,78 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using NUnit.Framework; +using osu.Game.Audio; + +namespace osu.Game.Tests.Audio +{ + [TestFixture] + public class SampleInfoEqualityTest + { + [Test] + public void TestSameSingleSamplesAreEqual() + { + var first = new SampleInfo("sample"); + var second = new SampleInfo("sample"); + + assertEquality(first, second); + } + + [Test] + public void TestDifferentSingleSamplesAreNotEqual() + { + var first = new SampleInfo("first"); + var second = new SampleInfo("second"); + + assertNonEquality(first, second); + } + + [Test] + public void TestDifferentCountSampleSetsAreNotEqual() + { + var first = new SampleInfo("sample", "extra"); + var second = new SampleInfo("sample"); + + assertNonEquality(first, second); + } + + [Test] + public void TestDifferentSampleSetsOfSameCountAreNotEqual() + { + var first = new SampleInfo("first", "common"); + var second = new SampleInfo("common", "second"); + + assertNonEquality(first, second); + } + + [Test] + public void TestSameOrderSameSampleSetsAreEqual() + { + var first = new SampleInfo("first", "second"); + var second = new SampleInfo("first", "second"); + + assertEquality(first, second); + } + + [Test] + public void TestDifferentOrderSameSampleSetsAreEqual() + { + var first = new SampleInfo("first", "second"); + var second = new SampleInfo("second", "first"); + + assertEquality(first, second); + } + + private void assertEquality(SampleInfo first, SampleInfo second) + { + Assert.That(first.Equals(second), Is.True); + Assert.That(first.GetHashCode(), Is.EqualTo(second.GetHashCode())); + } + + private void assertNonEquality(SampleInfo first, SampleInfo second) + { + Assert.That(first.Equals(second), Is.False); + Assert.That(first.GetHashCode(), Is.Not.EqualTo(second.GetHashCode())); + } + } +} From 15d9147eddb9a39a4569d53042fcc05f1d5cf62b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Thu, 3 Dec 2020 23:19:26 +0100 Subject: [PATCH 120/184] Ensure equality member consistency for SampleInfo The previous implementation of `SampleInfo`'s equality members was not completely correct in its treatment of the `sampleNames` array. While `Equals()` compared the values of `sampleNames` using `SequenceEqual()`, therefore performing a structural check that inspects the contents of both arrays, `GetHashCode()` used `HashCode.Combine()` directly on the arrays, therefore operating on reference equality. This could cause the pooling mechanism of samples to fail, as pointed out in #11079. To resolve, change the `GetHashCode()` implementation such that it also considers the contents of the array rather than just the reference to the array itself. This is achieved by leveraging `StructuralEqualityComparer`. Additionally, as a bonus, an array sort was added to the constructor of `SampleInfo`. This is intended to be a "canonicalisation" processing step for the array of sample names. Thanks to that sort, two instances of `SampleInfo` that have the same sample names but permutated will also turn out to be equal and have the same hash codes, given the implementation of both equality members. This gives `SampleInfo` set-like semantics. --- osu.Game/Audio/SampleInfo.cs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/osu.Game/Audio/SampleInfo.cs b/osu.Game/Audio/SampleInfo.cs index 221bc31639..5d8240204e 100644 --- a/osu.Game/Audio/SampleInfo.cs +++ b/osu.Game/Audio/SampleInfo.cs @@ -2,6 +2,7 @@ // See the LICENCE file in the repository root for full licence text. using System; +using System.Collections; using System.Collections.Generic; using System.Linq; @@ -17,6 +18,7 @@ namespace osu.Game.Audio public SampleInfo(params string[] sampleNames) { this.sampleNames = sampleNames; + Array.Sort(sampleNames); } public IEnumerable LookupNames => sampleNames; @@ -25,7 +27,9 @@ namespace osu.Game.Audio public override int GetHashCode() { - return HashCode.Combine(sampleNames, Volume); + return HashCode.Combine( + StructuralComparisons.StructuralEqualityComparer.GetHashCode(sampleNames), + Volume); } public bool Equals(SampleInfo other) From 3de46d0a3be4309fb45b58fa1b9d734d8d6a0b55 Mon Sep 17 00:00:00 2001 From: ekrctb Date: Fri, 4 Dec 2020 10:09:07 +0900 Subject: [PATCH 121/184] Fix & clarify catcher tests --- .../TestSceneCatcher.cs | 36 ++++++++++--------- 1 file changed, 19 insertions(+), 17 deletions(-) diff --git a/osu.Game.Rulesets.Catch.Tests/TestSceneCatcher.cs b/osu.Game.Rulesets.Catch.Tests/TestSceneCatcher.cs index f41a16026a..194a12a9b7 100644 --- a/osu.Game.Rulesets.Catch.Tests/TestSceneCatcher.cs +++ b/osu.Game.Rulesets.Catch.Tests/TestSceneCatcher.cs @@ -71,7 +71,7 @@ namespace osu.Game.Rulesets.Catch.Tests } [Test] - public void TestCatcherStateFruit() + public void TestFruitChangesCatcherState() { AddStep("miss fruit", () => attemptCatch(new Fruit { X = 100 })); checkState(CatcherAnimationState.Fail); @@ -82,7 +82,19 @@ namespace osu.Game.Rulesets.Catch.Tests } [Test] - public void TestCatcherStateTinyDroplet() + public void TestNormalFruitResetsHyperDashState() + { + AddStep("catch hyper fruit", () => attemptCatch(new Fruit + { + HyperDashTarget = new Fruit { X = 100 } + })); + checkHyperDash(true); + AddStep("catch normal fruit", () => attemptCatch(new Fruit())); + checkHyperDash(false); + } + + [Test] + public void TestTinyDropletMissPreservesCatcherState() { AddStep("catch hyper kiai fruit", () => attemptCatch(new TestKiaiFruit { @@ -90,19 +102,21 @@ namespace osu.Game.Rulesets.Catch.Tests })); AddStep("catch tiny droplet", () => attemptCatch(new TinyDroplet())); AddStep("miss tiny droplet", () => attemptCatch(new TinyDroplet { X = 100 })); + // catcher state and hyper dash state is preserved checkState(CatcherAnimationState.Kiai); checkHyperDash(true); } [Test] - public void TestCatcherStateBanana() + public void TestBananaMissPreservesCatcherState() { AddStep("catch hyper kiai fruit", () => attemptCatch(new TestKiaiFruit { HyperDashTarget = new Fruit { X = 100 } })); - AddStep("miss banana", () => attemptCatch(new Banana())); - checkState(CatcherAnimationState.Idle); + AddStep("miss banana", () => attemptCatch(new Banana { X = 100 })); + // catcher state is preserved but hyper dash state is reset + checkState(CatcherAnimationState.Kiai); checkHyperDash(false); } @@ -135,18 +149,6 @@ namespace osu.Game.Rulesets.Catch.Tests AddAssert("fruits are dropped", () => !catcher.CaughtObjects.Any() && droppedObjectContainer.Count == 10); } - [Test] - public void TestHyperFruitHyperDash() - { - AddStep("catch hyper fruit", () => attemptCatch(new Fruit - { - HyperDashTarget = new Fruit { X = 100 } - })); - checkHyperDash(true); - AddStep("catch normal fruit", () => attemptCatch(new Fruit())); - checkHyperDash(false); - } - [TestCase(true)] [TestCase(false)] public void TestHitLighting(bool enabled) From e82ca66d3ee144b5569e646d25a22e246458aac8 Mon Sep 17 00:00:00 2001 From: ekrctb Date: Fri, 4 Dec 2020 10:21:54 +0900 Subject: [PATCH 122/184] Fix depth of dropped objects --- .../TestSceneCatcherArea.cs | 26 +++++++++++++------ .../TestSceneHyperDashColouring.cs | 2 +- osu.Game.Rulesets.Catch/UI/CatchPlayfield.cs | 6 ++--- osu.Game.Rulesets.Catch/UI/CatcherArea.cs | 4 +-- 4 files changed, 24 insertions(+), 14 deletions(-) diff --git a/osu.Game.Rulesets.Catch.Tests/TestSceneCatcherArea.cs b/osu.Game.Rulesets.Catch.Tests/TestSceneCatcherArea.cs index 7be6fc92ac..281ddc7eaa 100644 --- a/osu.Game.Rulesets.Catch.Tests/TestSceneCatcherArea.cs +++ b/osu.Game.Rulesets.Catch.Tests/TestSceneCatcherArea.cs @@ -6,6 +6,7 @@ using NUnit.Framework; using osu.Framework.Allocation; using osu.Framework.Extensions.IEnumerableExtensions; using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; using osu.Framework.Testing; using osu.Game.Beatmaps; using osu.Game.Beatmaps.ControlPoints; @@ -72,14 +73,23 @@ namespace osu.Game.Rulesets.Catch.Tests { circleSize = size; - SetContents(() => new CatchInputManager(catchRuleset) + SetContents(() => { - RelativeSizeAxes = Axes.Both, - Child = new TestCatcherArea(new BeatmapDifficulty { CircleSize = size }) + var droppedObjectContainer = new Container(); + + return new CatchInputManager(catchRuleset) { - Anchor = Anchor.Centre, - Origin = Anchor.TopCentre, - }, + RelativeSizeAxes = Axes.Both, + Children = new Drawable[] + { + droppedObjectContainer, + new TestCatcherArea(droppedObjectContainer, new BeatmapDifficulty { CircleSize = size }) + { + Anchor = Anchor.Centre, + Origin = Anchor.TopCentre, + } + } + }; }); } @@ -91,8 +101,8 @@ namespace osu.Game.Rulesets.Catch.Tests private class TestCatcherArea : CatcherArea { - public TestCatcherArea(BeatmapDifficulty beatmapDifficulty) - : base(beatmapDifficulty) + public TestCatcherArea(Container droppedObjectContainer, BeatmapDifficulty beatmapDifficulty) + : base(droppedObjectContainer, beatmapDifficulty) { } diff --git a/osu.Game.Rulesets.Catch.Tests/TestSceneHyperDashColouring.cs b/osu.Game.Rulesets.Catch.Tests/TestSceneHyperDashColouring.cs index 1b8368794c..07cb73e5ff 100644 --- a/osu.Game.Rulesets.Catch.Tests/TestSceneHyperDashColouring.cs +++ b/osu.Game.Rulesets.Catch.Tests/TestSceneHyperDashColouring.cs @@ -117,7 +117,7 @@ namespace osu.Game.Rulesets.Catch.Tests AddStep("create hyper-dashing catcher", () => { - Child = setupSkinHierarchy(catcherArea = new CatcherArea + Child = setupSkinHierarchy(catcherArea = new CatcherArea(new Container()) { Anchor = Anchor.Centre, Origin = Anchor.Centre, diff --git a/osu.Game.Rulesets.Catch/UI/CatchPlayfield.cs b/osu.Game.Rulesets.Catch/UI/CatchPlayfield.cs index 6934dcc1f9..df87359ed6 100644 --- a/osu.Game.Rulesets.Catch/UI/CatchPlayfield.cs +++ b/osu.Game.Rulesets.Catch/UI/CatchPlayfield.cs @@ -36,12 +36,12 @@ namespace osu.Game.Rulesets.Catch.UI public CatchPlayfield(BeatmapDifficulty difficulty, Func> createDrawableRepresentation) { - var explodingFruitContainer = new Container + var droppedObjectContainer = new Container { RelativeSizeAxes = Axes.Both, }; - CatcherArea = new CatcherArea(difficulty) + CatcherArea = new CatcherArea(droppedObjectContainer, difficulty) { Anchor = Anchor.BottomLeft, Origin = Anchor.TopLeft, @@ -49,7 +49,7 @@ namespace osu.Game.Rulesets.Catch.UI InternalChildren = new[] { - explodingFruitContainer, + droppedObjectContainer, CatcherArea.MovableCatcher.CreateProxiedContent(), HitObjectContainer, CatcherArea, diff --git a/osu.Game.Rulesets.Catch/UI/CatcherArea.cs b/osu.Game.Rulesets.Catch/UI/CatcherArea.cs index 9cd0785b85..539776354c 100644 --- a/osu.Game.Rulesets.Catch/UI/CatcherArea.cs +++ b/osu.Game.Rulesets.Catch/UI/CatcherArea.cs @@ -22,7 +22,7 @@ namespace osu.Game.Rulesets.Catch.UI public readonly Catcher MovableCatcher; private readonly CatchComboDisplay comboDisplay; - public CatcherArea(BeatmapDifficulty difficulty = null) + public CatcherArea(Container droppedObjectContainer, BeatmapDifficulty difficulty = null) { Size = new Vector2(CatchPlayfield.WIDTH, CATCHER_SIZE); Children = new Drawable[] @@ -36,7 +36,7 @@ namespace osu.Game.Rulesets.Catch.UI Margin = new MarginPadding { Bottom = 350f }, X = CatchPlayfield.CENTER_X }, - MovableCatcher = new Catcher(this, this, difficulty) { X = CatchPlayfield.CENTER_X }, + MovableCatcher = new Catcher(this, droppedObjectContainer, difficulty) { X = CatchPlayfield.CENTER_X }, }; } From 23af70dd328c9216dde5540fa8f6c9e6e30c6f8a Mon Sep 17 00:00:00 2001 From: ekrctb Date: Fri, 4 Dec 2020 10:24:25 +0900 Subject: [PATCH 123/184] Invert `if` --- osu.Game.Rulesets.Catch/UI/Catcher.cs | 41 +++++++++++++-------------- 1 file changed, 20 insertions(+), 21 deletions(-) diff --git a/osu.Game.Rulesets.Catch/UI/Catcher.cs b/osu.Game.Rulesets.Catch/UI/Catcher.cs index 1101e5b6b4..1037678734 100644 --- a/osu.Game.Rulesets.Catch/UI/Catcher.cs +++ b/osu.Game.Rulesets.Catch/UI/Catcher.cs @@ -245,30 +245,29 @@ namespace osu.Game.Rulesets.Catch.UI catchObjectPosition >= catcherPosition - halfCatchWidth && catchObjectPosition <= catcherPosition + halfCatchWidth; - // droplet doesn't affect the catcher state - if (!(fruit is TinyDroplet)) - { - if (validCatch && fruit.HyperDash) - { - var target = fruit.HyperDashTarget; - var timeDifference = target.StartTime - fruit.StartTime; - double positionDifference = target.X - catcherPosition; - var velocity = positionDifference / Math.Max(1.0, timeDifference - 1000.0 / 60.0); - - SetHyperDashState(Math.Abs(velocity), target.X); - } - else - SetHyperDashState(); - - if (validCatch) - updateState(fruit.Kiai ? CatcherAnimationState.Kiai : CatcherAnimationState.Idle); - else if (!(fruit is Banana)) - updateState(CatcherAnimationState.Fail); - } - if (validCatch) placeCaughtObject(fruit); + // droplet doesn't affect the catcher state + if (fruit is TinyDroplet) return validCatch; + + if (validCatch && fruit.HyperDash) + { + var target = fruit.HyperDashTarget; + var timeDifference = target.StartTime - fruit.StartTime; + double positionDifference = target.X - catcherPosition; + var velocity = positionDifference / Math.Max(1.0, timeDifference - 1000.0 / 60.0); + + SetHyperDashState(Math.Abs(velocity), target.X); + } + else + SetHyperDashState(); + + if (validCatch) + updateState(fruit.Kiai ? CatcherAnimationState.Kiai : CatcherAnimationState.Idle); + else if (!(fruit is Banana)) + updateState(CatcherAnimationState.Fail); + return validCatch; } From 898802340787ec59b212d8d0e7aa955ed797da88 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 4 Dec 2020 14:35:56 +0900 Subject: [PATCH 124/184] Tidy up code formatting and remove unnecessarily publicly exposed methods --- osu.Game.Rulesets.Catch/UI/Catcher.cs | 84 +++++++++++++-------------- 1 file changed, 40 insertions(+), 44 deletions(-) diff --git a/osu.Game.Rulesets.Catch/UI/Catcher.cs b/osu.Game.Rulesets.Catch/UI/Catcher.cs index 1037678734..2b88f24348 100644 --- a/osu.Game.Rulesets.Catch/UI/Catcher.cs +++ b/osu.Game.Rulesets.Catch/UI/Catcher.cs @@ -175,55 +175,19 @@ namespace osu.Game.Rulesets.Catch.UI /// /// Calculates the scale of the catcher based off the provided beatmap difficulty. /// - private static Vector2 calculateScale(BeatmapDifficulty difficulty) - => new Vector2(1.0f - 0.7f * (difficulty.CircleSize - 5) / 5); + private static Vector2 calculateScale(BeatmapDifficulty difficulty) => new Vector2(1.0f - 0.7f * (difficulty.CircleSize - 5) / 5); /// /// Calculates the width of the area used for attempting catches in gameplay. /// /// The scale of the catcher. - internal static float CalculateCatchWidth(Vector2 scale) - => CatcherArea.CATCHER_SIZE * Math.Abs(scale.X) * ALLOWED_CATCH_RANGE; + internal static float CalculateCatchWidth(Vector2 scale) => CatcherArea.CATCHER_SIZE * Math.Abs(scale.X) * ALLOWED_CATCH_RANGE; /// /// Calculates the width of the area used for attempting catches in gameplay. /// /// The beatmap difficulty. - internal static float CalculateCatchWidth(BeatmapDifficulty difficulty) - => CalculateCatchWidth(calculateScale(difficulty)); - - /// - /// Add a caught fruit to the catcher's stack. - /// - /// The fruit that was caught. - public void PlaceOnPlate(DrawablePalpableCatchHitObject fruit) - { - var ourRadius = fruit.DisplayRadius; - float theirRadius = 0; - - const float allowance = 10; - - while (caughtFruitContainer.Any(f => - Vector2Extensions.Distance(f.Position, fruit.Position) < (ourRadius + (theirRadius = CatchHitObject.OBJECT_RADIUS / 2)) / (allowance / 2))) - { - var diff = (ourRadius + theirRadius) / allowance; - fruit.X += (RNG.NextSingle() - 0.5f) * diff * 2; - fruit.Y -= RNG.NextSingle() * diff; - } - - fruit.X = Math.Clamp(fruit.X, -CatcherArea.CATCHER_SIZE / 2, CatcherArea.CATCHER_SIZE / 2); - - caughtFruitContainer.Add(fruit); - - if (hitLighting.Value) - { - HitExplosion hitExplosion = hitExplosionPool.Get(); - hitExplosion.X = fruit.X; - hitExplosion.Scale = new Vector2(fruit.HitObject.Scale); - hitExplosion.ObjectColour = fruit.AccentColour.Value; - hitExplosionContainer.Add(hitExplosion); - } - } + internal static float CalculateCatchWidth(BeatmapDifficulty difficulty) => CalculateCatchWidth(calculateScale(difficulty)); /// /// Let the catcher attempt to catch a fruit. @@ -375,12 +339,10 @@ namespace osu.Game.Rulesets.Catch.UI public void Drop() => clearPlate(DroppedObjectAnimation.Drop); /// - /// Explode any fruit off the plate. + /// Explode all fruit off the plate. /// public void Explode() => clearPlate(DroppedObjectAnimation.Explode); - public void Explode(DrawablePalpableCatchHitObject caughtObject) => removeFromPlate(caughtObject, DroppedObjectAnimation.Explode); - protected override void SkinChanged(ISkinSource skin, bool allowFallback) { base.SkinChanged(skin, allowFallback); @@ -456,6 +418,7 @@ namespace osu.Game.Rulesets.Catch.UI private void placeCaughtObject(PalpableCatchHitObject source) { var caughtObject = createCaughtObject(source); + if (caughtObject == null) return; caughtObject.RelativePositionAxes = Axes.None; @@ -468,10 +431,43 @@ namespace osu.Game.Rulesets.Catch.UI caughtObject.LifetimeStart = source.StartTime; caughtObject.LifetimeEnd = double.MaxValue; - PlaceOnPlate(caughtObject); + adjustPositionInStack(caughtObject); + + caughtFruitContainer.Add(caughtObject); + + addLighting(caughtObject); if (!caughtObject.StaysOnPlate) - Explode(caughtObject); + removeFromPlate(caughtObject, DroppedObjectAnimation.Explode); + } + + private void adjustPositionInStack(DrawablePalpableCatchHitObject caughtObject) + { + const float radius_div_2 = CatchHitObject.OBJECT_RADIUS / 2; + const float allowance = 10; + + float caughtObjectRadius = caughtObject.DisplayRadius; + + while (caughtFruitContainer.Any(f => Vector2Extensions.Distance(f.Position, caughtObject.Position) < (caughtObjectRadius + radius_div_2) / (allowance / 2))) + { + float diff = (caughtObjectRadius + radius_div_2) / allowance; + + caughtObject.X += (RNG.NextSingle() - 0.5f) * diff * 2; + caughtObject.Y -= RNG.NextSingle() * diff; + } + + caughtObject.X = Math.Clamp(caughtObject.X, -CatcherArea.CATCHER_SIZE / 2, CatcherArea.CATCHER_SIZE / 2); + } + + private void addLighting(DrawablePalpableCatchHitObject caughtObject) + { + if (!hitLighting.Value) return; + + HitExplosion hitExplosion = hitExplosionPool.Get(); + hitExplosion.X = caughtObject.X; + hitExplosion.Scale = new Vector2(caughtObject.HitObject.Scale); + hitExplosion.ObjectColour = caughtObject.AccentColour.Value; + hitExplosionContainer.Add(hitExplosion); } private DrawablePalpableCatchHitObject createCaughtObject(PalpableCatchHitObject source) From d3a17b65d52f1eabb6351a9036e983d1970ac5bf Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 4 Dec 2020 14:36:40 +0900 Subject: [PATCH 125/184] Move public methods upwards --- osu.Game.Rulesets.Catch/UI/Catcher.cs | 50 +++++++++++++-------------- 1 file changed, 25 insertions(+), 25 deletions(-) diff --git a/osu.Game.Rulesets.Catch/UI/Catcher.cs b/osu.Game.Rulesets.Catch/UI/Catcher.cs index 2b88f24348..2a3447c80a 100644 --- a/osu.Game.Rulesets.Catch/UI/Catcher.cs +++ b/osu.Game.Rulesets.Catch/UI/Catcher.cs @@ -266,24 +266,17 @@ namespace osu.Game.Rulesets.Catch.UI } } - private void runHyperDashStateTransition(bool hyperDashing) + public void UpdatePosition(float position) { - updateTrailVisibility(); + position = Math.Clamp(position, 0, CatchPlayfield.WIDTH); - if (hyperDashing) - { - this.FadeColour(hyperDashColour, HYPER_DASH_TRANSITION_DURATION, Easing.OutQuint); - this.FadeTo(0.2f, HYPER_DASH_TRANSITION_DURATION, Easing.OutQuint); - } - else - { - this.FadeColour(Color4.White, HYPER_DASH_TRANSITION_DURATION, Easing.OutQuint); - this.FadeTo(1f, HYPER_DASH_TRANSITION_DURATION, Easing.OutQuint); - } + if (position == X) + return; + + Scale = new Vector2(Math.Abs(Scale.X) * (position > X ? 1 : -1), Scale.Y); + X = position; } - private void updateTrailVisibility() => trails.DisplayTrail = Dashing || HyperDashing; - public bool OnPressed(CatchAction action) { switch (action) @@ -322,17 +315,6 @@ namespace osu.Game.Rulesets.Catch.UI } } - public void UpdatePosition(float position) - { - position = Math.Clamp(position, 0, CatchPlayfield.WIDTH); - - if (position == X) - return; - - Scale = new Vector2(Math.Abs(Scale.X) * (position > X ? 1 : -1), Scale.Y); - X = position; - } - /// /// Drop any fruit off the plate. /// @@ -343,6 +325,24 @@ namespace osu.Game.Rulesets.Catch.UI /// public void Explode() => clearPlate(DroppedObjectAnimation.Explode); + private void runHyperDashStateTransition(bool hyperDashing) + { + updateTrailVisibility(); + + if (hyperDashing) + { + this.FadeColour(hyperDashColour, HYPER_DASH_TRANSITION_DURATION, Easing.OutQuint); + this.FadeTo(0.2f, HYPER_DASH_TRANSITION_DURATION, Easing.OutQuint); + } + else + { + this.FadeColour(Color4.White, HYPER_DASH_TRANSITION_DURATION, Easing.OutQuint); + this.FadeTo(1f, HYPER_DASH_TRANSITION_DURATION, Easing.OutQuint); + } + } + + private void updateTrailVisibility() => trails.DisplayTrail = Dashing || HyperDashing; + protected override void SkinChanged(ISkinSource skin, bool allowFallback) { base.SkinChanged(skin, allowFallback); From b8c284b34fcfd754451382ab66612c3de5c5f37e Mon Sep 17 00:00:00 2001 From: Joehu Date: Fri, 4 Dec 2020 00:51:46 -0800 Subject: [PATCH 126/184] Fix one more key binding string not being sentence cased --- osu.Game/Input/Bindings/GlobalActionContainer.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Input/Bindings/GlobalActionContainer.cs b/osu.Game/Input/Bindings/GlobalActionContainer.cs index f4a4813b94..1270df5374 100644 --- a/osu.Game/Input/Bindings/GlobalActionContainer.cs +++ b/osu.Game/Input/Bindings/GlobalActionContainer.cs @@ -149,7 +149,7 @@ namespace osu.Game.Input.Bindings [Description("Select")] Select, - [Description("Quick exit (Hold)")] + [Description("Quick exit (hold)")] QuickExit, // Game-wide beatmap music controller keybindings From a12b04915447d11f43598a81df468e3eba9e8aaa Mon Sep 17 00:00:00 2001 From: ekrctb Date: Fri, 4 Dec 2020 20:11:35 +0900 Subject: [PATCH 127/184] Move piece files in Osu ruleset --- .../Drawables/Pieces => Skinning/Default}/ApproachCircle.cs | 0 .../{Objects/Drawables/Pieces => Skinning/Default}/CirclePiece.cs | 0 .../Drawables/Pieces => Skinning/Default}/DefaultSpinnerDisc.cs | 0 .../Drawables/Pieces => Skinning/Default}/DrawableSliderPath.cs | 0 .../Drawables/Pieces => Skinning/Default}/ExplodePiece.cs | 0 .../{Objects/Drawables/Pieces => Skinning/Default}/FlashPiece.cs | 0 .../{Objects/Drawables/Pieces => Skinning/Default}/GlowPiece.cs | 0 .../Drawables/Pieces => Skinning/Default}/MainCirclePiece.cs | 0 .../Drawables/Pieces => Skinning/Default}/ManualSliderBody.cs | 0 .../{Objects/Drawables/Pieces => Skinning/Default}/NumberPiece.cs | 0 .../Drawables/Pieces => Skinning/Default}/PlaySliderBody.cs | 0 .../Drawables/Pieces => Skinning/Default}/ReverseArrowPiece.cs | 0 .../{Objects/Drawables/Pieces => Skinning/Default}/RingPiece.cs | 0 .../{Objects/Drawables/Pieces => Skinning/Default}/SliderBall.cs | 0 .../{Objects/Drawables/Pieces => Skinning/Default}/SliderBody.cs | 0 .../Drawables/Pieces => Skinning/Default}/SnakingSliderBody.cs | 0 .../Drawables/Pieces => Skinning/Default}/SpinnerBonusDisplay.cs | 0 .../{Objects/Drawables/Pieces => Skinning/Default}/SpinnerFill.cs | 0 .../Pieces => Skinning/Default}/SpinnerRotationTracker.cs | 0 .../Drawables/Pieces => Skinning/Default}/SpinnerSpmCounter.cs | 0 .../Drawables/Pieces => Skinning/Default}/SpinnerTicks.cs | 0 .../Drawables/Pieces => Skinning/Default}/TrianglesPiece.cs | 0 osu.Game.Rulesets.Osu/Skinning/{ => Legacy}/LegacyCursor.cs | 0 osu.Game.Rulesets.Osu/Skinning/{ => Legacy}/LegacyCursorTrail.cs | 0 .../Skinning/{ => Legacy}/LegacyMainCirclePiece.cs | 0 .../Skinning/{ => Legacy}/LegacyNewStyleSpinner.cs | 0 .../Skinning/{ => Legacy}/LegacyOldStyleSpinner.cs | 0 osu.Game.Rulesets.Osu/Skinning/{ => Legacy}/LegacySliderBall.cs | 0 osu.Game.Rulesets.Osu/Skinning/{ => Legacy}/LegacySliderBody.cs | 0 osu.Game.Rulesets.Osu/Skinning/{ => Legacy}/LegacySpinner.cs | 0 30 files changed, 0 insertions(+), 0 deletions(-) rename osu.Game.Rulesets.Osu/{Objects/Drawables/Pieces => Skinning/Default}/ApproachCircle.cs (100%) rename osu.Game.Rulesets.Osu/{Objects/Drawables/Pieces => Skinning/Default}/CirclePiece.cs (100%) rename osu.Game.Rulesets.Osu/{Objects/Drawables/Pieces => Skinning/Default}/DefaultSpinnerDisc.cs (100%) rename osu.Game.Rulesets.Osu/{Objects/Drawables/Pieces => Skinning/Default}/DrawableSliderPath.cs (100%) rename osu.Game.Rulesets.Osu/{Objects/Drawables/Pieces => Skinning/Default}/ExplodePiece.cs (100%) rename osu.Game.Rulesets.Osu/{Objects/Drawables/Pieces => Skinning/Default}/FlashPiece.cs (100%) rename osu.Game.Rulesets.Osu/{Objects/Drawables/Pieces => Skinning/Default}/GlowPiece.cs (100%) rename osu.Game.Rulesets.Osu/{Objects/Drawables/Pieces => Skinning/Default}/MainCirclePiece.cs (100%) rename osu.Game.Rulesets.Osu/{Objects/Drawables/Pieces => Skinning/Default}/ManualSliderBody.cs (100%) rename osu.Game.Rulesets.Osu/{Objects/Drawables/Pieces => Skinning/Default}/NumberPiece.cs (100%) rename osu.Game.Rulesets.Osu/{Objects/Drawables/Pieces => Skinning/Default}/PlaySliderBody.cs (100%) rename osu.Game.Rulesets.Osu/{Objects/Drawables/Pieces => Skinning/Default}/ReverseArrowPiece.cs (100%) rename osu.Game.Rulesets.Osu/{Objects/Drawables/Pieces => Skinning/Default}/RingPiece.cs (100%) rename osu.Game.Rulesets.Osu/{Objects/Drawables/Pieces => Skinning/Default}/SliderBall.cs (100%) rename osu.Game.Rulesets.Osu/{Objects/Drawables/Pieces => Skinning/Default}/SliderBody.cs (100%) rename osu.Game.Rulesets.Osu/{Objects/Drawables/Pieces => Skinning/Default}/SnakingSliderBody.cs (100%) rename osu.Game.Rulesets.Osu/{Objects/Drawables/Pieces => Skinning/Default}/SpinnerBonusDisplay.cs (100%) rename osu.Game.Rulesets.Osu/{Objects/Drawables/Pieces => Skinning/Default}/SpinnerFill.cs (100%) rename osu.Game.Rulesets.Osu/{Objects/Drawables/Pieces => Skinning/Default}/SpinnerRotationTracker.cs (100%) rename osu.Game.Rulesets.Osu/{Objects/Drawables/Pieces => Skinning/Default}/SpinnerSpmCounter.cs (100%) rename osu.Game.Rulesets.Osu/{Objects/Drawables/Pieces => Skinning/Default}/SpinnerTicks.cs (100%) rename osu.Game.Rulesets.Osu/{Objects/Drawables/Pieces => Skinning/Default}/TrianglesPiece.cs (100%) rename osu.Game.Rulesets.Osu/Skinning/{ => Legacy}/LegacyCursor.cs (100%) rename osu.Game.Rulesets.Osu/Skinning/{ => Legacy}/LegacyCursorTrail.cs (100%) rename osu.Game.Rulesets.Osu/Skinning/{ => Legacy}/LegacyMainCirclePiece.cs (100%) rename osu.Game.Rulesets.Osu/Skinning/{ => Legacy}/LegacyNewStyleSpinner.cs (100%) rename osu.Game.Rulesets.Osu/Skinning/{ => Legacy}/LegacyOldStyleSpinner.cs (100%) rename osu.Game.Rulesets.Osu/Skinning/{ => Legacy}/LegacySliderBall.cs (100%) rename osu.Game.Rulesets.Osu/Skinning/{ => Legacy}/LegacySliderBody.cs (100%) rename osu.Game.Rulesets.Osu/Skinning/{ => Legacy}/LegacySpinner.cs (100%) diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/ApproachCircle.cs b/osu.Game.Rulesets.Osu/Skinning/Default/ApproachCircle.cs similarity index 100% rename from osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/ApproachCircle.cs rename to osu.Game.Rulesets.Osu/Skinning/Default/ApproachCircle.cs diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/CirclePiece.cs b/osu.Game.Rulesets.Osu/Skinning/Default/CirclePiece.cs similarity index 100% rename from osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/CirclePiece.cs rename to osu.Game.Rulesets.Osu/Skinning/Default/CirclePiece.cs diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/DefaultSpinnerDisc.cs b/osu.Game.Rulesets.Osu/Skinning/Default/DefaultSpinnerDisc.cs similarity index 100% rename from osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/DefaultSpinnerDisc.cs rename to osu.Game.Rulesets.Osu/Skinning/Default/DefaultSpinnerDisc.cs diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/DrawableSliderPath.cs b/osu.Game.Rulesets.Osu/Skinning/Default/DrawableSliderPath.cs similarity index 100% rename from osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/DrawableSliderPath.cs rename to osu.Game.Rulesets.Osu/Skinning/Default/DrawableSliderPath.cs diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/ExplodePiece.cs b/osu.Game.Rulesets.Osu/Skinning/Default/ExplodePiece.cs similarity index 100% rename from osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/ExplodePiece.cs rename to osu.Game.Rulesets.Osu/Skinning/Default/ExplodePiece.cs diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/FlashPiece.cs b/osu.Game.Rulesets.Osu/Skinning/Default/FlashPiece.cs similarity index 100% rename from osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/FlashPiece.cs rename to osu.Game.Rulesets.Osu/Skinning/Default/FlashPiece.cs diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/GlowPiece.cs b/osu.Game.Rulesets.Osu/Skinning/Default/GlowPiece.cs similarity index 100% rename from osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/GlowPiece.cs rename to osu.Game.Rulesets.Osu/Skinning/Default/GlowPiece.cs diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/MainCirclePiece.cs b/osu.Game.Rulesets.Osu/Skinning/Default/MainCirclePiece.cs similarity index 100% rename from osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/MainCirclePiece.cs rename to osu.Game.Rulesets.Osu/Skinning/Default/MainCirclePiece.cs diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/ManualSliderBody.cs b/osu.Game.Rulesets.Osu/Skinning/Default/ManualSliderBody.cs similarity index 100% rename from osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/ManualSliderBody.cs rename to osu.Game.Rulesets.Osu/Skinning/Default/ManualSliderBody.cs diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/NumberPiece.cs b/osu.Game.Rulesets.Osu/Skinning/Default/NumberPiece.cs similarity index 100% rename from osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/NumberPiece.cs rename to osu.Game.Rulesets.Osu/Skinning/Default/NumberPiece.cs diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/PlaySliderBody.cs b/osu.Game.Rulesets.Osu/Skinning/Default/PlaySliderBody.cs similarity index 100% rename from osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/PlaySliderBody.cs rename to osu.Game.Rulesets.Osu/Skinning/Default/PlaySliderBody.cs diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/ReverseArrowPiece.cs b/osu.Game.Rulesets.Osu/Skinning/Default/ReverseArrowPiece.cs similarity index 100% rename from osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/ReverseArrowPiece.cs rename to osu.Game.Rulesets.Osu/Skinning/Default/ReverseArrowPiece.cs diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/RingPiece.cs b/osu.Game.Rulesets.Osu/Skinning/Default/RingPiece.cs similarity index 100% rename from osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/RingPiece.cs rename to osu.Game.Rulesets.Osu/Skinning/Default/RingPiece.cs diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SliderBall.cs b/osu.Game.Rulesets.Osu/Skinning/Default/SliderBall.cs similarity index 100% rename from osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SliderBall.cs rename to osu.Game.Rulesets.Osu/Skinning/Default/SliderBall.cs diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SliderBody.cs b/osu.Game.Rulesets.Osu/Skinning/Default/SliderBody.cs similarity index 100% rename from osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SliderBody.cs rename to osu.Game.Rulesets.Osu/Skinning/Default/SliderBody.cs diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SnakingSliderBody.cs b/osu.Game.Rulesets.Osu/Skinning/Default/SnakingSliderBody.cs similarity index 100% rename from osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SnakingSliderBody.cs rename to osu.Game.Rulesets.Osu/Skinning/Default/SnakingSliderBody.cs diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SpinnerBonusDisplay.cs b/osu.Game.Rulesets.Osu/Skinning/Default/SpinnerBonusDisplay.cs similarity index 100% rename from osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SpinnerBonusDisplay.cs rename to osu.Game.Rulesets.Osu/Skinning/Default/SpinnerBonusDisplay.cs diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SpinnerFill.cs b/osu.Game.Rulesets.Osu/Skinning/Default/SpinnerFill.cs similarity index 100% rename from osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SpinnerFill.cs rename to osu.Game.Rulesets.Osu/Skinning/Default/SpinnerFill.cs diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SpinnerRotationTracker.cs b/osu.Game.Rulesets.Osu/Skinning/Default/SpinnerRotationTracker.cs similarity index 100% rename from osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SpinnerRotationTracker.cs rename to osu.Game.Rulesets.Osu/Skinning/Default/SpinnerRotationTracker.cs diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SpinnerSpmCounter.cs b/osu.Game.Rulesets.Osu/Skinning/Default/SpinnerSpmCounter.cs similarity index 100% rename from osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SpinnerSpmCounter.cs rename to osu.Game.Rulesets.Osu/Skinning/Default/SpinnerSpmCounter.cs diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SpinnerTicks.cs b/osu.Game.Rulesets.Osu/Skinning/Default/SpinnerTicks.cs similarity index 100% rename from osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SpinnerTicks.cs rename to osu.Game.Rulesets.Osu/Skinning/Default/SpinnerTicks.cs diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/TrianglesPiece.cs b/osu.Game.Rulesets.Osu/Skinning/Default/TrianglesPiece.cs similarity index 100% rename from osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/TrianglesPiece.cs rename to osu.Game.Rulesets.Osu/Skinning/Default/TrianglesPiece.cs diff --git a/osu.Game.Rulesets.Osu/Skinning/LegacyCursor.cs b/osu.Game.Rulesets.Osu/Skinning/Legacy/LegacyCursor.cs similarity index 100% rename from osu.Game.Rulesets.Osu/Skinning/LegacyCursor.cs rename to osu.Game.Rulesets.Osu/Skinning/Legacy/LegacyCursor.cs diff --git a/osu.Game.Rulesets.Osu/Skinning/LegacyCursorTrail.cs b/osu.Game.Rulesets.Osu/Skinning/Legacy/LegacyCursorTrail.cs similarity index 100% rename from osu.Game.Rulesets.Osu/Skinning/LegacyCursorTrail.cs rename to osu.Game.Rulesets.Osu/Skinning/Legacy/LegacyCursorTrail.cs diff --git a/osu.Game.Rulesets.Osu/Skinning/LegacyMainCirclePiece.cs b/osu.Game.Rulesets.Osu/Skinning/Legacy/LegacyMainCirclePiece.cs similarity index 100% rename from osu.Game.Rulesets.Osu/Skinning/LegacyMainCirclePiece.cs rename to osu.Game.Rulesets.Osu/Skinning/Legacy/LegacyMainCirclePiece.cs diff --git a/osu.Game.Rulesets.Osu/Skinning/LegacyNewStyleSpinner.cs b/osu.Game.Rulesets.Osu/Skinning/Legacy/LegacyNewStyleSpinner.cs similarity index 100% rename from osu.Game.Rulesets.Osu/Skinning/LegacyNewStyleSpinner.cs rename to osu.Game.Rulesets.Osu/Skinning/Legacy/LegacyNewStyleSpinner.cs diff --git a/osu.Game.Rulesets.Osu/Skinning/LegacyOldStyleSpinner.cs b/osu.Game.Rulesets.Osu/Skinning/Legacy/LegacyOldStyleSpinner.cs similarity index 100% rename from osu.Game.Rulesets.Osu/Skinning/LegacyOldStyleSpinner.cs rename to osu.Game.Rulesets.Osu/Skinning/Legacy/LegacyOldStyleSpinner.cs diff --git a/osu.Game.Rulesets.Osu/Skinning/LegacySliderBall.cs b/osu.Game.Rulesets.Osu/Skinning/Legacy/LegacySliderBall.cs similarity index 100% rename from osu.Game.Rulesets.Osu/Skinning/LegacySliderBall.cs rename to osu.Game.Rulesets.Osu/Skinning/Legacy/LegacySliderBall.cs diff --git a/osu.Game.Rulesets.Osu/Skinning/LegacySliderBody.cs b/osu.Game.Rulesets.Osu/Skinning/Legacy/LegacySliderBody.cs similarity index 100% rename from osu.Game.Rulesets.Osu/Skinning/LegacySliderBody.cs rename to osu.Game.Rulesets.Osu/Skinning/Legacy/LegacySliderBody.cs diff --git a/osu.Game.Rulesets.Osu/Skinning/LegacySpinner.cs b/osu.Game.Rulesets.Osu/Skinning/Legacy/LegacySpinner.cs similarity index 100% rename from osu.Game.Rulesets.Osu/Skinning/LegacySpinner.cs rename to osu.Game.Rulesets.Osu/Skinning/Legacy/LegacySpinner.cs From 245be2c5ed0274a25f331b8027f35001171be7b7 Mon Sep 17 00:00:00 2001 From: ekrctb Date: Fri, 4 Dec 2020 20:21:53 +0900 Subject: [PATCH 128/184] Adjust namespace --- .../Mods/TestSceneOsuModSpunOut.cs | 2 +- osu.Game.Rulesets.Osu.Tests/TestSceneCursorTrail.cs | 2 +- .../TestSceneSliderApplication.cs | 2 +- osu.Game.Rulesets.Osu.Tests/TestSceneSliderSnaking.cs | 2 +- .../Blueprints/HitCircles/Components/HitCirclePiece.cs | 2 +- .../Blueprints/Sliders/Components/SliderBodyPiece.cs | 2 +- .../Edit/Blueprints/Spinners/Components/SpinnerPiece.cs | 2 +- osu.Game.Rulesets.Osu/Mods/OsuModTraceable.cs | 2 +- .../Objects/Drawables/DrawableHitCircle.cs | 2 +- .../Objects/Drawables/DrawableSlider.cs | 2 +- .../Objects/Drawables/DrawableSliderRepeat.cs | 2 +- .../Objects/Drawables/DrawableSpinner.cs | 2 +- .../Objects/Drawables/SpinnerBackgroundLayer.cs | 2 +- .../Objects/Drawables/SpinnerCentreLayer.cs | 2 +- osu.Game.Rulesets.Osu/Skinning/Default/ApproachCircle.cs | 2 +- osu.Game.Rulesets.Osu/Skinning/Default/CirclePiece.cs | 3 ++- .../Skinning/Default/DefaultSpinnerDisc.cs | 4 +++- .../Skinning/Default/DrawableSliderPath.cs | 2 +- osu.Game.Rulesets.Osu/Skinning/Default/ExplodePiece.cs | 3 ++- osu.Game.Rulesets.Osu/Skinning/Default/FlashPiece.cs | 5 +++-- osu.Game.Rulesets.Osu/Skinning/Default/GlowPiece.cs | 2 +- .../Skinning/Default/MainCirclePiece.cs | 4 +++- .../Skinning/Default/ManualSliderBody.cs | 2 +- osu.Game.Rulesets.Osu/Skinning/Default/NumberPiece.cs | 6 +++--- osu.Game.Rulesets.Osu/Skinning/Default/PlaySliderBody.cs | 5 +++-- .../Skinning/Default/ReverseArrowPiece.cs | 9 +++++---- osu.Game.Rulesets.Osu/Skinning/Default/RingPiece.cs | 5 +++-- osu.Game.Rulesets.Osu/Skinning/Default/SliderBall.cs | 9 +++++---- osu.Game.Rulesets.Osu/Skinning/Default/SliderBody.cs | 2 +- .../Skinning/Default/SnakingSliderBody.cs | 4 +++- .../Skinning/Default/SpinnerBonusDisplay.cs | 3 ++- osu.Game.Rulesets.Osu/Skinning/Default/SpinnerFill.cs | 2 +- .../Skinning/Default/SpinnerRotationTracker.cs | 3 ++- .../Skinning/Default/SpinnerSpmCounter.cs | 2 +- osu.Game.Rulesets.Osu/Skinning/Default/SpinnerTicks.cs | 6 +++--- osu.Game.Rulesets.Osu/Skinning/Default/TrianglesPiece.cs | 2 +- osu.Game.Rulesets.Osu/Skinning/Legacy/LegacyCursor.cs | 4 ++-- .../Skinning/Legacy/LegacyCursorTrail.cs | 2 +- .../Skinning/Legacy/LegacyMainCirclePiece.cs | 2 +- .../Skinning/Legacy/LegacyNewStyleSpinner.cs | 2 +- .../Skinning/Legacy/LegacyOldStyleSpinner.cs | 2 +- .../Skinning/Legacy/LegacySliderBall.cs | 2 +- .../Skinning/Legacy/LegacySliderBody.cs | 4 ++-- osu.Game.Rulesets.Osu/Skinning/Legacy/LegacySpinner.cs | 2 +- .../Skinning/OsuLegacySkinTransformer.cs | 1 + 45 files changed, 75 insertions(+), 59 deletions(-) diff --git a/osu.Game.Rulesets.Osu.Tests/Mods/TestSceneOsuModSpunOut.cs b/osu.Game.Rulesets.Osu.Tests/Mods/TestSceneOsuModSpunOut.cs index 7b909d2907..7df5ca0f7c 100644 --- a/osu.Game.Rulesets.Osu.Tests/Mods/TestSceneOsuModSpunOut.cs +++ b/osu.Game.Rulesets.Osu.Tests/Mods/TestSceneOsuModSpunOut.cs @@ -13,7 +13,7 @@ using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Osu.Mods; using osu.Game.Rulesets.Osu.Objects; using osu.Game.Rulesets.Osu.Objects.Drawables; -using osu.Game.Rulesets.Osu.Objects.Drawables.Pieces; +using osu.Game.Rulesets.Osu.Skinning.Default; using osuTK; namespace osu.Game.Rulesets.Osu.Tests.Mods diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneCursorTrail.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneCursorTrail.cs index dde02e873b..fefe983f97 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestSceneCursorTrail.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneCursorTrail.cs @@ -12,7 +12,7 @@ using osu.Framework.Graphics.OpenGL.Textures; using osu.Framework.Graphics.Textures; using osu.Framework.Testing.Input; using osu.Game.Audio; -using osu.Game.Rulesets.Osu.Skinning; +using osu.Game.Rulesets.Osu.Skinning.Legacy; using osu.Game.Rulesets.Osu.UI.Cursor; using osu.Game.Skinning; using osu.Game.Tests.Visual; diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneSliderApplication.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneSliderApplication.cs index 084af7dafe..aac6db60fe 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestSceneSliderApplication.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneSliderApplication.cs @@ -12,7 +12,7 @@ using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Objects.Types; using osu.Game.Rulesets.Osu.Objects; using osu.Game.Rulesets.Osu.Objects.Drawables; -using osu.Game.Rulesets.Osu.Objects.Drawables.Pieces; +using osu.Game.Rulesets.Osu.Skinning.Default; using osu.Game.Skinning; using osu.Game.Tests.Visual; using osuTK; diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneSliderSnaking.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneSliderSnaking.cs index b71400b71d..e111bb1054 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestSceneSliderSnaking.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneSliderSnaking.cs @@ -19,7 +19,7 @@ using osu.Game.Rulesets.Objects.Types; using osu.Game.Rulesets.Osu.Configuration; using osu.Game.Rulesets.Osu.Objects; using osu.Game.Rulesets.Osu.Objects.Drawables; -using osu.Game.Rulesets.Osu.Objects.Drawables.Pieces; +using osu.Game.Rulesets.Osu.Skinning.Default; using osu.Game.Storyboards; using osuTK; diff --git a/osu.Game.Rulesets.Osu/Edit/Blueprints/HitCircles/Components/HitCirclePiece.cs b/osu.Game.Rulesets.Osu/Edit/Blueprints/HitCircles/Components/HitCirclePiece.cs index 2868ddeaa4..0cfc67cedb 100644 --- a/osu.Game.Rulesets.Osu/Edit/Blueprints/HitCircles/Components/HitCirclePiece.cs +++ b/osu.Game.Rulesets.Osu/Edit/Blueprints/HitCircles/Components/HitCirclePiece.cs @@ -5,7 +5,7 @@ using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Game.Graphics; using osu.Game.Rulesets.Osu.Objects; -using osu.Game.Rulesets.Osu.Objects.Drawables.Pieces; +using osu.Game.Rulesets.Osu.Skinning.Default; using osuTK; namespace osu.Game.Rulesets.Osu.Edit.Blueprints.HitCircles.Components diff --git a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/SliderBodyPiece.cs b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/SliderBodyPiece.cs index 5581ce4bfd..1c3d270c95 100644 --- a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/SliderBodyPiece.cs +++ b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/SliderBodyPiece.cs @@ -5,7 +5,7 @@ using System.Collections.Generic; using osu.Framework.Allocation; using osu.Game.Graphics; using osu.Game.Rulesets.Osu.Objects; -using osu.Game.Rulesets.Osu.Objects.Drawables.Pieces; +using osu.Game.Rulesets.Osu.Skinning.Default; using osuTK; using osuTK.Graphics; diff --git a/osu.Game.Rulesets.Osu/Edit/Blueprints/Spinners/Components/SpinnerPiece.cs b/osu.Game.Rulesets.Osu/Edit/Blueprints/Spinners/Components/SpinnerPiece.cs index 2347d8a34c..92961b40bc 100644 --- a/osu.Game.Rulesets.Osu/Edit/Blueprints/Spinners/Components/SpinnerPiece.cs +++ b/osu.Game.Rulesets.Osu/Edit/Blueprints/Spinners/Components/SpinnerPiece.cs @@ -7,7 +7,7 @@ using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; using osu.Game.Graphics; using osu.Game.Rulesets.Osu.Objects; -using osu.Game.Rulesets.Osu.Objects.Drawables.Pieces; +using osu.Game.Rulesets.Osu.Skinning.Default; using osuTK; namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Spinners.Components diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModTraceable.cs b/osu.Game.Rulesets.Osu/Mods/OsuModTraceable.cs index b7e60295cb..df0a41455f 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModTraceable.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModTraceable.cs @@ -7,7 +7,7 @@ using osu.Framework.Graphics; using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.Osu.Objects.Drawables; -using osu.Game.Rulesets.Osu.Objects.Drawables.Pieces; +using osu.Game.Rulesets.Osu.Skinning.Default; namespace osu.Game.Rulesets.Osu.Mods { diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableHitCircle.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableHitCircle.cs index abb51ae420..3c0260f5f5 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableHitCircle.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableHitCircle.cs @@ -12,7 +12,7 @@ using osu.Framework.Input.Bindings; using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.Osu.Judgements; -using osu.Game.Rulesets.Osu.Objects.Drawables.Pieces; +using osu.Game.Rulesets.Osu.Skinning.Default; using osu.Game.Rulesets.Scoring; using osu.Game.Skinning; using osuTK; diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs index af5b609ec8..511cbc2347 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs @@ -7,13 +7,13 @@ using JetBrains.Annotations; using osuTK; using osu.Framework.Graphics; using osu.Game.Rulesets.Objects.Drawables; -using osu.Game.Rulesets.Osu.Objects.Drawables.Pieces; using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics.Containers; using osu.Game.Audio; using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Osu.Skinning; +using osu.Game.Rulesets.Osu.Skinning.Default; using osu.Game.Rulesets.Osu.UI; using osuTK.Graphics; using osu.Game.Skinning; diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderRepeat.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderRepeat.cs index a684df98cb..76490e0de1 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderRepeat.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderRepeat.cs @@ -9,7 +9,7 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Utils; using osu.Game.Rulesets.Objects.Drawables; -using osu.Game.Rulesets.Osu.Objects.Drawables.Pieces; +using osu.Game.Rulesets.Osu.Skinning.Default; using osu.Game.Skinning; using osuTK; diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinner.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinner.cs index aea37acf6f..1f3bcece0c 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinner.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinner.cs @@ -15,8 +15,8 @@ using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.Osu.Judgements; -using osu.Game.Rulesets.Osu.Objects.Drawables.Pieces; using osu.Game.Rulesets.Osu.Skinning; +using osu.Game.Rulesets.Osu.Skinning.Default; using osu.Game.Rulesets.Scoring; using osu.Game.Screens.Ranking; using osu.Game.Skinning; diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/SpinnerBackgroundLayer.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/SpinnerBackgroundLayer.cs index 3cd2454706..10a7d33073 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/SpinnerBackgroundLayer.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/SpinnerBackgroundLayer.cs @@ -5,7 +5,7 @@ using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Game.Graphics; using osu.Game.Rulesets.Objects.Drawables; -using osu.Game.Rulesets.Osu.Objects.Drawables.Pieces; +using osu.Game.Rulesets.Osu.Skinning.Default; namespace osu.Game.Rulesets.Osu.Objects.Drawables { diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/SpinnerCentreLayer.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/SpinnerCentreLayer.cs index b62ce822f0..0c38c3a855 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/SpinnerCentreLayer.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/SpinnerCentreLayer.cs @@ -9,7 +9,7 @@ using osu.Framework.Graphics.Sprites; using osu.Framework.Utils; using osu.Game.Graphics; using osu.Game.Rulesets.Objects.Drawables; -using osu.Game.Rulesets.Osu.Objects.Drawables.Pieces; +using osu.Game.Rulesets.Osu.Skinning.Default; using osuTK; using osuTK.Graphics; diff --git a/osu.Game.Rulesets.Osu/Skinning/Default/ApproachCircle.cs b/osu.Game.Rulesets.Osu/Skinning/Default/ApproachCircle.cs index 1b474f265c..62f00a2b49 100644 --- a/osu.Game.Rulesets.Osu/Skinning/Default/ApproachCircle.cs +++ b/osu.Game.Rulesets.Osu/Skinning/Default/ApproachCircle.cs @@ -8,7 +8,7 @@ using osu.Framework.Graphics.Textures; using osu.Game.Skinning; using osuTK; -namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces +namespace osu.Game.Rulesets.Osu.Skinning.Default { public class ApproachCircle : Container { diff --git a/osu.Game.Rulesets.Osu/Skinning/Default/CirclePiece.cs b/osu.Game.Rulesets.Osu/Skinning/Default/CirclePiece.cs index d0e1055dce..ba41ebd445 100644 --- a/osu.Game.Rulesets.Osu/Skinning/Default/CirclePiece.cs +++ b/osu.Game.Rulesets.Osu/Skinning/Default/CirclePiece.cs @@ -7,9 +7,10 @@ using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Sprites; using osu.Framework.Graphics.Textures; using osu.Game.Rulesets.Objects.Drawables; +using osu.Game.Rulesets.Osu.Objects; using osuTK; -namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces +namespace osu.Game.Rulesets.Osu.Skinning.Default { public class CirclePiece : CompositeDrawable { diff --git a/osu.Game.Rulesets.Osu/Skinning/Default/DefaultSpinnerDisc.cs b/osu.Game.Rulesets.Osu/Skinning/Default/DefaultSpinnerDisc.cs index 14ce3b014d..667fee1495 100644 --- a/osu.Game.Rulesets.Osu/Skinning/Default/DefaultSpinnerDisc.cs +++ b/osu.Game.Rulesets.Osu/Skinning/Default/DefaultSpinnerDisc.cs @@ -10,10 +10,12 @@ using osu.Framework.Graphics.Containers; using osu.Framework.Utils; using osu.Game.Graphics; using osu.Game.Rulesets.Objects.Drawables; +using osu.Game.Rulesets.Osu.Objects; +using osu.Game.Rulesets.Osu.Objects.Drawables; using osuTK; using osuTK.Graphics; -namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces +namespace osu.Game.Rulesets.Osu.Skinning.Default { public class DefaultSpinnerDisc : CompositeDrawable { diff --git a/osu.Game.Rulesets.Osu/Skinning/Default/DrawableSliderPath.cs b/osu.Game.Rulesets.Osu/Skinning/Default/DrawableSliderPath.cs index c31d6beb01..db077f009d 100644 --- a/osu.Game.Rulesets.Osu/Skinning/Default/DrawableSliderPath.cs +++ b/osu.Game.Rulesets.Osu/Skinning/Default/DrawableSliderPath.cs @@ -4,7 +4,7 @@ using osu.Framework.Graphics.Lines; using osuTK.Graphics; -namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces +namespace osu.Game.Rulesets.Osu.Skinning.Default { public abstract class DrawableSliderPath : SmoothPath { diff --git a/osu.Game.Rulesets.Osu/Skinning/Default/ExplodePiece.cs b/osu.Game.Rulesets.Osu/Skinning/Default/ExplodePiece.cs index 09299a3622..510ed225a8 100644 --- a/osu.Game.Rulesets.Osu/Skinning/Default/ExplodePiece.cs +++ b/osu.Game.Rulesets.Osu/Skinning/Default/ExplodePiece.cs @@ -5,9 +5,10 @@ using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Game.Rulesets.Objects.Drawables; +using osu.Game.Rulesets.Osu.Objects; using osuTK; -namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces +namespace osu.Game.Rulesets.Osu.Skinning.Default { public class ExplodePiece : Container { diff --git a/osu.Game.Rulesets.Osu/Skinning/Default/FlashPiece.cs b/osu.Game.Rulesets.Osu/Skinning/Default/FlashPiece.cs index 038a2299e9..06ee64d8b3 100644 --- a/osu.Game.Rulesets.Osu/Skinning/Default/FlashPiece.cs +++ b/osu.Game.Rulesets.Osu/Skinning/Default/FlashPiece.cs @@ -3,10 +3,11 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; -using osuTK; using osu.Framework.Graphics.Shapes; +using osu.Game.Rulesets.Osu.Objects; +using osuTK; -namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces +namespace osu.Game.Rulesets.Osu.Skinning.Default { public class FlashPiece : Container { diff --git a/osu.Game.Rulesets.Osu/Skinning/Default/GlowPiece.cs b/osu.Game.Rulesets.Osu/Skinning/Default/GlowPiece.cs index 30937313fd..f5e01b802e 100644 --- a/osu.Game.Rulesets.Osu/Skinning/Default/GlowPiece.cs +++ b/osu.Game.Rulesets.Osu/Skinning/Default/GlowPiece.cs @@ -7,7 +7,7 @@ using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Sprites; using osu.Framework.Graphics.Textures; -namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces +namespace osu.Game.Rulesets.Osu.Skinning.Default { public class GlowPiece : Container { diff --git a/osu.Game.Rulesets.Osu/Skinning/Default/MainCirclePiece.cs b/osu.Game.Rulesets.Osu/Skinning/Default/MainCirclePiece.cs index 102166f8dd..fcbe4c1b28 100644 --- a/osu.Game.Rulesets.Osu/Skinning/Default/MainCirclePiece.cs +++ b/osu.Game.Rulesets.Osu/Skinning/Default/MainCirclePiece.cs @@ -6,10 +6,12 @@ using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Game.Rulesets.Objects.Drawables; +using osu.Game.Rulesets.Osu.Objects; +using osu.Game.Rulesets.Osu.Objects.Drawables; using osuTK; using osuTK.Graphics; -namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces +namespace osu.Game.Rulesets.Osu.Skinning.Default { public class MainCirclePiece : CompositeDrawable { diff --git a/osu.Game.Rulesets.Osu/Skinning/Default/ManualSliderBody.cs b/osu.Game.Rulesets.Osu/Skinning/Default/ManualSliderBody.cs index d69df1d5c2..d73c94eb9b 100644 --- a/osu.Game.Rulesets.Osu/Skinning/Default/ManualSliderBody.cs +++ b/osu.Game.Rulesets.Osu/Skinning/Default/ManualSliderBody.cs @@ -4,7 +4,7 @@ using System.Collections.Generic; using osuTK; -namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces +namespace osu.Game.Rulesets.Osu.Skinning.Default { /// /// A with the ability to set the drawn vertices manually. diff --git a/osu.Game.Rulesets.Osu/Skinning/Default/NumberPiece.cs b/osu.Game.Rulesets.Osu/Skinning/Default/NumberPiece.cs index 7c94568835..bea6186501 100644 --- a/osu.Game.Rulesets.Osu/Skinning/Default/NumberPiece.cs +++ b/osu.Game.Rulesets.Osu/Skinning/Default/NumberPiece.cs @@ -5,12 +5,12 @@ using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Effects; -using osu.Game.Graphics.Sprites; -using osuTK.Graphics; using osu.Game.Graphics; +using osu.Game.Graphics.Sprites; using osu.Game.Skinning; +using osuTK.Graphics; -namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces +namespace osu.Game.Rulesets.Osu.Skinning.Default { public class NumberPiece : Container { diff --git a/osu.Game.Rulesets.Osu/Skinning/Default/PlaySliderBody.cs b/osu.Game.Rulesets.Osu/Skinning/Default/PlaySliderBody.cs index 29dff53f54..e77c93c721 100644 --- a/osu.Game.Rulesets.Osu/Skinning/Default/PlaySliderBody.cs +++ b/osu.Game.Rulesets.Osu/Skinning/Default/PlaySliderBody.cs @@ -5,11 +5,12 @@ using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.Osu.Configuration; -using osu.Game.Rulesets.Osu.Skinning; +using osu.Game.Rulesets.Osu.Objects; +using osu.Game.Rulesets.Osu.Objects.Drawables; using osu.Game.Skinning; using osuTK.Graphics; -namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces +namespace osu.Game.Rulesets.Osu.Skinning.Default { public abstract class PlaySliderBody : SnakingSliderBody { diff --git a/osu.Game.Rulesets.Osu/Skinning/Default/ReverseArrowPiece.cs b/osu.Game.Rulesets.Osu/Skinning/Default/ReverseArrowPiece.cs index ae43006e76..0009ffc586 100644 --- a/osu.Game.Rulesets.Osu/Skinning/Default/ReverseArrowPiece.cs +++ b/osu.Game.Rulesets.Osu/Skinning/Default/ReverseArrowPiece.cs @@ -1,17 +1,18 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using osu.Framework.Allocation; using osu.Framework.Audio.Track; using osu.Framework.Graphics; -using osuTK; using osu.Framework.Graphics.Sprites; using osu.Game.Beatmaps.ControlPoints; using osu.Game.Graphics.Containers; -using osu.Game.Skinning; -using osu.Framework.Allocation; using osu.Game.Rulesets.Objects.Drawables; +using osu.Game.Rulesets.Osu.Objects; +using osu.Game.Skinning; +using osuTK; -namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces +namespace osu.Game.Rulesets.Osu.Skinning.Default { public class ReverseArrowPiece : BeatSyncedContainer { diff --git a/osu.Game.Rulesets.Osu/Skinning/Default/RingPiece.cs b/osu.Game.Rulesets.Osu/Skinning/Default/RingPiece.cs index 619fea73bc..7f10a7bf56 100644 --- a/osu.Game.Rulesets.Osu/Skinning/Default/RingPiece.cs +++ b/osu.Game.Rulesets.Osu/Skinning/Default/RingPiece.cs @@ -3,11 +3,12 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Shapes; +using osu.Game.Rulesets.Osu.Objects; using osuTK; using osuTK.Graphics; -using osu.Framework.Graphics.Shapes; -namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces +namespace osu.Game.Rulesets.Osu.Skinning.Default { public class RingPiece : CircularContainer { diff --git a/osu.Game.Rulesets.Osu/Skinning/Default/SliderBall.cs b/osu.Game.Rulesets.Osu/Skinning/Default/SliderBall.cs index ca5ca7ac59..a96beb66d4 100644 --- a/osu.Game.Rulesets.Osu/Skinning/Default/SliderBall.cs +++ b/osu.Game.Rulesets.Osu/Skinning/Default/SliderBall.cs @@ -10,15 +10,16 @@ using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; using osu.Framework.Input; using osu.Framework.Input.Events; +using osu.Game.Graphics; using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.Objects.Types; -using osu.Game.Rulesets.Osu.Skinning; -using osuTK.Graphics; +using osu.Game.Rulesets.Osu.Objects; +using osu.Game.Rulesets.Osu.Objects.Drawables; using osu.Game.Skinning; using osuTK; -using osu.Game.Graphics; +using osuTK.Graphics; -namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces +namespace osu.Game.Rulesets.Osu.Skinning.Default { public class SliderBall : CircularContainer, ISliderProgress, IRequireHighFrequencyMousePosition, IHasAccentColour { diff --git a/osu.Game.Rulesets.Osu/Skinning/Default/SliderBody.cs b/osu.Game.Rulesets.Osu/Skinning/Default/SliderBody.cs index 8758a4a066..7e6df759f8 100644 --- a/osu.Game.Rulesets.Osu/Skinning/Default/SliderBody.cs +++ b/osu.Game.Rulesets.Osu/Skinning/Default/SliderBody.cs @@ -9,7 +9,7 @@ using osu.Framework.Graphics.Lines; using osuTK; using osuTK.Graphics; -namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces +namespace osu.Game.Rulesets.Osu.Skinning.Default { public abstract class SliderBody : CompositeDrawable { diff --git a/osu.Game.Rulesets.Osu/Skinning/Default/SnakingSliderBody.cs b/osu.Game.Rulesets.Osu/Skinning/Default/SnakingSliderBody.cs index 8835a0d84a..ed4e04184b 100644 --- a/osu.Game.Rulesets.Osu/Skinning/Default/SnakingSliderBody.cs +++ b/osu.Game.Rulesets.Osu/Skinning/Default/SnakingSliderBody.cs @@ -8,9 +8,11 @@ using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.Objects.Types; +using osu.Game.Rulesets.Osu.Objects; +using osu.Game.Rulesets.Osu.Objects.Drawables; using osuTK; -namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces +namespace osu.Game.Rulesets.Osu.Skinning.Default { /// /// A which changes its curve depending on the snaking progress. diff --git a/osu.Game.Rulesets.Osu/Skinning/Default/SpinnerBonusDisplay.cs b/osu.Game.Rulesets.Osu/Skinning/Default/SpinnerBonusDisplay.cs index f483bb1b26..c0db6228ef 100644 --- a/osu.Game.Rulesets.Osu/Skinning/Default/SpinnerBonusDisplay.cs +++ b/osu.Game.Rulesets.Osu/Skinning/Default/SpinnerBonusDisplay.cs @@ -5,8 +5,9 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Game.Graphics; using osu.Game.Graphics.Sprites; +using osu.Game.Rulesets.Osu.Objects; -namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces +namespace osu.Game.Rulesets.Osu.Skinning.Default { /// /// Shows incremental bonus score achieved for a spinner. diff --git a/osu.Game.Rulesets.Osu/Skinning/Default/SpinnerFill.cs b/osu.Game.Rulesets.Osu/Skinning/Default/SpinnerFill.cs index 043bc5618c..f574ae589e 100644 --- a/osu.Game.Rulesets.Osu/Skinning/Default/SpinnerFill.cs +++ b/osu.Game.Rulesets.Osu/Skinning/Default/SpinnerFill.cs @@ -8,7 +8,7 @@ using osu.Framework.Graphics.Shapes; using osu.Game.Graphics; using osuTK.Graphics; -namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces +namespace osu.Game.Rulesets.Osu.Skinning.Default { public class SpinnerFill : CircularContainer, IHasAccentColour { diff --git a/osu.Game.Rulesets.Osu/Skinning/Default/SpinnerRotationTracker.cs b/osu.Game.Rulesets.Osu/Skinning/Default/SpinnerRotationTracker.cs index f82003edb8..9393a589eb 100644 --- a/osu.Game.Rulesets.Osu/Skinning/Default/SpinnerRotationTracker.cs +++ b/osu.Game.Rulesets.Osu/Skinning/Default/SpinnerRotationTracker.cs @@ -9,10 +9,11 @@ using osu.Framework.Graphics.Containers; using osu.Framework.Input.Events; using osu.Framework.Utils; using osu.Game.Rulesets.Objects.Drawables; +using osu.Game.Rulesets.Osu.Objects.Drawables; using osu.Game.Screens.Play; using osuTK; -namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces +namespace osu.Game.Rulesets.Osu.Skinning.Default { public class SpinnerRotationTracker : CircularContainer { diff --git a/osu.Game.Rulesets.Osu/Skinning/Default/SpinnerSpmCounter.cs b/osu.Game.Rulesets.Osu/Skinning/Default/SpinnerSpmCounter.cs index 80ab03c45c..e5952ecf97 100644 --- a/osu.Game.Rulesets.Osu/Skinning/Default/SpinnerSpmCounter.cs +++ b/osu.Game.Rulesets.Osu/Skinning/Default/SpinnerSpmCounter.cs @@ -10,7 +10,7 @@ using osu.Framework.Utils; using osu.Game.Graphics; using osu.Game.Graphics.Sprites; -namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces +namespace osu.Game.Rulesets.Osu.Skinning.Default { public class SpinnerSpmCounter : Container { diff --git a/osu.Game.Rulesets.Osu/Skinning/Default/SpinnerTicks.cs b/osu.Game.Rulesets.Osu/Skinning/Default/SpinnerTicks.cs index ba7e8eae6f..e518ae1da8 100644 --- a/osu.Game.Rulesets.Osu/Skinning/Default/SpinnerTicks.cs +++ b/osu.Game.Rulesets.Osu/Skinning/Default/SpinnerTicks.cs @@ -7,12 +7,12 @@ using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Effects; -using osuTK; -using osuTK.Graphics; using osu.Framework.Graphics.Shapes; using osu.Game.Graphics; +using osuTK; +using osuTK.Graphics; -namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces +namespace osu.Game.Rulesets.Osu.Skinning.Default { public class SpinnerTicks : Container, IHasAccentColour { diff --git a/osu.Game.Rulesets.Osu/Skinning/Default/TrianglesPiece.cs b/osu.Game.Rulesets.Osu/Skinning/Default/TrianglesPiece.cs index 53dc7ecea3..fa23c60d57 100644 --- a/osu.Game.Rulesets.Osu/Skinning/Default/TrianglesPiece.cs +++ b/osu.Game.Rulesets.Osu/Skinning/Default/TrianglesPiece.cs @@ -3,7 +3,7 @@ using osu.Game.Graphics.Backgrounds; -namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces +namespace osu.Game.Rulesets.Osu.Skinning.Default { public class TrianglesPiece : Triangles { diff --git a/osu.Game.Rulesets.Osu/Skinning/Legacy/LegacyCursor.cs b/osu.Game.Rulesets.Osu/Skinning/Legacy/LegacyCursor.cs index e96bd29ad5..314139d02a 100644 --- a/osu.Game.Rulesets.Osu/Skinning/Legacy/LegacyCursor.cs +++ b/osu.Game.Rulesets.Osu/Skinning/Legacy/LegacyCursor.cs @@ -3,11 +3,11 @@ using osu.Framework.Allocation; using osu.Framework.Graphics; -using osu.Game.Skinning; using osu.Game.Rulesets.Osu.UI.Cursor; +using osu.Game.Skinning; using osuTK; -namespace osu.Game.Rulesets.Osu.Skinning +namespace osu.Game.Rulesets.Osu.Skinning.Legacy { public class LegacyCursor : OsuCursorSprite { diff --git a/osu.Game.Rulesets.Osu/Skinning/Legacy/LegacyCursorTrail.cs b/osu.Game.Rulesets.Osu/Skinning/Legacy/LegacyCursorTrail.cs index e6cd7bc59d..f18d3191ca 100644 --- a/osu.Game.Rulesets.Osu/Skinning/Legacy/LegacyCursorTrail.cs +++ b/osu.Game.Rulesets.Osu/Skinning/Legacy/LegacyCursorTrail.cs @@ -10,7 +10,7 @@ using osu.Game.Configuration; using osu.Game.Rulesets.Osu.UI.Cursor; using osu.Game.Skinning; -namespace osu.Game.Rulesets.Osu.Skinning +namespace osu.Game.Rulesets.Osu.Skinning.Legacy { public class LegacyCursorTrail : CursorTrail { diff --git a/osu.Game.Rulesets.Osu/Skinning/Legacy/LegacyMainCirclePiece.cs b/osu.Game.Rulesets.Osu/Skinning/Legacy/LegacyMainCirclePiece.cs index 21af9a479e..545e80a709 100644 --- a/osu.Game.Rulesets.Osu/Skinning/Legacy/LegacyMainCirclePiece.cs +++ b/osu.Game.Rulesets.Osu/Skinning/Legacy/LegacyMainCirclePiece.cs @@ -17,7 +17,7 @@ using osuTK; using osuTK.Graphics; using static osu.Game.Skinning.LegacySkinConfiguration; -namespace osu.Game.Rulesets.Osu.Skinning +namespace osu.Game.Rulesets.Osu.Skinning.Legacy { public class LegacyMainCirclePiece : CompositeDrawable { diff --git a/osu.Game.Rulesets.Osu/Skinning/Legacy/LegacyNewStyleSpinner.cs b/osu.Game.Rulesets.Osu/Skinning/Legacy/LegacyNewStyleSpinner.cs index 05f4c8e307..efeca53969 100644 --- a/osu.Game.Rulesets.Osu/Skinning/Legacy/LegacyNewStyleSpinner.cs +++ b/osu.Game.Rulesets.Osu/Skinning/Legacy/LegacyNewStyleSpinner.cs @@ -13,7 +13,7 @@ using osu.Game.Skinning; using osuTK; using osuTK.Graphics; -namespace osu.Game.Rulesets.Osu.Skinning +namespace osu.Game.Rulesets.Osu.Skinning.Legacy { /// /// Legacy skinned spinner with two main spinning layers, one fixed overlay and one final spinning overlay. diff --git a/osu.Game.Rulesets.Osu/Skinning/Legacy/LegacyOldStyleSpinner.cs b/osu.Game.Rulesets.Osu/Skinning/Legacy/LegacyOldStyleSpinner.cs index fba802f085..4e07cb60b3 100644 --- a/osu.Game.Rulesets.Osu/Skinning/Legacy/LegacyOldStyleSpinner.cs +++ b/osu.Game.Rulesets.Osu/Skinning/Legacy/LegacyOldStyleSpinner.cs @@ -13,7 +13,7 @@ using osu.Game.Rulesets.Osu.Objects.Drawables; using osu.Game.Skinning; using osuTK; -namespace osu.Game.Rulesets.Osu.Skinning +namespace osu.Game.Rulesets.Osu.Skinning.Legacy { /// /// Legacy skinned spinner with one main spinning layer and a background layer. diff --git a/osu.Game.Rulesets.Osu/Skinning/Legacy/LegacySliderBall.cs b/osu.Game.Rulesets.Osu/Skinning/Legacy/LegacySliderBall.cs index 836069013d..1a8c5ada1b 100644 --- a/osu.Game.Rulesets.Osu/Skinning/Legacy/LegacySliderBall.cs +++ b/osu.Game.Rulesets.Osu/Skinning/Legacy/LegacySliderBall.cs @@ -8,7 +8,7 @@ using osu.Framework.Graphics.Sprites; using osu.Game.Skinning; using osuTK.Graphics; -namespace osu.Game.Rulesets.Osu.Skinning +namespace osu.Game.Rulesets.Osu.Skinning.Legacy { public class LegacySliderBall : CompositeDrawable { diff --git a/osu.Game.Rulesets.Osu/Skinning/Legacy/LegacySliderBody.cs b/osu.Game.Rulesets.Osu/Skinning/Legacy/LegacySliderBody.cs index aad8b189d9..744ded37c9 100644 --- a/osu.Game.Rulesets.Osu/Skinning/Legacy/LegacySliderBody.cs +++ b/osu.Game.Rulesets.Osu/Skinning/Legacy/LegacySliderBody.cs @@ -5,10 +5,10 @@ using System; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Utils; using osu.Game.Rulesets.Osu.Objects; -using osu.Game.Rulesets.Osu.Objects.Drawables.Pieces; +using osu.Game.Rulesets.Osu.Skinning.Default; using osuTK.Graphics; -namespace osu.Game.Rulesets.Osu.Skinning +namespace osu.Game.Rulesets.Osu.Skinning.Legacy { public class LegacySliderBody : PlaySliderBody { diff --git a/osu.Game.Rulesets.Osu/Skinning/Legacy/LegacySpinner.cs b/osu.Game.Rulesets.Osu/Skinning/Legacy/LegacySpinner.cs index 5aa136cf7e..ec7ecb0d28 100644 --- a/osu.Game.Rulesets.Osu/Skinning/Legacy/LegacySpinner.cs +++ b/osu.Game.Rulesets.Osu/Skinning/Legacy/LegacySpinner.cs @@ -12,7 +12,7 @@ using osu.Game.Rulesets.Osu.Objects.Drawables; using osu.Game.Skinning; using osuTK; -namespace osu.Game.Rulesets.Osu.Skinning +namespace osu.Game.Rulesets.Osu.Skinning.Legacy { public abstract class LegacySpinner : CompositeDrawable { diff --git a/osu.Game.Rulesets.Osu/Skinning/OsuLegacySkinTransformer.cs b/osu.Game.Rulesets.Osu/Skinning/OsuLegacySkinTransformer.cs index 78bc26eff7..70abfa1ac9 100644 --- a/osu.Game.Rulesets.Osu/Skinning/OsuLegacySkinTransformer.cs +++ b/osu.Game.Rulesets.Osu/Skinning/OsuLegacySkinTransformer.cs @@ -4,6 +4,7 @@ using System; using osu.Framework.Bindables; using osu.Framework.Graphics; +using osu.Game.Rulesets.Osu.Skinning.Legacy; using osu.Game.Skinning; using osuTK; From 626956febdeb3505b91b4aab168f013c1f15060e Mon Sep 17 00:00:00 2001 From: ekrctb Date: Fri, 4 Dec 2020 20:25:12 +0900 Subject: [PATCH 129/184] Move some files from Drawables to Skinning.Default namespace --- .../Drawables => Skinning/Default}/SpinnerBackgroundLayer.cs | 0 .../{Objects/Drawables => Skinning/Default}/SpinnerCentreLayer.cs | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename osu.Game.Rulesets.Osu/{Objects/Drawables => Skinning/Default}/SpinnerBackgroundLayer.cs (100%) rename osu.Game.Rulesets.Osu/{Objects/Drawables => Skinning/Default}/SpinnerCentreLayer.cs (100%) diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/SpinnerBackgroundLayer.cs b/osu.Game.Rulesets.Osu/Skinning/Default/SpinnerBackgroundLayer.cs similarity index 100% rename from osu.Game.Rulesets.Osu/Objects/Drawables/SpinnerBackgroundLayer.cs rename to osu.Game.Rulesets.Osu/Skinning/Default/SpinnerBackgroundLayer.cs diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/SpinnerCentreLayer.cs b/osu.Game.Rulesets.Osu/Skinning/Default/SpinnerCentreLayer.cs similarity index 100% rename from osu.Game.Rulesets.Osu/Objects/Drawables/SpinnerCentreLayer.cs rename to osu.Game.Rulesets.Osu/Skinning/Default/SpinnerCentreLayer.cs From 0ed9989a8203bde71733773bb43e79399b28cd03 Mon Sep 17 00:00:00 2001 From: ekrctb Date: Fri, 4 Dec 2020 20:25:49 +0900 Subject: [PATCH 130/184] Adjust namespace --- .../Skinning/Default/SpinnerBackgroundLayer.cs | 3 +-- osu.Game.Rulesets.Osu/Skinning/Default/SpinnerCentreLayer.cs | 4 ++-- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Skinning/Default/SpinnerBackgroundLayer.cs b/osu.Game.Rulesets.Osu/Skinning/Default/SpinnerBackgroundLayer.cs index 10a7d33073..f8a6e1d3c9 100644 --- a/osu.Game.Rulesets.Osu/Skinning/Default/SpinnerBackgroundLayer.cs +++ b/osu.Game.Rulesets.Osu/Skinning/Default/SpinnerBackgroundLayer.cs @@ -5,9 +5,8 @@ using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Game.Graphics; using osu.Game.Rulesets.Objects.Drawables; -using osu.Game.Rulesets.Osu.Skinning.Default; -namespace osu.Game.Rulesets.Osu.Objects.Drawables +namespace osu.Game.Rulesets.Osu.Skinning.Default { public class SpinnerBackgroundLayer : SpinnerFill { diff --git a/osu.Game.Rulesets.Osu/Skinning/Default/SpinnerCentreLayer.cs b/osu.Game.Rulesets.Osu/Skinning/Default/SpinnerCentreLayer.cs index 0c38c3a855..67b5ed5410 100644 --- a/osu.Game.Rulesets.Osu/Skinning/Default/SpinnerCentreLayer.cs +++ b/osu.Game.Rulesets.Osu/Skinning/Default/SpinnerCentreLayer.cs @@ -9,11 +9,11 @@ using osu.Framework.Graphics.Sprites; using osu.Framework.Utils; using osu.Game.Graphics; using osu.Game.Rulesets.Objects.Drawables; -using osu.Game.Rulesets.Osu.Skinning.Default; +using osu.Game.Rulesets.Osu.Objects.Drawables; using osuTK; using osuTK.Graphics; -namespace osu.Game.Rulesets.Osu.Objects.Drawables +namespace osu.Game.Rulesets.Osu.Skinning.Default { public class SpinnerCentreLayer : CompositeDrawable, IHasAccentColour { From 7c0edb796ee352cbc96950e152d7308dade7e1f5 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 4 Dec 2020 20:49:18 +0900 Subject: [PATCH 131/184] Always confine mouse to screen when running fullscreen --- osu.Game/Input/ConfineMouseTracker.cs | 15 +++++++++++---- osu.Game/Input/OsuConfineMouseMode.cs | 5 ----- 2 files changed, 11 insertions(+), 9 deletions(-) diff --git a/osu.Game/Input/ConfineMouseTracker.cs b/osu.Game/Input/ConfineMouseTracker.cs index 3dadae6317..75d9c8debb 100644 --- a/osu.Game/Input/ConfineMouseTracker.cs +++ b/osu.Game/Input/ConfineMouseTracker.cs @@ -18,6 +18,8 @@ namespace osu.Game.Input public class ConfineMouseTracker : Component { private Bindable frameworkConfineMode; + private Bindable frameworkWindowMode; + private Bindable osuConfineMode; private IBindable localUserPlaying; @@ -25,6 +27,9 @@ namespace osu.Game.Input private void load(OsuGame game, FrameworkConfigManager frameworkConfigManager, OsuConfigManager osuConfigManager) { frameworkConfineMode = frameworkConfigManager.GetBindable(FrameworkSetting.ConfineMouseMode); + frameworkWindowMode = frameworkConfigManager.GetBindable(FrameworkSetting.WindowMode); + frameworkWindowMode.BindValueChanged(_ => updateConfineMode()); + osuConfineMode = osuConfigManager.GetBindable(OsuSetting.ConfineMouseMode); localUserPlaying = game.LocalUserPlaying.GetBoundCopy(); @@ -38,16 +43,18 @@ namespace osu.Game.Input if (frameworkConfineMode.Disabled) return; + if (frameworkWindowMode.Value == WindowMode.Fullscreen) + { + frameworkConfineMode.Value = ConfineMouseMode.Fullscreen; + return; + } + switch (osuConfineMode.Value) { case OsuConfineMouseMode.Never: frameworkConfineMode.Value = ConfineMouseMode.Never; break; - case OsuConfineMouseMode.Fullscreen: - frameworkConfineMode.Value = ConfineMouseMode.Fullscreen; - break; - case OsuConfineMouseMode.DuringGameplay: frameworkConfineMode.Value = localUserPlaying.Value ? ConfineMouseMode.Always : ConfineMouseMode.Never; break; diff --git a/osu.Game/Input/OsuConfineMouseMode.cs b/osu.Game/Input/OsuConfineMouseMode.cs index 32b456395c..a4a1c9eb46 100644 --- a/osu.Game/Input/OsuConfineMouseMode.cs +++ b/osu.Game/Input/OsuConfineMouseMode.cs @@ -17,11 +17,6 @@ namespace osu.Game.Input /// Never, - /// - /// The mouse cursor will be locked to the window bounds while in fullscreen mode. - /// - Fullscreen, - /// /// The mouse cursor will be locked to the window bounds during gameplay, /// but may otherwise move freely. From 0a745144e398c897d31293e12b0e0cc1befd9545 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Sat, 5 Dec 2020 13:11:52 +0100 Subject: [PATCH 132/184] Disable confine mode dropdown when full-screen After hard-locking the mouse confine mode to `Always` in full-screen to prevent confine issues from popping up, the confine mode dropdown in settings had confusing UX due to seemingly having no effect when full-screen. --- osu.Game/Input/ConfineMouseTracker.cs | 31 ++++++++++++++++++--------- 1 file changed, 21 insertions(+), 10 deletions(-) diff --git a/osu.Game/Input/ConfineMouseTracker.cs b/osu.Game/Input/ConfineMouseTracker.cs index 75d9c8debb..739bfaadab 100644 --- a/osu.Game/Input/ConfineMouseTracker.cs +++ b/osu.Game/Input/ConfineMouseTracker.cs @@ -28,27 +28,38 @@ namespace osu.Game.Input { frameworkConfineMode = frameworkConfigManager.GetBindable(FrameworkSetting.ConfineMouseMode); frameworkWindowMode = frameworkConfigManager.GetBindable(FrameworkSetting.WindowMode); - frameworkWindowMode.BindValueChanged(_ => updateConfineMode()); + frameworkWindowMode.BindValueChanged(_ => updateGameConfineMode()); osuConfineMode = osuConfigManager.GetBindable(OsuSetting.ConfineMouseMode); localUserPlaying = game.LocalUserPlaying.GetBoundCopy(); - osuConfineMode.ValueChanged += _ => updateConfineMode(); - localUserPlaying.BindValueChanged(_ => updateConfineMode(), true); + osuConfineMode.ValueChanged += _ => updateFrameworkConfineMode(); + localUserPlaying.BindValueChanged(_ => updateFrameworkConfineMode(), true); } - private void updateConfineMode() + private LeasedBindable leasedOsuConfineMode; + + private void updateGameConfineMode() + { + if (frameworkWindowMode.Value == WindowMode.Fullscreen && leasedOsuConfineMode == null) + { + leasedOsuConfineMode = osuConfineMode.BeginLease(true); + leasedOsuConfineMode.Value = OsuConfineMouseMode.Always; + } + + if (frameworkWindowMode.Value != WindowMode.Fullscreen && leasedOsuConfineMode != null) + { + leasedOsuConfineMode.Return(); + leasedOsuConfineMode = null; + } + } + + private void updateFrameworkConfineMode() { // confine mode is unavailable on some platforms if (frameworkConfineMode.Disabled) return; - if (frameworkWindowMode.Value == WindowMode.Fullscreen) - { - frameworkConfineMode.Value = ConfineMouseMode.Fullscreen; - return; - } - switch (osuConfineMode.Value) { case OsuConfineMouseMode.Never: From 15ce7bacf1fcc319916f9365643f5ef1e73f26d6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Sat, 5 Dec 2020 14:12:15 +0100 Subject: [PATCH 133/184] Add test coverage for confine functionality Due to growing levels of complexity around confine logic. --- .../Input/ConfineMouseTrackerTest.cs | 114 ++++++++++++++++++ 1 file changed, 114 insertions(+) create mode 100644 osu.Game.Tests/Input/ConfineMouseTrackerTest.cs diff --git a/osu.Game.Tests/Input/ConfineMouseTrackerTest.cs b/osu.Game.Tests/Input/ConfineMouseTrackerTest.cs new file mode 100644 index 0000000000..42f5209643 --- /dev/null +++ b/osu.Game.Tests/Input/ConfineMouseTrackerTest.cs @@ -0,0 +1,114 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using NUnit.Framework; +using osu.Framework.Allocation; +using osu.Framework.Configuration; +using osu.Framework.Input; +using osu.Framework.Testing; +using osu.Game.Configuration; +using osu.Game.Input; +using osu.Game.Tests.Visual.Navigation; + +namespace osu.Game.Tests.Input +{ + [HeadlessTest] + public class ConfineMouseTrackerTest : OsuGameTestScene + { + [Resolved] + private FrameworkConfigManager frameworkConfigManager { get; set; } + + [Resolved] + private OsuConfigManager osuConfigManager { get; set; } + + [TestCase(WindowMode.Windowed)] + [TestCase(WindowMode.Borderless)] + public void TestDisableConfining(WindowMode windowMode) + { + setWindowModeTo(windowMode); + setGameSideModeTo(OsuConfineMouseMode.Never); + + gameSideConfineModeDisabled(false); + + setLocalUserPlayingTo(false); + frameworkSideModeIs(ConfineMouseMode.Never); + + setLocalUserPlayingTo(true); + frameworkSideModeIs(ConfineMouseMode.Never); + } + + [TestCase(WindowMode.Windowed)] + [TestCase(WindowMode.Borderless)] + public void TestConfiningDuringGameplay(WindowMode windowMode) + { + setWindowModeTo(windowMode); + setGameSideModeTo(OsuConfineMouseMode.DuringGameplay); + + gameSideConfineModeDisabled(false); + + setLocalUserPlayingTo(false); + frameworkSideModeIs(ConfineMouseMode.Never); + + setLocalUserPlayingTo(true); + frameworkSideModeIs(ConfineMouseMode.Always); + } + + [TestCase(WindowMode.Windowed)] + [TestCase(WindowMode.Borderless)] + public void TestConfineAlwaysUserSetting(WindowMode windowMode) + { + setWindowModeTo(windowMode); + setGameSideModeTo(OsuConfineMouseMode.Always); + + gameSideConfineModeDisabled(false); + + setLocalUserPlayingTo(false); + frameworkSideModeIs(ConfineMouseMode.Always); + + setLocalUserPlayingTo(true); + frameworkSideModeIs(ConfineMouseMode.Always); + } + + [Test] + public void TestConfineAlwaysInFullscreen() + { + setGameSideModeTo(OsuConfineMouseMode.Never); + + setWindowModeTo(WindowMode.Fullscreen); + gameSideConfineModeDisabled(true); + + setLocalUserPlayingTo(false); + frameworkSideModeIs(ConfineMouseMode.Always); + + setLocalUserPlayingTo(true); + frameworkSideModeIs(ConfineMouseMode.Always); + + setWindowModeTo(WindowMode.Windowed); + + // old state is restored + gameSideModeIs(OsuConfineMouseMode.Never); + frameworkSideModeIs(ConfineMouseMode.Never); + gameSideConfineModeDisabled(false); + } + + private void setWindowModeTo(WindowMode mode) + // needs to go through .GetBindable().Value instead of .Set() due to default overrides + => AddStep($"make window {mode}", () => frameworkConfigManager.GetBindable(FrameworkSetting.WindowMode).Value = mode); + + private void setGameSideModeTo(OsuConfineMouseMode mode) + => AddStep($"set {mode} game-side", () => Game.LocalConfig.Set(OsuSetting.ConfineMouseMode, mode)); + + private void setLocalUserPlayingTo(bool playing) + => AddStep($"local user {(playing ? "playing" : "not playing")}", () => Game.LocalUserPlaying.Value = playing); + + private void gameSideModeIs(OsuConfineMouseMode mode) + => AddAssert($"mode is {mode} game-side", () => Game.LocalConfig.Get(OsuSetting.ConfineMouseMode) == mode); + + private void frameworkSideModeIs(ConfineMouseMode mode) + => AddAssert($"mode is {mode} framework-side", () => frameworkConfigManager.Get(FrameworkSetting.ConfineMouseMode) == mode); + + private void gameSideConfineModeDisabled(bool disabled) + => AddAssert($"game-side confine mode {(disabled ? "disabled" : "enabled")}", + () => Game.LocalConfig.GetBindable(OsuSetting.ConfineMouseMode).Disabled == disabled); + } +} From 08f23cc4249694f0a86aecf6eac545b5027e1796 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Sat, 5 Dec 2020 22:07:39 +0100 Subject: [PATCH 134/184] Revert leasing logic --- .../Input/ConfineMouseTrackerTest.cs | 16 ++-------- osu.Game/Input/ConfineMouseTracker.cs | 31 ++++++------------- 2 files changed, 12 insertions(+), 35 deletions(-) diff --git a/osu.Game.Tests/Input/ConfineMouseTrackerTest.cs b/osu.Game.Tests/Input/ConfineMouseTrackerTest.cs index 42f5209643..b90382488f 100644 --- a/osu.Game.Tests/Input/ConfineMouseTrackerTest.cs +++ b/osu.Game.Tests/Input/ConfineMouseTrackerTest.cs @@ -28,8 +28,6 @@ namespace osu.Game.Tests.Input setWindowModeTo(windowMode); setGameSideModeTo(OsuConfineMouseMode.Never); - gameSideConfineModeDisabled(false); - setLocalUserPlayingTo(false); frameworkSideModeIs(ConfineMouseMode.Never); @@ -44,8 +42,6 @@ namespace osu.Game.Tests.Input setWindowModeTo(windowMode); setGameSideModeTo(OsuConfineMouseMode.DuringGameplay); - gameSideConfineModeDisabled(false); - setLocalUserPlayingTo(false); frameworkSideModeIs(ConfineMouseMode.Never); @@ -60,8 +56,6 @@ namespace osu.Game.Tests.Input setWindowModeTo(windowMode); setGameSideModeTo(OsuConfineMouseMode.Always); - gameSideConfineModeDisabled(false); - setLocalUserPlayingTo(false); frameworkSideModeIs(ConfineMouseMode.Always); @@ -75,20 +69,18 @@ namespace osu.Game.Tests.Input setGameSideModeTo(OsuConfineMouseMode.Never); setWindowModeTo(WindowMode.Fullscreen); - gameSideConfineModeDisabled(true); setLocalUserPlayingTo(false); - frameworkSideModeIs(ConfineMouseMode.Always); + frameworkSideModeIs(ConfineMouseMode.Fullscreen); setLocalUserPlayingTo(true); - frameworkSideModeIs(ConfineMouseMode.Always); + frameworkSideModeIs(ConfineMouseMode.Fullscreen); setWindowModeTo(WindowMode.Windowed); // old state is restored gameSideModeIs(OsuConfineMouseMode.Never); frameworkSideModeIs(ConfineMouseMode.Never); - gameSideConfineModeDisabled(false); } private void setWindowModeTo(WindowMode mode) @@ -106,9 +98,5 @@ namespace osu.Game.Tests.Input private void frameworkSideModeIs(ConfineMouseMode mode) => AddAssert($"mode is {mode} framework-side", () => frameworkConfigManager.Get(FrameworkSetting.ConfineMouseMode) == mode); - - private void gameSideConfineModeDisabled(bool disabled) - => AddAssert($"game-side confine mode {(disabled ? "disabled" : "enabled")}", - () => Game.LocalConfig.GetBindable(OsuSetting.ConfineMouseMode).Disabled == disabled); } } diff --git a/osu.Game/Input/ConfineMouseTracker.cs b/osu.Game/Input/ConfineMouseTracker.cs index 739bfaadab..75d9c8debb 100644 --- a/osu.Game/Input/ConfineMouseTracker.cs +++ b/osu.Game/Input/ConfineMouseTracker.cs @@ -28,38 +28,27 @@ namespace osu.Game.Input { frameworkConfineMode = frameworkConfigManager.GetBindable(FrameworkSetting.ConfineMouseMode); frameworkWindowMode = frameworkConfigManager.GetBindable(FrameworkSetting.WindowMode); - frameworkWindowMode.BindValueChanged(_ => updateGameConfineMode()); + frameworkWindowMode.BindValueChanged(_ => updateConfineMode()); osuConfineMode = osuConfigManager.GetBindable(OsuSetting.ConfineMouseMode); localUserPlaying = game.LocalUserPlaying.GetBoundCopy(); - osuConfineMode.ValueChanged += _ => updateFrameworkConfineMode(); - localUserPlaying.BindValueChanged(_ => updateFrameworkConfineMode(), true); + osuConfineMode.ValueChanged += _ => updateConfineMode(); + localUserPlaying.BindValueChanged(_ => updateConfineMode(), true); } - private LeasedBindable leasedOsuConfineMode; - - private void updateGameConfineMode() - { - if (frameworkWindowMode.Value == WindowMode.Fullscreen && leasedOsuConfineMode == null) - { - leasedOsuConfineMode = osuConfineMode.BeginLease(true); - leasedOsuConfineMode.Value = OsuConfineMouseMode.Always; - } - - if (frameworkWindowMode.Value != WindowMode.Fullscreen && leasedOsuConfineMode != null) - { - leasedOsuConfineMode.Return(); - leasedOsuConfineMode = null; - } - } - - private void updateFrameworkConfineMode() + private void updateConfineMode() { // confine mode is unavailable on some platforms if (frameworkConfineMode.Disabled) return; + if (frameworkWindowMode.Value == WindowMode.Fullscreen) + { + frameworkConfineMode.Value = ConfineMouseMode.Fullscreen; + return; + } + switch (osuConfineMode.Value) { case OsuConfineMouseMode.Never: From 71edada623d017be357d397f495d87ca6babd933 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Sat, 5 Dec 2020 22:13:51 +0100 Subject: [PATCH 135/184] Hide confine setting entirely in fullscreen --- .../Overlays/Settings/Sections/Input/MouseSettings.cs | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/osu.Game/Overlays/Settings/Sections/Input/MouseSettings.cs b/osu.Game/Overlays/Settings/Sections/Input/MouseSettings.cs index b54ad9a641..ec0ce08004 100644 --- a/osu.Game/Overlays/Settings/Sections/Input/MouseSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Input/MouseSettings.cs @@ -20,6 +20,9 @@ namespace osu.Game.Overlays.Settings.Sections.Input private Bindable sensitivityBindable = new BindableDouble(); private Bindable ignoredInputHandlers; + private Bindable windowMode; + private SettingsEnumDropdown confineMouseModeSetting; + [BackgroundDependencyLoader] private void load(OsuConfigManager osuConfig, FrameworkConfigManager config) { @@ -30,6 +33,9 @@ namespace osu.Game.Overlays.Settings.Sections.Input configSensitivity.BindValueChanged(val => sensitivityBindable.Value = val.NewValue); sensitivityBindable.BindValueChanged(val => configSensitivity.Value = val.NewValue); + windowMode = config.GetBindable(FrameworkSetting.WindowMode); + windowMode.BindValueChanged(mode => confineMouseModeSetting.Alpha = mode.NewValue == WindowMode.Fullscreen ? 0 : 1); + Children = new Drawable[] { new SettingsCheckbox @@ -47,7 +53,7 @@ namespace osu.Game.Overlays.Settings.Sections.Input LabelText = "Map absolute input to window", Current = config.GetBindable(FrameworkSetting.MapAbsoluteInputToWindow) }, - new SettingsEnumDropdown + confineMouseModeSetting = new SettingsEnumDropdown { LabelText = "Confine mouse cursor to window", Current = osuConfig.GetBindable(OsuSetting.ConfineMouseMode) From f6d15b975704c8358fa4eda4c8cbec19597aa252 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Sun, 6 Dec 2020 18:59:38 +0100 Subject: [PATCH 136/184] Invert back-to-front logic --- osu.Game/Skinning/PoolableSkinnableSample.cs | 2 +- osu.Game/Skinning/SkinnableSound.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Skinning/PoolableSkinnableSample.cs b/osu.Game/Skinning/PoolableSkinnableSample.cs index a59fcfea27..cc6b85a13e 100644 --- a/osu.Game/Skinning/PoolableSkinnableSample.cs +++ b/osu.Game/Skinning/PoolableSkinnableSample.cs @@ -102,7 +102,7 @@ namespace osu.Game.Skinning sampleContainer.Add(Sample = new DrawableSample(ch) { Looping = Looping }); // Start playback internally for the new sample if the previous one was playing beforehand. - if (wasPlaying && !Looping) + if (wasPlaying && Looping) Play(); } diff --git a/osu.Game/Skinning/SkinnableSound.cs b/osu.Game/Skinning/SkinnableSound.cs index 166f005473..645c08cd00 100644 --- a/osu.Game/Skinning/SkinnableSound.cs +++ b/osu.Game/Skinning/SkinnableSound.cs @@ -159,7 +159,7 @@ namespace osu.Game.Skinning samplesContainer.Add(sample); } - if (wasPlaying && !Looping) + if (wasPlaying && Looping) Play(); } From 0f9b38da081bc95eb7bdcc393df928f19457f036 Mon Sep 17 00:00:00 2001 From: Joehu Date: Sun, 6 Dec 2020 11:35:14 -0800 Subject: [PATCH 137/184] Add fade in/out animations to mod settings container --- osu.Game/Overlays/Mods/ModSelectOverlay.cs | 4 ++-- osu.Game/Overlays/Mods/ModSettingsContainer.cs | 14 +++++++++++++- 2 files changed, 15 insertions(+), 3 deletions(-) diff --git a/osu.Game/Overlays/Mods/ModSelectOverlay.cs b/osu.Game/Overlays/Mods/ModSelectOverlay.cs index 31adf47456..12da718ab2 100644 --- a/osu.Game/Overlays/Mods/ModSelectOverlay.cs +++ b/osu.Game/Overlays/Mods/ModSelectOverlay.cs @@ -237,7 +237,7 @@ namespace osu.Game.Overlays.Mods { Width = 180, Text = "Customisation", - Action = () => ModSettingsContainer.Alpha = ModSettingsContainer.Alpha == 1 ? 0 : 1, + Action = () => ModSettingsContainer.ToggleVisibility(), Enabled = { Value = false }, Origin = Anchor.CentreLeft, Anchor = Anchor.CentreLeft, @@ -430,7 +430,7 @@ namespace osu.Game.Overlays.Mods DeselectTypes(selectedMod.IncompatibleMods, true); - if (selectedMod.RequiresConfiguration) ModSettingsContainer.Alpha = 1; + if (selectedMod.RequiresConfiguration) ModSettingsContainer.Show(); } else { diff --git a/osu.Game/Overlays/Mods/ModSettingsContainer.cs b/osu.Game/Overlays/Mods/ModSettingsContainer.cs index b185b56ecd..a1d00f91b4 100644 --- a/osu.Game/Overlays/Mods/ModSettingsContainer.cs +++ b/osu.Game/Overlays/Mods/ModSettingsContainer.cs @@ -17,7 +17,7 @@ using osuTK.Graphics; namespace osu.Game.Overlays.Mods { - public class ModSettingsContainer : Container + public class ModSettingsContainer : VisibilityContainer { public readonly IBindable> SelectedMods = new Bindable>(Array.Empty()); @@ -27,6 +27,8 @@ namespace osu.Game.Overlays.Mods private readonly FillFlowContainer modSettingsContent; + private const double transition_duration = 200; + public ModSettingsContainer() { Children = new Drawable[] @@ -80,5 +82,15 @@ namespace osu.Game.Overlays.Mods protected override bool OnMouseDown(MouseDownEvent e) => true; protected override bool OnHover(HoverEvent e) => true; + + protected override void PopIn() + { + this.FadeIn(transition_duration, Easing.OutQuint); + } + + protected override void PopOut() + { + this.FadeOut(transition_duration, Easing.OutQuint); + } } } From 15e0ea332b85ddd23823909f1fba32d5e21829a6 Mon Sep 17 00:00:00 2001 From: Joehu Date: Sun, 6 Dec 2020 13:18:19 -0800 Subject: [PATCH 138/184] Check state instead of alpha in tests --- .../Visual/UserInterface/TestSceneModSettings.cs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneModSettings.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneModSettings.cs index 645b83758c..8614700b15 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneModSettings.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneModSettings.cs @@ -50,7 +50,7 @@ namespace osu.Game.Tests.Visual.UserInterface AddAssert("button enabled", () => modSelect.CustomiseButton.Enabled.Value); AddStep("open Customisation", () => modSelect.CustomiseButton.Click()); AddStep("deselect mod", () => modSelect.SelectMod(testCustomisableMod)); - AddAssert("controls hidden", () => modSelect.ModSettingsContainer.Alpha == 0); + AddAssert("controls hidden", () => modSelect.ModSettingsContainer.State.Value == Visibility.Hidden); } [Test] @@ -72,11 +72,11 @@ namespace osu.Game.Tests.Visual.UserInterface createModSelect(); openModSelect(); - AddAssert("Customisation closed", () => modSelect.ModSettingsContainer.Alpha == 0); + AddAssert("Customisation closed", () => modSelect.ModSettingsContainer.State.Value == Visibility.Hidden); AddStep("select mod", () => modSelect.SelectMod(testCustomisableAutoOpenMod)); - AddAssert("Customisation opened", () => modSelect.ModSettingsContainer.Alpha == 1); + AddAssert("Customisation opened", () => modSelect.ModSettingsContainer.State.Value == Visibility.Visible); AddStep("deselect mod", () => modSelect.SelectMod(testCustomisableAutoOpenMod)); - AddAssert("Customisation closed", () => modSelect.ModSettingsContainer.Alpha == 0); + AddAssert("Customisation closed", () => modSelect.ModSettingsContainer.State.Value == Visibility.Hidden); } [Test] @@ -123,7 +123,7 @@ namespace osu.Game.Tests.Visual.UserInterface AddStep("change mod settings menu width to full screen", () => modSelect.SetModSettingsWidth(1.0f)); AddStep("select cm2", () => modSelect.SelectMod(testCustomisableAutoOpenMod)); - AddAssert("Customisation opened", () => modSelect.ModSettingsContainer.Alpha == 1); + AddAssert("Customisation opened", () => modSelect.ModSettingsContainer.State.Value == Visibility.Visible); AddStep("hover over mod behind settings menu", () => InputManager.MoveMouseTo(modSelect.GetModButton(testCustomisableMod))); AddAssert("Mod is not considered hovered over", () => !modSelect.GetModButton(testCustomisableMod).IsHovered); AddStep("left click mod", () => InputManager.Click(MouseButton.Left)); @@ -153,7 +153,7 @@ namespace osu.Game.Tests.Visual.UserInterface private class TestModSelectOverlay : ModSelectOverlay { - public new Container ModSettingsContainer => base.ModSettingsContainer; + public new VisibilityContainer ModSettingsContainer => base.ModSettingsContainer; public new TriangleButton CustomiseButton => base.CustomiseButton; public bool ButtonsLoaded => ModSectionsContainer.Children.All(c => c.ModIconsLoaded); From cf3fbe0b0b832ef2476e46eb600f086b385005b9 Mon Sep 17 00:00:00 2001 From: Xexxar Date: Sun, 6 Dec 2020 18:06:36 -0600 Subject: [PATCH 139/184] osuDifficulty ar11 nerf --- .../Difficulty/OsuPerformanceCalculator.cs | 22 +++++++++---------- 1 file changed, 10 insertions(+), 12 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Difficulty/OsuPerformanceCalculator.cs b/osu.Game.Rulesets.Osu/Difficulty/OsuPerformanceCalculator.cs index 063cde8747..3f0b0dcc71 100644 --- a/osu.Game.Rulesets.Osu/Difficulty/OsuPerformanceCalculator.cs +++ b/osu.Game.Rulesets.Osu/Difficulty/OsuPerformanceCalculator.cs @@ -99,16 +99,13 @@ namespace osu.Game.Rulesets.Osu.Difficulty if (Attributes.MaxCombo > 0) aimValue *= Math.Min(Math.Pow(scoreMaxCombo, 0.8) / Math.Pow(Attributes.MaxCombo, 0.8), 1.0); - double approachRateFactor = 1.0; - + double approachRateFactor = 0.0; if (Attributes.ApproachRate > 10.33) - approachRateFactor += 0.3 * (Attributes.ApproachRate - 10.33); + approachRateFactor += 0.4 * (Attributes.ApproachRate - 10.33); else if (Attributes.ApproachRate < 8.0) - { - approachRateFactor += 0.01 * (8.0 - Attributes.ApproachRate); - } + approachRateFactor += 0.1 * (8.0 - Attributes.ApproachRate); - aimValue *= approachRateFactor; + aimValue *= 1.0 + Math.Min(approachRateFactor, approachRateFactor * (totalHits / 1000.0)); // We want to give more reward for lower AR when it comes to aim and HD. This nerfs high AR and buffs lower AR. if (mods.Any(h => h is OsuModHidden)) @@ -137,8 +134,9 @@ namespace osu.Game.Rulesets.Osu.Difficulty double speedValue = Math.Pow(5.0 * Math.Max(1.0, Attributes.SpeedStrain / 0.0675) - 4.0, 3.0) / 100000.0; // Longer maps are worth more - speedValue *= 0.95 + 0.4 * Math.Min(1.0, totalHits / 2000.0) + - (totalHits > 2000 ? Math.Log10(totalHits / 2000.0) * 0.5 : 0.0); + double lengthBonus = 0.95 + 0.4 * Math.Min(1.0, totalHits / 2000.0) + + (totalHits > 2000 ? Math.Log10(totalHits / 2000.0) * 0.5 : 0.0); + speedValue *= lengthBonus; // Penalize misses exponentially. This mainly fixes tag4 maps and the likes until a per-hitobject solution is available speedValue *= Math.Pow(0.97, countMiss); @@ -147,11 +145,11 @@ namespace osu.Game.Rulesets.Osu.Difficulty if (Attributes.MaxCombo > 0) speedValue *= Math.Min(Math.Pow(scoreMaxCombo, 0.8) / Math.Pow(Attributes.MaxCombo, 0.8), 1.0); - double approachRateFactor = 1.0; + double approachRateFactor = 0.0; if (Attributes.ApproachRate > 10.33) - approachRateFactor += 0.3 * (Attributes.ApproachRate - 10.33); + approachRateFactor += 0.4 * (Attributes.ApproachRate - 10.33); - speedValue *= approachRateFactor; + speedValue *= 1.0 + Math.Min(approachRateFactor, approachRateFactor * (totalHits / 1000.0)); if (mods.Any(m => m is OsuModHidden)) speedValue *= 1.0 + 0.04 * (12.0 - Attributes.ApproachRate); From c905df8a770a72294401952b5120680ec004b92c Mon Sep 17 00:00:00 2001 From: ekrctb Date: Mon, 7 Dec 2020 12:26:58 +0900 Subject: [PATCH 140/184] Move LegacySkinTransformer --- .../Skinning/{ => Legacy}/OsuLegacySkinTransformer.cs | 1 - 1 file changed, 1 deletion(-) rename osu.Game.Rulesets.Osu/Skinning/{ => Legacy}/OsuLegacySkinTransformer.cs (99%) diff --git a/osu.Game.Rulesets.Osu/Skinning/OsuLegacySkinTransformer.cs b/osu.Game.Rulesets.Osu/Skinning/Legacy/OsuLegacySkinTransformer.cs similarity index 99% rename from osu.Game.Rulesets.Osu/Skinning/OsuLegacySkinTransformer.cs rename to osu.Game.Rulesets.Osu/Skinning/Legacy/OsuLegacySkinTransformer.cs index 70abfa1ac9..78bc26eff7 100644 --- a/osu.Game.Rulesets.Osu/Skinning/OsuLegacySkinTransformer.cs +++ b/osu.Game.Rulesets.Osu/Skinning/Legacy/OsuLegacySkinTransformer.cs @@ -4,7 +4,6 @@ using System; using osu.Framework.Bindables; using osu.Framework.Graphics; -using osu.Game.Rulesets.Osu.Skinning.Legacy; using osu.Game.Skinning; using osuTK; From 0d88ff340489ef14e1ecc8dc6c52dd0c92848770 Mon Sep 17 00:00:00 2001 From: ekrctb Date: Mon, 7 Dec 2020 12:27:12 +0900 Subject: [PATCH 141/184] Adjust namespace --- osu.Game.Rulesets.Osu/OsuRuleset.cs | 2 +- .../Skinning/Legacy/OsuLegacySkinTransformer.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game.Rulesets.Osu/OsuRuleset.cs b/osu.Game.Rulesets.Osu/OsuRuleset.cs index d8180b0e58..cba0c5be14 100644 --- a/osu.Game.Rulesets.Osu/OsuRuleset.cs +++ b/osu.Game.Rulesets.Osu/OsuRuleset.cs @@ -24,13 +24,13 @@ using osu.Game.Rulesets.Osu.Beatmaps; using osu.Game.Rulesets.Osu.Configuration; using osu.Game.Rulesets.Osu.Difficulty; using osu.Game.Rulesets.Osu.Scoring; -using osu.Game.Rulesets.Osu.Skinning; using osu.Game.Rulesets.Scoring; using osu.Game.Scoring; using osu.Game.Skinning; using System; using System.Linq; using osu.Game.Rulesets.Osu.Objects; +using osu.Game.Rulesets.Osu.Skinning.Legacy; using osu.Game.Rulesets.Osu.Statistics; using osu.Game.Screens.Ranking.Statistics; diff --git a/osu.Game.Rulesets.Osu/Skinning/Legacy/OsuLegacySkinTransformer.cs b/osu.Game.Rulesets.Osu/Skinning/Legacy/OsuLegacySkinTransformer.cs index 78bc26eff7..d74f885573 100644 --- a/osu.Game.Rulesets.Osu/Skinning/Legacy/OsuLegacySkinTransformer.cs +++ b/osu.Game.Rulesets.Osu/Skinning/Legacy/OsuLegacySkinTransformer.cs @@ -7,7 +7,7 @@ using osu.Framework.Graphics; using osu.Game.Skinning; using osuTK; -namespace osu.Game.Rulesets.Osu.Skinning +namespace osu.Game.Rulesets.Osu.Skinning.Legacy { public class OsuLegacySkinTransformer : LegacySkinTransformer { From f78bd7c7399435d12d47b672ec444979b3c376e4 Mon Sep 17 00:00:00 2001 From: ekrctb Date: Mon, 7 Dec 2020 12:29:14 +0900 Subject: [PATCH 142/184] Move piece files of Taiko ruleset --- .../Drawables/Pieces => Skinning/Default}/CentreHitCirclePiece.cs | 0 .../{Objects/Drawables/Pieces => Skinning/Default}/CirclePiece.cs | 0 .../Drawables/Pieces => Skinning/Default}/ElongatedCirclePiece.cs | 0 .../Drawables/Pieces => Skinning/Default}/RimHitCirclePiece.cs | 0 .../Drawables/Pieces => Skinning/Default}/SwellSymbolPiece.cs | 0 .../{Objects/Drawables/Pieces => Skinning/Default}/TickPiece.cs | 0 osu.Game.Rulesets.Taiko/Skinning/{ => Legacy}/LegacyBarLine.cs | 0 .../Skinning/{ => Legacy}/LegacyCirclePiece.cs | 0 osu.Game.Rulesets.Taiko/Skinning/{ => Legacy}/LegacyDrumRoll.cs | 0 osu.Game.Rulesets.Taiko/Skinning/{ => Legacy}/LegacyHit.cs | 0 .../Skinning/{ => Legacy}/LegacyHitExplosion.cs | 0 osu.Game.Rulesets.Taiko/Skinning/{ => Legacy}/LegacyInputDrum.cs | 0 .../Skinning/{ => Legacy}/LegacyTaikoScroller.cs | 0 .../Skinning/{ => Legacy}/TaikoLegacyHitTarget.cs | 0 .../Skinning/{ => Legacy}/TaikoLegacyPlayfieldBackgroundRight.cs | 0 .../Skinning/{ => Legacy}/TaikoLegacySkinTransformer.cs | 0 16 files changed, 0 insertions(+), 0 deletions(-) rename osu.Game.Rulesets.Taiko/{Objects/Drawables/Pieces => Skinning/Default}/CentreHitCirclePiece.cs (100%) rename osu.Game.Rulesets.Taiko/{Objects/Drawables/Pieces => Skinning/Default}/CirclePiece.cs (100%) rename osu.Game.Rulesets.Taiko/{Objects/Drawables/Pieces => Skinning/Default}/ElongatedCirclePiece.cs (100%) rename osu.Game.Rulesets.Taiko/{Objects/Drawables/Pieces => Skinning/Default}/RimHitCirclePiece.cs (100%) rename osu.Game.Rulesets.Taiko/{Objects/Drawables/Pieces => Skinning/Default}/SwellSymbolPiece.cs (100%) rename osu.Game.Rulesets.Taiko/{Objects/Drawables/Pieces => Skinning/Default}/TickPiece.cs (100%) rename osu.Game.Rulesets.Taiko/Skinning/{ => Legacy}/LegacyBarLine.cs (100%) rename osu.Game.Rulesets.Taiko/Skinning/{ => Legacy}/LegacyCirclePiece.cs (100%) rename osu.Game.Rulesets.Taiko/Skinning/{ => Legacy}/LegacyDrumRoll.cs (100%) rename osu.Game.Rulesets.Taiko/Skinning/{ => Legacy}/LegacyHit.cs (100%) rename osu.Game.Rulesets.Taiko/Skinning/{ => Legacy}/LegacyHitExplosion.cs (100%) rename osu.Game.Rulesets.Taiko/Skinning/{ => Legacy}/LegacyInputDrum.cs (100%) rename osu.Game.Rulesets.Taiko/Skinning/{ => Legacy}/LegacyTaikoScroller.cs (100%) rename osu.Game.Rulesets.Taiko/Skinning/{ => Legacy}/TaikoLegacyHitTarget.cs (100%) rename osu.Game.Rulesets.Taiko/Skinning/{ => Legacy}/TaikoLegacyPlayfieldBackgroundRight.cs (100%) rename osu.Game.Rulesets.Taiko/Skinning/{ => Legacy}/TaikoLegacySkinTransformer.cs (100%) diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/Pieces/CentreHitCirclePiece.cs b/osu.Game.Rulesets.Taiko/Skinning/Default/CentreHitCirclePiece.cs similarity index 100% rename from osu.Game.Rulesets.Taiko/Objects/Drawables/Pieces/CentreHitCirclePiece.cs rename to osu.Game.Rulesets.Taiko/Skinning/Default/CentreHitCirclePiece.cs diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/Pieces/CirclePiece.cs b/osu.Game.Rulesets.Taiko/Skinning/Default/CirclePiece.cs similarity index 100% rename from osu.Game.Rulesets.Taiko/Objects/Drawables/Pieces/CirclePiece.cs rename to osu.Game.Rulesets.Taiko/Skinning/Default/CirclePiece.cs diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/Pieces/ElongatedCirclePiece.cs b/osu.Game.Rulesets.Taiko/Skinning/Default/ElongatedCirclePiece.cs similarity index 100% rename from osu.Game.Rulesets.Taiko/Objects/Drawables/Pieces/ElongatedCirclePiece.cs rename to osu.Game.Rulesets.Taiko/Skinning/Default/ElongatedCirclePiece.cs diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/Pieces/RimHitCirclePiece.cs b/osu.Game.Rulesets.Taiko/Skinning/Default/RimHitCirclePiece.cs similarity index 100% rename from osu.Game.Rulesets.Taiko/Objects/Drawables/Pieces/RimHitCirclePiece.cs rename to osu.Game.Rulesets.Taiko/Skinning/Default/RimHitCirclePiece.cs diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/Pieces/SwellSymbolPiece.cs b/osu.Game.Rulesets.Taiko/Skinning/Default/SwellSymbolPiece.cs similarity index 100% rename from osu.Game.Rulesets.Taiko/Objects/Drawables/Pieces/SwellSymbolPiece.cs rename to osu.Game.Rulesets.Taiko/Skinning/Default/SwellSymbolPiece.cs diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/Pieces/TickPiece.cs b/osu.Game.Rulesets.Taiko/Skinning/Default/TickPiece.cs similarity index 100% rename from osu.Game.Rulesets.Taiko/Objects/Drawables/Pieces/TickPiece.cs rename to osu.Game.Rulesets.Taiko/Skinning/Default/TickPiece.cs diff --git a/osu.Game.Rulesets.Taiko/Skinning/LegacyBarLine.cs b/osu.Game.Rulesets.Taiko/Skinning/Legacy/LegacyBarLine.cs similarity index 100% rename from osu.Game.Rulesets.Taiko/Skinning/LegacyBarLine.cs rename to osu.Game.Rulesets.Taiko/Skinning/Legacy/LegacyBarLine.cs diff --git a/osu.Game.Rulesets.Taiko/Skinning/LegacyCirclePiece.cs b/osu.Game.Rulesets.Taiko/Skinning/Legacy/LegacyCirclePiece.cs similarity index 100% rename from osu.Game.Rulesets.Taiko/Skinning/LegacyCirclePiece.cs rename to osu.Game.Rulesets.Taiko/Skinning/Legacy/LegacyCirclePiece.cs diff --git a/osu.Game.Rulesets.Taiko/Skinning/LegacyDrumRoll.cs b/osu.Game.Rulesets.Taiko/Skinning/Legacy/LegacyDrumRoll.cs similarity index 100% rename from osu.Game.Rulesets.Taiko/Skinning/LegacyDrumRoll.cs rename to osu.Game.Rulesets.Taiko/Skinning/Legacy/LegacyDrumRoll.cs diff --git a/osu.Game.Rulesets.Taiko/Skinning/LegacyHit.cs b/osu.Game.Rulesets.Taiko/Skinning/Legacy/LegacyHit.cs similarity index 100% rename from osu.Game.Rulesets.Taiko/Skinning/LegacyHit.cs rename to osu.Game.Rulesets.Taiko/Skinning/Legacy/LegacyHit.cs diff --git a/osu.Game.Rulesets.Taiko/Skinning/LegacyHitExplosion.cs b/osu.Game.Rulesets.Taiko/Skinning/Legacy/LegacyHitExplosion.cs similarity index 100% rename from osu.Game.Rulesets.Taiko/Skinning/LegacyHitExplosion.cs rename to osu.Game.Rulesets.Taiko/Skinning/Legacy/LegacyHitExplosion.cs diff --git a/osu.Game.Rulesets.Taiko/Skinning/LegacyInputDrum.cs b/osu.Game.Rulesets.Taiko/Skinning/Legacy/LegacyInputDrum.cs similarity index 100% rename from osu.Game.Rulesets.Taiko/Skinning/LegacyInputDrum.cs rename to osu.Game.Rulesets.Taiko/Skinning/Legacy/LegacyInputDrum.cs diff --git a/osu.Game.Rulesets.Taiko/Skinning/LegacyTaikoScroller.cs b/osu.Game.Rulesets.Taiko/Skinning/Legacy/LegacyTaikoScroller.cs similarity index 100% rename from osu.Game.Rulesets.Taiko/Skinning/LegacyTaikoScroller.cs rename to osu.Game.Rulesets.Taiko/Skinning/Legacy/LegacyTaikoScroller.cs diff --git a/osu.Game.Rulesets.Taiko/Skinning/TaikoLegacyHitTarget.cs b/osu.Game.Rulesets.Taiko/Skinning/Legacy/TaikoLegacyHitTarget.cs similarity index 100% rename from osu.Game.Rulesets.Taiko/Skinning/TaikoLegacyHitTarget.cs rename to osu.Game.Rulesets.Taiko/Skinning/Legacy/TaikoLegacyHitTarget.cs diff --git a/osu.Game.Rulesets.Taiko/Skinning/TaikoLegacyPlayfieldBackgroundRight.cs b/osu.Game.Rulesets.Taiko/Skinning/Legacy/TaikoLegacyPlayfieldBackgroundRight.cs similarity index 100% rename from osu.Game.Rulesets.Taiko/Skinning/TaikoLegacyPlayfieldBackgroundRight.cs rename to osu.Game.Rulesets.Taiko/Skinning/Legacy/TaikoLegacyPlayfieldBackgroundRight.cs diff --git a/osu.Game.Rulesets.Taiko/Skinning/TaikoLegacySkinTransformer.cs b/osu.Game.Rulesets.Taiko/Skinning/Legacy/TaikoLegacySkinTransformer.cs similarity index 100% rename from osu.Game.Rulesets.Taiko/Skinning/TaikoLegacySkinTransformer.cs rename to osu.Game.Rulesets.Taiko/Skinning/Legacy/TaikoLegacySkinTransformer.cs From c70b13ecc2f0a0438d26853a09b138b0dc34e76c Mon Sep 17 00:00:00 2001 From: ekrctb Date: Mon, 7 Dec 2020 12:30:25 +0900 Subject: [PATCH 143/184] Adjust namespace --- .../Skinning/TestSceneTaikoScroller.cs | 2 +- .../Objects/Drawables/DrawableDrumRoll.cs | 2 +- .../Objects/Drawables/DrawableDrumRollTick.cs | 2 +- .../Objects/Drawables/DrawableHit.cs | 2 +- .../Objects/Drawables/DrawableSwell.cs | 2 +- .../Objects/Drawables/DrawableSwellTick.cs | 2 +- .../Skinning/Default/CentreHitCirclePiece.cs | 4 ++-- .../Skinning/Default/CirclePiece.cs | 10 +++++----- .../Skinning/Default/ElongatedCirclePiece.cs | 2 +- .../Skinning/Default/RimHitCirclePiece.cs | 2 +- .../Skinning/Default/SwellSymbolPiece.cs | 4 ++-- osu.Game.Rulesets.Taiko/Skinning/Default/TickPiece.cs | 4 ++-- .../Skinning/Legacy/LegacyBarLine.cs | 2 +- .../Skinning/Legacy/LegacyCirclePiece.cs | 2 +- .../Skinning/Legacy/LegacyDrumRoll.cs | 2 +- osu.Game.Rulesets.Taiko/Skinning/Legacy/LegacyHit.cs | 2 +- .../Skinning/Legacy/LegacyHitExplosion.cs | 2 +- .../Skinning/Legacy/LegacyInputDrum.cs | 2 +- .../Skinning/Legacy/LegacyTaikoScroller.cs | 2 +- .../Skinning/Legacy/TaikoLegacyHitTarget.cs | 2 +- .../Legacy/TaikoLegacyPlayfieldBackgroundRight.cs | 2 +- .../Skinning/Legacy/TaikoLegacySkinTransformer.cs | 2 +- osu.Game.Rulesets.Taiko/TaikoRuleset.cs | 2 +- 23 files changed, 30 insertions(+), 30 deletions(-) diff --git a/osu.Game.Rulesets.Taiko.Tests/Skinning/TestSceneTaikoScroller.cs b/osu.Game.Rulesets.Taiko.Tests/Skinning/TestSceneTaikoScroller.cs index 114038b81c..4ae3cbd418 100644 --- a/osu.Game.Rulesets.Taiko.Tests/Skinning/TestSceneTaikoScroller.cs +++ b/osu.Game.Rulesets.Taiko.Tests/Skinning/TestSceneTaikoScroller.cs @@ -6,7 +6,7 @@ using osu.Framework.Testing; using osu.Framework.Timing; using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Scoring; -using osu.Game.Rulesets.Taiko.Skinning; +using osu.Game.Rulesets.Taiko.Skinning.Legacy; using osu.Game.Skinning; namespace osu.Game.Rulesets.Taiko.Tests.Skinning diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableDrumRoll.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableDrumRoll.cs index c596fa2c7c..4ead4982a1 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableDrumRoll.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableDrumRoll.cs @@ -8,12 +8,12 @@ using osu.Framework.Utils; using osu.Game.Graphics; using osu.Game.Rulesets.Objects.Drawables; using osuTK.Graphics; -using osu.Game.Rulesets.Taiko.Objects.Drawables.Pieces; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Scoring; +using osu.Game.Rulesets.Taiko.Skinning.Default; using osu.Game.Skinning; using osuTK; diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableDrumRollTick.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableDrumRollTick.cs index be659f6ca5..e68e40ae1c 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableDrumRollTick.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableDrumRollTick.cs @@ -4,7 +4,7 @@ using System; using osu.Framework.Graphics; using osu.Game.Rulesets.Objects.Drawables; -using osu.Game.Rulesets.Taiko.Objects.Drawables.Pieces; +using osu.Game.Rulesets.Taiko.Skinning.Default; using osu.Game.Skinning; namespace osu.Game.Rulesets.Taiko.Objects.Drawables diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableHit.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableHit.cs index 29a96a7a40..d1751d8a75 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableHit.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableHit.cs @@ -11,7 +11,7 @@ using osu.Framework.Graphics; using osu.Game.Audio; using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.Scoring; -using osu.Game.Rulesets.Taiko.Objects.Drawables.Pieces; +using osu.Game.Rulesets.Taiko.Skinning.Default; using osu.Game.Skinning; namespace osu.Game.Rulesets.Taiko.Objects.Drawables diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableSwell.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableSwell.cs index ff0a27023d..5c6278ed08 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableSwell.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableSwell.cs @@ -13,7 +13,7 @@ using osuTK.Graphics; using osu.Framework.Graphics.Shapes; using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Scoring; -using osu.Game.Rulesets.Taiko.Objects.Drawables.Pieces; +using osu.Game.Rulesets.Taiko.Skinning.Default; using osu.Game.Skinning; namespace osu.Game.Rulesets.Taiko.Objects.Drawables diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableSwellTick.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableSwellTick.cs index 6202583494..14c86d151f 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableSwellTick.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableSwellTick.cs @@ -2,7 +2,7 @@ // See the LICENCE file in the repository root for full licence text. using osu.Framework.Graphics; -using osu.Game.Rulesets.Taiko.Objects.Drawables.Pieces; +using osu.Game.Rulesets.Taiko.Skinning.Default; using osu.Game.Skinning; namespace osu.Game.Rulesets.Taiko.Objects.Drawables diff --git a/osu.Game.Rulesets.Taiko/Skinning/Default/CentreHitCirclePiece.cs b/osu.Game.Rulesets.Taiko/Skinning/Default/CentreHitCirclePiece.cs index 0509841ba8..f65bb54726 100644 --- a/osu.Game.Rulesets.Taiko/Skinning/Default/CentreHitCirclePiece.cs +++ b/osu.Game.Rulesets.Taiko/Skinning/Default/CentreHitCirclePiece.cs @@ -4,11 +4,11 @@ using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; -using osuTK; using osu.Framework.Graphics.Shapes; using osu.Game.Graphics; +using osuTK; -namespace osu.Game.Rulesets.Taiko.Objects.Drawables.Pieces +namespace osu.Game.Rulesets.Taiko.Skinning.Default { public class CentreHitCirclePiece : CirclePiece { diff --git a/osu.Game.Rulesets.Taiko/Skinning/Default/CirclePiece.cs b/osu.Game.Rulesets.Taiko/Skinning/Default/CirclePiece.cs index f515a35c18..8ca996159b 100644 --- a/osu.Game.Rulesets.Taiko/Skinning/Default/CirclePiece.cs +++ b/osu.Game.Rulesets.Taiko/Skinning/Default/CirclePiece.cs @@ -5,15 +5,15 @@ using osu.Framework.Audio.Track; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; -using osu.Framework.Graphics.Shapes; -using osu.Game.Graphics.Backgrounds; -using osuTK.Graphics; -using osu.Game.Beatmaps.ControlPoints; using osu.Framework.Graphics.Effects; +using osu.Framework.Graphics.Shapes; +using osu.Game.Beatmaps.ControlPoints; using osu.Game.Graphics; +using osu.Game.Graphics.Backgrounds; using osu.Game.Graphics.Containers; +using osuTK.Graphics; -namespace osu.Game.Rulesets.Taiko.Objects.Drawables.Pieces +namespace osu.Game.Rulesets.Taiko.Skinning.Default { /// /// A circle piece which is used uniformly through osu!taiko to visualise hitobjects. diff --git a/osu.Game.Rulesets.Taiko/Skinning/Default/ElongatedCirclePiece.cs b/osu.Game.Rulesets.Taiko/Skinning/Default/ElongatedCirclePiece.cs index 034ab6dd21..210841bca0 100644 --- a/osu.Game.Rulesets.Taiko/Skinning/Default/ElongatedCirclePiece.cs +++ b/osu.Game.Rulesets.Taiko/Skinning/Default/ElongatedCirclePiece.cs @@ -5,7 +5,7 @@ using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Game.Graphics; -namespace osu.Game.Rulesets.Taiko.Objects.Drawables.Pieces +namespace osu.Game.Rulesets.Taiko.Skinning.Default { public class ElongatedCirclePiece : CirclePiece { diff --git a/osu.Game.Rulesets.Taiko/Skinning/Default/RimHitCirclePiece.cs b/osu.Game.Rulesets.Taiko/Skinning/Default/RimHitCirclePiece.cs index 3273ab7fa7..ca2ab301be 100644 --- a/osu.Game.Rulesets.Taiko/Skinning/Default/RimHitCirclePiece.cs +++ b/osu.Game.Rulesets.Taiko/Skinning/Default/RimHitCirclePiece.cs @@ -9,7 +9,7 @@ using osu.Game.Graphics; using osuTK; using osuTK.Graphics; -namespace osu.Game.Rulesets.Taiko.Objects.Drawables.Pieces +namespace osu.Game.Rulesets.Taiko.Skinning.Default { public class RimHitCirclePiece : CirclePiece { diff --git a/osu.Game.Rulesets.Taiko/Skinning/Default/SwellSymbolPiece.cs b/osu.Game.Rulesets.Taiko/Skinning/Default/SwellSymbolPiece.cs index a8f9f0b94d..2f59cac3ff 100644 --- a/osu.Game.Rulesets.Taiko/Skinning/Default/SwellSymbolPiece.cs +++ b/osu.Game.Rulesets.Taiko/Skinning/Default/SwellSymbolPiece.cs @@ -2,13 +2,13 @@ // See the LICENCE file in the repository root for full licence text. using osu.Framework.Allocation; -using osuTK; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Sprites; using osu.Game.Graphics; +using osuTK; -namespace osu.Game.Rulesets.Taiko.Objects.Drawables.Pieces +namespace osu.Game.Rulesets.Taiko.Skinning.Default { public class SwellCirclePiece : CirclePiece { diff --git a/osu.Game.Rulesets.Taiko/Skinning/Default/TickPiece.cs b/osu.Game.Rulesets.Taiko/Skinning/Default/TickPiece.cs index 0648bcebcd..09c8243aac 100644 --- a/osu.Game.Rulesets.Taiko/Skinning/Default/TickPiece.cs +++ b/osu.Game.Rulesets.Taiko/Skinning/Default/TickPiece.cs @@ -3,11 +3,11 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Shapes; using osuTK; using osuTK.Graphics; -using osu.Framework.Graphics.Shapes; -namespace osu.Game.Rulesets.Taiko.Objects.Drawables.Pieces +namespace osu.Game.Rulesets.Taiko.Skinning.Default { public class TickPiece : CompositeDrawable { diff --git a/osu.Game.Rulesets.Taiko/Skinning/Legacy/LegacyBarLine.cs b/osu.Game.Rulesets.Taiko/Skinning/Legacy/LegacyBarLine.cs index 7d08a21ab1..2b528ae8ce 100644 --- a/osu.Game.Rulesets.Taiko/Skinning/Legacy/LegacyBarLine.cs +++ b/osu.Game.Rulesets.Taiko/Skinning/Legacy/LegacyBarLine.cs @@ -7,7 +7,7 @@ using osu.Framework.Graphics.Sprites; using osu.Game.Skinning; using osuTK; -namespace osu.Game.Rulesets.Taiko.Skinning +namespace osu.Game.Rulesets.Taiko.Skinning.Legacy { public class LegacyBarLine : Sprite { diff --git a/osu.Game.Rulesets.Taiko/Skinning/Legacy/LegacyCirclePiece.cs b/osu.Game.Rulesets.Taiko/Skinning/Legacy/LegacyCirclePiece.cs index 9b73ccd248..821ddc3c04 100644 --- a/osu.Game.Rulesets.Taiko/Skinning/Legacy/LegacyCirclePiece.cs +++ b/osu.Game.Rulesets.Taiko/Skinning/Legacy/LegacyCirclePiece.cs @@ -12,7 +12,7 @@ using osu.Game.Skinning; using osuTK; using osuTK.Graphics; -namespace osu.Game.Rulesets.Taiko.Skinning +namespace osu.Game.Rulesets.Taiko.Skinning.Legacy { public class LegacyCirclePiece : CompositeDrawable, IHasAccentColour { diff --git a/osu.Game.Rulesets.Taiko/Skinning/Legacy/LegacyDrumRoll.cs b/osu.Game.Rulesets.Taiko/Skinning/Legacy/LegacyDrumRoll.cs index 5ab8e3a8c8..ea6f813be8 100644 --- a/osu.Game.Rulesets.Taiko/Skinning/Legacy/LegacyDrumRoll.cs +++ b/osu.Game.Rulesets.Taiko/Skinning/Legacy/LegacyDrumRoll.cs @@ -10,7 +10,7 @@ using osu.Game.Graphics; using osu.Game.Skinning; using osuTK.Graphics; -namespace osu.Game.Rulesets.Taiko.Skinning +namespace osu.Game.Rulesets.Taiko.Skinning.Legacy { public class LegacyDrumRoll : CompositeDrawable, IHasAccentColour { diff --git a/osu.Game.Rulesets.Taiko/Skinning/Legacy/LegacyHit.cs b/osu.Game.Rulesets.Taiko/Skinning/Legacy/LegacyHit.cs index b11b64c22c..d93317f0e2 100644 --- a/osu.Game.Rulesets.Taiko/Skinning/Legacy/LegacyHit.cs +++ b/osu.Game.Rulesets.Taiko/Skinning/Legacy/LegacyHit.cs @@ -5,7 +5,7 @@ using osu.Framework.Allocation; using osu.Game.Skinning; using osuTK.Graphics; -namespace osu.Game.Rulesets.Taiko.Skinning +namespace osu.Game.Rulesets.Taiko.Skinning.Legacy { public class LegacyHit : LegacyCirclePiece { diff --git a/osu.Game.Rulesets.Taiko/Skinning/Legacy/LegacyHitExplosion.cs b/osu.Game.Rulesets.Taiko/Skinning/Legacy/LegacyHitExplosion.cs index 19493271be..651cdd6438 100644 --- a/osu.Game.Rulesets.Taiko/Skinning/Legacy/LegacyHitExplosion.cs +++ b/osu.Game.Rulesets.Taiko/Skinning/Legacy/LegacyHitExplosion.cs @@ -8,7 +8,7 @@ using osu.Framework.Graphics.Containers; using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.Taiko.Objects.Drawables; -namespace osu.Game.Rulesets.Taiko.Skinning +namespace osu.Game.Rulesets.Taiko.Skinning.Legacy { public class LegacyHitExplosion : CompositeDrawable { diff --git a/osu.Game.Rulesets.Taiko/Skinning/Legacy/LegacyInputDrum.cs b/osu.Game.Rulesets.Taiko/Skinning/Legacy/LegacyInputDrum.cs index b7b55b9ae0..795885d4b9 100644 --- a/osu.Game.Rulesets.Taiko/Skinning/Legacy/LegacyInputDrum.cs +++ b/osu.Game.Rulesets.Taiko/Skinning/Legacy/LegacyInputDrum.cs @@ -11,7 +11,7 @@ using osu.Game.Rulesets.Taiko.Audio; using osu.Game.Skinning; using osuTK; -namespace osu.Game.Rulesets.Taiko.Skinning +namespace osu.Game.Rulesets.Taiko.Skinning.Legacy { /// /// A component of the playfield that captures input and displays input as a drum. diff --git a/osu.Game.Rulesets.Taiko/Skinning/Legacy/LegacyTaikoScroller.cs b/osu.Game.Rulesets.Taiko/Skinning/Legacy/LegacyTaikoScroller.cs index e029040ef3..eb92097204 100644 --- a/osu.Game.Rulesets.Taiko/Skinning/Legacy/LegacyTaikoScroller.cs +++ b/osu.Game.Rulesets.Taiko/Skinning/Legacy/LegacyTaikoScroller.cs @@ -13,7 +13,7 @@ using osu.Game.Screens.Play; using osu.Game.Skinning; using osuTK; -namespace osu.Game.Rulesets.Taiko.Skinning +namespace osu.Game.Rulesets.Taiko.Skinning.Legacy { public class LegacyTaikoScroller : CompositeDrawable { diff --git a/osu.Game.Rulesets.Taiko/Skinning/Legacy/TaikoLegacyHitTarget.cs b/osu.Game.Rulesets.Taiko/Skinning/Legacy/TaikoLegacyHitTarget.cs index e522fb7c10..9feb2054da 100644 --- a/osu.Game.Rulesets.Taiko/Skinning/Legacy/TaikoLegacyHitTarget.cs +++ b/osu.Game.Rulesets.Taiko/Skinning/Legacy/TaikoLegacyHitTarget.cs @@ -9,7 +9,7 @@ using osu.Game.Rulesets.Taiko.UI; using osu.Game.Skinning; using osuTK; -namespace osu.Game.Rulesets.Taiko.Skinning +namespace osu.Game.Rulesets.Taiko.Skinning.Legacy { public class TaikoLegacyHitTarget : CompositeDrawable { diff --git a/osu.Game.Rulesets.Taiko/Skinning/Legacy/TaikoLegacyPlayfieldBackgroundRight.cs b/osu.Game.Rulesets.Taiko/Skinning/Legacy/TaikoLegacyPlayfieldBackgroundRight.cs index 4bbb6be6b1..02756d57a4 100644 --- a/osu.Game.Rulesets.Taiko/Skinning/Legacy/TaikoLegacyPlayfieldBackgroundRight.cs +++ b/osu.Game.Rulesets.Taiko/Skinning/Legacy/TaikoLegacyPlayfieldBackgroundRight.cs @@ -10,7 +10,7 @@ using osu.Game.Graphics.Containers; using osu.Game.Skinning; using osuTK; -namespace osu.Game.Rulesets.Taiko.Skinning +namespace osu.Game.Rulesets.Taiko.Skinning.Legacy { public class TaikoLegacyPlayfieldBackgroundRight : BeatSyncedContainer { diff --git a/osu.Game.Rulesets.Taiko/Skinning/Legacy/TaikoLegacySkinTransformer.cs b/osu.Game.Rulesets.Taiko/Skinning/Legacy/TaikoLegacySkinTransformer.cs index 96fb065e79..d8e3100048 100644 --- a/osu.Game.Rulesets.Taiko/Skinning/Legacy/TaikoLegacySkinTransformer.cs +++ b/osu.Game.Rulesets.Taiko/Skinning/Legacy/TaikoLegacySkinTransformer.cs @@ -11,7 +11,7 @@ using osu.Game.Rulesets.Scoring; using osu.Game.Rulesets.Taiko.UI; using osu.Game.Skinning; -namespace osu.Game.Rulesets.Taiko.Skinning +namespace osu.Game.Rulesets.Taiko.Skinning.Legacy { public class TaikoLegacySkinTransformer : LegacySkinTransformer { diff --git a/osu.Game.Rulesets.Taiko/TaikoRuleset.cs b/osu.Game.Rulesets.Taiko/TaikoRuleset.cs index 2a49dd655c..f2b5d195b4 100644 --- a/osu.Game.Rulesets.Taiko/TaikoRuleset.cs +++ b/osu.Game.Rulesets.Taiko/TaikoRuleset.cs @@ -25,7 +25,7 @@ using System.Linq; using osu.Game.Rulesets.Edit; using osu.Game.Rulesets.Taiko.Edit; using osu.Game.Rulesets.Taiko.Objects; -using osu.Game.Rulesets.Taiko.Skinning; +using osu.Game.Rulesets.Taiko.Skinning.Legacy; using osu.Game.Screens.Ranking.Statistics; using osu.Game.Skinning; From 40da799103b049070a18c5dccaa9f9f58da53ab1 Mon Sep 17 00:00:00 2001 From: ekrctb Date: Mon, 7 Dec 2020 12:31:56 +0900 Subject: [PATCH 144/184] Move piece files of Mania ruleset --- .../Drawables/Pieces => Skinning/Default}/DefaultBodyPiece.cs | 0 .../Drawables/Pieces => Skinning/Default}/DefaultNotePiece.cs | 0 .../Drawables/Pieces => Skinning/Default}/IHoldNoteBody.cs | 0 .../Skinning/{ => Legacy}/HitTargetInsetContainer.cs | 0 osu.Game.Rulesets.Mania/Skinning/{ => Legacy}/LegacyBodyPiece.cs | 0 .../Skinning/{ => Legacy}/LegacyColumnBackground.cs | 0 .../Skinning/{ => Legacy}/LegacyHitExplosion.cs | 0 osu.Game.Rulesets.Mania/Skinning/{ => Legacy}/LegacyHitTarget.cs | 0 .../Skinning/{ => Legacy}/LegacyHoldNoteHeadPiece.cs | 0 .../Skinning/{ => Legacy}/LegacyHoldNoteTailPiece.cs | 0 osu.Game.Rulesets.Mania/Skinning/{ => Legacy}/LegacyKeyArea.cs | 0 .../Skinning/{ => Legacy}/LegacyManiaColumnElement.cs | 0 osu.Game.Rulesets.Mania/Skinning/{ => Legacy}/LegacyNotePiece.cs | 0 .../Skinning/{ => Legacy}/LegacyStageBackground.cs | 0 .../Skinning/{ => Legacy}/LegacyStageForeground.cs | 0 .../Skinning/{ => Legacy}/ManiaLegacySkinTransformer.cs | 0 16 files changed, 0 insertions(+), 0 deletions(-) rename osu.Game.Rulesets.Mania/{Objects/Drawables/Pieces => Skinning/Default}/DefaultBodyPiece.cs (100%) rename osu.Game.Rulesets.Mania/{Objects/Drawables/Pieces => Skinning/Default}/DefaultNotePiece.cs (100%) rename osu.Game.Rulesets.Mania/{Objects/Drawables/Pieces => Skinning/Default}/IHoldNoteBody.cs (100%) rename osu.Game.Rulesets.Mania/Skinning/{ => Legacy}/HitTargetInsetContainer.cs (100%) rename osu.Game.Rulesets.Mania/Skinning/{ => Legacy}/LegacyBodyPiece.cs (100%) rename osu.Game.Rulesets.Mania/Skinning/{ => Legacy}/LegacyColumnBackground.cs (100%) rename osu.Game.Rulesets.Mania/Skinning/{ => Legacy}/LegacyHitExplosion.cs (100%) rename osu.Game.Rulesets.Mania/Skinning/{ => Legacy}/LegacyHitTarget.cs (100%) rename osu.Game.Rulesets.Mania/Skinning/{ => Legacy}/LegacyHoldNoteHeadPiece.cs (100%) rename osu.Game.Rulesets.Mania/Skinning/{ => Legacy}/LegacyHoldNoteTailPiece.cs (100%) rename osu.Game.Rulesets.Mania/Skinning/{ => Legacy}/LegacyKeyArea.cs (100%) rename osu.Game.Rulesets.Mania/Skinning/{ => Legacy}/LegacyManiaColumnElement.cs (100%) rename osu.Game.Rulesets.Mania/Skinning/{ => Legacy}/LegacyNotePiece.cs (100%) rename osu.Game.Rulesets.Mania/Skinning/{ => Legacy}/LegacyStageBackground.cs (100%) rename osu.Game.Rulesets.Mania/Skinning/{ => Legacy}/LegacyStageForeground.cs (100%) rename osu.Game.Rulesets.Mania/Skinning/{ => Legacy}/ManiaLegacySkinTransformer.cs (100%) diff --git a/osu.Game.Rulesets.Mania/Objects/Drawables/Pieces/DefaultBodyPiece.cs b/osu.Game.Rulesets.Mania/Skinning/Default/DefaultBodyPiece.cs similarity index 100% rename from osu.Game.Rulesets.Mania/Objects/Drawables/Pieces/DefaultBodyPiece.cs rename to osu.Game.Rulesets.Mania/Skinning/Default/DefaultBodyPiece.cs diff --git a/osu.Game.Rulesets.Mania/Objects/Drawables/Pieces/DefaultNotePiece.cs b/osu.Game.Rulesets.Mania/Skinning/Default/DefaultNotePiece.cs similarity index 100% rename from osu.Game.Rulesets.Mania/Objects/Drawables/Pieces/DefaultNotePiece.cs rename to osu.Game.Rulesets.Mania/Skinning/Default/DefaultNotePiece.cs diff --git a/osu.Game.Rulesets.Mania/Objects/Drawables/Pieces/IHoldNoteBody.cs b/osu.Game.Rulesets.Mania/Skinning/Default/IHoldNoteBody.cs similarity index 100% rename from osu.Game.Rulesets.Mania/Objects/Drawables/Pieces/IHoldNoteBody.cs rename to osu.Game.Rulesets.Mania/Skinning/Default/IHoldNoteBody.cs diff --git a/osu.Game.Rulesets.Mania/Skinning/HitTargetInsetContainer.cs b/osu.Game.Rulesets.Mania/Skinning/Legacy/HitTargetInsetContainer.cs similarity index 100% rename from osu.Game.Rulesets.Mania/Skinning/HitTargetInsetContainer.cs rename to osu.Game.Rulesets.Mania/Skinning/Legacy/HitTargetInsetContainer.cs diff --git a/osu.Game.Rulesets.Mania/Skinning/LegacyBodyPiece.cs b/osu.Game.Rulesets.Mania/Skinning/Legacy/LegacyBodyPiece.cs similarity index 100% rename from osu.Game.Rulesets.Mania/Skinning/LegacyBodyPiece.cs rename to osu.Game.Rulesets.Mania/Skinning/Legacy/LegacyBodyPiece.cs diff --git a/osu.Game.Rulesets.Mania/Skinning/LegacyColumnBackground.cs b/osu.Game.Rulesets.Mania/Skinning/Legacy/LegacyColumnBackground.cs similarity index 100% rename from osu.Game.Rulesets.Mania/Skinning/LegacyColumnBackground.cs rename to osu.Game.Rulesets.Mania/Skinning/Legacy/LegacyColumnBackground.cs diff --git a/osu.Game.Rulesets.Mania/Skinning/LegacyHitExplosion.cs b/osu.Game.Rulesets.Mania/Skinning/Legacy/LegacyHitExplosion.cs similarity index 100% rename from osu.Game.Rulesets.Mania/Skinning/LegacyHitExplosion.cs rename to osu.Game.Rulesets.Mania/Skinning/Legacy/LegacyHitExplosion.cs diff --git a/osu.Game.Rulesets.Mania/Skinning/LegacyHitTarget.cs b/osu.Game.Rulesets.Mania/Skinning/Legacy/LegacyHitTarget.cs similarity index 100% rename from osu.Game.Rulesets.Mania/Skinning/LegacyHitTarget.cs rename to osu.Game.Rulesets.Mania/Skinning/Legacy/LegacyHitTarget.cs diff --git a/osu.Game.Rulesets.Mania/Skinning/LegacyHoldNoteHeadPiece.cs b/osu.Game.Rulesets.Mania/Skinning/Legacy/LegacyHoldNoteHeadPiece.cs similarity index 100% rename from osu.Game.Rulesets.Mania/Skinning/LegacyHoldNoteHeadPiece.cs rename to osu.Game.Rulesets.Mania/Skinning/Legacy/LegacyHoldNoteHeadPiece.cs diff --git a/osu.Game.Rulesets.Mania/Skinning/LegacyHoldNoteTailPiece.cs b/osu.Game.Rulesets.Mania/Skinning/Legacy/LegacyHoldNoteTailPiece.cs similarity index 100% rename from osu.Game.Rulesets.Mania/Skinning/LegacyHoldNoteTailPiece.cs rename to osu.Game.Rulesets.Mania/Skinning/Legacy/LegacyHoldNoteTailPiece.cs diff --git a/osu.Game.Rulesets.Mania/Skinning/LegacyKeyArea.cs b/osu.Game.Rulesets.Mania/Skinning/Legacy/LegacyKeyArea.cs similarity index 100% rename from osu.Game.Rulesets.Mania/Skinning/LegacyKeyArea.cs rename to osu.Game.Rulesets.Mania/Skinning/Legacy/LegacyKeyArea.cs diff --git a/osu.Game.Rulesets.Mania/Skinning/LegacyManiaColumnElement.cs b/osu.Game.Rulesets.Mania/Skinning/Legacy/LegacyManiaColumnElement.cs similarity index 100% rename from osu.Game.Rulesets.Mania/Skinning/LegacyManiaColumnElement.cs rename to osu.Game.Rulesets.Mania/Skinning/Legacy/LegacyManiaColumnElement.cs diff --git a/osu.Game.Rulesets.Mania/Skinning/LegacyNotePiece.cs b/osu.Game.Rulesets.Mania/Skinning/Legacy/LegacyNotePiece.cs similarity index 100% rename from osu.Game.Rulesets.Mania/Skinning/LegacyNotePiece.cs rename to osu.Game.Rulesets.Mania/Skinning/Legacy/LegacyNotePiece.cs diff --git a/osu.Game.Rulesets.Mania/Skinning/LegacyStageBackground.cs b/osu.Game.Rulesets.Mania/Skinning/Legacy/LegacyStageBackground.cs similarity index 100% rename from osu.Game.Rulesets.Mania/Skinning/LegacyStageBackground.cs rename to osu.Game.Rulesets.Mania/Skinning/Legacy/LegacyStageBackground.cs diff --git a/osu.Game.Rulesets.Mania/Skinning/LegacyStageForeground.cs b/osu.Game.Rulesets.Mania/Skinning/Legacy/LegacyStageForeground.cs similarity index 100% rename from osu.Game.Rulesets.Mania/Skinning/LegacyStageForeground.cs rename to osu.Game.Rulesets.Mania/Skinning/Legacy/LegacyStageForeground.cs diff --git a/osu.Game.Rulesets.Mania/Skinning/ManiaLegacySkinTransformer.cs b/osu.Game.Rulesets.Mania/Skinning/Legacy/ManiaLegacySkinTransformer.cs similarity index 100% rename from osu.Game.Rulesets.Mania/Skinning/ManiaLegacySkinTransformer.cs rename to osu.Game.Rulesets.Mania/Skinning/Legacy/ManiaLegacySkinTransformer.cs From e3c035fe9c651ac1eec750dd8197bbc037e9e994 Mon Sep 17 00:00:00 2001 From: ekrctb Date: Mon, 7 Dec 2020 12:32:52 +0900 Subject: [PATCH 145/184] Adjust namespace --- .../Editor/TestSceneManiaHitObjectComposer.cs | 2 +- .../Skinning/TestSceneHitExplosion.cs | 2 +- .../Edit/Blueprints/Components/EditBodyPiece.cs | 2 +- .../Edit/Blueprints/Components/EditNotePiece.cs | 2 +- .../Edit/ManiaHitObjectComposer.cs | 2 +- osu.Game.Rulesets.Mania/ManiaRuleset.cs | 2 +- .../Objects/Drawables/DrawableHoldNote.cs | 2 +- .../Objects/Drawables/DrawableNote.cs | 2 +- .../Skinning/Default/DefaultBodyPiece.cs | 5 +++-- .../Skinning/Default/DefaultNotePiece.cs | 4 ++-- .../Skinning/Default/IHoldNoteBody.cs | 2 +- .../Skinning/Legacy/HitTargetInsetContainer.cs | 2 +- .../Skinning/Legacy/LegacyBodyPiece.cs | 2 +- .../Skinning/Legacy/LegacyColumnBackground.cs | 2 +- .../Skinning/Legacy/LegacyHitExplosion.cs | 2 +- .../Skinning/Legacy/LegacyHitTarget.cs | 2 +- .../Skinning/Legacy/LegacyHoldNoteHeadPiece.cs | 2 +- .../Skinning/Legacy/LegacyHoldNoteTailPiece.cs | 2 +- .../Skinning/Legacy/LegacyKeyArea.cs | 2 +- .../Skinning/Legacy/LegacyManiaColumnElement.cs | 2 +- .../Skinning/Legacy/LegacyNotePiece.cs | 2 +- .../Skinning/Legacy/LegacyStageBackground.cs | 2 +- .../Skinning/Legacy/LegacyStageForeground.cs | 2 +- .../Skinning/Legacy/ManiaLegacySkinTransformer.cs | 14 +++++++------- .../UI/Components/DefaultHitTarget.cs | 2 +- osu.Game.Rulesets.Mania/UI/DefaultHitExplosion.cs | 2 +- 26 files changed, 35 insertions(+), 34 deletions(-) diff --git a/osu.Game.Rulesets.Mania.Tests/Editor/TestSceneManiaHitObjectComposer.cs b/osu.Game.Rulesets.Mania.Tests/Editor/TestSceneManiaHitObjectComposer.cs index c9551ee79e..aaf96c63a6 100644 --- a/osu.Game.Rulesets.Mania.Tests/Editor/TestSceneManiaHitObjectComposer.cs +++ b/osu.Game.Rulesets.Mania.Tests/Editor/TestSceneManiaHitObjectComposer.cs @@ -15,7 +15,7 @@ using osu.Game.Rulesets.Mania.Edit; using osu.Game.Rulesets.Mania.Edit.Blueprints; using osu.Game.Rulesets.Mania.Objects; using osu.Game.Rulesets.Mania.Objects.Drawables; -using osu.Game.Rulesets.Mania.Objects.Drawables.Pieces; +using osu.Game.Rulesets.Mania.Skinning.Default; using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.UI.Scrolling; using osu.Game.Screens.Edit; diff --git a/osu.Game.Rulesets.Mania.Tests/Skinning/TestSceneHitExplosion.cs b/osu.Game.Rulesets.Mania.Tests/Skinning/TestSceneHitExplosion.cs index 0c56f7bcf4..4dc6700786 100644 --- a/osu.Game.Rulesets.Mania.Tests/Skinning/TestSceneHitExplosion.cs +++ b/osu.Game.Rulesets.Mania.Tests/Skinning/TestSceneHitExplosion.cs @@ -10,7 +10,7 @@ using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Pooling; using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Mania.Judgements; -using osu.Game.Rulesets.Mania.Objects.Drawables.Pieces; +using osu.Game.Rulesets.Mania.Skinning.Default; using osu.Game.Rulesets.Mania.UI; using osu.Game.Rulesets.Objects; using osuTK; diff --git a/osu.Game.Rulesets.Mania/Edit/Blueprints/Components/EditBodyPiece.cs b/osu.Game.Rulesets.Mania/Edit/Blueprints/Components/EditBodyPiece.cs index 5fa687298a..f5067ea366 100644 --- a/osu.Game.Rulesets.Mania/Edit/Blueprints/Components/EditBodyPiece.cs +++ b/osu.Game.Rulesets.Mania/Edit/Blueprints/Components/EditBodyPiece.cs @@ -4,7 +4,7 @@ using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Game.Graphics; -using osu.Game.Rulesets.Mania.Objects.Drawables.Pieces; +using osu.Game.Rulesets.Mania.Skinning.Default; namespace osu.Game.Rulesets.Mania.Edit.Blueprints.Components { diff --git a/osu.Game.Rulesets.Mania/Edit/Blueprints/Components/EditNotePiece.cs b/osu.Game.Rulesets.Mania/Edit/Blueprints/Components/EditNotePiece.cs index 8773a39939..9c9273de3a 100644 --- a/osu.Game.Rulesets.Mania/Edit/Blueprints/Components/EditNotePiece.cs +++ b/osu.Game.Rulesets.Mania/Edit/Blueprints/Components/EditNotePiece.cs @@ -4,7 +4,7 @@ using osu.Framework.Allocation; using osu.Framework.Graphics.Containers; using osu.Game.Graphics; -using osu.Game.Rulesets.Mania.Objects.Drawables.Pieces; +using osu.Game.Rulesets.Mania.Skinning.Default; namespace osu.Game.Rulesets.Mania.Edit.Blueprints.Components { diff --git a/osu.Game.Rulesets.Mania/Edit/ManiaHitObjectComposer.cs b/osu.Game.Rulesets.Mania/Edit/ManiaHitObjectComposer.cs index 01d572447b..324670c4b2 100644 --- a/osu.Game.Rulesets.Mania/Edit/ManiaHitObjectComposer.cs +++ b/osu.Game.Rulesets.Mania/Edit/ManiaHitObjectComposer.cs @@ -9,7 +9,7 @@ using System.Collections.Generic; using System.Linq; using osu.Framework.Allocation; using osu.Framework.Input; -using osu.Game.Rulesets.Mania.Objects.Drawables.Pieces; +using osu.Game.Rulesets.Mania.Skinning.Default; using osu.Game.Rulesets.Mania.UI; using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.Objects; diff --git a/osu.Game.Rulesets.Mania/ManiaRuleset.cs b/osu.Game.Rulesets.Mania/ManiaRuleset.cs index 906f7382c5..59c766fd84 100644 --- a/osu.Game.Rulesets.Mania/ManiaRuleset.cs +++ b/osu.Game.Rulesets.Mania/ManiaRuleset.cs @@ -26,7 +26,7 @@ using osu.Game.Rulesets.Mania.Configuration; using osu.Game.Rulesets.Mania.Difficulty; using osu.Game.Rulesets.Mania.Edit; using osu.Game.Rulesets.Mania.Scoring; -using osu.Game.Rulesets.Mania.Skinning; +using osu.Game.Rulesets.Mania.Skinning.Legacy; using osu.Game.Rulesets.Scoring; using osu.Game.Skinning; using osu.Game.Scoring; diff --git a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNote.cs b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNote.cs index a64cc6dc67..4f062753a6 100644 --- a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNote.cs +++ b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNote.cs @@ -4,9 +4,9 @@ using System; using osu.Framework.Bindables; using osu.Framework.Graphics; -using osu.Game.Rulesets.Mania.Objects.Drawables.Pieces; using osu.Framework.Graphics.Containers; using osu.Framework.Input.Bindings; +using osu.Game.Rulesets.Mania.Skinning.Default; using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.Scoring; diff --git a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableNote.cs b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableNote.cs index b3402d13e4..b512986ccb 100644 --- a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableNote.cs +++ b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableNote.cs @@ -5,7 +5,7 @@ using System.Diagnostics; using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Input.Bindings; -using osu.Game.Rulesets.Mania.Objects.Drawables.Pieces; +using osu.Game.Rulesets.Mania.Skinning.Default; using osu.Game.Rulesets.Scoring; using osu.Game.Rulesets.UI.Scrolling; using osu.Game.Skinning; diff --git a/osu.Game.Rulesets.Mania/Skinning/Default/DefaultBodyPiece.cs b/osu.Game.Rulesets.Mania/Skinning/Default/DefaultBodyPiece.cs index 9999983af5..db1ac6da88 100644 --- a/osu.Game.Rulesets.Mania/Skinning/Default/DefaultBodyPiece.cs +++ b/osu.Game.Rulesets.Mania/Skinning/Default/DefaultBodyPiece.cs @@ -5,16 +5,17 @@ using System; using JetBrains.Annotations; using osu.Framework.Allocation; using osu.Framework.Bindables; -using osuTK.Graphics; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Effects; using osu.Framework.Graphics.Shapes; using osu.Framework.Layout; +using osu.Game.Rulesets.Mania.Objects.Drawables; using osu.Game.Rulesets.Objects.Drawables; +using osuTK.Graphics; -namespace osu.Game.Rulesets.Mania.Objects.Drawables.Pieces +namespace osu.Game.Rulesets.Mania.Skinning.Default { /// /// Represents length-wise portion of a hold note. diff --git a/osu.Game.Rulesets.Mania/Skinning/Default/DefaultNotePiece.cs b/osu.Game.Rulesets.Mania/Skinning/Default/DefaultNotePiece.cs index 29f5217fd8..c9c3cff799 100644 --- a/osu.Game.Rulesets.Mania/Skinning/Default/DefaultNotePiece.cs +++ b/osu.Game.Rulesets.Mania/Skinning/Default/DefaultNotePiece.cs @@ -4,7 +4,6 @@ using JetBrains.Annotations; using osu.Framework.Allocation; using osu.Framework.Bindables; -using osuTK.Graphics; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; @@ -12,8 +11,9 @@ using osu.Framework.Graphics.Effects; using osu.Framework.Graphics.Shapes; using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.UI.Scrolling; +using osuTK.Graphics; -namespace osu.Game.Rulesets.Mania.Objects.Drawables.Pieces +namespace osu.Game.Rulesets.Mania.Skinning.Default { /// /// Represents the static hit markers of notes. diff --git a/osu.Game.Rulesets.Mania/Skinning/Default/IHoldNoteBody.cs b/osu.Game.Rulesets.Mania/Skinning/Default/IHoldNoteBody.cs index ac3792c01d..1f290f1f1c 100644 --- a/osu.Game.Rulesets.Mania/Skinning/Default/IHoldNoteBody.cs +++ b/osu.Game.Rulesets.Mania/Skinning/Default/IHoldNoteBody.cs @@ -1,7 +1,7 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -namespace osu.Game.Rulesets.Mania.Objects.Drawables.Pieces +namespace osu.Game.Rulesets.Mania.Skinning.Default { /// /// Interface for mania hold note bodies. diff --git a/osu.Game.Rulesets.Mania/Skinning/Legacy/HitTargetInsetContainer.cs b/osu.Game.Rulesets.Mania/Skinning/Legacy/HitTargetInsetContainer.cs index c8b05ed2f8..3c89e2c04a 100644 --- a/osu.Game.Rulesets.Mania/Skinning/Legacy/HitTargetInsetContainer.cs +++ b/osu.Game.Rulesets.Mania/Skinning/Legacy/HitTargetInsetContainer.cs @@ -9,7 +9,7 @@ using osu.Game.Rulesets.Mania.UI; using osu.Game.Rulesets.UI.Scrolling; using osu.Game.Skinning; -namespace osu.Game.Rulesets.Mania.Skinning +namespace osu.Game.Rulesets.Mania.Skinning.Legacy { public class HitTargetInsetContainer : Container { diff --git a/osu.Game.Rulesets.Mania/Skinning/Legacy/LegacyBodyPiece.cs b/osu.Game.Rulesets.Mania/Skinning/Legacy/LegacyBodyPiece.cs index 8902d82f33..31db08ce2f 100644 --- a/osu.Game.Rulesets.Mania/Skinning/Legacy/LegacyBodyPiece.cs +++ b/osu.Game.Rulesets.Mania/Skinning/Legacy/LegacyBodyPiece.cs @@ -14,7 +14,7 @@ using osu.Game.Rulesets.UI.Scrolling; using osu.Game.Skinning; using osuTK; -namespace osu.Game.Rulesets.Mania.Skinning +namespace osu.Game.Rulesets.Mania.Skinning.Legacy { public class LegacyBodyPiece : LegacyManiaColumnElement { diff --git a/osu.Game.Rulesets.Mania/Skinning/Legacy/LegacyColumnBackground.cs b/osu.Game.Rulesets.Mania/Skinning/Legacy/LegacyColumnBackground.cs index 3bf51b3073..661e7f66f4 100644 --- a/osu.Game.Rulesets.Mania/Skinning/Legacy/LegacyColumnBackground.cs +++ b/osu.Game.Rulesets.Mania/Skinning/Legacy/LegacyColumnBackground.cs @@ -12,7 +12,7 @@ using osu.Game.Skinning; using osuTK; using osuTK.Graphics; -namespace osu.Game.Rulesets.Mania.Skinning +namespace osu.Game.Rulesets.Mania.Skinning.Legacy { public class LegacyColumnBackground : LegacyManiaColumnElement, IKeyBindingHandler { diff --git a/osu.Game.Rulesets.Mania/Skinning/Legacy/LegacyHitExplosion.cs b/osu.Game.Rulesets.Mania/Skinning/Legacy/LegacyHitExplosion.cs index 7c5d41efcf..73aece1ed4 100644 --- a/osu.Game.Rulesets.Mania/Skinning/Legacy/LegacyHitExplosion.cs +++ b/osu.Game.Rulesets.Mania/Skinning/Legacy/LegacyHitExplosion.cs @@ -13,7 +13,7 @@ using osu.Game.Rulesets.UI.Scrolling; using osu.Game.Skinning; using osuTK; -namespace osu.Game.Rulesets.Mania.Skinning +namespace osu.Game.Rulesets.Mania.Skinning.Legacy { public class LegacyHitExplosion : LegacyManiaColumnElement, IHitExplosion { diff --git a/osu.Game.Rulesets.Mania/Skinning/Legacy/LegacyHitTarget.cs b/osu.Game.Rulesets.Mania/Skinning/Legacy/LegacyHitTarget.cs index 6eced571d2..490a03d11a 100644 --- a/osu.Game.Rulesets.Mania/Skinning/Legacy/LegacyHitTarget.cs +++ b/osu.Game.Rulesets.Mania/Skinning/Legacy/LegacyHitTarget.cs @@ -12,7 +12,7 @@ using osu.Game.Skinning; using osuTK; using osuTK.Graphics; -namespace osu.Game.Rulesets.Mania.Skinning +namespace osu.Game.Rulesets.Mania.Skinning.Legacy { public class LegacyHitTarget : CompositeDrawable { diff --git a/osu.Game.Rulesets.Mania/Skinning/Legacy/LegacyHoldNoteHeadPiece.cs b/osu.Game.Rulesets.Mania/Skinning/Legacy/LegacyHoldNoteHeadPiece.cs index c5aa062d0f..21e5bdd5d6 100644 --- a/osu.Game.Rulesets.Mania/Skinning/Legacy/LegacyHoldNoteHeadPiece.cs +++ b/osu.Game.Rulesets.Mania/Skinning/Legacy/LegacyHoldNoteHeadPiece.cs @@ -4,7 +4,7 @@ using osu.Framework.Graphics.Textures; using osu.Game.Skinning; -namespace osu.Game.Rulesets.Mania.Skinning +namespace osu.Game.Rulesets.Mania.Skinning.Legacy { public class LegacyHoldNoteHeadPiece : LegacyNotePiece { diff --git a/osu.Game.Rulesets.Mania/Skinning/Legacy/LegacyHoldNoteTailPiece.cs b/osu.Game.Rulesets.Mania/Skinning/Legacy/LegacyHoldNoteTailPiece.cs index 2e8259f10a..232b47ae27 100644 --- a/osu.Game.Rulesets.Mania/Skinning/Legacy/LegacyHoldNoteTailPiece.cs +++ b/osu.Game.Rulesets.Mania/Skinning/Legacy/LegacyHoldNoteTailPiece.cs @@ -6,7 +6,7 @@ using osu.Framework.Graphics.Textures; using osu.Game.Rulesets.UI.Scrolling; using osu.Game.Skinning; -namespace osu.Game.Rulesets.Mania.Skinning +namespace osu.Game.Rulesets.Mania.Skinning.Legacy { public class LegacyHoldNoteTailPiece : LegacyNotePiece { diff --git a/osu.Game.Rulesets.Mania/Skinning/Legacy/LegacyKeyArea.cs b/osu.Game.Rulesets.Mania/Skinning/Legacy/LegacyKeyArea.cs index b269ea25d4..78ccb83a8c 100644 --- a/osu.Game.Rulesets.Mania/Skinning/Legacy/LegacyKeyArea.cs +++ b/osu.Game.Rulesets.Mania/Skinning/Legacy/LegacyKeyArea.cs @@ -12,7 +12,7 @@ using osu.Game.Rulesets.UI.Scrolling; using osu.Game.Skinning; using osuTK; -namespace osu.Game.Rulesets.Mania.Skinning +namespace osu.Game.Rulesets.Mania.Skinning.Legacy { public class LegacyKeyArea : LegacyManiaColumnElement, IKeyBindingHandler { diff --git a/osu.Game.Rulesets.Mania/Skinning/Legacy/LegacyManiaColumnElement.cs b/osu.Game.Rulesets.Mania/Skinning/Legacy/LegacyManiaColumnElement.cs index 3c0c632c14..eb5514ba43 100644 --- a/osu.Game.Rulesets.Mania/Skinning/Legacy/LegacyManiaColumnElement.cs +++ b/osu.Game.Rulesets.Mania/Skinning/Legacy/LegacyManiaColumnElement.cs @@ -8,7 +8,7 @@ using osu.Game.Rulesets.Mania.Beatmaps; using osu.Game.Rulesets.Mania.UI; using osu.Game.Skinning; -namespace osu.Game.Rulesets.Mania.Skinning +namespace osu.Game.Rulesets.Mania.Skinning.Legacy { /// /// A which is placed somewhere within a . diff --git a/osu.Game.Rulesets.Mania/Skinning/Legacy/LegacyNotePiece.cs b/osu.Game.Rulesets.Mania/Skinning/Legacy/LegacyNotePiece.cs index 283b04373b..31279796ce 100644 --- a/osu.Game.Rulesets.Mania/Skinning/Legacy/LegacyNotePiece.cs +++ b/osu.Game.Rulesets.Mania/Skinning/Legacy/LegacyNotePiece.cs @@ -12,7 +12,7 @@ using osu.Game.Rulesets.UI.Scrolling; using osu.Game.Skinning; using osuTK; -namespace osu.Game.Rulesets.Mania.Skinning +namespace osu.Game.Rulesets.Mania.Skinning.Legacy { public class LegacyNotePiece : LegacyManiaColumnElement { diff --git a/osu.Game.Rulesets.Mania/Skinning/Legacy/LegacyStageBackground.cs b/osu.Game.Rulesets.Mania/Skinning/Legacy/LegacyStageBackground.cs index b0bab8e760..fec3e9493e 100644 --- a/osu.Game.Rulesets.Mania/Skinning/Legacy/LegacyStageBackground.cs +++ b/osu.Game.Rulesets.Mania/Skinning/Legacy/LegacyStageBackground.cs @@ -12,7 +12,7 @@ using osu.Game.Skinning; using osuTK; using osuTK.Graphics; -namespace osu.Game.Rulesets.Mania.Skinning +namespace osu.Game.Rulesets.Mania.Skinning.Legacy { public class LegacyStageBackground : CompositeDrawable { diff --git a/osu.Game.Rulesets.Mania/Skinning/Legacy/LegacyStageForeground.cs b/osu.Game.Rulesets.Mania/Skinning/Legacy/LegacyStageForeground.cs index 4609fcc849..4e1952a670 100644 --- a/osu.Game.Rulesets.Mania/Skinning/Legacy/LegacyStageForeground.cs +++ b/osu.Game.Rulesets.Mania/Skinning/Legacy/LegacyStageForeground.cs @@ -9,7 +9,7 @@ using osu.Game.Rulesets.UI.Scrolling; using osu.Game.Skinning; using osuTK; -namespace osu.Game.Rulesets.Mania.Skinning +namespace osu.Game.Rulesets.Mania.Skinning.Legacy { public class LegacyStageForeground : CompositeDrawable { diff --git a/osu.Game.Rulesets.Mania/Skinning/Legacy/ManiaLegacySkinTransformer.cs b/osu.Game.Rulesets.Mania/Skinning/Legacy/ManiaLegacySkinTransformer.cs index 3724269f4d..89f639e2fe 100644 --- a/osu.Game.Rulesets.Mania/Skinning/Legacy/ManiaLegacySkinTransformer.cs +++ b/osu.Game.Rulesets.Mania/Skinning/Legacy/ManiaLegacySkinTransformer.cs @@ -2,19 +2,19 @@ // See the LICENCE file in the repository root for full licence text. using System; -using osu.Framework.Graphics; -using osu.Framework.Bindables; -using osu.Game.Rulesets.Scoring; -using osu.Game.Beatmaps; -using osu.Game.Rulesets.Mania.Beatmaps; -using osu.Game.Skinning; using System.Collections.Generic; using System.Diagnostics; using osu.Framework.Audio.Sample; +using osu.Framework.Bindables; +using osu.Framework.Graphics; using osu.Game.Audio; +using osu.Game.Beatmaps; +using osu.Game.Rulesets.Mania.Beatmaps; using osu.Game.Rulesets.Objects.Legacy; +using osu.Game.Rulesets.Scoring; +using osu.Game.Skinning; -namespace osu.Game.Rulesets.Mania.Skinning +namespace osu.Game.Rulesets.Mania.Skinning.Legacy { public class ManiaLegacySkinTransformer : LegacySkinTransformer { diff --git a/osu.Game.Rulesets.Mania/UI/Components/DefaultHitTarget.cs b/osu.Game.Rulesets.Mania/UI/Components/DefaultHitTarget.cs index e0b099ab9b..ec6c377a2e 100644 --- a/osu.Game.Rulesets.Mania/UI/Components/DefaultHitTarget.cs +++ b/osu.Game.Rulesets.Mania/UI/Components/DefaultHitTarget.cs @@ -8,7 +8,7 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Effects; using osu.Framework.Graphics.Shapes; -using osu.Game.Rulesets.Mania.Objects.Drawables.Pieces; +using osu.Game.Rulesets.Mania.Skinning.Default; using osu.Game.Rulesets.UI.Scrolling; using osuTK.Graphics; diff --git a/osu.Game.Rulesets.Mania/UI/DefaultHitExplosion.cs b/osu.Game.Rulesets.Mania/UI/DefaultHitExplosion.cs index 225269cf48..69b81d6d5c 100644 --- a/osu.Game.Rulesets.Mania/UI/DefaultHitExplosion.cs +++ b/osu.Game.Rulesets.Mania/UI/DefaultHitExplosion.cs @@ -10,7 +10,7 @@ using osu.Framework.Graphics.Effects; using osu.Framework.Utils; using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Mania.Judgements; -using osu.Game.Rulesets.Mania.Objects.Drawables.Pieces; +using osu.Game.Rulesets.Mania.Skinning.Default; using osu.Game.Rulesets.UI.Scrolling; using osuTK; using osuTK.Graphics; From b4b9312e0f9ad08ae3c9fda7f8d55450d3cbffdf Mon Sep 17 00:00:00 2001 From: ekrctb Date: Mon, 7 Dec 2020 12:34:38 +0900 Subject: [PATCH 146/184] Move piece files of Catch ruleset --- .../{Objects/Drawables/Pieces => Skinning/Default}/BananaPiece.cs | 0 .../{Objects/Drawables/Pieces => Skinning/Default}/BorderPiece.cs | 0 .../Drawables/Pieces => Skinning/Default}/DropletPiece.cs | 0 .../{Objects/Drawables/Pieces => Skinning/Default}/FruitPiece.cs | 0 .../{Objects/Drawables/Pieces => Skinning/Default}/GrapePiece.cs | 0 .../Drawables/Pieces => Skinning/Default}/HyperBorderPiece.cs | 0 .../Pieces => Skinning/Default}/HyperDropletBorderPiece.cs | 0 .../{Objects/Drawables/Pieces => Skinning/Default}/PearPiece.cs | 0 .../Drawables/Pieces => Skinning/Default}/PineapplePiece.cs | 0 .../{Objects/Drawables/Pieces => Skinning/Default}/Pulp.cs | 0 .../Drawables/Pieces => Skinning/Default}/PulpFormation.cs | 0 .../Drawables/Pieces => Skinning/Default}/RaspberryPiece.cs | 0 .../Skinning/{ => Legacy}/CatchLegacySkinTransformer.cs | 0 .../Skinning/{ => Legacy}/LegacyCatchComboCounter.cs | 0 osu.Game.Rulesets.Catch/Skinning/{ => Legacy}/LegacyFruitPiece.cs | 0 15 files changed, 0 insertions(+), 0 deletions(-) rename osu.Game.Rulesets.Catch/{Objects/Drawables/Pieces => Skinning/Default}/BananaPiece.cs (100%) rename osu.Game.Rulesets.Catch/{Objects/Drawables/Pieces => Skinning/Default}/BorderPiece.cs (100%) rename osu.Game.Rulesets.Catch/{Objects/Drawables/Pieces => Skinning/Default}/DropletPiece.cs (100%) rename osu.Game.Rulesets.Catch/{Objects/Drawables/Pieces => Skinning/Default}/FruitPiece.cs (100%) rename osu.Game.Rulesets.Catch/{Objects/Drawables/Pieces => Skinning/Default}/GrapePiece.cs (100%) rename osu.Game.Rulesets.Catch/{Objects/Drawables/Pieces => Skinning/Default}/HyperBorderPiece.cs (100%) rename osu.Game.Rulesets.Catch/{Objects/Drawables/Pieces => Skinning/Default}/HyperDropletBorderPiece.cs (100%) rename osu.Game.Rulesets.Catch/{Objects/Drawables/Pieces => Skinning/Default}/PearPiece.cs (100%) rename osu.Game.Rulesets.Catch/{Objects/Drawables/Pieces => Skinning/Default}/PineapplePiece.cs (100%) rename osu.Game.Rulesets.Catch/{Objects/Drawables/Pieces => Skinning/Default}/Pulp.cs (100%) rename osu.Game.Rulesets.Catch/{Objects/Drawables/Pieces => Skinning/Default}/PulpFormation.cs (100%) rename osu.Game.Rulesets.Catch/{Objects/Drawables/Pieces => Skinning/Default}/RaspberryPiece.cs (100%) rename osu.Game.Rulesets.Catch/Skinning/{ => Legacy}/CatchLegacySkinTransformer.cs (100%) rename osu.Game.Rulesets.Catch/Skinning/{ => Legacy}/LegacyCatchComboCounter.cs (100%) rename osu.Game.Rulesets.Catch/Skinning/{ => Legacy}/LegacyFruitPiece.cs (100%) diff --git a/osu.Game.Rulesets.Catch/Objects/Drawables/Pieces/BananaPiece.cs b/osu.Game.Rulesets.Catch/Skinning/Default/BananaPiece.cs similarity index 100% rename from osu.Game.Rulesets.Catch/Objects/Drawables/Pieces/BananaPiece.cs rename to osu.Game.Rulesets.Catch/Skinning/Default/BananaPiece.cs diff --git a/osu.Game.Rulesets.Catch/Objects/Drawables/Pieces/BorderPiece.cs b/osu.Game.Rulesets.Catch/Skinning/Default/BorderPiece.cs similarity index 100% rename from osu.Game.Rulesets.Catch/Objects/Drawables/Pieces/BorderPiece.cs rename to osu.Game.Rulesets.Catch/Skinning/Default/BorderPiece.cs diff --git a/osu.Game.Rulesets.Catch/Objects/Drawables/Pieces/DropletPiece.cs b/osu.Game.Rulesets.Catch/Skinning/Default/DropletPiece.cs similarity index 100% rename from osu.Game.Rulesets.Catch/Objects/Drawables/Pieces/DropletPiece.cs rename to osu.Game.Rulesets.Catch/Skinning/Default/DropletPiece.cs diff --git a/osu.Game.Rulesets.Catch/Objects/Drawables/Pieces/FruitPiece.cs b/osu.Game.Rulesets.Catch/Skinning/Default/FruitPiece.cs similarity index 100% rename from osu.Game.Rulesets.Catch/Objects/Drawables/Pieces/FruitPiece.cs rename to osu.Game.Rulesets.Catch/Skinning/Default/FruitPiece.cs diff --git a/osu.Game.Rulesets.Catch/Objects/Drawables/Pieces/GrapePiece.cs b/osu.Game.Rulesets.Catch/Skinning/Default/GrapePiece.cs similarity index 100% rename from osu.Game.Rulesets.Catch/Objects/Drawables/Pieces/GrapePiece.cs rename to osu.Game.Rulesets.Catch/Skinning/Default/GrapePiece.cs diff --git a/osu.Game.Rulesets.Catch/Objects/Drawables/Pieces/HyperBorderPiece.cs b/osu.Game.Rulesets.Catch/Skinning/Default/HyperBorderPiece.cs similarity index 100% rename from osu.Game.Rulesets.Catch/Objects/Drawables/Pieces/HyperBorderPiece.cs rename to osu.Game.Rulesets.Catch/Skinning/Default/HyperBorderPiece.cs diff --git a/osu.Game.Rulesets.Catch/Objects/Drawables/Pieces/HyperDropletBorderPiece.cs b/osu.Game.Rulesets.Catch/Skinning/Default/HyperDropletBorderPiece.cs similarity index 100% rename from osu.Game.Rulesets.Catch/Objects/Drawables/Pieces/HyperDropletBorderPiece.cs rename to osu.Game.Rulesets.Catch/Skinning/Default/HyperDropletBorderPiece.cs diff --git a/osu.Game.Rulesets.Catch/Objects/Drawables/Pieces/PearPiece.cs b/osu.Game.Rulesets.Catch/Skinning/Default/PearPiece.cs similarity index 100% rename from osu.Game.Rulesets.Catch/Objects/Drawables/Pieces/PearPiece.cs rename to osu.Game.Rulesets.Catch/Skinning/Default/PearPiece.cs diff --git a/osu.Game.Rulesets.Catch/Objects/Drawables/Pieces/PineapplePiece.cs b/osu.Game.Rulesets.Catch/Skinning/Default/PineapplePiece.cs similarity index 100% rename from osu.Game.Rulesets.Catch/Objects/Drawables/Pieces/PineapplePiece.cs rename to osu.Game.Rulesets.Catch/Skinning/Default/PineapplePiece.cs diff --git a/osu.Game.Rulesets.Catch/Objects/Drawables/Pieces/Pulp.cs b/osu.Game.Rulesets.Catch/Skinning/Default/Pulp.cs similarity index 100% rename from osu.Game.Rulesets.Catch/Objects/Drawables/Pieces/Pulp.cs rename to osu.Game.Rulesets.Catch/Skinning/Default/Pulp.cs diff --git a/osu.Game.Rulesets.Catch/Objects/Drawables/Pieces/PulpFormation.cs b/osu.Game.Rulesets.Catch/Skinning/Default/PulpFormation.cs similarity index 100% rename from osu.Game.Rulesets.Catch/Objects/Drawables/Pieces/PulpFormation.cs rename to osu.Game.Rulesets.Catch/Skinning/Default/PulpFormation.cs diff --git a/osu.Game.Rulesets.Catch/Objects/Drawables/Pieces/RaspberryPiece.cs b/osu.Game.Rulesets.Catch/Skinning/Default/RaspberryPiece.cs similarity index 100% rename from osu.Game.Rulesets.Catch/Objects/Drawables/Pieces/RaspberryPiece.cs rename to osu.Game.Rulesets.Catch/Skinning/Default/RaspberryPiece.cs diff --git a/osu.Game.Rulesets.Catch/Skinning/CatchLegacySkinTransformer.cs b/osu.Game.Rulesets.Catch/Skinning/Legacy/CatchLegacySkinTransformer.cs similarity index 100% rename from osu.Game.Rulesets.Catch/Skinning/CatchLegacySkinTransformer.cs rename to osu.Game.Rulesets.Catch/Skinning/Legacy/CatchLegacySkinTransformer.cs diff --git a/osu.Game.Rulesets.Catch/Skinning/LegacyCatchComboCounter.cs b/osu.Game.Rulesets.Catch/Skinning/Legacy/LegacyCatchComboCounter.cs similarity index 100% rename from osu.Game.Rulesets.Catch/Skinning/LegacyCatchComboCounter.cs rename to osu.Game.Rulesets.Catch/Skinning/Legacy/LegacyCatchComboCounter.cs diff --git a/osu.Game.Rulesets.Catch/Skinning/LegacyFruitPiece.cs b/osu.Game.Rulesets.Catch/Skinning/Legacy/LegacyFruitPiece.cs similarity index 100% rename from osu.Game.Rulesets.Catch/Skinning/LegacyFruitPiece.cs rename to osu.Game.Rulesets.Catch/Skinning/Legacy/LegacyFruitPiece.cs From d18397acad71b87231ee5b15e5751426428f81cb Mon Sep 17 00:00:00 2001 From: ekrctb Date: Mon, 7 Dec 2020 12:35:24 +0900 Subject: [PATCH 147/184] Adjust namespace --- osu.Game.Rulesets.Catch.Tests/CatchSkinColourDecodingTest.cs | 1 + osu.Game.Rulesets.Catch.Tests/TestSceneHyperDashColouring.cs | 1 + osu.Game.Rulesets.Catch/CatchRuleset.cs | 2 +- osu.Game.Rulesets.Catch/Objects/Drawables/DrawableDroplet.cs | 2 +- osu.Game.Rulesets.Catch/Objects/Drawables/DrawableFruit.cs | 2 +- osu.Game.Rulesets.Catch/Skinning/Default/BananaPiece.cs | 2 +- osu.Game.Rulesets.Catch/Skinning/Default/BorderPiece.cs | 3 ++- osu.Game.Rulesets.Catch/Skinning/Default/DropletPiece.cs | 3 ++- osu.Game.Rulesets.Catch/Skinning/Default/FruitPiece.cs | 3 ++- osu.Game.Rulesets.Catch/Skinning/Default/GrapePiece.cs | 2 +- osu.Game.Rulesets.Catch/Skinning/Default/HyperBorderPiece.cs | 2 +- .../Skinning/Default/HyperDropletBorderPiece.cs | 2 +- osu.Game.Rulesets.Catch/Skinning/Default/PearPiece.cs | 2 +- osu.Game.Rulesets.Catch/Skinning/Default/PineapplePiece.cs | 2 +- osu.Game.Rulesets.Catch/Skinning/Default/Pulp.cs | 2 +- osu.Game.Rulesets.Catch/Skinning/Default/PulpFormation.cs | 3 ++- osu.Game.Rulesets.Catch/Skinning/Default/RaspberryPiece.cs | 2 +- .../Skinning/Legacy/CatchLegacySkinTransformer.cs | 2 +- .../Skinning/Legacy/LegacyCatchComboCounter.cs | 2 +- osu.Game.Rulesets.Catch/Skinning/Legacy/LegacyFruitPiece.cs | 2 +- 20 files changed, 24 insertions(+), 18 deletions(-) diff --git a/osu.Game.Rulesets.Catch.Tests/CatchSkinColourDecodingTest.cs b/osu.Game.Rulesets.Catch.Tests/CatchSkinColourDecodingTest.cs index b570f090ca..e70def7f8b 100644 --- a/osu.Game.Rulesets.Catch.Tests/CatchSkinColourDecodingTest.cs +++ b/osu.Game.Rulesets.Catch.Tests/CatchSkinColourDecodingTest.cs @@ -4,6 +4,7 @@ using NUnit.Framework; using osu.Framework.IO.Stores; using osu.Game.Rulesets.Catch.Skinning; +using osu.Game.Rulesets.Catch.Skinning.Legacy; using osu.Game.Skinning; using osuTK.Graphics; diff --git a/osu.Game.Rulesets.Catch.Tests/TestSceneHyperDashColouring.cs b/osu.Game.Rulesets.Catch.Tests/TestSceneHyperDashColouring.cs index 07cb73e5ff..d78dc2d2b5 100644 --- a/osu.Game.Rulesets.Catch.Tests/TestSceneHyperDashColouring.cs +++ b/osu.Game.Rulesets.Catch.Tests/TestSceneHyperDashColouring.cs @@ -13,6 +13,7 @@ using osu.Game.Beatmaps.ControlPoints; using osu.Game.Rulesets.Catch.Objects; using osu.Game.Rulesets.Catch.Objects.Drawables; using osu.Game.Rulesets.Catch.Skinning; +using osu.Game.Rulesets.Catch.Skinning.Legacy; using osu.Game.Rulesets.Catch.UI; using osu.Game.Skinning; using osu.Game.Tests.Visual; diff --git a/osu.Game.Rulesets.Catch/CatchRuleset.cs b/osu.Game.Rulesets.Catch/CatchRuleset.cs index ad584d3f48..0a817eca0d 100644 --- a/osu.Game.Rulesets.Catch/CatchRuleset.cs +++ b/osu.Game.Rulesets.Catch/CatchRuleset.cs @@ -21,7 +21,7 @@ using osu.Game.Rulesets.Difficulty; using osu.Game.Rulesets.Scoring; using osu.Game.Scoring; using System; -using osu.Game.Rulesets.Catch.Skinning; +using osu.Game.Rulesets.Catch.Skinning.Legacy; using osu.Game.Skinning; namespace osu.Game.Rulesets.Catch diff --git a/osu.Game.Rulesets.Catch/Objects/Drawables/DrawableDroplet.cs b/osu.Game.Rulesets.Catch/Objects/Drawables/DrawableDroplet.cs index b8acea625b..e87d862fa5 100644 --- a/osu.Game.Rulesets.Catch/Objects/Drawables/DrawableDroplet.cs +++ b/osu.Game.Rulesets.Catch/Objects/Drawables/DrawableDroplet.cs @@ -4,7 +4,7 @@ using JetBrains.Annotations; using osu.Framework.Allocation; using osu.Framework.Graphics; -using osu.Game.Rulesets.Catch.Objects.Drawables.Pieces; +using osu.Game.Rulesets.Catch.Skinning.Default; using osu.Game.Skinning; namespace osu.Game.Rulesets.Catch.Objects.Drawables diff --git a/osu.Game.Rulesets.Catch/Objects/Drawables/DrawableFruit.cs b/osu.Game.Rulesets.Catch/Objects/Drawables/DrawableFruit.cs index ef9df02a68..da2529615e 100644 --- a/osu.Game.Rulesets.Catch/Objects/Drawables/DrawableFruit.cs +++ b/osu.Game.Rulesets.Catch/Objects/Drawables/DrawableFruit.cs @@ -6,7 +6,7 @@ using JetBrains.Annotations; using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; -using osu.Game.Rulesets.Catch.Objects.Drawables.Pieces; +using osu.Game.Rulesets.Catch.Skinning.Default; using osu.Game.Skinning; namespace osu.Game.Rulesets.Catch.Objects.Drawables diff --git a/osu.Game.Rulesets.Catch/Skinning/Default/BananaPiece.cs b/osu.Game.Rulesets.Catch/Skinning/Default/BananaPiece.cs index fa8837dec5..815855dbcf 100644 --- a/osu.Game.Rulesets.Catch/Skinning/Default/BananaPiece.cs +++ b/osu.Game.Rulesets.Catch/Skinning/Default/BananaPiece.cs @@ -4,7 +4,7 @@ using osu.Framework.Graphics; using osuTK; -namespace osu.Game.Rulesets.Catch.Objects.Drawables.Pieces +namespace osu.Game.Rulesets.Catch.Skinning.Default { public class BananaPiece : PulpFormation { diff --git a/osu.Game.Rulesets.Catch/Skinning/Default/BorderPiece.cs b/osu.Game.Rulesets.Catch/Skinning/Default/BorderPiece.cs index 1e7a0b0685..7308d6b499 100644 --- a/osu.Game.Rulesets.Catch/Skinning/Default/BorderPiece.cs +++ b/osu.Game.Rulesets.Catch/Skinning/Default/BorderPiece.cs @@ -3,10 +3,11 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Shapes; +using osu.Game.Rulesets.Catch.Objects; using osuTK; using osuTK.Graphics; -namespace osu.Game.Rulesets.Catch.Objects.Drawables.Pieces +namespace osu.Game.Rulesets.Catch.Skinning.Default { public class BorderPiece : Circle { diff --git a/osu.Game.Rulesets.Catch/Skinning/Default/DropletPiece.cs b/osu.Game.Rulesets.Catch/Skinning/Default/DropletPiece.cs index c90407ae15..0d305dbca5 100644 --- a/osu.Game.Rulesets.Catch/Skinning/Default/DropletPiece.cs +++ b/osu.Game.Rulesets.Catch/Skinning/Default/DropletPiece.cs @@ -5,10 +5,11 @@ using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; +using osu.Game.Rulesets.Catch.Objects; using osu.Game.Rulesets.Objects.Drawables; using osuTK; -namespace osu.Game.Rulesets.Catch.Objects.Drawables.Pieces +namespace osu.Game.Rulesets.Catch.Skinning.Default { public class DropletPiece : CompositeDrawable { diff --git a/osu.Game.Rulesets.Catch/Skinning/Default/FruitPiece.cs b/osu.Game.Rulesets.Catch/Skinning/Default/FruitPiece.cs index 31487ee407..81667315a0 100644 --- a/osu.Game.Rulesets.Catch/Skinning/Default/FruitPiece.cs +++ b/osu.Game.Rulesets.Catch/Skinning/Default/FruitPiece.cs @@ -7,9 +7,10 @@ using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; +using osu.Game.Rulesets.Catch.Objects.Drawables; using osu.Game.Rulesets.Objects.Drawables; -namespace osu.Game.Rulesets.Catch.Objects.Drawables.Pieces +namespace osu.Game.Rulesets.Catch.Skinning.Default { internal class FruitPiece : CompositeDrawable { diff --git a/osu.Game.Rulesets.Catch/Skinning/Default/GrapePiece.cs b/osu.Game.Rulesets.Catch/Skinning/Default/GrapePiece.cs index 15349c18d5..bb6a787c21 100644 --- a/osu.Game.Rulesets.Catch/Skinning/Default/GrapePiece.cs +++ b/osu.Game.Rulesets.Catch/Skinning/Default/GrapePiece.cs @@ -4,7 +4,7 @@ using osu.Framework.Graphics; using osuTK; -namespace osu.Game.Rulesets.Catch.Objects.Drawables.Pieces +namespace osu.Game.Rulesets.Catch.Skinning.Default { public class GrapePiece : PulpFormation { diff --git a/osu.Game.Rulesets.Catch/Skinning/Default/HyperBorderPiece.cs b/osu.Game.Rulesets.Catch/Skinning/Default/HyperBorderPiece.cs index 60bb07e89d..d160956a6e 100644 --- a/osu.Game.Rulesets.Catch/Skinning/Default/HyperBorderPiece.cs +++ b/osu.Game.Rulesets.Catch/Skinning/Default/HyperBorderPiece.cs @@ -4,7 +4,7 @@ using osu.Framework.Graphics; using osu.Game.Rulesets.Catch.UI; -namespace osu.Game.Rulesets.Catch.Objects.Drawables.Pieces +namespace osu.Game.Rulesets.Catch.Skinning.Default { public class HyperBorderPiece : BorderPiece { diff --git a/osu.Game.Rulesets.Catch/Skinning/Default/HyperDropletBorderPiece.cs b/osu.Game.Rulesets.Catch/Skinning/Default/HyperDropletBorderPiece.cs index 1bd9fd6bb2..53a487b97f 100644 --- a/osu.Game.Rulesets.Catch/Skinning/Default/HyperDropletBorderPiece.cs +++ b/osu.Game.Rulesets.Catch/Skinning/Default/HyperDropletBorderPiece.cs @@ -1,7 +1,7 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -namespace osu.Game.Rulesets.Catch.Objects.Drawables.Pieces +namespace osu.Game.Rulesets.Catch.Skinning.Default { public class HyperDropletBorderPiece : HyperBorderPiece { diff --git a/osu.Game.Rulesets.Catch/Skinning/Default/PearPiece.cs b/osu.Game.Rulesets.Catch/Skinning/Default/PearPiece.cs index 3372a06996..a99a4034ed 100644 --- a/osu.Game.Rulesets.Catch/Skinning/Default/PearPiece.cs +++ b/osu.Game.Rulesets.Catch/Skinning/Default/PearPiece.cs @@ -4,7 +4,7 @@ using osu.Framework.Graphics; using osuTK; -namespace osu.Game.Rulesets.Catch.Objects.Drawables.Pieces +namespace osu.Game.Rulesets.Catch.Skinning.Default { public class PearPiece : PulpFormation { diff --git a/osu.Game.Rulesets.Catch/Skinning/Default/PineapplePiece.cs b/osu.Game.Rulesets.Catch/Skinning/Default/PineapplePiece.cs index 7f80c58178..8d7dce6fc4 100644 --- a/osu.Game.Rulesets.Catch/Skinning/Default/PineapplePiece.cs +++ b/osu.Game.Rulesets.Catch/Skinning/Default/PineapplePiece.cs @@ -4,7 +4,7 @@ using osu.Framework.Graphics; using osuTK; -namespace osu.Game.Rulesets.Catch.Objects.Drawables.Pieces +namespace osu.Game.Rulesets.Catch.Skinning.Default { public class PineapplePiece : PulpFormation { diff --git a/osu.Game.Rulesets.Catch/Skinning/Default/Pulp.cs b/osu.Game.Rulesets.Catch/Skinning/Default/Pulp.cs index d3e4945611..37a8334068 100644 --- a/osu.Game.Rulesets.Catch/Skinning/Default/Pulp.cs +++ b/osu.Game.Rulesets.Catch/Skinning/Default/Pulp.cs @@ -8,7 +8,7 @@ using osu.Framework.Graphics.Effects; using osu.Framework.Graphics.Shapes; using osuTK.Graphics; -namespace osu.Game.Rulesets.Catch.Objects.Drawables.Pieces +namespace osu.Game.Rulesets.Catch.Skinning.Default { public class Pulp : Circle { diff --git a/osu.Game.Rulesets.Catch/Skinning/Default/PulpFormation.cs b/osu.Game.Rulesets.Catch/Skinning/Default/PulpFormation.cs index 1df548e70a..837bc74540 100644 --- a/osu.Game.Rulesets.Catch/Skinning/Default/PulpFormation.cs +++ b/osu.Game.Rulesets.Catch/Skinning/Default/PulpFormation.cs @@ -6,11 +6,12 @@ using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; +using osu.Game.Rulesets.Catch.Objects.Drawables; using osu.Game.Rulesets.Objects.Drawables; using osuTK; using osuTK.Graphics; -namespace osu.Game.Rulesets.Catch.Objects.Drawables.Pieces +namespace osu.Game.Rulesets.Catch.Skinning.Default { public abstract class PulpFormation : CompositeDrawable { diff --git a/osu.Game.Rulesets.Catch/Skinning/Default/RaspberryPiece.cs b/osu.Game.Rulesets.Catch/Skinning/Default/RaspberryPiece.cs index 288ece95b2..f35d64f593 100644 --- a/osu.Game.Rulesets.Catch/Skinning/Default/RaspberryPiece.cs +++ b/osu.Game.Rulesets.Catch/Skinning/Default/RaspberryPiece.cs @@ -4,7 +4,7 @@ using osu.Framework.Graphics; using osuTK; -namespace osu.Game.Rulesets.Catch.Objects.Drawables.Pieces +namespace osu.Game.Rulesets.Catch.Skinning.Default { public class RaspberryPiece : PulpFormation { diff --git a/osu.Game.Rulesets.Catch/Skinning/Legacy/CatchLegacySkinTransformer.cs b/osu.Game.Rulesets.Catch/Skinning/Legacy/CatchLegacySkinTransformer.cs index 22db147e32..d597d439c2 100644 --- a/osu.Game.Rulesets.Catch/Skinning/Legacy/CatchLegacySkinTransformer.cs +++ b/osu.Game.Rulesets.Catch/Skinning/Legacy/CatchLegacySkinTransformer.cs @@ -9,7 +9,7 @@ using osuTK; using osuTK.Graphics; using static osu.Game.Skinning.LegacySkinConfiguration; -namespace osu.Game.Rulesets.Catch.Skinning +namespace osu.Game.Rulesets.Catch.Skinning.Legacy { public class CatchLegacySkinTransformer : LegacySkinTransformer { diff --git a/osu.Game.Rulesets.Catch/Skinning/Legacy/LegacyCatchComboCounter.cs b/osu.Game.Rulesets.Catch/Skinning/Legacy/LegacyCatchComboCounter.cs index 34608b07ff..f797ae75c2 100644 --- a/osu.Game.Rulesets.Catch/Skinning/Legacy/LegacyCatchComboCounter.cs +++ b/osu.Game.Rulesets.Catch/Skinning/Legacy/LegacyCatchComboCounter.cs @@ -9,7 +9,7 @@ using osuTK; using osuTK.Graphics; using static osu.Game.Skinning.LegacySkinConfiguration; -namespace osu.Game.Rulesets.Catch.Skinning +namespace osu.Game.Rulesets.Catch.Skinning.Legacy { /// /// A combo counter implementation that visually behaves almost similar to stable's osu!catch combo counter. diff --git a/osu.Game.Rulesets.Catch/Skinning/Legacy/LegacyFruitPiece.cs b/osu.Game.Rulesets.Catch/Skinning/Legacy/LegacyFruitPiece.cs index b8648f46f0..2db95a11a1 100644 --- a/osu.Game.Rulesets.Catch/Skinning/Legacy/LegacyFruitPiece.cs +++ b/osu.Game.Rulesets.Catch/Skinning/Legacy/LegacyFruitPiece.cs @@ -13,7 +13,7 @@ using osu.Game.Skinning; using osuTK; using osuTK.Graphics; -namespace osu.Game.Rulesets.Catch.Skinning +namespace osu.Game.Rulesets.Catch.Skinning.Legacy { internal class LegacyFruitPiece : CompositeDrawable { From 87189452d1a7d53c1167eb94fc291a74b27ded16 Mon Sep 17 00:00:00 2001 From: ekrctb Date: Mon, 7 Dec 2020 12:57:24 +0900 Subject: [PATCH 148/184] Refactor legacy skin piece to allow texture update --- .../Skinning/LegacyCatchHitObjectPiece.cs | 100 ++++++++++++++++++ .../Skinning/LegacyDropletPiece.cs | 20 ++++ .../Skinning/LegacyFruitPiece.cs | 84 ++++----------- 3 files changed, 140 insertions(+), 64 deletions(-) create mode 100644 osu.Game.Rulesets.Catch/Skinning/LegacyCatchHitObjectPiece.cs create mode 100644 osu.Game.Rulesets.Catch/Skinning/LegacyDropletPiece.cs diff --git a/osu.Game.Rulesets.Catch/Skinning/LegacyCatchHitObjectPiece.cs b/osu.Game.Rulesets.Catch/Skinning/LegacyCatchHitObjectPiece.cs new file mode 100644 index 0000000000..4bcb92b9be --- /dev/null +++ b/osu.Game.Rulesets.Catch/Skinning/LegacyCatchHitObjectPiece.cs @@ -0,0 +1,100 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using JetBrains.Annotations; +using osu.Framework.Allocation; +using osu.Framework.Bindables; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Pooling; +using osu.Framework.Graphics.Sprites; +using osu.Framework.Graphics.Textures; +using osu.Game.Rulesets.Catch.Objects.Drawables; +using osu.Game.Rulesets.Catch.UI; +using osu.Game.Rulesets.Objects.Drawables; +using osu.Game.Skinning; +using osuTK; +using osuTK.Graphics; + +namespace osu.Game.Rulesets.Catch.Skinning +{ + public abstract class LegacyCatchHitObjectPiece : PoolableDrawable + { + public readonly Bindable AccentColour = new Bindable(); + public readonly Bindable HyperDash = new Bindable(); + + private readonly Sprite colouredSprite; + private readonly Sprite overlaySprite; + private readonly Sprite hyperSprite; + + [Resolved] + private ISkinSource skin { get; set; } + + protected ISkinSource Skin => skin; + + [Resolved(canBeNull: true)] + private DrawableHitObject drawableHitObject { get; set; } + + [CanBeNull] + protected DrawablePalpableCatchHitObject DrawableHitObject => (DrawablePalpableCatchHitObject)drawableHitObject; + + protected LegacyCatchHitObjectPiece() + { + RelativeSizeAxes = Axes.Both; + + InternalChildren = new Drawable[] + { + colouredSprite = new Sprite + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + }, + overlaySprite = new Sprite + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + }, + hyperSprite = new Sprite + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Blending = BlendingParameters.Additive, + Depth = 1, + Alpha = 0, + Scale = new Vector2(1.2f), + } + }; + } + + protected override void LoadComplete() + { + base.LoadComplete(); + + if (DrawableHitObject != null) + { + AccentColour.BindTo(DrawableHitObject.AccentColour); + HyperDash.BindTo(DrawableHitObject.HyperDash); + } + + hyperSprite.Colour = Skin.GetConfig(CatchSkinColour.HyperDashFruit)?.Value ?? + Skin.GetConfig(CatchSkinColour.HyperDash)?.Value ?? + Catcher.DEFAULT_HYPER_DASH_COLOUR; + + AccentColour.BindValueChanged(colour => + { + colouredSprite.Colour = LegacyColourCompatibility.DisallowZeroAlpha(colour.NewValue); + }, true); + + HyperDash.BindValueChanged(hyper => + { + hyperSprite.Alpha = hyper.NewValue ? 0.7f : 0; + }, true); + } + + protected void SetTexture(Texture texture, Texture overlayTexture) + { + colouredSprite.Texture = texture; + overlaySprite.Texture = overlayTexture; + hyperSprite.Texture = texture; + } + } +} diff --git a/osu.Game.Rulesets.Catch/Skinning/LegacyDropletPiece.cs b/osu.Game.Rulesets.Catch/Skinning/LegacyDropletPiece.cs new file mode 100644 index 0000000000..cc8886f631 --- /dev/null +++ b/osu.Game.Rulesets.Catch/Skinning/LegacyDropletPiece.cs @@ -0,0 +1,20 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using osu.Framework.Graphics.Textures; + +namespace osu.Game.Rulesets.Catch.Skinning +{ + public class LegacyDropletPiece : LegacyCatchHitObjectPiece + { + protected override void LoadComplete() + { + base.LoadComplete(); + + Texture texture = Skin.GetTexture("fruit-drop"); + Texture overlayTexture = Skin.GetTexture("fruit-drop-overlay"); + + SetTexture(texture, overlayTexture); + } + } +} diff --git a/osu.Game.Rulesets.Catch/Skinning/LegacyFruitPiece.cs b/osu.Game.Rulesets.Catch/Skinning/LegacyFruitPiece.cs index b8648f46f0..7008234e99 100644 --- a/osu.Game.Rulesets.Catch/Skinning/LegacyFruitPiece.cs +++ b/osu.Game.Rulesets.Catch/Skinning/LegacyFruitPiece.cs @@ -1,83 +1,39 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -using osu.Framework.Allocation; using osu.Framework.Bindables; -using osu.Framework.Graphics; -using osu.Framework.Graphics.Containers; -using osu.Framework.Graphics.Sprites; +using osu.Framework.Graphics.Textures; using osu.Game.Rulesets.Catch.Objects.Drawables; -using osu.Game.Rulesets.Catch.UI; -using osu.Game.Rulesets.Objects.Drawables; -using osu.Game.Skinning; -using osuTK; -using osuTK.Graphics; namespace osu.Game.Rulesets.Catch.Skinning { - internal class LegacyFruitPiece : CompositeDrawable + internal class LegacyFruitPiece : LegacyCatchHitObjectPiece { - private readonly string lookupName; + public readonly Bindable VisualRepresentation = new Bindable(); - private readonly Bindable accentColour = new Bindable(); - private readonly Bindable hyperDash = new Bindable(); - private Sprite colouredSprite; - - public LegacyFruitPiece(string lookupName) + private readonly string[] lookupNames = { - this.lookupName = lookupName; - RelativeSizeAxes = Axes.Both; - } - - [BackgroundDependencyLoader] - private void load(DrawableHitObject drawableObject, ISkinSource skin) - { - var drawableCatchObject = (DrawablePalpableCatchHitObject)drawableObject; - - accentColour.BindTo(drawableCatchObject.AccentColour); - hyperDash.BindTo(drawableCatchObject.HyperDash); - - InternalChildren = new Drawable[] - { - colouredSprite = new Sprite - { - Texture = skin.GetTexture(lookupName), - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - }, - new Sprite - { - Texture = skin.GetTexture($"{lookupName}-overlay"), - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - }, - }; - - if (hyperDash.Value) - { - var hyperDashOverlay = new Sprite - { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - Blending = BlendingParameters.Additive, - Depth = 1, - Alpha = 0.7f, - Scale = new Vector2(1.2f), - Texture = skin.GetTexture(lookupName), - Colour = skin.GetConfig(CatchSkinColour.HyperDashFruit)?.Value ?? - skin.GetConfig(CatchSkinColour.HyperDash)?.Value ?? - Catcher.DEFAULT_HYPER_DASH_COLOUR, - }; - - AddInternal(hyperDashOverlay); - } - } + "fruit-pear", "fruit-grapes", "fruit-apple", "fruit-orange", "fruit-bananas" + }; protected override void LoadComplete() { base.LoadComplete(); - accentColour.BindValueChanged(colour => colouredSprite.Colour = LegacyColourCompatibility.DisallowZeroAlpha(colour.NewValue), true); + var fruit = (DrawableFruit)DrawableHitObject; + + if (fruit != null) + VisualRepresentation.BindTo(fruit.VisualRepresentation); + + VisualRepresentation.BindValueChanged(visual => setTexture(visual.NewValue), true); + } + + private void setTexture(FruitVisualRepresentation visualRepresentation) + { + Texture texture = Skin.GetTexture(lookupNames[(int)visualRepresentation]); + Texture overlayTexture = Skin.GetTexture(lookupNames[(int)visualRepresentation] + "-overlay"); + + SetTexture(texture, overlayTexture); } } } From d51d2c533155d292c454780a9597bfc866f83556 Mon Sep 17 00:00:00 2001 From: ekrctb Date: Mon, 7 Dec 2020 12:59:03 +0900 Subject: [PATCH 149/184] Don't recreate pieces when catch DHO is reused --- .../CatchSkinComponents.cs | 7 +--- .../Objects/Drawables/DrawableDroplet.cs | 7 +--- .../Objects/Drawables/DrawableFruit.cs | 39 ++----------------- .../Skinning/CatchLegacySkinTransformer.cs | 21 +++++----- 4 files changed, 17 insertions(+), 57 deletions(-) diff --git a/osu.Game.Rulesets.Catch/CatchSkinComponents.cs b/osu.Game.Rulesets.Catch/CatchSkinComponents.cs index 23d8428fec..668f7197be 100644 --- a/osu.Game.Rulesets.Catch/CatchSkinComponents.cs +++ b/osu.Game.Rulesets.Catch/CatchSkinComponents.cs @@ -5,11 +5,8 @@ namespace osu.Game.Rulesets.Catch { public enum CatchSkinComponents { - FruitBananas, - FruitApple, - FruitGrapes, - FruitOrange, - FruitPear, + Fruit, + Banana, Droplet, CatcherIdle, CatcherFail, diff --git a/osu.Game.Rulesets.Catch/Objects/Drawables/DrawableDroplet.cs b/osu.Game.Rulesets.Catch/Objects/Drawables/DrawableDroplet.cs index b8acea625b..4c49bfe6c9 100644 --- a/osu.Game.Rulesets.Catch/Objects/Drawables/DrawableDroplet.cs +++ b/osu.Game.Rulesets.Catch/Objects/Drawables/DrawableDroplet.cs @@ -25,17 +25,12 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawables [BackgroundDependencyLoader] private void load() - { - HyperDash.BindValueChanged(_ => updatePiece(), true); - } - - private void updatePiece() { ScaleContainer.Child = new SkinnableDrawable( new CatchSkinComponent(CatchSkinComponents.Droplet), _ => new DropletPiece { - HyperDash = { BindTarget = HyperDash } + HyperDash = { BindTarget = HyperDash }, }); } diff --git a/osu.Game.Rulesets.Catch/Objects/Drawables/DrawableFruit.cs b/osu.Game.Rulesets.Catch/Objects/Drawables/DrawableFruit.cs index ef9df02a68..2998d2cc6f 100644 --- a/osu.Game.Rulesets.Catch/Objects/Drawables/DrawableFruit.cs +++ b/osu.Game.Rulesets.Catch/Objects/Drawables/DrawableFruit.cs @@ -1,7 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -using System; using JetBrains.Annotations; using osu.Framework.Allocation; using osu.Framework.Bindables; @@ -35,21 +34,8 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawables VisualRepresentation.Value = GetVisualRepresentation(change.NewValue); }, true); - VisualRepresentation.BindValueChanged(_ => updatePiece()); - HyperDash.BindValueChanged(_ => updatePiece(), true); - } - - protected override void UpdateInitialTransforms() - { - base.UpdateInitialTransforms(); - - ScaleContainer.RotateTo((RandomSingle(1) - 0.5f) * 40); - } - - private void updatePiece() - { ScaleContainer.Child = new SkinnableDrawable( - new CatchSkinComponent(getComponent(VisualRepresentation.Value)), + new CatchSkinComponent(this is DrawableBanana ? CatchSkinComponents.Banana : CatchSkinComponents.Fruit), _ => new FruitPiece { VisualRepresentation = { BindTarget = VisualRepresentation }, @@ -57,28 +43,11 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawables }); } - private CatchSkinComponents getComponent(FruitVisualRepresentation hitObjectVisualRepresentation) + protected override void UpdateInitialTransforms() { - switch (hitObjectVisualRepresentation) - { - case FruitVisualRepresentation.Pear: - return CatchSkinComponents.FruitPear; + base.UpdateInitialTransforms(); - case FruitVisualRepresentation.Grape: - return CatchSkinComponents.FruitGrapes; - - case FruitVisualRepresentation.Pineapple: - return CatchSkinComponents.FruitApple; - - case FruitVisualRepresentation.Raspberry: - return CatchSkinComponents.FruitOrange; - - case FruitVisualRepresentation.Banana: - return CatchSkinComponents.FruitBananas; - - default: - throw new ArgumentOutOfRangeException(nameof(hitObjectVisualRepresentation), hitObjectVisualRepresentation, null); - } + ScaleContainer.RotateTo((RandomSingle(1) - 0.5f) * 40); } } diff --git a/osu.Game.Rulesets.Catch/Skinning/CatchLegacySkinTransformer.cs b/osu.Game.Rulesets.Catch/Skinning/CatchLegacySkinTransformer.cs index 22db147e32..1889b230a7 100644 --- a/osu.Game.Rulesets.Catch/Skinning/CatchLegacySkinTransformer.cs +++ b/osu.Game.Rulesets.Catch/Skinning/CatchLegacySkinTransformer.cs @@ -1,11 +1,9 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -using Humanizer; using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Game.Skinning; -using osuTK; using osuTK.Graphics; using static osu.Game.Skinning.LegacySkinConfiguration; @@ -40,20 +38,21 @@ namespace osu.Game.Rulesets.Catch.Skinning switch (catchSkinComponent.Component) { - case CatchSkinComponents.FruitApple: - case CatchSkinComponents.FruitBananas: - case CatchSkinComponents.FruitOrange: - case CatchSkinComponents.FruitGrapes: - case CatchSkinComponents.FruitPear: - var lookupName = catchSkinComponent.Component.ToString().Kebaberize(); - if (GetTexture(lookupName) != null) - return new LegacyFruitPiece(lookupName); + case CatchSkinComponents.Fruit: + if (GetTexture("fruit-pear") != null) + return new LegacyFruitPiece(); + + break; + + case CatchSkinComponents.Banana: + if (GetTexture("fruit-bananas") != null) + return new LegacyFruitPiece(); break; case CatchSkinComponents.Droplet: if (GetTexture("fruit-drop") != null) - return new LegacyFruitPiece("fruit-drop") { Scale = new Vector2(0.8f) }; + return new LegacyDropletPiece(); break; From 42b810d0c84ebb1ed7f5701b0d5f1fb99a57c139 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 7 Dec 2020 13:03:34 +0900 Subject: [PATCH 150/184] Update DiscordRichPresence with fix for startup crashes --- osu.Desktop/osu.Desktop.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Desktop/osu.Desktop.csproj b/osu.Desktop/osu.Desktop.csproj index adf9c452f6..8b8ad9f8af 100644 --- a/osu.Desktop/osu.Desktop.csproj +++ b/osu.Desktop/osu.Desktop.csproj @@ -29,7 +29,7 @@ - + From 0d73bf84888b655ef1b233464bf1a9239c70b9f3 Mon Sep 17 00:00:00 2001 From: ekrctb Date: Mon, 7 Dec 2020 13:14:00 +0900 Subject: [PATCH 151/184] Refactor catch default piece to allow reuse But Fruit in-place update is still incomplete, as child drawables are recreated when reused. --- .../Objects/Drawables/DrawableDroplet.cs | 5 +- .../Objects/Drawables/DrawableFruit.cs | 6 +-- .../Drawables/Pieces/CatchHitObjectPiece.cs | 54 +++++++++++++++++++ .../Objects/Drawables/Pieces/DropletPiece.cs | 27 +++------- .../Objects/Drawables/Pieces/FruitPiece.cs | 48 +++++++---------- 5 files changed, 83 insertions(+), 57 deletions(-) create mode 100644 osu.Game.Rulesets.Catch/Objects/Drawables/Pieces/CatchHitObjectPiece.cs diff --git a/osu.Game.Rulesets.Catch/Objects/Drawables/DrawableDroplet.cs b/osu.Game.Rulesets.Catch/Objects/Drawables/DrawableDroplet.cs index 4c49bfe6c9..dea19a2446 100644 --- a/osu.Game.Rulesets.Catch/Objects/Drawables/DrawableDroplet.cs +++ b/osu.Game.Rulesets.Catch/Objects/Drawables/DrawableDroplet.cs @@ -28,10 +28,7 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawables { ScaleContainer.Child = new SkinnableDrawable( new CatchSkinComponent(CatchSkinComponents.Droplet), - _ => new DropletPiece - { - HyperDash = { BindTarget = HyperDash }, - }); + _ => new DropletPiece()); } protected override void UpdateInitialTransforms() diff --git a/osu.Game.Rulesets.Catch/Objects/Drawables/DrawableFruit.cs b/osu.Game.Rulesets.Catch/Objects/Drawables/DrawableFruit.cs index 2998d2cc6f..8db8f5ec82 100644 --- a/osu.Game.Rulesets.Catch/Objects/Drawables/DrawableFruit.cs +++ b/osu.Game.Rulesets.Catch/Objects/Drawables/DrawableFruit.cs @@ -36,11 +36,7 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawables ScaleContainer.Child = new SkinnableDrawable( new CatchSkinComponent(this is DrawableBanana ? CatchSkinComponents.Banana : CatchSkinComponents.Fruit), - _ => new FruitPiece - { - VisualRepresentation = { BindTarget = VisualRepresentation }, - HyperDash = { BindTarget = HyperDash }, - }); + _ => new FruitPiece()); } protected override void UpdateInitialTransforms() diff --git a/osu.Game.Rulesets.Catch/Objects/Drawables/Pieces/CatchHitObjectPiece.cs b/osu.Game.Rulesets.Catch/Objects/Drawables/Pieces/CatchHitObjectPiece.cs new file mode 100644 index 0000000000..ec5f66a945 --- /dev/null +++ b/osu.Game.Rulesets.Catch/Objects/Drawables/Pieces/CatchHitObjectPiece.cs @@ -0,0 +1,54 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System; +using JetBrains.Annotations; +using osu.Framework.Allocation; +using osu.Framework.Bindables; +using osu.Framework.Graphics.Containers; +using osu.Game.Rulesets.Objects.Drawables; +using osuTK.Graphics; + +namespace osu.Game.Rulesets.Catch.Objects.Drawables.Pieces +{ + public class CatchHitObjectPiece : CompositeDrawable + { + public readonly Bindable AccentColour = new Bindable(); + public readonly Bindable HyperDash = new Bindable(); + + [Resolved(canBeNull: true)] + private DrawableHitObject drawableHitObject { get; set; } + + [CanBeNull] + protected DrawablePalpableCatchHitObject DrawableHitObject => (DrawablePalpableCatchHitObject)drawableHitObject; + + [CanBeNull] + protected BorderPiece BorderPiece; + + [CanBeNull] + protected HyperBorderPiece HyperBorderPiece; + + protected override void LoadComplete() + { + base.LoadComplete(); + + if (DrawableHitObject != null) + { + AccentColour.BindTo(DrawableHitObject.AccentColour); + HyperDash.BindTo(DrawableHitObject.HyperDash); + } + + HyperDash.BindValueChanged(hyper => + { + if (HyperBorderPiece != null) + HyperBorderPiece.Alpha = hyper.NewValue ? 1 : 0; + }, true); + } + + protected override void Update() + { + if (BorderPiece != null && DrawableHitObject?.HitObject != null) + BorderPiece.Alpha = (float)Math.Clamp((DrawableHitObject.HitObject.StartTime - Time.Current) / 500, 0, 1); + } + } +} diff --git a/osu.Game.Rulesets.Catch/Objects/Drawables/Pieces/DropletPiece.cs b/osu.Game.Rulesets.Catch/Objects/Drawables/Pieces/DropletPiece.cs index c90407ae15..f92c92160a 100644 --- a/osu.Game.Rulesets.Catch/Objects/Drawables/Pieces/DropletPiece.cs +++ b/osu.Game.Rulesets.Catch/Objects/Drawables/Pieces/DropletPiece.cs @@ -1,37 +1,26 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -using osu.Framework.Allocation; -using osu.Framework.Bindables; using osu.Framework.Graphics; -using osu.Framework.Graphics.Containers; -using osu.Game.Rulesets.Objects.Drawables; using osuTK; namespace osu.Game.Rulesets.Catch.Objects.Drawables.Pieces { - public class DropletPiece : CompositeDrawable + public class DropletPiece : CatchHitObjectPiece { - public readonly Bindable HyperDash = new Bindable(); - public DropletPiece() { Size = new Vector2(CatchHitObject.OBJECT_RADIUS / 2); - } - [BackgroundDependencyLoader] - private void load(DrawableHitObject drawableObject) - { - InternalChild = new Pulp + InternalChildren = new Drawable[] { - RelativeSizeAxes = Axes.Both, - AccentColour = { BindTarget = drawableObject.AccentColour } + new Pulp + { + RelativeSizeAxes = Axes.Both, + AccentColour = { BindTarget = AccentColour } + }, + HyperBorderPiece = new HyperDropletBorderPiece() }; - - if (HyperDash.Value) - { - AddInternal(new HyperDropletBorderPiece()); - } } } } diff --git a/osu.Game.Rulesets.Catch/Objects/Drawables/Pieces/FruitPiece.cs b/osu.Game.Rulesets.Catch/Objects/Drawables/Pieces/FruitPiece.cs index 31487ee407..9b5c00b2bf 100644 --- a/osu.Game.Rulesets.Catch/Objects/Drawables/Pieces/FruitPiece.cs +++ b/osu.Game.Rulesets.Catch/Objects/Drawables/Pieces/FruitPiece.cs @@ -1,17 +1,12 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -using System; -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; namespace osu.Game.Rulesets.Catch.Objects.Drawables.Pieces { - internal class FruitPiece : CompositeDrawable + internal class FruitPiece : CatchHitObjectPiece { /// /// Because we're adding a border around the fruit, we need to scale down some. @@ -19,38 +14,36 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawables.Pieces public const float RADIUS_ADJUST = 1.1f; public readonly Bindable VisualRepresentation = new Bindable(); - public readonly Bindable HyperDash = new Bindable(); - - [CanBeNull] - private DrawableCatchHitObject drawableHitObject; - - [CanBeNull] - private BorderPiece borderPiece; public FruitPiece() { RelativeSizeAxes = Axes.Both; } - [BackgroundDependencyLoader(permitNulls: true)] - private void load([CanBeNull] DrawableHitObject drawable) + protected override void LoadComplete() { - drawableHitObject = (DrawableCatchHitObject)drawable; + base.LoadComplete(); + + if (DrawableHitObject != null) + { + var fruit = (DrawableFruit)DrawableHitObject; + VisualRepresentation.BindTo(fruit.VisualRepresentation); + } + + VisualRepresentation.BindValueChanged(_ => recreateChildren(), true); + } + + private void recreateChildren() + { + ClearInternal(); AddInternal(getFruitFor(VisualRepresentation.Value)); - // if it is not part of a DHO, the border is always invisible. - if (drawableHitObject != null) - AddInternal(borderPiece = new BorderPiece()); + if (DrawableHitObject != null) + AddInternal(BorderPiece = new BorderPiece()); if (HyperDash.Value) - AddInternal(new HyperBorderPiece()); - } - - protected override void Update() - { - if (borderPiece != null && drawableHitObject?.HitObject != null) - borderPiece.Alpha = (float)Math.Clamp((drawableHitObject.HitObject.StartTime - Time.Current) / 500, 0, 1); + AddInternal(HyperBorderPiece = new HyperBorderPiece()); } private Drawable getFruitFor(FruitVisualRepresentation representation) @@ -66,9 +59,6 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawables.Pieces case FruitVisualRepresentation.Pineapple: return new PineapplePiece(); - case FruitVisualRepresentation.Banana: - return new BananaPiece(); - case FruitVisualRepresentation.Raspberry: return new RaspberryPiece(); } From b8f1c499a45f6dd71b925b2963ba7f5f7858d05c Mon Sep 17 00:00:00 2001 From: ekrctb Date: Mon, 7 Dec 2020 13:56:22 +0900 Subject: [PATCH 152/184] Allow PulpFormation to update formation dynamically Pulps are lazily allocated but never deallocated for a DrawableFruit --- .../Objects/Drawables/Pieces/BananaPiece.cs | 30 --------- .../Objects/Drawables/Pieces/FruitPiece.cs | 46 ++++---------- .../Drawables/Pieces/FruitPulpFormation.cs | 63 +++++++++++++++++++ .../Objects/Drawables/Pieces/GrapePiece.cs | 42 ------------- .../Objects/Drawables/Pieces/PearPiece.cs | 42 ------------- .../Drawables/Pieces/PineapplePiece.cs | 48 -------------- .../Objects/Drawables/Pieces/Pulp.cs | 4 +- .../Objects/Drawables/Pieces/PulpFormation.cs | 26 +++++--- .../Drawables/Pieces/RaspberryPiece.cs | 48 -------------- 9 files changed, 95 insertions(+), 254 deletions(-) delete mode 100644 osu.Game.Rulesets.Catch/Objects/Drawables/Pieces/BananaPiece.cs create mode 100644 osu.Game.Rulesets.Catch/Objects/Drawables/Pieces/FruitPulpFormation.cs delete mode 100644 osu.Game.Rulesets.Catch/Objects/Drawables/Pieces/GrapePiece.cs delete mode 100644 osu.Game.Rulesets.Catch/Objects/Drawables/Pieces/PearPiece.cs delete mode 100644 osu.Game.Rulesets.Catch/Objects/Drawables/Pieces/PineapplePiece.cs delete mode 100644 osu.Game.Rulesets.Catch/Objects/Drawables/Pieces/RaspberryPiece.cs diff --git a/osu.Game.Rulesets.Catch/Objects/Drawables/Pieces/BananaPiece.cs b/osu.Game.Rulesets.Catch/Objects/Drawables/Pieces/BananaPiece.cs deleted file mode 100644 index fa8837dec5..0000000000 --- a/osu.Game.Rulesets.Catch/Objects/Drawables/Pieces/BananaPiece.cs +++ /dev/null @@ -1,30 +0,0 @@ -// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. -// See the LICENCE file in the repository root for full licence text. - -using osu.Framework.Graphics; -using osuTK; - -namespace osu.Game.Rulesets.Catch.Objects.Drawables.Pieces -{ - public class BananaPiece : PulpFormation - { - public BananaPiece() - { - InternalChildren = new Drawable[] - { - new Pulp - { - AccentColour = { BindTarget = AccentColour }, - Size = new Vector2(SMALL_PULP), - Y = -0.3f - }, - new Pulp - { - AccentColour = { BindTarget = AccentColour }, - Size = new Vector2(LARGE_PULP_4 * 0.8f, LARGE_PULP_4 * 2.5f), - Y = 0.05f, - }, - }; - } - } -} diff --git a/osu.Game.Rulesets.Catch/Objects/Drawables/Pieces/FruitPiece.cs b/osu.Game.Rulesets.Catch/Objects/Drawables/Pieces/FruitPiece.cs index 9b5c00b2bf..e915253ff7 100644 --- a/osu.Game.Rulesets.Catch/Objects/Drawables/Pieces/FruitPiece.cs +++ b/osu.Game.Rulesets.Catch/Objects/Drawables/Pieces/FruitPiece.cs @@ -18,6 +18,17 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawables.Pieces public FruitPiece() { RelativeSizeAxes = Axes.Both; + + InternalChildren = new Drawable[] + { + new FruitPulpFormation + { + AccentColour = { BindTarget = AccentColour }, + VisualRepresentation = { BindTarget = VisualRepresentation } + }, + BorderPiece = new BorderPiece(), + HyperBorderPiece = new HyperBorderPiece() + }; } protected override void LoadComplete() @@ -29,41 +40,6 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawables.Pieces var fruit = (DrawableFruit)DrawableHitObject; VisualRepresentation.BindTo(fruit.VisualRepresentation); } - - VisualRepresentation.BindValueChanged(_ => recreateChildren(), true); - } - - private void recreateChildren() - { - ClearInternal(); - - AddInternal(getFruitFor(VisualRepresentation.Value)); - - if (DrawableHitObject != null) - AddInternal(BorderPiece = new BorderPiece()); - - if (HyperDash.Value) - AddInternal(HyperBorderPiece = new HyperBorderPiece()); - } - - private Drawable getFruitFor(FruitVisualRepresentation representation) - { - switch (representation) - { - case FruitVisualRepresentation.Pear: - return new PearPiece(); - - case FruitVisualRepresentation.Grape: - return new GrapePiece(); - - case FruitVisualRepresentation.Pineapple: - return new PineapplePiece(); - - case FruitVisualRepresentation.Raspberry: - return new RaspberryPiece(); - } - - return Empty(); } } } diff --git a/osu.Game.Rulesets.Catch/Objects/Drawables/Pieces/FruitPulpFormation.cs b/osu.Game.Rulesets.Catch/Objects/Drawables/Pieces/FruitPulpFormation.cs new file mode 100644 index 0000000000..cd870b1f98 --- /dev/null +++ b/osu.Game.Rulesets.Catch/Objects/Drawables/Pieces/FruitPulpFormation.cs @@ -0,0 +1,63 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using osu.Framework.Bindables; +using osuTK; + +namespace osu.Game.Rulesets.Catch.Objects.Drawables.Pieces +{ + public class FruitPulpFormation : PulpFormation + { + public readonly Bindable VisualRepresentation = new Bindable(); + + protected override void LoadComplete() + { + base.LoadComplete(); + + VisualRepresentation.BindValueChanged(setFormation, true); + } + + private void setFormation(ValueChangedEvent visualRepresentation) + { + Clear(); + + switch (visualRepresentation.NewValue) + { + case FruitVisualRepresentation.Pear: + Add(new Vector2(0, -0.33f), new Vector2(SMALL_PULP)); + Add(PositionAt(60, DISTANCE_FROM_CENTRE_3), new Vector2(LARGE_PULP_3)); + Add(PositionAt(180, DISTANCE_FROM_CENTRE_3), new Vector2(LARGE_PULP_3)); + Add(PositionAt(300, DISTANCE_FROM_CENTRE_3), new Vector2(LARGE_PULP_3)); + break; + + case FruitVisualRepresentation.Grape: + Add(new Vector2(0, -0.25f), new Vector2(SMALL_PULP)); + Add(PositionAt(0, DISTANCE_FROM_CENTRE_3), new Vector2(LARGE_PULP_3)); + Add(PositionAt(120, DISTANCE_FROM_CENTRE_3), new Vector2(LARGE_PULP_3)); + Add(PositionAt(240, DISTANCE_FROM_CENTRE_3), new Vector2(LARGE_PULP_3)); + break; + + case FruitVisualRepresentation.Pineapple: + Add(new Vector2(0, -0.3f), new Vector2(SMALL_PULP)); + Add(PositionAt(45, DISTANCE_FROM_CENTRE_4), new Vector2(LARGE_PULP_4)); + Add(PositionAt(135, DISTANCE_FROM_CENTRE_4), new Vector2(LARGE_PULP_4)); + Add(PositionAt(225, DISTANCE_FROM_CENTRE_4), new Vector2(LARGE_PULP_4)); + Add(PositionAt(315, DISTANCE_FROM_CENTRE_4), new Vector2(LARGE_PULP_4)); + break; + + case FruitVisualRepresentation.Raspberry: + Add(new Vector2(0, -0.34f), new Vector2(SMALL_PULP)); + Add(PositionAt(0, DISTANCE_FROM_CENTRE_4), new Vector2(LARGE_PULP_4)); + Add(PositionAt(90, DISTANCE_FROM_CENTRE_4), new Vector2(LARGE_PULP_4)); + Add(PositionAt(180, DISTANCE_FROM_CENTRE_4), new Vector2(LARGE_PULP_4)); + Add(PositionAt(270, DISTANCE_FROM_CENTRE_4), new Vector2(LARGE_PULP_4)); + break; + + case FruitVisualRepresentation.Banana: + Add(new Vector2(0, -0.3f), new Vector2(SMALL_PULP)); + Add(new Vector2(0, 0.05f), new Vector2(LARGE_PULP_4 * 0.8f, LARGE_PULP_4 * 2.5f)); + break; + } + } + } +} diff --git a/osu.Game.Rulesets.Catch/Objects/Drawables/Pieces/GrapePiece.cs b/osu.Game.Rulesets.Catch/Objects/Drawables/Pieces/GrapePiece.cs deleted file mode 100644 index 15349c18d5..0000000000 --- a/osu.Game.Rulesets.Catch/Objects/Drawables/Pieces/GrapePiece.cs +++ /dev/null @@ -1,42 +0,0 @@ -// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. -// See the LICENCE file in the repository root for full licence text. - -using osu.Framework.Graphics; -using osuTK; - -namespace osu.Game.Rulesets.Catch.Objects.Drawables.Pieces -{ - public class GrapePiece : PulpFormation - { - public GrapePiece() - { - InternalChildren = new Drawable[] - { - new Pulp - { - AccentColour = { BindTarget = AccentColour }, - Size = new Vector2(SMALL_PULP), - Y = -0.25f, - }, - new Pulp - { - AccentColour = { BindTarget = AccentColour }, - Size = new Vector2(LARGE_PULP_3), - Position = PositionAt(0, DISTANCE_FROM_CENTRE_3), - }, - new Pulp - { - AccentColour = { BindTarget = AccentColour }, - Size = new Vector2(LARGE_PULP_3), - Position = PositionAt(120, DISTANCE_FROM_CENTRE_3), - }, - new Pulp - { - Size = new Vector2(LARGE_PULP_3), - AccentColour = { BindTarget = AccentColour }, - Position = PositionAt(240, DISTANCE_FROM_CENTRE_3), - }, - }; - } - } -} diff --git a/osu.Game.Rulesets.Catch/Objects/Drawables/Pieces/PearPiece.cs b/osu.Game.Rulesets.Catch/Objects/Drawables/Pieces/PearPiece.cs deleted file mode 100644 index 3372a06996..0000000000 --- a/osu.Game.Rulesets.Catch/Objects/Drawables/Pieces/PearPiece.cs +++ /dev/null @@ -1,42 +0,0 @@ -// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. -// See the LICENCE file in the repository root for full licence text. - -using osu.Framework.Graphics; -using osuTK; - -namespace osu.Game.Rulesets.Catch.Objects.Drawables.Pieces -{ - public class PearPiece : PulpFormation - { - public PearPiece() - { - InternalChildren = new Drawable[] - { - new Pulp - { - AccentColour = { BindTarget = AccentColour }, - Size = new Vector2(SMALL_PULP), - Y = -0.33f, - }, - new Pulp - { - AccentColour = { BindTarget = AccentColour }, - Size = new Vector2(LARGE_PULP_3), - Position = PositionAt(60, DISTANCE_FROM_CENTRE_3), - }, - new Pulp - { - AccentColour = { BindTarget = AccentColour }, - Size = new Vector2(LARGE_PULP_3), - Position = PositionAt(180, DISTANCE_FROM_CENTRE_3), - }, - new Pulp - { - Size = new Vector2(LARGE_PULP_3), - AccentColour = { BindTarget = AccentColour }, - Position = PositionAt(300, DISTANCE_FROM_CENTRE_3), - }, - }; - } - } -} diff --git a/osu.Game.Rulesets.Catch/Objects/Drawables/Pieces/PineapplePiece.cs b/osu.Game.Rulesets.Catch/Objects/Drawables/Pieces/PineapplePiece.cs deleted file mode 100644 index 7f80c58178..0000000000 --- a/osu.Game.Rulesets.Catch/Objects/Drawables/Pieces/PineapplePiece.cs +++ /dev/null @@ -1,48 +0,0 @@ -// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. -// See the LICENCE file in the repository root for full licence text. - -using osu.Framework.Graphics; -using osuTK; - -namespace osu.Game.Rulesets.Catch.Objects.Drawables.Pieces -{ - public class PineapplePiece : PulpFormation - { - public PineapplePiece() - { - InternalChildren = new Drawable[] - { - new Pulp - { - AccentColour = { BindTarget = AccentColour }, - Size = new Vector2(SMALL_PULP), - Y = -0.3f, - }, - new Pulp - { - AccentColour = { BindTarget = AccentColour }, - Size = new Vector2(LARGE_PULP_4), - Position = PositionAt(45, DISTANCE_FROM_CENTRE_4), - }, - new Pulp - { - AccentColour = { BindTarget = AccentColour }, - Size = new Vector2(LARGE_PULP_4), - Position = PositionAt(135, DISTANCE_FROM_CENTRE_4), - }, - new Pulp - { - AccentColour = { BindTarget = AccentColour }, - Size = new Vector2(LARGE_PULP_4), - Position = PositionAt(225, DISTANCE_FROM_CENTRE_4), - }, - new Pulp - { - Size = new Vector2(LARGE_PULP_4), - AccentColour = { BindTarget = AccentColour }, - Position = PositionAt(315, DISTANCE_FROM_CENTRE_4), - }, - }; - } - } -} diff --git a/osu.Game.Rulesets.Catch/Objects/Drawables/Pieces/Pulp.cs b/osu.Game.Rulesets.Catch/Objects/Drawables/Pieces/Pulp.cs index d3e4945611..3113cf0ceb 100644 --- a/osu.Game.Rulesets.Catch/Objects/Drawables/Pieces/Pulp.cs +++ b/osu.Game.Rulesets.Catch/Objects/Drawables/Pieces/Pulp.cs @@ -12,6 +12,8 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawables.Pieces { public class Pulp : Circle { + public readonly Bindable AccentColour = new Bindable(); + public Pulp() { RelativePositionAxes = Axes.Both; @@ -22,8 +24,6 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawables.Pieces Colour = Color4.White.Opacity(0.9f); } - public readonly Bindable AccentColour = new Bindable(); - protected override void LoadComplete() { base.LoadComplete(); diff --git a/osu.Game.Rulesets.Catch/Objects/Drawables/Pieces/PulpFormation.cs b/osu.Game.Rulesets.Catch/Objects/Drawables/Pieces/PulpFormation.cs index 1df548e70a..412750019f 100644 --- a/osu.Game.Rulesets.Catch/Objects/Drawables/Pieces/PulpFormation.cs +++ b/osu.Game.Rulesets.Catch/Objects/Drawables/Pieces/PulpFormation.cs @@ -2,11 +2,9 @@ // See the LICENCE file in the repository root for full licence text. using System; -using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; -using osu.Game.Rulesets.Objects.Drawables; using osuTK; using osuTK.Graphics; @@ -14,7 +12,7 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawables.Pieces { public abstract class PulpFormation : CompositeDrawable { - protected readonly IBindable AccentColour = new Bindable(); + public readonly Bindable AccentColour = new Bindable(); protected const float LARGE_PULP_3 = 16f * FruitPiece.RADIUS_ADJUST; protected const float DISTANCE_FROM_CENTRE_3 = 0.15f; @@ -24,6 +22,8 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawables.Pieces protected const float SMALL_PULP = LARGE_PULP_3 / 2; + private int numPulps; + protected PulpFormation() { RelativeSizeAxes = Axes.Both; @@ -33,11 +33,23 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawables.Pieces distance * MathF.Sin(angle * MathF.PI / 180), distance * MathF.Cos(angle * MathF.PI / 180)); - [BackgroundDependencyLoader] - private void load(DrawableHitObject drawableObject) + protected void Clear() { - DrawableCatchHitObject drawableCatchObject = (DrawableCatchHitObject)drawableObject; - AccentColour.BindTo(drawableCatchObject.AccentColour); + for (; numPulps > 0; numPulps--) + InternalChildren[numPulps - 1].Alpha = 0; + } + + protected void Add(Vector2 position, Vector2 size) + { + if (numPulps == InternalChildren.Count) + AddInternal(new Pulp { AccentColour = { BindTarget = AccentColour } }); + + var pulp = InternalChildren[numPulps]; + pulp.Position = position; + pulp.Size = size; + pulp.Alpha = 1; + + numPulps++; } } } diff --git a/osu.Game.Rulesets.Catch/Objects/Drawables/Pieces/RaspberryPiece.cs b/osu.Game.Rulesets.Catch/Objects/Drawables/Pieces/RaspberryPiece.cs deleted file mode 100644 index 288ece95b2..0000000000 --- a/osu.Game.Rulesets.Catch/Objects/Drawables/Pieces/RaspberryPiece.cs +++ /dev/null @@ -1,48 +0,0 @@ -// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. -// See the LICENCE file in the repository root for full licence text. - -using osu.Framework.Graphics; -using osuTK; - -namespace osu.Game.Rulesets.Catch.Objects.Drawables.Pieces -{ - public class RaspberryPiece : PulpFormation - { - public RaspberryPiece() - { - InternalChildren = new Drawable[] - { - new Pulp - { - AccentColour = { BindTarget = AccentColour }, - Size = new Vector2(SMALL_PULP), - Y = -0.34f, - }, - new Pulp - { - AccentColour = { BindTarget = AccentColour }, - Size = new Vector2(LARGE_PULP_4), - Position = PositionAt(0, DISTANCE_FROM_CENTRE_4), - }, - new Pulp - { - AccentColour = { BindTarget = AccentColour }, - Size = new Vector2(LARGE_PULP_4), - Position = PositionAt(90, DISTANCE_FROM_CENTRE_4), - }, - new Pulp - { - AccentColour = { BindTarget = AccentColour }, - Size = new Vector2(LARGE_PULP_4), - Position = PositionAt(180, DISTANCE_FROM_CENTRE_4), - }, - new Pulp - { - Size = new Vector2(LARGE_PULP_4), - AccentColour = { BindTarget = AccentColour }, - Position = PositionAt(270, DISTANCE_FROM_CENTRE_4), - }, - }; - } - } -} From c0f39514b9aba1295ba168ad29b541ba92d4b1a7 Mon Sep 17 00:00:00 2001 From: ekrctb Date: Mon, 7 Dec 2020 14:00:22 +0900 Subject: [PATCH 153/184] Fix legacy droplet scale --- osu.Game.Rulesets.Catch/Skinning/LegacyDropletPiece.cs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/osu.Game.Rulesets.Catch/Skinning/LegacyDropletPiece.cs b/osu.Game.Rulesets.Catch/Skinning/LegacyDropletPiece.cs index cc8886f631..8f4331d2a3 100644 --- a/osu.Game.Rulesets.Catch/Skinning/LegacyDropletPiece.cs +++ b/osu.Game.Rulesets.Catch/Skinning/LegacyDropletPiece.cs @@ -2,11 +2,17 @@ // See the LICENCE file in the repository root for full licence text. using osu.Framework.Graphics.Textures; +using osuTK; namespace osu.Game.Rulesets.Catch.Skinning { public class LegacyDropletPiece : LegacyCatchHitObjectPiece { + public LegacyDropletPiece() + { + Scale = new Vector2(0.8f); + } + protected override void LoadComplete() { base.LoadComplete(); From 7f1ad1040d3fef6def87abcd4144014b3952148b Mon Sep 17 00:00:00 2001 From: ekrctb Date: Mon, 7 Dec 2020 14:08:50 +0900 Subject: [PATCH 154/184] Don't inherit DrawableFruit from DrawableBanana - A banana cannot be hyper --- .../Objects/Drawables/DrawableBanana.cs | 15 +++++++++--- .../Objects/Drawables/DrawableFruit.cs | 7 ++---- .../Objects/Drawables/Pieces/BananaPiece.cs | 24 +++++++++++++++++++ .../Drawables/Pieces/BananaPulpFormation.cs | 16 +++++++++++++ .../Drawables/Pieces/FruitPulpFormation.cs | 5 ---- .../Skinning/CatchLegacySkinTransformer.cs | 2 +- .../Skinning/LegacyBananaPiece.cs | 20 ++++++++++++++++ .../Skinning/LegacyFruitPiece.cs | 2 +- 8 files changed, 76 insertions(+), 15 deletions(-) create mode 100644 osu.Game.Rulesets.Catch/Objects/Drawables/Pieces/BananaPiece.cs create mode 100644 osu.Game.Rulesets.Catch/Objects/Drawables/Pieces/BananaPulpFormation.cs create mode 100644 osu.Game.Rulesets.Catch/Skinning/LegacyBananaPiece.cs diff --git a/osu.Game.Rulesets.Catch/Objects/Drawables/DrawableBanana.cs b/osu.Game.Rulesets.Catch/Objects/Drawables/DrawableBanana.cs index 8e9d80106b..bdf257a13f 100644 --- a/osu.Game.Rulesets.Catch/Objects/Drawables/DrawableBanana.cs +++ b/osu.Game.Rulesets.Catch/Objects/Drawables/DrawableBanana.cs @@ -2,14 +2,15 @@ // See the LICENCE file in the repository root for full licence text. using JetBrains.Annotations; +using osu.Framework.Allocation; using osu.Framework.Graphics; +using osu.Game.Rulesets.Catch.Objects.Drawables.Pieces; +using osu.Game.Skinning; namespace osu.Game.Rulesets.Catch.Objects.Drawables { - public class DrawableBanana : DrawableFruit + public class DrawableBanana : DrawablePalpableCatchHitObject { - protected override FruitVisualRepresentation GetVisualRepresentation(int indexInBeatmap) => FruitVisualRepresentation.Banana; - public DrawableBanana() : this(null) { @@ -20,6 +21,14 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawables { } + [BackgroundDependencyLoader] + private void load() + { + ScaleContainer.Child = new SkinnableDrawable( + new CatchSkinComponent(CatchSkinComponents.Banana), + _ => new BananaPiece()); + } + protected override void LoadComplete() { base.LoadComplete(); diff --git a/osu.Game.Rulesets.Catch/Objects/Drawables/DrawableFruit.cs b/osu.Game.Rulesets.Catch/Objects/Drawables/DrawableFruit.cs index 8db8f5ec82..63b48ea99f 100644 --- a/osu.Game.Rulesets.Catch/Objects/Drawables/DrawableFruit.cs +++ b/osu.Game.Rulesets.Catch/Objects/Drawables/DrawableFruit.cs @@ -14,8 +14,6 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawables { public readonly Bindable VisualRepresentation = new Bindable(); - protected virtual FruitVisualRepresentation GetVisualRepresentation(int indexInBeatmap) => (FruitVisualRepresentation)(indexInBeatmap % 4); - public DrawableFruit() : this(null) { @@ -31,11 +29,11 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawables { IndexInBeatmap.BindValueChanged(change => { - VisualRepresentation.Value = GetVisualRepresentation(change.NewValue); + VisualRepresentation.Value = (FruitVisualRepresentation)(change.NewValue % 4); }, true); ScaleContainer.Child = new SkinnableDrawable( - new CatchSkinComponent(this is DrawableBanana ? CatchSkinComponents.Banana : CatchSkinComponents.Fruit), + new CatchSkinComponent(CatchSkinComponents.Fruit), _ => new FruitPiece()); } @@ -53,6 +51,5 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawables Grape, Pineapple, Raspberry, - Banana // banananananannaanana } } diff --git a/osu.Game.Rulesets.Catch/Objects/Drawables/Pieces/BananaPiece.cs b/osu.Game.Rulesets.Catch/Objects/Drawables/Pieces/BananaPiece.cs new file mode 100644 index 0000000000..9f5d3f36df --- /dev/null +++ b/osu.Game.Rulesets.Catch/Objects/Drawables/Pieces/BananaPiece.cs @@ -0,0 +1,24 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using osu.Framework.Graphics; + +namespace osu.Game.Rulesets.Catch.Objects.Drawables.Pieces +{ + public class BananaPiece : CatchHitObjectPiece + { + public BananaPiece() + { + RelativeSizeAxes = Axes.Both; + + InternalChildren = new Drawable[] + { + new BananaPulpFormation + { + AccentColour = { BindTarget = AccentColour }, + }, + BorderPiece = new BorderPiece(), + }; + } + } +} diff --git a/osu.Game.Rulesets.Catch/Objects/Drawables/Pieces/BananaPulpFormation.cs b/osu.Game.Rulesets.Catch/Objects/Drawables/Pieces/BananaPulpFormation.cs new file mode 100644 index 0000000000..b22d7fb413 --- /dev/null +++ b/osu.Game.Rulesets.Catch/Objects/Drawables/Pieces/BananaPulpFormation.cs @@ -0,0 +1,16 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using osuTK; + +namespace osu.Game.Rulesets.Catch.Objects.Drawables.Pieces +{ + public class BananaPulpFormation : PulpFormation + { + public BananaPulpFormation() + { + Add(new Vector2(0, -0.3f), new Vector2(SMALL_PULP)); + Add(new Vector2(0, 0.05f), new Vector2(LARGE_PULP_4 * 0.8f, LARGE_PULP_4 * 2.5f)); + } + } +} diff --git a/osu.Game.Rulesets.Catch/Objects/Drawables/Pieces/FruitPulpFormation.cs b/osu.Game.Rulesets.Catch/Objects/Drawables/Pieces/FruitPulpFormation.cs index cd870b1f98..c0b1f588f5 100644 --- a/osu.Game.Rulesets.Catch/Objects/Drawables/Pieces/FruitPulpFormation.cs +++ b/osu.Game.Rulesets.Catch/Objects/Drawables/Pieces/FruitPulpFormation.cs @@ -52,11 +52,6 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawables.Pieces Add(PositionAt(180, DISTANCE_FROM_CENTRE_4), new Vector2(LARGE_PULP_4)); Add(PositionAt(270, DISTANCE_FROM_CENTRE_4), new Vector2(LARGE_PULP_4)); break; - - case FruitVisualRepresentation.Banana: - Add(new Vector2(0, -0.3f), new Vector2(SMALL_PULP)); - Add(new Vector2(0, 0.05f), new Vector2(LARGE_PULP_4 * 0.8f, LARGE_PULP_4 * 2.5f)); - break; } } } diff --git a/osu.Game.Rulesets.Catch/Skinning/CatchLegacySkinTransformer.cs b/osu.Game.Rulesets.Catch/Skinning/CatchLegacySkinTransformer.cs index 1889b230a7..b4bee8adc6 100644 --- a/osu.Game.Rulesets.Catch/Skinning/CatchLegacySkinTransformer.cs +++ b/osu.Game.Rulesets.Catch/Skinning/CatchLegacySkinTransformer.cs @@ -46,7 +46,7 @@ namespace osu.Game.Rulesets.Catch.Skinning case CatchSkinComponents.Banana: if (GetTexture("fruit-bananas") != null) - return new LegacyFruitPiece(); + return new LegacyBananaPiece(); break; diff --git a/osu.Game.Rulesets.Catch/Skinning/LegacyBananaPiece.cs b/osu.Game.Rulesets.Catch/Skinning/LegacyBananaPiece.cs new file mode 100644 index 0000000000..f80e50c8c0 --- /dev/null +++ b/osu.Game.Rulesets.Catch/Skinning/LegacyBananaPiece.cs @@ -0,0 +1,20 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using osu.Framework.Graphics.Textures; + +namespace osu.Game.Rulesets.Catch.Skinning +{ + public class LegacyBananaPiece : LegacyCatchHitObjectPiece + { + protected override void LoadComplete() + { + base.LoadComplete(); + + Texture texture = Skin.GetTexture("fruit-bananas"); + Texture overlayTexture = Skin.GetTexture("fruit-bananas-overlay"); + + SetTexture(texture, overlayTexture); + } + } +} diff --git a/osu.Game.Rulesets.Catch/Skinning/LegacyFruitPiece.cs b/osu.Game.Rulesets.Catch/Skinning/LegacyFruitPiece.cs index 7008234e99..9b3003f1d6 100644 --- a/osu.Game.Rulesets.Catch/Skinning/LegacyFruitPiece.cs +++ b/osu.Game.Rulesets.Catch/Skinning/LegacyFruitPiece.cs @@ -13,7 +13,7 @@ namespace osu.Game.Rulesets.Catch.Skinning private readonly string[] lookupNames = { - "fruit-pear", "fruit-grapes", "fruit-apple", "fruit-orange", "fruit-bananas" + "fruit-pear", "fruit-grapes", "fruit-apple", "fruit-orange" }; protected override void LoadComplete() From c1d39b64010652f194df448b74f9ccedc04fea0a Mon Sep 17 00:00:00 2001 From: ekrctb Date: Mon, 7 Dec 2020 14:10:17 +0900 Subject: [PATCH 155/184] Don't inherit Fruit from Banana --- osu.Game.Rulesets.Catch/Objects/Banana.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Catch/Objects/Banana.cs b/osu.Game.Rulesets.Catch/Objects/Banana.cs index 3f71da713e..178306b3bc 100644 --- a/osu.Game.Rulesets.Catch/Objects/Banana.cs +++ b/osu.Game.Rulesets.Catch/Objects/Banana.cs @@ -14,7 +14,7 @@ using osuTK.Graphics; namespace osu.Game.Rulesets.Catch.Objects { - public class Banana : Fruit, IHasComboInformation + public class Banana : PalpableCatchHitObject, IHasComboInformation { /// /// Index of banana in current shower. From 2469608c1004d73dcf6a71704acdf8fabe96f53d Mon Sep 17 00:00:00 2001 From: ekrctb Date: Mon, 7 Dec 2020 15:19:18 +0900 Subject: [PATCH 156/184] Fix possible null reference due to bindable change before variable is initialized --- osu.Game/Overlays/Settings/Sections/Input/MouseSettings.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/osu.Game/Overlays/Settings/Sections/Input/MouseSettings.cs b/osu.Game/Overlays/Settings/Sections/Input/MouseSettings.cs index ec0ce08004..ebdf23e5bd 100644 --- a/osu.Game/Overlays/Settings/Sections/Input/MouseSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Input/MouseSettings.cs @@ -33,9 +33,6 @@ namespace osu.Game.Overlays.Settings.Sections.Input configSensitivity.BindValueChanged(val => sensitivityBindable.Value = val.NewValue); sensitivityBindable.BindValueChanged(val => configSensitivity.Value = val.NewValue); - windowMode = config.GetBindable(FrameworkSetting.WindowMode); - windowMode.BindValueChanged(mode => confineMouseModeSetting.Alpha = mode.NewValue == WindowMode.Fullscreen ? 0 : 1); - Children = new Drawable[] { new SettingsCheckbox @@ -70,6 +67,9 @@ namespace osu.Game.Overlays.Settings.Sections.Input }, }; + windowMode = config.GetBindable(FrameworkSetting.WindowMode); + windowMode.BindValueChanged(mode => confineMouseModeSetting.Alpha = mode.NewValue == WindowMode.Fullscreen ? 0 : 1); + if (RuntimeInfo.OS != RuntimeInfo.Platform.Windows) { rawInputToggle.Disabled = true; From f4eb17d398b5c98e711986fe02a1c4c30ca1b0a5 Mon Sep 17 00:00:00 2001 From: ekrctb <32995012+ekrctb@users.noreply.github.com> Date: Mon, 7 Dec 2020 16:09:14 +0900 Subject: [PATCH 157/184] Update osu.Game/Overlays/Settings/Sections/Input/MouseSettings.cs Set mouse confine mode at initialization Co-authored-by: Dean Herbert --- osu.Game/Overlays/Settings/Sections/Input/MouseSettings.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Overlays/Settings/Sections/Input/MouseSettings.cs b/osu.Game/Overlays/Settings/Sections/Input/MouseSettings.cs index ebdf23e5bd..455e13711d 100644 --- a/osu.Game/Overlays/Settings/Sections/Input/MouseSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Input/MouseSettings.cs @@ -68,7 +68,7 @@ namespace osu.Game.Overlays.Settings.Sections.Input }; windowMode = config.GetBindable(FrameworkSetting.WindowMode); - windowMode.BindValueChanged(mode => confineMouseModeSetting.Alpha = mode.NewValue == WindowMode.Fullscreen ? 0 : 1); + windowMode.BindValueChanged(mode => confineMouseModeSetting.Alpha = mode.NewValue == WindowMode.Fullscreen ? 0 : 1, true); if (RuntimeInfo.OS != RuntimeInfo.Platform.Windows) { From 7253866e1790c7009304a1ebfb2f1ecb5cca1258 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 7 Dec 2020 16:42:55 +0900 Subject: [PATCH 158/184] Move customisation panel to be in same area as main content --- osu.Game/Overlays/Mods/ModSelectOverlay.cs | 84 ++++++++++++---------- 1 file changed, 47 insertions(+), 37 deletions(-) diff --git a/osu.Game/Overlays/Mods/ModSelectOverlay.cs b/osu.Game/Overlays/Mods/ModSelectOverlay.cs index 12da718ab2..34f5c70adb 100644 --- a/osu.Game/Overlays/Mods/ModSelectOverlay.cs +++ b/osu.Game/Overlays/Mods/ModSelectOverlay.cs @@ -158,37 +158,57 @@ namespace osu.Game.Overlays.Mods }, new Drawable[] { - // Body - new OsuScrollContainer + new Container { - ScrollbarVisible = false, - Origin = Anchor.TopCentre, - Anchor = Anchor.TopCentre, RelativeSizeAxes = Axes.Both, - Padding = new MarginPadding + Children = new Drawable[] { - Vertical = 10, - Horizontal = OsuScreen.HORIZONTAL_OVERFLOW_PADDING - }, - Child = ModSectionsContainer = new FillFlowContainer - { - Origin = Anchor.TopCentre, - Anchor = Anchor.TopCentre, - RelativeSizeAxes = Axes.X, - AutoSizeAxes = Axes.Y, - Spacing = new Vector2(0f, 10f), - Width = content_width, - LayoutDuration = 200, - LayoutEasing = Easing.OutQuint, - Children = new ModSection[] + // Body + new OsuScrollContainer { - new DifficultyReductionSection { Action = modButtonPressed }, - new DifficultyIncreaseSection { Action = modButtonPressed }, - new AutomationSection { Action = modButtonPressed }, - new ConversionSection { Action = modButtonPressed }, - new FunSection { Action = modButtonPressed }, - } - }, + ScrollbarVisible = false, + Origin = Anchor.TopCentre, + Anchor = Anchor.TopCentre, + RelativeSizeAxes = Axes.Both, + Padding = new MarginPadding + { + Vertical = 10, + Horizontal = OsuScreen.HORIZONTAL_OVERFLOW_PADDING + }, + Children = new Drawable[] + { + ModSectionsContainer = new FillFlowContainer + { + Origin = Anchor.TopCentre, + Anchor = Anchor.TopCentre, + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + Spacing = new Vector2(0f, 10f), + Width = content_width, + LayoutDuration = 200, + LayoutEasing = Easing.OutQuint, + Children = new ModSection[] + { + new DifficultyReductionSection { Action = modButtonPressed }, + new DifficultyIncreaseSection { Action = modButtonPressed }, + new AutomationSection { Action = modButtonPressed }, + new ConversionSection { Action = modButtonPressed }, + new FunSection { Action = modButtonPressed }, + } + }, + } + }, + ModSettingsContainer = new ModSettingsContainer + { + RelativeSizeAxes = Axes.Both, + Anchor = Anchor.BottomRight, + Origin = Anchor.BottomRight, + Width = 0.3f, + Alpha = 0, + Padding = new MarginPadding(30), + SelectedMods = { BindTarget = SelectedMods }, + }, + } }, }, new Drawable[] @@ -281,16 +301,6 @@ namespace osu.Game.Overlays.Mods }, }, }, - ModSettingsContainer = new ModSettingsContainer - { - RelativeSizeAxes = Axes.Both, - Anchor = Anchor.BottomRight, - Origin = Anchor.BottomRight, - Width = 0.25f, - Alpha = 0, - X = -100, - SelectedMods = { BindTarget = SelectedMods }, - } }; ((IBindable)CustomiseButton.Enabled).BindTo(ModSettingsContainer.HasSettingsForSelection); From 454e94574c5c8a7a3c4989c4a1b79b1c47f5967a Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 7 Dec 2020 16:43:07 +0900 Subject: [PATCH 159/184] Add corner rounding and positional transform --- .../Overlays/Mods/ModSettingsContainer.cs | 46 ++++++++++++------- 1 file changed, 30 insertions(+), 16 deletions(-) diff --git a/osu.Game/Overlays/Mods/ModSettingsContainer.cs b/osu.Game/Overlays/Mods/ModSettingsContainer.cs index a1d00f91b4..1c57ff54ad 100644 --- a/osu.Game/Overlays/Mods/ModSettingsContainer.cs +++ b/osu.Game/Overlays/Mods/ModSettingsContainer.cs @@ -27,28 +27,40 @@ namespace osu.Game.Overlays.Mods private readonly FillFlowContainer modSettingsContent; - private const double transition_duration = 200; + private readonly Container content; + + private const double transition_duration = 400; public ModSettingsContainer() { - Children = new Drawable[] + RelativeSizeAxes = Axes.Both; + + Child = content = new Container { - new Box + Masking = true, + CornerRadius = 10, + RelativeSizeAxes = Axes.Both, + RelativePositionAxes = Axes.Both, + X = 1, + Children = new Drawable[] { - RelativeSizeAxes = Axes.Both, - Colour = new Color4(0, 0, 0, 192) - }, - new OsuScrollContainer - { - RelativeSizeAxes = Axes.Both, - Child = modSettingsContent = new FillFlowContainer + new Box { - Anchor = Anchor.TopCentre, - Origin = Anchor.TopCentre, - RelativeSizeAxes = Axes.X, - AutoSizeAxes = Axes.Y, - Spacing = new Vector2(0f, 10f), - Padding = new MarginPadding(20), + RelativeSizeAxes = Axes.Both, + Colour = new Color4(0, 0, 0, 192) + }, + new OsuScrollContainer + { + RelativeSizeAxes = Axes.Both, + Child = modSettingsContent = new FillFlowContainer + { + Anchor = Anchor.TopCentre, + Origin = Anchor.TopCentre, + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + Spacing = new Vector2(0f, 10f), + Padding = new MarginPadding(20), + } } } }; @@ -86,11 +98,13 @@ namespace osu.Game.Overlays.Mods protected override void PopIn() { this.FadeIn(transition_duration, Easing.OutQuint); + content.MoveToX(0, transition_duration, Easing.OutQuint); } protected override void PopOut() { this.FadeOut(transition_duration, Easing.OutQuint); + content.MoveToX(1, transition_duration, Easing.OutQuint); } } } From a548269c341296145d5381ca6d1365640be50991 Mon Sep 17 00:00:00 2001 From: ekrctb Date: Mon, 7 Dec 2020 17:26:12 +0900 Subject: [PATCH 160/184] Fix scrolling hit object displayed in wrong position for one frame --- .../Scrolling/ScrollingHitObjectContainer.cs | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/osu.Game/Rulesets/UI/Scrolling/ScrollingHitObjectContainer.cs b/osu.Game/Rulesets/UI/Scrolling/ScrollingHitObjectContainer.cs index 3a5e3c098f..289578f3d8 100644 --- a/osu.Game/Rulesets/UI/Scrolling/ScrollingHitObjectContainer.cs +++ b/osu.Game/Rulesets/UI/Scrolling/ScrollingHitObjectContainer.cs @@ -225,10 +225,19 @@ namespace osu.Game.Rulesets.UI.Scrolling hitObject.LifetimeStart = computeOriginAdjustedLifetimeStart(hitObject); toComputeLifetime.Clear(); + } - // only AliveObjects need to be considered for layout (reduces overhead in the case of scroll speed changes). + protected override void UpdateAfterChildrenLife() + { + base.UpdateAfterChildrenLife(); + + // We need to calculate hit object positions (including nested hit objects) as soon as possible after lifetimes + // to prevent hit objects displayed in a wrong position for one frame. + // Only AliveObjects need to be considered for layout (reduces overhead in the case of scroll speed changes). foreach (var obj in AliveObjects) { + updatePosition(obj, Time.Current); + if (layoutComputed.Contains(obj)) continue; @@ -293,15 +302,6 @@ namespace osu.Game.Rulesets.UI.Scrolling } } - protected override void UpdateAfterChildrenLife() - { - base.UpdateAfterChildrenLife(); - - // We need to calculate hitobject positions as soon as possible after lifetimes so that hitobjects get the final say in their positions - foreach (var obj in AliveObjects) - updatePosition(obj, Time.Current); - } - private void updatePosition(DrawableHitObject hitObject, double currentTime) { switch (direction.Value) From eb38bc4b4c755f0e7612cf9b9e10063341c4f318 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 7 Dec 2020 18:00:45 +0900 Subject: [PATCH 161/184] Add the ability to import into ArchiveModelManagers from a stream --- .../Beatmaps/IO/ImportBeatmapTest.cs | 15 ++-- .../Menus/TestSceneMusicActionHandling.cs | 3 +- .../Online/TestSceneDirectDownloadButton.cs | 2 +- .../TestSceneDeleteLocalScore.cs | 3 +- osu.Game/Database/ArchiveModelManager.cs | 55 ++++++-------- .../DownloadableArchiveModelManager.cs | 2 +- osu.Game/Database/ICanAcceptFiles.cs | 8 ++ osu.Game/Database/ImportTask.cs | 73 +++++++++++++++++++ osu.Game/OsuGameBase.cs | 11 +++ .../Screens/Edit/Setup/ResourcesSection.cs | 3 + 10 files changed, 132 insertions(+), 43 deletions(-) create mode 100644 osu.Game/Database/ImportTask.cs diff --git a/osu.Game.Tests/Beatmaps/IO/ImportBeatmapTest.cs b/osu.Game.Tests/Beatmaps/IO/ImportBeatmapTest.cs index b941313103..6e16058360 100644 --- a/osu.Game.Tests/Beatmaps/IO/ImportBeatmapTest.cs +++ b/osu.Game.Tests/Beatmaps/IO/ImportBeatmapTest.cs @@ -14,6 +14,7 @@ using osu.Framework.Allocation; using osu.Framework.Extensions; using osu.Framework.Logging; using osu.Game.Beatmaps; +using osu.Game.Database; using osu.Game.IO; using osu.Game.Rulesets.Osu; using osu.Game.Rulesets.Osu.Objects; @@ -127,7 +128,7 @@ namespace osu.Game.Tests.Beatmaps.IO // zip files differ because different compression or encoder. Assert.AreNotEqual(hashBefore, hashFile(temp)); - var importedSecondTime = await osu.Dependencies.Get().Import(temp); + var importedSecondTime = await osu.Dependencies.Get().Import(new ImportTask(temp)); ensureLoaded(osu); @@ -184,7 +185,7 @@ namespace osu.Game.Tests.Beatmaps.IO zip.SaveTo(temp, new ZipWriterOptions(CompressionType.Deflate)); } - var importedSecondTime = await osu.Dependencies.Get().Import(temp); + var importedSecondTime = await osu.Dependencies.Get().Import(new ImportTask(temp)); ensureLoaded(osu); @@ -235,7 +236,7 @@ namespace osu.Game.Tests.Beatmaps.IO zip.SaveTo(temp, new ZipWriterOptions(CompressionType.Deflate)); } - var importedSecondTime = await osu.Dependencies.Get().Import(temp); + var importedSecondTime = await osu.Dependencies.Get().Import(new ImportTask(temp)); ensureLoaded(osu); @@ -351,7 +352,7 @@ namespace osu.Game.Tests.Beatmaps.IO // this will trigger purging of the existing beatmap (online set id match) but should rollback due to broken osu. try { - await manager.Import(breakTemp); + await manager.Import(new ImportTask(breakTemp)); } catch { @@ -614,7 +615,7 @@ namespace osu.Game.Tests.Beatmaps.IO zip.SaveTo(temp, new ZipWriterOptions(CompressionType.Deflate)); } - var imported = await osu.Dependencies.Get().Import(temp); + var imported = await osu.Dependencies.Get().Import(new ImportTask(temp)); ensureLoaded(osu); @@ -667,7 +668,7 @@ namespace osu.Game.Tests.Beatmaps.IO zip.SaveTo(temp, new ZipWriterOptions(CompressionType.Deflate)); } - var imported = await osu.Dependencies.Get().Import(temp); + var imported = await osu.Dependencies.Get().Import(new ImportTask(temp)); ensureLoaded(osu); @@ -821,7 +822,7 @@ namespace osu.Game.Tests.Beatmaps.IO var manager = osu.Dependencies.Get(); - var importedSet = await manager.Import(temp); + var importedSet = await manager.Import(new ImportTask(temp)); ensureLoaded(osu); diff --git a/osu.Game.Tests/Visual/Menus/TestSceneMusicActionHandling.cs b/osu.Game.Tests/Visual/Menus/TestSceneMusicActionHandling.cs index b34e027e9c..aaf3323432 100644 --- a/osu.Game.Tests/Visual/Menus/TestSceneMusicActionHandling.cs +++ b/osu.Game.Tests/Visual/Menus/TestSceneMusicActionHandling.cs @@ -6,6 +6,7 @@ using System.Linq; using NUnit.Framework; using osu.Framework.Testing; using osu.Game.Beatmaps; +using osu.Game.Database; using osu.Game.Input.Bindings; using osu.Game.Overlays; using osu.Game.Tests.Resources; @@ -52,7 +53,7 @@ namespace osu.Game.Tests.Visual.Menus AddStep("import beatmap with track", () => { - var setWithTrack = Game.BeatmapManager.Import(TestResources.GetTestBeatmapForImport()).Result; + var setWithTrack = Game.BeatmapManager.Import(new ImportTask(TestResources.GetTestBeatmapForImport())).Result; Beatmap.Value = Game.BeatmapManager.GetWorkingBeatmap(setWithTrack.Beatmaps.First()); }); diff --git a/osu.Game.Tests/Visual/Online/TestSceneDirectDownloadButton.cs b/osu.Game.Tests/Visual/Online/TestSceneDirectDownloadButton.cs index 684ce10820..63bda08c88 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneDirectDownloadButton.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneDirectDownloadButton.cs @@ -42,7 +42,7 @@ namespace osu.Game.Tests.Visual.Online ensureSoleilyRemoved(); createButtonWithBeatmap(createSoleily()); AddAssert("button state not downloaded", () => downloadButton.DownloadState == DownloadState.NotDownloaded); - AddStep("import soleily", () => beatmaps.Import(new[] { TestResources.GetTestBeatmapForImport() })); + AddStep("import soleily", () => beatmaps.Import(TestResources.GetTestBeatmapForImport())); AddUntilStep("wait for beatmap import", () => beatmaps.GetAllUsableBeatmapSets().Any(b => b.OnlineBeatmapSetID == 241526)); createButtonWithBeatmap(createSoleily()); AddAssert("button state downloaded", () => downloadButton.DownloadState == DownloadState.LocallyAvailable); diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneDeleteLocalScore.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneDeleteLocalScore.cs index e54292f7cc..81862448a8 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneDeleteLocalScore.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneDeleteLocalScore.cs @@ -12,6 +12,7 @@ using osu.Framework.Platform; using osu.Framework.Testing; using osu.Framework.Utils; using osu.Game.Beatmaps; +using osu.Game.Database; using osu.Game.Graphics.Cursor; using osu.Game.Graphics.UserInterface; using osu.Game.Online.Leaderboards; @@ -83,7 +84,7 @@ namespace osu.Game.Tests.Visual.UserInterface dependencies.Cache(beatmapManager = new BeatmapManager(LocalStorage, ContextFactory, rulesetStore, null, dependencies.Get(), dependencies.Get(), Beatmap.Default)); dependencies.Cache(scoreManager = new ScoreManager(rulesetStore, () => beatmapManager, LocalStorage, null, ContextFactory)); - beatmap = beatmapManager.Import(TestResources.GetTestBeatmapForImport()).Result.Beatmaps[0]; + beatmap = beatmapManager.Import(new ImportTask(TestResources.GetTestBeatmapForImport())).Result.Beatmaps[0]; for (int i = 0; i < 50; i++) { diff --git a/osu.Game/Database/ArchiveModelManager.cs b/osu.Game/Database/ArchiveModelManager.cs index 8bdc804311..e18dc7f7eb 100644 --- a/osu.Game/Database/ArchiveModelManager.cs +++ b/osu.Game/Database/ArchiveModelManager.cs @@ -21,9 +21,7 @@ using osu.Game.IO; using osu.Game.IO.Archives; using osu.Game.IPC; using osu.Game.Overlays.Notifications; -using osu.Game.Utils; using SharpCompress.Archives.Zip; -using SharpCompress.Common; using FileInfo = osu.Game.IO.FileInfo; namespace osu.Game.Database @@ -114,10 +112,19 @@ namespace osu.Game.Database PostNotification?.Invoke(notification); - return Import(notification, paths); + return Import(notification, paths.Select(p => new ImportTask(p)).ToArray()); } - protected async Task> Import(ProgressNotification notification, params string[] paths) + public Task Import(Stream stream, string filename) + { + var notification = new ProgressNotification { State = ProgressNotificationState.Active }; + + PostNotification?.Invoke(notification); + + return Import(notification, new ImportTask(stream, filename)); + } + + protected async Task> Import(ProgressNotification notification, params ImportTask[] tasks) { notification.Progress = 0; notification.Text = $"{HumanisedModelName.Humanize(LetterCasing.Title)} import is initialising..."; @@ -126,13 +133,13 @@ namespace osu.Game.Database var imported = new List(); - await Task.WhenAll(paths.Select(async path => + await Task.WhenAll(tasks.Select(async task => { notification.CancellationToken.ThrowIfCancellationRequested(); try { - var model = await Import(path, notification.CancellationToken); + var model = await Import(task, notification.CancellationToken); lock (imported) { @@ -140,8 +147,8 @@ namespace osu.Game.Database imported.Add(model); current++; - notification.Text = $"Imported {current} of {paths.Length} {HumanisedModelName}s"; - notification.Progress = (float)current / paths.Length; + notification.Text = $"Imported {current} of {tasks.Length} {HumanisedModelName}s"; + notification.Progress = (float)current / tasks.Length; } } catch (TaskCanceledException) @@ -150,7 +157,7 @@ namespace osu.Game.Database } catch (Exception e) { - Logger.Error(e, $@"Could not import ({Path.GetFileName(path)})", LoggingTarget.Database); + Logger.Error(e, $@"Could not import ({task})", LoggingTarget.Database); } })); @@ -183,16 +190,17 @@ namespace osu.Game.Database /// /// Import one from the filesystem and delete the file on success. + /// Note that this bypasses the UI flow and should only be used for special cases or testing. /// - /// The archive location on disk. + /// The archive location on disk. /// An optional cancellation token. /// The imported model, if successful. - public async Task Import(string path, CancellationToken cancellationToken = default) + internal async Task Import(ImportTask task, CancellationToken cancellationToken = default) { cancellationToken.ThrowIfCancellationRequested(); TModel import; - using (ArchiveReader reader = getReaderFrom(path)) + using (ArchiveReader reader = task.GetReader()) import = await Import(reader, cancellationToken); // We may or may not want to delete the file depending on where it is stored. @@ -201,12 +209,12 @@ namespace osu.Game.Database // TODO: Add a check to prevent files from storage to be deleted. try { - if (import != null && File.Exists(path) && ShouldDeleteArchive(path)) - File.Delete(path); + if (import != null && File.Exists(task.Path) && ShouldDeleteArchive(task.Path)) + File.Delete(task.Path); } catch (Exception e) { - LogForModel(import, $@"Could not delete original file after import ({Path.GetFileName(path)})", e); + LogForModel(import, $@"Could not delete original file after import ({task})", e); } return import; @@ -727,23 +735,6 @@ namespace osu.Game.Database protected virtual string HumanisedModelName => $"{typeof(TModel).Name.Replace("Info", "").ToLower()}"; - /// - /// Creates an from a valid storage path. - /// - /// A file or folder path resolving the archive content. - /// A reader giving access to the archive's content. - private ArchiveReader getReaderFrom(string path) - { - if (ZipUtils.IsZipArchive(path)) - return new ZipArchiveReader(File.Open(path, FileMode.Open, FileAccess.Read, FileShare.Read), Path.GetFileName(path)); - if (Directory.Exists(path)) - return new LegacyDirectoryArchiveReader(path); - if (File.Exists(path)) - return new LegacyFileArchiveReader(path); - - throw new InvalidFormatException($"{path} is not a valid archive"); - } - #region Event handling / delaying private readonly List queuedEvents = new List(); diff --git a/osu.Game/Database/DownloadableArchiveModelManager.cs b/osu.Game/Database/DownloadableArchiveModelManager.cs index 8f469ca590..50b022f9ff 100644 --- a/osu.Game/Database/DownloadableArchiveModelManager.cs +++ b/osu.Game/Database/DownloadableArchiveModelManager.cs @@ -82,7 +82,7 @@ namespace osu.Game.Database Task.Factory.StartNew(async () => { // This gets scheduled back to the update thread, but we want the import to run in the background. - var imported = await Import(notification, filename); + var imported = await Import(notification, new ImportTask(filename)); // for now a failed import will be marked as a failed download for simplicity. if (!imported.Any()) diff --git a/osu.Game/Database/ICanAcceptFiles.cs b/osu.Game/Database/ICanAcceptFiles.cs index e4d92d957c..276c284c9f 100644 --- a/osu.Game/Database/ICanAcceptFiles.cs +++ b/osu.Game/Database/ICanAcceptFiles.cs @@ -2,6 +2,7 @@ // See the LICENCE file in the repository root for full licence text. using System.Collections.Generic; +using System.IO; using System.Threading.Tasks; namespace osu.Game.Database @@ -17,6 +18,13 @@ namespace osu.Game.Database /// The files which should be imported. Task Import(params string[] paths); + /// + /// Import the provided stream as a simple item. + /// + /// The stream to import files from. Should be in a supported archive format. + /// The filename of the archive being imported. + Task Import(Stream stream, string filename); + /// /// An array of accepted file extensions (in the standard format of ".abc"). /// diff --git a/osu.Game/Database/ImportTask.cs b/osu.Game/Database/ImportTask.cs new file mode 100644 index 0000000000..89eb347df0 --- /dev/null +++ b/osu.Game/Database/ImportTask.cs @@ -0,0 +1,73 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System.IO; +using osu.Game.IO.Archives; +using osu.Game.Utils; +using SharpCompress.Common; + +namespace osu.Game.Database +{ + /// + /// An encapsulated import task to be imported to an . + /// + public class ImportTask + { + /// + /// The path to the file (or filename in the case a stream is provided). + /// + public string Path { get; } + + /// + /// An optional stream which provides the file content. + /// + public Stream Stream { get; } + + /// + /// Construct a new import task from a path (on a local filesystem). + /// + public ImportTask(string path) + { + Path = path; + } + + /// + /// Construct a new import task from a stream. + /// + public ImportTask(Stream stream, string filename) + { + Path = filename; + Stream = stream; + } + + /// + /// Retrieve an archive reader from this task. + /// + public ArchiveReader GetReader() + { + if (Stream != null) + return new ZipArchiveReader(Stream, Path); + + return getReaderFrom(Path); + } + + /// + /// Creates an from a valid storage path. + /// + /// A file or folder path resolving the archive content. + /// A reader giving access to the archive's content. + private ArchiveReader getReaderFrom(string path) + { + if (ZipUtils.IsZipArchive(path)) + return new ZipArchiveReader(File.Open(path, FileMode.Open, FileAccess.Read, FileShare.Read), System.IO.Path.GetFileName(path)); + if (Directory.Exists(path)) + return new LegacyDirectoryArchiveReader(path); + if (File.Exists(path)) + return new LegacyFileArchiveReader(path); + + throw new InvalidFormatException($"{path} is not a valid archive"); + } + + public override string ToString() => System.IO.Path.GetFileName(Path); + } +} diff --git a/osu.Game/OsuGameBase.cs b/osu.Game/OsuGameBase.cs index e7b5d3304d..0fc2b8d1d7 100644 --- a/osu.Game/OsuGameBase.cs +++ b/osu.Game/OsuGameBase.cs @@ -395,6 +395,17 @@ namespace osu.Game } } + public async Task Import(Stream stream, string filename) + { + var extension = Path.GetExtension(filename)?.ToLowerInvariant(); + + foreach (var importer in fileImporters) + { + if (importer.HandledExtensions.Contains(extension)) + await importer.Import(stream, Path.GetFileNameWithoutExtension(filename)); + } + } + public IEnumerable HandledExtensions => fileImporters.SelectMany(i => i.HandledExtensions); protected override void Dispose(bool isDisposing) diff --git a/osu.Game/Screens/Edit/Setup/ResourcesSection.cs b/osu.Game/Screens/Edit/Setup/ResourcesSection.cs index 17ecfdd52e..0c957b80af 100644 --- a/osu.Game/Screens/Edit/Setup/ResourcesSection.cs +++ b/osu.Game/Screens/Edit/Setup/ResourcesSection.cs @@ -1,6 +1,7 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System; using System.Collections.Generic; using System.IO; using System.Linq; @@ -99,6 +100,8 @@ namespace osu.Game.Screens.Edit.Setup return Task.CompletedTask; } + Task ICanAcceptFiles.Import(Stream stream, string filename) => throw new NotImplementedException(); + protected override void LoadComplete() { base.LoadComplete(); From 12c6b3c1fb8df3431cc7b64db5aeda623c0a2687 Mon Sep 17 00:00:00 2001 From: ekrctb Date: Mon, 7 Dec 2020 18:12:55 +0900 Subject: [PATCH 162/184] Pool catcher trail sprite --- .../UI/CatcherTrailDisplay.cs | 22 +++++++++++-------- .../UI/CatcherTrailSprite.cs | 18 ++++++++++++--- 2 files changed, 28 insertions(+), 12 deletions(-) diff --git a/osu.Game.Rulesets.Catch/UI/CatcherTrailDisplay.cs b/osu.Game.Rulesets.Catch/UI/CatcherTrailDisplay.cs index f7e9fd19a7..fa65190032 100644 --- a/osu.Game.Rulesets.Catch/UI/CatcherTrailDisplay.cs +++ b/osu.Game.Rulesets.Catch/UI/CatcherTrailDisplay.cs @@ -6,6 +6,7 @@ using JetBrains.Annotations; using osu.Framework.Graphics; using osu.Framework.Graphics.Animations; using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Pooling; using osu.Framework.Graphics.Sprites; using osuTK; using osuTK.Graphics; @@ -20,6 +21,8 @@ namespace osu.Game.Rulesets.Catch.UI { private readonly Catcher catcher; + private readonly DrawablePool trailPool; + private readonly Container dashTrails; private readonly Container hyperDashTrails; private readonly Container endGlowSprites; @@ -80,8 +83,9 @@ namespace osu.Game.Rulesets.Catch.UI RelativeSizeAxes = Axes.Both; - InternalChildren = new[] + InternalChildren = new Drawable[] { + trailPool = new DrawablePool(30), dashTrails = new Container { RelativeSizeAxes = Axes.Both }, hyperDashTrails = new Container { RelativeSizeAxes = Axes.Both, Colour = Catcher.DEFAULT_HYPER_DASH_COLOUR }, endGlowSprites = new Container { RelativeSizeAxes = Axes.Both, Colour = Catcher.DEFAULT_HYPER_DASH_COLOUR }, @@ -118,14 +122,14 @@ namespace osu.Game.Rulesets.Catch.UI { var texture = (catcher.CurrentDrawableCatcher as TextureAnimation)?.CurrentFrame ?? ((Sprite)catcher.CurrentDrawableCatcher).Texture; - var sprite = new CatcherTrailSprite(texture) - { - Anchor = catcher.Anchor, - Scale = catcher.Scale, - Blending = BlendingParameters.Additive, - RelativePositionAxes = catcher.RelativePositionAxes, - Position = catcher.Position - }; + CatcherTrailSprite sprite = trailPool.Get(); + + sprite.Texture = texture; + sprite.Anchor = catcher.Anchor; + sprite.Scale = catcher.Scale; + sprite.Blending = BlendingParameters.Additive; + sprite.RelativePositionAxes = catcher.RelativePositionAxes; + sprite.Position = catcher.Position; target.Add(sprite); diff --git a/osu.Game.Rulesets.Catch/UI/CatcherTrailSprite.cs b/osu.Game.Rulesets.Catch/UI/CatcherTrailSprite.cs index 56cb7dbfda..b3be18d46b 100644 --- a/osu.Game.Rulesets.Catch/UI/CatcherTrailSprite.cs +++ b/osu.Game.Rulesets.Catch/UI/CatcherTrailSprite.cs @@ -1,17 +1,29 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using osu.Framework.Graphics; +using osu.Framework.Graphics.Pooling; using osu.Framework.Graphics.Sprites; using osu.Framework.Graphics.Textures; using osuTK; namespace osu.Game.Rulesets.Catch.UI { - public class CatcherTrailSprite : Sprite + public class CatcherTrailSprite : PoolableDrawable { - public CatcherTrailSprite(Texture texture) + public Texture Texture { - Texture = texture; + set => sprite.Texture = value; + } + + private readonly Sprite sprite; + + public CatcherTrailSprite() + { + InternalChild = sprite = new Sprite + { + RelativeSizeAxes = Axes.Both + }; Size = new Vector2(CatcherArea.CATCHER_SIZE); From 8eb1076fd7e276a74415ff98d9011703dcb6e0f2 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 7 Dec 2020 18:18:14 +0900 Subject: [PATCH 163/184] Add test coverage --- .../Beatmaps/IO/ImportBeatmapTest.cs | 36 +++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/osu.Game.Tests/Beatmaps/IO/ImportBeatmapTest.cs b/osu.Game.Tests/Beatmaps/IO/ImportBeatmapTest.cs index 6e16058360..c32e359de6 100644 --- a/osu.Game.Tests/Beatmaps/IO/ImportBeatmapTest.cs +++ b/osu.Game.Tests/Beatmaps/IO/ImportBeatmapTest.cs @@ -69,6 +69,42 @@ namespace osu.Game.Tests.Beatmaps.IO } } + [Test] + public async Task TestImportThenDeleteFromStream() + { + // unfortunately for the time being we need to reference osu.Framework.Desktop for a game host here. + using (HeadlessGameHost host = new CleanRunHeadlessGameHost(nameof(ImportBeatmapTest))) + { + try + { + var osu = LoadOsuIntoHost(host); + + var tempPath = TestResources.GetTestBeatmapForImport(); + + var manager = osu.Dependencies.Get(); + + BeatmapSetInfo importedSet; + + using (var stream = File.OpenRead(tempPath)) + { + importedSet = await manager.Import(new ImportTask(stream, Path.GetFileName(tempPath))); + ensureLoaded(osu); + } + + Assert.IsTrue(File.Exists(tempPath), "Stream source file somehow went missing"); + File.Delete(tempPath); + + var imported = manager.GetAllUsableBeatmapSets().Find(beatmapSet => beatmapSet.ID == importedSet.ID); + + deleteBeatmapSet(imported, osu); + } + finally + { + host.Exit(); + } + } + } + [Test] public async Task TestImportThenImport() { From fa658747631ab6c4f7176da1a2b5ea1f2cff125a Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 7 Dec 2020 21:09:38 +0900 Subject: [PATCH 164/184] Limit room name to 100 characters --- osu.Game/Screens/Multi/Match/Components/MatchSettingsOverlay.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/osu.Game/Screens/Multi/Match/Components/MatchSettingsOverlay.cs b/osu.Game/Screens/Multi/Match/Components/MatchSettingsOverlay.cs index 668a373d80..b8003b9774 100644 --- a/osu.Game/Screens/Multi/Match/Components/MatchSettingsOverlay.cs +++ b/osu.Game/Screens/Multi/Match/Components/MatchSettingsOverlay.cs @@ -135,6 +135,7 @@ namespace osu.Game.Screens.Multi.Match.Components { RelativeSizeAxes = Axes.X, TabbableContentContainer = this, + LengthLimit = 100 }, }, new Section("Duration") From 5be0672fe91eec0f766f8fd88f1434f41d22b7a3 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 7 Dec 2020 21:54:42 +0900 Subject: [PATCH 165/184] Split out enums --- .../Multi/Lounge/Components/FilterControl.cs | 18 ------------------ .../Lounge/Components/RoomCategoryFilter.cs | 12 ++++++++++++ .../Lounge/Components/RoomStatusFilter.cs | 17 +++++++++++++++++ 3 files changed, 29 insertions(+), 18 deletions(-) create mode 100644 osu.Game/Screens/Multi/Lounge/Components/RoomCategoryFilter.cs create mode 100644 osu.Game/Screens/Multi/Lounge/Components/RoomStatusFilter.cs diff --git a/osu.Game/Screens/Multi/Lounge/Components/FilterControl.cs b/osu.Game/Screens/Multi/Lounge/Components/FilterControl.cs index 3fc1359006..2afadc6536 100644 --- a/osu.Game/Screens/Multi/Lounge/Components/FilterControl.cs +++ b/osu.Game/Screens/Multi/Lounge/Components/FilterControl.cs @@ -1,7 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -using System.ComponentModel; using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Extensions.Color4Extensions; @@ -71,21 +70,4 @@ namespace osu.Game.Screens.Multi.Lounge.Components }; } } - - public enum RoomStatusFilter - { - Open, - - [Description("Recently Ended")] - Ended, - Participated, - Owned, - } - - public enum RoomCategoryFilter - { - Any, - Normal, - Spotlight - } } diff --git a/osu.Game/Screens/Multi/Lounge/Components/RoomCategoryFilter.cs b/osu.Game/Screens/Multi/Lounge/Components/RoomCategoryFilter.cs new file mode 100644 index 0000000000..c076905174 --- /dev/null +++ b/osu.Game/Screens/Multi/Lounge/Components/RoomCategoryFilter.cs @@ -0,0 +1,12 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +namespace osu.Game.Screens.Multi.Lounge.Components +{ + public enum RoomCategoryFilter + { + Any, + Normal, + Spotlight + } +} diff --git a/osu.Game/Screens/Multi/Lounge/Components/RoomStatusFilter.cs b/osu.Game/Screens/Multi/Lounge/Components/RoomStatusFilter.cs new file mode 100644 index 0000000000..9da938ac8b --- /dev/null +++ b/osu.Game/Screens/Multi/Lounge/Components/RoomStatusFilter.cs @@ -0,0 +1,17 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System.ComponentModel; + +namespace osu.Game.Screens.Multi.Lounge.Components +{ + public enum RoomStatusFilter + { + Open, + + [Description("Recently Ended")] + Ended, + Participated, + Owned, + } +} From 1b3836aeef6c531f59035a3ff98d5bf1ad9273aa Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 7 Dec 2020 21:59:26 +0900 Subject: [PATCH 166/184] Re-implement multiplayer FilterControl --- .../Multi/Lounge/Components/FilterControl.cs | 110 ++++++++++++++---- .../Screens/Multi/Lounge/LoungeSubScreen.cs | 8 +- 2 files changed, 89 insertions(+), 29 deletions(-) diff --git a/osu.Game/Screens/Multi/Lounge/Components/FilterControl.cs b/osu.Game/Screens/Multi/Lounge/Components/FilterControl.cs index 2afadc6536..032c50aa73 100644 --- a/osu.Game/Screens/Multi/Lounge/Components/FilterControl.cs +++ b/osu.Game/Screens/Multi/Lounge/Components/FilterControl.cs @@ -3,21 +3,21 @@ using osu.Framework.Allocation; using osu.Framework.Bindables; -using osu.Framework.Extensions.Color4Extensions; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Shapes; using osu.Framework.Threading; -using osu.Game.Overlays.SearchableList; +using osu.Game.Graphics; +using osu.Game.Graphics.UserInterface; using osu.Game.Rulesets; using osuTK.Graphics; namespace osu.Game.Screens.Multi.Lounge.Components { - public class FilterControl : SearchableListFilterControl + public abstract class FilterControl : CompositeDrawable { - protected override Color4 BackgroundColour => Color4.Black.Opacity(0.5f); - protected override RoomStatusFilter DefaultTab => RoomStatusFilter.Open; - protected override RoomCategoryFilter DefaultCategory => RoomCategoryFilter.Any; - - protected override float ContentHorizontalPadding => base.ContentHorizontalPadding + OsuScreen.HORIZONTAL_OVERFLOW_PADDING; + protected const float VERTICAL_PADDING = 10; + protected const float HORIZONTAL_PADDING = 80; [Resolved(CanBeNull = true)] private Bindable filter { get; set; } @@ -25,49 +25,109 @@ namespace osu.Game.Screens.Multi.Lounge.Components [Resolved] private IBindable ruleset { get; set; } + private readonly Box tabStrip; + private readonly SearchTextBox search; + private readonly PageTabControl tabs; + public FilterControl() { - DisplayStyleControl.Hide(); + InternalChildren = new Drawable[] + { + new Box + { + RelativeSizeAxes = Axes.Both, + Colour = Color4.Black, + Alpha = 0.25f, + }, + tabStrip = new Box + { + Anchor = Anchor.BottomLeft, + Origin = Anchor.BottomLeft, + RelativeSizeAxes = Axes.X, + Height = 1, + }, + new Container + { + RelativeSizeAxes = Axes.Both, + Padding = new MarginPadding + { + Top = VERTICAL_PADDING, + Horizontal = HORIZONTAL_PADDING + }, + Children = new Drawable[] + { + search = new FilterSearchTextBox + { + RelativeSizeAxes = Axes.X, + }, + tabs = new PageTabControl + { + Anchor = Anchor.BottomLeft, + Origin = Anchor.BottomLeft, + RelativeSizeAxes = Axes.X, + }, + } + } + }; + + tabs.Current.Value = RoomStatusFilter.Open; + tabs.Current.TriggerChange(); } [BackgroundDependencyLoader] - private void load() + private void load(OsuColour colours) { filter ??= new Bindable(); + tabStrip.Colour = colours.Yellow; } protected override void LoadComplete() { base.LoadComplete(); - ruleset.BindValueChanged(_ => updateFilter()); - Search.Current.BindValueChanged(_ => scheduleUpdateFilter()); - Dropdown.Current.BindValueChanged(_ => updateFilter()); - Tabs.Current.BindValueChanged(_ => updateFilter(), true); + search.Current.BindValueChanged(_ => updateFilterDebounced()); + ruleset.BindValueChanged(_ => UpdateFilter()); + tabs.Current.BindValueChanged(_ => UpdateFilter(), true); } private ScheduledDelegate scheduledFilterUpdate; - private void scheduleUpdateFilter() + private void updateFilterDebounced() { scheduledFilterUpdate?.Cancel(); - scheduledFilterUpdate = Scheduler.AddDelayed(updateFilter, 200); + scheduledFilterUpdate = Scheduler.AddDelayed(UpdateFilter, 200); } - private void updateFilter() + protected void UpdateFilter() { scheduledFilterUpdate?.Cancel(); - if (filter == null) - return; + var criteria = CreateCriteria(); + criteria.SearchString = search.Current.Value; + criteria.Status = tabs.Current.Value; + criteria.Ruleset = ruleset.Value; - filter.Value = new FilterCriteria + filter.Value = criteria; + } + + protected virtual FilterCriteria CreateCriteria() => new FilterCriteria(); + + public bool HoldFocus + { + get => search.HoldFocus; + set => search.HoldFocus = value; + } + + public void TakeFocus() => search.TakeFocus(); + + private class FilterSearchTextBox : SearchTextBox + { + [BackgroundDependencyLoader] + private void load() { - SearchString = Search.Current.Value ?? string.Empty, - StatusFilter = Tabs.Current.Value, - RoomCategoryFilter = Dropdown.Current.Value, - Ruleset = ruleset.Value - }; + BackgroundUnfocused = OsuColour.Gray(0.06f); + BackgroundFocused = OsuColour.Gray(0.12f); + } } } } diff --git a/osu.Game/Screens/Multi/Lounge/LoungeSubScreen.cs b/osu.Game/Screens/Multi/Lounge/LoungeSubScreen.cs index 4dc9ba549b..b33a79772e 100644 --- a/osu.Game/Screens/Multi/Lounge/LoungeSubScreen.cs +++ b/osu.Game/Screens/Multi/Lounge/LoungeSubScreen.cs @@ -112,7 +112,7 @@ namespace osu.Game.Screens.Multi.Lounge protected override void OnFocus(FocusEvent e) { - Filter.Search.TakeFocus(); + Filter.TakeFocus(); } public override void OnEntering(IScreen last) @@ -136,19 +136,19 @@ namespace osu.Game.Screens.Multi.Lounge private void onReturning() { - Filter.Search.HoldFocus = true; + Filter.HoldFocus = true; } public override bool OnExiting(IScreen next) { - Filter.Search.HoldFocus = false; + Filter.HoldFocus = false; return base.OnExiting(next); } public override void OnSuspending(IScreen next) { base.OnSuspending(next); - Filter.Search.HoldFocus = false; + Filter.HoldFocus = false; } private void joinRequested(Room room) From f599427080ed04c6968134a2e78c6239c1d86010 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 7 Dec 2020 21:59:38 +0900 Subject: [PATCH 167/184] Implement TimeshiftFilterControl --- ....cs => TestSceneTimeshiftFilterControl.cs} | 11 ++-- .../Online/Multiplayer/GetRoomsRequest.cs | 18 +++--- .../Multi/Lounge/Components/FilterCriteria.cs | 4 +- .../Lounge/Components/RoomCategoryFilter.cs | 12 ---- .../Components/TimeshiftFilterControl.cs | 59 +++++++++++++++++++ .../Screens/Multi/Lounge/LoungeSubScreen.cs | 6 +- osu.Game/Screens/Multi/RoomManager.cs | 2 +- 7 files changed, 83 insertions(+), 29 deletions(-) rename osu.Game.Tests/Visual/Multiplayer/{TestSceneLoungeFilterControl.cs => TestSceneTimeshiftFilterControl.cs} (55%) delete mode 100644 osu.Game/Screens/Multi/Lounge/Components/RoomCategoryFilter.cs create mode 100644 osu.Game/Screens/Multi/Lounge/Components/TimeshiftFilterControl.cs diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneLoungeFilterControl.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneTimeshiftFilterControl.cs similarity index 55% rename from osu.Game.Tests/Visual/Multiplayer/TestSceneLoungeFilterControl.cs rename to osu.Game.Tests/Visual/Multiplayer/TestSceneTimeshiftFilterControl.cs index 7c0c2797f5..f635a28b5c 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneLoungeFilterControl.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneTimeshiftFilterControl.cs @@ -6,14 +6,17 @@ using osu.Game.Screens.Multi.Lounge.Components; namespace osu.Game.Tests.Visual.Multiplayer { - public class TestSceneLoungeFilterControl : OsuTestScene + public class TestSceneTimeshiftFilterControl : OsuTestScene { - public TestSceneLoungeFilterControl() + public TestSceneTimeshiftFilterControl() { - Child = new FilterControl + Child = new TimeshiftFilterControl { Anchor = Anchor.Centre, - Origin = Anchor.Centre + Origin = Anchor.Centre, + RelativeSizeAxes = Axes.X, + Width = 0.7f, + Height = 80, }; } } diff --git a/osu.Game/Online/Multiplayer/GetRoomsRequest.cs b/osu.Game/Online/Multiplayer/GetRoomsRequest.cs index 64e0386f77..a0609f77dd 100644 --- a/osu.Game/Online/Multiplayer/GetRoomsRequest.cs +++ b/osu.Game/Online/Multiplayer/GetRoomsRequest.cs @@ -11,24 +11,24 @@ namespace osu.Game.Online.Multiplayer { public class GetRoomsRequest : APIRequest> { - private readonly RoomStatusFilter statusFilter; - private readonly RoomCategoryFilter categoryFilter; + private readonly RoomStatusFilter status; + private readonly string category; - public GetRoomsRequest(RoomStatusFilter statusFilter, RoomCategoryFilter categoryFilter) + public GetRoomsRequest(RoomStatusFilter status, string category) { - this.statusFilter = statusFilter; - this.categoryFilter = categoryFilter; + this.status = status; + this.category = category; } protected override WebRequest CreateWebRequest() { var req = base.CreateWebRequest(); - if (statusFilter != RoomStatusFilter.Open) - req.AddParameter("mode", statusFilter.ToString().Underscore().ToLowerInvariant()); + if (status != RoomStatusFilter.Open) + req.AddParameter("mode", status.ToString().Underscore().ToLowerInvariant()); - if (categoryFilter != RoomCategoryFilter.Any) - req.AddParameter("category", categoryFilter.ToString().Underscore().ToLowerInvariant()); + if (!string.IsNullOrEmpty(category)) + req.AddParameter("category", category); return req; } diff --git a/osu.Game/Screens/Multi/Lounge/Components/FilterCriteria.cs b/osu.Game/Screens/Multi/Lounge/Components/FilterCriteria.cs index 6d70225eec..7b04be86b1 100644 --- a/osu.Game/Screens/Multi/Lounge/Components/FilterCriteria.cs +++ b/osu.Game/Screens/Multi/Lounge/Components/FilterCriteria.cs @@ -8,8 +8,8 @@ namespace osu.Game.Screens.Multi.Lounge.Components public class FilterCriteria { public string SearchString; - public RoomStatusFilter StatusFilter; - public RoomCategoryFilter RoomCategoryFilter; + public RoomStatusFilter Status; + public string Category; public RulesetInfo Ruleset; } } diff --git a/osu.Game/Screens/Multi/Lounge/Components/RoomCategoryFilter.cs b/osu.Game/Screens/Multi/Lounge/Components/RoomCategoryFilter.cs deleted file mode 100644 index c076905174..0000000000 --- a/osu.Game/Screens/Multi/Lounge/Components/RoomCategoryFilter.cs +++ /dev/null @@ -1,12 +0,0 @@ -// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. -// See the LICENCE file in the repository root for full licence text. - -namespace osu.Game.Screens.Multi.Lounge.Components -{ - public enum RoomCategoryFilter - { - Any, - Normal, - Spotlight - } -} diff --git a/osu.Game/Screens/Multi/Lounge/Components/TimeshiftFilterControl.cs b/osu.Game/Screens/Multi/Lounge/Components/TimeshiftFilterControl.cs new file mode 100644 index 0000000000..a2ea104c74 --- /dev/null +++ b/osu.Game/Screens/Multi/Lounge/Components/TimeshiftFilterControl.cs @@ -0,0 +1,59 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using osu.Framework.Graphics; +using osu.Framework.Graphics.UserInterface; +using osu.Game.Overlays.SearchableList; + +namespace osu.Game.Screens.Multi.Lounge.Components +{ + public class TimeshiftFilterControl : FilterControl + { + private readonly Dropdown dropdown; + + public TimeshiftFilterControl() + { + AddInternal(dropdown = new SlimEnumDropdown + { + Anchor = Anchor.BottomRight, + Origin = Anchor.TopRight, + RelativeSizeAxes = Axes.None, + Width = 160, + X = -HORIZONTAL_PADDING, + Y = -30 + }); + } + + protected override void LoadComplete() + { + base.LoadComplete(); + + dropdown.Current.BindValueChanged(_ => UpdateFilter()); + } + + protected override FilterCriteria CreateCriteria() + { + var criteria = base.CreateCriteria(); + + switch (dropdown.Current.Value) + { + case TimeshiftCategory.Normal: + criteria.Category = "normal"; + break; + + case TimeshiftCategory.Spotlight: + criteria.Category = "spotlight"; + break; + } + + return criteria; + } + + private enum TimeshiftCategory + { + Any, + Normal, + Spotlight + } + } +} diff --git a/osu.Game/Screens/Multi/Lounge/LoungeSubScreen.cs b/osu.Game/Screens/Multi/Lounge/LoungeSubScreen.cs index b33a79772e..a26a64d86d 100644 --- a/osu.Game/Screens/Multi/Lounge/LoungeSubScreen.cs +++ b/osu.Game/Screens/Multi/Lounge/LoungeSubScreen.cs @@ -48,7 +48,6 @@ namespace osu.Game.Screens.Multi.Lounge InternalChildren = new Drawable[] { - Filter = new FilterControl { Depth = -1 }, content = new Container { RelativeSizeAxes = Axes.Both, @@ -79,6 +78,11 @@ namespace osu.Game.Screens.Multi.Lounge }, }, }, + Filter = new TimeshiftFilterControl + { + RelativeSizeAxes = Axes.X, + Height = 80, + }, }; // scroll selected room into view on selection. diff --git a/osu.Game/Screens/Multi/RoomManager.cs b/osu.Game/Screens/Multi/RoomManager.cs index 2a96fa536d..fb0cf73bb9 100644 --- a/osu.Game/Screens/Multi/RoomManager.cs +++ b/osu.Game/Screens/Multi/RoomManager.cs @@ -317,7 +317,7 @@ namespace osu.Game.Screens.Multi var tcs = new TaskCompletionSource(); pollReq?.Cancel(); - pollReq = new GetRoomsRequest(currentFilter.Value.StatusFilter, currentFilter.Value.RoomCategoryFilter); + pollReq = new GetRoomsRequest(currentFilter.Value.Status, currentFilter.Value.Category); pollReq.Success += result => { From 34f36727509e6b108564c06714f2252505a5bf3a Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 7 Dec 2020 22:04:41 +0900 Subject: [PATCH 168/184] Make ctor protected --- osu.Game/Screens/Multi/Lounge/Components/FilterControl.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Screens/Multi/Lounge/Components/FilterControl.cs b/osu.Game/Screens/Multi/Lounge/Components/FilterControl.cs index 032c50aa73..896c215c42 100644 --- a/osu.Game/Screens/Multi/Lounge/Components/FilterControl.cs +++ b/osu.Game/Screens/Multi/Lounge/Components/FilterControl.cs @@ -29,7 +29,7 @@ namespace osu.Game.Screens.Multi.Lounge.Components private readonly SearchTextBox search; private readonly PageTabControl tabs; - public FilterControl() + protected FilterControl() { InternalChildren = new Drawable[] { From 10c1823534cd9e873997965f81fbb72e5dc1b6fa Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 7 Dec 2020 22:07:11 +0900 Subject: [PATCH 169/184] Remove now unused files --- .../UserInterface}/SlimEnumDropdown.cs | 5 +- .../SearchableList/DisplayStyleControl.cs | 84 --------- .../SearchableList/HeaderTabControl.cs | 29 --- .../SearchableListFilterControl.cs | 165 ------------------ .../Components/TimeshiftFilterControl.cs | 2 +- 5 files changed, 3 insertions(+), 282 deletions(-) rename osu.Game/{Overlays/SearchableList => Graphics/UserInterface}/SlimEnumDropdown.cs (94%) delete mode 100644 osu.Game/Overlays/SearchableList/DisplayStyleControl.cs delete mode 100644 osu.Game/Overlays/SearchableList/HeaderTabControl.cs delete mode 100644 osu.Game/Overlays/SearchableList/SearchableListFilterControl.cs diff --git a/osu.Game/Overlays/SearchableList/SlimEnumDropdown.cs b/osu.Game/Graphics/UserInterface/SlimEnumDropdown.cs similarity index 94% rename from osu.Game/Overlays/SearchableList/SlimEnumDropdown.cs rename to osu.Game/Graphics/UserInterface/SlimEnumDropdown.cs index 9e7ff1205f..965734792c 100644 --- a/osu.Game/Overlays/SearchableList/SlimEnumDropdown.cs +++ b/osu.Game/Graphics/UserInterface/SlimEnumDropdown.cs @@ -2,14 +2,13 @@ // See the LICENCE file in the repository root for full licence text. using System; -using osuTK.Graphics; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.UserInterface; -using osu.Game.Graphics.UserInterface; using osuTK; +using osuTK.Graphics; -namespace osu.Game.Overlays.SearchableList +namespace osu.Game.Graphics.UserInterface { public class SlimEnumDropdown : OsuEnumDropdown where T : struct, Enum diff --git a/osu.Game/Overlays/SearchableList/DisplayStyleControl.cs b/osu.Game/Overlays/SearchableList/DisplayStyleControl.cs deleted file mode 100644 index ffbc1c9586..0000000000 --- a/osu.Game/Overlays/SearchableList/DisplayStyleControl.cs +++ /dev/null @@ -1,84 +0,0 @@ -// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. -// See the LICENCE file in the repository root for full licence text. - -using osu.Framework.Bindables; -using osuTK; -using osu.Framework.Graphics; -using osu.Framework.Graphics.Containers; -using osu.Framework.Graphics.Sprites; -using osu.Game.Graphics.Containers; - -namespace osu.Game.Overlays.SearchableList -{ - public class DisplayStyleControl : CompositeDrawable - { - public readonly Bindable DisplayStyle = new Bindable(); - - public DisplayStyleControl() - { - AutoSizeAxes = Axes.Both; - - InternalChild = new FillFlowContainer - { - AutoSizeAxes = Axes.Both, - Spacing = new Vector2(5f, 0f), - Direction = FillDirection.Horizontal, - Children = new[] - { - new DisplayStyleToggleButton(FontAwesome.Solid.ThLarge, PanelDisplayStyle.Grid, DisplayStyle), - new DisplayStyleToggleButton(FontAwesome.Solid.ListUl, PanelDisplayStyle.List, DisplayStyle), - }, - }; - - DisplayStyle.Value = PanelDisplayStyle.Grid; - } - - private class DisplayStyleToggleButton : OsuClickableContainer - { - private readonly SpriteIcon icon; - private readonly PanelDisplayStyle style; - private readonly Bindable bindable; - - public DisplayStyleToggleButton(IconUsage icon, PanelDisplayStyle style, Bindable bindable) - { - this.bindable = bindable; - this.style = style; - Size = new Vector2(25f); - - Children = new Drawable[] - { - this.icon = new SpriteIcon - { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - Icon = icon, - Size = new Vector2(18), - Alpha = 0.5f, - }, - }; - - bindable.ValueChanged += Bindable_ValueChanged; - Bindable_ValueChanged(new ValueChangedEvent(bindable.Value, bindable.Value)); - Action = () => bindable.Value = this.style; - } - - private void Bindable_ValueChanged(ValueChangedEvent e) - { - icon.FadeTo(e.NewValue == style ? 1.0f : 0.5f, 100); - } - - protected override void Dispose(bool isDisposing) - { - base.Dispose(isDisposing); - - bindable.ValueChanged -= Bindable_ValueChanged; - } - } - } - - public enum PanelDisplayStyle - { - Grid, - List, - } -} diff --git a/osu.Game/Overlays/SearchableList/HeaderTabControl.cs b/osu.Game/Overlays/SearchableList/HeaderTabControl.cs deleted file mode 100644 index 2087a72c54..0000000000 --- a/osu.Game/Overlays/SearchableList/HeaderTabControl.cs +++ /dev/null @@ -1,29 +0,0 @@ -// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. -// See the LICENCE file in the repository root for full licence text. - -using osuTK.Graphics; -using osu.Framework.Graphics.UserInterface; -using osu.Game.Graphics.UserInterface; - -namespace osu.Game.Overlays.SearchableList -{ - public class HeaderTabControl : OsuTabControl - { - protected override TabItem CreateTabItem(T value) => new HeaderTabItem(value); - - public HeaderTabControl() - { - Height = 26; - AccentColour = Color4.White; - } - - private class HeaderTabItem : OsuTabItem - { - public HeaderTabItem(T value) - : base(value) - { - Text.Font = Text.Font.With(size: 16); - } - } - } -} diff --git a/osu.Game/Overlays/SearchableList/SearchableListFilterControl.cs b/osu.Game/Overlays/SearchableList/SearchableListFilterControl.cs deleted file mode 100644 index 1990674aa9..0000000000 --- a/osu.Game/Overlays/SearchableList/SearchableListFilterControl.cs +++ /dev/null @@ -1,165 +0,0 @@ -// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. -// See the LICENCE file in the repository root for full licence text. - -using System; -using osuTK.Graphics; -using osu.Framework.Allocation; -using osu.Framework.Extensions.Color4Extensions; -using osu.Framework.Graphics; -using osu.Framework.Graphics.Containers; -using osu.Game.Graphics; -using osu.Game.Graphics.UserInterface; -using osu.Framework.Graphics.Shapes; - -namespace osu.Game.Overlays.SearchableList -{ - public abstract class SearchableListFilterControl : Container - where TTab : struct, Enum - where TCategory : struct, Enum - { - private const float padding = 10; - - private readonly Drawable filterContainer; - private readonly Drawable rightFilterContainer; - private readonly Box tabStrip; - - public readonly SearchTextBox Search; - public readonly PageTabControl Tabs; - public readonly SlimEnumDropdown Dropdown; - public readonly DisplayStyleControl DisplayStyleControl; - - protected abstract Color4 BackgroundColour { get; } - protected abstract TTab DefaultTab { get; } - protected abstract TCategory DefaultCategory { get; } - protected virtual Drawable CreateSupplementaryControls() => null; - - /// - /// The amount of padding added to content (does not affect background or tab control strip). - /// - protected virtual float ContentHorizontalPadding => WaveOverlayContainer.WIDTH_PADDING; - - protected SearchableListFilterControl() - { - RelativeSizeAxes = Axes.X; - - var controls = CreateSupplementaryControls(); - Container controlsContainer; - Children = new[] - { - filterContainer = new Container - { - RelativeSizeAxes = Axes.X, - AutoSizeAxes = Axes.Y, - Children = new Drawable[] - { - new Box - { - RelativeSizeAxes = Axes.Both, - Colour = BackgroundColour, - Alpha = 0.9f, - }, - tabStrip = new Box - { - Anchor = Anchor.BottomLeft, - Origin = Anchor.BottomLeft, - RelativeSizeAxes = Axes.X, - Height = 1, - }, - new FillFlowContainer - { - RelativeSizeAxes = Axes.X, - AutoSizeAxes = Axes.Y, - Padding = new MarginPadding - { - Top = padding, - Horizontal = ContentHorizontalPadding - }, - Children = new Drawable[] - { - Search = new FilterSearchTextBox - { - RelativeSizeAxes = Axes.X, - }, - controlsContainer = new Container - { - RelativeSizeAxes = Axes.X, - AutoSizeAxes = Axes.Y, - Margin = new MarginPadding { Top = controls != null ? padding : 0 }, - }, - new Container - { - RelativeSizeAxes = Axes.X, - AutoSizeAxes = Axes.Y, - Padding = new MarginPadding { Right = 225 }, - Child = Tabs = new PageTabControl - { - RelativeSizeAxes = Axes.X, - }, - }, - new Box // keep the tab strip part of autosize, but don't put it in the flow container - { - RelativeSizeAxes = Axes.X, - Height = 1, - Colour = Color4.White.Opacity(0), - }, - }, - }, - }, - }, - rightFilterContainer = new FillFlowContainer - { - Anchor = Anchor.TopRight, - Origin = Anchor.TopRight, - AutoSizeAxes = Axes.Both, - Children = new Drawable[] - { - Dropdown = new SlimEnumDropdown - { - Anchor = Anchor.TopRight, - Origin = Anchor.TopRight, - RelativeSizeAxes = Axes.None, - Width = 160f, - }, - DisplayStyleControl = new DisplayStyleControl - { - Anchor = Anchor.TopRight, - Origin = Anchor.TopRight, - }, - } - } - }; - - if (controls != null) controlsContainer.Children = new[] { controls }; - - Tabs.Current.Value = DefaultTab; - Tabs.Current.TriggerChange(); - - Dropdown.Current.Value = DefaultCategory; - Dropdown.Current.TriggerChange(); - } - - [BackgroundDependencyLoader] - private void load(OsuColour colours) - { - tabStrip.Colour = colours.Yellow; - } - - protected override void Update() - { - base.Update(); - - Height = filterContainer.Height; - rightFilterContainer.Margin = new MarginPadding { Top = filterContainer.Height - 30, Right = ContentHorizontalPadding }; - } - - private class FilterSearchTextBox : SearchTextBox - { - [BackgroundDependencyLoader] - private void load() - { - BackgroundUnfocused = OsuColour.Gray(0.06f); - BackgroundFocused = OsuColour.Gray(0.12f); - } - } - } -} diff --git a/osu.Game/Screens/Multi/Lounge/Components/TimeshiftFilterControl.cs b/osu.Game/Screens/Multi/Lounge/Components/TimeshiftFilterControl.cs index a2ea104c74..68cab283a0 100644 --- a/osu.Game/Screens/Multi/Lounge/Components/TimeshiftFilterControl.cs +++ b/osu.Game/Screens/Multi/Lounge/Components/TimeshiftFilterControl.cs @@ -3,7 +3,7 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.UserInterface; -using osu.Game.Overlays.SearchableList; +using osu.Game.Graphics.UserInterface; namespace osu.Game.Screens.Multi.Lounge.Components { From 3cbdaf5960a992e21b4fff30ad8660987edf005a Mon Sep 17 00:00:00 2001 From: ekrctb Date: Tue, 8 Dec 2020 10:30:23 +0900 Subject: [PATCH 170/184] Make resolved properties protected --- .../Skinning/Default/CatchHitObjectPiece.cs | 12 ++++++------ .../Skinning/Default/FruitPiece.cs | 7 +++---- .../Skinning/LegacyCatchHitObjectPiece.cs | 16 +++++++--------- 3 files changed, 16 insertions(+), 19 deletions(-) diff --git a/osu.Game.Rulesets.Catch/Skinning/Default/CatchHitObjectPiece.cs b/osu.Game.Rulesets.Catch/Skinning/Default/CatchHitObjectPiece.cs index 3c3cb5b0ee..be6cf0fc05 100644 --- a/osu.Game.Rulesets.Catch/Skinning/Default/CatchHitObjectPiece.cs +++ b/osu.Game.Rulesets.Catch/Skinning/Default/CatchHitObjectPiece.cs @@ -18,10 +18,8 @@ namespace osu.Game.Rulesets.Catch.Skinning.Default public readonly Bindable HyperDash = new Bindable(); [Resolved(canBeNull: true)] - private DrawableHitObject drawableHitObject { get; set; } - [CanBeNull] - protected DrawablePalpableCatchHitObject DrawableHitObject => (DrawablePalpableCatchHitObject)drawableHitObject; + protected DrawableHitObject DrawableHitObject { get; private set; } [CanBeNull] protected BorderPiece BorderPiece; @@ -33,10 +31,12 @@ namespace osu.Game.Rulesets.Catch.Skinning.Default { base.LoadComplete(); - if (DrawableHitObject != null) + var hitObject = (DrawablePalpableCatchHitObject)DrawableHitObject; + + if (hitObject != null) { - AccentColour.BindTo(DrawableHitObject.AccentColour); - HyperDash.BindTo(DrawableHitObject.HyperDash); + AccentColour.BindTo(hitObject.AccentColour); + HyperDash.BindTo(hitObject.HyperDash); } HyperDash.BindValueChanged(hyper => diff --git a/osu.Game.Rulesets.Catch/Skinning/Default/FruitPiece.cs b/osu.Game.Rulesets.Catch/Skinning/Default/FruitPiece.cs index 05b924eb75..45d688c4e5 100644 --- a/osu.Game.Rulesets.Catch/Skinning/Default/FruitPiece.cs +++ b/osu.Game.Rulesets.Catch/Skinning/Default/FruitPiece.cs @@ -36,11 +36,10 @@ namespace osu.Game.Rulesets.Catch.Skinning.Default { base.LoadComplete(); - if (DrawableHitObject != null) - { - var fruit = (DrawableFruit)DrawableHitObject; + var fruit = (DrawableFruit)DrawableHitObject; + + if (fruit != null) VisualRepresentation.BindTo(fruit.VisualRepresentation); - } } } } diff --git a/osu.Game.Rulesets.Catch/Skinning/LegacyCatchHitObjectPiece.cs b/osu.Game.Rulesets.Catch/Skinning/LegacyCatchHitObjectPiece.cs index 4bcb92b9be..1e68439402 100644 --- a/osu.Game.Rulesets.Catch/Skinning/LegacyCatchHitObjectPiece.cs +++ b/osu.Game.Rulesets.Catch/Skinning/LegacyCatchHitObjectPiece.cs @@ -27,15 +27,11 @@ namespace osu.Game.Rulesets.Catch.Skinning private readonly Sprite hyperSprite; [Resolved] - private ISkinSource skin { get; set; } - - protected ISkinSource Skin => skin; + protected ISkinSource Skin { get; private set; } [Resolved(canBeNull: true)] - private DrawableHitObject drawableHitObject { get; set; } - [CanBeNull] - protected DrawablePalpableCatchHitObject DrawableHitObject => (DrawablePalpableCatchHitObject)drawableHitObject; + protected DrawableHitObject DrawableHitObject { get; private set; } protected LegacyCatchHitObjectPiece() { @@ -69,10 +65,12 @@ namespace osu.Game.Rulesets.Catch.Skinning { base.LoadComplete(); - if (DrawableHitObject != null) + var hitObject = (DrawablePalpableCatchHitObject)DrawableHitObject; + + if (hitObject != null) { - AccentColour.BindTo(DrawableHitObject.AccentColour); - HyperDash.BindTo(DrawableHitObject.HyperDash); + AccentColour.BindTo(hitObject.AccentColour); + HyperDash.BindTo(hitObject.HyperDash); } hyperSprite.Colour = Skin.GetConfig(CatchSkinColour.HyperDashFruit)?.Value ?? From 4da6717d0e3ececba5dc73a36326a1bb92e4ea26 Mon Sep 17 00:00:00 2001 From: ekrctb Date: Tue, 8 Dec 2020 10:32:46 +0900 Subject: [PATCH 171/184] Rename things in PulpFormation --- .../Skinning/Default/BananaPulpFormation.cs | 4 +-- .../Skinning/Default/FruitPulpFormation.cs | 36 +++++++++---------- .../Skinning/Default/PulpFormation.cs | 15 ++++---- 3 files changed, 28 insertions(+), 27 deletions(-) diff --git a/osu.Game.Rulesets.Catch/Skinning/Default/BananaPulpFormation.cs b/osu.Game.Rulesets.Catch/Skinning/Default/BananaPulpFormation.cs index cabea46083..ee1cc68f7d 100644 --- a/osu.Game.Rulesets.Catch/Skinning/Default/BananaPulpFormation.cs +++ b/osu.Game.Rulesets.Catch/Skinning/Default/BananaPulpFormation.cs @@ -9,8 +9,8 @@ namespace osu.Game.Rulesets.Catch.Skinning.Default { public BananaPulpFormation() { - Add(new Vector2(0, -0.3f), new Vector2(SMALL_PULP)); - Add(new Vector2(0, 0.05f), new Vector2(LARGE_PULP_4 * 0.8f, LARGE_PULP_4 * 2.5f)); + AddPulp(new Vector2(0, -0.3f), new Vector2(SMALL_PULP)); + AddPulp(new Vector2(0, 0.05f), new Vector2(LARGE_PULP_4 * 0.8f, LARGE_PULP_4 * 2.5f)); } } } diff --git a/osu.Game.Rulesets.Catch/Skinning/Default/FruitPulpFormation.cs b/osu.Game.Rulesets.Catch/Skinning/Default/FruitPulpFormation.cs index 8696854f23..88e0b5133a 100644 --- a/osu.Game.Rulesets.Catch/Skinning/Default/FruitPulpFormation.cs +++ b/osu.Game.Rulesets.Catch/Skinning/Default/FruitPulpFormation.cs @@ -25,33 +25,33 @@ namespace osu.Game.Rulesets.Catch.Skinning.Default switch (visualRepresentation.NewValue) { case FruitVisualRepresentation.Pear: - Add(new Vector2(0, -0.33f), new Vector2(SMALL_PULP)); - Add(PositionAt(60, DISTANCE_FROM_CENTRE_3), new Vector2(LARGE_PULP_3)); - Add(PositionAt(180, DISTANCE_FROM_CENTRE_3), new Vector2(LARGE_PULP_3)); - Add(PositionAt(300, DISTANCE_FROM_CENTRE_3), new Vector2(LARGE_PULP_3)); + AddPulp(new Vector2(0, -0.33f), new Vector2(SMALL_PULP)); + AddPulp(PositionAt(60, DISTANCE_FROM_CENTRE_3), new Vector2(LARGE_PULP_3)); + AddPulp(PositionAt(180, DISTANCE_FROM_CENTRE_3), new Vector2(LARGE_PULP_3)); + AddPulp(PositionAt(300, DISTANCE_FROM_CENTRE_3), new Vector2(LARGE_PULP_3)); break; case FruitVisualRepresentation.Grape: - Add(new Vector2(0, -0.25f), new Vector2(SMALL_PULP)); - Add(PositionAt(0, DISTANCE_FROM_CENTRE_3), new Vector2(LARGE_PULP_3)); - Add(PositionAt(120, DISTANCE_FROM_CENTRE_3), new Vector2(LARGE_PULP_3)); - Add(PositionAt(240, DISTANCE_FROM_CENTRE_3), new Vector2(LARGE_PULP_3)); + AddPulp(new Vector2(0, -0.25f), new Vector2(SMALL_PULP)); + AddPulp(PositionAt(0, DISTANCE_FROM_CENTRE_3), new Vector2(LARGE_PULP_3)); + AddPulp(PositionAt(120, DISTANCE_FROM_CENTRE_3), new Vector2(LARGE_PULP_3)); + AddPulp(PositionAt(240, DISTANCE_FROM_CENTRE_3), new Vector2(LARGE_PULP_3)); break; case FruitVisualRepresentation.Pineapple: - Add(new Vector2(0, -0.3f), new Vector2(SMALL_PULP)); - Add(PositionAt(45, DISTANCE_FROM_CENTRE_4), new Vector2(LARGE_PULP_4)); - Add(PositionAt(135, DISTANCE_FROM_CENTRE_4), new Vector2(LARGE_PULP_4)); - Add(PositionAt(225, DISTANCE_FROM_CENTRE_4), new Vector2(LARGE_PULP_4)); - Add(PositionAt(315, DISTANCE_FROM_CENTRE_4), new Vector2(LARGE_PULP_4)); + AddPulp(new Vector2(0, -0.3f), new Vector2(SMALL_PULP)); + AddPulp(PositionAt(45, DISTANCE_FROM_CENTRE_4), new Vector2(LARGE_PULP_4)); + AddPulp(PositionAt(135, DISTANCE_FROM_CENTRE_4), new Vector2(LARGE_PULP_4)); + AddPulp(PositionAt(225, DISTANCE_FROM_CENTRE_4), new Vector2(LARGE_PULP_4)); + AddPulp(PositionAt(315, DISTANCE_FROM_CENTRE_4), new Vector2(LARGE_PULP_4)); break; case FruitVisualRepresentation.Raspberry: - Add(new Vector2(0, -0.34f), new Vector2(SMALL_PULP)); - Add(PositionAt(0, DISTANCE_FROM_CENTRE_4), new Vector2(LARGE_PULP_4)); - Add(PositionAt(90, DISTANCE_FROM_CENTRE_4), new Vector2(LARGE_PULP_4)); - Add(PositionAt(180, DISTANCE_FROM_CENTRE_4), new Vector2(LARGE_PULP_4)); - Add(PositionAt(270, DISTANCE_FROM_CENTRE_4), new Vector2(LARGE_PULP_4)); + AddPulp(new Vector2(0, -0.34f), new Vector2(SMALL_PULP)); + AddPulp(PositionAt(0, DISTANCE_FROM_CENTRE_4), new Vector2(LARGE_PULP_4)); + AddPulp(PositionAt(90, DISTANCE_FROM_CENTRE_4), new Vector2(LARGE_PULP_4)); + AddPulp(PositionAt(180, DISTANCE_FROM_CENTRE_4), new Vector2(LARGE_PULP_4)); + AddPulp(PositionAt(270, DISTANCE_FROM_CENTRE_4), new Vector2(LARGE_PULP_4)); break; } } diff --git a/osu.Game.Rulesets.Catch/Skinning/Default/PulpFormation.cs b/osu.Game.Rulesets.Catch/Skinning/Default/PulpFormation.cs index c0e3d0e724..8753aa4077 100644 --- a/osu.Game.Rulesets.Catch/Skinning/Default/PulpFormation.cs +++ b/osu.Game.Rulesets.Catch/Skinning/Default/PulpFormation.cs @@ -22,7 +22,7 @@ namespace osu.Game.Rulesets.Catch.Skinning.Default protected const float SMALL_PULP = LARGE_PULP_3 / 2; - private int numPulps; + private int pulpsInUse; protected PulpFormation() { @@ -35,21 +35,22 @@ namespace osu.Game.Rulesets.Catch.Skinning.Default protected void Clear() { - for (; numPulps > 0; numPulps--) - InternalChildren[numPulps - 1].Alpha = 0; + for (int i = 0; i < pulpsInUse; i++) + InternalChildren[i].Alpha = 0; + pulpsInUse = 0; } - protected void Add(Vector2 position, Vector2 size) + protected void AddPulp(Vector2 position, Vector2 size) { - if (numPulps == InternalChildren.Count) + if (pulpsInUse == InternalChildren.Count) AddInternal(new Pulp { AccentColour = { BindTarget = AccentColour } }); - var pulp = InternalChildren[numPulps]; + var pulp = InternalChildren[pulpsInUse]; pulp.Position = position; pulp.Size = size; pulp.Alpha = 1; - numPulps++; + pulpsInUse++; } } } From 57b7ef88e2f85e7e9e5073a7ece9acc043b7c246 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 8 Dec 2020 12:12:53 +0900 Subject: [PATCH 172/184] Fix spacing --- osu.Game.Rulesets.Osu/Difficulty/OsuPerformanceCalculator.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Difficulty/OsuPerformanceCalculator.cs b/osu.Game.Rulesets.Osu/Difficulty/OsuPerformanceCalculator.cs index 3f0b0dcc71..0ebe0ddc2d 100644 --- a/osu.Game.Rulesets.Osu/Difficulty/OsuPerformanceCalculator.cs +++ b/osu.Game.Rulesets.Osu/Difficulty/OsuPerformanceCalculator.cs @@ -101,9 +101,9 @@ namespace osu.Game.Rulesets.Osu.Difficulty double approachRateFactor = 0.0; if (Attributes.ApproachRate > 10.33) - approachRateFactor += 0.4 * (Attributes.ApproachRate - 10.33); + approachRateFactor += 0.4 * (Attributes.ApproachRate - 10.33); else if (Attributes.ApproachRate < 8.0) - approachRateFactor += 0.1 * (8.0 - Attributes.ApproachRate); + approachRateFactor += 0.1 * (8.0 - Attributes.ApproachRate); aimValue *= 1.0 + Math.Min(approachRateFactor, approachRateFactor * (totalHits / 1000.0)); From 77279a7e56154ae3796444403b561e4023a3183c Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 8 Dec 2020 12:48:59 +0900 Subject: [PATCH 173/184] Update stale xmldoc on import method MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Bartłomiej Dach --- osu.Game/Database/ArchiveModelManager.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Database/ArchiveModelManager.cs b/osu.Game/Database/ArchiveModelManager.cs index e18dc7f7eb..36cc4cce39 100644 --- a/osu.Game/Database/ArchiveModelManager.cs +++ b/osu.Game/Database/ArchiveModelManager.cs @@ -192,7 +192,7 @@ namespace osu.Game.Database /// Import one from the filesystem and delete the file on success. /// Note that this bypasses the UI flow and should only be used for special cases or testing. /// - /// The archive location on disk. + /// The containing data about the to import. /// An optional cancellation token. /// The imported model, if successful. internal async Task Import(ImportTask task, CancellationToken cancellationToken = default) From 58d7e4197809c986c62389e52b90e3465bf8b225 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 8 Dec 2020 12:52:34 +0900 Subject: [PATCH 174/184] Enable nullable on ImportTask --- osu.Game/Database/ImportTask.cs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/osu.Game/Database/ImportTask.cs b/osu.Game/Database/ImportTask.cs index 89eb347df0..1433a567a9 100644 --- a/osu.Game/Database/ImportTask.cs +++ b/osu.Game/Database/ImportTask.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable enable + using System.IO; using osu.Game.IO.Archives; using osu.Game.Utils; @@ -21,7 +23,7 @@ namespace osu.Game.Database /// /// An optional stream which provides the file content. /// - public Stream Stream { get; } + public Stream? Stream { get; } /// /// Construct a new import task from a path (on a local filesystem). From 0213f77b4b4c43e09c5c5e7e4229f0dd4af500f5 Mon Sep 17 00:00:00 2001 From: ekrctb Date: Tue, 8 Dec 2020 14:28:30 +0900 Subject: [PATCH 175/184] Move catcher state changing logic to OnNewResult method --- .../TestSceneCatcher.cs | 31 +++++++++++++- .../TestSceneCatcherArea.cs | 3 +- osu.Game.Rulesets.Catch/UI/CatchPlayfield.cs | 2 +- osu.Game.Rulesets.Catch/UI/Catcher.cs | 41 +++++++++++-------- osu.Game.Rulesets.Catch/UI/CatcherArea.cs | 11 +++-- 5 files changed, 60 insertions(+), 28 deletions(-) diff --git a/osu.Game.Rulesets.Catch.Tests/TestSceneCatcher.cs b/osu.Game.Rulesets.Catch.Tests/TestSceneCatcher.cs index 194a12a9b7..d97c56164e 100644 --- a/osu.Game.Rulesets.Catch.Tests/TestSceneCatcher.cs +++ b/osu.Game.Rulesets.Catch.Tests/TestSceneCatcher.cs @@ -1,6 +1,7 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System; using System.Collections.Generic; using System.Linq; using NUnit.Framework; @@ -12,8 +13,11 @@ using osu.Framework.Testing; using osu.Game.Beatmaps; using osu.Game.Beatmaps.ControlPoints; using osu.Game.Configuration; +using osu.Game.Rulesets.Catch.Judgements; using osu.Game.Rulesets.Catch.Objects; using osu.Game.Rulesets.Catch.Objects.Drawables; +using osu.Game.Rulesets.Judgements; +using osu.Game.Rulesets.Scoring; using osu.Game.Tests.Visual; namespace osu.Game.Rulesets.Catch.Tests @@ -169,7 +173,32 @@ namespace osu.Game.Rulesets.Catch.Tests hitObject.ApplyDefaults(new ControlPointInfo(), new BeatmapDifficulty()); for (var i = 0; i < count; i++) - catcher.AttemptCatch(hitObject); + { + var drawableObject = createDrawableObject(hitObject); + var result = new JudgementResult(hitObject, new CatchJudgement()) + { + Type = catcher.CanCatch(hitObject) ? HitResult.Great : HitResult.Miss + }; + catcher.OnNewResult(drawableObject, result); + } + } + + private DrawableCatchHitObject createDrawableObject(CatchHitObject hitObject) + { + switch (hitObject) + { + case Banana banana: + return new DrawableBanana(banana); + + case Droplet droplet: + return new DrawableDroplet(droplet); + + case Fruit fruit: + return new DrawableFruit(fruit); + + default: + throw new ArgumentOutOfRangeException(nameof(hitObject)); + } } public class TestCatcher : Catcher diff --git a/osu.Game.Rulesets.Catch.Tests/TestSceneCatcherArea.cs b/osu.Game.Rulesets.Catch.Tests/TestSceneCatcherArea.cs index 281ddc7eaa..c8826aa174 100644 --- a/osu.Game.Rulesets.Catch.Tests/TestSceneCatcherArea.cs +++ b/osu.Game.Rulesets.Catch.Tests/TestSceneCatcherArea.cs @@ -58,10 +58,9 @@ namespace osu.Game.Rulesets.Catch.Tests Schedule(() => { - bool caught = area.AttemptCatch(fruit); area.OnNewResult(drawable, new JudgementResult(fruit, new CatchJudgement()) { - Type = caught ? HitResult.Great : HitResult.Miss + Type = area.MovableCatcher.CanCatch(fruit) ? HitResult.Great : HitResult.Miss }); drawable.Expire(); diff --git a/osu.Game.Rulesets.Catch/UI/CatchPlayfield.cs b/osu.Game.Rulesets.Catch/UI/CatchPlayfield.cs index df87359ed6..fdc12bf088 100644 --- a/osu.Game.Rulesets.Catch/UI/CatchPlayfield.cs +++ b/osu.Game.Rulesets.Catch/UI/CatchPlayfield.cs @@ -81,7 +81,7 @@ namespace osu.Game.Rulesets.Catch.UI ((DrawableCatchHitObject)d).CheckPosition = checkIfWeCanCatch; } - private bool checkIfWeCanCatch(CatchHitObject obj) => CatcherArea.AttemptCatch(obj); + private bool checkIfWeCanCatch(CatchHitObject obj) => CatcherArea.MovableCatcher.CanCatch(obj); private void onNewResult(DrawableHitObject judgedObject, JudgementResult result) => CatcherArea.OnNewResult((DrawableCatchHitObject)judgedObject, result); diff --git a/osu.Game.Rulesets.Catch/UI/Catcher.cs b/osu.Game.Rulesets.Catch/UI/Catcher.cs index 2a3447c80a..8998dbf488 100644 --- a/osu.Game.Rulesets.Catch/UI/Catcher.cs +++ b/osu.Game.Rulesets.Catch/UI/Catcher.cs @@ -17,6 +17,7 @@ using osu.Game.Configuration; using osu.Game.Rulesets.Catch.Objects; using osu.Game.Rulesets.Catch.Objects.Drawables; using osu.Game.Rulesets.Catch.Skinning; +using osu.Game.Rulesets.Judgements; using osu.Game.Skinning; using osuTK; using osuTK.Graphics; @@ -190,11 +191,9 @@ namespace osu.Game.Rulesets.Catch.UI internal static float CalculateCatchWidth(BeatmapDifficulty difficulty) => CalculateCatchWidth(calculateScale(difficulty)); /// - /// Let the catcher attempt to catch a fruit. + /// Determine if this catcher can catch a in the current position. /// - /// The fruit to catch. - /// Whether the catch is possible. - public bool AttemptCatch(CatchHitObject hitObject) + public bool CanCatch(CatchHitObject hitObject) { if (!(hitObject is PalpableCatchHitObject fruit)) return false; @@ -205,21 +204,25 @@ namespace osu.Game.Rulesets.Catch.UI var catchObjectPosition = fruit.X; var catcherPosition = Position.X; - var validCatch = - catchObjectPosition >= catcherPosition - halfCatchWidth && - catchObjectPosition <= catcherPosition + halfCatchWidth; + return catchObjectPosition >= catcherPosition - halfCatchWidth && + catchObjectPosition <= catcherPosition + halfCatchWidth; + } - if (validCatch) - placeCaughtObject(fruit); + public void OnNewResult(DrawableCatchHitObject drawableObject, JudgementResult result) + { + if (!(drawableObject.HitObject is PalpableCatchHitObject hitObject)) return; + + if (result.IsHit) + placeCaughtObject(hitObject); // droplet doesn't affect the catcher state - if (fruit is TinyDroplet) return validCatch; + if (hitObject is TinyDroplet) return; - if (validCatch && fruit.HyperDash) + if (result.IsHit && hitObject.HyperDash) { - var target = fruit.HyperDashTarget; - var timeDifference = target.StartTime - fruit.StartTime; - double positionDifference = target.X - catcherPosition; + var target = hitObject.HyperDashTarget; + var timeDifference = target.StartTime - hitObject.StartTime; + double positionDifference = target.X - X; var velocity = positionDifference / Math.Max(1.0, timeDifference - 1000.0 / 60.0); SetHyperDashState(Math.Abs(velocity), target.X); @@ -227,12 +230,14 @@ namespace osu.Game.Rulesets.Catch.UI else SetHyperDashState(); - if (validCatch) - updateState(fruit.Kiai ? CatcherAnimationState.Kiai : CatcherAnimationState.Idle); - else if (!(fruit is Banana)) + if (result.IsHit) + updateState(hitObject.Kiai ? CatcherAnimationState.Kiai : CatcherAnimationState.Idle); + else if (!(hitObject is Banana)) updateState(CatcherAnimationState.Fail); + } - return validCatch; + public void OnRevertResult(DrawableCatchHitObject fruit, JudgementResult result) + { } /// diff --git a/osu.Game.Rulesets.Catch/UI/CatcherArea.cs b/osu.Game.Rulesets.Catch/UI/CatcherArea.cs index 539776354c..857d9141c9 100644 --- a/osu.Game.Rulesets.Catch/UI/CatcherArea.cs +++ b/osu.Game.Rulesets.Catch/UI/CatcherArea.cs @@ -5,7 +5,6 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Game.Beatmaps; using osu.Game.Rulesets.Catch.Judgements; -using osu.Game.Rulesets.Catch.Objects; using osu.Game.Rulesets.Catch.Objects.Drawables; using osu.Game.Rulesets.Catch.Replays; using osu.Game.Rulesets.Judgements; @@ -42,6 +41,8 @@ namespace osu.Game.Rulesets.Catch.UI public void OnNewResult(DrawableCatchHitObject hitObject, JudgementResult result) { + MovableCatcher.OnNewResult(hitObject, result); + if (!result.Type.IsScorable()) return; @@ -56,12 +57,10 @@ namespace osu.Game.Rulesets.Catch.UI comboDisplay.OnNewResult(hitObject, result); } - public void OnRevertResult(DrawableCatchHitObject fruit, JudgementResult result) - => comboDisplay.OnRevertResult(fruit, result); - - public bool AttemptCatch(CatchHitObject obj) + public void OnRevertResult(DrawableCatchHitObject hitObject, JudgementResult result) { - return MovableCatcher.AttemptCatch(obj); + comboDisplay.OnRevertResult(hitObject, result); + MovableCatcher.OnRevertResult(hitObject, result); } protected override void UpdateAfterChildren() From cb76a2d7b549072aed1ad4ac3beae16fbcbb6c35 Mon Sep 17 00:00:00 2001 From: ekrctb Date: Tue, 8 Dec 2020 15:02:55 +0900 Subject: [PATCH 176/184] Restore catcher state on revert judgement result --- .../TestSceneCatcher.cs | 38 ++++++++++++++----- .../Judgements/CatchJudgementResult.cs | 23 +++++++++++ .../Drawables/DrawableCatchHitObject.cs | 4 ++ osu.Game.Rulesets.Catch/UI/Catcher.cs | 6 +++ 4 files changed, 62 insertions(+), 9 deletions(-) create mode 100644 osu.Game.Rulesets.Catch/Judgements/CatchJudgementResult.cs diff --git a/osu.Game.Rulesets.Catch.Tests/TestSceneCatcher.cs b/osu.Game.Rulesets.Catch.Tests/TestSceneCatcher.cs index d97c56164e..62149620d2 100644 --- a/osu.Game.Rulesets.Catch.Tests/TestSceneCatcher.cs +++ b/osu.Game.Rulesets.Catch.Tests/TestSceneCatcher.cs @@ -56,6 +56,24 @@ namespace osu.Game.Rulesets.Catch.Tests }; }); + [Test] + public void TestCatcherStateRevert() + { + DrawableCatchHitObject drawableObject = null; + JudgementResult result = null; + AddStep("catch kiai fruit", () => + { + drawableObject = createDrawableObject(new TestKiaiFruit()); + result = attemptCatch(drawableObject); + }); + checkState(CatcherAnimationState.Kiai); + AddStep("revert result", () => + { + catcher.OnRevertResult(drawableObject, result); + }); + checkState(CatcherAnimationState.Idle); + } + [Test] public void TestCatcherCatchWidth() { @@ -170,17 +188,19 @@ namespace osu.Game.Rulesets.Catch.Tests private void attemptCatch(CatchHitObject hitObject, int count = 1) { - hitObject.ApplyDefaults(new ControlPointInfo(), new BeatmapDifficulty()); - for (var i = 0; i < count; i++) + attemptCatch(createDrawableObject(hitObject)); + } + + private JudgementResult attemptCatch(DrawableCatchHitObject drawableObject) + { + drawableObject.HitObject.ApplyDefaults(new ControlPointInfo(), new BeatmapDifficulty()); + var result = new CatchJudgementResult(drawableObject.HitObject, drawableObject.HitObject.CreateJudgement()) { - var drawableObject = createDrawableObject(hitObject); - var result = new JudgementResult(hitObject, new CatchJudgement()) - { - Type = catcher.CanCatch(hitObject) ? HitResult.Great : HitResult.Miss - }; - catcher.OnNewResult(drawableObject, result); - } + Type = catcher.CanCatch(drawableObject.HitObject) ? HitResult.Great : HitResult.Miss + }; + catcher.OnNewResult(drawableObject, result); + return result; } private DrawableCatchHitObject createDrawableObject(CatchHitObject hitObject) diff --git a/osu.Game.Rulesets.Catch/Judgements/CatchJudgementResult.cs b/osu.Game.Rulesets.Catch/Judgements/CatchJudgementResult.cs new file mode 100644 index 0000000000..4b375e641b --- /dev/null +++ b/osu.Game.Rulesets.Catch/Judgements/CatchJudgementResult.cs @@ -0,0 +1,23 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using JetBrains.Annotations; +using osu.Game.Rulesets.Catch.UI; +using osu.Game.Rulesets.Judgements; +using osu.Game.Rulesets.Objects; + +namespace osu.Game.Rulesets.Catch.Judgements +{ + public class CatchJudgementResult : JudgementResult + { + /// + /// The catcher animation state prior to this judgement. + /// + public CatcherAnimationState CatcherAnimationState; + + public CatchJudgementResult([NotNull] HitObject hitObject, [NotNull] Judgement judgement) + : base(hitObject, judgement) + { + } + } +} diff --git a/osu.Game.Rulesets.Catch/Objects/Drawables/DrawableCatchHitObject.cs b/osu.Game.Rulesets.Catch/Objects/Drawables/DrawableCatchHitObject.cs index 6aa8ff439e..70efe9cf29 100644 --- a/osu.Game.Rulesets.Catch/Objects/Drawables/DrawableCatchHitObject.cs +++ b/osu.Game.Rulesets.Catch/Objects/Drawables/DrawableCatchHitObject.cs @@ -5,7 +5,9 @@ using System; using JetBrains.Annotations; using osu.Framework.Bindables; using osu.Framework.Graphics; +using osu.Game.Rulesets.Catch.Judgements; using osu.Game.Rulesets.Catch.UI; +using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Utils; @@ -52,6 +54,8 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawables public override bool RemoveWhenNotAlive => IsOnPlate; + protected override JudgementResult CreateResult(Judgement judgement) => new CatchJudgementResult(HitObject, judgement); + protected override void CheckForResult(bool userTriggered, double timeOffset) { if (CheckPosition == null) return; diff --git a/osu.Game.Rulesets.Catch/UI/Catcher.cs b/osu.Game.Rulesets.Catch/UI/Catcher.cs index 8998dbf488..33068f95eb 100644 --- a/osu.Game.Rulesets.Catch/UI/Catcher.cs +++ b/osu.Game.Rulesets.Catch/UI/Catcher.cs @@ -14,6 +14,7 @@ using osu.Framework.Input.Bindings; using osu.Framework.Utils; using osu.Game.Beatmaps; using osu.Game.Configuration; +using osu.Game.Rulesets.Catch.Judgements; using osu.Game.Rulesets.Catch.Objects; using osu.Game.Rulesets.Catch.Objects.Drawables; using osu.Game.Rulesets.Catch.Skinning; @@ -210,6 +211,9 @@ namespace osu.Game.Rulesets.Catch.UI public void OnNewResult(DrawableCatchHitObject drawableObject, JudgementResult result) { + var catchResult = (CatchJudgementResult)result; + catchResult.CatcherAnimationState = CurrentState; + if (!(drawableObject.HitObject is PalpableCatchHitObject hitObject)) return; if (result.IsHit) @@ -238,6 +242,8 @@ namespace osu.Game.Rulesets.Catch.UI public void OnRevertResult(DrawableCatchHitObject fruit, JudgementResult result) { + var catchResult = (CatchJudgementResult)result; + updateState(catchResult.CatcherAnimationState); } /// From 100b365c98977011702d0c6ffaa8a343250067bb Mon Sep 17 00:00:00 2001 From: ekrctb Date: Tue, 8 Dec 2020 15:21:47 +0900 Subject: [PATCH 177/184] Restore hyper dash state on revert judgement result --- .../TestSceneCatcher.cs | 31 ++++++++++++++++++- .../Judgements/CatchJudgementResult.cs | 5 +++ osu.Game.Rulesets.Catch/UI/Catcher.cs | 13 +++++++- 3 files changed, 47 insertions(+), 2 deletions(-) diff --git a/osu.Game.Rulesets.Catch.Tests/TestSceneCatcher.cs b/osu.Game.Rulesets.Catch.Tests/TestSceneCatcher.cs index 62149620d2..cf6011d721 100644 --- a/osu.Game.Rulesets.Catch.Tests/TestSceneCatcher.cs +++ b/osu.Game.Rulesets.Catch.Tests/TestSceneCatcher.cs @@ -57,7 +57,36 @@ namespace osu.Game.Rulesets.Catch.Tests }); [Test] - public void TestCatcherStateRevert() + public void TestCatcherHyperStateReverted() + { + DrawableCatchHitObject drawableObject1 = null; + DrawableCatchHitObject drawableObject2 = null; + JudgementResult result1 = null; + JudgementResult result2 = null; + AddStep("catch hyper fruit", () => + { + drawableObject1 = createDrawableObject(new Fruit { HyperDashTarget = new Fruit { X = 100 } }); + result1 = attemptCatch(drawableObject1); + }); + AddStep("catch normal fruit", () => + { + drawableObject2 = createDrawableObject(new Fruit()); + result2 = attemptCatch(drawableObject2); + }); + AddStep("revert second result", () => + { + catcher.OnRevertResult(drawableObject2, result2); + }); + checkHyperDash(true); + AddStep("revert first result", () => + { + catcher.OnRevertResult(drawableObject1, result1); + }); + checkHyperDash(false); + } + + [Test] + public void TestCatcherAnimationStateReverted() { DrawableCatchHitObject drawableObject = null; JudgementResult result = null; diff --git a/osu.Game.Rulesets.Catch/Judgements/CatchJudgementResult.cs b/osu.Game.Rulesets.Catch/Judgements/CatchJudgementResult.cs index 4b375e641b..c09355d59c 100644 --- a/osu.Game.Rulesets.Catch/Judgements/CatchJudgementResult.cs +++ b/osu.Game.Rulesets.Catch/Judgements/CatchJudgementResult.cs @@ -15,6 +15,11 @@ namespace osu.Game.Rulesets.Catch.Judgements /// public CatcherAnimationState CatcherAnimationState; + /// + /// Whether the catcher was hyper dashing prior to this judgement. + /// + public bool CatcherHyperDash; + public CatchJudgementResult([NotNull] HitObject hitObject, [NotNull] Judgement judgement) : base(hitObject, judgement) { diff --git a/osu.Game.Rulesets.Catch/UI/Catcher.cs b/osu.Game.Rulesets.Catch/UI/Catcher.cs index 33068f95eb..da80fa2bd5 100644 --- a/osu.Game.Rulesets.Catch/UI/Catcher.cs +++ b/osu.Game.Rulesets.Catch/UI/Catcher.cs @@ -213,6 +213,7 @@ namespace osu.Game.Rulesets.Catch.UI { var catchResult = (CatchJudgementResult)result; catchResult.CatcherAnimationState = CurrentState; + catchResult.CatcherHyperDash = HyperDashing; if (!(drawableObject.HitObject is PalpableCatchHitObject hitObject)) return; @@ -243,7 +244,17 @@ namespace osu.Game.Rulesets.Catch.UI public void OnRevertResult(DrawableCatchHitObject fruit, JudgementResult result) { var catchResult = (CatchJudgementResult)result; - updateState(catchResult.CatcherAnimationState); + + if (CurrentState != catchResult.CatcherAnimationState) + updateState(catchResult.CatcherAnimationState); + + if (HyperDashing != catchResult.CatcherHyperDash) + { + if (catchResult.CatcherHyperDash) + SetHyperDashState(2); + else + SetHyperDashState(); + } } /// From 1a66d8f2bc7ae8ae423b2da010965ad22dc4ff60 Mon Sep 17 00:00:00 2001 From: ekrctb Date: Tue, 8 Dec 2020 15:24:39 +0900 Subject: [PATCH 178/184] Remove caught objects on revert result --- osu.Game.Rulesets.Catch/UI/Catcher.cs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Catch/UI/Catcher.cs b/osu.Game.Rulesets.Catch/UI/Catcher.cs index da80fa2bd5..2bf085312f 100644 --- a/osu.Game.Rulesets.Catch/UI/Catcher.cs +++ b/osu.Game.Rulesets.Catch/UI/Catcher.cs @@ -241,7 +241,7 @@ namespace osu.Game.Rulesets.Catch.UI updateState(CatcherAnimationState.Fail); } - public void OnRevertResult(DrawableCatchHitObject fruit, JudgementResult result) + public void OnRevertResult(DrawableCatchHitObject drawableObject, JudgementResult result) { var catchResult = (CatchJudgementResult)result; @@ -255,6 +255,9 @@ namespace osu.Game.Rulesets.Catch.UI else SetHyperDashState(); } + + caughtFruitContainer.RemoveAll(d => d.HitObject == drawableObject.HitObject); + droppedObjectTarget.RemoveAll(d => (d as DrawableCatchHitObject)?.HitObject == drawableObject.HitObject); } /// From 02571ec7ae3f45df77db3d162d1bd3cc4afe640c Mon Sep 17 00:00:00 2001 From: ekrctb Date: Tue, 8 Dec 2020 15:43:17 +0900 Subject: [PATCH 179/184] Remove hit explosion on revert result --- osu.Game.Rulesets.Catch/UI/Catcher.cs | 2 ++ osu.Game.Rulesets.Catch/UI/HitExplosion.cs | 2 ++ 2 files changed, 4 insertions(+) diff --git a/osu.Game.Rulesets.Catch/UI/Catcher.cs b/osu.Game.Rulesets.Catch/UI/Catcher.cs index 2bf085312f..a806e623af 100644 --- a/osu.Game.Rulesets.Catch/UI/Catcher.cs +++ b/osu.Game.Rulesets.Catch/UI/Catcher.cs @@ -258,6 +258,7 @@ namespace osu.Game.Rulesets.Catch.UI caughtFruitContainer.RemoveAll(d => d.HitObject == drawableObject.HitObject); droppedObjectTarget.RemoveAll(d => (d as DrawableCatchHitObject)?.HitObject == drawableObject.HitObject); + hitExplosionContainer.RemoveAll(d => d.HitObject == drawableObject.HitObject); } /// @@ -489,6 +490,7 @@ namespace osu.Game.Rulesets.Catch.UI if (!hitLighting.Value) return; HitExplosion hitExplosion = hitExplosionPool.Get(); + hitExplosion.HitObject = caughtObject.HitObject; hitExplosion.X = caughtObject.X; hitExplosion.Scale = new Vector2(caughtObject.HitObject.Scale); hitExplosion.ObjectColour = caughtObject.AccentColour.Value; diff --git a/osu.Game.Rulesets.Catch/UI/HitExplosion.cs b/osu.Game.Rulesets.Catch/UI/HitExplosion.cs index 24ca778248..26627422e1 100644 --- a/osu.Game.Rulesets.Catch/UI/HitExplosion.cs +++ b/osu.Game.Rulesets.Catch/UI/HitExplosion.cs @@ -7,6 +7,7 @@ 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; using osuTK; using osuTK.Graphics; @@ -15,6 +16,7 @@ namespace osu.Game.Rulesets.Catch.UI public class HitExplosion : PoolableDrawable { private Color4 objectColour; + public CatchHitObject HitObject; public Color4 ObjectColour { From 17d48c82f6f4d8ed22981b2ed4e749012709db55 Mon Sep 17 00:00:00 2001 From: ekrctb Date: Tue, 8 Dec 2020 16:59:06 +0900 Subject: [PATCH 180/184] Use switch statement instead of an array --- .../Skinning/Legacy/LegacyFruitPiece.cs | 26 ++++++++++++------- 1 file changed, 17 insertions(+), 9 deletions(-) diff --git a/osu.Game.Rulesets.Catch/Skinning/Legacy/LegacyFruitPiece.cs b/osu.Game.Rulesets.Catch/Skinning/Legacy/LegacyFruitPiece.cs index e45f00c6aa..6f93e68594 100644 --- a/osu.Game.Rulesets.Catch/Skinning/Legacy/LegacyFruitPiece.cs +++ b/osu.Game.Rulesets.Catch/Skinning/Legacy/LegacyFruitPiece.cs @@ -2,7 +2,6 @@ // See the LICENCE file in the repository root for full licence text. using osu.Framework.Bindables; -using osu.Framework.Graphics.Textures; using osu.Game.Rulesets.Catch.Objects.Drawables; namespace osu.Game.Rulesets.Catch.Skinning.Legacy @@ -11,11 +10,6 @@ namespace osu.Game.Rulesets.Catch.Skinning.Legacy { public readonly Bindable VisualRepresentation = new Bindable(); - private readonly string[] lookupNames = - { - "fruit-pear", "fruit-grapes", "fruit-apple", "fruit-orange" - }; - protected override void LoadComplete() { base.LoadComplete(); @@ -30,10 +24,24 @@ namespace osu.Game.Rulesets.Catch.Skinning.Legacy private void setTexture(FruitVisualRepresentation visualRepresentation) { - Texture texture = Skin.GetTexture(lookupNames[(int)visualRepresentation]); - Texture overlayTexture = Skin.GetTexture(lookupNames[(int)visualRepresentation] + "-overlay"); + switch (visualRepresentation) + { + case FruitVisualRepresentation.Pear: + SetTexture(Skin.GetTexture("fruit-pear"), Skin.GetTexture("fruit-pear-overlay")); + break; - SetTexture(texture, overlayTexture); + case FruitVisualRepresentation.Grape: + SetTexture(Skin.GetTexture("fruit-grapes"), Skin.GetTexture("fruit-grapes-overlay")); + break; + + case FruitVisualRepresentation.Pineapple: + SetTexture(Skin.GetTexture("fruit-apple"), Skin.GetTexture("fruit-apple-overlay")); + break; + + case FruitVisualRepresentation.Raspberry: + SetTexture(Skin.GetTexture("fruit-orange"), Skin.GetTexture("fruit-orange-overlay")); + break; + } } } } From 603cecb2ebbf2241f605ed86daf18d1139013140 Mon Sep 17 00:00:00 2001 From: ekrctb Date: Tue, 8 Dec 2020 17:02:57 +0900 Subject: [PATCH 181/184] Make CatchHitObjectPiece abstract class --- osu.Game.Rulesets.Catch/Skinning/Default/CatchHitObjectPiece.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Catch/Skinning/Default/CatchHitObjectPiece.cs b/osu.Game.Rulesets.Catch/Skinning/Default/CatchHitObjectPiece.cs index be6cf0fc05..0d4a4e8e78 100644 --- a/osu.Game.Rulesets.Catch/Skinning/Default/CatchHitObjectPiece.cs +++ b/osu.Game.Rulesets.Catch/Skinning/Default/CatchHitObjectPiece.cs @@ -12,7 +12,7 @@ using osuTK.Graphics; namespace osu.Game.Rulesets.Catch.Skinning.Default { - public class CatchHitObjectPiece : CompositeDrawable + public abstract class CatchHitObjectPiece : CompositeDrawable { public readonly Bindable AccentColour = new Bindable(); public readonly Bindable HyperDash = new Bindable(); From 9d926de9443143f7a7b75860c4b05ac973e0d9ee Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 8 Dec 2020 17:04:26 +0900 Subject: [PATCH 182/184] Fix test failure --- osu.Game.Rulesets.Catch.Tests/TestSceneCatcherArea.cs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/osu.Game.Rulesets.Catch.Tests/TestSceneCatcherArea.cs b/osu.Game.Rulesets.Catch.Tests/TestSceneCatcherArea.cs index c8826aa174..8602c7aad1 100644 --- a/osu.Game.Rulesets.Catch.Tests/TestSceneCatcherArea.cs +++ b/osu.Game.Rulesets.Catch.Tests/TestSceneCatcherArea.cs @@ -15,7 +15,6 @@ using osu.Game.Rulesets.Catch.Judgements; using osu.Game.Rulesets.Catch.Objects; using osu.Game.Rulesets.Catch.Objects.Drawables; using osu.Game.Rulesets.Catch.UI; -using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Scoring; namespace osu.Game.Rulesets.Catch.Tests @@ -58,7 +57,7 @@ namespace osu.Game.Rulesets.Catch.Tests Schedule(() => { - area.OnNewResult(drawable, new JudgementResult(fruit, new CatchJudgement()) + area.OnNewResult(drawable, new CatchJudgementResult(fruit, new CatchJudgement()) { Type = area.MovableCatcher.CanCatch(fruit) ? HitResult.Great : HitResult.Miss }); From 4d5c242d35e0603282bee8d157a92fb4239c9e22 Mon Sep 17 00:00:00 2001 From: ekrctb Date: Tue, 8 Dec 2020 17:15:40 +0900 Subject: [PATCH 183/184] Use virtual property instead of a field for optional pieces --- .../Skinning/Default/BananaPiece.cs | 2 ++ .../Skinning/Default/CatchHitObjectPiece.cs | 10 ++++++++-- .../Skinning/Default/DropletPiece.cs | 2 ++ osu.Game.Rulesets.Catch/Skinning/Default/FruitPiece.cs | 3 +++ 4 files changed, 15 insertions(+), 2 deletions(-) diff --git a/osu.Game.Rulesets.Catch/Skinning/Default/BananaPiece.cs b/osu.Game.Rulesets.Catch/Skinning/Default/BananaPiece.cs index f81c1063b9..8da18a668a 100644 --- a/osu.Game.Rulesets.Catch/Skinning/Default/BananaPiece.cs +++ b/osu.Game.Rulesets.Catch/Skinning/Default/BananaPiece.cs @@ -7,6 +7,8 @@ namespace osu.Game.Rulesets.Catch.Skinning.Default { public class BananaPiece : CatchHitObjectPiece { + protected override BorderPiece BorderPiece { get; } + public BananaPiece() { RelativeSizeAxes = Axes.Both; diff --git a/osu.Game.Rulesets.Catch/Skinning/Default/CatchHitObjectPiece.cs b/osu.Game.Rulesets.Catch/Skinning/Default/CatchHitObjectPiece.cs index 0d4a4e8e78..d59b6cc0de 100644 --- a/osu.Game.Rulesets.Catch/Skinning/Default/CatchHitObjectPiece.cs +++ b/osu.Game.Rulesets.Catch/Skinning/Default/CatchHitObjectPiece.cs @@ -21,11 +21,17 @@ namespace osu.Game.Rulesets.Catch.Skinning.Default [CanBeNull] protected DrawableHitObject DrawableHitObject { get; private set; } + /// + /// A part of this piece that will be faded out while falling in the playfield. + /// [CanBeNull] - protected BorderPiece BorderPiece; + protected virtual BorderPiece BorderPiece => null; + /// + /// A part of this piece that will be only visible when is true. + /// [CanBeNull] - protected HyperBorderPiece HyperBorderPiece; + protected virtual HyperBorderPiece HyperBorderPiece => null; protected override void LoadComplete() { diff --git a/osu.Game.Rulesets.Catch/Skinning/Default/DropletPiece.cs b/osu.Game.Rulesets.Catch/Skinning/Default/DropletPiece.cs index c149f7769f..8b1052dfe2 100644 --- a/osu.Game.Rulesets.Catch/Skinning/Default/DropletPiece.cs +++ b/osu.Game.Rulesets.Catch/Skinning/Default/DropletPiece.cs @@ -9,6 +9,8 @@ namespace osu.Game.Rulesets.Catch.Skinning.Default { public class DropletPiece : CatchHitObjectPiece { + protected override HyperBorderPiece HyperBorderPiece { get; } + public DropletPiece() { Size = new Vector2(CatchHitObject.OBJECT_RADIUS / 2); diff --git a/osu.Game.Rulesets.Catch/Skinning/Default/FruitPiece.cs b/osu.Game.Rulesets.Catch/Skinning/Default/FruitPiece.cs index 45d688c4e5..2e3803a31a 100644 --- a/osu.Game.Rulesets.Catch/Skinning/Default/FruitPiece.cs +++ b/osu.Game.Rulesets.Catch/Skinning/Default/FruitPiece.cs @@ -16,6 +16,9 @@ namespace osu.Game.Rulesets.Catch.Skinning.Default public readonly Bindable VisualRepresentation = new Bindable(); + protected override BorderPiece BorderPiece { get; } + protected override HyperBorderPiece HyperBorderPiece { get; } + public FruitPiece() { RelativeSizeAxes = Axes.Both; From 22a5df6309aad3ab7f075c38e7617eee64c4c12c Mon Sep 17 00:00:00 2001 From: ekrctb Date: Tue, 8 Dec 2020 17:31:00 +0900 Subject: [PATCH 184/184] Clear all transforms of catcher trail sprite before returned to pool --- osu.Game.Rulesets.Catch/UI/CatcherTrailSprite.cs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/osu.Game.Rulesets.Catch/UI/CatcherTrailSprite.cs b/osu.Game.Rulesets.Catch/UI/CatcherTrailSprite.cs index b3be18d46b..0e3e409fac 100644 --- a/osu.Game.Rulesets.Catch/UI/CatcherTrailSprite.cs +++ b/osu.Game.Rulesets.Catch/UI/CatcherTrailSprite.cs @@ -30,5 +30,11 @@ namespace osu.Game.Rulesets.Catch.UI // Sets the origin roughly to the centre of the catcher's plate to allow for correct scaling. OriginPosition = new Vector2(0.5f, 0.06f) * CatcherArea.CATCHER_SIZE; } + + protected override void FreeAfterUse() + { + ClearTransforms(); + base.FreeAfterUse(); + } } }