diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneOsuDistanceSnapGrid.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneOsuDistanceSnapGrid.cs index eff4d919b0..c9b3d08a22 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestSceneOsuDistanceSnapGrid.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneOsuDistanceSnapGrid.cs @@ -33,8 +33,8 @@ namespace osu.Game.Rulesets.Osu.Tests typeof(CircularDistanceSnapGrid) }; - [Cached(typeof(IEditorBeatmap))] - private readonly EditorBeatmap editorBeatmap; + [Cached(typeof(EditorBeatmap))] + private readonly EditorBeatmap editorBeatmap; [Cached] private readonly BindableBeatDivisor beatDivisor = new BindableBeatDivisor(); @@ -46,7 +46,7 @@ namespace osu.Game.Rulesets.Osu.Tests public TestSceneOsuDistanceSnapGrid() { - editorBeatmap = new EditorBeatmap(new OsuBeatmap()); + editorBeatmap = new EditorBeatmap(new OsuBeatmap()); } [SetUp] diff --git a/osu.Game.Rulesets.Osu/Edit/OsuHitObjectComposer.cs b/osu.Game.Rulesets.Osu/Edit/OsuHitObjectComposer.cs index a2c1a5f5f4..49624ea733 100644 --- a/osu.Game.Rulesets.Osu/Edit/OsuHitObjectComposer.cs +++ b/osu.Game.Rulesets.Osu/Edit/OsuHitObjectComposer.cs @@ -91,10 +91,10 @@ namespace osu.Game.Rulesets.Osu.Edit if (sourceIndex == -1) return null; - OsuHitObject sourceObject = EditorBeatmap.HitObjects[sourceIndex]; + HitObject sourceObject = EditorBeatmap.HitObjects[sourceIndex]; int targetIndex = sourceIndex + targetOffset; - OsuHitObject targetObject = null; + HitObject targetObject = null; // Keep advancing the target object while its start time falls before the end time of the source object while (true) @@ -111,7 +111,7 @@ namespace osu.Game.Rulesets.Osu.Edit targetIndex++; } - return new OsuDistanceSnapGrid(sourceObject, targetObject); + return new OsuDistanceSnapGrid((OsuHitObject)sourceObject, (OsuHitObject)targetObject); } } } diff --git a/osu.Game.Rulesets.Taiko/Audio/DrumSampleMapping.cs b/osu.Game.Rulesets.Taiko/Audio/DrumSampleMapping.cs index aaf113f216..c31b07344d 100644 --- a/osu.Game.Rulesets.Taiko/Audio/DrumSampleMapping.cs +++ b/osu.Game.Rulesets.Taiko/Audio/DrumSampleMapping.cs @@ -26,10 +26,6 @@ namespace osu.Game.Rulesets.Taiko.Audio var centre = s.GetSampleInfo(); var rim = s.GetSampleInfo(HitSampleInfo.HIT_CLAP); - // todo: this is ugly - centre.Namespace = "taiko"; - rim.Namespace = "taiko"; - mappings[s.Time] = new DrumSample { Centre = addSound(centre), diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableTaikoHitObject.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableTaikoHitObject.cs index 2da5a9c403..b9d31ff906 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableTaikoHitObject.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableTaikoHitObject.cs @@ -166,8 +166,6 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables // Normal and clap samples are handled by the drum protected override IEnumerable GetSamples() => HitObject.Samples.Where(s => s.Name != HitSampleInfo.HIT_NORMAL && s.Name != HitSampleInfo.HIT_CLAP); - protected override string SampleNamespace => "taiko"; - protected virtual TaikoPiece CreateMainPiece() => new CirclePiece(); /// diff --git a/osu.Game.Rulesets.Taiko/Resources/Samples/Gameplay/normal-hitclap.wav b/osu.Game.Rulesets.Taiko/Resources/Samples/Gameplay/normal-hitclap.wav new file mode 100755 index 0000000000..9ea2be5855 Binary files /dev/null and b/osu.Game.Rulesets.Taiko/Resources/Samples/Gameplay/normal-hitclap.wav differ diff --git a/osu.Game.Rulesets.Taiko/Resources/Samples/Gameplay/normal-hitfinish.wav b/osu.Game.Rulesets.Taiko/Resources/Samples/Gameplay/normal-hitfinish.wav new file mode 100755 index 0000000000..af270ae12a Binary files /dev/null and b/osu.Game.Rulesets.Taiko/Resources/Samples/Gameplay/normal-hitfinish.wav differ diff --git a/osu.Game.Rulesets.Taiko/Resources/Samples/Gameplay/normal-hitnormal.wav b/osu.Game.Rulesets.Taiko/Resources/Samples/Gameplay/normal-hitnormal.wav new file mode 100755 index 0000000000..3d8024c6ae Binary files /dev/null and b/osu.Game.Rulesets.Taiko/Resources/Samples/Gameplay/normal-hitnormal.wav differ diff --git a/osu.Game.Rulesets.Taiko/Resources/Samples/Gameplay/normal-hitwhistle.wav b/osu.Game.Rulesets.Taiko/Resources/Samples/Gameplay/normal-hitwhistle.wav new file mode 100755 index 0000000000..16d254cc87 Binary files /dev/null and b/osu.Game.Rulesets.Taiko/Resources/Samples/Gameplay/normal-hitwhistle.wav differ diff --git a/osu.Game.Rulesets.Taiko/Resources/Samples/Gameplay/soft-hitclap.wav b/osu.Game.Rulesets.Taiko/Resources/Samples/Gameplay/soft-hitclap.wav new file mode 100755 index 0000000000..b4cfa26265 Binary files /dev/null and b/osu.Game.Rulesets.Taiko/Resources/Samples/Gameplay/soft-hitclap.wav differ diff --git a/osu.Game.Rulesets.Taiko/Resources/Samples/Gameplay/soft-hitfinish.wav b/osu.Game.Rulesets.Taiko/Resources/Samples/Gameplay/soft-hitfinish.wav new file mode 100755 index 0000000000..97804a5a61 Binary files /dev/null and b/osu.Game.Rulesets.Taiko/Resources/Samples/Gameplay/soft-hitfinish.wav differ diff --git a/osu.Game.Rulesets.Taiko/Resources/Samples/Gameplay/soft-hitnormal.wav b/osu.Game.Rulesets.Taiko/Resources/Samples/Gameplay/soft-hitnormal.wav new file mode 100755 index 0000000000..67f02877a8 Binary files /dev/null and b/osu.Game.Rulesets.Taiko/Resources/Samples/Gameplay/soft-hitnormal.wav differ diff --git a/osu.Game.Rulesets.Taiko/Resources/Samples/Gameplay/soft-hitwhistle.wav b/osu.Game.Rulesets.Taiko/Resources/Samples/Gameplay/soft-hitwhistle.wav new file mode 100755 index 0000000000..10206cd228 Binary files /dev/null and b/osu.Game.Rulesets.Taiko/Resources/Samples/Gameplay/soft-hitwhistle.wav differ diff --git a/osu.Game.Rulesets.Taiko/Skinning/TaikoLegacySkinTransformer.cs b/osu.Game.Rulesets.Taiko/Skinning/TaikoLegacySkinTransformer.cs new file mode 100644 index 0000000000..381cd14cd4 --- /dev/null +++ b/osu.Game.Rulesets.Taiko/Skinning/TaikoLegacySkinTransformer.cs @@ -0,0 +1,55 @@ +// 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 osu.Framework.Audio.Sample; +using osu.Framework.Bindables; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Textures; +using osu.Game.Audio; +using osu.Game.Skinning; + +namespace osu.Game.Rulesets.Taiko.Skinning +{ + public class TaikoLegacySkinTransformer : ISkin + { + private readonly ISkinSource source; + + public TaikoLegacySkinTransformer(ISkinSource source) + { + this.source = source; + } + + public Drawable GetDrawableComponent(ISkinComponent component) => source.GetDrawableComponent(component); + + public Texture GetTexture(string componentName) => source.GetTexture(componentName); + + public SampleChannel GetSample(ISampleInfo sampleInfo) => source.GetSample(new LegacyTaikoSampleInfo(sampleInfo)); + + public IBindable GetConfig(TLookup lookup) => source.GetConfig(lookup); + + private class LegacyTaikoSampleInfo : ISampleInfo + { + private readonly ISampleInfo source; + + public LegacyTaikoSampleInfo(ISampleInfo source) + { + this.source = source; + } + + public IEnumerable LookupNames + { + get + { + foreach (var name in source.LookupNames) + yield return $"taiko-{name}"; + + foreach (var name in source.LookupNames) + yield return name; + } + } + + public int Volume => source.Volume; + } + } +} diff --git a/osu.Game.Rulesets.Taiko/TaikoRuleset.cs b/osu.Game.Rulesets.Taiko/TaikoRuleset.cs index 777b68a993..536cbdc562 100644 --- a/osu.Game.Rulesets.Taiko/TaikoRuleset.cs +++ b/osu.Game.Rulesets.Taiko/TaikoRuleset.cs @@ -21,6 +21,8 @@ using osu.Game.Rulesets.Taiko.Difficulty; using osu.Game.Rulesets.Taiko.Scoring; using osu.Game.Scoring; using System; +using osu.Game.Rulesets.Taiko.Skinning; +using osu.Game.Skinning; namespace osu.Game.Rulesets.Taiko { @@ -34,6 +36,8 @@ namespace osu.Game.Rulesets.Taiko public override IBeatmapConverter CreateBeatmapConverter(IBeatmap beatmap) => new TaikoBeatmapConverter(beatmap, this); + public override ISkin CreateLegacySkinProvider(ISkinSource source) => new TaikoLegacySkinTransformer(source); + public const string SHORT_NAME = "taiko"; public override IEnumerable GetDefaultKeyBindings(int variant = 0) => new[] diff --git a/osu.Game.Tests/Beatmaps/EditorBeatmapTest.cs b/osu.Game.Tests/Beatmaps/EditorBeatmapTest.cs index 98e630abd2..12d729d09f 100644 --- a/osu.Game.Tests/Beatmaps/EditorBeatmapTest.cs +++ b/osu.Game.Tests/Beatmaps/EditorBeatmapTest.cs @@ -20,7 +20,7 @@ namespace osu.Game.Tests.Beatmaps [Test] public void TestHitObjectAddEvent() { - var editorBeatmap = new EditorBeatmap(new OsuBeatmap()); + var editorBeatmap = new EditorBeatmap(new OsuBeatmap()); HitObject addedObject = null; editorBeatmap.HitObjectAdded += h => addedObject = h; @@ -38,7 +38,7 @@ namespace osu.Game.Tests.Beatmaps public void HitObjectRemoveEvent() { var hitCircle = new HitCircle(); - var editorBeatmap = new EditorBeatmap(new OsuBeatmap { HitObjects = { hitCircle } }); + var editorBeatmap = new EditorBeatmap(new OsuBeatmap { HitObjects = { hitCircle } }); HitObject removedObject = null; editorBeatmap.HitObjectRemoved += h => removedObject = h; @@ -55,7 +55,7 @@ namespace osu.Game.Tests.Beatmaps public void TestInitialHitObjectStartTimeChangeEvent() { var hitCircle = new HitCircle(); - var editorBeatmap = new EditorBeatmap(new OsuBeatmap { HitObjects = { hitCircle } }); + var editorBeatmap = new EditorBeatmap(new OsuBeatmap { HitObjects = { hitCircle } }); HitObject changedObject = null; editorBeatmap.StartTimeChanged += h => changedObject = h; @@ -71,7 +71,7 @@ namespace osu.Game.Tests.Beatmaps [Test] public void TestAddedHitObjectStartTimeChangeEvent() { - var editorBeatmap = new EditorBeatmap(new OsuBeatmap()); + var editorBeatmap = new EditorBeatmap(new OsuBeatmap()); HitObject changedObject = null; editorBeatmap.StartTimeChanged += h => changedObject = h; @@ -92,7 +92,7 @@ namespace osu.Game.Tests.Beatmaps public void TestRemovedHitObjectStartTimeChangeEvent() { var hitCircle = new HitCircle(); - var editorBeatmap = new EditorBeatmap(new OsuBeatmap { HitObjects = { hitCircle } }); + var editorBeatmap = new EditorBeatmap(new OsuBeatmap { HitObjects = { hitCircle } }); HitObject changedObject = null; editorBeatmap.StartTimeChanged += h => changedObject = h; @@ -110,7 +110,7 @@ namespace osu.Game.Tests.Beatmaps [Test] public void TestAddHitObjectInMiddle() { - var editorBeatmap = new EditorBeatmap(new OsuBeatmap + var editorBeatmap = new EditorBeatmap(new OsuBeatmap { HitObjects = { @@ -134,7 +134,7 @@ namespace osu.Game.Tests.Beatmaps public void TestResortWhenStartTimeChanged() { var hitCircle = new HitCircle { StartTime = 1000 }; - var editorBeatmap = new EditorBeatmap(new OsuBeatmap + var editorBeatmap = new EditorBeatmap(new OsuBeatmap { HitObjects = { diff --git a/osu.Game.Tests/Editor/TestSceneHitObjectComposerDistanceSnapping.cs b/osu.Game.Tests/Editor/TestSceneHitObjectComposerDistanceSnapping.cs index fe3cc375ea..2d336bd19c 100644 --- a/osu.Game.Tests/Editor/TestSceneHitObjectComposerDistanceSnapping.cs +++ b/osu.Game.Tests/Editor/TestSceneHitObjectComposerDistanceSnapping.cs @@ -2,11 +2,12 @@ // See the LICENCE file in the repository root for full licence text. using NUnit.Framework; +using osu.Framework.Allocation; using osu.Framework.Testing; using osu.Game.Beatmaps.ControlPoints; using osu.Game.Rulesets.Osu; +using osu.Game.Rulesets.Osu.Beatmaps; using osu.Game.Rulesets.Osu.Edit; -using osu.Game.Rulesets.Osu.Objects; using osu.Game.Screens.Edit; using osu.Game.Tests.Visual; @@ -17,6 +18,9 @@ namespace osu.Game.Tests.Editor { private TestHitObjectComposer composer; + [Cached(typeof(EditorBeatmap))] + private readonly EditorBeatmap editorBeatmap = new EditorBeatmap(new OsuBeatmap()); + [SetUp] public void Setup() => Schedule(() => { @@ -183,7 +187,7 @@ namespace osu.Game.Tests.Editor private class TestHitObjectComposer : OsuHitObjectComposer { - public new EditorBeatmap EditorBeatmap => base.EditorBeatmap; + public new EditorBeatmap EditorBeatmap => base.EditorBeatmap; public TestHitObjectComposer() : base(new OsuRuleset()) diff --git a/osu.Game.Tests/Gameplay/TestSceneStoryboardSamples.cs b/osu.Game.Tests/Gameplay/TestSceneStoryboardSamples.cs new file mode 100644 index 0000000000..5deb136c85 --- /dev/null +++ b/osu.Game.Tests/Gameplay/TestSceneStoryboardSamples.cs @@ -0,0 +1,74 @@ +// 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.IO; +using System.Threading.Tasks; +using NUnit.Framework; +using osu.Framework.Audio; +using osu.Framework.Audio.Sample; +using osu.Framework.IO.Stores; +using osu.Game.Audio; +using osu.Game.Skinning; +using osu.Game.Tests.Resources; +using osu.Game.Tests.Visual; + +namespace osu.Game.Tests.Gameplay +{ + public class TestSceneStoryboardSamples : OsuTestScene + { + [Test] + public void TestRetrieveTopLevelSample() + { + ISkin skin = null; + SampleChannel channel = null; + + AddStep("create skin", () => skin = new TestSkin("test-sample", Audio)); + AddStep("retrieve sample", () => channel = skin.GetSample(new SampleInfo("test-sample"))); + + AddAssert("sample is non-null", () => channel != null); + } + + [Test] + public void TestRetrieveSampleInSubFolder() + { + ISkin skin = null; + SampleChannel channel = null; + + AddStep("create skin", () => skin = new TestSkin("folder/test-sample", Audio)); + AddStep("retrieve sample", () => channel = skin.GetSample(new SampleInfo("folder/test-sample"))); + + AddAssert("sample is non-null", () => channel != null); + } + + private class TestSkin : LegacySkin + { + public TestSkin(string resourceName, AudioManager audioManager) + : base(DefaultLegacySkin.Info, new TestResourceStore(resourceName), audioManager, "skin.ini") + { + } + } + + private class TestResourceStore : IResourceStore + { + private readonly string resourceName; + + public TestResourceStore(string resourceName) + { + this.resourceName = resourceName; + } + + public byte[] Get(string name) => name == resourceName ? TestResources.GetStore().Get("Resources/test-sample.mp3") : null; + + public Task GetAsync(string name) => name == resourceName ? TestResources.GetStore().GetAsync("Resources/test-sample.mp3") : null; + + public Stream GetStream(string name) => name == resourceName ? TestResources.GetStore().GetStream("Resources/test-sample.mp3") : null; + + public IEnumerable GetAvailableResources() => new[] { resourceName }; + + public void Dispose() + { + } + } + } +} diff --git a/osu.Game.Tests/Resources/test-sample.mp3 b/osu.Game.Tests/Resources/test-sample.mp3 new file mode 100644 index 0000000000..f7c344f39a Binary files /dev/null and b/osu.Game.Tests/Resources/test-sample.mp3 differ diff --git a/osu.Game.Tests/Visual/Editor/TestSceneComposeScreen.cs b/osu.Game.Tests/Visual/Editor/TestSceneComposeScreen.cs index 9f16e1d781..3562689482 100644 --- a/osu.Game.Tests/Visual/Editor/TestSceneComposeScreen.cs +++ b/osu.Game.Tests/Visual/Editor/TestSceneComposeScreen.cs @@ -4,6 +4,8 @@ using NUnit.Framework; using osu.Framework.Allocation; using osu.Game.Rulesets.Osu; +using osu.Game.Rulesets.Osu.Beatmaps; +using osu.Game.Screens.Edit; using osu.Game.Screens.Edit.Compose; namespace osu.Game.Tests.Visual.Editor @@ -11,10 +13,21 @@ namespace osu.Game.Tests.Visual.Editor [TestFixture] public class TestSceneComposeScreen : EditorClockTestScene { + [Cached(typeof(EditorBeatmap))] + private readonly EditorBeatmap editorBeatmap = + new EditorBeatmap(new OsuBeatmap + { + BeatmapInfo = + { + Ruleset = new OsuRuleset().RulesetInfo + } + }); + [BackgroundDependencyLoader] private void load() { - Beatmap.Value = CreateWorkingBeatmap(new OsuRuleset().RulesetInfo); + Beatmap.Value = CreateWorkingBeatmap(editorBeatmap.PlayableBeatmap); + Child = new ComposeScreen(); } } diff --git a/osu.Game.Tests/Visual/Editor/TestSceneDistanceSnapGrid.cs b/osu.Game.Tests/Visual/Editor/TestSceneDistanceSnapGrid.cs index 39b4bf7218..847d168e51 100644 --- a/osu.Game.Tests/Visual/Editor/TestSceneDistanceSnapGrid.cs +++ b/osu.Game.Tests/Visual/Editor/TestSceneDistanceSnapGrid.cs @@ -8,7 +8,6 @@ using osu.Framework.Graphics.Shapes; using osu.Game.Beatmaps.ControlPoints; using osu.Game.Rulesets.Edit; using osu.Game.Rulesets.Osu.Beatmaps; -using osu.Game.Rulesets.Osu.Objects; using osu.Game.Screens.Edit; using osu.Game.Screens.Edit.Compose.Components; using osuTK; @@ -21,15 +20,15 @@ namespace osu.Game.Tests.Visual.Editor private const double beat_length = 100; private static readonly Vector2 grid_position = new Vector2(512, 384); - [Cached(typeof(IEditorBeatmap))] - private readonly EditorBeatmap editorBeatmap; + [Cached(typeof(EditorBeatmap))] + private readonly EditorBeatmap editorBeatmap; [Cached(typeof(IDistanceSnapProvider))] private readonly SnapProvider snapProvider = new SnapProvider(); public TestSceneDistanceSnapGrid() { - editorBeatmap = new EditorBeatmap(new OsuBeatmap()); + editorBeatmap = new EditorBeatmap(new OsuBeatmap()); editorBeatmap.ControlPointInfo.Add(0, new TimingControlPoint { BeatLength = beat_length }); } diff --git a/osu.Game.Tests/Visual/Editor/TestSceneEditorComposeTimeline.cs b/osu.Game.Tests/Visual/Editor/TestSceneEditorComposeTimeline.cs index ed6bc5fe0c..29575cb42e 100644 --- a/osu.Game.Tests/Visual/Editor/TestSceneEditorComposeTimeline.cs +++ b/osu.Game.Tests/Visual/Editor/TestSceneEditorComposeTimeline.cs @@ -38,7 +38,7 @@ namespace osu.Game.Tests.Visual.Editor { Beatmap.Value = new WaveformTestBeatmap(audio); - var editorBeatmap = new EditorBeatmap((Beatmap)Beatmap.Value.Beatmap); + var editorBeatmap = new EditorBeatmap((Beatmap)Beatmap.Value.Beatmap); Children = new Drawable[] { diff --git a/osu.Game.Tests/Visual/Editor/TestSceneHitObjectComposer.cs b/osu.Game.Tests/Visual/Editor/TestSceneHitObjectComposer.cs index b7c7028b52..c001c83877 100644 --- a/osu.Game.Tests/Visual/Editor/TestSceneHitObjectComposer.cs +++ b/osu.Game.Tests/Visual/Editor/TestSceneHitObjectComposer.cs @@ -16,6 +16,7 @@ using osu.Game.Rulesets.Osu.Edit; using osu.Game.Rulesets.Osu.Edit.Blueprints.HitCircles; using osu.Game.Rulesets.Osu.Edit.Blueprints.HitCircles.Components; using osu.Game.Rulesets.Osu.Objects; +using osu.Game.Screens.Edit; using osu.Game.Screens.Edit.Compose.Components; using osuTK; @@ -59,9 +60,12 @@ namespace osu.Game.Tests.Visual.Editor }, }); + var editorBeatmap = new EditorBeatmap(Beatmap.Value.GetPlayableBeatmap(new OsuRuleset().RulesetInfo)); + var clock = new DecoupleableInterpolatingFramedClock { IsCoupled = false }; Dependencies.CacheAs(clock); Dependencies.CacheAs(clock); + Dependencies.CacheAs(editorBeatmap); Child = new OsuHitObjectComposer(new OsuRuleset()); } diff --git a/osu.Game.Tests/Visual/Editor/TestSceneTimingScreen.cs b/osu.Game.Tests/Visual/Editor/TestSceneTimingScreen.cs index 121853d8d0..adfed9a299 100644 --- a/osu.Game.Tests/Visual/Editor/TestSceneTimingScreen.cs +++ b/osu.Game.Tests/Visual/Editor/TestSceneTimingScreen.cs @@ -5,7 +5,8 @@ using System; using System.Collections.Generic; using NUnit.Framework; using osu.Framework.Allocation; -using osu.Game.Rulesets.Osu; +using osu.Game.Rulesets.Osu.Beatmaps; +using osu.Game.Screens.Edit; using osu.Game.Screens.Edit.Timing; namespace osu.Game.Tests.Visual.Editor @@ -25,10 +26,13 @@ namespace osu.Game.Tests.Visual.Editor typeof(RowAttribute) }; + [Cached(typeof(EditorBeatmap))] + private readonly EditorBeatmap editorBeatmap = new EditorBeatmap(new OsuBeatmap()); + [BackgroundDependencyLoader] private void load() { - Beatmap.Value = CreateWorkingBeatmap(new OsuRuleset().RulesetInfo); + Beatmap.Value = CreateWorkingBeatmap(editorBeatmap.PlayableBeatmap); Child = new TimingScreen(); } } diff --git a/osu.Game/Audio/HitSampleInfo.cs b/osu.Game/Audio/HitSampleInfo.cs index 23a74d3fa6..f6b0107bd2 100644 --- a/osu.Game/Audio/HitSampleInfo.cs +++ b/osu.Game/Audio/HitSampleInfo.cs @@ -17,11 +17,6 @@ namespace osu.Game.Audio public const string HIT_NORMAL = @"hitnormal"; public const string HIT_CLAP = @"hitclap"; - /// - /// An optional ruleset namespace. - /// - public string Namespace; - /// /// The bank to load the sample from. /// @@ -49,15 +44,6 @@ namespace osu.Game.Audio { get { - if (!string.IsNullOrEmpty(Namespace)) - { - if (!string.IsNullOrEmpty(Suffix)) - yield return $"{Namespace}/{Bank}-{Name}{Suffix}"; - - yield return $"{Namespace}/{Bank}-{Name}"; - } - - // check non-namespace as a fallback even when we have a namespace if (!string.IsNullOrEmpty(Suffix)) yield return $"{Bank}-{Name}{Suffix}"; diff --git a/osu.Game/Rulesets/Edit/DrawableEditRulesetWrapper.cs b/osu.Game/Rulesets/Edit/DrawableEditRulesetWrapper.cs index 4710465536..89e7866707 100644 --- a/osu.Game/Rulesets/Edit/DrawableEditRulesetWrapper.cs +++ b/osu.Game/Rulesets/Edit/DrawableEditRulesetWrapper.cs @@ -22,7 +22,7 @@ namespace osu.Game.Rulesets.Edit private readonly DrawableRuleset drawableRuleset; [Resolved] - private IEditorBeatmap beatmap { get; set; } + private EditorBeatmap beatmap { get; set; } public DrawableEditRulesetWrapper(DrawableRuleset drawableRuleset) { diff --git a/osu.Game/Rulesets/Edit/HitObjectComposer.cs b/osu.Game/Rulesets/Edit/HitObjectComposer.cs index 22d94abcb9..bfaa7e8872 100644 --- a/osu.Game/Rulesets/Edit/HitObjectComposer.cs +++ b/osu.Game/Rulesets/Edit/HitObjectComposer.cs @@ -6,7 +6,6 @@ using System.Collections.Generic; using System.Linq; using JetBrains.Annotations; using osu.Framework.Allocation; -using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Input; @@ -35,20 +34,20 @@ namespace osu.Game.Rulesets.Edit { protected IRulesetConfigManager Config { get; private set; } - protected new EditorBeatmap EditorBeatmap { get; private set; } - protected readonly Ruleset Ruleset; [Resolved] protected IFrameBasedClock EditorClock { get; private set; } + [Resolved] + protected EditorBeatmap EditorBeatmap { get; private set; } + [Resolved] private IAdjustableClock adjustableClock { get; set; } [Resolved] private BindableBeatDivisor beatDivisor { get; set; } - private Beatmap playableBeatmap; private IBeatmapProcessor beatmapProcessor; private DrawableEditRulesetWrapper drawableRulesetWrapper; @@ -68,9 +67,17 @@ namespace osu.Game.Rulesets.Edit [BackgroundDependencyLoader] private void load(IFrameBasedClock framedClock) { + beatmapProcessor = Ruleset.CreateBeatmapProcessor(EditorBeatmap.PlayableBeatmap); + + EditorBeatmap.HitObjectAdded += addHitObject; + EditorBeatmap.HitObjectRemoved += removeHitObject; + EditorBeatmap.StartTimeChanged += UpdateHitObject; + + Config = Dependencies.Get().GetConfigFor(Ruleset); + try { - drawableRulesetWrapper = new DrawableEditRulesetWrapper(CreateDrawableRuleset(Ruleset, playableBeatmap)) + drawableRulesetWrapper = new DrawableEditRulesetWrapper(CreateDrawableRuleset(Ruleset, EditorBeatmap.PlayableBeatmap)) { Clock = framedClock, ProcessCustomClock = false @@ -140,28 +147,6 @@ namespace osu.Game.Rulesets.Edit blueprintContainer.SelectionChanged += selectionChanged; } - protected override IReadOnlyDependencyContainer CreateChildDependencies(IReadOnlyDependencyContainer parent) - { - var parentWorkingBeatmap = parent.Get>().Value; - - playableBeatmap = (Beatmap)parentWorkingBeatmap.GetPlayableBeatmap(Ruleset.RulesetInfo); - - beatmapProcessor = Ruleset.CreateBeatmapProcessor(playableBeatmap); - - base.EditorBeatmap = EditorBeatmap = new EditorBeatmap(playableBeatmap); - EditorBeatmap.HitObjectAdded += addHitObject; - EditorBeatmap.HitObjectRemoved += removeHitObject; - EditorBeatmap.StartTimeChanged += UpdateHitObject; - - var dependencies = new DependencyContainer(parent); - dependencies.CacheAs(EditorBeatmap); - dependencies.CacheAs>(EditorBeatmap); - - Config = dependencies.Get().GetConfigFor(Ruleset); - - return base.CreateChildDependencies(dependencies); - } - protected override void LoadComplete() { base.LoadComplete(); @@ -234,7 +219,7 @@ namespace osu.Game.Rulesets.Edit scheduledUpdate = Schedule(() => { beatmapProcessor?.PreProcess(); - hitObject?.ApplyDefaults(playableBeatmap.ControlPointInfo, playableBeatmap.BeatmapInfo.BaseDifficulty); + hitObject?.ApplyDefaults(EditorBeatmap.ControlPointInfo, EditorBeatmap.BeatmapInfo.BaseDifficulty); beatmapProcessor?.PostProcess(); }); } @@ -333,11 +318,6 @@ namespace osu.Game.Rulesets.Edit /// public abstract IEnumerable HitObjects { get; } - /// - /// An editor-specific beatmap, exposing mutation events. - /// - public IEditorBeatmap EditorBeatmap { get; protected set; } - /// /// Whether the user's cursor is currently in an area of the that is valid for placement. /// diff --git a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs index a959fee9be..4ac30fe7fb 100644 --- a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs +++ b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs @@ -31,9 +31,6 @@ namespace osu.Game.Rulesets.Objects.Drawables /// public readonly Bindable AccentColour = new Bindable(Color4.Gray); - // Todo: Rulesets should be overriding the resources instead, but we need to figure out where/when to apply overrides first - protected virtual string SampleNamespace => null; - protected SkinnableSound Samples { get; private set; } protected virtual IEnumerable GetSamples() => HitObject.Samples; @@ -154,11 +151,7 @@ namespace osu.Game.Rulesets.Objects.Drawables + $" This is an indication that {nameof(HitObject.ApplyDefaults)} has not been invoked on {this}."); } - samples = samples.Select(s => HitObject.SampleControlPoint.ApplyTo(s)).ToArray(); - foreach (var s in samples) - s.Namespace = SampleNamespace; - - AddInternal(Samples = new SkinnableSound(samples)); + AddInternal(Samples = new SkinnableSound(samples.Select(s => HitObject.SampleControlPoint.ApplyTo(s)))); } private void onDefaultsApplied() => apply(HitObject); diff --git a/osu.Game/Screens/Edit/Compose/Components/BlueprintContainer.cs b/osu.Game/Screens/Edit/Compose/Components/BlueprintContainer.cs index 195bc663f1..cafaddc39e 100644 --- a/osu.Game/Screens/Edit/Compose/Components/BlueprintContainer.cs +++ b/osu.Game/Screens/Edit/Compose/Components/BlueprintContainer.cs @@ -40,7 +40,7 @@ namespace osu.Game.Screens.Edit.Compose.Components private HitObjectComposer composer { get; set; } [Resolved] - private IEditorBeatmap beatmap { get; set; } + private EditorBeatmap beatmap { get; set; } public BlueprintContainer() { diff --git a/osu.Game/Screens/Edit/Compose/Components/DistanceSnapGrid.cs b/osu.Game/Screens/Edit/Compose/Components/DistanceSnapGrid.cs index 00326d04f7..53c5cf97fa 100644 --- a/osu.Game/Screens/Edit/Compose/Components/DistanceSnapGrid.cs +++ b/osu.Game/Screens/Edit/Compose/Components/DistanceSnapGrid.cs @@ -45,7 +45,7 @@ namespace osu.Game.Screens.Edit.Compose.Components protected IDistanceSnapProvider SnapProvider { get; private set; } [Resolved] - private IEditorBeatmap beatmap { get; set; } + private EditorBeatmap beatmap { get; set; } [Resolved] private BindableBeatDivisor beatDivisor { get; set; } diff --git a/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineHitObjectDisplay.cs b/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineHitObjectDisplay.cs index db4aca75e5..b20f2fa11d 100644 --- a/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineHitObjectDisplay.cs +++ b/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineHitObjectDisplay.cs @@ -16,9 +16,9 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline { internal class TimelineHitObjectDisplay : TimelinePart { - private IEditorBeatmap beatmap { get; } + private EditorBeatmap beatmap { get; } - public TimelineHitObjectDisplay(IEditorBeatmap beatmap) + public TimelineHitObjectDisplay(EditorBeatmap beatmap) { RelativeSizeAxes = Axes.Both; diff --git a/osu.Game/Screens/Edit/Compose/ComposeScreen.cs b/osu.Game/Screens/Edit/Compose/ComposeScreen.cs index 5d9757778d..1a6aae294a 100644 --- a/osu.Game/Screens/Edit/Compose/ComposeScreen.cs +++ b/osu.Game/Screens/Edit/Compose/ComposeScreen.cs @@ -32,6 +32,6 @@ namespace osu.Game.Screens.Edit.Compose return beatmapSkinProvider.WithChild(rulesetSkinProvider.WithChild(composer)); } - protected override Drawable CreateTimelineContent() => composer == null ? base.CreateTimelineContent() : new TimelineHitObjectDisplay(composer.EditorBeatmap); + protected override Drawable CreateTimelineContent() => composer == null ? base.CreateTimelineContent() : new TimelineHitObjectDisplay(EditorBeatmap); } } diff --git a/osu.Game/Screens/Edit/Editor.cs b/osu.Game/Screens/Edit/Editor.cs index 1b4964c068..14d69cddd1 100644 --- a/osu.Game/Screens/Edit/Editor.cs +++ b/osu.Game/Screens/Edit/Editor.cs @@ -23,6 +23,7 @@ using osuTK.Input; using System.Collections.Generic; using osu.Framework; using osu.Framework.Input.Bindings; +using osu.Game.Beatmaps; using osu.Game.Graphics.Cursor; using osu.Game.Input.Bindings; using osu.Game.Screens.Edit.Compose; @@ -49,9 +50,11 @@ namespace osu.Game.Screens.Edit private EditorScreen currentScreen; private readonly BindableBeatDivisor beatDivisor = new BindableBeatDivisor(); - private EditorClock clock; + private IBeatmap playableBeatmap; + private EditorBeatmap editorBeatmap; + private DependencyContainer dependencies; private GameHost host; @@ -73,9 +76,13 @@ namespace osu.Game.Screens.Edit clock = new EditorClock(Beatmap.Value, beatDivisor) { IsCoupled = false }; clock.ChangeSource(sourceClock); + playableBeatmap = Beatmap.Value.GetPlayableBeatmap(Beatmap.Value.BeatmapInfo.Ruleset); + editorBeatmap = new EditorBeatmap(playableBeatmap); + dependencies.CacheAs(clock); dependencies.CacheAs(clock); dependencies.Cache(beatDivisor); + dependencies.CacheAs(editorBeatmap); EditorMenuBar menuBar; diff --git a/osu.Game/Screens/Edit/EditorBeatmap.cs b/osu.Game/Screens/Edit/EditorBeatmap.cs index c3a322ea36..6ed74dfdb0 100644 --- a/osu.Game/Screens/Edit/EditorBeatmap.cs +++ b/osu.Game/Screens/Edit/EditorBeatmap.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 osu.Framework.Bindables; using osu.Game.Beatmaps; @@ -11,30 +12,30 @@ using osu.Game.Rulesets.Objects; namespace osu.Game.Screens.Edit { - public class EditorBeatmap : IEditorBeatmap - where T : HitObject + public class EditorBeatmap : IBeatmap { /// - /// Invoked when a is added to this . + /// Invoked when a is added to this . /// public event Action HitObjectAdded; /// - /// Invoked when a is removed from this . + /// Invoked when a is removed from this . /// public event Action HitObjectRemoved; /// - /// Invoked when the start time of a in this was changed. + /// Invoked when the start time of a in this was changed. /// public event Action StartTimeChanged; - private readonly Dictionary> startTimeBindables = new Dictionary>(); - private readonly Beatmap beatmap; + public readonly IBeatmap PlayableBeatmap; - public EditorBeatmap(Beatmap beatmap) + private readonly Dictionary> startTimeBindables = new Dictionary>(); + + public EditorBeatmap(IBeatmap playableBeatmap) { - this.beatmap = beatmap; + PlayableBeatmap = playableBeatmap; foreach (var obj in HitObjects) trackStartTime(obj); @@ -42,82 +43,83 @@ namespace osu.Game.Screens.Edit public BeatmapInfo BeatmapInfo { - get => beatmap.BeatmapInfo; - set => beatmap.BeatmapInfo = value; + get => PlayableBeatmap.BeatmapInfo; + set => PlayableBeatmap.BeatmapInfo = value; } - public BeatmapMetadata Metadata => beatmap.Metadata; + public BeatmapMetadata Metadata => PlayableBeatmap.Metadata; - public ControlPointInfo ControlPointInfo => beatmap.ControlPointInfo; + public ControlPointInfo ControlPointInfo => PlayableBeatmap.ControlPointInfo; - public List Breaks => beatmap.Breaks; + public List Breaks => PlayableBeatmap.Breaks; - public double TotalBreakTime => beatmap.TotalBreakTime; + public double TotalBreakTime => PlayableBeatmap.TotalBreakTime; - public IReadOnlyList HitObjects => beatmap.HitObjects; + public IReadOnlyList HitObjects => PlayableBeatmap.HitObjects; - IReadOnlyList IBeatmap.HitObjects => beatmap.HitObjects; + public IEnumerable GetStatistics() => PlayableBeatmap.GetStatistics(); - public IEnumerable GetStatistics() => beatmap.GetStatistics(); + public IBeatmap Clone() => (EditorBeatmap)MemberwiseClone(); - public IBeatmap Clone() => (EditorBeatmap)MemberwiseClone(); + private IList mutableHitObjects => (IList)PlayableBeatmap.HitObjects; /// - /// Adds a to this . + /// Adds a to this . /// /// The to add. - public void Add(T hitObject) + public void Add(HitObject hitObject) { trackStartTime(hitObject); // Preserve existing sorting order in the beatmap - var insertionIndex = beatmap.HitObjects.FindLastIndex(h => h.StartTime <= hitObject.StartTime); - beatmap.HitObjects.Insert(insertionIndex + 1, hitObject); + var insertionIndex = findInsertionIndex(PlayableBeatmap.HitObjects, hitObject.StartTime); + mutableHitObjects.Insert(insertionIndex + 1, hitObject); HitObjectAdded?.Invoke(hitObject); } /// - /// Removes a from this . + /// Removes a from this . /// /// The to add. - public void Remove(T hitObject) + public void Remove(HitObject hitObject) { - if (beatmap.HitObjects.Remove(hitObject)) - { - var bindable = startTimeBindables[hitObject]; - bindable.UnbindAll(); + if (!mutableHitObjects.Contains(hitObject)) + return; - startTimeBindables.Remove(hitObject); - HitObjectRemoved?.Invoke(hitObject); - } + mutableHitObjects.Remove(hitObject); + + var bindable = startTimeBindables[hitObject]; + bindable.UnbindAll(); + + startTimeBindables.Remove(hitObject); + HitObjectRemoved?.Invoke(hitObject); } - private void trackStartTime(T hitObject) + private void trackStartTime(HitObject hitObject) { startTimeBindables[hitObject] = hitObject.StartTimeBindable.GetBoundCopy(); startTimeBindables[hitObject].ValueChanged += _ => { // For now we'll remove and re-add the hitobject. This is not optimal and can be improved if required. - beatmap.HitObjects.Remove(hitObject); + mutableHitObjects.Remove(hitObject); - var insertionIndex = beatmap.HitObjects.FindLastIndex(h => h.StartTime <= hitObject.StartTime); - beatmap.HitObjects.Insert(insertionIndex + 1, hitObject); + var insertionIndex = findInsertionIndex(PlayableBeatmap.HitObjects, hitObject.StartTime); + mutableHitObjects.Insert(insertionIndex + 1, hitObject); StartTimeChanged?.Invoke(hitObject); }; } - /// - /// Adds a to this . - /// - /// The to add. - public void Add(HitObject hitObject) => Add((T)hitObject); + private int findInsertionIndex(IReadOnlyList list, double startTime) + { + for (int i = 0; i < list.Count; i++) + { + if (list[i].StartTime > startTime) + return i - 1; + } - /// - /// Removes a from this . - /// - /// The to add. - public void Remove(HitObject hitObject) => Remove((T)hitObject); + return list.Count - 1; + } } } diff --git a/osu.Game/Screens/Edit/EditorScreen.cs b/osu.Game/Screens/Edit/EditorScreen.cs index 1b57c703ae..d42447ac4b 100644 --- a/osu.Game/Screens/Edit/EditorScreen.cs +++ b/osu.Game/Screens/Edit/EditorScreen.cs @@ -17,6 +17,9 @@ namespace osu.Game.Screens.Edit [Resolved] protected IBindable Beatmap { get; private set; } + [Resolved] + protected EditorBeatmap EditorBeatmap { get; private set; } + protected override Container Content => content; private readonly Container content; diff --git a/osu.Game/Screens/Edit/IEditorBeatmap.cs b/osu.Game/Screens/Edit/IEditorBeatmap.cs deleted file mode 100644 index 3e3418ef79..0000000000 --- a/osu.Game/Screens/Edit/IEditorBeatmap.cs +++ /dev/null @@ -1,41 +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 osu.Game.Beatmaps; -using osu.Game.Rulesets.Edit; -using osu.Game.Rulesets.Objects; - -namespace osu.Game.Screens.Edit -{ - /// - /// Interface for the contained by the see . - /// Children of may resolve the beatmap via or . - /// - public interface IEditorBeatmap : IBeatmap - { - /// - /// Invoked when a is added to this . - /// - event Action HitObjectAdded; - - /// - /// Invoked when a is removed from this . - /// - event Action HitObjectRemoved; - - /// - /// Invoked when the start time of a in this was changed. - /// - event Action StartTimeChanged; - } - - /// - /// Interface for the contained by the see . - /// Children of may resolve the beatmap via or . - /// - public interface IEditorBeatmap : IEditorBeatmap, IBeatmap - where T : HitObject - { - } -} diff --git a/osu.Game/Skinning/LegacySkin.cs b/osu.Game/Skinning/LegacySkin.cs index 48c520986a..671d37fda4 100644 --- a/osu.Game/Skinning/LegacySkin.cs +++ b/osu.Game/Skinning/LegacySkin.cs @@ -175,7 +175,7 @@ namespace osu.Game.Skinning { foreach (var lookup in sampleInfo.LookupNames) { - var sample = Samples?.Get(getFallbackName(lookup)); + var sample = Samples?.Get(lookup); if (sample != null) return sample; diff --git a/osu.Game/Tests/Visual/OsuTestScene.cs b/osu.Game/Tests/Visual/OsuTestScene.cs index 18dbd212cc..8926c76018 100644 --- a/osu.Game/Tests/Visual/OsuTestScene.cs +++ b/osu.Game/Tests/Visual/OsuTestScene.cs @@ -105,7 +105,7 @@ namespace osu.Game.Tests.Visual } [Resolved] - private AudioManager audio { get; set; } + protected AudioManager Audio { get; private set; } protected virtual IBeatmap CreateBeatmap(RulesetInfo ruleset) => new TestBeatmap(ruleset); @@ -113,7 +113,7 @@ namespace osu.Game.Tests.Visual CreateWorkingBeatmap(CreateBeatmap(ruleset), null); protected virtual WorkingBeatmap CreateWorkingBeatmap(IBeatmap beatmap, Storyboard storyboard = null) => - new ClockBackedTestWorkingBeatmap(beatmap, storyboard, Clock, audio); + new ClockBackedTestWorkingBeatmap(beatmap, storyboard, Clock, Audio); [BackgroundDependencyLoader] private void load(RulesetStore rulesets)