mirror of
https://github.com/ppy/osu.git
synced 2025-01-30 00:03:08 +08:00
Merge pull request #31519 from EVAST9919/trail-rotate
Add support for `CursorTrailRotate` skin command
This commit is contained in:
commit
471180d947
@ -6,6 +6,7 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using JetBrains.Annotations;
|
||||
using NUnit.Framework;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Audio.Sample;
|
||||
@ -17,6 +18,7 @@ using osu.Framework.Graphics.Textures;
|
||||
using osu.Framework.Testing;
|
||||
using osu.Framework.Testing.Input;
|
||||
using osu.Game.Audio;
|
||||
using osu.Game.Rulesets.Osu.Skinning;
|
||||
using osu.Game.Rulesets.Osu.Skinning.Legacy;
|
||||
using osu.Game.Rulesets.Osu.UI.Cursor;
|
||||
using osu.Game.Skinning;
|
||||
@ -103,6 +105,23 @@ namespace osu.Game.Rulesets.Osu.Tests
|
||||
AddStep("contract", () => this.ChildrenOfType<CursorTrail>().Single().NewPartScale = Vector2.One);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestRotation()
|
||||
{
|
||||
createTest(() =>
|
||||
{
|
||||
var skinContainer = new LegacySkinContainer(renderer, provideMiddle: true, enableRotation: true);
|
||||
var legacyCursorTrail = new LegacyRotatingCursorTrail(skinContainer)
|
||||
{
|
||||
NewPartScale = new Vector2(10)
|
||||
};
|
||||
|
||||
skinContainer.Child = legacyCursorTrail;
|
||||
|
||||
return skinContainer;
|
||||
});
|
||||
}
|
||||
|
||||
private void createTest(Func<Drawable> createContent) => AddStep("create trail", () =>
|
||||
{
|
||||
Clear();
|
||||
@ -121,12 +140,14 @@ namespace osu.Game.Rulesets.Osu.Tests
|
||||
private readonly IRenderer renderer;
|
||||
private readonly bool provideMiddle;
|
||||
private readonly bool provideCursor;
|
||||
private readonly bool enableRotation;
|
||||
|
||||
public LegacySkinContainer(IRenderer renderer, bool provideMiddle, bool provideCursor = true)
|
||||
public LegacySkinContainer(IRenderer renderer, bool provideMiddle, bool provideCursor = true, bool enableRotation = false)
|
||||
{
|
||||
this.renderer = renderer;
|
||||
this.provideMiddle = provideMiddle;
|
||||
this.provideCursor = provideCursor;
|
||||
this.enableRotation = enableRotation;
|
||||
|
||||
RelativeSizeAxes = Axes.Both;
|
||||
}
|
||||
@ -152,7 +173,19 @@ namespace osu.Game.Rulesets.Osu.Tests
|
||||
|
||||
public ISample GetSample(ISampleInfo sampleInfo) => null;
|
||||
|
||||
public IBindable<TValue> GetConfig<TLookup, TValue>(TLookup lookup) => null;
|
||||
public IBindable<TValue> GetConfig<TLookup, TValue>(TLookup lookup)
|
||||
{
|
||||
switch (lookup)
|
||||
{
|
||||
case OsuSkinConfiguration osuLookup:
|
||||
if (osuLookup == OsuSkinConfiguration.CursorTrailRotate)
|
||||
return SkinUtils.As<TValue>(new BindableBool(enableRotation));
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public ISkin FindProvider(Func<ISkin, bool> lookupFunction) => lookupFunction(this) ? this : null;
|
||||
|
||||
@ -185,5 +218,19 @@ namespace osu.Game.Rulesets.Osu.Tests
|
||||
MoveMouseTo(ToScreenSpace(DrawSize / 2 + DrawSize / 3 * rPos));
|
||||
}
|
||||
}
|
||||
|
||||
private partial class LegacyRotatingCursorTrail : LegacyCursorTrail
|
||||
{
|
||||
public LegacyRotatingCursorTrail([NotNull] ISkin skin)
|
||||
: base(skin)
|
||||
{
|
||||
}
|
||||
|
||||
protected override void Update()
|
||||
{
|
||||
base.Update();
|
||||
PartRotation += (float)(Time.Elapsed * 0.1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -11,6 +11,8 @@ namespace osu.Game.Rulesets.Osu.Skinning.Legacy
|
||||
{
|
||||
public partial class LegacyCursor : SkinnableCursor
|
||||
{
|
||||
public static readonly int REVOLUTION_DURATION = 10000;
|
||||
|
||||
private const float pressed_scale = 1.3f;
|
||||
private const float released_scale = 1f;
|
||||
|
||||
@ -52,7 +54,7 @@ namespace osu.Game.Rulesets.Osu.Skinning.Legacy
|
||||
protected override void LoadComplete()
|
||||
{
|
||||
if (spin)
|
||||
ExpandTarget.Spin(10000, RotationDirection.Clockwise);
|
||||
ExpandTarget.Spin(REVOLUTION_DURATION, RotationDirection.Clockwise);
|
||||
}
|
||||
|
||||
public override void Expand()
|
||||
|
@ -34,6 +34,7 @@ namespace osu.Game.Rulesets.Osu.Skinning.Legacy
|
||||
private void load(OsuConfigManager config, ISkinSource skinSource)
|
||||
{
|
||||
cursorSize = config.GetBindable<float>(OsuSetting.GameplayCursorSize).GetBoundCopy();
|
||||
AllowPartRotation = skin.GetConfig<OsuSkinConfiguration, bool>(OsuSkinConfiguration.CursorTrailRotate)?.Value ?? true;
|
||||
|
||||
Texture = skin.GetTexture("cursortrail");
|
||||
|
||||
|
@ -9,6 +9,7 @@ namespace osu.Game.Rulesets.Osu.Skinning
|
||||
CursorCentre,
|
||||
CursorExpand,
|
||||
CursorRotate,
|
||||
CursorTrailRotate,
|
||||
HitCircleOverlayAboveNumber,
|
||||
|
||||
// ReSharper disable once IdentifierTypo
|
||||
|
@ -34,19 +34,24 @@ namespace osu.Game.Rulesets.Osu.UI.Cursor
|
||||
/// </summary>
|
||||
protected virtual float FadeExponent => 1.7f;
|
||||
|
||||
private readonly TrailPart[] parts = new TrailPart[max_sprites];
|
||||
private int currentIndex;
|
||||
private IShader shader;
|
||||
private double timeOffset;
|
||||
private float time;
|
||||
|
||||
/// <summary>
|
||||
/// The scale used on creation of a new trail part.
|
||||
/// </summary>
|
||||
public Vector2 NewPartScale = Vector2.One;
|
||||
public Vector2 NewPartScale { get; set; } = Vector2.One;
|
||||
|
||||
private Anchor trailOrigin = Anchor.Centre;
|
||||
/// <summary>
|
||||
/// The rotation (in degrees) to apply to trail parts when <see cref="AllowPartRotation"/> is <c>true</c>.
|
||||
/// </summary>
|
||||
public float PartRotation { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Whether to rotate trail parts based on the value of <see cref="PartRotation"/>.
|
||||
/// </summary>
|
||||
protected bool AllowPartRotation { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The trail part texture origin.
|
||||
/// </summary>
|
||||
protected Anchor TrailOrigin
|
||||
{
|
||||
get => trailOrigin;
|
||||
@ -57,6 +62,13 @@ namespace osu.Game.Rulesets.Osu.UI.Cursor
|
||||
}
|
||||
}
|
||||
|
||||
private readonly TrailPart[] parts = new TrailPart[max_sprites];
|
||||
private Anchor trailOrigin = Anchor.Centre;
|
||||
private int currentIndex;
|
||||
private IShader shader;
|
||||
private double timeOffset;
|
||||
private float time;
|
||||
|
||||
public CursorTrail()
|
||||
{
|
||||
// as we are currently very dependent on having a running clock, let's make our own clock for the time being.
|
||||
@ -220,6 +232,7 @@ namespace osu.Game.Rulesets.Osu.UI.Cursor
|
||||
|
||||
private float time;
|
||||
private float fadeExponent;
|
||||
private float angle;
|
||||
|
||||
private readonly TrailPart[] parts = new TrailPart[max_sprites];
|
||||
private Vector2 originPosition;
|
||||
@ -239,6 +252,7 @@ namespace osu.Game.Rulesets.Osu.UI.Cursor
|
||||
texture = Source.texture;
|
||||
time = Source.time;
|
||||
fadeExponent = Source.FadeExponent;
|
||||
angle = Source.AllowPartRotation ? float.DegreesToRadians(Source.PartRotation) : 0;
|
||||
|
||||
originPosition = Vector2.Zero;
|
||||
|
||||
@ -279,6 +293,9 @@ namespace osu.Game.Rulesets.Osu.UI.Cursor
|
||||
|
||||
renderer.PushLocalMatrix(DrawInfo.Matrix);
|
||||
|
||||
float sin = MathF.Sin(angle);
|
||||
float cos = MathF.Cos(angle);
|
||||
|
||||
foreach (var part in parts)
|
||||
{
|
||||
if (part.InvalidationID == -1)
|
||||
@ -289,7 +306,9 @@ namespace osu.Game.Rulesets.Osu.UI.Cursor
|
||||
|
||||
vertexBatch.Add(new TexturedTrailVertex
|
||||
{
|
||||
Position = new Vector2(part.Position.X - texture.DisplayWidth * originPosition.X * part.Scale.X, part.Position.Y + texture.DisplayHeight * (1 - originPosition.Y) * part.Scale.Y),
|
||||
Position = rotateAround(
|
||||
new Vector2(part.Position.X - texture.DisplayWidth * originPosition.X * part.Scale.X, part.Position.Y + texture.DisplayHeight * (1 - originPosition.Y) * part.Scale.Y),
|
||||
part.Position, sin, cos),
|
||||
TexturePosition = textureRect.BottomLeft,
|
||||
TextureRect = new Vector4(0, 0, 1, 1),
|
||||
Colour = DrawColourInfo.Colour.BottomLeft.Linear,
|
||||
@ -298,7 +317,9 @@ namespace osu.Game.Rulesets.Osu.UI.Cursor
|
||||
|
||||
vertexBatch.Add(new TexturedTrailVertex
|
||||
{
|
||||
Position = new Vector2(part.Position.X + texture.DisplayWidth * (1 - originPosition.X) * part.Scale.X, part.Position.Y + texture.DisplayHeight * (1 - originPosition.Y) * part.Scale.Y),
|
||||
Position = rotateAround(
|
||||
new Vector2(part.Position.X + texture.DisplayWidth * (1 - originPosition.X) * part.Scale.X,
|
||||
part.Position.Y + texture.DisplayHeight * (1 - originPosition.Y) * part.Scale.Y), part.Position, sin, cos),
|
||||
TexturePosition = textureRect.BottomRight,
|
||||
TextureRect = new Vector4(0, 0, 1, 1),
|
||||
Colour = DrawColourInfo.Colour.BottomRight.Linear,
|
||||
@ -307,7 +328,9 @@ namespace osu.Game.Rulesets.Osu.UI.Cursor
|
||||
|
||||
vertexBatch.Add(new TexturedTrailVertex
|
||||
{
|
||||
Position = new Vector2(part.Position.X + texture.DisplayWidth * (1 - originPosition.X) * part.Scale.X, part.Position.Y - texture.DisplayHeight * originPosition.Y * part.Scale.Y),
|
||||
Position = rotateAround(
|
||||
new Vector2(part.Position.X + texture.DisplayWidth * (1 - originPosition.X) * part.Scale.X, part.Position.Y - texture.DisplayHeight * originPosition.Y * part.Scale.Y),
|
||||
part.Position, sin, cos),
|
||||
TexturePosition = textureRect.TopRight,
|
||||
TextureRect = new Vector4(0, 0, 1, 1),
|
||||
Colour = DrawColourInfo.Colour.TopRight.Linear,
|
||||
@ -316,7 +339,9 @@ namespace osu.Game.Rulesets.Osu.UI.Cursor
|
||||
|
||||
vertexBatch.Add(new TexturedTrailVertex
|
||||
{
|
||||
Position = new Vector2(part.Position.X - texture.DisplayWidth * originPosition.X * part.Scale.X, part.Position.Y - texture.DisplayHeight * originPosition.Y * part.Scale.Y),
|
||||
Position = rotateAround(
|
||||
new Vector2(part.Position.X - texture.DisplayWidth * originPosition.X * part.Scale.X, part.Position.Y - texture.DisplayHeight * originPosition.Y * part.Scale.Y),
|
||||
part.Position, sin, cos),
|
||||
TexturePosition = textureRect.TopLeft,
|
||||
TextureRect = new Vector4(0, 0, 1, 1),
|
||||
Colour = DrawColourInfo.Colour.TopLeft.Linear,
|
||||
@ -330,6 +355,14 @@ namespace osu.Game.Rulesets.Osu.UI.Cursor
|
||||
shader.Unbind();
|
||||
}
|
||||
|
||||
private static Vector2 rotateAround(Vector2 input, Vector2 origin, float sin, float cos)
|
||||
{
|
||||
float xTranslated = input.X - origin.X;
|
||||
float yTranslated = input.Y - origin.Y;
|
||||
|
||||
return new Vector2(xTranslated * cos - yTranslated * sin, xTranslated * sin + yTranslated * cos) + origin;
|
||||
}
|
||||
|
||||
protected override void Dispose(bool isDisposing)
|
||||
{
|
||||
base.Dispose(isDisposing);
|
||||
|
@ -36,6 +36,11 @@ namespace osu.Game.Rulesets.Osu.UI.Cursor
|
||||
/// </summary>
|
||||
public Vector2 CurrentExpandedScale => skinnableCursor.ExpandTarget?.Scale ?? Vector2.One;
|
||||
|
||||
/// <summary>
|
||||
/// The current rotation of the cursor.
|
||||
/// </summary>
|
||||
public float CurrentRotation => skinnableCursor.ExpandTarget?.Rotation ?? 0;
|
||||
|
||||
public IBindable<float> CursorScale => cursorScale;
|
||||
|
||||
/// <summary>
|
||||
|
@ -83,7 +83,10 @@ namespace osu.Game.Rulesets.Osu.UI.Cursor
|
||||
base.Update();
|
||||
|
||||
if (cursorTrail.Drawable is CursorTrail trail)
|
||||
{
|
||||
trail.NewPartScale = ActiveCursor.CurrentExpandedScale;
|
||||
trail.PartRotation = ActiveCursor.CurrentRotation;
|
||||
}
|
||||
}
|
||||
|
||||
public bool OnPressed(KeyBindingPressEvent<OsuAction> e)
|
||||
|
Loading…
Reference in New Issue
Block a user