mirror of
https://github.com/ppy/osu.git
synced 2025-01-28 02:43:19 +08:00
Merge branch 'master' into fix-tags-overflow
This commit is contained in:
commit
2a127c6ef8
@ -21,7 +21,11 @@ namespace osu.Desktop
|
||||
{
|
||||
public static class Program
|
||||
{
|
||||
#if DEBUG
|
||||
private const string base_game_name = @"osu-development";
|
||||
#else
|
||||
private const string base_game_name = @"osu";
|
||||
#endif
|
||||
|
||||
private static LegacyTcpIpcProvider legacyIpc;
|
||||
|
||||
|
@ -1,8 +1,6 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
#nullable disable
|
||||
|
||||
using osu.Game.Tests.Visual;
|
||||
|
||||
namespace osu.Game.Rulesets.Osu.Tests.Mods
|
||||
|
@ -1,8 +1,6 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
#nullable disable
|
||||
|
||||
using System.Collections.Generic;
|
||||
using NUnit.Framework;
|
||||
using osu.Game.Beatmaps;
|
||||
|
@ -1,10 +1,9 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
#nullable disable
|
||||
|
||||
using System.Linq;
|
||||
using NUnit.Framework;
|
||||
using osu.Framework.Extensions.ObjectExtensions;
|
||||
using osu.Framework.Testing;
|
||||
using osu.Framework.Utils;
|
||||
using osu.Game.Beatmaps;
|
||||
@ -35,7 +34,7 @@ namespace osu.Game.Rulesets.Osu.Tests.Mods
|
||||
|
||||
private void runSpmTest(Mod mod)
|
||||
{
|
||||
SpinnerSpmCalculator spmCalculator = null;
|
||||
SpinnerSpmCalculator? spmCalculator = null;
|
||||
|
||||
CreateModTest(new ModTestData
|
||||
{
|
||||
@ -61,7 +60,7 @@ namespace osu.Game.Rulesets.Osu.Tests.Mods
|
||||
return spmCalculator != null;
|
||||
});
|
||||
|
||||
AddUntilStep("SPM is correct", () => Precision.AlmostEquals(spmCalculator.Result.Value, 477, 5));
|
||||
AddUntilStep("SPM is correct", () => Precision.AlmostEquals(spmCalculator.AsNonNull().Result.Value, 477, 5));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,8 +1,6 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
#nullable disable
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using NUnit.Framework;
|
||||
|
@ -1,8 +1,6 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
#nullable disable
|
||||
|
||||
using NUnit.Framework;
|
||||
using osu.Framework.Utils;
|
||||
using osu.Game.Rulesets.Osu.Mods;
|
||||
|
@ -1,8 +1,6 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
#nullable disable
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using NUnit.Framework;
|
||||
@ -162,7 +160,7 @@ namespace osu.Game.Rulesets.Osu.Tests.Mods
|
||||
|
||||
private class TestOsuModHidden : OsuModHidden
|
||||
{
|
||||
public new HitObject FirstObject => base.FirstObject;
|
||||
public new HitObject? FirstObject => base.FirstObject;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,8 +1,6 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
#nullable disable
|
||||
|
||||
using NUnit.Framework;
|
||||
using osu.Game.Rulesets.Osu.Mods;
|
||||
|
||||
|
@ -1,8 +1,6 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
#nullable disable
|
||||
|
||||
using System.Linq;
|
||||
using NUnit.Framework;
|
||||
using osu.Framework.Testing;
|
||||
@ -33,7 +31,7 @@ namespace osu.Game.Rulesets.Osu.Tests.Mods
|
||||
[Test]
|
||||
public void TestModCopy()
|
||||
{
|
||||
OsuModMuted muted = null;
|
||||
OsuModMuted muted = null!;
|
||||
|
||||
AddStep("create inversed mod", () => muted = new OsuModMuted
|
||||
{
|
||||
|
@ -1,8 +1,6 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
#nullable disable
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using NUnit.Framework;
|
||||
|
@ -1,8 +1,6 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
#nullable disable
|
||||
|
||||
using NUnit.Framework;
|
||||
using osu.Game.Rulesets.Objects;
|
||||
using osu.Game.Rulesets.Objects.Types;
|
||||
|
@ -1,8 +1,6 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
#nullable disable
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
@ -30,8 +28,8 @@ namespace osu.Game.Rulesets.Osu.Tests.Mods
|
||||
[Test]
|
||||
public void TestSpinnerAutoCompleted()
|
||||
{
|
||||
DrawableSpinner spinner = null;
|
||||
JudgementResult lastResult = null;
|
||||
DrawableSpinner? spinner = null;
|
||||
JudgementResult? lastResult = null;
|
||||
|
||||
CreateModTest(new ModTestData
|
||||
{
|
||||
@ -63,11 +61,11 @@ namespace osu.Game.Rulesets.Osu.Tests.Mods
|
||||
[TestCase(null)]
|
||||
[TestCase(typeof(OsuModDoubleTime))]
|
||||
[TestCase(typeof(OsuModHalfTime))]
|
||||
public void TestSpinRateUnaffectedByMods(Type additionalModType)
|
||||
public void TestSpinRateUnaffectedByMods(Type? additionalModType)
|
||||
{
|
||||
var mods = new List<Mod> { new OsuModSpunOut() };
|
||||
if (additionalModType != null)
|
||||
mods.Add((Mod)Activator.CreateInstance(additionalModType));
|
||||
mods.Add((Mod)Activator.CreateInstance(additionalModType)!);
|
||||
|
||||
CreateModTest(new ModTestData
|
||||
{
|
||||
@ -96,7 +94,7 @@ namespace osu.Game.Rulesets.Osu.Tests.Mods
|
||||
[Test]
|
||||
public void TestSpinnerGetsNoBonusScore()
|
||||
{
|
||||
DrawableSpinner spinner = null;
|
||||
DrawableSpinner? spinner = null;
|
||||
List<JudgementResult> results = new List<JudgementResult>();
|
||||
|
||||
CreateModTest(new ModTestData
|
||||
|
@ -1,8 +1,6 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace osu.Game.Rulesets.Osu.Mods
|
||||
{
|
||||
/// <summary>
|
||||
|
@ -1,8 +1,6 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace osu.Game.Rulesets.Osu.Mods
|
||||
{
|
||||
/// <summary>
|
||||
|
@ -1,8 +1,6 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
#nullable disable
|
||||
|
||||
using System;
|
||||
using osu.Framework.Bindables;
|
||||
using osu.Framework.Graphics;
|
||||
|
@ -1,8 +1,6 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
#nullable disable
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
@ -30,11 +28,11 @@ namespace osu.Game.Rulesets.Osu.Mods
|
||||
|
||||
public bool RestartOnFail => false;
|
||||
|
||||
private OsuInputManager inputManager;
|
||||
private OsuInputManager inputManager = null!;
|
||||
|
||||
private IFrameStableClock gameplayClock;
|
||||
private IFrameStableClock gameplayClock = null!;
|
||||
|
||||
private List<OsuReplayFrame> replayFrames;
|
||||
private List<OsuReplayFrame> replayFrames = null!;
|
||||
|
||||
private int currentFrame;
|
||||
|
||||
|
@ -1,8 +1,6 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
#nullable disable
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
@ -1,8 +1,6 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
#nullable disable
|
||||
|
||||
using osu.Game.Rulesets.Mods;
|
||||
using osu.Game.Rulesets.Objects.Drawables;
|
||||
using osu.Game.Rulesets.Osu.Objects;
|
||||
|
@ -1,8 +1,6 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
#nullable disable
|
||||
|
||||
using System;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Graphics;
|
||||
@ -33,7 +31,7 @@ namespace osu.Game.Rulesets.Osu.Mods
|
||||
public override double ScoreMultiplier => UsesDefaultConfiguration ? 1.12 : 1;
|
||||
public override Type[] IncompatibleMods => new[] { typeof(OsuModFlashlight) };
|
||||
|
||||
private DrawableOsuBlinds blinds;
|
||||
private DrawableOsuBlinds blinds = null!;
|
||||
|
||||
public void ApplyToDrawableRuleset(DrawableRuleset<OsuHitObject> drawableRuleset)
|
||||
{
|
||||
@ -55,9 +53,12 @@ namespace osu.Game.Rulesets.Osu.Mods
|
||||
/// <summary>
|
||||
/// Black background boxes behind blind panel textures.
|
||||
/// </summary>
|
||||
private Box blackBoxLeft, blackBoxRight;
|
||||
private Box blackBoxLeft = null!, blackBoxRight = null!;
|
||||
|
||||
private Drawable panelLeft, panelRight, bgPanelLeft, bgPanelRight;
|
||||
private Drawable panelLeft = null!;
|
||||
private Drawable panelRight = null!;
|
||||
private Drawable bgPanelLeft = null!;
|
||||
private Drawable bgPanelRight = null!;
|
||||
|
||||
private readonly Beatmap<OsuHitObject> beatmap;
|
||||
|
||||
|
@ -1,8 +1,6 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
#nullable disable
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
@ -1,8 +1,6 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
#nullable disable
|
||||
|
||||
using System;
|
||||
using System.Linq;
|
||||
using osu.Framework.Bindables;
|
||||
|
@ -1,8 +1,6 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
#nullable disable
|
||||
|
||||
using osu.Game.Rulesets.Mods;
|
||||
|
||||
namespace osu.Game.Rulesets.Osu.Mods
|
||||
|
@ -1,8 +1,6 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
#nullable disable
|
||||
|
||||
using osu.Framework.Bindables;
|
||||
using osu.Framework.Graphics.Sprites;
|
||||
using osu.Game.Configuration;
|
||||
|
@ -1,8 +1,6 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
#nullable disable
|
||||
|
||||
using System.Linq;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Configuration;
|
||||
|
@ -1,8 +1,6 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
#nullable disable
|
||||
|
||||
using osu.Game.Rulesets.Mods;
|
||||
|
||||
namespace osu.Game.Rulesets.Osu.Mods
|
||||
|
@ -1,8 +1,6 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
#nullable disable
|
||||
|
||||
using osu.Game.Rulesets.Mods;
|
||||
|
||||
namespace osu.Game.Rulesets.Osu.Mods
|
||||
|
@ -1,8 +1,6 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
#nullable disable
|
||||
|
||||
using System;
|
||||
using System.Linq;
|
||||
using osu.Framework.Bindables;
|
||||
@ -53,7 +51,7 @@ namespace osu.Game.Rulesets.Osu.Mods
|
||||
|
||||
public override float DefaultFlashlightSize => 180;
|
||||
|
||||
private OsuFlashlight flashlight;
|
||||
private OsuFlashlight flashlight = null!;
|
||||
|
||||
protected override Flashlight CreateFlashlight() => flashlight = new OsuFlashlight(this);
|
||||
|
||||
|
@ -1,8 +1,6 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
#nullable disable
|
||||
|
||||
using osu.Framework.Bindables;
|
||||
using osu.Framework.Graphics.Sprites;
|
||||
using osu.Game.Configuration;
|
||||
|
@ -1,8 +1,6 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
#nullable disable
|
||||
|
||||
using osu.Game.Rulesets.Mods;
|
||||
|
||||
namespace osu.Game.Rulesets.Osu.Mods
|
||||
|
@ -1,8 +1,6 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
#nullable disable
|
||||
|
||||
using System;
|
||||
using System.Linq;
|
||||
using osu.Game.Rulesets.Mods;
|
||||
|
@ -1,8 +1,6 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
#nullable disable
|
||||
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
|
@ -1,8 +1,6 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
#nullable disable
|
||||
|
||||
using System;
|
||||
using osu.Framework.Bindables;
|
||||
using osu.Framework.Graphics.Sprites;
|
||||
@ -28,7 +26,7 @@ namespace osu.Game.Rulesets.Osu.Mods
|
||||
public override double ScoreMultiplier => 1;
|
||||
public override Type[] IncompatibleMods => new[] { typeof(OsuModAutopilot), typeof(OsuModWiggle), typeof(OsuModTransform), typeof(ModAutoplay), typeof(OsuModRelax), typeof(OsuModRepel) };
|
||||
|
||||
private IFrameStableClock gameplayClock;
|
||||
private IFrameStableClock gameplayClock = null!;
|
||||
|
||||
[SettingSource("Attraction strength", "How strong the pull is.", 0)]
|
||||
public BindableFloat AttractionStrength { get; } = new BindableFloat(0.5f)
|
||||
|
@ -1,8 +1,6 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
#nullable disable
|
||||
|
||||
using System;
|
||||
using osu.Framework.Bindables;
|
||||
using osu.Game.Configuration;
|
||||
|
@ -1,8 +1,6 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
#nullable disable
|
||||
|
||||
using osu.Game.Rulesets.Mods;
|
||||
using osu.Game.Rulesets.Osu.Objects;
|
||||
|
||||
|
@ -1,8 +1,6 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
#nullable disable
|
||||
|
||||
using osu.Game.Rulesets.Mods;
|
||||
using osu.Game.Rulesets.Osu.Objects;
|
||||
|
||||
|
@ -1,8 +1,6 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
#nullable disable
|
||||
|
||||
using System;
|
||||
using System.Linq;
|
||||
using osu.Game.Rulesets.Mods;
|
||||
|
@ -1,8 +1,6 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
#nullable disable
|
||||
|
||||
using System;
|
||||
using System.Linq;
|
||||
using osu.Framework.Bindables;
|
||||
@ -21,7 +19,7 @@ namespace osu.Game.Rulesets.Osu.Mods
|
||||
{
|
||||
public override string Description => "Where's the cursor?";
|
||||
|
||||
private PeriodTracker spinnerPeriods;
|
||||
private PeriodTracker spinnerPeriods = null!;
|
||||
|
||||
[SettingSource(
|
||||
"Hidden at combo",
|
||||
|
@ -1,8 +1,6 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
#nullable disable
|
||||
|
||||
using System;
|
||||
using osu.Framework.Bindables;
|
||||
using osu.Framework.Graphics;
|
||||
|
@ -1,8 +1,6 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
#nullable disable
|
||||
|
||||
using System;
|
||||
using System.Linq;
|
||||
using osu.Game.Rulesets.Mods;
|
||||
|
@ -1,8 +1,6 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
#nullable disable
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
@ -31,9 +29,9 @@ namespace osu.Game.Rulesets.Osu.Mods
|
||||
private bool isDownState;
|
||||
private bool wasLeft;
|
||||
|
||||
private OsuInputManager osuInputManager;
|
||||
private OsuInputManager osuInputManager = null!;
|
||||
|
||||
private ReplayState<OsuAction> state;
|
||||
private ReplayState<OsuAction> state = null!;
|
||||
private double lastStateChangeTime;
|
||||
|
||||
private bool hasReplay;
|
||||
@ -134,7 +132,7 @@ namespace osu.Game.Rulesets.Osu.Mods
|
||||
wasLeft = !wasLeft;
|
||||
}
|
||||
|
||||
state?.Apply(osuInputManager.CurrentState, osuInputManager);
|
||||
state.Apply(osuInputManager.CurrentState, osuInputManager);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,8 +1,6 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
#nullable disable
|
||||
|
||||
using System;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Sprites;
|
||||
|
@ -1,8 +1,6 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
#nullable disable
|
||||
|
||||
using System;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Sprites;
|
||||
|
@ -1,8 +1,6 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
#nullable disable
|
||||
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
|
@ -1,8 +1,6 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
#nullable disable
|
||||
|
||||
using System;
|
||||
using System.Linq;
|
||||
using osu.Game.Rulesets.Mods;
|
||||
|
@ -1,8 +1,6 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
#nullable disable
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
@ -96,11 +94,7 @@ namespace osu.Game.Rulesets.Osu.Mods
|
||||
|
||||
#region Private Fields
|
||||
|
||||
private ControlPointInfo controlPointInfo;
|
||||
|
||||
private List<OsuHitObject> originalHitObjects;
|
||||
|
||||
private Random rng;
|
||||
private ControlPointInfo controlPointInfo = null!;
|
||||
|
||||
#endregion
|
||||
|
||||
@ -171,16 +165,17 @@ namespace osu.Game.Rulesets.Osu.Mods
|
||||
public override void ApplyToBeatmap(IBeatmap beatmap)
|
||||
{
|
||||
Seed.Value ??= RNG.Next();
|
||||
rng = new Random(Seed.Value.Value);
|
||||
|
||||
var rng = new Random(Seed.Value.Value);
|
||||
|
||||
var osuBeatmap = (OsuBeatmap)beatmap;
|
||||
|
||||
if (osuBeatmap.HitObjects.Count == 0) return;
|
||||
|
||||
controlPointInfo = osuBeatmap.ControlPointInfo;
|
||||
originalHitObjects = osuBeatmap.HitObjects.OrderBy(x => x.StartTime).ToList();
|
||||
|
||||
var hitObjects = generateBeats(osuBeatmap)
|
||||
var originalHitObjects = osuBeatmap.HitObjects.OrderBy(x => x.StartTime).ToList();
|
||||
var hitObjects = generateBeats(osuBeatmap, originalHitObjects)
|
||||
.Select(beat =>
|
||||
{
|
||||
var newCircle = new HitCircle();
|
||||
@ -189,18 +184,18 @@ namespace osu.Game.Rulesets.Osu.Mods
|
||||
return (OsuHitObject)newCircle;
|
||||
}).ToList();
|
||||
|
||||
addHitSamples(hitObjects);
|
||||
addHitSamples(hitObjects, originalHitObjects);
|
||||
|
||||
fixComboInfo(hitObjects);
|
||||
fixComboInfo(hitObjects, originalHitObjects);
|
||||
|
||||
randomizeCirclePos(hitObjects);
|
||||
randomizeCirclePos(hitObjects, rng);
|
||||
|
||||
osuBeatmap.HitObjects = hitObjects;
|
||||
|
||||
base.ApplyToBeatmap(beatmap);
|
||||
}
|
||||
|
||||
private IEnumerable<double> generateBeats(IBeatmap beatmap)
|
||||
private IEnumerable<double> generateBeats(IBeatmap beatmap, IReadOnlyCollection<OsuHitObject> originalHitObjects)
|
||||
{
|
||||
double startTime = originalHitObjects.First().StartTime;
|
||||
double endTime = originalHitObjects.Last().GetEndTime();
|
||||
@ -213,7 +208,7 @@ namespace osu.Game.Rulesets.Osu.Mods
|
||||
// Remove beats before startTime
|
||||
.Where(beat => almostBigger(beat, startTime))
|
||||
// Remove beats during breaks
|
||||
.Where(beat => !isInsideBreakPeriod(beatmap.Breaks, beat))
|
||||
.Where(beat => !isInsideBreakPeriod(originalHitObjects, beatmap.Breaks, beat))
|
||||
.ToList();
|
||||
|
||||
// Remove beats that are too close to the next one (e.g. due to timing point changes)
|
||||
@ -228,7 +223,7 @@ namespace osu.Game.Rulesets.Osu.Mods
|
||||
return beats;
|
||||
}
|
||||
|
||||
private void addHitSamples(IEnumerable<OsuHitObject> hitObjects)
|
||||
private void addHitSamples(IEnumerable<OsuHitObject> hitObjects, List<OsuHitObject> originalHitObjects)
|
||||
{
|
||||
foreach (var obj in hitObjects)
|
||||
{
|
||||
@ -240,7 +235,7 @@ namespace osu.Game.Rulesets.Osu.Mods
|
||||
}
|
||||
}
|
||||
|
||||
private void fixComboInfo(List<OsuHitObject> hitObjects)
|
||||
private void fixComboInfo(List<OsuHitObject> hitObjects, List<OsuHitObject> originalHitObjects)
|
||||
{
|
||||
// Copy combo indices from an original object at the same time or from the closest preceding object
|
||||
// (Objects lying between two combos are assumed to belong to the preceding combo)
|
||||
@ -274,7 +269,7 @@ namespace osu.Game.Rulesets.Osu.Mods
|
||||
}
|
||||
}
|
||||
|
||||
private void randomizeCirclePos(IReadOnlyList<OsuHitObject> hitObjects)
|
||||
private void randomizeCirclePos(IReadOnlyList<OsuHitObject> hitObjects, Random rng)
|
||||
{
|
||||
if (hitObjects.Count == 0) return;
|
||||
|
||||
@ -355,9 +350,10 @@ namespace osu.Game.Rulesets.Osu.Mods
|
||||
/// The given time is also considered to be inside a break if it is earlier than the
|
||||
/// start time of the first original hit object after the break.
|
||||
/// </remarks>
|
||||
/// <param name="originalHitObjects">Hit objects order by time.</param>
|
||||
/// <param name="breaks">The breaks of the beatmap.</param>
|
||||
/// <param name="time">The time to be checked.</param>=
|
||||
private bool isInsideBreakPeriod(IEnumerable<BreakPeriod> breaks, double time)
|
||||
private bool isInsideBreakPeriod(IReadOnlyCollection<OsuHitObject> originalHitObjects, IEnumerable<BreakPeriod> breaks, double time)
|
||||
{
|
||||
return breaks.Any(breakPeriod =>
|
||||
{
|
||||
@ -405,7 +401,7 @@ namespace osu.Game.Rulesets.Osu.Mods
|
||||
/// <param name="hitObjects">The list of hit objects in a beatmap, ordered by StartTime</param>
|
||||
/// <param name="time">The point in time to get samples for</param>
|
||||
/// <returns>Hit samples</returns>
|
||||
private IList<HitSampleInfo> getSamplesAtTime(IEnumerable<OsuHitObject> hitObjects, double time)
|
||||
private IList<HitSampleInfo>? getSamplesAtTime(IEnumerable<OsuHitObject> hitObjects, double time)
|
||||
{
|
||||
// Get a hit object that
|
||||
// either has StartTime equal to the target time
|
||||
|
@ -1,8 +1,6 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
#nullable disable
|
||||
|
||||
using osu.Game.Rulesets.Mods;
|
||||
|
||||
namespace osu.Game.Rulesets.Osu.Mods
|
||||
|
@ -1,8 +1,6 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
#nullable disable
|
||||
|
||||
using System;
|
||||
using osu.Framework.Extensions.Color4Extensions;
|
||||
using osu.Framework.Graphics;
|
||||
@ -59,7 +57,7 @@ namespace osu.Game.Rulesets.Osu.Mods
|
||||
}
|
||||
}
|
||||
|
||||
private void applyCirclePieceState(DrawableOsuHitObject hitObject, IDrawable hitCircle = null)
|
||||
private void applyCirclePieceState(DrawableOsuHitObject hitObject, IDrawable? hitCircle = null)
|
||||
{
|
||||
var h = hitObject.HitObject;
|
||||
using (hitObject.BeginAbsoluteSequence(h.StartTime - h.TimePreempt))
|
||||
|
@ -1,8 +1,6 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
#nullable disable
|
||||
|
||||
using System;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Sprites;
|
||||
|
@ -1,8 +1,6 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
#nullable disable
|
||||
|
||||
using System;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Sprites;
|
||||
|
@ -1,8 +1,6 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
#nullable disable
|
||||
|
||||
using System.Reflection;
|
||||
using NUnit.Framework;
|
||||
using osu.Framework.IO.Stores;
|
||||
@ -17,7 +15,6 @@ namespace osu.Game.Rulesets.Taiko.Tests
|
||||
protected override IResourceStore<byte[]> RulesetResources => new DllResourceStore(Assembly.GetAssembly(typeof(TestSceneTaikoHitObjectSamples)));
|
||||
|
||||
[TestCase("taiko-normal-hitnormal")]
|
||||
[TestCase("normal-hitnormal")]
|
||||
[TestCase("hitnormal")]
|
||||
public void TestDefaultCustomSampleFromBeatmap(string expectedSample)
|
||||
{
|
||||
@ -29,7 +26,6 @@ namespace osu.Game.Rulesets.Taiko.Tests
|
||||
}
|
||||
|
||||
[TestCase("taiko-normal-hitnormal")]
|
||||
[TestCase("normal-hitnormal")]
|
||||
[TestCase("hitnormal")]
|
||||
public void TestDefaultCustomSampleFromUserSkinFallback(string expectedSample)
|
||||
{
|
||||
@ -41,7 +37,6 @@ namespace osu.Game.Rulesets.Taiko.Tests
|
||||
}
|
||||
|
||||
[TestCase("taiko-normal-hitnormal2")]
|
||||
[TestCase("normal-hitnormal2")]
|
||||
public void TestUserSkinLookupIgnoresSampleBank(string unwantedSample)
|
||||
{
|
||||
SetupSkins(string.Empty, unwantedSample);
|
||||
|
@ -1,8 +1,6 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
#nullable disable
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using osu.Framework.Audio.Sample;
|
||||
@ -24,7 +22,7 @@ namespace osu.Game.Rulesets.Taiko.Skinning.Legacy
|
||||
hasExplosion = new Lazy<bool>(() => GetTexture(getHitName(TaikoSkinComponents.TaikoExplosionGreat)) != null);
|
||||
}
|
||||
|
||||
public override Drawable GetDrawableComponent(ISkinComponent component)
|
||||
public override Drawable? GetDrawableComponent(ISkinComponent component)
|
||||
{
|
||||
if (component is GameplaySkinComponent<HitResult>)
|
||||
{
|
||||
@ -151,7 +149,7 @@ namespace osu.Game.Rulesets.Taiko.Skinning.Legacy
|
||||
throw new ArgumentOutOfRangeException(nameof(component), $"Invalid component type: {component}");
|
||||
}
|
||||
|
||||
public override ISample GetSample(ISampleInfo sampleInfo)
|
||||
public override ISample? GetSample(ISampleInfo sampleInfo)
|
||||
{
|
||||
if (sampleInfo is HitSampleInfo hitSampleInfo)
|
||||
return base.GetSample(new LegacyTaikoSampleInfo(hitSampleInfo));
|
||||
@ -173,9 +171,6 @@ namespace osu.Game.Rulesets.Taiko.Skinning.Legacy
|
||||
{
|
||||
foreach (string name in base.LookupNames)
|
||||
yield return name.Insert(name.LastIndexOf('/') + 1, "taiko-");
|
||||
|
||||
foreach (string name in base.LookupNames)
|
||||
yield return name;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -702,6 +702,8 @@ namespace osu.Game.Tests.Database
|
||||
var firstImport = await importer.Import(new ImportTask(pathMissingOneBeatmap));
|
||||
Assert.That(firstImport, Is.Not.Null);
|
||||
|
||||
realm.Run(r => r.Refresh());
|
||||
|
||||
Assert.That(realm.Realm.All<BeatmapSetInfo>().Where(s => !s.DeletePending), Has.Count.EqualTo(1));
|
||||
Assert.That(realm.Realm.All<BeatmapSetInfo>().First(s => !s.DeletePending).Beatmaps, Has.Count.EqualTo(11));
|
||||
|
||||
@ -709,6 +711,8 @@ namespace osu.Game.Tests.Database
|
||||
var secondImport = await importer.Import(new ImportTask(pathOriginal));
|
||||
Assert.That(secondImport, Is.Not.Null);
|
||||
|
||||
realm.Run(r => r.Refresh());
|
||||
|
||||
Assert.That(realm.Realm.All<BeatmapInfo>(), Has.Count.EqualTo(23));
|
||||
Assert.That(realm.Realm.All<BeatmapSetInfo>(), Has.Count.EqualTo(2));
|
||||
|
||||
|
BIN
osu.Game.Tests/Resources/Archives/modified-classic-20220723.osk
Normal file
BIN
osu.Game.Tests/Resources/Archives/modified-classic-20220723.osk
Normal file
Binary file not shown.
BIN
osu.Game.Tests/Resources/Archives/modified-classic-20220801.osk
Normal file
BIN
osu.Game.Tests/Resources/Archives/modified-classic-20220801.osk
Normal file
Binary file not shown.
BIN
osu.Game.Tests/Resources/Archives/modified-default-20220723.osk
Normal file
BIN
osu.Game.Tests/Resources/Archives/modified-default-20220723.osk
Normal file
Binary file not shown.
128
osu.Game.Tests/Skins/SkinDeserialisationTest.cs
Normal file
128
osu.Game.Tests/Skins/SkinDeserialisationTest.cs
Normal file
@ -0,0 +1,128 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. 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;
|
||||
using osu.Framework.Audio.Sample;
|
||||
using osu.Framework.Bindables;
|
||||
using osu.Framework.Graphics.OpenGL.Textures;
|
||||
using osu.Framework.Graphics.Textures;
|
||||
using osu.Framework.IO.Stores;
|
||||
using osu.Game.Audio;
|
||||
using osu.Game.IO;
|
||||
using osu.Game.IO.Archives;
|
||||
using osu.Game.Screens.Play.HUD;
|
||||
using osu.Game.Screens.Play.HUD.HitErrorMeters;
|
||||
using osu.Game.Skinning;
|
||||
using osu.Game.Tests.Resources;
|
||||
|
||||
namespace osu.Game.Tests.Skins
|
||||
{
|
||||
/// <summary>
|
||||
/// Test that the main components (which are serialised based on namespace/class name)
|
||||
/// remain compatible with any changes.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// If this test breaks, check any naming or class structure changes.
|
||||
/// Migration rules may need to be added to <see cref="Skin"/>.
|
||||
/// </remarks>
|
||||
[TestFixture]
|
||||
public class SkinDeserialisationTest
|
||||
{
|
||||
private static readonly string[] available_skins =
|
||||
{
|
||||
// Covers song progress before namespace changes, and most other components.
|
||||
"Archives/modified-default-20220723.osk",
|
||||
"Archives/modified-classic-20220723.osk",
|
||||
// Covers legacy song progress, UR counter, colour hit error metre.
|
||||
"Archives/modified-classic-20220801.osk"
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// If this test fails, new test resources should be added to include new components.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestSkinnableComponentsCoveredByDeserialisationTests()
|
||||
{
|
||||
HashSet<Type> instantiatedTypes = new HashSet<Type>();
|
||||
|
||||
foreach (string oskFile in available_skins)
|
||||
{
|
||||
using (var stream = TestResources.OpenResource(oskFile))
|
||||
using (var storage = new ZipArchiveReader(stream))
|
||||
{
|
||||
var skin = new TestSkin(new SkinInfo(), null, storage);
|
||||
|
||||
foreach (var target in skin.DrawableComponentInfo)
|
||||
{
|
||||
foreach (var info in target.Value)
|
||||
instantiatedTypes.Add(info.Type);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var editableTypes = SkinnableInfo.GetAllAvailableDrawables().Where(t => (Activator.CreateInstance(t) as ISkinnableDrawable)?.IsEditable == true);
|
||||
|
||||
Assert.That(instantiatedTypes, Is.EquivalentTo(editableTypes));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestDeserialiseModifiedDefault()
|
||||
{
|
||||
using (var stream = TestResources.OpenResource("Archives/modified-default-20220723.osk"))
|
||||
using (var storage = new ZipArchiveReader(stream))
|
||||
{
|
||||
var skin = new TestSkin(new SkinInfo(), null, storage);
|
||||
|
||||
Assert.That(skin.DrawableComponentInfo, Has.Count.EqualTo(2));
|
||||
Assert.That(skin.DrawableComponentInfo[SkinnableTarget.MainHUDComponents], Has.Length.EqualTo(9));
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestDeserialiseModifiedClassic()
|
||||
{
|
||||
using (var stream = TestResources.OpenResource("Archives/modified-classic-20220723.osk"))
|
||||
using (var storage = new ZipArchiveReader(stream))
|
||||
{
|
||||
var skin = new TestSkin(new SkinInfo(), null, storage);
|
||||
|
||||
Assert.That(skin.DrawableComponentInfo, Has.Count.EqualTo(2));
|
||||
Assert.That(skin.DrawableComponentInfo[SkinnableTarget.MainHUDComponents], Has.Length.EqualTo(6));
|
||||
Assert.That(skin.DrawableComponentInfo[SkinnableTarget.SongSelect], Has.Length.EqualTo(1));
|
||||
|
||||
var skinnableInfo = skin.DrawableComponentInfo[SkinnableTarget.SongSelect].First();
|
||||
|
||||
Assert.That(skinnableInfo.Type, Is.EqualTo(typeof(SkinnableSprite)));
|
||||
Assert.That(skinnableInfo.Settings.First().Key, Is.EqualTo("sprite_name"));
|
||||
Assert.That(skinnableInfo.Settings.First().Value, Is.EqualTo("ppy_logo-2.png"));
|
||||
}
|
||||
|
||||
using (var stream = TestResources.OpenResource("Archives/modified-classic-20220801.osk"))
|
||||
using (var storage = new ZipArchiveReader(stream))
|
||||
{
|
||||
var skin = new TestSkin(new SkinInfo(), null, storage);
|
||||
Assert.That(skin.DrawableComponentInfo[SkinnableTarget.MainHUDComponents], Has.Length.EqualTo(8));
|
||||
Assert.That(skin.DrawableComponentInfo[SkinnableTarget.MainHUDComponents].Select(i => i.Type), Contains.Item(typeof(UnstableRateCounter)));
|
||||
Assert.That(skin.DrawableComponentInfo[SkinnableTarget.MainHUDComponents].Select(i => i.Type), Contains.Item(typeof(ColourHitErrorMeter)));
|
||||
Assert.That(skin.DrawableComponentInfo[SkinnableTarget.MainHUDComponents].Select(i => i.Type), Contains.Item(typeof(LegacySongProgress)));
|
||||
}
|
||||
}
|
||||
|
||||
private class TestSkin : Skin
|
||||
{
|
||||
public TestSkin(SkinInfo skin, IStorageResourceProvider? resources, IResourceStore<byte[]>? storage = null, string configurationFilename = "skin.ini")
|
||||
: base(skin, resources, storage, configurationFilename)
|
||||
{
|
||||
}
|
||||
|
||||
public override Texture GetTexture(string componentName, WrapMode wrapModeS, WrapMode wrapModeT) => throw new NotImplementedException();
|
||||
|
||||
public override IBindable<TValue> GetConfig<TLookup, TValue>(TLookup lookup) => throw new NotImplementedException();
|
||||
|
||||
public override ISample GetSample(ISampleInfo sampleInfo) => throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
}
|
@ -136,6 +136,20 @@ namespace osu.Game.Tests.Visual.Editing
|
||||
|
||||
AddAssert("track is not virtual", () => Beatmap.Value.Track is not TrackVirtual);
|
||||
AddAssert("track length changed", () => Beatmap.Value.Track.Length > 60000);
|
||||
|
||||
AddStep("test play", () => Editor.TestGameplay());
|
||||
|
||||
AddUntilStep("wait for dialog", () => DialogOverlay.CurrentDialog != null);
|
||||
AddStep("confirm save", () => InputManager.Key(Key.Number1));
|
||||
|
||||
AddUntilStep("wait for return to editor", () => Editor.IsCurrentScreen());
|
||||
|
||||
AddAssert("track is still not virtual", () => Beatmap.Value.Track is not TrackVirtual);
|
||||
AddAssert("track length correct", () => Beatmap.Value.Track.Length > 60000);
|
||||
|
||||
AddUntilStep("track not playing", () => !EditorClock.IsRunning);
|
||||
AddStep("play track", () => InputManager.Key(Key.Space));
|
||||
AddUntilStep("wait for track playing", () => EditorClock.IsRunning);
|
||||
}
|
||||
|
||||
[Test]
|
||||
|
@ -5,10 +5,14 @@ using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using NUnit.Framework;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Extensions.ObjectExtensions;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Testing;
|
||||
using osu.Game.Overlays;
|
||||
using osu.Game.Overlays.Mods;
|
||||
using osu.Game.Rulesets;
|
||||
using osu.Game.Rulesets.Mania.Mods;
|
||||
using osu.Game.Rulesets.Mods;
|
||||
using osu.Game.Rulesets.Osu.Mods;
|
||||
|
||||
@ -16,29 +20,133 @@ namespace osu.Game.Tests.Visual.UserInterface
|
||||
{
|
||||
public class TestSceneModPresetColumn : OsuTestScene
|
||||
{
|
||||
protected override bool UseFreshStoragePerRun => true;
|
||||
|
||||
private RulesetStore rulesets = null!;
|
||||
|
||||
[Cached]
|
||||
private OverlayColourProvider colourProvider = new OverlayColourProvider(OverlayColourScheme.Green);
|
||||
|
||||
[Test]
|
||||
public void TestBasicAppearance()
|
||||
[BackgroundDependencyLoader]
|
||||
private void load()
|
||||
{
|
||||
ModPresetColumn modPresetColumn = null!;
|
||||
Dependencies.Cache(rulesets = new RealmRulesetStore(Realm));
|
||||
Dependencies.Cache(Realm);
|
||||
}
|
||||
|
||||
[SetUpSteps]
|
||||
public void SetUpSteps()
|
||||
{
|
||||
AddStep("clear contents", Clear);
|
||||
AddStep("reset storage", () =>
|
||||
{
|
||||
Realm.Write(realm =>
|
||||
{
|
||||
realm.RemoveAll<ModPreset>();
|
||||
|
||||
var testPresets = createTestPresets();
|
||||
foreach (var preset in testPresets)
|
||||
preset.Ruleset = realm.Find<RulesetInfo>(preset.Ruleset.ShortName);
|
||||
|
||||
realm.Add(testPresets);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestBasicOperation()
|
||||
{
|
||||
AddStep("set osu! ruleset", () => Ruleset.Value = rulesets.GetRuleset(0));
|
||||
AddStep("create content", () => Child = new Container
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Padding = new MarginPadding(30),
|
||||
Child = modPresetColumn = new ModPresetColumn
|
||||
Child = new ModPresetColumn
|
||||
{
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
Presets = createTestPresets().ToArray()
|
||||
}
|
||||
});
|
||||
AddStep("change presets", () => modPresetColumn.Presets = createTestPresets().Skip(1).ToArray());
|
||||
AddUntilStep("3 panels visible", () => this.ChildrenOfType<ModPresetPanel>().Count() == 3);
|
||||
|
||||
AddStep("change ruleset to mania", () => Ruleset.Value = rulesets.GetRuleset(3));
|
||||
AddUntilStep("1 panel visible", () => this.ChildrenOfType<ModPresetPanel>().Count() == 1);
|
||||
|
||||
AddStep("add another mania preset", () => Realm.Write(r => r.Add(new ModPreset
|
||||
{
|
||||
Name = "and another one",
|
||||
Mods = new Mod[]
|
||||
{
|
||||
new ManiaModMirror(),
|
||||
new ManiaModNightcore(),
|
||||
new ManiaModHardRock()
|
||||
},
|
||||
Ruleset = r.Find<RulesetInfo>("mania")
|
||||
})));
|
||||
AddUntilStep("2 panels visible", () => this.ChildrenOfType<ModPresetPanel>().Count() == 2);
|
||||
|
||||
AddStep("add another osu! preset", () => Realm.Write(r => r.Add(new ModPreset
|
||||
{
|
||||
Name = "hdhr",
|
||||
Mods = new Mod[]
|
||||
{
|
||||
new OsuModHidden(),
|
||||
new OsuModHardRock()
|
||||
},
|
||||
Ruleset = r.Find<RulesetInfo>("osu")
|
||||
})));
|
||||
AddUntilStep("2 panels visible", () => this.ChildrenOfType<ModPresetPanel>().Count() == 2);
|
||||
|
||||
AddStep("remove mania preset", () => Realm.Write(r =>
|
||||
{
|
||||
var toRemove = r.All<ModPreset>().Single(preset => preset.Name == "Different ruleset");
|
||||
r.Remove(toRemove);
|
||||
}));
|
||||
AddUntilStep("1 panel visible", () => this.ChildrenOfType<ModPresetPanel>().Count() == 1);
|
||||
|
||||
AddStep("set osu! ruleset", () => Ruleset.Value = rulesets.GetRuleset(0));
|
||||
AddUntilStep("4 panels visible", () => this.ChildrenOfType<ModPresetPanel>().Count() == 4);
|
||||
}
|
||||
|
||||
private static IEnumerable<ModPreset> createTestPresets() => new[]
|
||||
[Test]
|
||||
public void TestSoftDeleteSupport()
|
||||
{
|
||||
AddStep("set osu! ruleset", () => Ruleset.Value = rulesets.GetRuleset(0));
|
||||
AddStep("create content", () => Child = new Container
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Padding = new MarginPadding(30),
|
||||
Child = new ModPresetColumn
|
||||
{
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
}
|
||||
});
|
||||
AddUntilStep("3 panels visible", () => this.ChildrenOfType<ModPresetPanel>().Count() == 3);
|
||||
|
||||
AddStep("soft delete preset", () => Realm.Write(r =>
|
||||
{
|
||||
var toSoftDelete = r.All<ModPreset>().Single(preset => preset.Name == "AR0");
|
||||
toSoftDelete.DeletePending = true;
|
||||
}));
|
||||
AddUntilStep("2 panels visible", () => this.ChildrenOfType<ModPresetPanel>().Count() == 2);
|
||||
|
||||
AddStep("soft delete all presets", () => Realm.Write(r =>
|
||||
{
|
||||
foreach (var preset in r.All<ModPreset>())
|
||||
preset.DeletePending = true;
|
||||
}));
|
||||
AddUntilStep("no panels visible", () => this.ChildrenOfType<ModPresetPanel>().Count() == 0);
|
||||
|
||||
AddStep("undelete preset", () => Realm.Write(r =>
|
||||
{
|
||||
foreach (var preset in r.All<ModPreset>())
|
||||
preset.DeletePending = false;
|
||||
}));
|
||||
AddUntilStep("3 panels visible", () => this.ChildrenOfType<ModPresetPanel>().Count() == 3);
|
||||
}
|
||||
|
||||
private ICollection<ModPreset> createTestPresets() => new[]
|
||||
{
|
||||
new ModPreset
|
||||
{
|
||||
@ -48,7 +156,8 @@ namespace osu.Game.Tests.Visual.UserInterface
|
||||
{
|
||||
new OsuModHardRock(),
|
||||
new OsuModDoubleTime()
|
||||
}
|
||||
},
|
||||
Ruleset = rulesets.GetRuleset(0).AsNonNull()
|
||||
},
|
||||
new ModPreset
|
||||
{
|
||||
@ -60,7 +169,8 @@ namespace osu.Game.Tests.Visual.UserInterface
|
||||
{
|
||||
ApproachRate = { Value = 0 }
|
||||
}
|
||||
}
|
||||
},
|
||||
Ruleset = rulesets.GetRuleset(0).AsNonNull()
|
||||
},
|
||||
new ModPreset
|
||||
{
|
||||
@ -70,7 +180,19 @@ namespace osu.Game.Tests.Visual.UserInterface
|
||||
{
|
||||
new OsuModFlashlight(),
|
||||
new OsuModSpinIn()
|
||||
}
|
||||
},
|
||||
Ruleset = rulesets.GetRuleset(0).AsNonNull()
|
||||
},
|
||||
new ModPreset
|
||||
{
|
||||
Name = "Different ruleset",
|
||||
Description = "Just to shake things up",
|
||||
Mods = new Mod[]
|
||||
{
|
||||
new ManiaModKey4(),
|
||||
new ManiaModFadeIn()
|
||||
},
|
||||
Ruleset = rulesets.GetRuleset(3).AsNonNull()
|
||||
}
|
||||
};
|
||||
}
|
||||
|
@ -7,9 +7,11 @@ using NUnit.Framework;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Game.Database;
|
||||
using osu.Game.Overlays;
|
||||
using osu.Game.Overlays.Mods;
|
||||
using osu.Game.Rulesets.Mods;
|
||||
using osu.Game.Rulesets.Osu;
|
||||
using osu.Game.Rulesets.Osu.Mods;
|
||||
using osuTK;
|
||||
|
||||
@ -31,7 +33,7 @@ namespace osu.Game.Tests.Visual.UserInterface
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
Spacing = new Vector2(0, 5),
|
||||
ChildrenEnumerable = createTestPresets().Select(preset => new ModPresetPanel(preset))
|
||||
ChildrenEnumerable = createTestPresets().Select(preset => new ModPresetPanel(preset.ToLiveUnmanaged()))
|
||||
});
|
||||
}
|
||||
|
||||
@ -45,7 +47,8 @@ namespace osu.Game.Tests.Visual.UserInterface
|
||||
{
|
||||
new OsuModHardRock(),
|
||||
new OsuModDoubleTime()
|
||||
}
|
||||
},
|
||||
Ruleset = new OsuRuleset().RulesetInfo
|
||||
},
|
||||
new ModPreset
|
||||
{
|
||||
@ -57,7 +60,8 @@ namespace osu.Game.Tests.Visual.UserInterface
|
||||
{
|
||||
ApproachRate = { Value = 0 }
|
||||
}
|
||||
}
|
||||
},
|
||||
Ruleset = new OsuRuleset().RulesetInfo
|
||||
},
|
||||
new ModPreset
|
||||
{
|
||||
@ -67,7 +71,8 @@ namespace osu.Game.Tests.Visual.UserInterface
|
||||
{
|
||||
new OsuModFlashlight(),
|
||||
new OsuModSpinIn()
|
||||
}
|
||||
},
|
||||
Ruleset = new OsuRuleset().RulesetInfo
|
||||
}
|
||||
};
|
||||
}
|
||||
|
@ -66,8 +66,9 @@ namespace osu.Game.Database
|
||||
/// 19 2022-07-19 Added DateSubmitted and DateRanked to BeatmapSetInfo.
|
||||
/// 20 2022-07-21 Added LastAppliedDifficultyVersion to RulesetInfo, changed default value of BeatmapInfo.StarRating to -1.
|
||||
/// 21 2022-07-27 Migrate collections to realm (BeatmapCollection).
|
||||
/// 22 2022-07-31 Added ModPreset.
|
||||
/// </summary>
|
||||
private const int schema_version = 21;
|
||||
private const int schema_version = 22;
|
||||
|
||||
/// <summary>
|
||||
/// Lock object which is held during <see cref="BlockAllOperations"/> sections, blocking realm retrieval during blocking periods.
|
||||
|
@ -96,12 +96,22 @@ namespace osu.Game.IO
|
||||
if (!destination.Exists)
|
||||
Directory.CreateDirectory(destination.FullName);
|
||||
|
||||
foreach (System.IO.FileInfo fi in source.GetFiles())
|
||||
foreach (System.IO.FileInfo fileInfo in source.GetFiles())
|
||||
{
|
||||
if (topLevelExcludes && IgnoreFiles.Contains(fi.Name))
|
||||
if (topLevelExcludes && IgnoreFiles.Contains(fileInfo.Name))
|
||||
continue;
|
||||
|
||||
AttemptOperation(() => fi.CopyTo(Path.Combine(destination.FullName, fi.Name), true));
|
||||
AttemptOperation(() =>
|
||||
{
|
||||
fileInfo.Refresh();
|
||||
|
||||
// A temporary file may have been deleted since the initial GetFiles operation.
|
||||
// We don't want the whole migration process to fail in such a case.
|
||||
if (!fileInfo.Exists)
|
||||
return;
|
||||
|
||||
fileInfo.CopyTo(Path.Combine(destination.FullName, fileInfo.Name), true);
|
||||
});
|
||||
}
|
||||
|
||||
foreach (DirectoryInfo dir in source.GetDirectories())
|
||||
|
@ -212,6 +212,10 @@ namespace osu.Game
|
||||
{
|
||||
Name = @"osu!";
|
||||
|
||||
#if DEBUG
|
||||
Name += " (development)";
|
||||
#endif
|
||||
|
||||
allowableExceptions = UnhandledExceptionsBeforeCrash;
|
||||
}
|
||||
|
||||
|
@ -7,31 +7,24 @@ using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Bindables;
|
||||
using osu.Game.Database;
|
||||
using osu.Game.Graphics;
|
||||
using osu.Game.Localisation;
|
||||
using osu.Game.Rulesets;
|
||||
using osu.Game.Rulesets.Mods;
|
||||
using osuTK;
|
||||
using Realms;
|
||||
|
||||
namespace osu.Game.Overlays.Mods
|
||||
{
|
||||
public class ModPresetColumn : ModSelectColumn
|
||||
{
|
||||
private IReadOnlyList<ModPreset> presets = Array.Empty<ModPreset>();
|
||||
[Resolved]
|
||||
private RealmAccess realm { get; set; } = null!;
|
||||
|
||||
/// <summary>
|
||||
/// Sets the collection of available mod presets.
|
||||
/// </summary>
|
||||
public IReadOnlyList<ModPreset> Presets
|
||||
{
|
||||
get => presets;
|
||||
set
|
||||
{
|
||||
presets = value;
|
||||
|
||||
if (IsLoaded)
|
||||
asyncLoadPanels();
|
||||
}
|
||||
}
|
||||
[Resolved]
|
||||
private IBindable<RulesetInfo> ruleset { get; set; } = null!;
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(OsuColour colours)
|
||||
@ -44,7 +37,20 @@ namespace osu.Game.Overlays.Mods
|
||||
{
|
||||
base.LoadComplete();
|
||||
|
||||
asyncLoadPanels();
|
||||
ruleset.BindValueChanged(_ => rulesetChanged(), true);
|
||||
}
|
||||
|
||||
private IDisposable? presetSubscription;
|
||||
|
||||
private void rulesetChanged()
|
||||
{
|
||||
presetSubscription?.Dispose();
|
||||
presetSubscription = realm.RegisterForNotifications(r =>
|
||||
r.All<ModPreset>()
|
||||
.Filter($"{nameof(ModPreset.Ruleset)}.{nameof(RulesetInfo.ShortName)} == $0"
|
||||
+ $" && {nameof(ModPreset.DeletePending)} == false", ruleset.Value.ShortName)
|
||||
.OrderBy(preset => preset.Name),
|
||||
(presets, _, _) => asyncLoadPanels(presets));
|
||||
}
|
||||
|
||||
private CancellationTokenSource? cancellationTokenSource;
|
||||
@ -52,11 +58,17 @@ namespace osu.Game.Overlays.Mods
|
||||
private Task? latestLoadTask;
|
||||
internal bool ItemsLoaded => latestLoadTask == null;
|
||||
|
||||
private void asyncLoadPanels()
|
||||
private void asyncLoadPanels(IReadOnlyList<ModPreset> presets)
|
||||
{
|
||||
cancellationTokenSource?.Cancel();
|
||||
|
||||
var panels = presets.Select(preset => new ModPresetPanel(preset)
|
||||
if (!presets.Any())
|
||||
{
|
||||
ItemsFlow.Clear();
|
||||
return;
|
||||
}
|
||||
|
||||
var panels = presets.Select(preset => new ModPresetPanel(preset.ToLive(realm))
|
||||
{
|
||||
Shear = Vector2.Zero
|
||||
});
|
||||
@ -73,5 +85,12 @@ namespace osu.Game.Overlays.Mods
|
||||
latestLoadTask = null;
|
||||
});
|
||||
}
|
||||
|
||||
protected override void Dispose(bool isDisposing)
|
||||
{
|
||||
base.Dispose(isDisposing);
|
||||
|
||||
presetSubscription?.Dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -4,6 +4,7 @@
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Bindables;
|
||||
using osu.Framework.Graphics.Cursor;
|
||||
using osu.Game.Database;
|
||||
using osu.Game.Graphics;
|
||||
using osu.Game.Rulesets.Mods;
|
||||
|
||||
@ -11,16 +12,16 @@ namespace osu.Game.Overlays.Mods
|
||||
{
|
||||
public class ModPresetPanel : ModSelectPanel, IHasCustomTooltip<ModPreset>
|
||||
{
|
||||
public readonly ModPreset Preset;
|
||||
public readonly Live<ModPreset> Preset;
|
||||
|
||||
public override BindableBool Active { get; } = new BindableBool();
|
||||
|
||||
public ModPresetPanel(ModPreset preset)
|
||||
public ModPresetPanel(Live<ModPreset> preset)
|
||||
{
|
||||
Preset = preset;
|
||||
|
||||
Title = preset.Name;
|
||||
Description = preset.Description;
|
||||
Title = preset.Value.Name;
|
||||
Description = preset.Value.Description;
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
@ -29,7 +30,7 @@ namespace osu.Game.Overlays.Mods
|
||||
AccentColour = colours.Orange1;
|
||||
}
|
||||
|
||||
public ModPreset TooltipContent => Preset;
|
||||
public ModPreset TooltipContent => Preset.Value;
|
||||
public ITooltip<ModPreset> GetCustomTooltip() => new ModPresetTooltip(ColourProvider);
|
||||
}
|
||||
}
|
||||
|
@ -50,7 +50,7 @@ namespace osu.Game.Overlays.Mods
|
||||
|
||||
public void SetContent(ModPreset preset)
|
||||
{
|
||||
if (preset == lastPreset)
|
||||
if (ReferenceEquals(preset, lastPreset))
|
||||
return;
|
||||
|
||||
lastPreset = preset;
|
||||
|
@ -70,7 +70,11 @@ namespace osu.Game.Overlays
|
||||
/// <summary>
|
||||
/// Forcefully reload the current <see cref="WorkingBeatmap"/>'s track from disk.
|
||||
/// </summary>
|
||||
public void ReloadCurrentTrack() => changeTrack();
|
||||
public void ReloadCurrentTrack()
|
||||
{
|
||||
changeTrack();
|
||||
TrackChanged?.Invoke(current, TrackChangeDirection.None);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns whether the beatmap track is playing.
|
||||
|
@ -3,6 +3,12 @@
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Newtonsoft.Json;
|
||||
using osu.Framework.Extensions.ObjectExtensions;
|
||||
using osu.Game.Database;
|
||||
using osu.Game.Online.API;
|
||||
using Realms;
|
||||
|
||||
namespace osu.Game.Rulesets.Mods
|
||||
{
|
||||
@ -10,12 +16,18 @@ namespace osu.Game.Rulesets.Mods
|
||||
/// A mod preset is a named collection of configured mods.
|
||||
/// Presets are presented to the user in the mod select overlay for convenience.
|
||||
/// </summary>
|
||||
public class ModPreset
|
||||
public class ModPreset : RealmObject, IHasGuidPrimaryKey, ISoftDelete
|
||||
{
|
||||
/// <summary>
|
||||
/// The internal database ID of the preset.
|
||||
/// </summary>
|
||||
[PrimaryKey]
|
||||
public Guid ID { get; set; } = Guid.NewGuid();
|
||||
|
||||
/// <summary>
|
||||
/// The ruleset that the preset is valid for.
|
||||
/// </summary>
|
||||
public RulesetInfo RulesetInfo { get; set; } = null!;
|
||||
public RulesetInfo Ruleset { get; set; } = null!;
|
||||
|
||||
/// <summary>
|
||||
/// The name of the mod preset.
|
||||
@ -30,6 +42,34 @@ namespace osu.Game.Rulesets.Mods
|
||||
/// <summary>
|
||||
/// The set of configured mods that are part of the preset.
|
||||
/// </summary>
|
||||
public ICollection<Mod> Mods { get; set; } = Array.Empty<Mod>();
|
||||
[Ignored]
|
||||
public ICollection<Mod> Mods
|
||||
{
|
||||
get
|
||||
{
|
||||
if (string.IsNullOrEmpty(ModsJson))
|
||||
return Array.Empty<Mod>();
|
||||
|
||||
var apiMods = JsonConvert.DeserializeObject<IEnumerable<APIMod>>(ModsJson);
|
||||
var ruleset = Ruleset.CreateInstance();
|
||||
return apiMods.AsNonNull().Select(mod => mod.ToMod(ruleset)).ToArray();
|
||||
}
|
||||
set
|
||||
{
|
||||
var apiMods = value.Select(mod => new APIMod(mod)).ToArray();
|
||||
ModsJson = JsonConvert.SerializeObject(apiMods);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The set of configured mods that are part of the preset, serialised as a JSON blob.
|
||||
/// </summary>
|
||||
[MapTo("Mods")]
|
||||
public string ModsJson { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// Whether the preset has been soft-deleted by the user.
|
||||
/// </summary>
|
||||
public bool DeletePending { get; set; }
|
||||
}
|
||||
}
|
||||
|
@ -329,6 +329,9 @@ namespace osu.Game.Screens.Edit
|
||||
changeHandler?.CanRedo.BindValueChanged(v => redoMenuItem.Action.Disabled = !v.NewValue, true);
|
||||
}
|
||||
|
||||
[Resolved]
|
||||
private MusicController musicController { get; set; }
|
||||
|
||||
protected override void LoadComplete()
|
||||
{
|
||||
base.LoadComplete();
|
||||
@ -336,12 +339,18 @@ namespace osu.Game.Screens.Edit
|
||||
|
||||
Mode.Value = isNewBeatmap ? EditorScreenMode.SongSetup : EditorScreenMode.Compose;
|
||||
Mode.BindValueChanged(onModeChanged, true);
|
||||
|
||||
musicController.TrackChanged += onTrackChanged;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// If the beatmap's track has changed, this method must be called to keep the editor in a valid state.
|
||||
/// </summary>
|
||||
public void UpdateClockSource() => clock.ChangeSource(Beatmap.Value.Track);
|
||||
protected override void Dispose(bool isDisposing)
|
||||
{
|
||||
base.Dispose(isDisposing);
|
||||
|
||||
musicController.TrackChanged -= onTrackChanged;
|
||||
}
|
||||
|
||||
private void onTrackChanged(WorkingBeatmap working, TrackChangeDirection direction) => clock.ChangeSource(working.Track);
|
||||
|
||||
/// <summary>
|
||||
/// Creates an <see cref="EditorState"/> instance representing the current state of the editor.
|
||||
|
@ -30,8 +30,8 @@ namespace osu.Game.Screens.Edit.Setup
|
||||
[Resolved]
|
||||
private IBindable<WorkingBeatmap> working { get; set; }
|
||||
|
||||
[Resolved(canBeNull: true)]
|
||||
private Editor editor { get; set; }
|
||||
[Resolved]
|
||||
private EditorBeatmap editorBeatmap { get; set; }
|
||||
|
||||
[Resolved]
|
||||
private SetupScreenHeader header { get; set; }
|
||||
@ -88,6 +88,8 @@ namespace osu.Game.Screens.Edit.Setup
|
||||
beatmaps.AddFile(set, stream, destination.Name);
|
||||
}
|
||||
|
||||
editorBeatmap.SaveState();
|
||||
|
||||
working.Value.Metadata.BackgroundFile = destination.Name;
|
||||
header.Background.UpdateBackground();
|
||||
|
||||
@ -117,9 +119,9 @@ namespace osu.Game.Screens.Edit.Setup
|
||||
|
||||
working.Value.Metadata.AudioFile = destination.Name;
|
||||
|
||||
editorBeatmap.SaveState();
|
||||
music.ReloadCurrentTrack();
|
||||
|
||||
editor?.UpdateClockSource();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -204,6 +204,9 @@ namespace osu.Game.Screens.OnlinePlay
|
||||
|
||||
public bool OnPressed(KeyBindingPressEvent<GlobalAction> e)
|
||||
{
|
||||
if (!AllowSelection)
|
||||
return false;
|
||||
|
||||
switch (e.Action)
|
||||
{
|
||||
case GlobalAction.SelectNext:
|
||||
@ -224,9 +227,6 @@ namespace osu.Game.Screens.OnlinePlay
|
||||
|
||||
private void selectNext(int direction)
|
||||
{
|
||||
if (!AllowSelection)
|
||||
return;
|
||||
|
||||
var visibleItems = ListContainer.AsEnumerable().Where(r => r.IsPresent);
|
||||
|
||||
PlaylistItem item;
|
||||
|
@ -98,5 +98,14 @@ namespace osu.Game.Screens.Play.HUD
|
||||
return Drawable.Empty();
|
||||
}
|
||||
}
|
||||
|
||||
public static Type[] GetAllAvailableDrawables()
|
||||
{
|
||||
return typeof(OsuGame).Assembly.GetTypes()
|
||||
.Where(t => !t.IsInterface && !t.IsAbstract)
|
||||
.Where(t => typeof(ISkinnableDrawable).IsAssignableFrom(t))
|
||||
.OrderBy(t => t.Name)
|
||||
.ToArray();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,11 +1,8 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
#nullable disable
|
||||
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
@ -16,24 +13,25 @@ using osu.Game.Graphics.Sprites;
|
||||
using osu.Game.Graphics.UserInterface;
|
||||
using osu.Game.Overlays;
|
||||
using osu.Game.Screens.Edit.Components;
|
||||
using osu.Game.Screens.Play.HUD;
|
||||
using osuTK;
|
||||
|
||||
namespace osu.Game.Skinning.Editor
|
||||
{
|
||||
public class SkinComponentToolbox : EditorSidebarSection
|
||||
{
|
||||
public Action<Type> RequestPlacement;
|
||||
public Action<Type>? RequestPlacement;
|
||||
|
||||
private readonly CompositeDrawable target;
|
||||
private readonly CompositeDrawable? target;
|
||||
|
||||
public SkinComponentToolbox(CompositeDrawable target = null)
|
||||
private FillFlowContainer fill = null!;
|
||||
|
||||
public SkinComponentToolbox(CompositeDrawable? target = null)
|
||||
: base("Components")
|
||||
{
|
||||
this.target = target;
|
||||
}
|
||||
|
||||
private FillFlowContainer fill;
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load()
|
||||
{
|
||||
@ -52,12 +50,7 @@ namespace osu.Game.Skinning.Editor
|
||||
{
|
||||
fill.Clear();
|
||||
|
||||
var skinnableTypes = typeof(OsuGame).Assembly.GetTypes()
|
||||
.Where(t => !t.IsInterface && !t.IsAbstract)
|
||||
.Where(t => typeof(ISkinnableDrawable).IsAssignableFrom(t))
|
||||
.OrderBy(t => t.Name)
|
||||
.ToArray();
|
||||
|
||||
var skinnableTypes = SkinnableInfo.GetAllAvailableDrawables();
|
||||
foreach (var type in skinnableTypes)
|
||||
attemptAddComponent(type);
|
||||
}
|
||||
@ -90,21 +83,21 @@ namespace osu.Game.Skinning.Editor
|
||||
|
||||
public class ToolboxComponentButton : OsuButton
|
||||
{
|
||||
public Action<Type>? RequestPlacement;
|
||||
|
||||
protected override bool ShouldBeConsideredForInput(Drawable child) => false;
|
||||
|
||||
public override bool PropagateNonPositionalInputSubTree => false;
|
||||
|
||||
private readonly Drawable component;
|
||||
private readonly CompositeDrawable dependencySource;
|
||||
private readonly CompositeDrawable? dependencySource;
|
||||
|
||||
public Action<Type> RequestPlacement;
|
||||
|
||||
private Container innerContainer;
|
||||
private Container innerContainer = null!;
|
||||
|
||||
private const float contracted_size = 60;
|
||||
private const float expanded_size = 120;
|
||||
|
||||
public ToolboxComponentButton(Drawable component, CompositeDrawable dependencySource)
|
||||
public ToolboxComponentButton(Drawable component, CompositeDrawable? dependencySource)
|
||||
{
|
||||
this.component = component;
|
||||
this.dependencySource = dependencySource;
|
||||
@ -184,9 +177,9 @@ namespace osu.Game.Skinning.Editor
|
||||
|
||||
public class DependencyBorrowingContainer : Container
|
||||
{
|
||||
private readonly CompositeDrawable donor;
|
||||
private readonly CompositeDrawable? donor;
|
||||
|
||||
public DependencyBorrowingContainer(CompositeDrawable donor)
|
||||
public DependencyBorrowingContainer(CompositeDrawable? donor)
|
||||
{
|
||||
this.donor = donor;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user