mirror of
https://github.com/ppy/osu.git
synced 2024-12-14 10:12:54 +08:00
Merge branch 'master' into remove-hud-component-lookup
This commit is contained in:
commit
7c6400735f
@ -51,7 +51,7 @@
|
|||||||
<Reference Include="Java.Interop" />
|
<Reference Include="Java.Interop" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="ppy.osu.Game.Resources" Version="2021.422.0" />
|
<PackageReference Include="ppy.osu.Game.Resources" Version="2021.525.0" />
|
||||||
<PackageReference Include="ppy.osu.Framework.Android" Version="2021.528.0" />
|
<PackageReference Include="ppy.osu.Framework.Android" Version="2021.528.0" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
</Project>
|
</Project>
|
||||||
|
@ -1,8 +1,16 @@
|
|||||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
// 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.
|
// See the LICENCE file in the repository root for full licence text.
|
||||||
|
|
||||||
|
using System.Linq;
|
||||||
using NUnit.Framework;
|
using NUnit.Framework;
|
||||||
|
using osu.Framework.Extensions.IEnumerableExtensions;
|
||||||
|
using osu.Framework.Graphics.Containers;
|
||||||
|
using osu.Framework.Screens;
|
||||||
|
using osu.Framework.Testing;
|
||||||
|
using osu.Game.Screens.Play.HUD;
|
||||||
|
using osu.Game.Skinning;
|
||||||
using osu.Game.Tests.Visual;
|
using osu.Game.Tests.Visual;
|
||||||
|
using osuTK;
|
||||||
|
|
||||||
namespace osu.Game.Rulesets.Catch.Tests
|
namespace osu.Game.Rulesets.Catch.Tests
|
||||||
{
|
{
|
||||||
@ -10,5 +18,22 @@ namespace osu.Game.Rulesets.Catch.Tests
|
|||||||
public class TestSceneCatchPlayerLegacySkin : LegacySkinPlayerTestScene
|
public class TestSceneCatchPlayerLegacySkin : LegacySkinPlayerTestScene
|
||||||
{
|
{
|
||||||
protected override Ruleset CreatePlayerRuleset() => new CatchRuleset();
|
protected override Ruleset CreatePlayerRuleset() => new CatchRuleset();
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void TestLegacyHUDComboCounterHidden([Values] bool withModifiedSkin)
|
||||||
|
{
|
||||||
|
if (withModifiedSkin)
|
||||||
|
{
|
||||||
|
AddStep("change component scale", () => Player.ChildrenOfType<LegacyScoreCounter>().First().Scale = new Vector2(2f));
|
||||||
|
AddStep("update target", () => Player.ChildrenOfType<SkinnableTargetContainer>().ForEach(LegacySkin.UpdateDrawableTarget));
|
||||||
|
AddStep("exit player", () => Player.Exit());
|
||||||
|
CreateTest(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
AddAssert("legacy HUD combo counter hidden", () =>
|
||||||
|
{
|
||||||
|
return Player.ChildrenOfType<LegacyComboCounter>().All(c => c.ChildrenOfType<Container>().Single().Alpha == 0f);
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -32,28 +32,28 @@ namespace osu.Game.Rulesets.Catch.Tests
|
|||||||
[TestCase(true, false)]
|
[TestCase(true, false)]
|
||||||
[TestCase(false, true)]
|
[TestCase(false, true)]
|
||||||
[TestCase(false, false)]
|
[TestCase(false, false)]
|
||||||
public override void TestBeatmapComboColours(bool userHasCustomColours, bool useBeatmapSkin)
|
public void TestBeatmapComboColours(bool userHasCustomColours, bool useBeatmapSkin)
|
||||||
{
|
{
|
||||||
TestBeatmap = new CatchCustomSkinWorkingBeatmap(audio, true);
|
PrepareBeatmap(() => new CatchCustomSkinWorkingBeatmap(audio, true));
|
||||||
base.TestBeatmapComboColours(userHasCustomColours, useBeatmapSkin);
|
ConfigureTest(useBeatmapSkin, true, userHasCustomColours);
|
||||||
AddAssert("is beatmap skin colours", () => TestPlayer.UsableComboColours.SequenceEqual(TestBeatmapSkin.Colours));
|
AddAssert("is beatmap skin colours", () => TestPlayer.UsableComboColours.SequenceEqual(TestBeatmapSkin.Colours));
|
||||||
}
|
}
|
||||||
|
|
||||||
[TestCase(true)]
|
[TestCase(true)]
|
||||||
[TestCase(false)]
|
[TestCase(false)]
|
||||||
public override void TestBeatmapComboColoursOverride(bool useBeatmapSkin)
|
public void TestBeatmapComboColoursOverride(bool useBeatmapSkin)
|
||||||
{
|
{
|
||||||
TestBeatmap = new CatchCustomSkinWorkingBeatmap(audio, true);
|
PrepareBeatmap(() => new CatchCustomSkinWorkingBeatmap(audio, true));
|
||||||
base.TestBeatmapComboColoursOverride(useBeatmapSkin);
|
ConfigureTest(useBeatmapSkin, false, true);
|
||||||
AddAssert("is user custom skin colours", () => TestPlayer.UsableComboColours.SequenceEqual(TestSkin.Colours));
|
AddAssert("is user custom skin colours", () => TestPlayer.UsableComboColours.SequenceEqual(TestSkin.Colours));
|
||||||
}
|
}
|
||||||
|
|
||||||
[TestCase(true)]
|
[TestCase(true)]
|
||||||
[TestCase(false)]
|
[TestCase(false)]
|
||||||
public override void TestBeatmapComboColoursOverrideWithDefaultColours(bool useBeatmapSkin)
|
public void TestBeatmapComboColoursOverrideWithDefaultColours(bool useBeatmapSkin)
|
||||||
{
|
{
|
||||||
TestBeatmap = new CatchCustomSkinWorkingBeatmap(audio, true);
|
PrepareBeatmap(() => new CatchCustomSkinWorkingBeatmap(audio, true));
|
||||||
base.TestBeatmapComboColoursOverrideWithDefaultColours(useBeatmapSkin);
|
ConfigureTest(useBeatmapSkin, false, false);
|
||||||
AddAssert("is default user skin colours", () => TestPlayer.UsableComboColours.SequenceEqual(SkinConfiguration.DefaultComboColours));
|
AddAssert("is default user skin colours", () => TestPlayer.UsableComboColours.SequenceEqual(SkinConfiguration.DefaultComboColours));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -61,10 +61,10 @@ namespace osu.Game.Rulesets.Catch.Tests
|
|||||||
[TestCase(false, true)]
|
[TestCase(false, true)]
|
||||||
[TestCase(true, false)]
|
[TestCase(true, false)]
|
||||||
[TestCase(false, false)]
|
[TestCase(false, false)]
|
||||||
public override void TestBeatmapNoComboColours(bool useBeatmapSkin, bool useBeatmapColour)
|
public void TestBeatmapNoComboColours(bool useBeatmapSkin, bool useBeatmapColour)
|
||||||
{
|
{
|
||||||
TestBeatmap = new CatchCustomSkinWorkingBeatmap(audio, false);
|
PrepareBeatmap(() => new CatchCustomSkinWorkingBeatmap(audio, false));
|
||||||
base.TestBeatmapNoComboColours(useBeatmapSkin, useBeatmapColour);
|
ConfigureTest(useBeatmapSkin, useBeatmapColour, false);
|
||||||
AddAssert("is default user skin colours", () => TestPlayer.UsableComboColours.SequenceEqual(SkinConfiguration.DefaultComboColours));
|
AddAssert("is default user skin colours", () => TestPlayer.UsableComboColours.SequenceEqual(SkinConfiguration.DefaultComboColours));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -72,10 +72,10 @@ namespace osu.Game.Rulesets.Catch.Tests
|
|||||||
[TestCase(false, true)]
|
[TestCase(false, true)]
|
||||||
[TestCase(true, false)]
|
[TestCase(true, false)]
|
||||||
[TestCase(false, false)]
|
[TestCase(false, false)]
|
||||||
public override void TestBeatmapNoComboColoursSkinOverride(bool useBeatmapSkin, bool useBeatmapColour)
|
public void TestBeatmapNoComboColoursSkinOverride(bool useBeatmapSkin, bool useBeatmapColour)
|
||||||
{
|
{
|
||||||
TestBeatmap = new CatchCustomSkinWorkingBeatmap(audio, false);
|
PrepareBeatmap(() => new CatchCustomSkinWorkingBeatmap(audio, false));
|
||||||
base.TestBeatmapNoComboColoursSkinOverride(useBeatmapSkin, useBeatmapColour);
|
ConfigureTest(useBeatmapSkin, useBeatmapColour, true);
|
||||||
AddAssert("is custom user skin colours", () => TestPlayer.UsableComboColours.SequenceEqual(TestSkin.Colours));
|
AddAssert("is custom user skin colours", () => TestPlayer.UsableComboColours.SequenceEqual(TestSkin.Colours));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -83,7 +83,7 @@ namespace osu.Game.Rulesets.Catch.Tests
|
|||||||
[TestCase(false)]
|
[TestCase(false)]
|
||||||
public void TestBeatmapHyperDashColours(bool useBeatmapSkin)
|
public void TestBeatmapHyperDashColours(bool useBeatmapSkin)
|
||||||
{
|
{
|
||||||
TestBeatmap = new CatchCustomSkinWorkingBeatmap(audio, true);
|
PrepareBeatmap(() => new CatchCustomSkinWorkingBeatmap(audio, true));
|
||||||
ConfigureTest(useBeatmapSkin, true, true);
|
ConfigureTest(useBeatmapSkin, true, true);
|
||||||
AddAssert("is custom hyper dash colours", () => ((CatchExposedPlayer)TestPlayer).UsableHyperDashColour == TestBeatmapSkin.HYPER_DASH_COLOUR);
|
AddAssert("is custom hyper dash colours", () => ((CatchExposedPlayer)TestPlayer).UsableHyperDashColour == TestBeatmapSkin.HYPER_DASH_COLOUR);
|
||||||
AddAssert("is custom hyper dash after image colours", () => ((CatchExposedPlayer)TestPlayer).UsableHyperDashAfterImageColour == TestBeatmapSkin.HYPER_DASH_AFTER_IMAGE_COLOUR);
|
AddAssert("is custom hyper dash after image colours", () => ((CatchExposedPlayer)TestPlayer).UsableHyperDashAfterImageColour == TestBeatmapSkin.HYPER_DASH_AFTER_IMAGE_COLOUR);
|
||||||
@ -94,7 +94,7 @@ namespace osu.Game.Rulesets.Catch.Tests
|
|||||||
[TestCase(false)]
|
[TestCase(false)]
|
||||||
public void TestBeatmapHyperDashColoursOverride(bool useBeatmapSkin)
|
public void TestBeatmapHyperDashColoursOverride(bool useBeatmapSkin)
|
||||||
{
|
{
|
||||||
TestBeatmap = new CatchCustomSkinWorkingBeatmap(audio, true);
|
PrepareBeatmap(() => new CatchCustomSkinWorkingBeatmap(audio, true));
|
||||||
ConfigureTest(useBeatmapSkin, false, true);
|
ConfigureTest(useBeatmapSkin, false, true);
|
||||||
AddAssert("is custom hyper dash colours", () => ((CatchExposedPlayer)TestPlayer).UsableHyperDashColour == TestSkin.HYPER_DASH_COLOUR);
|
AddAssert("is custom hyper dash colours", () => ((CatchExposedPlayer)TestPlayer).UsableHyperDashColour == TestSkin.HYPER_DASH_COLOUR);
|
||||||
AddAssert("is custom hyper dash after image colours", () => ((CatchExposedPlayer)TestPlayer).UsableHyperDashAfterImageColour == TestSkin.HYPER_DASH_AFTER_IMAGE_COLOUR);
|
AddAssert("is custom hyper dash after image colours", () => ((CatchExposedPlayer)TestPlayer).UsableHyperDashAfterImageColour == TestSkin.HYPER_DASH_AFTER_IMAGE_COLOUR);
|
||||||
|
@ -1,8 +1,10 @@
|
|||||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
// 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.
|
// See the LICENCE file in the repository root for full licence text.
|
||||||
|
|
||||||
|
using System.Linq;
|
||||||
using osu.Framework.Bindables;
|
using osu.Framework.Bindables;
|
||||||
using osu.Framework.Graphics;
|
using osu.Framework.Graphics;
|
||||||
|
using osu.Game.Screens.Play.HUD;
|
||||||
using osu.Game.Skinning;
|
using osu.Game.Skinning;
|
||||||
using osuTK.Graphics;
|
using osuTK.Graphics;
|
||||||
|
|
||||||
@ -22,6 +24,25 @@ namespace osu.Game.Rulesets.Catch.Skinning.Legacy
|
|||||||
|
|
||||||
public override Drawable GetDrawableComponent(ISkinComponent component)
|
public override Drawable GetDrawableComponent(ISkinComponent component)
|
||||||
{
|
{
|
||||||
|
if (component is SkinnableTargetComponent targetComponent)
|
||||||
|
{
|
||||||
|
switch (targetComponent.Target)
|
||||||
|
{
|
||||||
|
case SkinnableTarget.MainHUDComponents:
|
||||||
|
var components = Source.GetDrawableComponent(component) as SkinnableTargetComponentsContainer;
|
||||||
|
|
||||||
|
if (providesComboCounter && components != null)
|
||||||
|
{
|
||||||
|
// catch may provide its own combo counter; hide the default.
|
||||||
|
// todo: this should be done in an elegant way per ruleset, defining which HUD skin components should be displayed.
|
||||||
|
foreach (var legacyComboCounter in components.OfType<LegacyComboCounter>())
|
||||||
|
legacyComboCounter.HiddenByRulesetImplementation = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return components;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (component is CatchSkinComponent catchSkinComponent)
|
if (component is CatchSkinComponent catchSkinComponent)
|
||||||
{
|
{
|
||||||
switch (catchSkinComponent.Component)
|
switch (catchSkinComponent.Component)
|
||||||
|
@ -11,7 +11,7 @@ namespace osu.Game.Rulesets.Mania.Tests
|
|||||||
public class TestSceneManiaHitObjectSamples : HitObjectSampleTest
|
public class TestSceneManiaHitObjectSamples : HitObjectSampleTest
|
||||||
{
|
{
|
||||||
protected override Ruleset CreatePlayerRuleset() => new ManiaRuleset();
|
protected override Ruleset CreatePlayerRuleset() => new ManiaRuleset();
|
||||||
protected override IResourceStore<byte[]> Resources => new DllResourceStore(Assembly.GetAssembly(typeof(TestSceneManiaHitObjectSamples)));
|
protected override IResourceStore<byte[]> RulesetResources => new DllResourceStore(Assembly.GetAssembly(typeof(TestSceneManiaHitObjectSamples)));
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Tests that when a normal sample bank is used, the normal hitsound will be looked up.
|
/// Tests that when a normal sample bank is used, the normal hitsound will be looked up.
|
||||||
|
@ -30,28 +30,28 @@ namespace osu.Game.Rulesets.Osu.Tests
|
|||||||
[TestCase(true, false)]
|
[TestCase(true, false)]
|
||||||
[TestCase(false, true)]
|
[TestCase(false, true)]
|
||||||
[TestCase(false, false)]
|
[TestCase(false, false)]
|
||||||
public override void TestBeatmapComboColours(bool userHasCustomColours, bool useBeatmapSkin)
|
public void TestBeatmapComboColours(bool userHasCustomColours, bool useBeatmapSkin)
|
||||||
{
|
{
|
||||||
TestBeatmap = new OsuCustomSkinWorkingBeatmap(audio, true);
|
PrepareBeatmap(() => new OsuCustomSkinWorkingBeatmap(audio, true));
|
||||||
base.TestBeatmapComboColours(userHasCustomColours, useBeatmapSkin);
|
ConfigureTest(useBeatmapSkin, true, userHasCustomColours);
|
||||||
AddAssert("is beatmap skin colours", () => TestPlayer.UsableComboColours.SequenceEqual(TestBeatmapSkin.Colours));
|
AddAssert("is beatmap skin colours", () => TestPlayer.UsableComboColours.SequenceEqual(TestBeatmapSkin.Colours));
|
||||||
}
|
}
|
||||||
|
|
||||||
[TestCase(true)]
|
[TestCase(true)]
|
||||||
[TestCase(false)]
|
[TestCase(false)]
|
||||||
public override void TestBeatmapComboColoursOverride(bool useBeatmapSkin)
|
public void TestBeatmapComboColoursOverride(bool useBeatmapSkin)
|
||||||
{
|
{
|
||||||
TestBeatmap = new OsuCustomSkinWorkingBeatmap(audio, true);
|
PrepareBeatmap(() => new OsuCustomSkinWorkingBeatmap(audio, true));
|
||||||
base.TestBeatmapComboColoursOverride(useBeatmapSkin);
|
ConfigureTest(useBeatmapSkin, false, true);
|
||||||
AddAssert("is user custom skin colours", () => TestPlayer.UsableComboColours.SequenceEqual(TestSkin.Colours));
|
AddAssert("is user custom skin colours", () => TestPlayer.UsableComboColours.SequenceEqual(TestSkin.Colours));
|
||||||
}
|
}
|
||||||
|
|
||||||
[TestCase(true)]
|
[TestCase(true)]
|
||||||
[TestCase(false)]
|
[TestCase(false)]
|
||||||
public override void TestBeatmapComboColoursOverrideWithDefaultColours(bool useBeatmapSkin)
|
public void TestBeatmapComboColoursOverrideWithDefaultColours(bool useBeatmapSkin)
|
||||||
{
|
{
|
||||||
TestBeatmap = new OsuCustomSkinWorkingBeatmap(audio, true);
|
PrepareBeatmap(() => new OsuCustomSkinWorkingBeatmap(audio, true));
|
||||||
base.TestBeatmapComboColoursOverrideWithDefaultColours(useBeatmapSkin);
|
ConfigureTest(useBeatmapSkin, false, false);
|
||||||
AddAssert("is default user skin colours", () => TestPlayer.UsableComboColours.SequenceEqual(SkinConfiguration.DefaultComboColours));
|
AddAssert("is default user skin colours", () => TestPlayer.UsableComboColours.SequenceEqual(SkinConfiguration.DefaultComboColours));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -59,10 +59,10 @@ namespace osu.Game.Rulesets.Osu.Tests
|
|||||||
[TestCase(false, true)]
|
[TestCase(false, true)]
|
||||||
[TestCase(true, false)]
|
[TestCase(true, false)]
|
||||||
[TestCase(false, false)]
|
[TestCase(false, false)]
|
||||||
public override void TestBeatmapNoComboColours(bool useBeatmapSkin, bool useBeatmapColour)
|
public void TestBeatmapNoComboColours(bool useBeatmapSkin, bool useBeatmapColour)
|
||||||
{
|
{
|
||||||
TestBeatmap = new OsuCustomSkinWorkingBeatmap(audio, false);
|
PrepareBeatmap(() => new OsuCustomSkinWorkingBeatmap(audio, false));
|
||||||
base.TestBeatmapNoComboColours(useBeatmapSkin, useBeatmapColour);
|
ConfigureTest(useBeatmapSkin, useBeatmapColour, false);
|
||||||
AddAssert("is default user skin colours", () => TestPlayer.UsableComboColours.SequenceEqual(SkinConfiguration.DefaultComboColours));
|
AddAssert("is default user skin colours", () => TestPlayer.UsableComboColours.SequenceEqual(SkinConfiguration.DefaultComboColours));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -70,10 +70,10 @@ namespace osu.Game.Rulesets.Osu.Tests
|
|||||||
[TestCase(false, true)]
|
[TestCase(false, true)]
|
||||||
[TestCase(true, false)]
|
[TestCase(true, false)]
|
||||||
[TestCase(false, false)]
|
[TestCase(false, false)]
|
||||||
public override void TestBeatmapNoComboColoursSkinOverride(bool useBeatmapSkin, bool useBeatmapColour)
|
public void TestBeatmapNoComboColoursSkinOverride(bool useBeatmapSkin, bool useBeatmapColour)
|
||||||
{
|
{
|
||||||
TestBeatmap = new OsuCustomSkinWorkingBeatmap(audio, false);
|
PrepareBeatmap(() => new OsuCustomSkinWorkingBeatmap(audio, false));
|
||||||
base.TestBeatmapNoComboColoursSkinOverride(useBeatmapSkin, useBeatmapColour);
|
ConfigureTest(useBeatmapSkin, useBeatmapColour, true);
|
||||||
AddAssert("is custom user skin colours", () => TestPlayer.UsableComboColours.SequenceEqual(TestSkin.Colours));
|
AddAssert("is custom user skin colours", () => TestPlayer.UsableComboColours.SequenceEqual(TestSkin.Colours));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -12,7 +12,7 @@ namespace osu.Game.Rulesets.Taiko.Tests
|
|||||||
{
|
{
|
||||||
protected override Ruleset CreatePlayerRuleset() => new TaikoRuleset();
|
protected override Ruleset CreatePlayerRuleset() => new TaikoRuleset();
|
||||||
|
|
||||||
protected override IResourceStore<byte[]> Resources => new DllResourceStore(Assembly.GetAssembly(typeof(TestSceneTaikoHitObjectSamples)));
|
protected override IResourceStore<byte[]> RulesetResources => new DllResourceStore(Assembly.GetAssembly(typeof(TestSceneTaikoHitObjectSamples)));
|
||||||
|
|
||||||
[TestCase("taiko-normal-hitnormal")]
|
[TestCase("taiko-normal-hitnormal")]
|
||||||
[TestCase("normal-hitnormal")]
|
[TestCase("normal-hitnormal")]
|
||||||
|
@ -24,10 +24,10 @@ namespace osu.Game.Tests.Chat
|
|||||||
[TestCase(LinkAction.OpenBeatmap, "456", "https://dev.ppy.sh/beatmapsets/123#osu/456")]
|
[TestCase(LinkAction.OpenBeatmap, "456", "https://dev.ppy.sh/beatmapsets/123#osu/456")]
|
||||||
[TestCase(LinkAction.OpenBeatmap, "456", "https://dev.ppy.sh/beatmapsets/123#osu/456?whatever")]
|
[TestCase(LinkAction.OpenBeatmap, "456", "https://dev.ppy.sh/beatmapsets/123#osu/456?whatever")]
|
||||||
[TestCase(LinkAction.OpenBeatmap, "456", "https://dev.ppy.sh/beatmapsets/123/456")]
|
[TestCase(LinkAction.OpenBeatmap, "456", "https://dev.ppy.sh/beatmapsets/123/456")]
|
||||||
[TestCase(LinkAction.External, null, "https://dev.ppy.sh/beatmapsets/abc/def")]
|
[TestCase(LinkAction.External, "https://dev.ppy.sh/beatmapsets/abc/def", "https://dev.ppy.sh/beatmapsets/abc/def")]
|
||||||
[TestCase(LinkAction.OpenBeatmapSet, "123", "https://dev.ppy.sh/beatmapsets/123")]
|
[TestCase(LinkAction.OpenBeatmapSet, "123", "https://dev.ppy.sh/beatmapsets/123")]
|
||||||
[TestCase(LinkAction.OpenBeatmapSet, "123", "https://dev.ppy.sh/beatmapsets/123/whatever")]
|
[TestCase(LinkAction.OpenBeatmapSet, "123", "https://dev.ppy.sh/beatmapsets/123/whatever")]
|
||||||
[TestCase(LinkAction.External, null, "https://dev.ppy.sh/beatmapsets/abc")]
|
[TestCase(LinkAction.External, "https://dev.ppy.sh/beatmapsets/abc", "https://dev.ppy.sh/beatmapsets/abc")]
|
||||||
public void TestBeatmapLinks(LinkAction expectedAction, string expectedArg, string link)
|
public void TestBeatmapLinks(LinkAction expectedAction, string expectedArg, string link)
|
||||||
{
|
{
|
||||||
MessageFormatter.WebsiteRootUrl = "dev.ppy.sh";
|
MessageFormatter.WebsiteRootUrl = "dev.ppy.sh";
|
||||||
|
@ -14,7 +14,7 @@ namespace osu.Game.Tests.Gameplay
|
|||||||
public class TestSceneHitObjectSamples : HitObjectSampleTest
|
public class TestSceneHitObjectSamples : HitObjectSampleTest
|
||||||
{
|
{
|
||||||
protected override Ruleset CreatePlayerRuleset() => new OsuRuleset();
|
protected override Ruleset CreatePlayerRuleset() => new OsuRuleset();
|
||||||
protected override IResourceStore<byte[]> Resources => TestResources.GetStore();
|
protected override IResourceStore<byte[]> RulesetResources => TestResources.GetStore();
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Tests that a hitobject which provides no custom sample set retrieves samples from the user skin.
|
/// Tests that a hitobject which provides no custom sample set retrieves samples from the user skin.
|
||||||
|
@ -219,6 +219,7 @@ namespace osu.Game.Tests.Gameplay
|
|||||||
|
|
||||||
public AudioManager AudioManager => Audio;
|
public AudioManager AudioManager => Audio;
|
||||||
public IResourceStore<byte[]> Files => null;
|
public IResourceStore<byte[]> Files => null;
|
||||||
|
public new IResourceStore<byte[]> Resources => base.Resources;
|
||||||
public IResourceStore<TextureUpload> CreateTextureLoaderStore(IResourceStore<byte[]> underlyingStore) => null;
|
public IResourceStore<TextureUpload> CreateTextureLoaderStore(IResourceStore<byte[]> underlyingStore) => null;
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
@ -12,6 +12,7 @@ using osu.Framework.Allocation;
|
|||||||
using osu.Framework.Audio;
|
using osu.Framework.Audio;
|
||||||
using osu.Framework.Bindables;
|
using osu.Framework.Bindables;
|
||||||
using osu.Framework.Extensions;
|
using osu.Framework.Extensions;
|
||||||
|
using osu.Framework.IO.Stores;
|
||||||
using osu.Framework.Platform;
|
using osu.Framework.Platform;
|
||||||
using osu.Framework.Testing;
|
using osu.Framework.Testing;
|
||||||
using osu.Game.Beatmaps;
|
using osu.Game.Beatmaps;
|
||||||
@ -44,7 +45,7 @@ namespace osu.Game.Tests.Online
|
|||||||
private void load(AudioManager audio, GameHost host)
|
private void load(AudioManager audio, GameHost host)
|
||||||
{
|
{
|
||||||
Dependencies.Cache(rulesets = new RulesetStore(ContextFactory));
|
Dependencies.Cache(rulesets = new RulesetStore(ContextFactory));
|
||||||
Dependencies.CacheAs<BeatmapManager>(beatmaps = new TestBeatmapManager(LocalStorage, ContextFactory, rulesets, API, audio, host, Beatmap.Default));
|
Dependencies.CacheAs<BeatmapManager>(beatmaps = new TestBeatmapManager(LocalStorage, ContextFactory, rulesets, API, audio, Resources, host, Beatmap.Default));
|
||||||
}
|
}
|
||||||
|
|
||||||
[SetUp]
|
[SetUp]
|
||||||
@ -160,8 +161,8 @@ namespace osu.Game.Tests.Online
|
|||||||
protected override ArchiveDownloadRequest<BeatmapSetInfo> CreateDownloadRequest(BeatmapSetInfo set, bool minimiseDownloadSize)
|
protected override ArchiveDownloadRequest<BeatmapSetInfo> CreateDownloadRequest(BeatmapSetInfo set, bool minimiseDownloadSize)
|
||||||
=> new TestDownloadRequest(set);
|
=> new TestDownloadRequest(set);
|
||||||
|
|
||||||
public TestBeatmapManager(Storage storage, IDatabaseContextFactory contextFactory, RulesetStore rulesets, IAPIProvider api, [NotNull] AudioManager audioManager, GameHost host = null, WorkingBeatmap defaultBeatmap = null, bool performOnlineLookups = false)
|
public TestBeatmapManager(Storage storage, IDatabaseContextFactory contextFactory, RulesetStore rulesets, IAPIProvider api, [NotNull] AudioManager audioManager, IResourceStore<byte[]> resources, GameHost host = null, WorkingBeatmap defaultBeatmap = null, bool performOnlineLookups = false)
|
||||||
: base(storage, contextFactory, rulesets, api, audioManager, host, defaultBeatmap, performOnlineLookups)
|
: base(storage, contextFactory, rulesets, api, audioManager, resources, host, defaultBeatmap, performOnlineLookups)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -48,7 +48,7 @@ namespace osu.Game.Tests.Visual.Background
|
|||||||
private void load(GameHost host, AudioManager audio)
|
private void load(GameHost host, AudioManager audio)
|
||||||
{
|
{
|
||||||
Dependencies.Cache(rulesets = new RulesetStore(ContextFactory));
|
Dependencies.Cache(rulesets = new RulesetStore(ContextFactory));
|
||||||
Dependencies.Cache(manager = new BeatmapManager(LocalStorage, ContextFactory, rulesets, null, audio, host, Beatmap.Default));
|
Dependencies.Cache(manager = new BeatmapManager(LocalStorage, ContextFactory, rulesets, null, audio, Resources, host, Beatmap.Default));
|
||||||
Dependencies.Cache(new OsuConfigManager(LocalStorage));
|
Dependencies.Cache(new OsuConfigManager(LocalStorage));
|
||||||
|
|
||||||
manager.Import(TestResources.GetQuickTestBeatmapForImport()).Wait();
|
manager.Import(TestResources.GetQuickTestBeatmapForImport()).Wait();
|
||||||
|
@ -36,7 +36,7 @@ namespace osu.Game.Tests.Visual.Collections
|
|||||||
private void load(GameHost host)
|
private void load(GameHost host)
|
||||||
{
|
{
|
||||||
Dependencies.Cache(rulesets = new RulesetStore(ContextFactory));
|
Dependencies.Cache(rulesets = new RulesetStore(ContextFactory));
|
||||||
Dependencies.Cache(beatmapManager = new BeatmapManager(LocalStorage, ContextFactory, rulesets, null, Audio, host, Beatmap.Default));
|
Dependencies.Cache(beatmapManager = new BeatmapManager(LocalStorage, ContextFactory, rulesets, null, Audio, Resources, host, Beatmap.Default));
|
||||||
|
|
||||||
beatmapManager.Import(TestResources.GetQuickTestBeatmapForImport()).Wait();
|
beatmapManager.Import(TestResources.GetQuickTestBeatmapForImport()).Wait();
|
||||||
|
|
||||||
|
@ -24,13 +24,13 @@ namespace osu.Game.Tests.Visual.Editing
|
|||||||
|
|
||||||
protected override bool EditorComponentsReady => Editor.ChildrenOfType<SetupScreen>().SingleOrDefault()?.IsLoaded == true;
|
protected override bool EditorComponentsReady => Editor.ChildrenOfType<SetupScreen>().SingleOrDefault()?.IsLoaded == true;
|
||||||
|
|
||||||
|
protected override bool IsolateSavingFromDatabase => false;
|
||||||
|
|
||||||
[Resolved]
|
[Resolved]
|
||||||
private BeatmapManager beatmapManager { get; set; }
|
private BeatmapManager beatmapManager { get; set; }
|
||||||
|
|
||||||
public override void SetUpSteps()
|
public override void SetUpSteps()
|
||||||
{
|
{
|
||||||
AddStep("set dummy", () => Beatmap.Value = new DummyWorkingBeatmap(Audio, null));
|
|
||||||
|
|
||||||
base.SetUpSteps();
|
base.SetUpSteps();
|
||||||
|
|
||||||
// if we save a beatmap with a hash collision, things fall over.
|
// if we save a beatmap with a hash collision, things fall over.
|
||||||
@ -38,6 +38,12 @@ namespace osu.Game.Tests.Visual.Editing
|
|||||||
AddStep("make new beatmap unique", () => EditorBeatmap.Metadata.Title = Guid.NewGuid().ToString());
|
AddStep("make new beatmap unique", () => EditorBeatmap.Metadata.Title = Guid.NewGuid().ToString());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected override void LoadEditor()
|
||||||
|
{
|
||||||
|
Beatmap.Value = new DummyWorkingBeatmap(Audio, null);
|
||||||
|
base.LoadEditor();
|
||||||
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
public void TestCreateNewBeatmap()
|
public void TestCreateNewBeatmap()
|
||||||
{
|
{
|
||||||
|
@ -37,7 +37,7 @@ namespace osu.Game.Tests.Visual.Multiplayer
|
|||||||
private void load(GameHost host, AudioManager audio)
|
private void load(GameHost host, AudioManager audio)
|
||||||
{
|
{
|
||||||
Dependencies.Cache(rulesets = new RulesetStore(ContextFactory));
|
Dependencies.Cache(rulesets = new RulesetStore(ContextFactory));
|
||||||
Dependencies.Cache(manager = new BeatmapManager(LocalStorage, ContextFactory, rulesets, null, audio, host, Beatmap.Default));
|
Dependencies.Cache(manager = new BeatmapManager(LocalStorage, ContextFactory, rulesets, null, audio, Resources, host, Beatmap.Default));
|
||||||
|
|
||||||
manager.Import(new TestBeatmap(new OsuRuleset().RulesetInfo).BeatmapInfo.BeatmapSet).Wait();
|
manager.Import(new TestBeatmap(new OsuRuleset().RulesetInfo).BeatmapInfo.BeatmapSet).Wait();
|
||||||
}
|
}
|
||||||
|
@ -43,7 +43,7 @@ namespace osu.Game.Tests.Visual.Multiplayer
|
|||||||
private void load(GameHost host, AudioManager audio)
|
private void load(GameHost host, AudioManager audio)
|
||||||
{
|
{
|
||||||
Dependencies.Cache(rulesets = new RulesetStore(ContextFactory));
|
Dependencies.Cache(rulesets = new RulesetStore(ContextFactory));
|
||||||
Dependencies.Cache(beatmaps = new BeatmapManager(LocalStorage, ContextFactory, rulesets, null, audio, host, Beatmap.Default));
|
Dependencies.Cache(beatmaps = new BeatmapManager(LocalStorage, ContextFactory, rulesets, null, audio, Resources, host, Beatmap.Default));
|
||||||
}
|
}
|
||||||
|
|
||||||
[SetUp]
|
[SetUp]
|
||||||
|
@ -42,7 +42,7 @@ namespace osu.Game.Tests.Visual.Multiplayer
|
|||||||
private void load(GameHost host, AudioManager audio)
|
private void load(GameHost host, AudioManager audio)
|
||||||
{
|
{
|
||||||
Dependencies.Cache(rulesets = new RulesetStore(ContextFactory));
|
Dependencies.Cache(rulesets = new RulesetStore(ContextFactory));
|
||||||
Dependencies.Cache(manager = new BeatmapManager(LocalStorage, ContextFactory, rulesets, null, audio, host, Beatmap.Default));
|
Dependencies.Cache(manager = new BeatmapManager(LocalStorage, ContextFactory, rulesets, null, audio, Resources, host, Beatmap.Default));
|
||||||
|
|
||||||
beatmaps = new List<BeatmapInfo>();
|
beatmaps = new List<BeatmapInfo>();
|
||||||
|
|
||||||
|
@ -40,7 +40,7 @@ namespace osu.Game.Tests.Visual.Multiplayer
|
|||||||
private void load(GameHost host, AudioManager audio)
|
private void load(GameHost host, AudioManager audio)
|
||||||
{
|
{
|
||||||
Dependencies.Cache(rulesets = new RulesetStore(ContextFactory));
|
Dependencies.Cache(rulesets = new RulesetStore(ContextFactory));
|
||||||
Dependencies.Cache(beatmaps = new BeatmapManager(LocalStorage, ContextFactory, rulesets, null, audio, host, Beatmap.Default));
|
Dependencies.Cache(beatmaps = new BeatmapManager(LocalStorage, ContextFactory, rulesets, null, audio, Resources, host, Beatmap.Default));
|
||||||
beatmaps.Import(TestResources.GetQuickTestBeatmapForImport()).Wait();
|
beatmaps.Import(TestResources.GetQuickTestBeatmapForImport()).Wait();
|
||||||
|
|
||||||
importedSet = beatmaps.GetAllUsableBeatmapSetsEnumerable(IncludedDetails.All).First();
|
importedSet = beatmaps.GetAllUsableBeatmapSetsEnumerable(IncludedDetails.All).First();
|
||||||
|
@ -41,7 +41,7 @@ namespace osu.Game.Tests.Visual.Multiplayer
|
|||||||
private void load(GameHost host, AudioManager audio)
|
private void load(GameHost host, AudioManager audio)
|
||||||
{
|
{
|
||||||
Dependencies.Cache(rulesets = new RulesetStore(ContextFactory));
|
Dependencies.Cache(rulesets = new RulesetStore(ContextFactory));
|
||||||
Dependencies.Cache(beatmaps = new BeatmapManager(LocalStorage, ContextFactory, rulesets, null, audio, host, Beatmap.Default));
|
Dependencies.Cache(beatmaps = new BeatmapManager(LocalStorage, ContextFactory, rulesets, null, audio, Resources, host, Beatmap.Default));
|
||||||
beatmaps.Import(TestResources.GetQuickTestBeatmapForImport()).Wait();
|
beatmaps.Import(TestResources.GetQuickTestBeatmapForImport()).Wait();
|
||||||
|
|
||||||
Add(beatmapTracker = new OnlinePlayBeatmapAvailabilityTracker
|
Add(beatmapTracker = new OnlinePlayBeatmapAvailabilityTracker
|
||||||
|
@ -141,14 +141,21 @@ namespace osu.Game.Tests.Visual.Multiplayer
|
|||||||
|
|
||||||
private Room createRoom(Action<Room> initFunc = null)
|
private Room createRoom(Action<Room> initFunc = null)
|
||||||
{
|
{
|
||||||
var room = new Room();
|
var room = new Room
|
||||||
|
|
||||||
room.Name.Value = "test room";
|
|
||||||
room.Playlist.Add(new PlaylistItem
|
|
||||||
{
|
{
|
||||||
Beatmap = { Value = new TestBeatmap(Ruleset.Value).BeatmapInfo },
|
Name =
|
||||||
Ruleset = { Value = Ruleset.Value }
|
{
|
||||||
});
|
Value = "test room"
|
||||||
|
},
|
||||||
|
Playlist =
|
||||||
|
{
|
||||||
|
new PlaylistItem
|
||||||
|
{
|
||||||
|
Beatmap = { Value = new TestBeatmap(Ruleset.Value).BeatmapInfo },
|
||||||
|
Ruleset = { Value = Ruleset.Value }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
initFunc?.Invoke(room);
|
initFunc?.Invoke(room);
|
||||||
return room;
|
return room;
|
||||||
|
@ -59,7 +59,7 @@ namespace osu.Game.Tests.Visual.Multiplayer
|
|||||||
private void load(GameHost host, AudioManager audio)
|
private void load(GameHost host, AudioManager audio)
|
||||||
{
|
{
|
||||||
Dependencies.Cache(rulesets = new RulesetStore(ContextFactory));
|
Dependencies.Cache(rulesets = new RulesetStore(ContextFactory));
|
||||||
Dependencies.Cache(beatmaps = new BeatmapManager(LocalStorage, ContextFactory, rulesets, null, audio, host, Beatmap.Default));
|
Dependencies.Cache(beatmaps = new BeatmapManager(LocalStorage, ContextFactory, rulesets, null, audio, Resources, host, Beatmap.Default));
|
||||||
|
|
||||||
var beatmapTracker = new OnlinePlayBeatmapAvailabilityTracker { SelectedItem = { BindTarget = selectedItem } };
|
var beatmapTracker = new OnlinePlayBeatmapAvailabilityTracker { SelectedItem = { BindTarget = selectedItem } };
|
||||||
base.Content.Add(beatmapTracker);
|
base.Content.Add(beatmapTracker);
|
||||||
|
@ -38,7 +38,7 @@ namespace osu.Game.Tests.Visual.Multiplayer
|
|||||||
private void load(GameHost host, AudioManager audio)
|
private void load(GameHost host, AudioManager audio)
|
||||||
{
|
{
|
||||||
Dependencies.Cache(rulesets = new RulesetStore(ContextFactory));
|
Dependencies.Cache(rulesets = new RulesetStore(ContextFactory));
|
||||||
Dependencies.Cache(manager = new BeatmapManager(LocalStorage, ContextFactory, rulesets, null, audio, host, Beatmap.Default));
|
Dependencies.Cache(manager = new BeatmapManager(LocalStorage, ContextFactory, rulesets, null, audio, Resources, host, Beatmap.Default));
|
||||||
|
|
||||||
var beatmaps = new List<BeatmapInfo>();
|
var beatmaps = new List<BeatmapInfo>();
|
||||||
|
|
||||||
|
102
osu.Game.Tests/Visual/Online/TestSceneWikiHeader.cs
Normal file
102
osu.Game.Tests/Visual/Online/TestSceneWikiHeader.cs
Normal file
@ -0,0 +1,102 @@
|
|||||||
|
// 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.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using NUnit.Framework;
|
||||||
|
using osu.Framework.Allocation;
|
||||||
|
using osu.Framework.Bindables;
|
||||||
|
using osu.Framework.Graphics;
|
||||||
|
using osu.Game.Online.API.Requests.Responses;
|
||||||
|
using osu.Game.Overlays;
|
||||||
|
using osu.Game.Overlays.Wiki;
|
||||||
|
|
||||||
|
namespace osu.Game.Tests.Visual.Online
|
||||||
|
{
|
||||||
|
public class TestSceneWikiHeader : OsuTestScene
|
||||||
|
{
|
||||||
|
[Cached]
|
||||||
|
private readonly OverlayColourProvider colourProvider = new OverlayColourProvider(OverlayColourScheme.Orange);
|
||||||
|
|
||||||
|
[Cached]
|
||||||
|
private readonly Bindable<APIWikiPage> wikiPageData = new Bindable<APIWikiPage>(new APIWikiPage
|
||||||
|
{
|
||||||
|
Title = "Main Page",
|
||||||
|
Path = "Main_Page",
|
||||||
|
});
|
||||||
|
|
||||||
|
private TestHeader header;
|
||||||
|
|
||||||
|
[SetUp]
|
||||||
|
public void SetUp() => Schedule(() =>
|
||||||
|
{
|
||||||
|
Child = header = new TestHeader
|
||||||
|
{
|
||||||
|
Anchor = Anchor.Centre,
|
||||||
|
Origin = Anchor.Centre,
|
||||||
|
ShowIndexPage = dummyShowIndexPage,
|
||||||
|
ShowParentPage = dummyShowParentPage,
|
||||||
|
};
|
||||||
|
wikiPageData.BindTo(header.WikiPageData);
|
||||||
|
});
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void TestWikiHeader()
|
||||||
|
{
|
||||||
|
AddAssert("Current is index", () => checkCurrent("index"));
|
||||||
|
|
||||||
|
AddStep("Change wiki page data", () => wikiPageData.Value = new APIWikiPage
|
||||||
|
{
|
||||||
|
Title = "Welcome",
|
||||||
|
Path = "Welcome"
|
||||||
|
});
|
||||||
|
AddAssert("Current is welcome", () => checkCurrent("Welcome"));
|
||||||
|
AddAssert("Check breadcrumb", checkBreadcrumb);
|
||||||
|
|
||||||
|
AddStep("Change current to index", () => header.Current.Value = "index");
|
||||||
|
AddAssert("Current is index", () => checkCurrent("index"));
|
||||||
|
|
||||||
|
AddStep("Change wiki page data", () => wikiPageData.Value = new APIWikiPage
|
||||||
|
{
|
||||||
|
Title = "Developers",
|
||||||
|
Path = "People/The_Team/Developers",
|
||||||
|
Subtitle = "The Team",
|
||||||
|
});
|
||||||
|
AddAssert("Current is 'Developers'", () => checkCurrent("Developers"));
|
||||||
|
AddAssert("Check breadcrumb", checkBreadcrumb);
|
||||||
|
|
||||||
|
AddStep("Change current to 'The Team'", () => header.Current.Value = "The Team");
|
||||||
|
AddAssert("Current is 'The Team'", () => checkCurrent("The Team"));
|
||||||
|
AddAssert("Check breadcrumb", checkBreadcrumb);
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool checkCurrent(string expectedCurrent) => header.Current.Value == expectedCurrent;
|
||||||
|
|
||||||
|
private bool checkBreadcrumb()
|
||||||
|
{
|
||||||
|
var result = header.TabControlItems.Contains(wikiPageData.Value.Title);
|
||||||
|
|
||||||
|
if (wikiPageData.Value.Subtitle != null)
|
||||||
|
result = header.TabControlItems.Contains(wikiPageData.Value.Subtitle) && result;
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void dummyShowIndexPage() => wikiPageData.SetDefault();
|
||||||
|
|
||||||
|
private void dummyShowParentPage()
|
||||||
|
{
|
||||||
|
wikiPageData.Value = new APIWikiPage
|
||||||
|
{
|
||||||
|
Path = "People/The_Team",
|
||||||
|
Title = "The Team",
|
||||||
|
Subtitle = "People"
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private class TestHeader : WikiHeader
|
||||||
|
{
|
||||||
|
public IReadOnlyList<string> TabControlItems => TabControl.Items;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -48,7 +48,7 @@ namespace osu.Game.Tests.Visual.Online
|
|||||||
[Test]
|
[Test]
|
||||||
public void TestLink()
|
public void TestLink()
|
||||||
{
|
{
|
||||||
AddStep("set current path", () => markdownContainer.CurrentPath = "Article_styling_criteria/");
|
AddStep("set current path", () => markdownContainer.CurrentPath = $"{API.WebsiteRootUrl}/wiki/Article_styling_criteria/");
|
||||||
|
|
||||||
AddStep("set '/wiki/Main_Page''", () => markdownContainer.Text = "[wiki main page](/wiki/Main_Page)");
|
AddStep("set '/wiki/Main_Page''", () => markdownContainer.Text = "[wiki main page](/wiki/Main_Page)");
|
||||||
AddAssert("check url", () => markdownContainer.Link.Url == $"{API.WebsiteRootUrl}/wiki/Main_Page");
|
AddAssert("check url", () => markdownContainer.Link.Url == $"{API.WebsiteRootUrl}/wiki/Main_Page");
|
||||||
@ -113,7 +113,7 @@ needs_cleanup: true
|
|||||||
AddStep("Add relative image", () =>
|
AddStep("Add relative image", () =>
|
||||||
{
|
{
|
||||||
markdownContainer.DocumentUrl = "https://dev.ppy.sh";
|
markdownContainer.DocumentUrl = "https://dev.ppy.sh";
|
||||||
markdownContainer.CurrentPath = "Interface/";
|
markdownContainer.CurrentPath = $"{API.WebsiteRootUrl}/wiki/Interface/";
|
||||||
markdownContainer.Text = "![intro](img/intro-screen.jpg)";
|
markdownContainer.Text = "![intro](img/intro-screen.jpg)";
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -124,7 +124,7 @@ needs_cleanup: true
|
|||||||
AddStep("Add paragraph with block image", () =>
|
AddStep("Add paragraph with block image", () =>
|
||||||
{
|
{
|
||||||
markdownContainer.DocumentUrl = "https://dev.ppy.sh";
|
markdownContainer.DocumentUrl = "https://dev.ppy.sh";
|
||||||
markdownContainer.CurrentPath = "Interface/";
|
markdownContainer.CurrentPath = $"{API.WebsiteRootUrl}/wiki/Interface/";
|
||||||
markdownContainer.Text = @"Line before image
|
markdownContainer.Text = @"Line before image
|
||||||
|
|
||||||
![play menu](img/play-menu.jpg ""Main Menu in osu!"")
|
![play menu](img/play-menu.jpg ""Main Menu in osu!"")
|
||||||
|
72
osu.Game.Tests/Visual/Online/TestSceneWikiOverlay.cs
Normal file
72
osu.Game.Tests/Visual/Online/TestSceneWikiOverlay.cs
Normal file
File diff suppressed because one or more lines are too long
@ -38,7 +38,7 @@ namespace osu.Game.Tests.Visual.Playlists
|
|||||||
private void load(GameHost host, AudioManager audio)
|
private void load(GameHost host, AudioManager audio)
|
||||||
{
|
{
|
||||||
Dependencies.Cache(rulesets = new RulesetStore(ContextFactory));
|
Dependencies.Cache(rulesets = new RulesetStore(ContextFactory));
|
||||||
Dependencies.Cache(manager = new BeatmapManager(LocalStorage, ContextFactory, rulesets, null, audio, host, Beatmap.Default));
|
Dependencies.Cache(manager = new BeatmapManager(LocalStorage, ContextFactory, rulesets, null, audio, Resources, host, Beatmap.Default));
|
||||||
|
|
||||||
manager.Import(new TestBeatmap(new OsuRuleset().RulesetInfo).BeatmapInfo.BeatmapSet).Wait();
|
manager.Import(new TestBeatmap(new OsuRuleset().RulesetInfo).BeatmapInfo.BeatmapSet).Wait();
|
||||||
|
|
||||||
|
@ -36,7 +36,7 @@ namespace osu.Game.Tests.Visual.SongSelect
|
|||||||
private void load(GameHost host)
|
private void load(GameHost host)
|
||||||
{
|
{
|
||||||
Dependencies.Cache(rulesets = new RulesetStore(ContextFactory));
|
Dependencies.Cache(rulesets = new RulesetStore(ContextFactory));
|
||||||
Dependencies.Cache(beatmapManager = new BeatmapManager(LocalStorage, ContextFactory, rulesets, null, Audio, host, Beatmap.Default));
|
Dependencies.Cache(beatmapManager = new BeatmapManager(LocalStorage, ContextFactory, rulesets, null, Audio, Resources, host, Beatmap.Default));
|
||||||
|
|
||||||
beatmapManager.Import(TestResources.GetQuickTestBeatmapForImport()).Wait();
|
beatmapManager.Import(TestResources.GetQuickTestBeatmapForImport()).Wait();
|
||||||
|
|
||||||
|
@ -47,7 +47,7 @@ namespace osu.Game.Tests.Visual.SongSelect
|
|||||||
private void load(GameHost host, AudioManager audio)
|
private void load(GameHost host, AudioManager audio)
|
||||||
{
|
{
|
||||||
Dependencies.Cache(rulesets = new RulesetStore(ContextFactory));
|
Dependencies.Cache(rulesets = new RulesetStore(ContextFactory));
|
||||||
Dependencies.Cache(manager = new BeatmapManager(LocalStorage, ContextFactory, rulesets, null, audio, host, defaultBeatmap = Beatmap.Default));
|
Dependencies.Cache(manager = new BeatmapManager(LocalStorage, ContextFactory, rulesets, null, audio, Resources, host, defaultBeatmap = Beatmap.Default));
|
||||||
|
|
||||||
Dependencies.Cache(music = new MusicController());
|
Dependencies.Cache(music = new MusicController());
|
||||||
|
|
||||||
|
@ -81,7 +81,7 @@ namespace osu.Game.Tests.Visual.UserInterface
|
|||||||
var dependencies = new DependencyContainer(base.CreateChildDependencies(parent));
|
var dependencies = new DependencyContainer(base.CreateChildDependencies(parent));
|
||||||
|
|
||||||
dependencies.Cache(rulesetStore = new RulesetStore(ContextFactory));
|
dependencies.Cache(rulesetStore = new RulesetStore(ContextFactory));
|
||||||
dependencies.Cache(beatmapManager = new BeatmapManager(LocalStorage, ContextFactory, rulesetStore, null, dependencies.Get<AudioManager>(), dependencies.Get<GameHost>(), Beatmap.Default));
|
dependencies.Cache(beatmapManager = new BeatmapManager(LocalStorage, ContextFactory, rulesetStore, null, dependencies.Get<AudioManager>(), Resources, dependencies.Get<GameHost>(), Beatmap.Default));
|
||||||
dependencies.Cache(scoreManager = new ScoreManager(rulesetStore, () => beatmapManager, LocalStorage, null, ContextFactory));
|
dependencies.Cache(scoreManager = new ScoreManager(rulesetStore, () => beatmapManager, LocalStorage, null, ContextFactory));
|
||||||
|
|
||||||
beatmap = beatmapManager.Import(new ImportTask(TestResources.GetQuickTestBeatmapForImport())).Result.Beatmaps[0];
|
beatmap = beatmapManager.Import(new ImportTask(TestResources.GetQuickTestBeatmapForImport())).Result.Beatmaps[0];
|
||||||
|
@ -17,11 +17,12 @@ namespace osu.Game.Tournament.Tests.Screens
|
|||||||
[BackgroundDependencyLoader]
|
[BackgroundDependencyLoader]
|
||||||
private void load()
|
private void load()
|
||||||
{
|
{
|
||||||
var match = new TournamentMatch();
|
ladder.CurrentMatch.Value = new TournamentMatch
|
||||||
match.Team1.Value = Ladder.Teams.FirstOrDefault(t => t.Acronym.Value == "USA");
|
{
|
||||||
match.Team2.Value = Ladder.Teams.FirstOrDefault(t => t.Acronym.Value == "JPN");
|
Team1 = { Value = Ladder.Teams.FirstOrDefault(t => t.Acronym.Value == "USA") },
|
||||||
match.Round.Value = Ladder.Rounds.FirstOrDefault(g => g.Name.Value == "Finals");
|
Team2 = { Value = Ladder.Teams.FirstOrDefault(t => t.Acronym.Value == "JPN") },
|
||||||
ladder.CurrentMatch.Value = match;
|
Round = { Value = Ladder.Rounds.FirstOrDefault(g => g.Name.Value == "Finals") }
|
||||||
|
};
|
||||||
|
|
||||||
Add(new TeamIntroScreen
|
Add(new TeamIntroScreen
|
||||||
{
|
{
|
||||||
|
@ -3,7 +3,6 @@
|
|||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Diagnostics;
|
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Linq.Expressions;
|
using System.Linq.Expressions;
|
||||||
@ -73,6 +72,7 @@ namespace osu.Game.Beatmaps
|
|||||||
private readonly RulesetStore rulesets;
|
private readonly RulesetStore rulesets;
|
||||||
private readonly BeatmapStore beatmaps;
|
private readonly BeatmapStore beatmaps;
|
||||||
private readonly AudioManager audioManager;
|
private readonly AudioManager audioManager;
|
||||||
|
private readonly IResourceStore<byte[]> resources;
|
||||||
private readonly LargeTextureStore largeTextureStore;
|
private readonly LargeTextureStore largeTextureStore;
|
||||||
private readonly ITrackStore trackStore;
|
private readonly ITrackStore trackStore;
|
||||||
|
|
||||||
@ -82,12 +82,13 @@ namespace osu.Game.Beatmaps
|
|||||||
[CanBeNull]
|
[CanBeNull]
|
||||||
private readonly BeatmapOnlineLookupQueue onlineLookupQueue;
|
private readonly BeatmapOnlineLookupQueue onlineLookupQueue;
|
||||||
|
|
||||||
public BeatmapManager(Storage storage, IDatabaseContextFactory contextFactory, RulesetStore rulesets, IAPIProvider api, [NotNull] AudioManager audioManager, GameHost host = null,
|
public BeatmapManager(Storage storage, IDatabaseContextFactory contextFactory, RulesetStore rulesets, IAPIProvider api, [NotNull] AudioManager audioManager, IResourceStore<byte[]> resources, GameHost host = null,
|
||||||
WorkingBeatmap defaultBeatmap = null, bool performOnlineLookups = false)
|
WorkingBeatmap defaultBeatmap = null, bool performOnlineLookups = false)
|
||||||
: base(storage, contextFactory, api, new BeatmapStore(contextFactory), host)
|
: base(storage, contextFactory, api, new BeatmapStore(contextFactory), host)
|
||||||
{
|
{
|
||||||
this.rulesets = rulesets;
|
this.rulesets = rulesets;
|
||||||
this.audioManager = audioManager;
|
this.audioManager = audioManager;
|
||||||
|
this.resources = resources;
|
||||||
this.host = host;
|
this.host = host;
|
||||||
|
|
||||||
DefaultBeatmap = defaultBeatmap;
|
DefaultBeatmap = defaultBeatmap;
|
||||||
@ -241,12 +242,10 @@ namespace osu.Game.Beatmaps
|
|||||||
/// <param name="info">The <see cref="BeatmapInfo"/> to save the content against. The file referenced by <see cref="BeatmapInfo.Path"/> will be replaced.</param>
|
/// <param name="info">The <see cref="BeatmapInfo"/> to save the content against. The file referenced by <see cref="BeatmapInfo.Path"/> will be replaced.</param>
|
||||||
/// <param name="beatmapContent">The <see cref="IBeatmap"/> content to write.</param>
|
/// <param name="beatmapContent">The <see cref="IBeatmap"/> content to write.</param>
|
||||||
/// <param name="beatmapSkin">The beatmap <see cref="ISkin"/> content to write, null if to be omitted.</param>
|
/// <param name="beatmapSkin">The beatmap <see cref="ISkin"/> content to write, null if to be omitted.</param>
|
||||||
public void Save(BeatmapInfo info, IBeatmap beatmapContent, ISkin beatmapSkin = null)
|
public virtual void Save(BeatmapInfo info, IBeatmap beatmapContent, ISkin beatmapSkin = null)
|
||||||
{
|
{
|
||||||
var setInfo = info.BeatmapSet;
|
var setInfo = info.BeatmapSet;
|
||||||
|
|
||||||
Debug.Assert(setInfo.Files != null);
|
|
||||||
|
|
||||||
using (var stream = new MemoryStream())
|
using (var stream = new MemoryStream())
|
||||||
{
|
{
|
||||||
using (var sw = new StreamWriter(stream, Encoding.UTF8, 1024, true))
|
using (var sw = new StreamWriter(stream, Encoding.UTF8, 1024, true))
|
||||||
@ -283,25 +282,17 @@ namespace osu.Game.Beatmaps
|
|||||||
/// Retrieve a <see cref="WorkingBeatmap"/> instance for the provided <see cref="BeatmapInfo"/>
|
/// Retrieve a <see cref="WorkingBeatmap"/> instance for the provided <see cref="BeatmapInfo"/>
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="beatmapInfo">The beatmap to lookup.</param>
|
/// <param name="beatmapInfo">The beatmap to lookup.</param>
|
||||||
/// <param name="previous">The currently loaded <see cref="WorkingBeatmap"/>. Allows for optimisation where elements are shared with the new beatmap. May be returned if beatmapInfo requested matches</param>
|
|
||||||
/// <returns>A <see cref="WorkingBeatmap"/> instance correlating to the provided <see cref="BeatmapInfo"/>.</returns>
|
/// <returns>A <see cref="WorkingBeatmap"/> instance correlating to the provided <see cref="BeatmapInfo"/>.</returns>
|
||||||
public WorkingBeatmap GetWorkingBeatmap(BeatmapInfo beatmapInfo, WorkingBeatmap previous = null)
|
public virtual WorkingBeatmap GetWorkingBeatmap(BeatmapInfo beatmapInfo)
|
||||||
{
|
{
|
||||||
if (beatmapInfo?.ID > 0 && previous != null && previous.BeatmapInfo?.ID == beatmapInfo.ID)
|
// if there are no files, presume the full beatmap info has not yet been fetched from the database.
|
||||||
return previous;
|
if (beatmapInfo?.BeatmapSet?.Files.Count == 0)
|
||||||
|
|
||||||
if (beatmapInfo?.BeatmapSet == null || beatmapInfo == DefaultBeatmap?.BeatmapInfo)
|
|
||||||
return DefaultBeatmap;
|
|
||||||
|
|
||||||
// force a re-query if files are not in a state which looks like the model has
|
|
||||||
// full database information present.
|
|
||||||
if (beatmapInfo.BeatmapSet.Files == null || beatmapInfo.BeatmapSet.Files.Count == 0)
|
|
||||||
{
|
{
|
||||||
var info = beatmapInfo;
|
int lookupId = beatmapInfo.ID;
|
||||||
beatmapInfo = QueryBeatmap(b => b.ID == info.ID);
|
beatmapInfo = QueryBeatmap(b => b.ID == lookupId);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (beatmapInfo == null)
|
if (beatmapInfo?.BeatmapSet == null)
|
||||||
return DefaultBeatmap;
|
return DefaultBeatmap;
|
||||||
|
|
||||||
lock (workingCache)
|
lock (workingCache)
|
||||||
@ -511,6 +502,7 @@ namespace osu.Game.Beatmaps
|
|||||||
ITrackStore IBeatmapResourceProvider.Tracks => trackStore;
|
ITrackStore IBeatmapResourceProvider.Tracks => trackStore;
|
||||||
AudioManager IStorageResourceProvider.AudioManager => audioManager;
|
AudioManager IStorageResourceProvider.AudioManager => audioManager;
|
||||||
IResourceStore<byte[]> IStorageResourceProvider.Files => Files.Store;
|
IResourceStore<byte[]> IStorageResourceProvider.Files => Files.Store;
|
||||||
|
IResourceStore<byte[]> IStorageResourceProvider.Resources => resources;
|
||||||
IResourceStore<TextureUpload> IStorageResourceProvider.CreateTextureLoaderStore(IResourceStore<byte[]> underlyingStore) => host?.CreateTextureLoaderStore(underlyingStore);
|
IResourceStore<TextureUpload> IStorageResourceProvider.CreateTextureLoaderStore(IResourceStore<byte[]> underlyingStore) => host?.CreateTextureLoaderStore(underlyingStore);
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
@ -5,6 +5,7 @@ using System;
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.ComponentModel.DataAnnotations.Schema;
|
using System.ComponentModel.DataAnnotations.Schema;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using JetBrains.Annotations;
|
||||||
using osu.Framework.Testing;
|
using osu.Framework.Testing;
|
||||||
using osu.Game.Database;
|
using osu.Game.Database;
|
||||||
|
|
||||||
@ -31,6 +32,9 @@ namespace osu.Game.Beatmaps
|
|||||||
|
|
||||||
public List<BeatmapInfo> Beatmaps { get; set; }
|
public List<BeatmapInfo> Beatmaps { get; set; }
|
||||||
|
|
||||||
|
[NotNull]
|
||||||
|
public List<BeatmapSetFileInfo> Files { get; set; } = new List<BeatmapSetFileInfo>();
|
||||||
|
|
||||||
[NotMapped]
|
[NotMapped]
|
||||||
public BeatmapSetOnlineInfo OnlineInfo { get; set; }
|
public BeatmapSetOnlineInfo OnlineInfo { get; set; }
|
||||||
|
|
||||||
@ -57,16 +61,14 @@ namespace osu.Game.Beatmaps
|
|||||||
|
|
||||||
public string Hash { get; set; }
|
public string Hash { get; set; }
|
||||||
|
|
||||||
public string StoryboardFile => Files?.Find(f => f.Filename.EndsWith(".osb", StringComparison.OrdinalIgnoreCase))?.Filename;
|
public string StoryboardFile => Files.Find(f => f.Filename.EndsWith(".osb", StringComparison.OrdinalIgnoreCase))?.Filename;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Returns the storage path for the file in this beatmapset with the given filename, if any exists, otherwise null.
|
/// Returns the storage path for the file in this beatmapset with the given filename, if any exists, otherwise null.
|
||||||
/// The path returned is relative to the user file storage.
|
/// The path returned is relative to the user file storage.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="filename">The name of the file to get the storage path of.</param>
|
/// <param name="filename">The name of the file to get the storage path of.</param>
|
||||||
public string GetPathForFile(string filename) => Files?.SingleOrDefault(f => string.Equals(f.Filename, filename, StringComparison.OrdinalIgnoreCase))?.FileInfo.StoragePath;
|
public string GetPathForFile(string filename) => Files.SingleOrDefault(f => string.Equals(f.Filename, filename, StringComparison.OrdinalIgnoreCase))?.FileInfo.StoragePath;
|
||||||
|
|
||||||
public List<BeatmapSetFileInfo> Files { get; set; }
|
|
||||||
|
|
||||||
public override string ToString() => Metadata?.ToString() ?? base.ToString();
|
public override string ToString() => Metadata?.ToString() ?? base.ToString();
|
||||||
|
|
||||||
|
@ -6,13 +6,11 @@ using Markdig.Extensions.AutoIdentifiers;
|
|||||||
using Markdig.Extensions.Tables;
|
using Markdig.Extensions.Tables;
|
||||||
using Markdig.Extensions.Yaml;
|
using Markdig.Extensions.Yaml;
|
||||||
using Markdig.Syntax;
|
using Markdig.Syntax;
|
||||||
using osu.Framework.Allocation;
|
|
||||||
using osu.Framework.Graphics;
|
using osu.Framework.Graphics;
|
||||||
using osu.Framework.Graphics.Containers;
|
using osu.Framework.Graphics.Containers;
|
||||||
using osu.Framework.Graphics.Containers.Markdown;
|
using osu.Framework.Graphics.Containers.Markdown;
|
||||||
using osu.Framework.Graphics.Sprites;
|
using osu.Framework.Graphics.Sprites;
|
||||||
using osu.Game.Graphics.Sprites;
|
using osu.Game.Graphics.Sprites;
|
||||||
using osu.Game.Online.API;
|
|
||||||
|
|
||||||
namespace osu.Game.Graphics.Containers.Markdown
|
namespace osu.Game.Graphics.Containers.Markdown
|
||||||
{
|
{
|
||||||
@ -23,16 +21,6 @@ namespace osu.Game.Graphics.Containers.Markdown
|
|||||||
LineSpacing = 21;
|
LineSpacing = 21;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override IReadOnlyDependencyContainer CreateChildDependencies(IReadOnlyDependencyContainer parent)
|
|
||||||
{
|
|
||||||
var api = parent.Get<IAPIProvider>();
|
|
||||||
|
|
||||||
// needs to be set before the base BDL call executes to avoid invalidating any already populated markdown content.
|
|
||||||
DocumentUrl = api.WebsiteRootUrl;
|
|
||||||
|
|
||||||
return base.CreateChildDependencies(parent);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override void AddMarkdownComponent(IMarkdownObject markdownObject, FillFlowContainer container, int level)
|
protected override void AddMarkdownComponent(IMarkdownObject markdownObject, FillFlowContainer container, int level)
|
||||||
{
|
{
|
||||||
switch (markdownObject)
|
switch (markdownObject)
|
||||||
|
@ -19,6 +19,11 @@ namespace osu.Game.IO
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
IResourceStore<byte[]> Files { get; }
|
IResourceStore<byte[]> Files { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Access game-wide resources.
|
||||||
|
/// </summary>
|
||||||
|
IResourceStore<byte[]> Resources { get; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Create a texture loader store based on an underlying data store.
|
/// Create a texture loader store based on an underlying data store.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
21
osu.Game/Online/API/Requests/GetWikiRequest.cs
Normal file
21
osu.Game/Online/API/Requests/GetWikiRequest.cs
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
// 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 osu.Game.Online.API.Requests.Responses;
|
||||||
|
|
||||||
|
namespace osu.Game.Online.API.Requests
|
||||||
|
{
|
||||||
|
public class GetWikiRequest : APIRequest<APIWikiPage>
|
||||||
|
{
|
||||||
|
private readonly string path;
|
||||||
|
private readonly string locale;
|
||||||
|
|
||||||
|
public GetWikiRequest(string path, string locale = "en")
|
||||||
|
{
|
||||||
|
this.path = path;
|
||||||
|
this.locale = locale;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override string Target => $"wiki/{locale}/{path}";
|
||||||
|
}
|
||||||
|
}
|
32
osu.Game/Online/API/Requests/Responses/APIWikiPage.cs
Normal file
32
osu.Game/Online/API/Requests/Responses/APIWikiPage.cs
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
// 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.Collections.Generic;
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
|
||||||
|
namespace osu.Game.Online.API.Requests.Responses
|
||||||
|
{
|
||||||
|
public class APIWikiPage
|
||||||
|
{
|
||||||
|
[JsonProperty("layout")]
|
||||||
|
public string Layout { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("locale")]
|
||||||
|
public string Locale { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("markdown")]
|
||||||
|
public string Markdown { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("path")]
|
||||||
|
public string Path { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("subtitle")]
|
||||||
|
public string Subtitle { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("tags")]
|
||||||
|
public List<string> Tags { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("title")]
|
||||||
|
public string Title { get; set; }
|
||||||
|
}
|
||||||
|
}
|
@ -167,10 +167,13 @@ namespace osu.Game.Online.Chat
|
|||||||
case "u":
|
case "u":
|
||||||
case "users":
|
case "users":
|
||||||
return new LinkDetails(LinkAction.OpenUserProfile, mainArg);
|
return new LinkDetails(LinkAction.OpenUserProfile, mainArg);
|
||||||
|
|
||||||
|
case "wiki":
|
||||||
|
return new LinkDetails(LinkAction.OpenWiki, string.Join('/', args.Skip(3)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return new LinkDetails(LinkAction.External, null);
|
return new LinkDetails(LinkAction.External, url);
|
||||||
|
|
||||||
case "osu":
|
case "osu":
|
||||||
// every internal link also needs some kind of argument
|
// every internal link also needs some kind of argument
|
||||||
@ -311,7 +314,8 @@ namespace osu.Game.Online.Chat
|
|||||||
JoinMultiplayerMatch,
|
JoinMultiplayerMatch,
|
||||||
Spectate,
|
Spectate,
|
||||||
OpenUserProfile,
|
OpenUserProfile,
|
||||||
Custom
|
OpenWiki,
|
||||||
|
Custom,
|
||||||
}
|
}
|
||||||
|
|
||||||
public class Link : IComparable<Link>
|
public class Link : IComparable<Link>
|
||||||
|
@ -81,6 +81,8 @@ namespace osu.Game
|
|||||||
|
|
||||||
private BeatmapSetOverlay beatmapSetOverlay;
|
private BeatmapSetOverlay beatmapSetOverlay;
|
||||||
|
|
||||||
|
private WikiOverlay wikiOverlay;
|
||||||
|
|
||||||
private SkinEditorOverlay skinEditor;
|
private SkinEditorOverlay skinEditor;
|
||||||
|
|
||||||
private Container overlayContent;
|
private Container overlayContent;
|
||||||
@ -307,6 +309,10 @@ namespace osu.Game
|
|||||||
ShowUser(userId);
|
ShowUser(userId);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case LinkAction.OpenWiki:
|
||||||
|
ShowWiki(link.Argument);
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
throw new NotImplementedException($"This {nameof(LinkAction)} ({link.Action.ToString()}) is missing an associated action.");
|
throw new NotImplementedException($"This {nameof(LinkAction)} ({link.Action.ToString()}) is missing an associated action.");
|
||||||
}
|
}
|
||||||
@ -354,6 +360,12 @@ namespace osu.Game
|
|||||||
/// <param name="beatmapId">The beatmap to show.</param>
|
/// <param name="beatmapId">The beatmap to show.</param>
|
||||||
public void ShowBeatmap(int beatmapId) => waitForReady(() => beatmapSetOverlay, _ => beatmapSetOverlay.FetchAndShowBeatmap(beatmapId));
|
public void ShowBeatmap(int beatmapId) => waitForReady(() => beatmapSetOverlay, _ => beatmapSetOverlay.FetchAndShowBeatmap(beatmapId));
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Show a wiki's page as an overlay
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="path">The wiki page to show</param>
|
||||||
|
public void ShowWiki(string path) => waitForReady(() => wikiOverlay, _ => wikiOverlay.ShowPage(path));
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Present a beatmap at song select immediately.
|
/// Present a beatmap at song select immediately.
|
||||||
/// The user should have already requested this interactively.
|
/// The user should have already requested this interactively.
|
||||||
@ -719,6 +731,7 @@ namespace osu.Game
|
|||||||
var changelogOverlay = loadComponentSingleFile(new ChangelogOverlay(), overlayContent.Add, true);
|
var changelogOverlay = loadComponentSingleFile(new ChangelogOverlay(), overlayContent.Add, true);
|
||||||
loadComponentSingleFile(userProfile = new UserProfileOverlay(), overlayContent.Add, true);
|
loadComponentSingleFile(userProfile = new UserProfileOverlay(), overlayContent.Add, true);
|
||||||
loadComponentSingleFile(beatmapSetOverlay = new BeatmapSetOverlay(), overlayContent.Add, true);
|
loadComponentSingleFile(beatmapSetOverlay = new BeatmapSetOverlay(), overlayContent.Add, true);
|
||||||
|
loadComponentSingleFile(wikiOverlay = new WikiOverlay(), overlayContent.Add, true);
|
||||||
loadComponentSingleFile(skinEditor = new SkinEditorOverlay(screenContainer), overlayContent.Add);
|
loadComponentSingleFile(skinEditor = new SkinEditorOverlay(screenContainer), overlayContent.Add);
|
||||||
|
|
||||||
loadComponentSingleFile(new LoginOverlay
|
loadComponentSingleFile(new LoginOverlay
|
||||||
@ -769,7 +782,7 @@ namespace osu.Game
|
|||||||
}
|
}
|
||||||
|
|
||||||
// ensure only one of these overlays are open at once.
|
// ensure only one of these overlays are open at once.
|
||||||
var singleDisplayOverlays = new OverlayContainer[] { chatOverlay, news, dashboard, beatmapListing, changelogOverlay, rankingsOverlay };
|
var singleDisplayOverlays = new OverlayContainer[] { chatOverlay, news, dashboard, beatmapListing, changelogOverlay, rankingsOverlay, wikiOverlay };
|
||||||
|
|
||||||
foreach (var overlay in singleDisplayOverlays)
|
foreach (var overlay in singleDisplayOverlays)
|
||||||
{
|
{
|
||||||
|
@ -209,7 +209,7 @@ namespace osu.Game
|
|||||||
|
|
||||||
runMigrations();
|
runMigrations();
|
||||||
|
|
||||||
dependencies.Cache(SkinManager = new SkinManager(Storage, contextFactory, Host, Audio, new NamespacedResourceStore<byte[]>(Resources, "Skins/Legacy")));
|
dependencies.Cache(SkinManager = new SkinManager(Storage, contextFactory, Host, Resources, Audio));
|
||||||
dependencies.CacheAs<ISkinSource>(SkinManager);
|
dependencies.CacheAs<ISkinSource>(SkinManager);
|
||||||
|
|
||||||
// needs to be done here rather than inside SkinManager to ensure thread safety of CurrentSkinInfo.
|
// needs to be done here rather than inside SkinManager to ensure thread safety of CurrentSkinInfo.
|
||||||
@ -242,7 +242,7 @@ namespace osu.Game
|
|||||||
|
|
||||||
// ordering is important here to ensure foreign keys rules are not broken in ModelStore.Cleanup()
|
// ordering is important here to ensure foreign keys rules are not broken in ModelStore.Cleanup()
|
||||||
dependencies.Cache(ScoreManager = new ScoreManager(RulesetStore, () => BeatmapManager, Storage, API, contextFactory, Host, () => difficultyCache, LocalConfig));
|
dependencies.Cache(ScoreManager = new ScoreManager(RulesetStore, () => BeatmapManager, Storage, API, contextFactory, Host, () => difficultyCache, LocalConfig));
|
||||||
dependencies.Cache(BeatmapManager = new BeatmapManager(Storage, contextFactory, RulesetStore, API, Audio, Host, defaultBeatmap, true));
|
dependencies.Cache(BeatmapManager = new BeatmapManager(Storage, contextFactory, RulesetStore, API, Audio, Resources, Host, defaultBeatmap, true));
|
||||||
|
|
||||||
// this should likely be moved to ArchiveModelManager when another case appers where it is necessary
|
// this should likely be moved to ArchiveModelManager when another case appers where it is necessary
|
||||||
// to have inter-dependent model managers. this could be obtained with an IHasForeign<T> interface to
|
// to have inter-dependent model managers. this could be obtained with an IHasForeign<T> interface to
|
||||||
|
@ -252,7 +252,7 @@ namespace osu.Game.Overlays
|
|||||||
|
|
||||||
if (playable != null)
|
if (playable != null)
|
||||||
{
|
{
|
||||||
changeBeatmap(beatmaps.GetWorkingBeatmap(playable.Beatmaps.First(), beatmap.Value));
|
changeBeatmap(beatmaps.GetWorkingBeatmap(playable.Beatmaps.First()));
|
||||||
restartTrack();
|
restartTrack();
|
||||||
return PreviousTrackResult.Previous;
|
return PreviousTrackResult.Previous;
|
||||||
}
|
}
|
||||||
@ -283,7 +283,7 @@ namespace osu.Game.Overlays
|
|||||||
|
|
||||||
if (playable != null)
|
if (playable != null)
|
||||||
{
|
{
|
||||||
changeBeatmap(beatmaps.GetWorkingBeatmap(playable.Beatmaps.First(), beatmap.Value));
|
changeBeatmap(beatmaps.GetWorkingBeatmap(playable.Beatmaps.First()));
|
||||||
restartTrack();
|
restartTrack();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -92,6 +92,7 @@ namespace osu.Game.Overlays.Toolbar
|
|||||||
new ToolbarBeatmapListingButton(),
|
new ToolbarBeatmapListingButton(),
|
||||||
new ToolbarChatButton(),
|
new ToolbarChatButton(),
|
||||||
new ToolbarSocialButton(),
|
new ToolbarSocialButton(),
|
||||||
|
new ToolbarWikiButton(),
|
||||||
new ToolbarMusicButton(),
|
new ToolbarMusicButton(),
|
||||||
//new ToolbarButton
|
//new ToolbarButton
|
||||||
//{
|
//{
|
||||||
|
19
osu.Game/Overlays/Toolbar/ToolbarWikiButton.cs
Normal file
19
osu.Game/Overlays/Toolbar/ToolbarWikiButton.cs
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
// 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 osu.Framework.Allocation;
|
||||||
|
using osu.Framework.Graphics;
|
||||||
|
|
||||||
|
namespace osu.Game.Overlays.Toolbar
|
||||||
|
{
|
||||||
|
public class ToolbarWikiButton : ToolbarOverlayToggleButton
|
||||||
|
{
|
||||||
|
protected override Anchor TooltipAnchor => Anchor.TopRight;
|
||||||
|
|
||||||
|
[BackgroundDependencyLoader(true)]
|
||||||
|
private void load(WikiOverlay wiki)
|
||||||
|
{
|
||||||
|
StateContainer = wiki;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -5,17 +5,22 @@ using System.Linq;
|
|||||||
using Markdig.Extensions.Yaml;
|
using Markdig.Extensions.Yaml;
|
||||||
using Markdig.Syntax;
|
using Markdig.Syntax;
|
||||||
using Markdig.Syntax.Inlines;
|
using Markdig.Syntax.Inlines;
|
||||||
|
using osu.Framework.Allocation;
|
||||||
using osu.Framework.Graphics.Containers;
|
using osu.Framework.Graphics.Containers;
|
||||||
using osu.Framework.Graphics.Containers.Markdown;
|
using osu.Framework.Graphics.Containers.Markdown;
|
||||||
using osu.Game.Graphics.Containers.Markdown;
|
using osu.Game.Graphics.Containers.Markdown;
|
||||||
|
using osu.Game.Online.API;
|
||||||
|
|
||||||
namespace osu.Game.Overlays.Wiki.Markdown
|
namespace osu.Game.Overlays.Wiki.Markdown
|
||||||
{
|
{
|
||||||
public class WikiMarkdownContainer : OsuMarkdownContainer
|
public class WikiMarkdownContainer : OsuMarkdownContainer
|
||||||
{
|
{
|
||||||
|
[Resolved]
|
||||||
|
private IAPIProvider api { get; set; }
|
||||||
|
|
||||||
public string CurrentPath
|
public string CurrentPath
|
||||||
{
|
{
|
||||||
set => DocumentUrl = $"{DocumentUrl}wiki/{value}";
|
set => DocumentUrl = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void AddMarkdownComponent(IMarkdownObject markdownObject, FillFlowContainer container, int level)
|
protected override void AddMarkdownComponent(IMarkdownObject markdownObject, FillFlowContainer container, int level)
|
||||||
|
82
osu.Game/Overlays/Wiki/WikiHeader.cs
Normal file
82
osu.Game/Overlays/Wiki/WikiHeader.cs
Normal file
@ -0,0 +1,82 @@
|
|||||||
|
// 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.Linq;
|
||||||
|
using osu.Framework.Bindables;
|
||||||
|
using osu.Framework.Graphics;
|
||||||
|
using osu.Game.Online.API.Requests.Responses;
|
||||||
|
|
||||||
|
namespace osu.Game.Overlays.Wiki
|
||||||
|
{
|
||||||
|
public class WikiHeader : BreadcrumbControlOverlayHeader
|
||||||
|
{
|
||||||
|
private const string index_page_string = "index";
|
||||||
|
private const string index_path = "Main_Page";
|
||||||
|
|
||||||
|
public readonly Bindable<APIWikiPage> WikiPageData = new Bindable<APIWikiPage>();
|
||||||
|
|
||||||
|
public Action ShowIndexPage;
|
||||||
|
public Action ShowParentPage;
|
||||||
|
|
||||||
|
public WikiHeader()
|
||||||
|
{
|
||||||
|
TabControl.AddItem(index_page_string);
|
||||||
|
Current.Value = index_page_string;
|
||||||
|
|
||||||
|
WikiPageData.BindValueChanged(onWikiPageChange);
|
||||||
|
Current.BindValueChanged(onCurrentChange);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void onWikiPageChange(ValueChangedEvent<APIWikiPage> e)
|
||||||
|
{
|
||||||
|
if (e.NewValue == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
TabControl.Clear();
|
||||||
|
Current.Value = null;
|
||||||
|
|
||||||
|
TabControl.AddItem(index_page_string);
|
||||||
|
|
||||||
|
if (e.NewValue.Path == index_path)
|
||||||
|
{
|
||||||
|
Current.Value = index_page_string;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (e.NewValue.Subtitle != null)
|
||||||
|
TabControl.AddItem(e.NewValue.Subtitle);
|
||||||
|
|
||||||
|
TabControl.AddItem(e.NewValue.Title);
|
||||||
|
Current.Value = e.NewValue.Title;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void onCurrentChange(ValueChangedEvent<string> e)
|
||||||
|
{
|
||||||
|
if (e.NewValue == TabControl.Items.LastOrDefault())
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (e.NewValue == index_page_string)
|
||||||
|
{
|
||||||
|
ShowIndexPage?.Invoke();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ShowParentPage?.Invoke();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override Drawable CreateBackground() => new OverlayHeaderBackground(@"Headers/wiki");
|
||||||
|
|
||||||
|
protected override OverlayTitle CreateTitle() => new WikiHeaderTitle();
|
||||||
|
|
||||||
|
private class WikiHeaderTitle : OverlayTitle
|
||||||
|
{
|
||||||
|
public WikiHeaderTitle()
|
||||||
|
{
|
||||||
|
Title = "wiki";
|
||||||
|
Description = "knowledge base";
|
||||||
|
IconTexture = "Icons/Hexacons/wiki";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -13,6 +13,7 @@ using osu.Framework.Graphics.Shapes;
|
|||||||
using osu.Framework.Graphics.Sprites;
|
using osu.Framework.Graphics.Sprites;
|
||||||
using osu.Game.Graphics;
|
using osu.Game.Graphics;
|
||||||
using osu.Game.Graphics.Containers.Markdown;
|
using osu.Game.Graphics.Containers.Markdown;
|
||||||
|
using osu.Game.Online.API;
|
||||||
using osu.Game.Overlays.Wiki.Markdown;
|
using osu.Game.Overlays.Wiki.Markdown;
|
||||||
using osuTK;
|
using osuTK;
|
||||||
using osuTK.Graphics;
|
using osuTK.Graphics;
|
||||||
@ -37,7 +38,7 @@ namespace osu.Game.Overlays.Wiki
|
|||||||
}
|
}
|
||||||
|
|
||||||
[BackgroundDependencyLoader]
|
[BackgroundDependencyLoader]
|
||||||
private void load(OverlayColourProvider colourProvider)
|
private void load(OverlayColourProvider colourProvider, IAPIProvider api)
|
||||||
{
|
{
|
||||||
Children = new Drawable[]
|
Children = new Drawable[]
|
||||||
{
|
{
|
||||||
@ -61,6 +62,7 @@ namespace osu.Game.Overlays.Wiki
|
|||||||
},
|
},
|
||||||
panelContainer = new WikiPanelMarkdownContainer(isFullWidth)
|
panelContainer = new WikiPanelMarkdownContainer(isFullWidth)
|
||||||
{
|
{
|
||||||
|
CurrentPath = $@"{api.WebsiteRootUrl}/wiki/",
|
||||||
Text = text,
|
Text = text,
|
||||||
RelativeSizeAxes = Axes.X,
|
RelativeSizeAxes = Axes.X,
|
||||||
AutoSizeAxes = Axes.Y,
|
AutoSizeAxes = Axes.Y,
|
||||||
|
148
osu.Game/Overlays/WikiOverlay.cs
Normal file
148
osu.Game/Overlays/WikiOverlay.cs
Normal file
@ -0,0 +1,148 @@
|
|||||||
|
// 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.Linq;
|
||||||
|
using System.Threading;
|
||||||
|
using osu.Framework.Allocation;
|
||||||
|
using osu.Framework.Bindables;
|
||||||
|
using osu.Framework.Graphics;
|
||||||
|
using osu.Game.Online.API;
|
||||||
|
using osu.Game.Online.API.Requests;
|
||||||
|
using osu.Game.Online.API.Requests.Responses;
|
||||||
|
using osu.Game.Overlays.Wiki;
|
||||||
|
using osu.Game.Overlays.Wiki.Markdown;
|
||||||
|
|
||||||
|
namespace osu.Game.Overlays
|
||||||
|
{
|
||||||
|
public class WikiOverlay : OnlineOverlay<WikiHeader>
|
||||||
|
{
|
||||||
|
private const string index_path = @"main_page";
|
||||||
|
|
||||||
|
private readonly Bindable<string> path = new Bindable<string>(index_path);
|
||||||
|
|
||||||
|
private readonly Bindable<APIWikiPage> wikiData = new Bindable<APIWikiPage>();
|
||||||
|
|
||||||
|
[Resolved]
|
||||||
|
private IAPIProvider api { get; set; }
|
||||||
|
|
||||||
|
private GetWikiRequest request;
|
||||||
|
|
||||||
|
private CancellationTokenSource cancellationToken;
|
||||||
|
|
||||||
|
private bool displayUpdateRequired = true;
|
||||||
|
|
||||||
|
public WikiOverlay()
|
||||||
|
: base(OverlayColourScheme.Orange, false)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ShowPage(string pagePath = index_path)
|
||||||
|
{
|
||||||
|
path.Value = pagePath.Trim('/');
|
||||||
|
Show();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override WikiHeader CreateHeader() => new WikiHeader
|
||||||
|
{
|
||||||
|
ShowIndexPage = () => ShowPage(),
|
||||||
|
ShowParentPage = showParentPage,
|
||||||
|
};
|
||||||
|
|
||||||
|
protected override void LoadComplete()
|
||||||
|
{
|
||||||
|
base.LoadComplete();
|
||||||
|
path.BindValueChanged(onPathChanged);
|
||||||
|
wikiData.BindTo(Header.WikiPageData);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void PopIn()
|
||||||
|
{
|
||||||
|
base.PopIn();
|
||||||
|
|
||||||
|
if (displayUpdateRequired)
|
||||||
|
{
|
||||||
|
path.TriggerChange();
|
||||||
|
displayUpdateRequired = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void PopOutComplete()
|
||||||
|
{
|
||||||
|
base.PopOutComplete();
|
||||||
|
displayUpdateRequired = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void LoadDisplay(Drawable display)
|
||||||
|
{
|
||||||
|
ScrollFlow.ScrollToStart();
|
||||||
|
LoadComponentAsync(display, loaded =>
|
||||||
|
{
|
||||||
|
Child = loaded;
|
||||||
|
Loading.Hide();
|
||||||
|
}, (cancellationToken = new CancellationTokenSource()).Token);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void onPathChanged(ValueChangedEvent<string> e)
|
||||||
|
{
|
||||||
|
cancellationToken?.Cancel();
|
||||||
|
request?.Cancel();
|
||||||
|
|
||||||
|
request = new GetWikiRequest(e.NewValue);
|
||||||
|
|
||||||
|
Loading.Show();
|
||||||
|
|
||||||
|
request.Success += response => Schedule(() => onSuccess(response));
|
||||||
|
request.Failure += _ => Schedule(() => LoadDisplay(Empty()));
|
||||||
|
|
||||||
|
api.PerformAsync(request);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void onSuccess(APIWikiPage response)
|
||||||
|
{
|
||||||
|
wikiData.Value = response;
|
||||||
|
|
||||||
|
if (response.Layout == index_path)
|
||||||
|
{
|
||||||
|
LoadDisplay(new WikiMainPage
|
||||||
|
{
|
||||||
|
Markdown = response.Markdown,
|
||||||
|
Padding = new MarginPadding
|
||||||
|
{
|
||||||
|
Vertical = 20,
|
||||||
|
Horizontal = 50,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
LoadDisplay(new WikiMarkdownContainer
|
||||||
|
{
|
||||||
|
RelativeSizeAxes = Axes.X,
|
||||||
|
AutoSizeAxes = Axes.Y,
|
||||||
|
CurrentPath = $@"{api.WebsiteRootUrl}/wiki/{path.Value}/",
|
||||||
|
Text = response.Markdown,
|
||||||
|
DocumentMargin = new MarginPadding(0),
|
||||||
|
DocumentPadding = new MarginPadding
|
||||||
|
{
|
||||||
|
Vertical = 20,
|
||||||
|
Left = 30,
|
||||||
|
Right = 50,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void showParentPage()
|
||||||
|
{
|
||||||
|
var parentPath = string.Join("/", path.Value.Split('/').SkipLast(1));
|
||||||
|
ShowPage(parentPath);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void Dispose(bool isDisposing)
|
||||||
|
{
|
||||||
|
cancellationToken?.Cancel();
|
||||||
|
request?.Cancel();
|
||||||
|
base.Dispose(isDisposing);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,31 +0,0 @@
|
|||||||
// 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 osu.Framework.Bindables;
|
|
||||||
using osu.Framework.Graphics;
|
|
||||||
|
|
||||||
namespace osu.Game.Rulesets.Objects.Drawables
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// An interface that exposes properties required for scrolling hit objects to be properly displayed.
|
|
||||||
/// </summary>
|
|
||||||
internal interface IScrollingHitObject : IDrawable
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Time offset before the hit object start time at which this <see cref="IScrollingHitObject"/> becomes visible and the time offset
|
|
||||||
/// after the hit object's end time after which it expires.
|
|
||||||
///
|
|
||||||
/// <para>
|
|
||||||
/// This provides only a default life time range, however classes inheriting from <see cref="IScrollingHitObject"/> should override
|
|
||||||
/// their life times if more tight control is desired.
|
|
||||||
/// </para>
|
|
||||||
/// </summary>
|
|
||||||
BindableDouble LifetimeOffset { get; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Axes which this <see cref="IScrollingHitObject"/> will scroll through.
|
|
||||||
/// This is set by the container which this scrolls through.
|
|
||||||
/// </summary>
|
|
||||||
Axes ScrollingAxes { set; }
|
|
||||||
}
|
|
||||||
}
|
|
@ -122,18 +122,20 @@ namespace osu.Game.Rulesets.UI
|
|||||||
var entry = (HitObjectLifetimeEntry)lifetimeEntry;
|
var entry = (HitObjectLifetimeEntry)lifetimeEntry;
|
||||||
Debug.Assert(!aliveDrawableMap.ContainsKey(entry));
|
Debug.Assert(!aliveDrawableMap.ContainsKey(entry));
|
||||||
|
|
||||||
bool isNonPooled = nonPooledDrawableMap.TryGetValue(entry, out var drawable);
|
bool isPooled = !nonPooledDrawableMap.TryGetValue(entry, out var drawable);
|
||||||
drawable ??= pooledObjectProvider?.GetPooledDrawableRepresentation(entry.HitObject, null);
|
drawable ??= pooledObjectProvider?.GetPooledDrawableRepresentation(entry.HitObject, null);
|
||||||
if (drawable == null)
|
if (drawable == null)
|
||||||
throw new InvalidOperationException($"A drawable representation could not be retrieved for hitobject type: {entry.HitObject.GetType().ReadableName()}.");
|
throw new InvalidOperationException($"A drawable representation could not be retrieved for hitobject type: {entry.HitObject.GetType().ReadableName()}.");
|
||||||
|
|
||||||
aliveDrawableMap[entry] = drawable;
|
aliveDrawableMap[entry] = drawable;
|
||||||
|
|
||||||
|
if (isPooled)
|
||||||
|
{
|
||||||
|
addDrawable(drawable);
|
||||||
|
HitObjectUsageBegan?.Invoke(entry.HitObject);
|
||||||
|
}
|
||||||
|
|
||||||
OnAdd(drawable);
|
OnAdd(drawable);
|
||||||
|
|
||||||
if (isNonPooled) return;
|
|
||||||
|
|
||||||
addDrawable(drawable);
|
|
||||||
HitObjectUsageBegan?.Invoke(entry.HitObject);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void entryBecameDead(LifetimeEntry lifetimeEntry)
|
private void entryBecameDead(LifetimeEntry lifetimeEntry)
|
||||||
@ -142,17 +144,18 @@ namespace osu.Game.Rulesets.UI
|
|||||||
Debug.Assert(aliveDrawableMap.ContainsKey(entry));
|
Debug.Assert(aliveDrawableMap.ContainsKey(entry));
|
||||||
|
|
||||||
var drawable = aliveDrawableMap[entry];
|
var drawable = aliveDrawableMap[entry];
|
||||||
bool isNonPooled = nonPooledDrawableMap.ContainsKey(entry);
|
bool isPooled = !nonPooledDrawableMap.ContainsKey(entry);
|
||||||
|
|
||||||
drawable.OnKilled();
|
drawable.OnKilled();
|
||||||
aliveDrawableMap.Remove(entry);
|
aliveDrawableMap.Remove(entry);
|
||||||
|
|
||||||
|
if (isPooled)
|
||||||
|
{
|
||||||
|
removeDrawable(drawable);
|
||||||
|
HitObjectUsageFinished?.Invoke(entry.HitObject);
|
||||||
|
}
|
||||||
|
|
||||||
OnRemove(drawable);
|
OnRemove(drawable);
|
||||||
|
|
||||||
if (isNonPooled) return;
|
|
||||||
|
|
||||||
removeDrawable(drawable);
|
|
||||||
// The hit object is not freed when the DHO was not pooled.
|
|
||||||
HitObjectUsageFinished?.Invoke(entry.HitObject);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void addDrawable(DrawableHitObject drawable)
|
private void addDrawable(DrawableHitObject drawable)
|
||||||
@ -211,21 +214,16 @@ namespace osu.Game.Rulesets.UI
|
|||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Invoked when a <see cref="DrawableHitObject"/> is added to this container.
|
/// Invoked after a <see cref="DrawableHitObject"/> is added to this container.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <remarks>
|
|
||||||
/// This method is not invoked for nested <see cref="DrawableHitObject"/>s.
|
|
||||||
/// </remarks>
|
|
||||||
protected virtual void OnAdd(DrawableHitObject drawableHitObject)
|
protected virtual void OnAdd(DrawableHitObject drawableHitObject)
|
||||||
{
|
{
|
||||||
|
Debug.Assert(drawableHitObject.LoadState >= LoadState.Ready);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Invoked when a <see cref="DrawableHitObject"/> is removed from this container.
|
/// Invoked after a <see cref="DrawableHitObject"/> is removed from this container.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <remarks>
|
|
||||||
/// This method is not invoked for nested <see cref="DrawableHitObject"/>s.
|
|
||||||
/// </remarks>
|
|
||||||
protected virtual void OnRemove(DrawableHitObject drawableHitObject)
|
protected virtual void OnRemove(DrawableHitObject drawableHitObject)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
@ -18,12 +18,7 @@ namespace osu.Game.Rulesets.UI.Scrolling
|
|||||||
private readonly IBindable<ScrollingDirection> direction = new Bindable<ScrollingDirection>();
|
private readonly IBindable<ScrollingDirection> direction = new Bindable<ScrollingDirection>();
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Hit objects which require lifetime computation in the next update call.
|
/// A set of top-level <see cref="DrawableHitObject"/>s which have an up-to-date layout.
|
||||||
/// </summary>
|
|
||||||
private readonly HashSet<DrawableHitObject> toComputeLifetime = new HashSet<DrawableHitObject>();
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// A set containing all <see cref="HitObjectContainer.AliveObjects"/> which have an up-to-date layout.
|
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private readonly HashSet<DrawableHitObject> layoutComputed = new HashSet<DrawableHitObject>();
|
private readonly HashSet<DrawableHitObject> layoutComputed = new HashSet<DrawableHitObject>();
|
||||||
|
|
||||||
@ -54,7 +49,6 @@ namespace osu.Game.Rulesets.UI.Scrolling
|
|||||||
{
|
{
|
||||||
base.Clear();
|
base.Clear();
|
||||||
|
|
||||||
toComputeLifetime.Clear();
|
|
||||||
layoutComputed.Clear();
|
layoutComputed.Clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -83,7 +77,7 @@ namespace osu.Game.Rulesets.UI.Scrolling
|
|||||||
|
|
||||||
flipPositionIfRequired(ref position);
|
flipPositionIfRequired(ref position);
|
||||||
|
|
||||||
return scrollingInfo.Algorithm.TimeAt(position, Time.Current, scrollingInfo.TimeRange.Value, getLength());
|
return scrollingInfo.Algorithm.TimeAt(position, Time.Current, scrollingInfo.TimeRange.Value, scrollLength);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -91,7 +85,7 @@ namespace osu.Game.Rulesets.UI.Scrolling
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public Vector2 ScreenSpacePositionAtTime(double time)
|
public Vector2 ScreenSpacePositionAtTime(double time)
|
||||||
{
|
{
|
||||||
var pos = scrollingInfo.Algorithm.PositionAt(time, Time.Current, scrollingInfo.TimeRange.Value, getLength());
|
var pos = scrollingInfo.Algorithm.PositionAt(time, Time.Current, scrollingInfo.TimeRange.Value, scrollLength);
|
||||||
|
|
||||||
flipPositionIfRequired(ref pos);
|
flipPositionIfRequired(ref pos);
|
||||||
|
|
||||||
@ -106,16 +100,19 @@ namespace osu.Game.Rulesets.UI.Scrolling
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private float getLength()
|
private float scrollLength
|
||||||
{
|
{
|
||||||
switch (scrollingInfo.Direction.Value)
|
get
|
||||||
{
|
{
|
||||||
case ScrollingDirection.Left:
|
switch (scrollingInfo.Direction.Value)
|
||||||
case ScrollingDirection.Right:
|
{
|
||||||
return DrawWidth;
|
case ScrollingDirection.Left:
|
||||||
|
case ScrollingDirection.Right:
|
||||||
|
return DrawWidth;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return DrawHeight;
|
return DrawHeight;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -150,81 +147,40 @@ namespace osu.Game.Rulesets.UI.Scrolling
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void OnAdd(DrawableHitObject drawableHitObject) => onAddRecursive(drawableHitObject);
|
protected override void OnAdd(DrawableHitObject drawableHitObject)
|
||||||
|
|
||||||
protected override void OnRemove(DrawableHitObject drawableHitObject) => onRemoveRecursive(drawableHitObject);
|
|
||||||
|
|
||||||
private void onAddRecursive(DrawableHitObject hitObject)
|
|
||||||
{
|
{
|
||||||
invalidateHitObject(hitObject);
|
invalidateHitObject(drawableHitObject);
|
||||||
|
drawableHitObject.DefaultsApplied += invalidateHitObject;
|
||||||
hitObject.DefaultsApplied += invalidateHitObject;
|
|
||||||
|
|
||||||
foreach (var nested in hitObject.NestedHitObjects)
|
|
||||||
onAddRecursive(nested);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void onRemoveRecursive(DrawableHitObject hitObject)
|
protected override void OnRemove(DrawableHitObject drawableHitObject)
|
||||||
{
|
{
|
||||||
toComputeLifetime.Remove(hitObject);
|
layoutComputed.Remove(drawableHitObject);
|
||||||
layoutComputed.Remove(hitObject);
|
|
||||||
|
|
||||||
hitObject.DefaultsApplied -= invalidateHitObject;
|
drawableHitObject.DefaultsApplied -= invalidateHitObject;
|
||||||
|
|
||||||
foreach (var nested in hitObject.NestedHitObjects)
|
|
||||||
onRemoveRecursive(nested);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Make this <see cref="DrawableHitObject"/> lifetime and layout computed in next update.
|
|
||||||
/// </summary>
|
|
||||||
private void invalidateHitObject(DrawableHitObject hitObject)
|
private void invalidateHitObject(DrawableHitObject hitObject)
|
||||||
{
|
{
|
||||||
// Lifetime computation is delayed until next update because
|
hitObject.LifetimeStart = computeOriginAdjustedLifetimeStart(hitObject);
|
||||||
// when the hit object is not pooled this container is not loaded here and `scrollLength` cannot be computed.
|
|
||||||
toComputeLifetime.Add(hitObject);
|
|
||||||
layoutComputed.Remove(hitObject);
|
layoutComputed.Remove(hitObject);
|
||||||
}
|
}
|
||||||
|
|
||||||
private float scrollLength;
|
|
||||||
|
|
||||||
protected override void Update()
|
protected override void Update()
|
||||||
{
|
{
|
||||||
base.Update();
|
base.Update();
|
||||||
|
|
||||||
if (!layoutCache.IsValid)
|
if (layoutCache.IsValid) return;
|
||||||
|
|
||||||
|
foreach (var hitObject in Objects)
|
||||||
{
|
{
|
||||||
toComputeLifetime.Clear();
|
if (hitObject.HitObject != null)
|
||||||
|
invalidateHitObject(hitObject);
|
||||||
foreach (var hitObject in Objects)
|
|
||||||
{
|
|
||||||
if (hitObject.HitObject != null)
|
|
||||||
toComputeLifetime.Add(hitObject);
|
|
||||||
}
|
|
||||||
|
|
||||||
layoutComputed.Clear();
|
|
||||||
|
|
||||||
scrollingInfo.Algorithm.Reset();
|
|
||||||
|
|
||||||
switch (direction.Value)
|
|
||||||
{
|
|
||||||
case ScrollingDirection.Up:
|
|
||||||
case ScrollingDirection.Down:
|
|
||||||
scrollLength = DrawSize.Y;
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
scrollLength = DrawSize.X;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
layoutCache.Validate();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach (var hitObject in toComputeLifetime)
|
scrollingInfo.Algorithm.Reset();
|
||||||
hitObject.LifetimeStart = computeOriginAdjustedLifetimeStart(hitObject);
|
|
||||||
|
|
||||||
toComputeLifetime.Clear();
|
layoutCache.Validate();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void UpdateAfterChildrenLife()
|
protected override void UpdateAfterChildrenLife()
|
||||||
|
@ -39,7 +39,6 @@ namespace osu.Game.Screens.OnlinePlay.Lounge.Components
|
|||||||
public event Action<SelectionState> StateChanged;
|
public event Action<SelectionState> StateChanged;
|
||||||
|
|
||||||
private readonly Box selectionBox;
|
private readonly Box selectionBox;
|
||||||
private CachedModelDependencyContainer<Room> dependencies;
|
|
||||||
|
|
||||||
[Resolved(canBeNull: true)]
|
[Resolved(canBeNull: true)]
|
||||||
private OnlinePlayScreen parentScreen { get; set; }
|
private OnlinePlayScreen parentScreen { get; set; }
|
||||||
@ -209,9 +208,10 @@ namespace osu.Game.Screens.OnlinePlay.Lounge.Components
|
|||||||
|
|
||||||
protected override IReadOnlyDependencyContainer CreateChildDependencies(IReadOnlyDependencyContainer parent)
|
protected override IReadOnlyDependencyContainer CreateChildDependencies(IReadOnlyDependencyContainer parent)
|
||||||
{
|
{
|
||||||
dependencies = new CachedModelDependencyContainer<Room>(base.CreateChildDependencies(parent));
|
return new CachedModelDependencyContainer<Room>(base.CreateChildDependencies(parent))
|
||||||
dependencies.Model.Value = Room;
|
{
|
||||||
return dependencies;
|
Model = { Value = Room }
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void LoadComplete()
|
protected override void LoadComplete()
|
||||||
|
@ -54,12 +54,12 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer
|
|||||||
Logger.Log($"Polling adjusted (listing: {multiplayerRoomManager.TimeBetweenListingPolls.Value}, selection: {multiplayerRoomManager.TimeBetweenSelectionPolls.Value})");
|
Logger.Log($"Polling adjusted (listing: {multiplayerRoomManager.TimeBetweenListingPolls.Value}, selection: {multiplayerRoomManager.TimeBetweenSelectionPolls.Value})");
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override Room CreateNewRoom()
|
protected override Room CreateNewRoom() =>
|
||||||
{
|
new Room
|
||||||
var room = new Room { Name = { Value = $"{API.LocalUser}'s awesome room" } };
|
{
|
||||||
room.Category.Value = RoomCategory.Realtime;
|
Name = { Value = $"{API.LocalUser}'s awesome room" },
|
||||||
return room;
|
Category = { Value = RoomCategory.Realtime }
|
||||||
}
|
};
|
||||||
|
|
||||||
protected override string ScreenTitle => "Multiplayer";
|
protected override string ScreenTitle => "Multiplayer";
|
||||||
|
|
||||||
|
@ -96,15 +96,19 @@ namespace osu.Game.Screens.OnlinePlay
|
|||||||
{
|
{
|
||||||
itemSelected = true;
|
itemSelected = true;
|
||||||
|
|
||||||
var item = new PlaylistItem();
|
var item = new PlaylistItem
|
||||||
|
{
|
||||||
|
Beatmap =
|
||||||
|
{
|
||||||
|
Value = Beatmap.Value.BeatmapInfo
|
||||||
|
},
|
||||||
|
Ruleset =
|
||||||
|
{
|
||||||
|
Value = Ruleset.Value
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
item.Beatmap.Value = Beatmap.Value.BeatmapInfo;
|
|
||||||
item.Ruleset.Value = Ruleset.Value;
|
|
||||||
|
|
||||||
item.RequiredMods.Clear();
|
|
||||||
item.RequiredMods.AddRange(Mods.Value.Select(m => m.CreateCopy()));
|
item.RequiredMods.AddRange(Mods.Value.Select(m => m.CreateCopy()));
|
||||||
|
|
||||||
item.AllowedMods.Clear();
|
|
||||||
item.AllowedMods.AddRange(FreeMods.Value.Select(m => m.CreateCopy()));
|
item.AllowedMods.AddRange(FreeMods.Value.Select(m => m.CreateCopy()));
|
||||||
|
|
||||||
SelectItem(item);
|
SelectItem(item);
|
||||||
|
@ -17,7 +17,7 @@ namespace osu.Game.Screens.Play.HUD
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public class LegacyComboCounter : CompositeDrawable, ISkinnableDrawable
|
public class LegacyComboCounter : CompositeDrawable, ISkinnableDrawable
|
||||||
{
|
{
|
||||||
public Bindable<int> Current { get; } = new BindableInt { MinValue = 0, };
|
public Bindable<int> Current { get; } = new BindableInt { MinValue = 0 };
|
||||||
|
|
||||||
private uint scheduledPopOutCurrentId;
|
private uint scheduledPopOutCurrentId;
|
||||||
|
|
||||||
@ -32,9 +32,9 @@ namespace osu.Game.Screens.Play.HUD
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
private const double rolling_duration = 20;
|
private const double rolling_duration = 20;
|
||||||
|
|
||||||
private Drawable popOutCount;
|
private readonly Drawable popOutCount;
|
||||||
|
|
||||||
private Drawable displayedCountSpriteText;
|
private readonly Drawable displayedCountSpriteText;
|
||||||
|
|
||||||
private int previousValue;
|
private int previousValue;
|
||||||
|
|
||||||
@ -45,6 +45,20 @@ namespace osu.Game.Screens.Play.HUD
|
|||||||
[Resolved]
|
[Resolved]
|
||||||
private ISkinSource skin { get; set; }
|
private ISkinSource skin { get; set; }
|
||||||
|
|
||||||
|
private readonly Container counterContainer;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Hides the combo counter internally without affecting its <see cref="SkinnableInfo"/>.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// This is used for rulesets that provide their own combo counter and don't want this HUD one to be visible,
|
||||||
|
/// without potentially affecting the user's selected skin.
|
||||||
|
/// </remarks>
|
||||||
|
public bool HiddenByRulesetImplementation
|
||||||
|
{
|
||||||
|
set => counterContainer.Alpha = value ? 1 : 0;
|
||||||
|
}
|
||||||
|
|
||||||
public LegacyComboCounter()
|
public LegacyComboCounter()
|
||||||
{
|
{
|
||||||
AutoSizeAxes = Axes.Both;
|
AutoSizeAxes = Axes.Both;
|
||||||
@ -55,6 +69,25 @@ namespace osu.Game.Screens.Play.HUD
|
|||||||
Margin = new MarginPadding(10);
|
Margin = new MarginPadding(10);
|
||||||
|
|
||||||
Scale = new Vector2(1.2f);
|
Scale = new Vector2(1.2f);
|
||||||
|
|
||||||
|
InternalChild = counterContainer = new Container
|
||||||
|
{
|
||||||
|
AutoSizeAxes = Axes.Both,
|
||||||
|
AlwaysPresent = true,
|
||||||
|
Children = new[]
|
||||||
|
{
|
||||||
|
popOutCount = new LegacySpriteText(LegacyFont.Combo)
|
||||||
|
{
|
||||||
|
Alpha = 0,
|
||||||
|
Margin = new MarginPadding(0.05f),
|
||||||
|
Blending = BlendingParameters.Additive,
|
||||||
|
},
|
||||||
|
displayedCountSpriteText = new LegacySpriteText(LegacyFont.Combo)
|
||||||
|
{
|
||||||
|
Alpha = 0,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -82,20 +115,6 @@ namespace osu.Game.Screens.Play.HUD
|
|||||||
[BackgroundDependencyLoader]
|
[BackgroundDependencyLoader]
|
||||||
private void load(ScoreProcessor scoreProcessor)
|
private void load(ScoreProcessor scoreProcessor)
|
||||||
{
|
{
|
||||||
InternalChildren = new[]
|
|
||||||
{
|
|
||||||
popOutCount = new LegacySpriteText(LegacyFont.Combo)
|
|
||||||
{
|
|
||||||
Alpha = 0,
|
|
||||||
Margin = new MarginPadding(0.05f),
|
|
||||||
Blending = BlendingParameters.Additive,
|
|
||||||
},
|
|
||||||
displayedCountSpriteText = new LegacySpriteText(LegacyFont.Combo)
|
|
||||||
{
|
|
||||||
Alpha = 0,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
Current.BindTo(scoreProcessor.Combo);
|
Current.BindTo(scoreProcessor.Combo);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -105,10 +124,12 @@ namespace osu.Game.Screens.Play.HUD
|
|||||||
|
|
||||||
((IHasText)displayedCountSpriteText).Text = formatCount(Current.Value);
|
((IHasText)displayedCountSpriteText).Text = formatCount(Current.Value);
|
||||||
|
|
||||||
|
counterContainer.Anchor = Anchor;
|
||||||
|
counterContainer.Origin = Origin;
|
||||||
displayedCountSpriteText.Anchor = Anchor;
|
displayedCountSpriteText.Anchor = Anchor;
|
||||||
displayedCountSpriteText.Origin = Origin;
|
displayedCountSpriteText.Origin = Origin;
|
||||||
popOutCount.Origin = Origin;
|
|
||||||
popOutCount.Anchor = Anchor;
|
popOutCount.Anchor = Anchor;
|
||||||
|
popOutCount.Origin = Origin;
|
||||||
|
|
||||||
Current.BindValueChanged(combo => updateCount(combo.NewValue == 0), true);
|
Current.BindValueChanged(combo => updateCount(combo.NewValue == 0), true);
|
||||||
}
|
}
|
||||||
|
@ -505,12 +505,13 @@ namespace osu.Game.Screens.Select
|
|||||||
{
|
{
|
||||||
Logger.Log($"beatmap changed from \"{Beatmap.Value.BeatmapInfo}\" to \"{beatmap}\"");
|
Logger.Log($"beatmap changed from \"{Beatmap.Value.BeatmapInfo}\" to \"{beatmap}\"");
|
||||||
|
|
||||||
WorkingBeatmap previous = Beatmap.Value;
|
int? lastSetID = Beatmap.Value?.BeatmapInfo.BeatmapSetInfoID;
|
||||||
Beatmap.Value = beatmaps.GetWorkingBeatmap(beatmap, previous);
|
|
||||||
|
Beatmap.Value = beatmaps.GetWorkingBeatmap(beatmap);
|
||||||
|
|
||||||
if (beatmap != null)
|
if (beatmap != null)
|
||||||
{
|
{
|
||||||
if (beatmap.BeatmapSetInfoID == previous?.BeatmapInfo.BeatmapSetInfoID)
|
if (beatmap.BeatmapSetInfoID == lastSetID)
|
||||||
sampleChangeDifficulty.Play();
|
sampleChangeDifficulty.Play();
|
||||||
else
|
else
|
||||||
sampleChangeBeatmap.Play();
|
sampleChangeBeatmap.Play();
|
||||||
|
@ -11,14 +11,14 @@ namespace osu.Game.Skinning
|
|||||||
{
|
{
|
||||||
public class DefaultLegacySkin : LegacySkin
|
public class DefaultLegacySkin : LegacySkin
|
||||||
{
|
{
|
||||||
public DefaultLegacySkin(IResourceStore<byte[]> storage, IStorageResourceProvider resources)
|
public DefaultLegacySkin(IStorageResourceProvider resources)
|
||||||
: this(Info, storage, resources)
|
: this(Info, resources)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
[UsedImplicitly(ImplicitUseKindFlags.InstantiatedWithFixedConstructorSignature)]
|
[UsedImplicitly(ImplicitUseKindFlags.InstantiatedWithFixedConstructorSignature)]
|
||||||
public DefaultLegacySkin(SkinInfo skin, IResourceStore<byte[]> storage, IStorageResourceProvider resources)
|
public DefaultLegacySkin(SkinInfo skin, IStorageResourceProvider resources)
|
||||||
: base(skin, storage, resources, string.Empty)
|
: base(skin, new NamespacedResourceStore<byte[]>(resources.Resources, "Skins/Legacy"), resources, string.Empty)
|
||||||
{
|
{
|
||||||
Configuration.CustomColours["SliderBall"] = new Color4(2, 170, 255, 255);
|
Configuration.CustomColours["SliderBall"] = new Color4(2, 170, 255, 255);
|
||||||
Configuration.AddComboColours(
|
Configuration.AddComboColours(
|
||||||
|
@ -4,7 +4,6 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using osu.Framework.Extensions.ObjectExtensions;
|
using osu.Framework.Extensions.ObjectExtensions;
|
||||||
using osu.Framework.IO.Stores;
|
|
||||||
using osu.Game.Configuration;
|
using osu.Game.Configuration;
|
||||||
using osu.Game.Database;
|
using osu.Game.Database;
|
||||||
using osu.Game.Extensions;
|
using osu.Game.Extensions;
|
||||||
@ -28,16 +27,13 @@ namespace osu.Game.Skinning
|
|||||||
|
|
||||||
public string InstantiationInfo { get; set; }
|
public string InstantiationInfo { get; set; }
|
||||||
|
|
||||||
public virtual Skin CreateInstance(IResourceStore<byte[]> legacyDefaultResources, IStorageResourceProvider resources)
|
public virtual Skin CreateInstance(IStorageResourceProvider resources)
|
||||||
{
|
{
|
||||||
var type = string.IsNullOrEmpty(InstantiationInfo)
|
var type = string.IsNullOrEmpty(InstantiationInfo)
|
||||||
// handle the case of skins imported before InstantiationInfo was added.
|
// handle the case of skins imported before InstantiationInfo was added.
|
||||||
? typeof(LegacySkin)
|
? typeof(LegacySkin)
|
||||||
: Type.GetType(InstantiationInfo).AsNonNull();
|
: Type.GetType(InstantiationInfo).AsNonNull();
|
||||||
|
|
||||||
if (type == typeof(DefaultLegacySkin))
|
|
||||||
return (Skin)Activator.CreateInstance(type, this, legacyDefaultResources, resources);
|
|
||||||
|
|
||||||
return (Skin)Activator.CreateInstance(type, this, resources);
|
return (Skin)Activator.CreateInstance(type, this, resources);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -37,7 +37,7 @@ namespace osu.Game.Skinning
|
|||||||
|
|
||||||
private readonly GameHost host;
|
private readonly GameHost host;
|
||||||
|
|
||||||
private readonly IResourceStore<byte[]> legacyDefaultResources;
|
private readonly IResourceStore<byte[]> resources;
|
||||||
|
|
||||||
public readonly Bindable<Skin> CurrentSkin = new Bindable<Skin>(new DefaultSkin(null));
|
public readonly Bindable<Skin> CurrentSkin = new Bindable<Skin>(new DefaultSkin(null));
|
||||||
public readonly Bindable<SkinInfo> CurrentSkinInfo = new Bindable<SkinInfo>(SkinInfo.Default) { Default = SkinInfo.Default };
|
public readonly Bindable<SkinInfo> CurrentSkinInfo = new Bindable<SkinInfo>(SkinInfo.Default) { Default = SkinInfo.Default };
|
||||||
@ -48,13 +48,12 @@ namespace osu.Game.Skinning
|
|||||||
|
|
||||||
protected override string ImportFromStablePath => "Skins";
|
protected override string ImportFromStablePath => "Skins";
|
||||||
|
|
||||||
public SkinManager(Storage storage, DatabaseContextFactory contextFactory, GameHost host, AudioManager audio, IResourceStore<byte[]> legacyDefaultResources)
|
public SkinManager(Storage storage, DatabaseContextFactory contextFactory, GameHost host, IResourceStore<byte[]> resources, AudioManager audio)
|
||||||
: base(storage, contextFactory, new SkinStore(contextFactory, storage), host)
|
: base(storage, contextFactory, new SkinStore(contextFactory, storage), host)
|
||||||
{
|
{
|
||||||
this.audio = audio;
|
this.audio = audio;
|
||||||
this.host = host;
|
this.host = host;
|
||||||
|
this.resources = resources;
|
||||||
this.legacyDefaultResources = legacyDefaultResources;
|
|
||||||
|
|
||||||
CurrentSkinInfo.ValueChanged += skin => CurrentSkin.Value = GetSkin(skin.NewValue);
|
CurrentSkinInfo.ValueChanged += skin => CurrentSkin.Value = GetSkin(skin.NewValue);
|
||||||
CurrentSkin.ValueChanged += skin =>
|
CurrentSkin.ValueChanged += skin =>
|
||||||
@ -152,7 +151,7 @@ namespace osu.Game.Skinning
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="skinInfo">The skin to lookup.</param>
|
/// <param name="skinInfo">The skin to lookup.</param>
|
||||||
/// <returns>A <see cref="Skin"/> instance correlating to the provided <see cref="SkinInfo"/>.</returns>
|
/// <returns>A <see cref="Skin"/> instance correlating to the provided <see cref="SkinInfo"/>.</returns>
|
||||||
public Skin GetSkin(SkinInfo skinInfo) => skinInfo.CreateInstance(legacyDefaultResources, this);
|
public Skin GetSkin(SkinInfo skinInfo) => skinInfo.CreateInstance(this);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Ensure that the current skin is in a state it can accept user modifications.
|
/// Ensure that the current skin is in a state it can accept user modifications.
|
||||||
@ -216,6 +215,7 @@ namespace osu.Game.Skinning
|
|||||||
#region IResourceStorageProvider
|
#region IResourceStorageProvider
|
||||||
|
|
||||||
AudioManager IStorageResourceProvider.AudioManager => audio;
|
AudioManager IStorageResourceProvider.AudioManager => audio;
|
||||||
|
IResourceStore<byte[]> IStorageResourceProvider.Resources => resources;
|
||||||
IResourceStore<byte[]> IStorageResourceProvider.Files => Files.Store;
|
IResourceStore<byte[]> IStorageResourceProvider.Files => Files.Store;
|
||||||
IResourceStore<TextureUpload> IStorageResourceProvider.CreateTextureLoaderStore(IResourceStore<byte[]> underlyingStore) => host.CreateTextureLoaderStore(underlyingStore);
|
IResourceStore<TextureUpload> IStorageResourceProvider.CreateTextureLoaderStore(IResourceStore<byte[]> underlyingStore) => host.CreateTextureLoaderStore(underlyingStore);
|
||||||
|
|
||||||
|
@ -29,7 +29,7 @@ namespace osu.Game.Storyboards.Drawables
|
|||||||
[BackgroundDependencyLoader(true)]
|
[BackgroundDependencyLoader(true)]
|
||||||
private void load(IBindable<WorkingBeatmap> beatmap, TextureStore textureStore)
|
private void load(IBindable<WorkingBeatmap> beatmap, TextureStore textureStore)
|
||||||
{
|
{
|
||||||
var path = beatmap.Value.BeatmapSetInfo?.Files?.Find(f => f.Filename.Equals(Video.Path, StringComparison.OrdinalIgnoreCase))?.FileInfo.StoragePath;
|
var path = beatmap.Value.BeatmapSetInfo?.Files.Find(f => f.Filename.Equals(Video.Path, StringComparison.OrdinalIgnoreCase))?.FileInfo.StoragePath;
|
||||||
|
|
||||||
if (path == null)
|
if (path == null)
|
||||||
return;
|
return;
|
||||||
|
@ -91,7 +91,7 @@ namespace osu.Game.Storyboards
|
|||||||
public Drawable CreateSpriteFromResourcePath(string path, TextureStore textureStore)
|
public Drawable CreateSpriteFromResourcePath(string path, TextureStore textureStore)
|
||||||
{
|
{
|
||||||
Drawable drawable = null;
|
Drawable drawable = null;
|
||||||
var storyboardPath = BeatmapInfo.BeatmapSet?.Files?.Find(f => f.Filename.Equals(path, StringComparison.OrdinalIgnoreCase))?.FileInfo.StoragePath;
|
var storyboardPath = BeatmapInfo.BeatmapSet?.Files.Find(f => f.Filename.Equals(path, StringComparison.OrdinalIgnoreCase))?.FileInfo.StoragePath;
|
||||||
|
|
||||||
if (storyboardPath != null)
|
if (storyboardPath != null)
|
||||||
drawable = new Sprite { Texture = textureStore.Get(storyboardPath) };
|
drawable = new Sprite { Texture = textureStore.Get(storyboardPath) };
|
||||||
|
@ -31,12 +31,16 @@ namespace osu.Game.Tests.Beatmaps
|
|||||||
using (var stream = new LineBufferedReader(resStream))
|
using (var stream = new LineBufferedReader(resStream))
|
||||||
{
|
{
|
||||||
var decoder = Decoder.GetDecoder<Beatmap>(stream);
|
var decoder = Decoder.GetDecoder<Beatmap>(stream);
|
||||||
|
|
||||||
((LegacyBeatmapDecoder)decoder).ApplyOffsets = false;
|
((LegacyBeatmapDecoder)decoder).ApplyOffsets = false;
|
||||||
|
|
||||||
var working = new TestWorkingBeatmap(decoder.Decode(stream));
|
return new TestWorkingBeatmap(decoder.Decode(stream))
|
||||||
working.BeatmapInfo.Ruleset = CreateRuleset().RulesetInfo;
|
{
|
||||||
|
BeatmapInfo =
|
||||||
return working;
|
{
|
||||||
|
Ruleset = CreateRuleset().RulesetInfo
|
||||||
|
}
|
||||||
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -28,7 +28,7 @@ namespace osu.Game.Tests.Beatmaps
|
|||||||
[HeadlessTest]
|
[HeadlessTest]
|
||||||
public abstract class HitObjectSampleTest : PlayerTestScene, IStorageResourceProvider
|
public abstract class HitObjectSampleTest : PlayerTestScene, IStorageResourceProvider
|
||||||
{
|
{
|
||||||
protected abstract IResourceStore<byte[]> Resources { get; }
|
protected abstract IResourceStore<byte[]> RulesetResources { get; }
|
||||||
protected LegacySkin Skin { get; private set; }
|
protected LegacySkin Skin { get; private set; }
|
||||||
|
|
||||||
[Resolved]
|
[Resolved]
|
||||||
@ -75,7 +75,7 @@ namespace osu.Game.Tests.Beatmaps
|
|||||||
|
|
||||||
AddStep($"load {filename}", () =>
|
AddStep($"load {filename}", () =>
|
||||||
{
|
{
|
||||||
using (var reader = new LineBufferedReader(Resources.GetStream($"Resources/SampleLookups/{filename}")))
|
using (var reader = new LineBufferedReader(RulesetResources.GetStream($"Resources/SampleLookups/{filename}")))
|
||||||
currentTestBeatmap = Decoder.GetDecoder<Beatmap>(reader).Decode(reader);
|
currentTestBeatmap = Decoder.GetDecoder<Beatmap>(reader).Decode(reader);
|
||||||
|
|
||||||
// populate ruleset for beatmap converters that require it to be present.
|
// populate ruleset for beatmap converters that require it to be present.
|
||||||
@ -127,6 +127,7 @@ namespace osu.Game.Tests.Beatmaps
|
|||||||
|
|
||||||
public AudioManager AudioManager => Audio;
|
public AudioManager AudioManager => Audio;
|
||||||
public IResourceStore<byte[]> Files => userSkinResourceStore;
|
public IResourceStore<byte[]> Files => userSkinResourceStore;
|
||||||
|
public new IResourceStore<byte[]> Resources => base.Resources;
|
||||||
public IResourceStore<TextureUpload> CreateTextureLoaderStore(IResourceStore<byte[]> underlyingStore) => null;
|
public IResourceStore<TextureUpload> CreateTextureLoaderStore(IResourceStore<byte[]> underlyingStore) => null;
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
@ -21,23 +21,17 @@ namespace osu.Game.Tests.Beatmaps
|
|||||||
{
|
{
|
||||||
protected readonly Bindable<bool> BeatmapSkins = new Bindable<bool>();
|
protected readonly Bindable<bool> BeatmapSkins = new Bindable<bool>();
|
||||||
protected readonly Bindable<bool> BeatmapColours = new Bindable<bool>();
|
protected readonly Bindable<bool> BeatmapColours = new Bindable<bool>();
|
||||||
|
|
||||||
protected ExposedPlayer TestPlayer;
|
protected ExposedPlayer TestPlayer;
|
||||||
protected WorkingBeatmap TestBeatmap;
|
|
||||||
|
|
||||||
public virtual void TestBeatmapComboColours(bool userHasCustomColours, bool useBeatmapSkin) => ConfigureTest(useBeatmapSkin, true, userHasCustomColours);
|
private WorkingBeatmap testBeatmap;
|
||||||
|
|
||||||
public virtual void TestBeatmapComboColoursOverride(bool useBeatmapSkin) => ConfigureTest(useBeatmapSkin, false, true);
|
protected void PrepareBeatmap(Func<WorkingBeatmap> createBeatmap) => AddStep("prepare beatmap", () => testBeatmap = createBeatmap());
|
||||||
|
|
||||||
public virtual void TestBeatmapComboColoursOverrideWithDefaultColours(bool useBeatmapSkin) => ConfigureTest(useBeatmapSkin, false, false);
|
protected void ConfigureTest(bool useBeatmapSkin, bool useBeatmapColours, bool userHasCustomColours)
|
||||||
|
|
||||||
public virtual void TestBeatmapNoComboColours(bool useBeatmapSkin, bool useBeatmapColour) => ConfigureTest(useBeatmapSkin, useBeatmapColour, false);
|
|
||||||
|
|
||||||
public virtual void TestBeatmapNoComboColoursSkinOverride(bool useBeatmapSkin, bool useBeatmapColour) => ConfigureTest(useBeatmapSkin, useBeatmapColour, true);
|
|
||||||
|
|
||||||
protected virtual void ConfigureTest(bool useBeatmapSkin, bool useBeatmapColours, bool userHasCustomColours)
|
|
||||||
{
|
{
|
||||||
configureSettings(useBeatmapSkin, useBeatmapColours);
|
configureSettings(useBeatmapSkin, useBeatmapColours);
|
||||||
AddStep($"load {(((CustomSkinWorkingBeatmap)TestBeatmap).HasColours ? "coloured " : "")} beatmap", () => TestPlayer = LoadBeatmap(userHasCustomColours));
|
AddStep("load beatmap", () => TestPlayer = LoadBeatmap(userHasCustomColours));
|
||||||
AddUntilStep("wait for player load", () => TestPlayer.IsLoaded);
|
AddUntilStep("wait for player load", () => TestPlayer.IsLoaded);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -57,7 +51,7 @@ namespace osu.Game.Tests.Beatmaps
|
|||||||
{
|
{
|
||||||
ExposedPlayer player;
|
ExposedPlayer player;
|
||||||
|
|
||||||
Beatmap.Value = TestBeatmap;
|
Beatmap.Value = testBeatmap;
|
||||||
|
|
||||||
LoadScreen(player = CreateTestPlayer(userHasCustomColours));
|
LoadScreen(player = CreateTestPlayer(userHasCustomColours));
|
||||||
|
|
||||||
|
@ -29,7 +29,6 @@ namespace osu.Game.Tests.Beatmaps
|
|||||||
BeatmapInfo.Ruleset = ruleset;
|
BeatmapInfo.Ruleset = ruleset;
|
||||||
BeatmapInfo.RulesetID = ruleset.ID ?? 0;
|
BeatmapInfo.RulesetID = ruleset.ID ?? 0;
|
||||||
BeatmapInfo.BeatmapSet.Metadata = BeatmapInfo.Metadata;
|
BeatmapInfo.BeatmapSet.Metadata = BeatmapInfo.Metadata;
|
||||||
BeatmapInfo.BeatmapSet.Files = new List<BeatmapSetFileInfo>();
|
|
||||||
BeatmapInfo.BeatmapSet.Beatmaps = new List<BeatmapInfo> { BeatmapInfo };
|
BeatmapInfo.BeatmapSet.Beatmaps = new List<BeatmapInfo> { BeatmapInfo };
|
||||||
BeatmapInfo.Length = 75000;
|
BeatmapInfo.Length = 75000;
|
||||||
BeatmapInfo.OnlineInfo = new BeatmapOnlineInfo();
|
BeatmapInfo.OnlineInfo = new BeatmapOnlineInfo();
|
||||||
|
@ -4,11 +4,19 @@
|
|||||||
using System.Linq;
|
using System.Linq;
|
||||||
using JetBrains.Annotations;
|
using JetBrains.Annotations;
|
||||||
using osu.Framework.Allocation;
|
using osu.Framework.Allocation;
|
||||||
|
using osu.Framework.Audio;
|
||||||
|
using osu.Framework.IO.Stores;
|
||||||
|
using osu.Framework.Platform;
|
||||||
using osu.Framework.Testing;
|
using osu.Framework.Testing;
|
||||||
|
using osu.Game.Beatmaps;
|
||||||
|
using osu.Game.Database;
|
||||||
|
using osu.Game.IO.Archives;
|
||||||
|
using osu.Game.Online.API;
|
||||||
using osu.Game.Rulesets;
|
using osu.Game.Rulesets;
|
||||||
using osu.Game.Rulesets.Edit;
|
using osu.Game.Rulesets.Edit;
|
||||||
using osu.Game.Screens.Edit;
|
using osu.Game.Screens.Edit;
|
||||||
using osu.Game.Screens.Edit.Compose.Components.Timeline;
|
using osu.Game.Screens.Edit.Compose.Components.Timeline;
|
||||||
|
using osu.Game.Skinning;
|
||||||
|
|
||||||
namespace osu.Game.Tests.Visual
|
namespace osu.Game.Tests.Visual
|
||||||
{
|
{
|
||||||
@ -20,10 +28,20 @@ namespace osu.Game.Tests.Visual
|
|||||||
|
|
||||||
protected EditorClock EditorClock { get; private set; }
|
protected EditorClock EditorClock { get; private set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Whether any saves performed by the editor should be isolate (and not persist) to the underlying <see cref="BeatmapManager"/>.
|
||||||
|
/// </summary>
|
||||||
|
protected virtual bool IsolateSavingFromDatabase => true;
|
||||||
|
|
||||||
[BackgroundDependencyLoader]
|
[BackgroundDependencyLoader]
|
||||||
private void load()
|
private void load(GameHost host, AudioManager audio, RulesetStore rulesets)
|
||||||
{
|
{
|
||||||
Beatmap.Value = CreateWorkingBeatmap(Ruleset.Value);
|
var working = CreateWorkingBeatmap(Ruleset.Value);
|
||||||
|
|
||||||
|
Beatmap.Value = working;
|
||||||
|
|
||||||
|
if (IsolateSavingFromDatabase)
|
||||||
|
Dependencies.CacheAs<BeatmapManager>(new TestBeatmapManager(LocalStorage, ContextFactory, rulesets, null, audio, Resources, host, Beatmap.Default, working));
|
||||||
}
|
}
|
||||||
|
|
||||||
protected virtual bool EditorComponentsReady => Editor.ChildrenOfType<HitObjectComposer>().FirstOrDefault()?.IsLoaded == true
|
protected virtual bool EditorComponentsReady => Editor.ChildrenOfType<HitObjectComposer>().FirstOrDefault()?.IsLoaded == true
|
||||||
@ -33,12 +51,17 @@ namespace osu.Game.Tests.Visual
|
|||||||
{
|
{
|
||||||
base.SetUpSteps();
|
base.SetUpSteps();
|
||||||
|
|
||||||
AddStep("load editor", () => LoadScreen(Editor = CreateEditor()));
|
AddStep("load editor", LoadEditor);
|
||||||
AddUntilStep("wait for editor to load", () => EditorComponentsReady);
|
AddUntilStep("wait for editor to load", () => EditorComponentsReady);
|
||||||
AddStep("get beatmap", () => EditorBeatmap = Editor.ChildrenOfType<EditorBeatmap>().Single());
|
AddStep("get beatmap", () => EditorBeatmap = Editor.ChildrenOfType<EditorBeatmap>().Single());
|
||||||
AddStep("get clock", () => EditorClock = Editor.ChildrenOfType<EditorClock>().Single());
|
AddStep("get clock", () => EditorClock = Editor.ChildrenOfType<EditorClock>().Single());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected virtual void LoadEditor()
|
||||||
|
{
|
||||||
|
LoadScreen(Editor = CreateEditor());
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Creates the ruleset for providing a corresponding beatmap to load the editor on.
|
/// Creates the ruleset for providing a corresponding beatmap to load the editor on.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -65,5 +88,27 @@ namespace osu.Game.Tests.Visual
|
|||||||
|
|
||||||
public new bool HasUnsavedChanges => base.HasUnsavedChanges;
|
public new bool HasUnsavedChanges => base.HasUnsavedChanges;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private class TestBeatmapManager : BeatmapManager
|
||||||
|
{
|
||||||
|
private readonly WorkingBeatmap testBeatmap;
|
||||||
|
|
||||||
|
public TestBeatmapManager(Storage storage, IDatabaseContextFactory contextFactory, RulesetStore rulesets, IAPIProvider api, [NotNull] AudioManager audioManager, IResourceStore<byte[]> resources, GameHost host, WorkingBeatmap defaultBeatmap, WorkingBeatmap testBeatmap)
|
||||||
|
: base(storage, contextFactory, rulesets, api, audioManager, resources, host, defaultBeatmap, false)
|
||||||
|
{
|
||||||
|
this.testBeatmap = testBeatmap;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override string ComputeHash(BeatmapSetInfo item, ArchiveReader reader = null)
|
||||||
|
=> string.Empty;
|
||||||
|
|
||||||
|
public override WorkingBeatmap GetWorkingBeatmap(BeatmapInfo beatmapInfo)
|
||||||
|
=> testBeatmap;
|
||||||
|
|
||||||
|
public override void Save(BeatmapInfo info, IBeatmap beatmapContent, ISkin beatmapSkin = null)
|
||||||
|
{
|
||||||
|
// don't actually care about saving for this context.
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,7 +3,8 @@
|
|||||||
|
|
||||||
using NUnit.Framework;
|
using NUnit.Framework;
|
||||||
using osu.Framework.Allocation;
|
using osu.Framework.Allocation;
|
||||||
using osu.Framework.IO.Stores;
|
using osu.Framework.Extensions.IEnumerableExtensions;
|
||||||
|
using osu.Framework.Testing;
|
||||||
using osu.Game.Rulesets;
|
using osu.Game.Rulesets;
|
||||||
using osu.Game.Skinning;
|
using osu.Game.Skinning;
|
||||||
|
|
||||||
@ -12,15 +13,40 @@ namespace osu.Game.Tests.Visual
|
|||||||
[TestFixture]
|
[TestFixture]
|
||||||
public abstract class LegacySkinPlayerTestScene : PlayerTestScene
|
public abstract class LegacySkinPlayerTestScene : PlayerTestScene
|
||||||
{
|
{
|
||||||
|
protected LegacySkin LegacySkin { get; private set; }
|
||||||
|
|
||||||
private ISkinSource legacySkinSource;
|
private ISkinSource legacySkinSource;
|
||||||
|
|
||||||
protected override TestPlayer CreatePlayer(Ruleset ruleset) => new SkinProvidingPlayer(legacySkinSource);
|
protected override TestPlayer CreatePlayer(Ruleset ruleset) => new SkinProvidingPlayer(legacySkinSource);
|
||||||
|
|
||||||
[BackgroundDependencyLoader]
|
[BackgroundDependencyLoader]
|
||||||
private void load(OsuGameBase game, SkinManager skins)
|
private void load(SkinManager skins)
|
||||||
{
|
{
|
||||||
var legacySkin = new DefaultLegacySkin(new NamespacedResourceStore<byte[]>(game.Resources, "Skins/Legacy"), skins);
|
LegacySkin = new DefaultLegacySkin(skins);
|
||||||
legacySkinSource = new SkinProvidingContainer(legacySkin);
|
legacySkinSource = new SkinProvidingContainer(LegacySkin);
|
||||||
|
}
|
||||||
|
|
||||||
|
[SetUpSteps]
|
||||||
|
public override void SetUpSteps()
|
||||||
|
{
|
||||||
|
base.SetUpSteps();
|
||||||
|
addResetTargetsStep();
|
||||||
|
}
|
||||||
|
|
||||||
|
[TearDownSteps]
|
||||||
|
public override void TearDownSteps()
|
||||||
|
{
|
||||||
|
addResetTargetsStep();
|
||||||
|
base.TearDownSteps();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void addResetTargetsStep()
|
||||||
|
{
|
||||||
|
AddStep("reset targets", () => this.ChildrenOfType<SkinnableTargetContainer>().ForEach(t =>
|
||||||
|
{
|
||||||
|
LegacySkin.ResetDrawableTarget(t);
|
||||||
|
t.Reload();
|
||||||
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
public class SkinProvidingPlayer : TestPlayer
|
public class SkinProvidingPlayer : TestPlayer
|
||||||
|
@ -14,6 +14,7 @@ using osu.Framework.Audio.Track;
|
|||||||
using osu.Framework.Bindables;
|
using osu.Framework.Bindables;
|
||||||
using osu.Framework.Graphics;
|
using osu.Framework.Graphics;
|
||||||
using osu.Framework.Graphics.Containers;
|
using osu.Framework.Graphics.Containers;
|
||||||
|
using osu.Framework.IO.Stores;
|
||||||
using osu.Framework.Platform;
|
using osu.Framework.Platform;
|
||||||
using osu.Framework.Testing;
|
using osu.Framework.Testing;
|
||||||
using osu.Framework.Timing;
|
using osu.Framework.Timing;
|
||||||
@ -49,6 +50,8 @@ namespace osu.Game.Tests.Visual
|
|||||||
|
|
||||||
private Lazy<DatabaseContextFactory> contextFactory;
|
private Lazy<DatabaseContextFactory> contextFactory;
|
||||||
|
|
||||||
|
protected IResourceStore<byte[]> Resources;
|
||||||
|
|
||||||
protected IAPIProvider API
|
protected IAPIProvider API
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
@ -81,6 +84,8 @@ namespace osu.Game.Tests.Visual
|
|||||||
if (!UseFreshStoragePerRun)
|
if (!UseFreshStoragePerRun)
|
||||||
isolatedHostStorage = (parent.Get<GameHost>() as HeadlessGameHost)?.Storage;
|
isolatedHostStorage = (parent.Get<GameHost>() as HeadlessGameHost)?.Storage;
|
||||||
|
|
||||||
|
Resources = parent.Get<OsuGameBase>().Resources;
|
||||||
|
|
||||||
contextFactory = new Lazy<DatabaseContextFactory>(() =>
|
contextFactory = new Lazy<DatabaseContextFactory>(() =>
|
||||||
{
|
{
|
||||||
var factory = new DatabaseContextFactory(LocalStorage);
|
var factory = new DatabaseContextFactory(LocalStorage);
|
||||||
|
@ -40,12 +40,12 @@ namespace osu.Game.Tests.Visual
|
|||||||
}
|
}
|
||||||
|
|
||||||
[BackgroundDependencyLoader]
|
[BackgroundDependencyLoader]
|
||||||
private void load(AudioManager audio, SkinManager skinManager, OsuGameBase game)
|
private void load(AudioManager audio, SkinManager skinManager)
|
||||||
{
|
{
|
||||||
var dllStore = new DllResourceStore(DynamicCompilationOriginal.GetType().Assembly);
|
var dllStore = new DllResourceStore(DynamicCompilationOriginal.GetType().Assembly);
|
||||||
|
|
||||||
metricsSkin = new TestLegacySkin(new SkinInfo { Name = "metrics-skin" }, new NamespacedResourceStore<byte[]>(dllStore, "Resources/metrics_skin"), this, true);
|
metricsSkin = new TestLegacySkin(new SkinInfo { Name = "metrics-skin" }, new NamespacedResourceStore<byte[]>(dllStore, "Resources/metrics_skin"), this, true);
|
||||||
defaultSkin = new DefaultLegacySkin(new NamespacedResourceStore<byte[]>(game.Resources, "Skins/Legacy"), this);
|
defaultSkin = new DefaultLegacySkin(this);
|
||||||
specialSkin = new TestLegacySkin(new SkinInfo { Name = "special-skin" }, new NamespacedResourceStore<byte[]>(dllStore, "Resources/special_skin"), this, true);
|
specialSkin = new TestLegacySkin(new SkinInfo { Name = "special-skin" }, new NamespacedResourceStore<byte[]>(dllStore, "Resources/special_skin"), this, true);
|
||||||
oldSkin = new TestLegacySkin(new SkinInfo { Name = "old-skin" }, new NamespacedResourceStore<byte[]>(dllStore, "Resources/old_skin"), this, true);
|
oldSkin = new TestLegacySkin(new SkinInfo { Name = "old-skin" }, new NamespacedResourceStore<byte[]>(dllStore, "Resources/old_skin"), this, true);
|
||||||
}
|
}
|
||||||
@ -158,6 +158,7 @@ namespace osu.Game.Tests.Visual
|
|||||||
|
|
||||||
public AudioManager AudioManager => Audio;
|
public AudioManager AudioManager => Audio;
|
||||||
public IResourceStore<byte[]> Files => null;
|
public IResourceStore<byte[]> Files => null;
|
||||||
|
public new IResourceStore<byte[]> Resources => base.Resources;
|
||||||
public IResourceStore<TextureUpload> CreateTextureLoaderStore(IResourceStore<byte[]> underlyingStore) => host.CreateTextureLoaderStore(underlyingStore);
|
public IResourceStore<TextureUpload> CreateTextureLoaderStore(IResourceStore<byte[]> underlyingStore) => host.CreateTextureLoaderStore(underlyingStore);
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
@ -35,7 +35,7 @@
|
|||||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||||
</PackageReference>
|
</PackageReference>
|
||||||
<PackageReference Include="ppy.osu.Framework" Version="2021.528.0" />
|
<PackageReference Include="ppy.osu.Framework" Version="2021.528.0" />
|
||||||
<PackageReference Include="ppy.osu.Game.Resources" Version="2021.422.0" />
|
<PackageReference Include="ppy.osu.Game.Resources" Version="2021.525.0" />
|
||||||
<PackageReference Include="Sentry" Version="3.3.4" />
|
<PackageReference Include="Sentry" Version="3.3.4" />
|
||||||
<PackageReference Include="SharpCompress" Version="0.28.2" />
|
<PackageReference Include="SharpCompress" Version="0.28.2" />
|
||||||
<PackageReference Include="NUnit" Version="3.13.2" />
|
<PackageReference Include="NUnit" Version="3.13.2" />
|
||||||
|
@ -71,7 +71,7 @@
|
|||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup Label="Package References">
|
<ItemGroup Label="Package References">
|
||||||
<PackageReference Include="ppy.osu.Framework.iOS" Version="2021.528.0" />
|
<PackageReference Include="ppy.osu.Framework.iOS" Version="2021.528.0" />
|
||||||
<PackageReference Include="ppy.osu.Game.Resources" Version="2021.422.0" />
|
<PackageReference Include="ppy.osu.Game.Resources" Version="2021.525.0" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<!-- See https://github.com/dotnet/runtime/issues/35988 (can be removed after Xamarin uses net5.0 / net6.0) -->
|
<!-- See https://github.com/dotnet/runtime/issues/35988 (can be removed after Xamarin uses net5.0 / net6.0) -->
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
|
Loading…
Reference in New Issue
Block a user