mirror of
https://github.com/ppy/osu.git
synced 2024-11-11 12:17:26 +08:00
Merge branch 'master' of https://github.com/ppy/osu into arrow-easing
This commit is contained in:
commit
0b70c20aa3
@ -5,6 +5,6 @@
|
|||||||
"version": "3.1.100"
|
"version": "3.1.100"
|
||||||
},
|
},
|
||||||
"msbuild-sdks": {
|
"msbuild-sdks": {
|
||||||
"Microsoft.Build.Traversal": "2.0.32"
|
"Microsoft.Build.Traversal": "2.0.34"
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -52,6 +52,6 @@
|
|||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="ppy.osu.Game.Resources" Version="2020.403.0" />
|
<PackageReference Include="ppy.osu.Game.Resources" Version="2020.403.0" />
|
||||||
<PackageReference Include="ppy.osu.Framework.Android" Version="2020.403.0" />
|
<PackageReference Include="ppy.osu.Framework.Android" Version="2020.407.1" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
</Project>
|
</Project>
|
||||||
|
@ -39,7 +39,7 @@ namespace osu.Game.Rulesets.Mania.Skinning
|
|||||||
if (tmp is IFramedAnimation tmpAnimation && tmpAnimation.FrameCount > 0)
|
if (tmp is IFramedAnimation tmpAnimation && tmpAnimation.FrameCount > 0)
|
||||||
frameLength = Math.Max(1000 / 60.0, 170.0 / tmpAnimation.FrameCount);
|
frameLength = Math.Max(1000 / 60.0, 170.0 / tmpAnimation.FrameCount);
|
||||||
|
|
||||||
explosion = skin.GetAnimation(imageName, true, false, startAtCurrentTime: true, frameLength: frameLength).With(d =>
|
explosion = skin.GetAnimation(imageName, true, false, frameLength: frameLength).With(d =>
|
||||||
{
|
{
|
||||||
if (d == null)
|
if (d == null)
|
||||||
return;
|
return;
|
||||||
|
@ -20,6 +20,8 @@ namespace osu.Game.Rulesets.Mania.Skinning
|
|||||||
private Container directionContainer;
|
private Container directionContainer;
|
||||||
private Sprite noteSprite;
|
private Sprite noteSprite;
|
||||||
|
|
||||||
|
private float? minimumColumnWidth;
|
||||||
|
|
||||||
public LegacyNotePiece()
|
public LegacyNotePiece()
|
||||||
{
|
{
|
||||||
RelativeSizeAxes = Axes.X;
|
RelativeSizeAxes = Axes.X;
|
||||||
@ -29,6 +31,8 @@ namespace osu.Game.Rulesets.Mania.Skinning
|
|||||||
[BackgroundDependencyLoader]
|
[BackgroundDependencyLoader]
|
||||||
private void load(ISkinSource skin, IScrollingInfo scrollingInfo)
|
private void load(ISkinSource skin, IScrollingInfo scrollingInfo)
|
||||||
{
|
{
|
||||||
|
minimumColumnWidth = skin.GetConfig<ManiaSkinConfigurationLookup, float>(new ManiaSkinConfigurationLookup(LegacyManiaSkinConfigurationLookups.MinimumColumnWidth))?.Value;
|
||||||
|
|
||||||
InternalChild = directionContainer = new Container
|
InternalChild = directionContainer = new Container
|
||||||
{
|
{
|
||||||
Origin = Anchor.BottomCentre,
|
Origin = Anchor.BottomCentre,
|
||||||
@ -47,8 +51,10 @@ namespace osu.Game.Rulesets.Mania.Skinning
|
|||||||
|
|
||||||
if (noteSprite.Texture != null)
|
if (noteSprite.Texture != null)
|
||||||
{
|
{
|
||||||
var scale = DrawWidth / noteSprite.Texture.DisplayWidth;
|
// The height is scaled to the minimum column width, if provided.
|
||||||
noteSprite.Scale = new Vector2(scale);
|
float minimumWidth = minimumColumnWidth ?? DrawWidth;
|
||||||
|
|
||||||
|
noteSprite.Scale = Vector2.Divide(new Vector2(DrawWidth, minimumWidth), noteSprite.Texture.DisplayWidth);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -64,6 +64,7 @@ namespace osu.Game.Rulesets.Mania.UI
|
|||||||
{
|
{
|
||||||
// Mania doesn't care about global velocity
|
// Mania doesn't care about global velocity
|
||||||
p.Velocity = 1;
|
p.Velocity = 1;
|
||||||
|
p.BaseBeatLength *= Beatmap.BeatmapInfo.BaseDifficulty.SliderMultiplier;
|
||||||
|
|
||||||
// For non-mania beatmap, speed changes should only happen through timing points
|
// For non-mania beatmap, speed changes should only happen through timing points
|
||||||
if (!isForCurrentRuleset)
|
if (!isForCurrentRuleset)
|
||||||
|
253
osu.Game.Rulesets.Osu.Tests/TestSceneSliderSnaking.cs
Normal file
253
osu.Game.Rulesets.Osu.Tests/TestSceneSliderSnaking.cs
Normal file
@ -0,0 +1,253 @@
|
|||||||
|
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||||
|
// See the LICENCE file in the repository root for full licence text.
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using Humanizer;
|
||||||
|
using NUnit.Framework;
|
||||||
|
using osu.Framework.Allocation;
|
||||||
|
using osu.Framework.Audio;
|
||||||
|
using osu.Framework.Bindables;
|
||||||
|
using osu.Framework.Graphics.Containers;
|
||||||
|
using osu.Framework.Testing;
|
||||||
|
using osu.Framework.Timing;
|
||||||
|
using osu.Framework.Utils;
|
||||||
|
using osu.Game.Beatmaps;
|
||||||
|
using osu.Game.Rulesets.Objects;
|
||||||
|
using osu.Game.Rulesets.Objects.Types;
|
||||||
|
using osu.Game.Rulesets.Osu.Configuration;
|
||||||
|
using osu.Game.Rulesets.Osu.Objects;
|
||||||
|
using osu.Game.Rulesets.Osu.Objects.Drawables;
|
||||||
|
using osu.Game.Rulesets.Osu.Objects.Drawables.Pieces;
|
||||||
|
using osu.Game.Storyboards;
|
||||||
|
using osuTK;
|
||||||
|
using static osu.Game.Tests.Visual.OsuTestScene.ClockBackedTestWorkingBeatmap;
|
||||||
|
|
||||||
|
namespace osu.Game.Rulesets.Osu.Tests
|
||||||
|
{
|
||||||
|
[TestFixture]
|
||||||
|
public class TestSceneSliderSnaking : TestSceneOsuPlayer
|
||||||
|
{
|
||||||
|
[Resolved]
|
||||||
|
private AudioManager audioManager { get; set; }
|
||||||
|
|
||||||
|
private TrackVirtualManual track;
|
||||||
|
|
||||||
|
protected override bool Autoplay => autoplay;
|
||||||
|
private bool autoplay;
|
||||||
|
|
||||||
|
private readonly BindableBool snakingIn = new BindableBool();
|
||||||
|
private readonly BindableBool snakingOut = new BindableBool();
|
||||||
|
|
||||||
|
private const double duration_of_span = 3605;
|
||||||
|
private const double fade_in_modifier = -1200;
|
||||||
|
|
||||||
|
protected override WorkingBeatmap CreateWorkingBeatmap(IBeatmap beatmap, Storyboard storyboard = null)
|
||||||
|
{
|
||||||
|
var working = new ClockBackedTestWorkingBeatmap(beatmap, storyboard, new FramedClock(new ManualClock { Rate = 1 }), audioManager);
|
||||||
|
track = (TrackVirtualManual)working.Track;
|
||||||
|
return working;
|
||||||
|
}
|
||||||
|
|
||||||
|
[BackgroundDependencyLoader]
|
||||||
|
private void load(RulesetConfigCache configCache)
|
||||||
|
{
|
||||||
|
var config = (OsuRulesetConfigManager)configCache.GetConfigFor(Ruleset.Value.CreateInstance());
|
||||||
|
config.BindWith(OsuRulesetSetting.SnakingInSliders, snakingIn);
|
||||||
|
config.BindWith(OsuRulesetSetting.SnakingOutSliders, snakingOut);
|
||||||
|
}
|
||||||
|
|
||||||
|
private DrawableSlider slider;
|
||||||
|
|
||||||
|
[SetUpSteps]
|
||||||
|
public override void SetUpSteps() { }
|
||||||
|
|
||||||
|
[TestCase(0)]
|
||||||
|
[TestCase(1)]
|
||||||
|
[TestCase(2)]
|
||||||
|
public void TestSnakingEnabled(int sliderIndex)
|
||||||
|
{
|
||||||
|
AddStep("enable autoplay", () => autoplay = true);
|
||||||
|
base.SetUpSteps();
|
||||||
|
AddUntilStep("wait for track to start running", () => track.IsRunning);
|
||||||
|
|
||||||
|
double startTime = hitObjects[sliderIndex].StartTime;
|
||||||
|
retrieveDrawableSlider(sliderIndex);
|
||||||
|
setSnaking(true);
|
||||||
|
|
||||||
|
ensureSnakingIn(startTime + fade_in_modifier);
|
||||||
|
|
||||||
|
for (int i = 0; i < sliderIndex; i++)
|
||||||
|
{
|
||||||
|
// non-final repeats should not snake out
|
||||||
|
ensureNoSnakingOut(startTime, i);
|
||||||
|
}
|
||||||
|
|
||||||
|
// final repeat should snake out
|
||||||
|
ensureSnakingOut(startTime, sliderIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestCase(0)]
|
||||||
|
[TestCase(1)]
|
||||||
|
[TestCase(2)]
|
||||||
|
public void TestSnakingDisabled(int sliderIndex)
|
||||||
|
{
|
||||||
|
AddStep("have autoplay", () => autoplay = true);
|
||||||
|
base.SetUpSteps();
|
||||||
|
AddUntilStep("wait for track to start running", () => track.IsRunning);
|
||||||
|
|
||||||
|
double startTime = hitObjects[sliderIndex].StartTime;
|
||||||
|
retrieveDrawableSlider(sliderIndex);
|
||||||
|
setSnaking(false);
|
||||||
|
|
||||||
|
ensureNoSnakingIn(startTime + fade_in_modifier);
|
||||||
|
|
||||||
|
for (int i = 0; i <= sliderIndex; i++)
|
||||||
|
{
|
||||||
|
// no snaking out ever, including final repeat
|
||||||
|
ensureNoSnakingOut(startTime, i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void TestRepeatArrowDoesNotMoveWhenHit()
|
||||||
|
{
|
||||||
|
AddStep("enable autoplay", () => autoplay = true);
|
||||||
|
setSnaking(true);
|
||||||
|
base.SetUpSteps();
|
||||||
|
|
||||||
|
// repeat might have a chance to update its position depending on where in the frame its hit,
|
||||||
|
// so some leniency is allowed here instead of checking strict equality
|
||||||
|
checkPositionChange(16600, sliderRepeat, positionAlmostSame);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void TestRepeatArrowMovesWhenNotHit()
|
||||||
|
{
|
||||||
|
AddStep("disable autoplay", () => autoplay = false);
|
||||||
|
setSnaking(true);
|
||||||
|
base.SetUpSteps();
|
||||||
|
|
||||||
|
checkPositionChange(16600, sliderRepeat, positionDecreased);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void retrieveDrawableSlider(int index) => AddStep($"retrieve {(index + 1).ToOrdinalWords()} slider", () =>
|
||||||
|
{
|
||||||
|
slider = (DrawableSlider)Player.DrawableRuleset.Playfield.AllHitObjects.ElementAt(index);
|
||||||
|
});
|
||||||
|
|
||||||
|
private void ensureSnakingIn(double startTime) => checkPositionChange(startTime, sliderEnd, positionIncreased);
|
||||||
|
private void ensureNoSnakingIn(double startTime) => checkPositionChange(startTime, sliderEnd, positionRemainsSame);
|
||||||
|
|
||||||
|
private void ensureSnakingOut(double startTime, int repeatIndex)
|
||||||
|
{
|
||||||
|
var repeatTime = timeAtRepeat(startTime, repeatIndex);
|
||||||
|
|
||||||
|
if (repeatIndex % 2 == 0)
|
||||||
|
checkPositionChange(repeatTime, sliderStart, positionIncreased);
|
||||||
|
else
|
||||||
|
checkPositionChange(repeatTime, sliderEnd, positionDecreased);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ensureNoSnakingOut(double startTime, int repeatIndex) =>
|
||||||
|
checkPositionChange(timeAtRepeat(startTime, repeatIndex), positionAtRepeat(repeatIndex), positionRemainsSame);
|
||||||
|
|
||||||
|
private double timeAtRepeat(double startTime, int repeatIndex) => startTime + 100 + duration_of_span * repeatIndex;
|
||||||
|
private Func<Vector2> positionAtRepeat(int repeatIndex) => repeatIndex % 2 == 0 ? (Func<Vector2>)sliderStart : sliderEnd;
|
||||||
|
|
||||||
|
private List<Vector2> sliderCurve => ((PlaySliderBody)slider.Body.Drawable).CurrentCurve;
|
||||||
|
private Vector2 sliderStart() => sliderCurve.First();
|
||||||
|
private Vector2 sliderEnd() => sliderCurve.Last();
|
||||||
|
|
||||||
|
private Vector2 sliderRepeat()
|
||||||
|
{
|
||||||
|
var drawable = Player.DrawableRuleset.Playfield.AllHitObjects.ElementAt(1);
|
||||||
|
var repeat = drawable.ChildrenOfType<Container<DrawableSliderRepeat>>().First().Children.First();
|
||||||
|
return repeat.Position;
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool positionRemainsSame(Vector2 previous, Vector2 current) => previous == current;
|
||||||
|
private bool positionIncreased(Vector2 previous, Vector2 current) => current.X > previous.X && current.Y > previous.Y;
|
||||||
|
private bool positionDecreased(Vector2 previous, Vector2 current) => current.X < previous.X && current.Y < previous.Y;
|
||||||
|
private bool positionAlmostSame(Vector2 previous, Vector2 current) => Precision.AlmostEquals(previous, current, 1);
|
||||||
|
|
||||||
|
private void checkPositionChange(double startTime, Func<Vector2> positionToCheck, Func<Vector2, Vector2, bool> positionAssertion)
|
||||||
|
{
|
||||||
|
Vector2 previousPosition = Vector2.Zero;
|
||||||
|
|
||||||
|
string positionDescription = positionToCheck.Method.Name.Humanize(LetterCasing.LowerCase);
|
||||||
|
string assertionDescription = positionAssertion.Method.Name.Humanize(LetterCasing.LowerCase);
|
||||||
|
|
||||||
|
addSeekStep(startTime);
|
||||||
|
AddStep($"save {positionDescription} position", () => previousPosition = positionToCheck.Invoke());
|
||||||
|
addSeekStep(startTime + 100);
|
||||||
|
AddAssert($"{positionDescription} {assertionDescription}", () =>
|
||||||
|
{
|
||||||
|
var currentPosition = positionToCheck.Invoke();
|
||||||
|
return positionAssertion.Invoke(previousPosition, currentPosition);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setSnaking(bool value)
|
||||||
|
{
|
||||||
|
AddStep($"{(value ? "enable" : "disable")} snaking", () =>
|
||||||
|
{
|
||||||
|
snakingIn.Value = value;
|
||||||
|
snakingOut.Value = value;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private void addSeekStep(double time)
|
||||||
|
{
|
||||||
|
AddStep($"seek to {time}", () => track.Seek(time));
|
||||||
|
|
||||||
|
AddUntilStep("wait for seek to finish", () => Precision.AlmostEquals(time, Player.DrawableRuleset.FrameStableClock.CurrentTime, 100));
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override IBeatmap CreateBeatmap(RulesetInfo ruleset) => new Beatmap
|
||||||
|
{
|
||||||
|
HitObjects = hitObjects
|
||||||
|
};
|
||||||
|
|
||||||
|
private readonly List<HitObject> hitObjects = new List<HitObject>
|
||||||
|
{
|
||||||
|
new Slider
|
||||||
|
{
|
||||||
|
StartTime = 3000,
|
||||||
|
Position = new Vector2(100, 100),
|
||||||
|
Path = new SliderPath(PathType.PerfectCurve, new[]
|
||||||
|
{
|
||||||
|
Vector2.Zero,
|
||||||
|
new Vector2(300, 200)
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
new Slider
|
||||||
|
{
|
||||||
|
StartTime = 13000,
|
||||||
|
Position = new Vector2(100, 100),
|
||||||
|
Path = new SliderPath(PathType.PerfectCurve, new[]
|
||||||
|
{
|
||||||
|
Vector2.Zero,
|
||||||
|
new Vector2(300, 200)
|
||||||
|
}),
|
||||||
|
RepeatCount = 1,
|
||||||
|
},
|
||||||
|
new Slider
|
||||||
|
{
|
||||||
|
StartTime = 23000,
|
||||||
|
Position = new Vector2(100, 100),
|
||||||
|
Path = new SliderPath(PathType.PerfectCurve, new[]
|
||||||
|
{
|
||||||
|
Vector2.Zero,
|
||||||
|
new Vector2(300, 200)
|
||||||
|
}),
|
||||||
|
RepeatCount = 2,
|
||||||
|
},
|
||||||
|
new HitCircle
|
||||||
|
{
|
||||||
|
StartTime = 199999,
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
@ -43,7 +43,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Connections
|
|||||||
Anchor = Anchor.Centre,
|
Anchor = Anchor.Centre,
|
||||||
Alpha = 0.5f,
|
Alpha = 0.5f,
|
||||||
}
|
}
|
||||||
}, confineMode: ConfineMode.NoScaling);
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public double AnimationStartTime { get; set; }
|
public double AnimationStartTime { get; set; }
|
||||||
|
@ -186,7 +186,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
|
|||||||
base.ApplySkin(skin, allowFallback);
|
base.ApplySkin(skin, allowFallback);
|
||||||
|
|
||||||
bool allowBallTint = skin.GetConfig<OsuSkinConfiguration, bool>(OsuSkinConfiguration.AllowSliderBallTint)?.Value ?? false;
|
bool allowBallTint = skin.GetConfig<OsuSkinConfiguration, bool>(OsuSkinConfiguration.AllowSliderBallTint)?.Value ?? false;
|
||||||
Ball.Colour = allowBallTint ? AccentColour.Value : Color4.White;
|
Ball.AccentColour = allowBallTint ? AccentColour.Value : Color4.White;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void CheckForResult(bool userTriggered, double timeOffset)
|
protected override void CheckForResult(bool userTriggered, double timeOffset)
|
||||||
|
@ -46,7 +46,7 @@ namespace osu.Game.Rulesets.Osu.Skinning
|
|||||||
switch (osuComponent.Component)
|
switch (osuComponent.Component)
|
||||||
{
|
{
|
||||||
case OsuSkinComponents.FollowPoint:
|
case OsuSkinComponents.FollowPoint:
|
||||||
return this.GetAnimation(component.LookupName, true, false, true);
|
return this.GetAnimation(component.LookupName, true, false, true, startAtCurrentTime: false);
|
||||||
|
|
||||||
case OsuSkinComponents.SliderFollowCircle:
|
case OsuSkinComponents.SliderFollowCircle:
|
||||||
var followCircle = this.GetAnimation("sliderfollowcircle", true, true, true);
|
var followCircle = this.GetAnimation("sliderfollowcircle", true, true, true);
|
||||||
|
@ -106,7 +106,7 @@ namespace osu.Game.Tests.Skins
|
|||||||
var decoder = new LegacySkinDecoder();
|
var decoder = new LegacySkinDecoder();
|
||||||
using (var resStream = TestResources.OpenResource("skin-empty.ini"))
|
using (var resStream = TestResources.OpenResource("skin-empty.ini"))
|
||||||
using (var stream = new LineBufferedReader(resStream))
|
using (var stream = new LineBufferedReader(resStream))
|
||||||
Assert.IsNull(decoder.Decode(stream).LegacyVersion);
|
Assert.That(decoder.Decode(stream).LegacyVersion, Is.EqualTo(1.0m));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
// 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.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using NUnit.Framework;
|
using NUnit.Framework;
|
||||||
using osu.Framework.Allocation;
|
using osu.Framework.Allocation;
|
||||||
@ -12,7 +13,10 @@ using osu.Framework.Graphics.Containers;
|
|||||||
using osu.Framework.Graphics.Textures;
|
using osu.Framework.Graphics.Textures;
|
||||||
using osu.Framework.Testing;
|
using osu.Framework.Testing;
|
||||||
using osu.Game.Audio;
|
using osu.Game.Audio;
|
||||||
|
using osu.Game.IO;
|
||||||
|
using osu.Game.Rulesets.Osu;
|
||||||
using osu.Game.Skinning;
|
using osu.Game.Skinning;
|
||||||
|
using osu.Game.Tests.Beatmaps;
|
||||||
using osu.Game.Tests.Visual;
|
using osu.Game.Tests.Visual;
|
||||||
using osuTK.Graphics;
|
using osuTK.Graphics;
|
||||||
|
|
||||||
@ -22,15 +26,15 @@ namespace osu.Game.Tests.Skins
|
|||||||
[HeadlessTest]
|
[HeadlessTest]
|
||||||
public class TestSceneSkinConfigurationLookup : OsuTestScene
|
public class TestSceneSkinConfigurationLookup : OsuTestScene
|
||||||
{
|
{
|
||||||
private SkinSource source1;
|
private UserSkinSource userSource;
|
||||||
private SkinSource source2;
|
private BeatmapSkinSource beatmapSource;
|
||||||
private SkinRequester requester;
|
private SkinRequester requester;
|
||||||
|
|
||||||
[SetUp]
|
[SetUp]
|
||||||
public void SetUp() => Schedule(() =>
|
public void SetUp() => Schedule(() =>
|
||||||
{
|
{
|
||||||
Add(new SkinProvidingContainer(source1 = new SkinSource())
|
Add(new SkinProvidingContainer(userSource = new UserSkinSource())
|
||||||
.WithChild(new SkinProvidingContainer(source2 = new SkinSource())
|
.WithChild(new SkinProvidingContainer(beatmapSource = new BeatmapSkinSource())
|
||||||
.WithChild(requester = new SkinRequester())));
|
.WithChild(requester = new SkinRequester())));
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -39,31 +43,31 @@ namespace osu.Game.Tests.Skins
|
|||||||
{
|
{
|
||||||
AddStep("Add config values", () =>
|
AddStep("Add config values", () =>
|
||||||
{
|
{
|
||||||
source1.Configuration.ConfigDictionary["Lookup"] = "source1";
|
userSource.Configuration.ConfigDictionary["Lookup"] = "user skin";
|
||||||
source2.Configuration.ConfigDictionary["Lookup"] = "source2";
|
beatmapSource.Configuration.ConfigDictionary["Lookup"] = "beatmap skin";
|
||||||
});
|
});
|
||||||
|
|
||||||
AddAssert("Check lookup finds source2", () => requester.GetConfig<string, string>("Lookup")?.Value == "source2");
|
AddAssert("Check lookup finds beatmap skin", () => requester.GetConfig<string, string>("Lookup")?.Value == "beatmap skin");
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
public void TestFloatLookup()
|
public void TestFloatLookup()
|
||||||
{
|
{
|
||||||
AddStep("Add config values", () => source1.Configuration.ConfigDictionary["FloatTest"] = "1.1");
|
AddStep("Add config values", () => userSource.Configuration.ConfigDictionary["FloatTest"] = "1.1");
|
||||||
AddAssert("Check float parse lookup", () => requester.GetConfig<string, float>("FloatTest")?.Value == 1.1f);
|
AddAssert("Check float parse lookup", () => requester.GetConfig<string, float>("FloatTest")?.Value == 1.1f);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
public void TestBoolLookup()
|
public void TestBoolLookup()
|
||||||
{
|
{
|
||||||
AddStep("Add config values", () => source1.Configuration.ConfigDictionary["BoolTest"] = "1");
|
AddStep("Add config values", () => userSource.Configuration.ConfigDictionary["BoolTest"] = "1");
|
||||||
AddAssert("Check bool parse lookup", () => requester.GetConfig<string, bool>("BoolTest")?.Value == true);
|
AddAssert("Check bool parse lookup", () => requester.GetConfig<string, bool>("BoolTest")?.Value == true);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
public void TestEnumLookup()
|
public void TestEnumLookup()
|
||||||
{
|
{
|
||||||
AddStep("Add config values", () => source1.Configuration.ConfigDictionary["Test"] = "Test2");
|
AddStep("Add config values", () => userSource.Configuration.ConfigDictionary["Test"] = "Test2");
|
||||||
AddAssert("Check enum parse lookup", () => requester.GetConfig<LookupType, ValueType>(LookupType.Test)?.Value == ValueType.Test2);
|
AddAssert("Check enum parse lookup", () => requester.GetConfig<LookupType, ValueType>(LookupType.Test)?.Value == ValueType.Test2);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -76,7 +80,7 @@ namespace osu.Game.Tests.Skins
|
|||||||
[Test]
|
[Test]
|
||||||
public void TestLookupNull()
|
public void TestLookupNull()
|
||||||
{
|
{
|
||||||
AddStep("Add config values", () => source1.Configuration.ConfigDictionary["Lookup"] = null);
|
AddStep("Add config values", () => userSource.Configuration.ConfigDictionary["Lookup"] = null);
|
||||||
|
|
||||||
AddAssert("Check lookup null", () =>
|
AddAssert("Check lookup null", () =>
|
||||||
{
|
{
|
||||||
@ -88,7 +92,7 @@ namespace osu.Game.Tests.Skins
|
|||||||
[Test]
|
[Test]
|
||||||
public void TestColourLookup()
|
public void TestColourLookup()
|
||||||
{
|
{
|
||||||
AddStep("Add config colour", () => source1.Configuration.CustomColours["Lookup"] = Color4.Red);
|
AddStep("Add config colour", () => userSource.Configuration.CustomColours["Lookup"] = Color4.Red);
|
||||||
AddAssert("Check colour lookup", () => requester.GetConfig<SkinCustomColourLookup, Color4>(new SkinCustomColourLookup("Lookup"))?.Value == Color4.Red);
|
AddAssert("Check colour lookup", () => requester.GetConfig<SkinCustomColourLookup, Color4>(new SkinCustomColourLookup("Lookup"))?.Value == Color4.Red);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -101,7 +105,7 @@ namespace osu.Game.Tests.Skins
|
|||||||
[Test]
|
[Test]
|
||||||
public void TestWrongColourType()
|
public void TestWrongColourType()
|
||||||
{
|
{
|
||||||
AddStep("Add config colour", () => source1.Configuration.CustomColours["Lookup"] = Color4.Red);
|
AddStep("Add config colour", () => userSource.Configuration.CustomColours["Lookup"] = Color4.Red);
|
||||||
|
|
||||||
AddAssert("perform incorrect lookup", () =>
|
AddAssert("perform incorrect lookup", () =>
|
||||||
{
|
{
|
||||||
@ -127,26 +131,51 @@ namespace osu.Game.Tests.Skins
|
|||||||
[Test]
|
[Test]
|
||||||
public void TestEmptyComboColoursNoFallback()
|
public void TestEmptyComboColoursNoFallback()
|
||||||
{
|
{
|
||||||
AddStep("Add custom combo colours to source1", () => source1.Configuration.AddComboColours(
|
AddStep("Add custom combo colours to user skin", () => userSource.Configuration.AddComboColours(
|
||||||
new Color4(100, 150, 200, 255),
|
new Color4(100, 150, 200, 255),
|
||||||
new Color4(55, 110, 166, 255),
|
new Color4(55, 110, 166, 255),
|
||||||
new Color4(75, 125, 175, 255)
|
new Color4(75, 125, 175, 255)
|
||||||
));
|
));
|
||||||
|
|
||||||
AddStep("Disallow default colours fallback in source2", () => source2.Configuration.AllowDefaultComboColoursFallback = false);
|
AddStep("Disallow default colours fallback in beatmap skin", () => beatmapSource.Configuration.AllowDefaultComboColoursFallback = false);
|
||||||
|
|
||||||
AddAssert("Check retrieved combo colours from source1", () =>
|
AddAssert("Check retrieved combo colours from user skin", () =>
|
||||||
requester.GetConfig<GlobalSkinColours, IReadOnlyList<Color4>>(GlobalSkinColours.ComboColours)?.Value?.SequenceEqual(source1.Configuration.ComboColours) ?? false);
|
requester.GetConfig<GlobalSkinColours, IReadOnlyList<Color4>>(GlobalSkinColours.ComboColours)?.Value?.SequenceEqual(userSource.Configuration.ComboColours) ?? false);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
public void TestLegacyVersionLookup()
|
public void TestNullBeatmapVersionFallsBackToUserSkin()
|
||||||
{
|
{
|
||||||
AddStep("Set source1 version 2.3", () => source1.Configuration.LegacyVersion = 2.3m);
|
AddStep("Set user skin version 2.3", () => userSource.Configuration.LegacyVersion = 2.3m);
|
||||||
AddStep("Set source2 version null", () => source2.Configuration.LegacyVersion = null);
|
AddStep("Set beatmap skin version null", () => beatmapSource.Configuration.LegacyVersion = null);
|
||||||
AddAssert("Check legacy version lookup", () => requester.GetConfig<LegacySkinConfiguration.LegacySetting, decimal>(LegacySkinConfiguration.LegacySetting.Version)?.Value == 2.3m);
|
AddAssert("Check legacy version lookup", () => requester.GetConfig<LegacySkinConfiguration.LegacySetting, decimal>(LegacySkinConfiguration.LegacySetting.Version)?.Value == 2.3m);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void TestSetBeatmapVersionNoFallback()
|
||||||
|
{
|
||||||
|
AddStep("Set user skin version 2.3", () => userSource.Configuration.LegacyVersion = 2.3m);
|
||||||
|
AddStep("Set beatmap skin version null", () => beatmapSource.Configuration.LegacyVersion = 1.7m);
|
||||||
|
AddAssert("Check legacy version lookup", () => requester.GetConfig<LegacySkinConfiguration.LegacySetting, decimal>(LegacySkinConfiguration.LegacySetting.Version)?.Value == 1.7m);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void TestNullBeatmapAndUserVersionFallsBackToLatest()
|
||||||
|
{
|
||||||
|
AddStep("Set user skin version 2.3", () => userSource.Configuration.LegacyVersion = null);
|
||||||
|
AddStep("Set beatmap skin version null", () => beatmapSource.Configuration.LegacyVersion = null);
|
||||||
|
AddAssert("Check legacy version lookup",
|
||||||
|
() => requester.GetConfig<LegacySkinConfiguration.LegacySetting, decimal>(LegacySkinConfiguration.LegacySetting.Version)?.Value == LegacySkinConfiguration.LATEST_VERSION);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void TestIniWithNoVersionFallsBackTo1()
|
||||||
|
{
|
||||||
|
AddStep("Parse skin with no version", () => userSource.Configuration = new LegacySkinDecoder().Decode(new LineBufferedReader(new MemoryStream())));
|
||||||
|
AddStep("Set beatmap skin version null", () => beatmapSource.Configuration.LegacyVersion = null);
|
||||||
|
AddAssert("Check legacy version lookup", () => requester.GetConfig<LegacySkinConfiguration.LegacySetting, decimal>(LegacySkinConfiguration.LegacySetting.Version)?.Value == 1.0m);
|
||||||
|
}
|
||||||
|
|
||||||
public enum LookupType
|
public enum LookupType
|
||||||
{
|
{
|
||||||
Test
|
Test
|
||||||
@ -159,14 +188,22 @@ namespace osu.Game.Tests.Skins
|
|||||||
Test3
|
Test3
|
||||||
}
|
}
|
||||||
|
|
||||||
public class SkinSource : LegacySkin
|
public class UserSkinSource : LegacySkin
|
||||||
{
|
{
|
||||||
public SkinSource()
|
public UserSkinSource()
|
||||||
: base(new SkinInfo(), null, null, string.Empty)
|
: base(new SkinInfo(), null, null, string.Empty)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public class BeatmapSkinSource : LegacyBeatmapSkin
|
||||||
|
{
|
||||||
|
public BeatmapSkinSource()
|
||||||
|
: base(new TestBeatmap(new OsuRuleset().RulesetInfo).BeatmapInfo, null, null)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public class SkinRequester : Drawable, ISkin
|
public class SkinRequester : Drawable, ISkin
|
||||||
{
|
{
|
||||||
private ISkinSource skin;
|
private ISkinSource skin;
|
||||||
|
@ -26,16 +26,8 @@ namespace osu.Game.Tests.Visual.Gameplay
|
|||||||
|
|
||||||
private readonly IReadOnlyList<BreakPeriod> testBreaks = new List<BreakPeriod>
|
private readonly IReadOnlyList<BreakPeriod> testBreaks = new List<BreakPeriod>
|
||||||
{
|
{
|
||||||
new BreakPeriod
|
new BreakPeriod(1000, 5000),
|
||||||
{
|
new BreakPeriod(6000, 13500),
|
||||||
StartTime = 1000,
|
|
||||||
EndTime = 5000,
|
|
||||||
},
|
|
||||||
new BreakPeriod
|
|
||||||
{
|
|
||||||
StartTime = 6000,
|
|
||||||
EndTime = 13500,
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
|
|
||||||
public TestSceneBreakTracker()
|
public TestSceneBreakTracker()
|
||||||
@ -70,7 +62,7 @@ namespace osu.Game.Tests.Visual.Gameplay
|
|||||||
[Test]
|
[Test]
|
||||||
public void TestNoEffectsBreak()
|
public void TestNoEffectsBreak()
|
||||||
{
|
{
|
||||||
var shortBreak = new BreakPeriod { EndTime = 500 };
|
var shortBreak = new BreakPeriod(0, 500);
|
||||||
|
|
||||||
setClock(true);
|
setClock(true);
|
||||||
loadBreaksStep("short break", new[] { shortBreak });
|
loadBreaksStep("short break", new[] { shortBreak });
|
||||||
@ -127,13 +119,12 @@ namespace osu.Game.Tests.Visual.Gameplay
|
|||||||
|
|
||||||
private void addShowBreakStep(double seconds)
|
private void addShowBreakStep(double seconds)
|
||||||
{
|
{
|
||||||
AddStep($"show '{seconds}s' break", () => breakOverlay.Breaks = breakTracker.Breaks = new List<BreakPeriod>
|
AddStep($"show '{seconds}s' break", () =>
|
||||||
{
|
{
|
||||||
new BreakPeriod
|
breakOverlay.Breaks = breakTracker.Breaks = new List<BreakPeriod>
|
||||||
{
|
{
|
||||||
StartTime = Clock.CurrentTime,
|
new BreakPeriod(Clock.CurrentTime, Clock.CurrentTime + seconds * 1000)
|
||||||
EndTime = Clock.CurrentTime + seconds * 1000,
|
};
|
||||||
}
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -70,7 +70,7 @@ namespace osu.Game.Tests.Visual.UserInterface
|
|||||||
Anchor = Anchor.TopRight,
|
Anchor = Anchor.TopRight,
|
||||||
Origin = Anchor.TopRight,
|
Origin = Anchor.TopRight,
|
||||||
AutoSizeAxes = Axes.Both,
|
AutoSizeAxes = Axes.Both,
|
||||||
Position = new Vector2(0, 25),
|
Position = new Vector2(-5, 25),
|
||||||
Current = { BindTarget = modSelect.SelectedMods }
|
Current = { BindTarget = modSelect.SelectedMods }
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -305,12 +305,9 @@ namespace osu.Game.Beatmaps.Formats
|
|||||||
|
|
||||||
case LegacyEventType.Break:
|
case LegacyEventType.Break:
|
||||||
double start = getOffsetTime(Parsing.ParseDouble(split[1]));
|
double start = getOffsetTime(Parsing.ParseDouble(split[1]));
|
||||||
|
double end = Math.Max(start, getOffsetTime(Parsing.ParseDouble(split[2])));
|
||||||
|
|
||||||
var breakEvent = new BreakPeriod
|
var breakEvent = new BreakPeriod(start, end);
|
||||||
{
|
|
||||||
StartTime = start,
|
|
||||||
EndTime = Math.Max(start, getOffsetTime(Parsing.ParseDouble(split[2])))
|
|
||||||
};
|
|
||||||
|
|
||||||
if (!breakEvent.HasEffect)
|
if (!breakEvent.HasEffect)
|
||||||
return;
|
return;
|
||||||
|
@ -32,6 +32,17 @@ namespace osu.Game.Beatmaps.Timing
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public bool HasEffect => Duration >= MIN_BREAK_DURATION;
|
public bool HasEffect => Duration >= MIN_BREAK_DURATION;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Constructs a new break period.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="startTime">The start time of the break period.</param>
|
||||||
|
/// <param name="endTime">The end time of the break period.</param>
|
||||||
|
public BreakPeriod(double startTime, double endTime)
|
||||||
|
{
|
||||||
|
StartTime = startTime;
|
||||||
|
EndTime = endTime;
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Whether this break contains a specified time.
|
/// Whether this break contains a specified time.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -161,7 +161,7 @@ namespace osu.Game.Screens.Multi
|
|||||||
{
|
{
|
||||||
AutoSizeAxes = Axes.Both,
|
AutoSizeAxes = Axes.Both,
|
||||||
Direction = FillDirection.Horizontal,
|
Direction = FillDirection.Horizontal,
|
||||||
Spacing = new Vector2(10, 0),
|
Spacing = new Vector2(15, 0),
|
||||||
Children = new Drawable[]
|
Children = new Drawable[]
|
||||||
{
|
{
|
||||||
authorText = new LinkFlowContainer { AutoSizeAxes = Axes.Both },
|
authorText = new LinkFlowContainer { AutoSizeAxes = Axes.Both },
|
||||||
|
@ -41,7 +41,7 @@ namespace osu.Game.Screens.Play.HUD
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected readonly FillFlowContainer<ModIcon> IconsContainer;
|
private readonly FillFlowContainer<ModIcon> iconsContainer;
|
||||||
private readonly OsuSpriteText unrankedText;
|
private readonly OsuSpriteText unrankedText;
|
||||||
|
|
||||||
public ModDisplay()
|
public ModDisplay()
|
||||||
@ -50,13 +50,12 @@ namespace osu.Game.Screens.Play.HUD
|
|||||||
|
|
||||||
Children = new Drawable[]
|
Children = new Drawable[]
|
||||||
{
|
{
|
||||||
IconsContainer = new ReverseChildIDFillFlowContainer<ModIcon>
|
iconsContainer = new ReverseChildIDFillFlowContainer<ModIcon>
|
||||||
{
|
{
|
||||||
Anchor = Anchor.TopCentre,
|
Anchor = Anchor.TopCentre,
|
||||||
Origin = Anchor.TopCentre,
|
Origin = Anchor.TopCentre,
|
||||||
AutoSizeAxes = Axes.Both,
|
AutoSizeAxes = Axes.Both,
|
||||||
Direction = FillDirection.Horizontal,
|
Direction = FillDirection.Horizontal,
|
||||||
Margin = new MarginPadding { Left = 10, Right = 10 },
|
|
||||||
},
|
},
|
||||||
unrankedText = new OsuSpriteText
|
unrankedText = new OsuSpriteText
|
||||||
{
|
{
|
||||||
@ -69,11 +68,11 @@ namespace osu.Game.Screens.Play.HUD
|
|||||||
|
|
||||||
Current.ValueChanged += mods =>
|
Current.ValueChanged += mods =>
|
||||||
{
|
{
|
||||||
IconsContainer.Clear();
|
iconsContainer.Clear();
|
||||||
|
|
||||||
foreach (Mod mod in mods.NewValue)
|
foreach (Mod mod in mods.NewValue)
|
||||||
{
|
{
|
||||||
IconsContainer.Add(new ModIcon(mod) { Scale = new Vector2(0.6f) });
|
iconsContainer.Add(new ModIcon(mod) { Scale = new Vector2(0.6f) });
|
||||||
}
|
}
|
||||||
|
|
||||||
if (IsLoaded)
|
if (IsLoaded)
|
||||||
@ -92,7 +91,7 @@ namespace osu.Game.Screens.Play.HUD
|
|||||||
base.LoadComplete();
|
base.LoadComplete();
|
||||||
|
|
||||||
appearTransform();
|
appearTransform();
|
||||||
IconsContainer.FadeInFromZero(fade_duration, Easing.OutQuint);
|
iconsContainer.FadeInFromZero(fade_duration, Easing.OutQuint);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void appearTransform()
|
private void appearTransform()
|
||||||
@ -104,20 +103,20 @@ namespace osu.Game.Screens.Play.HUD
|
|||||||
|
|
||||||
expand();
|
expand();
|
||||||
|
|
||||||
using (IconsContainer.BeginDelayedSequence(1200))
|
using (iconsContainer.BeginDelayedSequence(1200))
|
||||||
contract();
|
contract();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void expand()
|
private void expand()
|
||||||
{
|
{
|
||||||
if (ExpansionMode != ExpansionMode.AlwaysContracted)
|
if (ExpansionMode != ExpansionMode.AlwaysContracted)
|
||||||
IconsContainer.TransformSpacingTo(new Vector2(5, 0), 500, Easing.OutQuint);
|
iconsContainer.TransformSpacingTo(new Vector2(5, 0), 500, Easing.OutQuint);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void contract()
|
private void contract()
|
||||||
{
|
{
|
||||||
if (ExpansionMode != ExpansionMode.AlwaysExpanded)
|
if (ExpansionMode != ExpansionMode.AlwaysExpanded)
|
||||||
IconsContainer.TransformSpacingTo(new Vector2(-25, 0), 500, Easing.OutQuint);
|
iconsContainer.TransformSpacingTo(new Vector2(-25, 0), 500, Easing.OutQuint);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override bool OnHover(HoverEvent e)
|
protected override bool OnHover(HoverEvent e)
|
||||||
|
@ -285,7 +285,7 @@ namespace osu.Game.Screens.Play
|
|||||||
Anchor = Anchor.TopRight,
|
Anchor = Anchor.TopRight,
|
||||||
Origin = Anchor.TopRight,
|
Origin = Anchor.TopRight,
|
||||||
AutoSizeAxes = Axes.Both,
|
AutoSizeAxes = Axes.Both,
|
||||||
Margin = new MarginPadding { Top = 20, Right = 10 },
|
Margin = new MarginPadding { Top = 20, Right = 20 },
|
||||||
};
|
};
|
||||||
|
|
||||||
protected virtual HitErrorDisplay CreateHitErrorDisplayOverlay() => new HitErrorDisplay(scoreProcessor, drawableRuleset?.FirstAvailableHitWindows);
|
protected virtual HitErrorDisplay CreateHitErrorDisplayOverlay() => new HitErrorDisplay(scoreProcessor, drawableRuleset?.FirstAvailableHitWindows);
|
||||||
|
@ -30,6 +30,9 @@ namespace osu.Game.Screens.Ranking.Expanded
|
|||||||
private readonly ScoreInfo score;
|
private readonly ScoreInfo score;
|
||||||
|
|
||||||
private readonly List<StatisticDisplay> statisticDisplays = new List<StatisticDisplay>();
|
private readonly List<StatisticDisplay> statisticDisplays = new List<StatisticDisplay>();
|
||||||
|
|
||||||
|
private FillFlowContainer starAndModDisplay;
|
||||||
|
|
||||||
private RollingCounter<long> scoreCounter;
|
private RollingCounter<long> scoreCounter;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -119,11 +122,12 @@ namespace osu.Game.Screens.Ranking.Expanded
|
|||||||
Alpha = 0,
|
Alpha = 0,
|
||||||
AlwaysPresent = true
|
AlwaysPresent = true
|
||||||
},
|
},
|
||||||
new FillFlowContainer
|
starAndModDisplay = new FillFlowContainer
|
||||||
{
|
{
|
||||||
Anchor = Anchor.TopCentre,
|
Anchor = Anchor.TopCentre,
|
||||||
Origin = Anchor.TopCentre,
|
Origin = Anchor.TopCentre,
|
||||||
AutoSizeAxes = Axes.Both,
|
AutoSizeAxes = Axes.Both,
|
||||||
|
Spacing = new Vector2(5, 0),
|
||||||
Children = new Drawable[]
|
Children = new Drawable[]
|
||||||
{
|
{
|
||||||
new StarRatingDisplay(beatmap)
|
new StarRatingDisplay(beatmap)
|
||||||
@ -131,15 +135,6 @@ namespace osu.Game.Screens.Ranking.Expanded
|
|||||||
Anchor = Anchor.CentreLeft,
|
Anchor = Anchor.CentreLeft,
|
||||||
Origin = Anchor.CentreLeft
|
Origin = Anchor.CentreLeft
|
||||||
},
|
},
|
||||||
new ModDisplay
|
|
||||||
{
|
|
||||||
Anchor = Anchor.CentreLeft,
|
|
||||||
Origin = Anchor.CentreLeft,
|
|
||||||
DisplayUnrankedText = false,
|
|
||||||
ExpansionMode = ExpansionMode.AlwaysExpanded,
|
|
||||||
Scale = new Vector2(0.5f),
|
|
||||||
Current = { Value = score.Mods }
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
new FillFlowContainer
|
new FillFlowContainer
|
||||||
@ -214,6 +209,19 @@ namespace osu.Game.Screens.Ranking.Expanded
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
if (score.Mods.Any())
|
||||||
|
{
|
||||||
|
starAndModDisplay.Add(new ModDisplay
|
||||||
|
{
|
||||||
|
Anchor = Anchor.CentreLeft,
|
||||||
|
Origin = Anchor.CentreLeft,
|
||||||
|
DisplayUnrankedText = false,
|
||||||
|
ExpansionMode = ExpansionMode.AlwaysExpanded,
|
||||||
|
Scale = new Vector2(0.5f),
|
||||||
|
Current = { Value = score.Mods }
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void LoadComplete()
|
protected override void LoadComplete()
|
||||||
|
@ -27,18 +27,19 @@ namespace osu.Game.Screens.Select
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected readonly OsuSpriteText MultiplierText;
|
protected readonly OsuSpriteText MultiplierText;
|
||||||
private readonly FooterModDisplay modDisplay;
|
private readonly ModDisplay modDisplay;
|
||||||
private Color4 lowMultiplierColour;
|
private Color4 lowMultiplierColour;
|
||||||
private Color4 highMultiplierColour;
|
private Color4 highMultiplierColour;
|
||||||
|
|
||||||
public FooterButtonMods()
|
public FooterButtonMods()
|
||||||
{
|
{
|
||||||
ButtonContentContainer.Add(modDisplay = new FooterModDisplay
|
ButtonContentContainer.Add(modDisplay = new ModDisplay
|
||||||
{
|
{
|
||||||
Anchor = Anchor.Centre,
|
Anchor = Anchor.Centre,
|
||||||
Origin = Anchor.Centre,
|
Origin = Anchor.Centre,
|
||||||
DisplayUnrankedText = false,
|
DisplayUnrankedText = false,
|
||||||
Scale = new Vector2(0.8f)
|
Scale = new Vector2(0.8f),
|
||||||
|
ExpansionMode = ExpansionMode.AlwaysContracted,
|
||||||
});
|
});
|
||||||
ButtonContentContainer.Add(MultiplierText = new OsuSpriteText
|
ButtonContentContainer.Add(MultiplierText = new OsuSpriteText
|
||||||
{
|
{
|
||||||
@ -84,16 +85,5 @@ namespace osu.Game.Screens.Select
|
|||||||
else
|
else
|
||||||
modDisplay.FadeOut();
|
modDisplay.FadeOut();
|
||||||
}
|
}
|
||||||
|
|
||||||
private class FooterModDisplay : ModDisplay
|
|
||||||
{
|
|
||||||
public override bool ReceivePositionalInputAt(Vector2 screenSpacePos) => Parent?.Parent?.ReceivePositionalInputAt(screenSpacePos) ?? false;
|
|
||||||
|
|
||||||
public FooterModDisplay()
|
|
||||||
{
|
|
||||||
ExpansionMode = ExpansionMode.AlwaysContracted;
|
|
||||||
IconsContainer.Margin = new MarginPadding();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
// 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.Bindables;
|
||||||
using osu.Framework.IO.Stores;
|
using osu.Framework.IO.Stores;
|
||||||
using osu.Game.Beatmaps;
|
using osu.Game.Beatmaps;
|
||||||
|
|
||||||
@ -18,6 +19,20 @@ namespace osu.Game.Skinning
|
|||||||
Configuration.AllowDefaultComboColoursFallback = false;
|
Configuration.AllowDefaultComboColoursFallback = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override IBindable<TValue> GetConfig<TLookup, TValue>(TLookup lookup)
|
||||||
|
{
|
||||||
|
switch (lookup)
|
||||||
|
{
|
||||||
|
case LegacySkinConfiguration.LegacySetting s when s == LegacySkinConfiguration.LegacySetting.Version:
|
||||||
|
if (Configuration.LegacyVersion is decimal version)
|
||||||
|
return SkinUtils.As<TValue>(new Bindable<decimal>(version));
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return base.GetConfig<TLookup, TValue>(lookup);
|
||||||
|
}
|
||||||
|
|
||||||
private static SkinInfo createSkinInfo(BeatmapInfo beatmap) =>
|
private static SkinInfo createSkinInfo(BeatmapInfo beatmap) =>
|
||||||
new SkinInfo { Name = beatmap.ToString(), Creator = beatmap.Metadata.Author.ToString() };
|
new SkinInfo { Name = beatmap.ToString(), Creator = beatmap.Metadata.Author.ToString() };
|
||||||
}
|
}
|
||||||
|
@ -3,6 +3,7 @@
|
|||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
using osu.Game.Beatmaps.Formats;
|
using osu.Game.Beatmaps.Formats;
|
||||||
using osuTK.Graphics;
|
using osuTK.Graphics;
|
||||||
|
|
||||||
@ -45,5 +46,13 @@ namespace osu.Game.Skinning
|
|||||||
ColumnLineWidth.AsSpan().Fill(2);
|
ColumnLineWidth.AsSpan().Fill(2);
|
||||||
ColumnWidth.AsSpan().Fill(DEFAULT_COLUMN_SIZE);
|
ColumnWidth.AsSpan().Fill(DEFAULT_COLUMN_SIZE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private float? minimumColumnWidth;
|
||||||
|
|
||||||
|
public float MinimumColumnWidth
|
||||||
|
{
|
||||||
|
get => minimumColumnWidth ?? ColumnWidth.Min();
|
||||||
|
set => minimumColumnWidth = value;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -36,6 +36,7 @@ namespace osu.Game.Skinning
|
|||||||
HoldNoteBodyImage,
|
HoldNoteBodyImage,
|
||||||
ExplosionImage,
|
ExplosionImage,
|
||||||
ExplosionScale,
|
ExplosionScale,
|
||||||
ColumnLineColour
|
ColumnLineColour,
|
||||||
|
MinimumColumnWidth
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -106,8 +106,14 @@ namespace osu.Game.Skinning
|
|||||||
case "LightingNWidth":
|
case "LightingNWidth":
|
||||||
parseArrayValue(pair.Value, currentConfig.ExplosionWidth);
|
parseArrayValue(pair.Value, currentConfig.ExplosionWidth);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case "WidthForNoteHeightScale":
|
||||||
|
currentConfig.MinimumColumnWidth = float.Parse(pair.Value, CultureInfo.InvariantCulture) * LegacyManiaSkinConfiguration.POSITION_SCALE_FACTOR;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pendingLines.Clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void parseArrayValue(string value, float[] output)
|
private void parseArrayValue(string value, float[] output)
|
||||||
|
@ -71,7 +71,7 @@ namespace osu.Game.Skinning
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
Configuration = new LegacySkinConfiguration { LegacyVersion = LegacySkinConfiguration.LATEST_VERSION };
|
Configuration = new LegacySkinConfiguration();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (storage != null)
|
if (storage != null)
|
||||||
@ -122,10 +122,7 @@ namespace osu.Game.Skinning
|
|||||||
switch (legacy)
|
switch (legacy)
|
||||||
{
|
{
|
||||||
case LegacySkinConfiguration.LegacySetting.Version:
|
case LegacySkinConfiguration.LegacySetting.Version:
|
||||||
if (Configuration.LegacyVersion is decimal version)
|
return SkinUtils.As<TValue>(new Bindable<decimal>(Configuration.LegacyVersion ?? LegacySkinConfiguration.LATEST_VERSION));
|
||||||
return SkinUtils.As<TValue>(new Bindable<decimal>(version));
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
@ -207,6 +204,9 @@ namespace osu.Game.Skinning
|
|||||||
|
|
||||||
case LegacyManiaSkinConfigurationLookups.ColumnLineColour:
|
case LegacyManiaSkinConfigurationLookups.ColumnLineColour:
|
||||||
return SkinUtils.As<TValue>(getCustomColour(existing, "ColourColumnLine"));
|
return SkinUtils.As<TValue>(getCustomColour(existing, "ColourColumnLine"));
|
||||||
|
|
||||||
|
case LegacyManiaSkinConfigurationLookups.MinimumColumnWidth:
|
||||||
|
return SkinUtils.As<TValue>(new Bindable<float>(existing.MinimumColumnWidth));
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
|
@ -52,5 +52,12 @@ namespace osu.Game.Skinning
|
|||||||
|
|
||||||
base.ParseLine(skin, section, line);
|
base.ParseLine(skin, section, line);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected override LegacySkinConfiguration CreateTemplateObject()
|
||||||
|
{
|
||||||
|
var config = base.CreateTemplateObject();
|
||||||
|
config.LegacyVersion = 1.0m;
|
||||||
|
return config;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -14,7 +14,7 @@ namespace osu.Game.Skinning
|
|||||||
public static class LegacySkinExtensions
|
public static class LegacySkinExtensions
|
||||||
{
|
{
|
||||||
public static Drawable GetAnimation(this ISkin source, string componentName, bool animatable, bool looping, bool applyConfigFrameRate = false, string animationSeparator = "-",
|
public static Drawable GetAnimation(this ISkin source, string componentName, bool animatable, bool looping, bool applyConfigFrameRate = false, string animationSeparator = "-",
|
||||||
bool startAtCurrentTime = false, double? frameLength = null)
|
bool startAtCurrentTime = true, double? frameLength = null)
|
||||||
{
|
{
|
||||||
Texture texture;
|
Texture texture;
|
||||||
|
|
||||||
@ -72,7 +72,7 @@ namespace osu.Game.Skinning
|
|||||||
if (timeReference != null)
|
if (timeReference != null)
|
||||||
{
|
{
|
||||||
Clock = timeReference.Clock;
|
Clock = timeReference.Clock;
|
||||||
PlaybackPosition = timeReference.AnimationStartTime - timeReference.Clock.CurrentTime;
|
PlaybackPosition = timeReference.Clock.CurrentTime - timeReference.AnimationStartTime;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -46,7 +46,6 @@ namespace osu.Game.Storyboards.Drawables
|
|||||||
Anchor = Anchor.Centre,
|
Anchor = Anchor.Centre,
|
||||||
Origin = Anchor.Centre,
|
Origin = Anchor.Centre,
|
||||||
Alpha = 0,
|
Alpha = 0,
|
||||||
PlaybackPosition = Video.StartTime
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -56,6 +55,8 @@ namespace osu.Game.Storyboards.Drawables
|
|||||||
|
|
||||||
if (video == null) return;
|
if (video == null) return;
|
||||||
|
|
||||||
|
video.PlaybackPosition = Clock.CurrentTime - Video.StartTime;
|
||||||
|
|
||||||
using (video.BeginAbsoluteSequence(0))
|
using (video.BeginAbsoluteSequence(0))
|
||||||
video.FadeIn(500);
|
video.FadeIn(500);
|
||||||
}
|
}
|
||||||
|
@ -34,7 +34,7 @@ namespace osu.Game.Tests.Visual
|
|||||||
[BackgroundDependencyLoader]
|
[BackgroundDependencyLoader]
|
||||||
private void load(AudioManager audio, SkinManager skinManager)
|
private void load(AudioManager audio, SkinManager skinManager)
|
||||||
{
|
{
|
||||||
var dllStore = new DllResourceStore(GetType().Assembly);
|
var dllStore = new DllResourceStore(DynamicCompilationOriginal.GetType().Assembly);
|
||||||
|
|
||||||
metricsSkin = new TestLegacySkin(new SkinInfo { Name = "metrics-skin" }, new NamespacedResourceStore<byte[]>(dllStore, "Resources/metrics_skin"), audio, true);
|
metricsSkin = new TestLegacySkin(new SkinInfo { Name = "metrics-skin" }, new NamespacedResourceStore<byte[]>(dllStore, "Resources/metrics_skin"), audio, true);
|
||||||
defaultSkin = skinManager.GetSkin(DefaultLegacySkin.Info);
|
defaultSkin = skinManager.GetSkin(DefaultLegacySkin.Info);
|
||||||
|
@ -22,10 +22,10 @@
|
|||||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="2.2.6" />
|
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="2.2.6" />
|
||||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite.Core" Version="2.2.6" />
|
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite.Core" Version="2.2.6" />
|
||||||
<PackageReference Include="Newtonsoft.Json" Version="12.0.3" />
|
<PackageReference Include="Newtonsoft.Json" Version="12.0.3" />
|
||||||
<PackageReference Include="ppy.osu.Framework" Version="2020.403.0" />
|
<PackageReference Include="ppy.osu.Framework" Version="2020.407.1" />
|
||||||
<PackageReference Include="ppy.osu.Game.Resources" Version="2020.403.0" />
|
<PackageReference Include="ppy.osu.Game.Resources" Version="2020.403.0" />
|
||||||
<PackageReference Include="Sentry" Version="2.1.1" />
|
<PackageReference Include="Sentry" Version="2.1.1" />
|
||||||
<PackageReference Include="SharpCompress" Version="0.24.0" />
|
<PackageReference Include="SharpCompress" Version="0.25.0" />
|
||||||
<PackageReference Include="NUnit" Version="3.12.0" />
|
<PackageReference Include="NUnit" Version="3.12.0" />
|
||||||
<PackageReference Include="System.ComponentModel.Annotations" Version="4.7.0" />
|
<PackageReference Include="System.ComponentModel.Annotations" Version="4.7.0" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
@ -70,7 +70,7 @@
|
|||||||
<Reference Include="System.Net.Http" />
|
<Reference Include="System.Net.Http" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup Label="Package References">
|
<ItemGroup Label="Package References">
|
||||||
<PackageReference Include="ppy.osu.Framework.iOS" Version="2020.403.0" />
|
<PackageReference Include="ppy.osu.Framework.iOS" Version="2020.407.1" />
|
||||||
<PackageReference Include="ppy.osu.Game.Resources" Version="2020.403.0" />
|
<PackageReference Include="ppy.osu.Game.Resources" Version="2020.403.0" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<!-- Xamarin.iOS does not automatically handle transitive dependencies from NuGet packages. -->
|
<!-- Xamarin.iOS does not automatically handle transitive dependencies from NuGet packages. -->
|
||||||
@ -79,8 +79,8 @@
|
|||||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="2.2.6" />
|
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="2.2.6" />
|
||||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite.Core" Version="2.2.6" />
|
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite.Core" Version="2.2.6" />
|
||||||
<PackageReference Include="Newtonsoft.Json" Version="12.0.3" />
|
<PackageReference Include="Newtonsoft.Json" Version="12.0.3" />
|
||||||
<PackageReference Include="ppy.osu.Framework" Version="2020.403.0" />
|
<PackageReference Include="ppy.osu.Framework" Version="2020.407.1" />
|
||||||
<PackageReference Include="SharpCompress" Version="0.24.0" />
|
<PackageReference Include="SharpCompress" Version="0.25.0" />
|
||||||
<PackageReference Include="NUnit" Version="3.12.0" />
|
<PackageReference Include="NUnit" Version="3.12.0" />
|
||||||
<PackageReference Include="SharpRaven" Version="2.4.0" />
|
<PackageReference Include="SharpRaven" Version="2.4.0" />
|
||||||
<PackageReference Include="System.ComponentModel.Annotations" Version="4.7.0" />
|
<PackageReference Include="System.ComponentModel.Annotations" Version="4.7.0" />
|
||||||
|
Loading…
Reference in New Issue
Block a user