mirror of
https://github.com/ppy/osu.git
synced 2025-01-15 14:53:01 +08:00
Merge branch 'master' of https://github.com/ppy/osu into Issue#9170
This commit is contained in:
commit
fdc9756b3f
@ -0,0 +1,10 @@
|
|||||||
|
osu file format v14
|
||||||
|
|
||||||
|
[General]
|
||||||
|
Mode: 3
|
||||||
|
|
||||||
|
[TimingPoints]
|
||||||
|
0,300,4,0,2,100,1,0
|
||||||
|
|
||||||
|
[HitObjects]
|
||||||
|
444,320,1000,5,2,0:0:0:0:
|
@ -0,0 +1,10 @@
|
|||||||
|
osu file format v14
|
||||||
|
|
||||||
|
[General]
|
||||||
|
Mode: 3
|
||||||
|
|
||||||
|
[TimingPoints]
|
||||||
|
0,300,4,0,2,100,1,0
|
||||||
|
|
||||||
|
[HitObjects]
|
||||||
|
444,320,1000,5,1,0:0:0:0:
|
@ -0,0 +1,49 @@
|
|||||||
|
// 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.Reflection;
|
||||||
|
using NUnit.Framework;
|
||||||
|
using osu.Framework.IO.Stores;
|
||||||
|
using osu.Game.Tests.Beatmaps;
|
||||||
|
|
||||||
|
namespace osu.Game.Rulesets.Mania.Tests
|
||||||
|
{
|
||||||
|
public class TestSceneManiaHitObjectSamples : HitObjectSampleTest
|
||||||
|
{
|
||||||
|
protected override Ruleset CreatePlayerRuleset() => new ManiaRuleset();
|
||||||
|
protected override IResourceStore<byte[]> Resources => new DllResourceStore(Assembly.GetAssembly(typeof(TestSceneManiaHitObjectSamples)));
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Tests that when a normal sample bank is used, the normal hitsound will be looked up.
|
||||||
|
/// </summary>
|
||||||
|
[Test]
|
||||||
|
public void TestManiaHitObjectNormalSampleBank()
|
||||||
|
{
|
||||||
|
const string expected_sample = "normal-hitnormal2";
|
||||||
|
|
||||||
|
SetupSkins(expected_sample, expected_sample);
|
||||||
|
|
||||||
|
CreateTestWithBeatmap("mania-hitobject-beatmap-normal-sample-bank.osu");
|
||||||
|
|
||||||
|
AssertBeatmapLookup(expected_sample);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Tests that when a custom sample bank is used, layered hitsounds are not played
|
||||||
|
/// (only the sample from the custom bank is looked up).
|
||||||
|
/// </summary>
|
||||||
|
[Test]
|
||||||
|
public void TestManiaHitObjectCustomSampleBank()
|
||||||
|
{
|
||||||
|
const string expected_sample = "normal-hitwhistle2";
|
||||||
|
const string unwanted_sample = "normal-hitnormal2";
|
||||||
|
|
||||||
|
SetupSkins(expected_sample, unwanted_sample);
|
||||||
|
|
||||||
|
CreateTestWithBeatmap("mania-hitobject-beatmap-custom-sample-bank.osu");
|
||||||
|
|
||||||
|
AssertBeatmapLookup(expected_sample);
|
||||||
|
AssertNoLookup(unwanted_sample);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -9,6 +9,9 @@ using osu.Game.Beatmaps;
|
|||||||
using osu.Game.Rulesets.Mania.Beatmaps;
|
using osu.Game.Rulesets.Mania.Beatmaps;
|
||||||
using osu.Game.Skinning;
|
using osu.Game.Skinning;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using osu.Framework.Audio.Sample;
|
||||||
|
using osu.Game.Audio;
|
||||||
|
using osu.Game.Rulesets.Objects.Legacy;
|
||||||
|
|
||||||
namespace osu.Game.Rulesets.Mania.Skinning
|
namespace osu.Game.Rulesets.Mania.Skinning
|
||||||
{
|
{
|
||||||
@ -129,6 +132,15 @@ namespace osu.Game.Rulesets.Mania.Skinning
|
|||||||
return this.GetAnimation(filename, true, true);
|
return this.GetAnimation(filename, true, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override SampleChannel GetSample(ISampleInfo sampleInfo)
|
||||||
|
{
|
||||||
|
// layered hit sounds never play in mania
|
||||||
|
if (sampleInfo is ConvertHitObjectParser.LegacyHitSampleInfo legacySample && legacySample.IsLayered)
|
||||||
|
return new SampleChannelVirtual();
|
||||||
|
|
||||||
|
return Source.GetSample(sampleInfo);
|
||||||
|
}
|
||||||
|
|
||||||
public override IBindable<TValue> GetConfig<TLookup, TValue>(TLookup lookup)
|
public override IBindable<TValue> GetConfig<TLookup, TValue>(TLookup lookup)
|
||||||
{
|
{
|
||||||
if (lookup is ManiaSkinConfigurationLookup maniaLookup)
|
if (lookup is ManiaSkinConfigurationLookup maniaLookup)
|
||||||
|
@ -6,6 +6,7 @@ using osu.Framework.IO.Stores;
|
|||||||
using osu.Framework.Testing;
|
using osu.Framework.Testing;
|
||||||
using osu.Game.Rulesets;
|
using osu.Game.Rulesets;
|
||||||
using osu.Game.Rulesets.Osu;
|
using osu.Game.Rulesets.Osu;
|
||||||
|
using osu.Game.Skinning;
|
||||||
using osu.Game.Tests.Beatmaps;
|
using osu.Game.Tests.Beatmaps;
|
||||||
using osu.Game.Tests.Resources;
|
using osu.Game.Tests.Resources;
|
||||||
|
|
||||||
@ -167,5 +168,64 @@ namespace osu.Game.Tests.Gameplay
|
|||||||
|
|
||||||
AssertBeatmapLookup(expected_sample);
|
AssertBeatmapLookup(expected_sample);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Tests that when a custom sample bank is used, both the normal and additional sounds will be looked up.
|
||||||
|
/// </summary>
|
||||||
|
[Test]
|
||||||
|
public void TestHitObjectCustomSampleBank()
|
||||||
|
{
|
||||||
|
string[] expectedSamples =
|
||||||
|
{
|
||||||
|
"normal-hitnormal2",
|
||||||
|
"normal-hitwhistle2"
|
||||||
|
};
|
||||||
|
|
||||||
|
SetupSkins(expectedSamples[0], expectedSamples[1]);
|
||||||
|
|
||||||
|
CreateTestWithBeatmap("hitobject-beatmap-custom-sample-bank.osu");
|
||||||
|
|
||||||
|
AssertBeatmapLookup(expectedSamples[0]);
|
||||||
|
AssertUserLookup(expectedSamples[1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Tests that when a custom sample bank is used, but <see cref="GlobalSkinConfiguration.LayeredHitSounds"/> is disabled,
|
||||||
|
/// only the additional sound will be looked up.
|
||||||
|
/// </summary>
|
||||||
|
[Test]
|
||||||
|
public void TestHitObjectCustomSampleBankWithoutLayered()
|
||||||
|
{
|
||||||
|
const string expected_sample = "normal-hitwhistle2";
|
||||||
|
const string unwanted_sample = "normal-hitnormal2";
|
||||||
|
|
||||||
|
SetupSkins(expected_sample, unwanted_sample);
|
||||||
|
disableLayeredHitSounds();
|
||||||
|
|
||||||
|
CreateTestWithBeatmap("hitobject-beatmap-custom-sample-bank.osu");
|
||||||
|
|
||||||
|
AssertBeatmapLookup(expected_sample);
|
||||||
|
AssertNoLookup(unwanted_sample);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Tests that when a normal sample bank is used and <see cref="GlobalSkinConfiguration.LayeredHitSounds"/> is disabled,
|
||||||
|
/// the normal sound will be looked up anyway.
|
||||||
|
/// </summary>
|
||||||
|
[Test]
|
||||||
|
public void TestHitObjectNormalSampleBankWithoutLayered()
|
||||||
|
{
|
||||||
|
const string expected_sample = "normal-hitnormal";
|
||||||
|
|
||||||
|
SetupSkins(expected_sample, expected_sample);
|
||||||
|
disableLayeredHitSounds();
|
||||||
|
|
||||||
|
CreateTestWithBeatmap("hitobject-beatmap-sample.osu");
|
||||||
|
|
||||||
|
AssertBeatmapLookup(expected_sample);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void disableLayeredHitSounds()
|
||||||
|
=> AddStep("set LayeredHitSounds to false", () => Skin.Configuration.ConfigDictionary[GlobalSkinConfiguration.LayeredHitSounds.ToString()] = "0");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -11,8 +11,10 @@ using osu.Framework.Audio.Sample;
|
|||||||
using osu.Framework.IO.Stores;
|
using osu.Framework.IO.Stores;
|
||||||
using osu.Framework.Testing;
|
using osu.Framework.Testing;
|
||||||
using osu.Game.Audio;
|
using osu.Game.Audio;
|
||||||
|
using osu.Game.Rulesets;
|
||||||
using osu.Game.Rulesets.Mods;
|
using osu.Game.Rulesets.Mods;
|
||||||
using osu.Game.Rulesets.Osu;
|
using osu.Game.Rulesets.Osu;
|
||||||
|
using osu.Game.Rulesets.Osu.Mods;
|
||||||
using osu.Game.Screens.Play;
|
using osu.Game.Screens.Play;
|
||||||
using osu.Game.Skinning;
|
using osu.Game.Skinning;
|
||||||
using osu.Game.Storyboards;
|
using osu.Game.Storyboards;
|
||||||
@ -70,6 +72,50 @@ namespace osu.Game.Tests.Gameplay
|
|||||||
AddUntilStep("sample playback succeeded", () => sample.LifetimeEnd < double.MaxValue);
|
AddUntilStep("sample playback succeeded", () => sample.LifetimeEnd < double.MaxValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[TestCase(typeof(OsuModDoubleTime), 1.5)]
|
||||||
|
[TestCase(typeof(OsuModHalfTime), 0.75)]
|
||||||
|
[TestCase(typeof(ModWindUp), 1.5)]
|
||||||
|
[TestCase(typeof(ModWindDown), 0.75)]
|
||||||
|
[TestCase(typeof(OsuModDoubleTime), 2)]
|
||||||
|
[TestCase(typeof(OsuModHalfTime), 0.5)]
|
||||||
|
[TestCase(typeof(ModWindUp), 2)]
|
||||||
|
[TestCase(typeof(ModWindDown), 0.5)]
|
||||||
|
public void TestSamplePlaybackWithRateMods(Type expectedMod, double expectedRate)
|
||||||
|
{
|
||||||
|
GameplayClockContainer gameplayContainer = null;
|
||||||
|
TestDrawableStoryboardSample sample = null;
|
||||||
|
|
||||||
|
Mod testedMod = Activator.CreateInstance(expectedMod) as Mod;
|
||||||
|
|
||||||
|
switch (testedMod)
|
||||||
|
{
|
||||||
|
case ModRateAdjust m:
|
||||||
|
m.SpeedChange.Value = expectedRate;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ModTimeRamp m:
|
||||||
|
m.InitialRate.Value = m.FinalRate.Value = expectedRate;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
AddStep("setup storyboard sample", () =>
|
||||||
|
{
|
||||||
|
Beatmap.Value = new TestCustomSkinWorkingBeatmap(new OsuRuleset().RulesetInfo, Audio);
|
||||||
|
SelectedMods.Value = new[] { testedMod };
|
||||||
|
|
||||||
|
Add(gameplayContainer = new GameplayClockContainer(Beatmap.Value, SelectedMods.Value, 0));
|
||||||
|
|
||||||
|
gameplayContainer.Add(sample = new TestDrawableStoryboardSample(new StoryboardSampleInfo("test-sample", 1, 1))
|
||||||
|
{
|
||||||
|
Clock = gameplayContainer.GameplayClock
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
AddStep("start", () => gameplayContainer.Start());
|
||||||
|
|
||||||
|
AddAssert("sample playback rate matches mod rates", () => sample.Channel.AggregateFrequency.Value == expectedRate);
|
||||||
|
}
|
||||||
|
|
||||||
private class TestSkin : LegacySkin
|
private class TestSkin : LegacySkin
|
||||||
{
|
{
|
||||||
public TestSkin(string resourceName, AudioManager audioManager)
|
public TestSkin(string resourceName, AudioManager audioManager)
|
||||||
@ -99,5 +145,28 @@ namespace osu.Game.Tests.Gameplay
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private class TestCustomSkinWorkingBeatmap : ClockBackedTestWorkingBeatmap
|
||||||
|
{
|
||||||
|
private readonly AudioManager audio;
|
||||||
|
|
||||||
|
public TestCustomSkinWorkingBeatmap(RulesetInfo ruleset, AudioManager audio)
|
||||||
|
: base(ruleset, null, audio)
|
||||||
|
{
|
||||||
|
this.audio = audio;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override ISkin GetSkin() => new TestSkin("test-sample", audio);
|
||||||
|
}
|
||||||
|
|
||||||
|
private class TestDrawableStoryboardSample : DrawableStoryboardSample
|
||||||
|
{
|
||||||
|
public TestDrawableStoryboardSample(StoryboardSampleInfo sampleInfo)
|
||||||
|
: base(sampleInfo)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public new SampleChannel Channel => base.Channel;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,7 @@
|
|||||||
|
osu file format v14
|
||||||
|
|
||||||
|
[TimingPoints]
|
||||||
|
0,300,4,0,2,100,1,0
|
||||||
|
|
||||||
|
[HitObjects]
|
||||||
|
444,320,1000,5,2,0:0:0:0:
|
5
osu.Game.Tests/Resources/skin-zero-alpha-colour.ini
Normal file
5
osu.Game.Tests/Resources/skin-zero-alpha-colour.ini
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
[General]
|
||||||
|
Version: latest
|
||||||
|
|
||||||
|
[Colours]
|
||||||
|
Combo1: 255,255,255,0
|
@ -108,5 +108,15 @@ namespace osu.Game.Tests.Skins
|
|||||||
using (var stream = new LineBufferedReader(resStream))
|
using (var stream = new LineBufferedReader(resStream))
|
||||||
Assert.That(decoder.Decode(stream).LegacyVersion, Is.EqualTo(1.0m));
|
Assert.That(decoder.Decode(stream).LegacyVersion, Is.EqualTo(1.0m));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void TestDecodeColourWithZeroAlpha()
|
||||||
|
{
|
||||||
|
var decoder = new LegacySkinDecoder();
|
||||||
|
|
||||||
|
using (var resStream = TestResources.OpenResource("skin-zero-alpha-colour.ini"))
|
||||||
|
using (var stream = new LineBufferedReader(resStream))
|
||||||
|
Assert.That(decoder.Decode(stream).ComboColours[0].A, Is.EqualTo(1.0f));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -9,7 +9,7 @@ using osu.Game.Tournament.Screens.Gameplay.Components;
|
|||||||
|
|
||||||
namespace osu.Game.Tournament.Tests.Components
|
namespace osu.Game.Tournament.Tests.Components
|
||||||
{
|
{
|
||||||
public class TestSceneMatchScoreDisplay : LadderTestScene
|
public class TestSceneMatchScoreDisplay : TournamentTestScene
|
||||||
{
|
{
|
||||||
[Cached(Type = typeof(MatchIPCInfo))]
|
[Cached(Type = typeof(MatchIPCInfo))]
|
||||||
private MatchIPCInfo matchInfo = new MatchIPCInfo();
|
private MatchIPCInfo matchInfo = new MatchIPCInfo();
|
||||||
|
@ -8,12 +8,11 @@ using osu.Game.Online.API;
|
|||||||
using osu.Game.Online.API.Requests;
|
using osu.Game.Online.API.Requests;
|
||||||
using osu.Game.Online.API.Requests.Responses;
|
using osu.Game.Online.API.Requests.Responses;
|
||||||
using osu.Game.Rulesets;
|
using osu.Game.Rulesets;
|
||||||
using osu.Game.Tests.Visual;
|
|
||||||
using osu.Game.Tournament.Components;
|
using osu.Game.Tournament.Components;
|
||||||
|
|
||||||
namespace osu.Game.Tournament.Tests.Components
|
namespace osu.Game.Tournament.Tests.Components
|
||||||
{
|
{
|
||||||
public class TestSceneTournamentBeatmapPanel : OsuTestScene
|
public class TestSceneTournamentBeatmapPanel : TournamentTestScene
|
||||||
{
|
{
|
||||||
[Resolved]
|
[Resolved]
|
||||||
private IAPIProvider api { get; set; }
|
private IAPIProvider api { get; set; }
|
||||||
|
@ -1,146 +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 System.Linq;
|
|
||||||
using NUnit.Framework;
|
|
||||||
using osu.Framework.Allocation;
|
|
||||||
using osu.Framework.Utils;
|
|
||||||
using osu.Game.Beatmaps;
|
|
||||||
using osu.Game.Rulesets;
|
|
||||||
using osu.Game.Tournament.Models;
|
|
||||||
using osu.Game.Users;
|
|
||||||
|
|
||||||
namespace osu.Game.Tournament.Tests
|
|
||||||
{
|
|
||||||
[TestFixture]
|
|
||||||
public abstract class LadderTestScene : TournamentTestScene
|
|
||||||
{
|
|
||||||
[Cached]
|
|
||||||
protected LadderInfo Ladder { get; private set; } = new LadderInfo();
|
|
||||||
|
|
||||||
[Resolved]
|
|
||||||
private RulesetStore rulesetStore { get; set; }
|
|
||||||
|
|
||||||
[BackgroundDependencyLoader]
|
|
||||||
private void load()
|
|
||||||
{
|
|
||||||
Ladder.Ruleset.Value ??= rulesetStore.AvailableRulesets.First();
|
|
||||||
|
|
||||||
Ruleset.BindTo(Ladder.Ruleset);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override void LoadComplete()
|
|
||||||
{
|
|
||||||
base.LoadComplete();
|
|
||||||
|
|
||||||
TournamentMatch match = CreateSampleMatch();
|
|
||||||
|
|
||||||
Ladder.Rounds.Add(match.Round.Value);
|
|
||||||
Ladder.Matches.Add(match);
|
|
||||||
Ladder.Teams.Add(match.Team1.Value);
|
|
||||||
Ladder.Teams.Add(match.Team2.Value);
|
|
||||||
|
|
||||||
Ladder.CurrentMatch.Value = match;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static TournamentMatch CreateSampleMatch() => new TournamentMatch
|
|
||||||
{
|
|
||||||
Team1 =
|
|
||||||
{
|
|
||||||
Value = new TournamentTeam
|
|
||||||
{
|
|
||||||
FlagName = { Value = "JP" },
|
|
||||||
FullName = { Value = "Japan" },
|
|
||||||
LastYearPlacing = { Value = 10 },
|
|
||||||
Seed = { Value = "Low" },
|
|
||||||
SeedingResults =
|
|
||||||
{
|
|
||||||
new SeedingResult
|
|
||||||
{
|
|
||||||
Mod = { Value = "NM" },
|
|
||||||
Seed = { Value = 10 },
|
|
||||||
Beatmaps =
|
|
||||||
{
|
|
||||||
new SeedingBeatmap
|
|
||||||
{
|
|
||||||
BeatmapInfo = CreateSampleBeatmapInfo(),
|
|
||||||
Score = 12345672,
|
|
||||||
Seed = { Value = 24 },
|
|
||||||
},
|
|
||||||
new SeedingBeatmap
|
|
||||||
{
|
|
||||||
BeatmapInfo = CreateSampleBeatmapInfo(),
|
|
||||||
Score = 1234567,
|
|
||||||
Seed = { Value = 12 },
|
|
||||||
},
|
|
||||||
new SeedingBeatmap
|
|
||||||
{
|
|
||||||
BeatmapInfo = CreateSampleBeatmapInfo(),
|
|
||||||
Score = 1234567,
|
|
||||||
Seed = { Value = 16 },
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
new SeedingResult
|
|
||||||
{
|
|
||||||
Mod = { Value = "DT" },
|
|
||||||
Seed = { Value = 5 },
|
|
||||||
Beatmaps =
|
|
||||||
{
|
|
||||||
new SeedingBeatmap
|
|
||||||
{
|
|
||||||
BeatmapInfo = CreateSampleBeatmapInfo(),
|
|
||||||
Score = 234567,
|
|
||||||
Seed = { Value = 3 },
|
|
||||||
},
|
|
||||||
new SeedingBeatmap
|
|
||||||
{
|
|
||||||
BeatmapInfo = CreateSampleBeatmapInfo(),
|
|
||||||
Score = 234567,
|
|
||||||
Seed = { Value = 6 },
|
|
||||||
},
|
|
||||||
new SeedingBeatmap
|
|
||||||
{
|
|
||||||
BeatmapInfo = CreateSampleBeatmapInfo(),
|
|
||||||
Score = 234567,
|
|
||||||
Seed = { Value = 12 },
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
Players =
|
|
||||||
{
|
|
||||||
new User { Username = "Hello", Statistics = new UserStatistics { Ranks = new UserStatistics.UserRanks { Global = 12 } } },
|
|
||||||
new User { Username = "Hello", Statistics = new UserStatistics { Ranks = new UserStatistics.UserRanks { Global = 16 } } },
|
|
||||||
new User { Username = "Hello", Statistics = new UserStatistics { Ranks = new UserStatistics.UserRanks { Global = 20 } } },
|
|
||||||
new User { Username = "Hello", Statistics = new UserStatistics { Ranks = new UserStatistics.UserRanks { Global = 24 } } },
|
|
||||||
new User { Username = "Hello", Statistics = new UserStatistics { Ranks = new UserStatistics.UserRanks { Global = 30 } } },
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
Team2 =
|
|
||||||
{
|
|
||||||
Value = new TournamentTeam
|
|
||||||
{
|
|
||||||
FlagName = { Value = "US" },
|
|
||||||
FullName = { Value = "United States" },
|
|
||||||
Players =
|
|
||||||
{
|
|
||||||
new User { Username = "Hello" },
|
|
||||||
new User { Username = "Hello" },
|
|
||||||
new User { Username = "Hello" },
|
|
||||||
new User { Username = "Hello" },
|
|
||||||
new User { Username = "Hello" },
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
Round =
|
|
||||||
{
|
|
||||||
Value = new TournamentRound { Name = { Value = "Quarterfinals" } }
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
public static BeatmapInfo CreateSampleBeatmapInfo() =>
|
|
||||||
new BeatmapInfo { Metadata = new BeatmapMetadata { Title = "Test Title", Artist = "Test Artist", ID = RNG.Next(0, 1000000) } };
|
|
||||||
}
|
|
||||||
}
|
|
@ -8,7 +8,7 @@ using osu.Game.Tournament.Screens.Editors;
|
|||||||
|
|
||||||
namespace osu.Game.Tournament.Tests.Screens
|
namespace osu.Game.Tournament.Tests.Screens
|
||||||
{
|
{
|
||||||
public class TestSceneLadderEditorScreen : LadderTestScene
|
public class TestSceneLadderEditorScreen : TournamentTestScene
|
||||||
{
|
{
|
||||||
[BackgroundDependencyLoader]
|
[BackgroundDependencyLoader]
|
||||||
private void load()
|
private void load()
|
||||||
|
@ -8,7 +8,7 @@ using osu.Game.Tournament.Screens.Ladder;
|
|||||||
|
|
||||||
namespace osu.Game.Tournament.Tests.Screens
|
namespace osu.Game.Tournament.Tests.Screens
|
||||||
{
|
{
|
||||||
public class TestSceneLadderScreen : LadderTestScene
|
public class TestSceneLadderScreen : TournamentTestScene
|
||||||
{
|
{
|
||||||
[BackgroundDependencyLoader]
|
[BackgroundDependencyLoader]
|
||||||
private void load()
|
private void load()
|
||||||
|
@ -12,7 +12,7 @@ using osu.Game.Tournament.Screens.MapPool;
|
|||||||
|
|
||||||
namespace osu.Game.Tournament.Tests.Screens
|
namespace osu.Game.Tournament.Tests.Screens
|
||||||
{
|
{
|
||||||
public class TestSceneMapPoolScreen : LadderTestScene
|
public class TestSceneMapPoolScreen : TournamentTestScene
|
||||||
{
|
{
|
||||||
private MapPoolScreen screen;
|
private MapPoolScreen screen;
|
||||||
|
|
||||||
|
@ -5,7 +5,7 @@ using osu.Game.Tournament.Screens.Editors;
|
|||||||
|
|
||||||
namespace osu.Game.Tournament.Tests.Screens
|
namespace osu.Game.Tournament.Tests.Screens
|
||||||
{
|
{
|
||||||
public class TestSceneRoundEditorScreen : LadderTestScene
|
public class TestSceneRoundEditorScreen : TournamentTestScene
|
||||||
{
|
{
|
||||||
public TestSceneRoundEditorScreen()
|
public TestSceneRoundEditorScreen()
|
||||||
{
|
{
|
||||||
|
@ -7,7 +7,7 @@ using osu.Game.Tournament.Screens.Editors;
|
|||||||
|
|
||||||
namespace osu.Game.Tournament.Tests.Screens
|
namespace osu.Game.Tournament.Tests.Screens
|
||||||
{
|
{
|
||||||
public class TestSceneSeedingEditorScreen : LadderTestScene
|
public class TestSceneSeedingEditorScreen : TournamentTestScene
|
||||||
{
|
{
|
||||||
[Cached]
|
[Cached]
|
||||||
private readonly LadderInfo ladder = new LadderInfo();
|
private readonly LadderInfo ladder = new LadderInfo();
|
||||||
|
@ -8,7 +8,7 @@ using osu.Game.Tournament.Screens.TeamIntro;
|
|||||||
|
|
||||||
namespace osu.Game.Tournament.Tests.Screens
|
namespace osu.Game.Tournament.Tests.Screens
|
||||||
{
|
{
|
||||||
public class TestSceneSeedingScreen : LadderTestScene
|
public class TestSceneSeedingScreen : TournamentTestScene
|
||||||
{
|
{
|
||||||
[Cached]
|
[Cached]
|
||||||
private readonly LadderInfo ladder = new LadderInfo();
|
private readonly LadderInfo ladder = new LadderInfo();
|
||||||
|
@ -5,7 +5,7 @@ using osu.Game.Tournament.Screens.Editors;
|
|||||||
|
|
||||||
namespace osu.Game.Tournament.Tests.Screens
|
namespace osu.Game.Tournament.Tests.Screens
|
||||||
{
|
{
|
||||||
public class TestSceneTeamEditorScreen : LadderTestScene
|
public class TestSceneTeamEditorScreen : TournamentTestScene
|
||||||
{
|
{
|
||||||
public TestSceneTeamEditorScreen()
|
public TestSceneTeamEditorScreen()
|
||||||
{
|
{
|
||||||
|
@ -9,7 +9,7 @@ using osu.Game.Tournament.Screens.TeamIntro;
|
|||||||
|
|
||||||
namespace osu.Game.Tournament.Tests.Screens
|
namespace osu.Game.Tournament.Tests.Screens
|
||||||
{
|
{
|
||||||
public class TestSceneTeamIntroScreen : LadderTestScene
|
public class TestSceneTeamIntroScreen : TournamentTestScene
|
||||||
{
|
{
|
||||||
[Cached]
|
[Cached]
|
||||||
private readonly LadderInfo ladder = new LadderInfo();
|
private readonly LadderInfo ladder = new LadderInfo();
|
||||||
|
@ -4,25 +4,19 @@
|
|||||||
using System.Linq;
|
using System.Linq;
|
||||||
using osu.Framework.Allocation;
|
using osu.Framework.Allocation;
|
||||||
using osu.Framework.Graphics;
|
using osu.Framework.Graphics;
|
||||||
using osu.Game.Tournament.Models;
|
|
||||||
using osu.Game.Tournament.Screens.TeamWin;
|
using osu.Game.Tournament.Screens.TeamWin;
|
||||||
|
|
||||||
namespace osu.Game.Tournament.Tests.Screens
|
namespace osu.Game.Tournament.Tests.Screens
|
||||||
{
|
{
|
||||||
public class TestSceneTeamWinScreen : LadderTestScene
|
public class TestSceneTeamWinScreen : TournamentTestScene
|
||||||
{
|
{
|
||||||
[Cached]
|
|
||||||
private readonly LadderInfo ladder = new LadderInfo();
|
|
||||||
|
|
||||||
[BackgroundDependencyLoader]
|
[BackgroundDependencyLoader]
|
||||||
private void load()
|
private void load()
|
||||||
{
|
{
|
||||||
var match = new TournamentMatch();
|
var match = Ladder.CurrentMatch.Value;
|
||||||
match.Team1.Value = Ladder.Teams.FirstOrDefault(t => t.Acronym.Value == "USA");
|
|
||||||
match.Team2.Value = Ladder.Teams.FirstOrDefault(t => t.Acronym.Value == "JPN");
|
|
||||||
match.Round.Value = Ladder.Rounds.FirstOrDefault(g => g.Name.Value == "Finals");
|
match.Round.Value = Ladder.Rounds.FirstOrDefault(g => g.Name.Value == "Finals");
|
||||||
match.Completed.Value = true;
|
match.Completed.Value = true;
|
||||||
ladder.CurrentMatch.Value = match;
|
|
||||||
|
|
||||||
Add(new TeamWinScreen
|
Add(new TeamWinScreen
|
||||||
{
|
{
|
||||||
|
@ -1,13 +1,151 @@
|
|||||||
// 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.Allocation;
|
||||||
|
using osu.Framework.Platform;
|
||||||
using osu.Framework.Testing;
|
using osu.Framework.Testing;
|
||||||
|
using osu.Framework.Utils;
|
||||||
|
using osu.Game.Beatmaps;
|
||||||
|
using osu.Game.Rulesets;
|
||||||
using osu.Game.Tests.Visual;
|
using osu.Game.Tests.Visual;
|
||||||
|
using osu.Game.Tournament.IPC;
|
||||||
|
using osu.Game.Tournament.Models;
|
||||||
|
using osu.Game.Users;
|
||||||
|
|
||||||
namespace osu.Game.Tournament.Tests
|
namespace osu.Game.Tournament.Tests
|
||||||
{
|
{
|
||||||
public abstract class TournamentTestScene : OsuTestScene
|
public abstract class TournamentTestScene : OsuTestScene
|
||||||
{
|
{
|
||||||
|
[Cached]
|
||||||
|
protected LadderInfo Ladder { get; private set; } = new LadderInfo();
|
||||||
|
|
||||||
|
[Resolved]
|
||||||
|
private RulesetStore rulesetStore { get; set; }
|
||||||
|
|
||||||
|
[Cached]
|
||||||
|
protected MatchIPCInfo IPCInfo { get; private set; } = new MatchIPCInfo();
|
||||||
|
|
||||||
|
[BackgroundDependencyLoader]
|
||||||
|
private void load(Storage storage)
|
||||||
|
{
|
||||||
|
Ladder.Ruleset.Value ??= rulesetStore.AvailableRulesets.First();
|
||||||
|
|
||||||
|
TournamentMatch match = CreateSampleMatch();
|
||||||
|
|
||||||
|
Ladder.Rounds.Add(match.Round.Value);
|
||||||
|
Ladder.Matches.Add(match);
|
||||||
|
Ladder.Teams.Add(match.Team1.Value);
|
||||||
|
Ladder.Teams.Add(match.Team2.Value);
|
||||||
|
|
||||||
|
Ladder.CurrentMatch.Value = match;
|
||||||
|
|
||||||
|
Ruleset.BindTo(Ladder.Ruleset);
|
||||||
|
Dependencies.CacheAs(new StableInfo(storage));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static TournamentMatch CreateSampleMatch() => new TournamentMatch
|
||||||
|
{
|
||||||
|
Team1 =
|
||||||
|
{
|
||||||
|
Value = new TournamentTeam
|
||||||
|
{
|
||||||
|
Acronym = { Value = "JPN" },
|
||||||
|
FlagName = { Value = "JP" },
|
||||||
|
FullName = { Value = "Japan" },
|
||||||
|
LastYearPlacing = { Value = 10 },
|
||||||
|
Seed = { Value = "Low" },
|
||||||
|
SeedingResults =
|
||||||
|
{
|
||||||
|
new SeedingResult
|
||||||
|
{
|
||||||
|
Mod = { Value = "NM" },
|
||||||
|
Seed = { Value = 10 },
|
||||||
|
Beatmaps =
|
||||||
|
{
|
||||||
|
new SeedingBeatmap
|
||||||
|
{
|
||||||
|
BeatmapInfo = CreateSampleBeatmapInfo(),
|
||||||
|
Score = 12345672,
|
||||||
|
Seed = { Value = 24 },
|
||||||
|
},
|
||||||
|
new SeedingBeatmap
|
||||||
|
{
|
||||||
|
BeatmapInfo = CreateSampleBeatmapInfo(),
|
||||||
|
Score = 1234567,
|
||||||
|
Seed = { Value = 12 },
|
||||||
|
},
|
||||||
|
new SeedingBeatmap
|
||||||
|
{
|
||||||
|
BeatmapInfo = CreateSampleBeatmapInfo(),
|
||||||
|
Score = 1234567,
|
||||||
|
Seed = { Value = 16 },
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
new SeedingResult
|
||||||
|
{
|
||||||
|
Mod = { Value = "DT" },
|
||||||
|
Seed = { Value = 5 },
|
||||||
|
Beatmaps =
|
||||||
|
{
|
||||||
|
new SeedingBeatmap
|
||||||
|
{
|
||||||
|
BeatmapInfo = CreateSampleBeatmapInfo(),
|
||||||
|
Score = 234567,
|
||||||
|
Seed = { Value = 3 },
|
||||||
|
},
|
||||||
|
new SeedingBeatmap
|
||||||
|
{
|
||||||
|
BeatmapInfo = CreateSampleBeatmapInfo(),
|
||||||
|
Score = 234567,
|
||||||
|
Seed = { Value = 6 },
|
||||||
|
},
|
||||||
|
new SeedingBeatmap
|
||||||
|
{
|
||||||
|
BeatmapInfo = CreateSampleBeatmapInfo(),
|
||||||
|
Score = 234567,
|
||||||
|
Seed = { Value = 12 },
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
Players =
|
||||||
|
{
|
||||||
|
new User { Username = "Hello", Statistics = new UserStatistics { Ranks = new UserStatistics.UserRanks { Global = 12 } } },
|
||||||
|
new User { Username = "Hello", Statistics = new UserStatistics { Ranks = new UserStatistics.UserRanks { Global = 16 } } },
|
||||||
|
new User { Username = "Hello", Statistics = new UserStatistics { Ranks = new UserStatistics.UserRanks { Global = 20 } } },
|
||||||
|
new User { Username = "Hello", Statistics = new UserStatistics { Ranks = new UserStatistics.UserRanks { Global = 24 } } },
|
||||||
|
new User { Username = "Hello", Statistics = new UserStatistics { Ranks = new UserStatistics.UserRanks { Global = 30 } } },
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
Team2 =
|
||||||
|
{
|
||||||
|
Value = new TournamentTeam
|
||||||
|
{
|
||||||
|
Acronym = { Value = "USA" },
|
||||||
|
FlagName = { Value = "US" },
|
||||||
|
FullName = { Value = "United States" },
|
||||||
|
Players =
|
||||||
|
{
|
||||||
|
new User { Username = "Hello" },
|
||||||
|
new User { Username = "Hello" },
|
||||||
|
new User { Username = "Hello" },
|
||||||
|
new User { Username = "Hello" },
|
||||||
|
new User { Username = "Hello" },
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
Round =
|
||||||
|
{
|
||||||
|
Value = new TournamentRound { Name = { Value = "Quarterfinals" } }
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
public static BeatmapInfo CreateSampleBeatmapInfo() =>
|
||||||
|
new BeatmapInfo { Metadata = new BeatmapMetadata { Title = "Test Title", Artist = "Test Artist", ID = RNG.Next(0, 1000000) } };
|
||||||
|
|
||||||
protected override ITestSceneTestRunner CreateRunner() => new TournamentTestSceneTestRunner();
|
protected override ITestSceneTestRunner CreateRunner() => new TournamentTestSceneTestRunner();
|
||||||
|
|
||||||
public class TournamentTestSceneTestRunner : TournamentGameBase, ITestSceneTestRunner
|
public class TournamentTestSceneTestRunner : TournamentGameBase, ITestSceneTestRunner
|
||||||
|
@ -37,7 +37,7 @@ namespace osu.Game.Tournament
|
|||||||
|
|
||||||
public const float STREAM_AREA_WIDTH = 1366;
|
public const float STREAM_AREA_WIDTH = 1366;
|
||||||
|
|
||||||
public const double REQUIRED_WIDTH = TournamentSceneManager.CONTROL_AREA_WIDTH * 2 + TournamentSceneManager.STREAM_AREA_WIDTH;
|
public const double REQUIRED_WIDTH = CONTROL_AREA_WIDTH * 2 + STREAM_AREA_WIDTH;
|
||||||
|
|
||||||
[Cached]
|
[Cached]
|
||||||
private TournamentMatchChatDisplay chat = new TournamentMatchChatDisplay();
|
private TournamentMatchChatDisplay chat = new TournamentMatchChatDisplay();
|
||||||
|
@ -103,7 +103,12 @@ namespace osu.Game.Beatmaps.Formats
|
|||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
colour = new Color4(byte.Parse(split[0]), byte.Parse(split[1]), byte.Parse(split[2]), split.Length == 4 ? byte.Parse(split[3]) : (byte)255);
|
byte alpha = split.Length == 4 ? byte.Parse(split[3]) : (byte)255;
|
||||||
|
|
||||||
|
if (alpha == 0)
|
||||||
|
alpha = 255;
|
||||||
|
|
||||||
|
colour = new Color4(byte.Parse(split[0]), byte.Parse(split[1]), byte.Parse(split[2]), alpha);
|
||||||
}
|
}
|
||||||
catch
|
catch
|
||||||
{
|
{
|
||||||
|
@ -11,7 +11,7 @@ namespace osu.Game.Beatmaps.Formats
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public static class Parsing
|
public static class Parsing
|
||||||
{
|
{
|
||||||
public const int MAX_COORDINATE_VALUE = 65536;
|
public const int MAX_COORDINATE_VALUE = 131072;
|
||||||
|
|
||||||
public const double MAX_PARSE_VALUE = int.MaxValue;
|
public const double MAX_PARSE_VALUE = int.MaxValue;
|
||||||
|
|
||||||
|
9
osu.Game/Rulesets/Mods/IApplicableToAudio.cs
Normal file
9
osu.Game/Rulesets/Mods/IApplicableToAudio.cs
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||||
|
// See the LICENCE file in the repository root for full licence text.
|
||||||
|
|
||||||
|
namespace osu.Game.Rulesets.Mods
|
||||||
|
{
|
||||||
|
public interface IApplicableToAudio : IApplicableToTrack, IApplicableToSample
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
15
osu.Game/Rulesets/Mods/IApplicableToSample.cs
Normal file
15
osu.Game/Rulesets/Mods/IApplicableToSample.cs
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
// 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.Audio.Sample;
|
||||||
|
|
||||||
|
namespace osu.Game.Rulesets.Mods
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// An interface for mods that make adjustments to a sample.
|
||||||
|
/// </summary>
|
||||||
|
public interface IApplicableToSample : IApplicableMod
|
||||||
|
{
|
||||||
|
void ApplyToSample(SampleChannel sample);
|
||||||
|
}
|
||||||
|
}
|
@ -2,12 +2,13 @@
|
|||||||
// 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 osu.Framework.Audio;
|
using osu.Framework.Audio;
|
||||||
|
using osu.Framework.Audio.Sample;
|
||||||
using osu.Framework.Audio.Track;
|
using osu.Framework.Audio.Track;
|
||||||
using osu.Framework.Bindables;
|
using osu.Framework.Bindables;
|
||||||
|
|
||||||
namespace osu.Game.Rulesets.Mods
|
namespace osu.Game.Rulesets.Mods
|
||||||
{
|
{
|
||||||
public abstract class ModRateAdjust : Mod, IApplicableToTrack
|
public abstract class ModRateAdjust : Mod, IApplicableToAudio
|
||||||
{
|
{
|
||||||
public abstract BindableNumber<double> SpeedChange { get; }
|
public abstract BindableNumber<double> SpeedChange { get; }
|
||||||
|
|
||||||
@ -16,6 +17,11 @@ namespace osu.Game.Rulesets.Mods
|
|||||||
track.AddAdjustment(AdjustableProperty.Tempo, SpeedChange);
|
track.AddAdjustment(AdjustableProperty.Tempo, SpeedChange);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public virtual void ApplyToSample(SampleChannel sample)
|
||||||
|
{
|
||||||
|
sample.AddAdjustment(AdjustableProperty.Frequency, SpeedChange);
|
||||||
|
}
|
||||||
|
|
||||||
public override string SettingDescription => SpeedChange.IsDefault ? string.Empty : $"{SpeedChange.Value:N2}x";
|
public override string SettingDescription => SpeedChange.IsDefault ? string.Empty : $"{SpeedChange.Value:N2}x";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -10,10 +10,11 @@ using osu.Game.Beatmaps;
|
|||||||
using osu.Game.Configuration;
|
using osu.Game.Configuration;
|
||||||
using osu.Game.Rulesets.UI;
|
using osu.Game.Rulesets.UI;
|
||||||
using osu.Game.Rulesets.Objects;
|
using osu.Game.Rulesets.Objects;
|
||||||
|
using osu.Framework.Audio.Sample;
|
||||||
|
|
||||||
namespace osu.Game.Rulesets.Mods
|
namespace osu.Game.Rulesets.Mods
|
||||||
{
|
{
|
||||||
public abstract class ModTimeRamp : Mod, IUpdatableByPlayfield, IApplicableToBeatmap, IApplicableToTrack
|
public abstract class ModTimeRamp : Mod, IUpdatableByPlayfield, IApplicableToBeatmap, IApplicableToAudio
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The point in the beatmap at which the final ramping rate should be reached.
|
/// The point in the beatmap at which the final ramping rate should be reached.
|
||||||
@ -58,6 +59,11 @@ namespace osu.Game.Rulesets.Mods
|
|||||||
AdjustPitch.TriggerChange();
|
AdjustPitch.TriggerChange();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void ApplyToSample(SampleChannel sample)
|
||||||
|
{
|
||||||
|
sample.AddAdjustment(AdjustableProperty.Frequency, SpeedChange);
|
||||||
|
}
|
||||||
|
|
||||||
public virtual void ApplyToBeatmap(IBeatmap beatmap)
|
public virtual void ApplyToBeatmap(IBeatmap beatmap)
|
||||||
{
|
{
|
||||||
HitObject lastObject = beatmap.HitObjects.LastOrDefault();
|
HitObject lastObject = beatmap.HitObjects.LastOrDefault();
|
||||||
|
@ -12,6 +12,7 @@ using System.Linq;
|
|||||||
using JetBrains.Annotations;
|
using JetBrains.Annotations;
|
||||||
using osu.Framework.Utils;
|
using osu.Framework.Utils;
|
||||||
using osu.Game.Beatmaps.Legacy;
|
using osu.Game.Beatmaps.Legacy;
|
||||||
|
using osu.Game.Skinning;
|
||||||
|
|
||||||
namespace osu.Game.Rulesets.Objects.Legacy
|
namespace osu.Game.Rulesets.Objects.Legacy
|
||||||
{
|
{
|
||||||
@ -356,7 +357,10 @@ namespace osu.Game.Rulesets.Objects.Legacy
|
|||||||
Bank = bankInfo.Normal,
|
Bank = bankInfo.Normal,
|
||||||
Name = HitSampleInfo.HIT_NORMAL,
|
Name = HitSampleInfo.HIT_NORMAL,
|
||||||
Volume = bankInfo.Volume,
|
Volume = bankInfo.Volume,
|
||||||
CustomSampleBank = bankInfo.CustomSampleBank
|
CustomSampleBank = bankInfo.CustomSampleBank,
|
||||||
|
// if the sound type doesn't have the Normal flag set, attach it anyway as a layered sample.
|
||||||
|
// None also counts as a normal non-layered sample: https://osu.ppy.sh/help/wiki/osu!_File_Formats/Osu_(file_format)#hitsounds
|
||||||
|
IsLayered = type != LegacyHitSoundType.None && !type.HasFlag(LegacyHitSoundType.Normal)
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -409,7 +413,7 @@ namespace osu.Game.Rulesets.Objects.Legacy
|
|||||||
public SampleBankInfo Clone() => (SampleBankInfo)MemberwiseClone();
|
public SampleBankInfo Clone() => (SampleBankInfo)MemberwiseClone();
|
||||||
}
|
}
|
||||||
|
|
||||||
internal class LegacyHitSampleInfo : HitSampleInfo
|
public class LegacyHitSampleInfo : HitSampleInfo
|
||||||
{
|
{
|
||||||
private int customSampleBank;
|
private int customSampleBank;
|
||||||
|
|
||||||
@ -424,6 +428,15 @@ namespace osu.Game.Rulesets.Objects.Legacy
|
|||||||
Suffix = value.ToString();
|
Suffix = value.ToString();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Whether this hit sample is layered.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Layered hit samples are automatically added in all modes (except osu!mania), but can be disabled
|
||||||
|
/// using the <see cref="GlobalSkinConfiguration.LayeredHitSounds"/> skin config option.
|
||||||
|
/// </remarks>
|
||||||
|
public bool IsLayered { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
private class FileHitSampleInfo : LegacyHitSampleInfo
|
private class FileHitSampleInfo : LegacyHitSampleInfo
|
||||||
|
@ -12,7 +12,7 @@ namespace osu.Game.Screens.Select
|
|||||||
public ImportFromStablePopup(Action importFromStable)
|
public ImportFromStablePopup(Action importFromStable)
|
||||||
{
|
{
|
||||||
HeaderText = @"You have no beatmaps!";
|
HeaderText = @"You have no beatmaps!";
|
||||||
BodyText = "An existing copy of osu! was found, though.\nWould you like to import your beatmaps, skins and scores?";
|
BodyText = "An existing copy of osu! was found, though.\nWould you like to import your beatmaps, skins and scores?\nThis will create a second copy of all files on disk.";
|
||||||
|
|
||||||
Icon = FontAwesome.Solid.Plane;
|
Icon = FontAwesome.Solid.Plane;
|
||||||
|
|
||||||
|
@ -5,6 +5,7 @@ namespace osu.Game.Skinning
|
|||||||
{
|
{
|
||||||
public enum GlobalSkinConfiguration
|
public enum GlobalSkinConfiguration
|
||||||
{
|
{
|
||||||
AnimationFramerate
|
AnimationFramerate,
|
||||||
|
LayeredHitSounds,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -6,6 +6,7 @@ using osu.Framework.Bindables;
|
|||||||
using osu.Framework.Graphics;
|
using osu.Framework.Graphics;
|
||||||
using osu.Framework.Graphics.Textures;
|
using osu.Framework.Graphics.Textures;
|
||||||
using osu.Game.Audio;
|
using osu.Game.Audio;
|
||||||
|
using osu.Game.Rulesets.Objects.Legacy;
|
||||||
|
|
||||||
namespace osu.Game.Skinning
|
namespace osu.Game.Skinning
|
||||||
{
|
{
|
||||||
@ -28,7 +29,17 @@ namespace osu.Game.Skinning
|
|||||||
|
|
||||||
public Texture GetTexture(string componentName) => Source.GetTexture(componentName);
|
public Texture GetTexture(string componentName) => Source.GetTexture(componentName);
|
||||||
|
|
||||||
public virtual SampleChannel GetSample(ISampleInfo sampleInfo) => Source.GetSample(sampleInfo);
|
public virtual SampleChannel GetSample(ISampleInfo sampleInfo)
|
||||||
|
{
|
||||||
|
if (!(sampleInfo is ConvertHitObjectParser.LegacyHitSampleInfo legacySample))
|
||||||
|
return Source.GetSample(sampleInfo);
|
||||||
|
|
||||||
|
var playLayeredHitSounds = GetConfig<GlobalSkinConfiguration, bool>(GlobalSkinConfiguration.LayeredHitSounds);
|
||||||
|
if (legacySample.IsLayered && playLayeredHitSounds?.Value == false)
|
||||||
|
return new SampleChannelVirtual();
|
||||||
|
|
||||||
|
return Source.GetSample(sampleInfo);
|
||||||
|
}
|
||||||
|
|
||||||
public abstract IBindable<TValue> GetConfig<TLookup, TValue>(TLookup lookup);
|
public abstract IBindable<TValue> GetConfig<TLookup, TValue>(TLookup lookup);
|
||||||
}
|
}
|
||||||
|
@ -1,11 +1,14 @@
|
|||||||
// 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.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
using osu.Framework.Allocation;
|
using osu.Framework.Allocation;
|
||||||
using osu.Framework.Audio.Sample;
|
using osu.Framework.Audio.Sample;
|
||||||
using osu.Framework.Bindables;
|
using osu.Framework.Bindables;
|
||||||
using osu.Framework.Graphics;
|
using osu.Framework.Graphics;
|
||||||
using osu.Game.Beatmaps;
|
using osu.Game.Beatmaps;
|
||||||
|
using osu.Game.Rulesets.Mods;
|
||||||
|
|
||||||
namespace osu.Game.Storyboards.Drawables
|
namespace osu.Game.Storyboards.Drawables
|
||||||
{
|
{
|
||||||
@ -17,7 +20,8 @@ namespace osu.Game.Storyboards.Drawables
|
|||||||
private const double allowable_late_start = 100;
|
private const double allowable_late_start = 100;
|
||||||
|
|
||||||
private readonly StoryboardSampleInfo sampleInfo;
|
private readonly StoryboardSampleInfo sampleInfo;
|
||||||
private SampleChannel channel;
|
|
||||||
|
protected SampleChannel Channel { get; private set; }
|
||||||
|
|
||||||
public override bool RemoveWhenNotAlive => false;
|
public override bool RemoveWhenNotAlive => false;
|
||||||
|
|
||||||
@ -28,12 +32,16 @@ namespace osu.Game.Storyboards.Drawables
|
|||||||
}
|
}
|
||||||
|
|
||||||
[BackgroundDependencyLoader]
|
[BackgroundDependencyLoader]
|
||||||
private void load(IBindable<WorkingBeatmap> beatmap)
|
private void load(IBindable<WorkingBeatmap> beatmap, IBindable<IReadOnlyList<Mod>> mods)
|
||||||
{
|
{
|
||||||
channel = beatmap.Value.Skin.GetSample(sampleInfo);
|
Channel = beatmap.Value.Skin.GetSample(sampleInfo);
|
||||||
|
if (Channel == null)
|
||||||
|
return;
|
||||||
|
|
||||||
if (channel != null)
|
Channel.Volume.Value = sampleInfo.Volume / 100.0;
|
||||||
channel.Volume.Value = sampleInfo.Volume / 100.0;
|
|
||||||
|
foreach (var mod in mods.Value.OfType<IApplicableToSample>())
|
||||||
|
mod.ApplyToSample(Channel);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void Update()
|
protected override void Update()
|
||||||
@ -44,7 +52,7 @@ namespace osu.Game.Storyboards.Drawables
|
|||||||
if (Time.Current < sampleInfo.StartTime)
|
if (Time.Current < sampleInfo.StartTime)
|
||||||
{
|
{
|
||||||
// We've rewound before the start time of the sample
|
// We've rewound before the start time of the sample
|
||||||
channel?.Stop();
|
Channel?.Stop();
|
||||||
|
|
||||||
// In the case that the user fast-forwards to a point far beyond the start time of the sample,
|
// In the case that the user fast-forwards to a point far beyond the start time of the sample,
|
||||||
// we want to be able to fall into the if-conditional below (therefore we must not have a life time end)
|
// we want to be able to fall into the if-conditional below (therefore we must not have a life time end)
|
||||||
@ -56,7 +64,7 @@ namespace osu.Game.Storyboards.Drawables
|
|||||||
// We've passed the start time of the sample. We only play the sample if we're within an allowable range
|
// We've passed the start time of the sample. We only play the sample if we're within an allowable range
|
||||||
// from the sample's start, to reduce layering if we've been fast-forwarded far into the future
|
// from the sample's start, to reduce layering if we've been fast-forwarded far into the future
|
||||||
if (Time.Current - sampleInfo.StartTime < allowable_late_start)
|
if (Time.Current - sampleInfo.StartTime < allowable_late_start)
|
||||||
channel?.Play();
|
Channel?.Play();
|
||||||
|
|
||||||
// In the case that the user rewinds to a point far behind the start time of the sample,
|
// In the case that the user rewinds to a point far behind the start time of the sample,
|
||||||
// we want to be able to fall into the if-conditional above (therefore we must not have a life time start)
|
// we want to be able to fall into the if-conditional above (therefore we must not have a life time start)
|
||||||
@ -67,7 +75,7 @@ namespace osu.Game.Storyboards.Drawables
|
|||||||
|
|
||||||
protected override void Dispose(bool isDisposing)
|
protected override void Dispose(bool isDisposing)
|
||||||
{
|
{
|
||||||
channel?.Stop();
|
Channel?.Stop();
|
||||||
base.Dispose(isDisposing);
|
base.Dispose(isDisposing);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -24,6 +24,10 @@ namespace osu.Game.Tests.Beatmaps
|
|||||||
public abstract class HitObjectSampleTest : PlayerTestScene
|
public abstract class HitObjectSampleTest : PlayerTestScene
|
||||||
{
|
{
|
||||||
protected abstract IResourceStore<byte[]> Resources { get; }
|
protected abstract IResourceStore<byte[]> Resources { get; }
|
||||||
|
protected LegacySkin Skin { get; private set; }
|
||||||
|
|
||||||
|
[Resolved]
|
||||||
|
private RulesetStore rulesetStore { get; set; }
|
||||||
|
|
||||||
private readonly SkinInfo userSkinInfo = new SkinInfo();
|
private readonly SkinInfo userSkinInfo = new SkinInfo();
|
||||||
|
|
||||||
@ -64,6 +68,9 @@ namespace osu.Game.Tests.Beatmaps
|
|||||||
{
|
{
|
||||||
using (var reader = new LineBufferedReader(Resources.GetStream($"Resources/SampleLookups/{filename}")))
|
using (var reader = new LineBufferedReader(Resources.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.
|
||||||
|
currentTestBeatmap.BeatmapInfo.Ruleset = rulesetStore.GetRuleset(currentTestBeatmap.BeatmapInfo.RulesetID);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -91,7 +98,7 @@ namespace osu.Game.Tests.Beatmaps
|
|||||||
};
|
};
|
||||||
|
|
||||||
// Need to refresh the cached skin source to refresh the skin resource store.
|
// Need to refresh the cached skin source to refresh the skin resource store.
|
||||||
dependencies.SkinSource = new SkinProvidingContainer(new LegacySkin(userSkinInfo, userSkinResourceStore, Audio));
|
dependencies.SkinSource = new SkinProvidingContainer(Skin = new LegacySkin(userSkinInfo, userSkinResourceStore, Audio));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -101,6 +108,9 @@ namespace osu.Game.Tests.Beatmaps
|
|||||||
protected void AssertUserLookup(string name) => AddAssert($"\"{name}\" looked up from user skin",
|
protected void AssertUserLookup(string name) => AddAssert($"\"{name}\" looked up from user skin",
|
||||||
() => !beatmapSkinResourceStore.PerformedLookups.Contains(name) && userSkinResourceStore.PerformedLookups.Contains(name));
|
() => !beatmapSkinResourceStore.PerformedLookups.Contains(name) && userSkinResourceStore.PerformedLookups.Contains(name));
|
||||||
|
|
||||||
|
protected void AssertNoLookup(string name) => AddAssert($"\"{name}\" not looked up",
|
||||||
|
() => !beatmapSkinResourceStore.PerformedLookups.Contains(name) && !userSkinResourceStore.PerformedLookups.Contains(name));
|
||||||
|
|
||||||
private class SkinSourceDependencyContainer : IReadOnlyDependencyContainer
|
private class SkinSourceDependencyContainer : IReadOnlyDependencyContainer
|
||||||
{
|
{
|
||||||
public ISkinSource SkinSource;
|
public ISkinSource SkinSource;
|
||||||
|
Loading…
Reference in New Issue
Block a user