mirror of
https://github.com/ppy/osu
synced 2024-12-29 02:12:43 +00:00
Merge branch 'master' into comment-mapper-pill
This commit is contained in:
commit
3f46e1afc3
@ -1,111 +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.
|
||||
|
||||
#nullable disable
|
||||
|
||||
using System.Linq;
|
||||
using NUnit.Framework;
|
||||
using osu.Framework.Bindables;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Testing;
|
||||
using osu.Framework.Utils;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Beatmaps.ControlPoints;
|
||||
using osu.Game.Rulesets.Catch.Judgements;
|
||||
using osu.Game.Rulesets.Catch.Objects;
|
||||
using osu.Game.Rulesets.Catch.Objects.Drawables;
|
||||
using osu.Game.Rulesets.Catch.Skinning;
|
||||
using osu.Game.Rulesets.Catch.UI;
|
||||
using osu.Game.Skinning;
|
||||
using osu.Game.Tests.Visual;
|
||||
using Direction = osu.Game.Rulesets.Catch.UI.Direction;
|
||||
|
||||
namespace osu.Game.Rulesets.Catch.Tests
|
||||
{
|
||||
public partial class TestSceneCatchSkinConfiguration : OsuTestScene
|
||||
{
|
||||
private Catcher catcher;
|
||||
|
||||
private readonly Container container;
|
||||
|
||||
public TestSceneCatchSkinConfiguration()
|
||||
{
|
||||
Add(container = new Container { RelativeSizeAxes = Axes.Both });
|
||||
}
|
||||
|
||||
[TestCase(false)]
|
||||
[TestCase(true)]
|
||||
public void TestCatcherPlateFlipping(bool flip)
|
||||
{
|
||||
AddStep("setup catcher", () =>
|
||||
{
|
||||
var skin = new TestSkin { FlipCatcherPlate = flip };
|
||||
container.Child = new SkinProvidingContainer(skin)
|
||||
{
|
||||
Child = catcher = new Catcher(new DroppedObjectContainer())
|
||||
{
|
||||
Anchor = Anchor.Centre
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
Fruit fruit = new Fruit();
|
||||
|
||||
AddStep("catch fruit", () => catchFruit(fruit, 20));
|
||||
|
||||
float position = 0;
|
||||
|
||||
AddStep("record fruit position", () => position = getCaughtObjectPosition(fruit));
|
||||
|
||||
AddStep("face left", () => catcher.VisualDirection = Direction.Left);
|
||||
|
||||
if (flip)
|
||||
AddAssert("fruit position changed", () => !Precision.AlmostEquals(getCaughtObjectPosition(fruit), position));
|
||||
else
|
||||
AddAssert("fruit position unchanged", () => Precision.AlmostEquals(getCaughtObjectPosition(fruit), position));
|
||||
|
||||
AddStep("face right", () => catcher.VisualDirection = Direction.Right);
|
||||
|
||||
AddAssert("fruit position restored", () => Precision.AlmostEquals(getCaughtObjectPosition(fruit), position));
|
||||
}
|
||||
|
||||
private float getCaughtObjectPosition(Fruit fruit)
|
||||
{
|
||||
var caughtObject = catcher.ChildrenOfType<CaughtObject>().Single(c => c.HitObject == fruit);
|
||||
return caughtObject.Parent!.ToSpaceOfOtherDrawable(caughtObject.Position, catcher).X;
|
||||
}
|
||||
|
||||
private void catchFruit(Fruit fruit, float x)
|
||||
{
|
||||
fruit.ApplyDefaults(new ControlPointInfo(), new BeatmapDifficulty());
|
||||
var drawableFruit = new DrawableFruit(fruit) { X = x };
|
||||
var judgement = fruit.CreateJudgement();
|
||||
catcher.OnNewResult(drawableFruit, new CatchJudgementResult(fruit, judgement)
|
||||
{
|
||||
Type = judgement.MaxResult
|
||||
});
|
||||
}
|
||||
|
||||
private class TestSkin : TrianglesSkin
|
||||
{
|
||||
public bool FlipCatcherPlate { get; set; }
|
||||
|
||||
public TestSkin()
|
||||
: base(null!)
|
||||
{
|
||||
}
|
||||
|
||||
public override IBindable<TValue> GetConfig<TLookup, TValue>(TLookup lookup)
|
||||
{
|
||||
if (lookup is CatchSkinConfiguration config)
|
||||
{
|
||||
if (config == CatchSkinConfiguration.FlipCatcherPlate)
|
||||
return SkinUtils.As<TValue>(new Bindable<bool>(FlipCatcherPlate));
|
||||
}
|
||||
|
||||
return base.GetConfig<TLookup, TValue>(lookup);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,13 +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.
|
||||
|
||||
namespace osu.Game.Rulesets.Catch.Skinning
|
||||
{
|
||||
public enum CatchSkinConfiguration
|
||||
{
|
||||
/// <summary>
|
||||
/// Whether the contents of the catcher plate should be visually flipped when the catcher direction is changed.
|
||||
/// </summary>
|
||||
FlipCatcherPlate
|
||||
}
|
||||
}
|
@ -122,19 +122,6 @@ namespace osu.Game.Rulesets.Catch.Skinning.Legacy
|
||||
|
||||
result.Value = LegacyColourCompatibility.DisallowZeroAlpha(result.Value);
|
||||
return (IBindable<TValue>)result;
|
||||
|
||||
case CatchSkinConfiguration config:
|
||||
switch (config)
|
||||
{
|
||||
case CatchSkinConfiguration.FlipCatcherPlate:
|
||||
// Don't flip catcher plate contents if the catcher is provided by this legacy skin.
|
||||
if (GetDrawableComponent(new CatchSkinComponentLookup(CatchSkinComponents.Catcher)) != null)
|
||||
return (IBindable<TValue>)new Bindable<bool>();
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
return base.GetConfig<TLookup, TValue>(lookup);
|
||||
|
@ -112,11 +112,6 @@ namespace osu.Game.Rulesets.Catch.UI
|
||||
|
||||
public Vector2 BodyScale => Scale * body.Scale;
|
||||
|
||||
/// <summary>
|
||||
/// Whether the contents of the catcher plate should be visually flipped when the catcher direction is changed.
|
||||
/// </summary>
|
||||
private bool flipCatcherPlate;
|
||||
|
||||
/// <summary>
|
||||
/// Width of the area that can be used to attempt catches during gameplay.
|
||||
/// </summary>
|
||||
@ -339,8 +334,6 @@ namespace osu.Game.Rulesets.Catch.UI
|
||||
skin.GetConfig<CatchSkinColour, Color4>(CatchSkinColour.HyperDash)?.Value ??
|
||||
DEFAULT_HYPER_DASH_COLOUR;
|
||||
|
||||
flipCatcherPlate = skin.GetConfig<CatchSkinConfiguration, bool>(CatchSkinConfiguration.FlipCatcherPlate)?.Value ?? true;
|
||||
|
||||
runHyperDashStateTransition(HyperDashing);
|
||||
}
|
||||
|
||||
@ -352,8 +345,7 @@ namespace osu.Game.Rulesets.Catch.UI
|
||||
|
||||
body.Scale = scaleFromDirection;
|
||||
// Inverse of catcher scale is applied here, as catcher gets scaled by circle size and so do the incoming fruit.
|
||||
caughtObjectContainer.Scale = (1 / Scale.X) * (flipCatcherPlate ? scaleFromDirection : Vector2.One);
|
||||
hitExplosionContainer.Scale = flipCatcherPlate ? scaleFromDirection : Vector2.One;
|
||||
caughtObjectContainer.Scale = new Vector2(1 / Scale.X);
|
||||
|
||||
// Correct overshooting.
|
||||
if ((hyperDashDirection > 0 && hyperDashTargetPosition < X) ||
|
||||
|
@ -1,4 +1,4 @@
|
||||
// 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.
|
||||
|
||||
using System;
|
||||
@ -38,12 +38,18 @@ namespace osu.Game.Rulesets.Osu.Mods
|
||||
private ReplayState<OsuAction> state = null!;
|
||||
private double lastStateChangeTime;
|
||||
|
||||
private DrawableOsuRuleset ruleset = null!;
|
||||
private IPressHandler pressHandler = null!;
|
||||
|
||||
private bool hasReplay;
|
||||
private bool legacyReplay;
|
||||
|
||||
public void ApplyToDrawableRuleset(DrawableRuleset<OsuHitObject> drawableRuleset)
|
||||
{
|
||||
ruleset = (DrawableOsuRuleset)drawableRuleset;
|
||||
|
||||
// grab the input manager for future use.
|
||||
osuInputManager = ((DrawableOsuRuleset)drawableRuleset).KeyBindingInputManager;
|
||||
osuInputManager = ruleset.KeyBindingInputManager;
|
||||
}
|
||||
|
||||
public void ApplyToPlayer(Player player)
|
||||
@ -51,15 +57,22 @@ namespace osu.Game.Rulesets.Osu.Mods
|
||||
if (osuInputManager.ReplayInputHandler != null)
|
||||
{
|
||||
hasReplay = true;
|
||||
|
||||
Debug.Assert(ruleset.ReplayScore != null);
|
||||
legacyReplay = ruleset.ReplayScore.ScoreInfo.IsLegacyScore;
|
||||
|
||||
pressHandler = legacyReplay ? new LegacyReplayPressHandler(this) : new PressHandler(this);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
pressHandler = new PressHandler(this);
|
||||
osuInputManager.AllowGameplayInputs = false;
|
||||
}
|
||||
|
||||
public void Update(Playfield playfield)
|
||||
{
|
||||
if (hasReplay)
|
||||
if (hasReplay && !legacyReplay)
|
||||
return;
|
||||
|
||||
bool requiresHold = false;
|
||||
@ -132,11 +145,62 @@ namespace osu.Game.Rulesets.Osu.Mods
|
||||
|
||||
if (down)
|
||||
{
|
||||
state.PressedActions.Add(wasLeft ? OsuAction.LeftButton : OsuAction.RightButton);
|
||||
pressHandler.HandlePress(wasLeft);
|
||||
wasLeft = !wasLeft;
|
||||
}
|
||||
else
|
||||
{
|
||||
pressHandler.HandleRelease(wasLeft);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
state.Apply(osuInputManager.CurrentState, osuInputManager);
|
||||
private interface IPressHandler
|
||||
{
|
||||
void HandlePress(bool wasLeft);
|
||||
void HandleRelease(bool wasLeft);
|
||||
}
|
||||
|
||||
private class PressHandler : IPressHandler
|
||||
{
|
||||
private readonly OsuModRelax mod;
|
||||
|
||||
public PressHandler(OsuModRelax mod)
|
||||
{
|
||||
this.mod = mod;
|
||||
}
|
||||
|
||||
public void HandlePress(bool wasLeft)
|
||||
{
|
||||
mod.state.PressedActions.Add(wasLeft ? OsuAction.LeftButton : OsuAction.RightButton);
|
||||
mod.state.Apply(mod.osuInputManager.CurrentState, mod.osuInputManager);
|
||||
}
|
||||
|
||||
public void HandleRelease(bool wasLeft)
|
||||
{
|
||||
mod.state.Apply(mod.osuInputManager.CurrentState, mod.osuInputManager);
|
||||
}
|
||||
}
|
||||
|
||||
// legacy replays do not contain key-presses with Relax mod, so they need to be triggered by themselves.
|
||||
private class LegacyReplayPressHandler : IPressHandler
|
||||
{
|
||||
private readonly OsuModRelax mod;
|
||||
|
||||
public LegacyReplayPressHandler(OsuModRelax mod)
|
||||
{
|
||||
this.mod = mod;
|
||||
}
|
||||
|
||||
public void HandlePress(bool wasLeft)
|
||||
{
|
||||
mod.osuInputManager.KeyBindingContainer.TriggerPressed(wasLeft ? OsuAction.LeftButton : OsuAction.RightButton);
|
||||
}
|
||||
|
||||
public void HandleRelease(bool wasLeft)
|
||||
{
|
||||
// this intentionally releases right when `wasLeft` is true because `wasLeft` is set at point of press and not at point of release
|
||||
mod.osuInputManager.KeyBindingContainer.TriggerReleased(wasLeft ? OsuAction.RightButton : OsuAction.LeftButton);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -43,13 +43,13 @@ namespace osu.Game.Tests.Rulesets
|
||||
|
||||
AddStep("setup provider", () =>
|
||||
{
|
||||
var rulesetSkinProvider = new RulesetSkinProvidingContainer(Ruleset.Value.CreateInstance(), Beatmap.Value.Beatmap, Beatmap.Value.Skin);
|
||||
|
||||
rulesetSkinProvider.Add(requester = new SkinRequester());
|
||||
|
||||
requester = new SkinRequester();
|
||||
requester.OnLoadAsync += () => textureOnLoad = requester.GetTexture("test-image");
|
||||
|
||||
Child = rulesetSkinProvider;
|
||||
Child = new RulesetSkinProvidingContainer(Ruleset.Value.CreateInstance(), Beatmap.Value.Beatmap, Beatmap.Value.Skin)
|
||||
{
|
||||
requester
|
||||
};
|
||||
});
|
||||
|
||||
AddAssert("requester got correct initial texture", () => textureOnLoad != null);
|
||||
|
Loading…
Reference in New Issue
Block a user