mirror of
https://github.com/ppy/osu.git
synced 2024-12-13 08:32:57 +08:00
Merge branch 'master' into fix-mania-rewinding
This commit is contained in:
commit
d63f196626
@ -8,7 +8,6 @@ using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Game.Rulesets.Mania.Beatmaps;
|
||||
using osu.Game.Rulesets.Mania.UI;
|
||||
using osuTK.Graphics;
|
||||
|
||||
namespace osu.Game.Rulesets.Mania.Tests.Skinning
|
||||
{
|
||||
@ -34,7 +33,6 @@ namespace osu.Game.Rulesets.Mania.Tests.Skinning
|
||||
this.column = new Column(column, false)
|
||||
{
|
||||
Action = { Value = action },
|
||||
AccentColour = { Value = Color4.Orange },
|
||||
Alpha = showColumn ? 1 : 0
|
||||
},
|
||||
content = new ManiaInputManager(new ManiaRuleset().RulesetInfo, 4)
|
||||
|
@ -61,7 +61,6 @@ namespace osu.Game.Rulesets.Mania.Tests.Skinning
|
||||
c.Add(CreateHitObject().With(h =>
|
||||
{
|
||||
h.HitObject.StartTime = Time.Current + 5000;
|
||||
h.AccentColour.Value = Color4.Orange;
|
||||
}));
|
||||
})
|
||||
},
|
||||
|
@ -65,22 +65,6 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables
|
||||
Direction.BindValueChanged(OnDirectionChanged, true);
|
||||
}
|
||||
|
||||
protected override void OnApply()
|
||||
{
|
||||
base.OnApply();
|
||||
|
||||
if (ParentHitObject != null)
|
||||
AccentColour.BindTo(ParentHitObject.AccentColour);
|
||||
}
|
||||
|
||||
protected override void OnFree()
|
||||
{
|
||||
base.OnFree();
|
||||
|
||||
if (ParentHitObject != null)
|
||||
AccentColour.UnbindFrom(ParentHitObject.AccentColour);
|
||||
}
|
||||
|
||||
protected virtual void OnDirectionChanged(ValueChangedEvent<ScrollingDirection> e)
|
||||
{
|
||||
Anchor = Origin = e.NewValue == ScrollingDirection.Up ? Anchor.TopCentre : Anchor.BottomCentre;
|
||||
|
101
osu.Game.Rulesets.Mania/Skinning/Argon/ArgonColumnBackground.cs
Normal file
101
osu.Game.Rulesets.Mania/Skinning/Argon/ArgonColumnBackground.cs
Normal file
@ -0,0 +1,101 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Bindables;
|
||||
using osu.Framework.Extensions.Color4Extensions;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Colour;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics.Shapes;
|
||||
using osu.Framework.Input.Bindings;
|
||||
using osu.Framework.Input.Events;
|
||||
using osu.Game.Rulesets.Mania.UI;
|
||||
using osu.Game.Rulesets.UI.Scrolling;
|
||||
using osuTK.Graphics;
|
||||
|
||||
namespace osu.Game.Rulesets.Mania.Skinning.Argon
|
||||
{
|
||||
public class ArgonColumnBackground : CompositeDrawable, IKeyBindingHandler<ManiaAction>
|
||||
{
|
||||
private readonly IBindable<ScrollingDirection> direction = new Bindable<ScrollingDirection>();
|
||||
|
||||
private Color4 brightColour;
|
||||
private Color4 dimColour;
|
||||
|
||||
private Box background = null!;
|
||||
private Box backgroundOverlay = null!;
|
||||
|
||||
[Resolved]
|
||||
private Column column { get; set; } = null!;
|
||||
|
||||
private Bindable<Color4> accentColour = null!;
|
||||
|
||||
public ArgonColumnBackground()
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both;
|
||||
|
||||
Masking = true;
|
||||
CornerRadius = ArgonNotePiece.CORNER_RADIUS;
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(IScrollingInfo scrollingInfo)
|
||||
{
|
||||
InternalChildren = new[]
|
||||
{
|
||||
background = new Box
|
||||
{
|
||||
Name = "Background",
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
},
|
||||
backgroundOverlay = new Box
|
||||
{
|
||||
Name = "Background Gradient Overlay",
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Height = 0.5f,
|
||||
Blending = BlendingParameters.Additive,
|
||||
Alpha = 0
|
||||
}
|
||||
};
|
||||
|
||||
accentColour = column.AccentColour.GetBoundCopy();
|
||||
accentColour.BindValueChanged(colour =>
|
||||
{
|
||||
background.Colour = colour.NewValue.Darken(5);
|
||||
brightColour = colour.NewValue.Opacity(0.6f);
|
||||
dimColour = colour.NewValue.Opacity(0);
|
||||
}, true);
|
||||
|
||||
direction.BindTo(scrollingInfo.Direction);
|
||||
direction.BindValueChanged(onDirectionChanged, true);
|
||||
}
|
||||
|
||||
private void onDirectionChanged(ValueChangedEvent<ScrollingDirection> direction)
|
||||
{
|
||||
if (direction.NewValue == ScrollingDirection.Up)
|
||||
{
|
||||
backgroundOverlay.Anchor = backgroundOverlay.Origin = Anchor.TopLeft;
|
||||
backgroundOverlay.Colour = ColourInfo.GradientVertical(brightColour, dimColour);
|
||||
}
|
||||
else
|
||||
{
|
||||
backgroundOverlay.Anchor = backgroundOverlay.Origin = Anchor.BottomLeft;
|
||||
backgroundOverlay.Colour = ColourInfo.GradientVertical(dimColour, brightColour);
|
||||
}
|
||||
}
|
||||
|
||||
public bool OnPressed(KeyBindingPressEvent<ManiaAction> e)
|
||||
{
|
||||
if (e.Action == column.Action.Value)
|
||||
backgroundOverlay.FadeTo(1, 50, Easing.OutQuint).Then().FadeTo(0.5f, 250, Easing.OutQuint);
|
||||
return false;
|
||||
}
|
||||
|
||||
public void OnReleased(KeyBindingReleaseEvent<ManiaAction> e)
|
||||
{
|
||||
if (e.Action == column.Action.Value)
|
||||
backgroundOverlay.FadeTo(0, 250, Easing.OutQuint);
|
||||
}
|
||||
}
|
||||
}
|
99
osu.Game.Rulesets.Mania/Skinning/Argon/ArgonHitExplosion.cs
Normal file
99
osu.Game.Rulesets.Mania/Skinning/Argon/ArgonHitExplosion.cs
Normal file
@ -0,0 +1,99 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Bindables;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics.Effects;
|
||||
using osu.Framework.Graphics.Shapes;
|
||||
using osu.Framework.Utils;
|
||||
using osu.Game.Rulesets.Judgements;
|
||||
using osu.Game.Rulesets.Mania.UI;
|
||||
using osu.Game.Rulesets.UI.Scrolling;
|
||||
using osuTK.Graphics;
|
||||
|
||||
namespace osu.Game.Rulesets.Mania.Skinning.Argon
|
||||
{
|
||||
public class ArgonHitExplosion : CompositeDrawable, IHitExplosion
|
||||
{
|
||||
private const float default_large_faint_size = 0.8f;
|
||||
|
||||
public override bool RemoveWhenNotAlive => true;
|
||||
|
||||
[Resolved]
|
||||
private Column column { get; set; } = null!;
|
||||
|
||||
private readonly IBindable<ScrollingDirection> direction = new Bindable<ScrollingDirection>();
|
||||
|
||||
private Container largeFaint = null!;
|
||||
|
||||
private Bindable<Color4> accentColour = null!;
|
||||
|
||||
public ArgonHitExplosion()
|
||||
{
|
||||
Origin = Anchor.Centre;
|
||||
|
||||
RelativeSizeAxes = Axes.X;
|
||||
Height = ArgonNotePiece.NOTE_HEIGHT;
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(IScrollingInfo scrollingInfo)
|
||||
{
|
||||
InternalChildren = new Drawable[]
|
||||
{
|
||||
largeFaint = new Container
|
||||
{
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Masking = true,
|
||||
CornerRadius = ArgonNotePiece.CORNER_RADIUS,
|
||||
Blending = BlendingParameters.Additive,
|
||||
Child = new Box
|
||||
{
|
||||
Colour = Color4.White,
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
direction.BindTo(scrollingInfo.Direction);
|
||||
direction.BindValueChanged(onDirectionChanged, true);
|
||||
|
||||
accentColour = column.AccentColour.GetBoundCopy();
|
||||
accentColour.BindValueChanged(colour =>
|
||||
{
|
||||
largeFaint.Colour = Interpolation.ValueAt(0.8f, colour.NewValue, Color4.White, 0, 1);
|
||||
|
||||
largeFaint.EdgeEffect = new EdgeEffectParameters
|
||||
{
|
||||
Type = EdgeEffectType.Glow,
|
||||
Colour = colour.NewValue,
|
||||
Roundness = 40,
|
||||
Radius = 60,
|
||||
};
|
||||
}, true);
|
||||
}
|
||||
|
||||
private void onDirectionChanged(ValueChangedEvent<ScrollingDirection> direction)
|
||||
{
|
||||
if (direction.NewValue == ScrollingDirection.Up)
|
||||
{
|
||||
Anchor = Anchor.TopCentre;
|
||||
Y = ArgonNotePiece.NOTE_HEIGHT / 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
Anchor = Anchor.BottomCentre;
|
||||
Y = -ArgonNotePiece.NOTE_HEIGHT / 2;
|
||||
}
|
||||
}
|
||||
|
||||
public void Animate(JudgementResult result)
|
||||
{
|
||||
this.FadeOutFromOne(PoolableHitExplosion.DURATION, Easing.Out);
|
||||
}
|
||||
}
|
||||
}
|
@ -6,7 +6,6 @@ using osu.Framework.Bindables;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics.Shapes;
|
||||
using osu.Game.Rulesets.Mania.Skinning.Default;
|
||||
using osu.Game.Rulesets.UI.Scrolling;
|
||||
using osuTK.Graphics;
|
||||
|
||||
@ -20,7 +19,10 @@ namespace osu.Game.Rulesets.Mania.Skinning.Argon
|
||||
private void load(IScrollingInfo scrollingInfo)
|
||||
{
|
||||
RelativeSizeAxes = Axes.X;
|
||||
Height = DefaultNotePiece.NOTE_HEIGHT;
|
||||
Height = ArgonNotePiece.NOTE_HEIGHT;
|
||||
|
||||
Masking = true;
|
||||
CornerRadius = ArgonNotePiece.CORNER_RADIUS;
|
||||
|
||||
InternalChildren = new[]
|
||||
{
|
||||
|
90
osu.Game.Rulesets.Mania/Skinning/Argon/ArgonHoldBodyPiece.cs
Normal file
90
osu.Game.Rulesets.Mania/Skinning/Argon/ArgonHoldBodyPiece.cs
Normal file
@ -0,0 +1,90 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Bindables;
|
||||
using osu.Framework.Extensions.Color4Extensions;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics.Shapes;
|
||||
using osu.Game.Rulesets.Mania.Objects.Drawables;
|
||||
using osu.Game.Rulesets.Objects.Drawables;
|
||||
using osuTK.Graphics;
|
||||
|
||||
namespace osu.Game.Rulesets.Mania.Skinning.Argon
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents length-wise portion of a hold note.
|
||||
/// </summary>
|
||||
public class ArgonHoldBodyPiece : CompositeDrawable
|
||||
{
|
||||
protected readonly Bindable<Color4> AccentColour = new Bindable<Color4>();
|
||||
protected readonly IBindable<bool> IsHitting = new Bindable<bool>();
|
||||
|
||||
private Drawable background = null!;
|
||||
private Box foreground = null!;
|
||||
|
||||
public ArgonHoldBodyPiece()
|
||||
{
|
||||
Blending = BlendingParameters.Additive;
|
||||
RelativeSizeAxes = Axes.Both;
|
||||
|
||||
// Without this, the width of the body will be slightly larger than the head/tail.
|
||||
Masking = true;
|
||||
CornerRadius = ArgonNotePiece.CORNER_RADIUS;
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader(true)]
|
||||
private void load(DrawableHitObject? drawableObject)
|
||||
{
|
||||
InternalChildren = new[]
|
||||
{
|
||||
background = new Box { RelativeSizeAxes = Axes.Both },
|
||||
foreground = new Box
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Blending = BlendingParameters.Additive,
|
||||
Alpha = 0,
|
||||
},
|
||||
};
|
||||
|
||||
if (drawableObject != null)
|
||||
{
|
||||
var holdNote = (DrawableHoldNote)drawableObject;
|
||||
|
||||
AccentColour.BindTo(drawableObject.AccentColour);
|
||||
IsHitting.BindTo(holdNote.IsHitting);
|
||||
}
|
||||
|
||||
AccentColour.BindValueChanged(colour =>
|
||||
{
|
||||
background.Colour = colour.NewValue.Opacity(0.2f);
|
||||
foreground.Colour = colour.NewValue.Opacity(0.1f);
|
||||
}, true);
|
||||
|
||||
IsHitting.BindValueChanged(hitting =>
|
||||
{
|
||||
const float animation_length = 50;
|
||||
|
||||
foreground.ClearTransforms();
|
||||
|
||||
if (hitting.NewValue)
|
||||
{
|
||||
// wait for the next sync point
|
||||
double synchronisedOffset = animation_length * 2 - Time.Current % (animation_length * 2);
|
||||
|
||||
using (foreground.BeginDelayedSequence(synchronisedOffset))
|
||||
{
|
||||
foreground.FadeTo(1, animation_length).Then()
|
||||
.FadeTo(0, animation_length)
|
||||
.Loop();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
foreground.FadeOut(animation_length);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,91 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Bindables;
|
||||
using osu.Framework.Extensions.Color4Extensions;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Colour;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics.Shapes;
|
||||
using osu.Game.Rulesets.Objects.Drawables;
|
||||
using osu.Game.Rulesets.UI.Scrolling;
|
||||
using osuTK.Graphics;
|
||||
|
||||
namespace osu.Game.Rulesets.Mania.Skinning.Argon
|
||||
{
|
||||
internal class ArgonHoldNoteTailPiece : CompositeDrawable
|
||||
{
|
||||
private readonly IBindable<ScrollingDirection> direction = new Bindable<ScrollingDirection>();
|
||||
private readonly IBindable<Color4> accentColour = new Bindable<Color4>();
|
||||
|
||||
private readonly Box colouredBox;
|
||||
private readonly Box shadow;
|
||||
|
||||
public ArgonHoldNoteTailPiece()
|
||||
{
|
||||
RelativeSizeAxes = Axes.X;
|
||||
Height = ArgonNotePiece.NOTE_HEIGHT;
|
||||
|
||||
CornerRadius = ArgonNotePiece.CORNER_RADIUS;
|
||||
Masking = true;
|
||||
|
||||
InternalChildren = new Drawable[]
|
||||
{
|
||||
shadow = new Box
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
},
|
||||
new Container
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Height = 0.82f,
|
||||
Masking = true,
|
||||
CornerRadius = ArgonNotePiece.CORNER_RADIUS,
|
||||
Children = new Drawable[]
|
||||
{
|
||||
colouredBox = new Box
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
}
|
||||
}
|
||||
},
|
||||
new Circle
|
||||
{
|
||||
RelativeSizeAxes = Axes.X,
|
||||
Height = ArgonNotePiece.CORNER_RADIUS * 2,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader(true)]
|
||||
private void load(IScrollingInfo scrollingInfo, DrawableHitObject? drawableObject)
|
||||
{
|
||||
direction.BindTo(scrollingInfo.Direction);
|
||||
direction.BindValueChanged(onDirectionChanged, true);
|
||||
|
||||
if (drawableObject != null)
|
||||
{
|
||||
accentColour.BindTo(drawableObject.AccentColour);
|
||||
accentColour.BindValueChanged(onAccentChanged, true);
|
||||
}
|
||||
}
|
||||
|
||||
private void onDirectionChanged(ValueChangedEvent<ScrollingDirection> direction)
|
||||
{
|
||||
colouredBox.Anchor = colouredBox.Origin = direction.NewValue == ScrollingDirection.Up
|
||||
? Anchor.TopCentre
|
||||
: Anchor.BottomCentre;
|
||||
}
|
||||
|
||||
private void onAccentChanged(ValueChangedEvent<Color4> accent)
|
||||
{
|
||||
colouredBox.Colour = ColourInfo.GradientVertical(
|
||||
accent.NewValue,
|
||||
accent.NewValue.Darken(0.1f)
|
||||
);
|
||||
|
||||
shadow.Colour = accent.NewValue.Darken(0.5f);
|
||||
}
|
||||
}
|
||||
}
|
193
osu.Game.Rulesets.Mania/Skinning/Argon/ArgonJudgementPiece.cs
Normal file
193
osu.Game.Rulesets.Mania/Skinning/Argon/ArgonJudgementPiece.cs
Normal file
@ -0,0 +1,193 @@
|
||||
// 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 osu.Framework.Allocation;
|
||||
using osu.Framework.Extensions;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics.Shapes;
|
||||
using osu.Framework.Graphics.Sprites;
|
||||
using osu.Framework.Utils;
|
||||
using osu.Game.Graphics;
|
||||
using osu.Game.Graphics.Sprites;
|
||||
using osu.Game.Rulesets.Judgements;
|
||||
using osu.Game.Rulesets.Scoring;
|
||||
using osuTK;
|
||||
using osuTK.Graphics;
|
||||
|
||||
namespace osu.Game.Rulesets.Mania.Skinning.Argon
|
||||
{
|
||||
public class ArgonJudgementPiece : CompositeDrawable, IAnimatableJudgement
|
||||
{
|
||||
protected readonly HitResult Result;
|
||||
|
||||
protected SpriteText JudgementText { get; private set; } = null!;
|
||||
|
||||
private RingExplosion? ringExplosion;
|
||||
|
||||
[Resolved]
|
||||
private OsuColour colours { get; set; } = null!;
|
||||
|
||||
public ArgonJudgementPiece(HitResult result)
|
||||
{
|
||||
Result = result;
|
||||
Origin = Anchor.Centre;
|
||||
Y = 160;
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load()
|
||||
{
|
||||
AutoSizeAxes = Axes.Both;
|
||||
|
||||
InternalChildren = new Drawable[]
|
||||
{
|
||||
JudgementText = new OsuSpriteText
|
||||
{
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
Text = Result.GetDescription().ToUpperInvariant(),
|
||||
Colour = colours.ForHitResult(Result),
|
||||
Blending = BlendingParameters.Additive,
|
||||
Spacing = new Vector2(10, 0),
|
||||
Font = OsuFont.Default.With(size: 28, weight: FontWeight.Regular),
|
||||
},
|
||||
};
|
||||
|
||||
if (Result.IsHit())
|
||||
{
|
||||
AddInternal(ringExplosion = new RingExplosion(Result)
|
||||
{
|
||||
Colour = colours.ForHitResult(Result),
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Plays the default animation for this judgement piece.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// The base implementation only handles fade (for all result types) and misses.
|
||||
/// Individual rulesets are recommended to implement their appropriate hit animations.
|
||||
/// </remarks>
|
||||
public virtual void PlayAnimation()
|
||||
{
|
||||
switch (Result)
|
||||
{
|
||||
default:
|
||||
JudgementText
|
||||
.ScaleTo(Vector2.One)
|
||||
.ScaleTo(new Vector2(1.4f), 1800, Easing.OutQuint);
|
||||
break;
|
||||
|
||||
case HitResult.Miss:
|
||||
this.ScaleTo(1.6f);
|
||||
this.ScaleTo(1, 100, Easing.In);
|
||||
|
||||
this.MoveTo(Vector2.Zero);
|
||||
this.MoveToOffset(new Vector2(0, 100), 800, Easing.InQuint);
|
||||
|
||||
this.RotateTo(0);
|
||||
this.RotateTo(40, 800, Easing.InQuint);
|
||||
break;
|
||||
}
|
||||
|
||||
this.FadeOutFromOne(800);
|
||||
|
||||
ringExplosion?.PlayAnimation();
|
||||
}
|
||||
|
||||
public Drawable? GetAboveHitObjectsProxiedContent() => null;
|
||||
|
||||
private class RingExplosion : CompositeDrawable
|
||||
{
|
||||
private readonly float travel = 52;
|
||||
|
||||
public RingExplosion(HitResult result)
|
||||
{
|
||||
const float thickness = 4;
|
||||
|
||||
const float small_size = 9;
|
||||
const float large_size = 14;
|
||||
|
||||
Anchor = Anchor.Centre;
|
||||
Origin = Anchor.Centre;
|
||||
|
||||
Blending = BlendingParameters.Additive;
|
||||
|
||||
int countSmall = 0;
|
||||
int countLarge = 0;
|
||||
|
||||
switch (result)
|
||||
{
|
||||
case HitResult.Meh:
|
||||
countSmall = 3;
|
||||
travel *= 0.3f;
|
||||
break;
|
||||
|
||||
case HitResult.Ok:
|
||||
case HitResult.Good:
|
||||
countSmall = 4;
|
||||
travel *= 0.6f;
|
||||
break;
|
||||
|
||||
case HitResult.Great:
|
||||
case HitResult.Perfect:
|
||||
countSmall = 4;
|
||||
countLarge = 4;
|
||||
break;
|
||||
}
|
||||
|
||||
for (int i = 0; i < countSmall; i++)
|
||||
AddInternal(new RingPiece(thickness) { Size = new Vector2(small_size) });
|
||||
|
||||
for (int i = 0; i < countLarge; i++)
|
||||
AddInternal(new RingPiece(thickness) { Size = new Vector2(large_size) });
|
||||
}
|
||||
|
||||
public void PlayAnimation()
|
||||
{
|
||||
foreach (var c in InternalChildren)
|
||||
{
|
||||
const float start_position_ratio = 0.3f;
|
||||
|
||||
float direction = RNG.NextSingle(0, 360);
|
||||
float distance = RNG.NextSingle(travel / 2, travel);
|
||||
|
||||
c.MoveTo(new Vector2(
|
||||
MathF.Cos(direction) * distance * start_position_ratio,
|
||||
MathF.Sin(direction) * distance * start_position_ratio
|
||||
));
|
||||
|
||||
c.MoveTo(new Vector2(
|
||||
MathF.Cos(direction) * distance,
|
||||
MathF.Sin(direction) * distance
|
||||
), 600, Easing.OutQuint);
|
||||
}
|
||||
|
||||
this.FadeOutFromOne(1000, Easing.OutQuint);
|
||||
}
|
||||
|
||||
public class RingPiece : CircularContainer
|
||||
{
|
||||
public RingPiece(float thickness = 9)
|
||||
{
|
||||
Anchor = Anchor.Centre;
|
||||
Origin = Anchor.Centre;
|
||||
|
||||
Masking = true;
|
||||
BorderThickness = thickness;
|
||||
BorderColour = Color4.White;
|
||||
|
||||
Child = new Box
|
||||
{
|
||||
AlwaysPresent = true,
|
||||
Alpha = 0,
|
||||
RelativeSizeAxes = Axes.Both
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -53,18 +53,26 @@ namespace osu.Game.Rulesets.Mania.Skinning.Argon
|
||||
Height = Stage.HIT_TARGET_POSITION,
|
||||
Children = new[]
|
||||
{
|
||||
background = new Box
|
||||
new Container
|
||||
{
|
||||
Name = "Key gradient",
|
||||
Masking = true,
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
CornerRadius = ArgonNotePiece.CORNER_RADIUS,
|
||||
Child = background = new Box
|
||||
{
|
||||
Name = "Key gradient",
|
||||
Alpha = 0,
|
||||
Blending = BlendingParameters.Additive,
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
},
|
||||
},
|
||||
hitTargetLine = new Circle
|
||||
{
|
||||
RelativeSizeAxes = Axes.X,
|
||||
Anchor = Anchor.TopCentre,
|
||||
Origin = Anchor.Centre,
|
||||
Origin = Anchor.BottomCentre,
|
||||
Colour = OsuColour.Gray(196 / 255f),
|
||||
Height = 4,
|
||||
Height = ArgonNotePiece.CORNER_RADIUS * 2,
|
||||
Masking = true,
|
||||
},
|
||||
new Container
|
||||
@ -137,10 +145,11 @@ namespace osu.Game.Rulesets.Mania.Skinning.Argon
|
||||
|
||||
accentColour = column.AccentColour.GetBoundCopy();
|
||||
accentColour.BindValueChanged(colour =>
|
||||
{
|
||||
background.Colour = colour.NewValue.Darken(0.6f);
|
||||
bottomIcon.Colour = colour.NewValue;
|
||||
}, true);
|
||||
{
|
||||
background.Colour = colour.NewValue.Darken(1f);
|
||||
bottomIcon.Colour = colour.NewValue;
|
||||
},
|
||||
true);
|
||||
}
|
||||
|
||||
private void onDirectionChanged(ValueChangedEvent<ScrollingDirection> direction)
|
||||
@ -169,8 +178,8 @@ namespace osu.Game.Rulesets.Mania.Skinning.Argon
|
||||
Color4 lightingColour = accentColour.Value.Lighten(0.9f);
|
||||
|
||||
background
|
||||
.FadeColour(accentColour.Value.Lighten(0.4f), 40).Then()
|
||||
.FadeColour(accentColour.Value, 150, Easing.OutQuint);
|
||||
.FadeTo(1, 40).Then()
|
||||
.FadeTo(0.8f, 150, Easing.OutQuint);
|
||||
|
||||
hitTargetLine.FadeColour(Color4.White, lighting_fade_in_duration, Easing.OutQuint);
|
||||
hitTargetLine.TransformTo(nameof(EdgeEffect), new EdgeEffectParameters
|
||||
@ -210,7 +219,7 @@ namespace osu.Game.Rulesets.Mania.Skinning.Argon
|
||||
const double lighting_fade_out_duration = 300;
|
||||
Color4 lightingColour = accentColour.Value.Lighten(0.9f).Opacity(0);
|
||||
|
||||
background.FadeColour(accentColour.Value.Darken(0.6f), lighting_fade_out_duration, Easing.OutQuint);
|
||||
background.FadeTo(0, lighting_fade_out_duration, Easing.OutQuint);
|
||||
|
||||
topIcon.ScaleTo(1f, 200, Easing.OutQuint);
|
||||
topIcon.TransformTo(nameof(EdgeEffect), new EdgeEffectParameters
|
||||
@ -225,7 +234,7 @@ namespace osu.Game.Rulesets.Mania.Skinning.Argon
|
||||
{
|
||||
Type = EdgeEffectType.Glow,
|
||||
Colour = lightingColour,
|
||||
Radius = 30,
|
||||
Radius = 25,
|
||||
}, lighting_fade_out_duration, Easing.OutQuint);
|
||||
|
||||
bottomIcon.FadeColour(accentColour.Value, lighting_fade_out_duration, Easing.OutQuint);
|
||||
|
110
osu.Game.Rulesets.Mania/Skinning/Argon/ArgonNotePiece.cs
Normal file
110
osu.Game.Rulesets.Mania/Skinning/Argon/ArgonNotePiece.cs
Normal file
@ -0,0 +1,110 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Bindables;
|
||||
using osu.Framework.Extensions.Color4Extensions;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Colour;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics.Shapes;
|
||||
using osu.Framework.Graphics.Sprites;
|
||||
using osu.Game.Rulesets.Objects.Drawables;
|
||||
using osu.Game.Rulesets.UI.Scrolling;
|
||||
using osuTK;
|
||||
using osuTK.Graphics;
|
||||
|
||||
namespace osu.Game.Rulesets.Mania.Skinning.Argon
|
||||
{
|
||||
internal class ArgonNotePiece : CompositeDrawable
|
||||
{
|
||||
public const float NOTE_HEIGHT = 42;
|
||||
|
||||
public const float CORNER_RADIUS = 3;
|
||||
|
||||
private readonly IBindable<ScrollingDirection> direction = new Bindable<ScrollingDirection>();
|
||||
private readonly IBindable<Color4> accentColour = new Bindable<Color4>();
|
||||
|
||||
private readonly Box colouredBox;
|
||||
private readonly Box shadow;
|
||||
|
||||
public ArgonNotePiece()
|
||||
{
|
||||
RelativeSizeAxes = Axes.X;
|
||||
Height = NOTE_HEIGHT;
|
||||
|
||||
CornerRadius = CORNER_RADIUS;
|
||||
Masking = true;
|
||||
|
||||
InternalChildren = new Drawable[]
|
||||
{
|
||||
shadow = new Box
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
},
|
||||
new Container
|
||||
{
|
||||
Anchor = Anchor.BottomLeft,
|
||||
Origin = Anchor.BottomLeft,
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Height = 0.82f,
|
||||
Masking = true,
|
||||
CornerRadius = CORNER_RADIUS,
|
||||
Children = new Drawable[]
|
||||
{
|
||||
colouredBox = new Box
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
}
|
||||
}
|
||||
},
|
||||
new Circle
|
||||
{
|
||||
Anchor = Anchor.BottomLeft,
|
||||
Origin = Anchor.BottomLeft,
|
||||
RelativeSizeAxes = Axes.X,
|
||||
Height = CORNER_RADIUS * 2,
|
||||
},
|
||||
new SpriteIcon
|
||||
{
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
Y = 4,
|
||||
Icon = FontAwesome.Solid.AngleDown,
|
||||
Size = new Vector2(20),
|
||||
Scale = new Vector2(1, 0.7f)
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader(true)]
|
||||
private void load(IScrollingInfo scrollingInfo, DrawableHitObject? drawableObject)
|
||||
{
|
||||
direction.BindTo(scrollingInfo.Direction);
|
||||
direction.BindValueChanged(onDirectionChanged, true);
|
||||
|
||||
if (drawableObject != null)
|
||||
{
|
||||
accentColour.BindTo(drawableObject.AccentColour);
|
||||
accentColour.BindValueChanged(onAccentChanged, true);
|
||||
}
|
||||
}
|
||||
|
||||
private void onDirectionChanged(ValueChangedEvent<ScrollingDirection> direction)
|
||||
{
|
||||
colouredBox.Anchor = colouredBox.Origin = direction.NewValue == ScrollingDirection.Up
|
||||
? Anchor.TopCentre
|
||||
: Anchor.BottomCentre;
|
||||
}
|
||||
|
||||
private void onAccentChanged(ValueChangedEvent<Color4> accent)
|
||||
{
|
||||
colouredBox.Colour = ColourInfo.GradientVertical(
|
||||
accent.NewValue.Lighten(0.1f),
|
||||
accent.NewValue
|
||||
);
|
||||
|
||||
shadow.Colour = accent.NewValue.Darken(0.5f);
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,16 @@
|
||||
// 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.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
|
||||
namespace osu.Game.Rulesets.Mania.Skinning.Argon
|
||||
{
|
||||
public class ArgonStageBackground : CompositeDrawable
|
||||
{
|
||||
public ArgonStageBackground()
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both;
|
||||
}
|
||||
}
|
||||
}
|
@ -3,9 +3,9 @@
|
||||
|
||||
using osu.Framework.Bindables;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Utils;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Rulesets.Mania.Beatmaps;
|
||||
using osu.Game.Rulesets.Scoring;
|
||||
using osu.Game.Skinning;
|
||||
using osuTK.Graphics;
|
||||
|
||||
@ -25,15 +25,37 @@ namespace osu.Game.Rulesets.Mania.Skinning.Argon
|
||||
{
|
||||
switch (component)
|
||||
{
|
||||
case GameplaySkinComponent<HitResult> resultComponent:
|
||||
return new ArgonJudgementPiece(resultComponent.Component);
|
||||
|
||||
case ManiaSkinComponent maniaComponent:
|
||||
// TODO: Once everything is finalised, consider throwing UnsupportedSkinComponentException on missing entries.
|
||||
switch (maniaComponent.Component)
|
||||
{
|
||||
case ManiaSkinComponents.StageBackground:
|
||||
return new ArgonStageBackground();
|
||||
|
||||
case ManiaSkinComponents.ColumnBackground:
|
||||
return new ArgonColumnBackground();
|
||||
|
||||
case ManiaSkinComponents.HoldNoteBody:
|
||||
return new ArgonHoldBodyPiece();
|
||||
|
||||
case ManiaSkinComponents.HoldNoteTail:
|
||||
return new ArgonHoldNoteTailPiece();
|
||||
|
||||
case ManiaSkinComponents.HoldNoteHead:
|
||||
case ManiaSkinComponents.Note:
|
||||
return new ArgonNotePiece();
|
||||
|
||||
case ManiaSkinComponents.HitTarget:
|
||||
return new ArgonHitTarget();
|
||||
|
||||
case ManiaSkinComponents.KeyArea:
|
||||
return new ArgonKeyArea();
|
||||
|
||||
case ManiaSkinComponents.HitExplosion:
|
||||
return new ArgonHitExplosion();
|
||||
}
|
||||
|
||||
break;
|
||||
@ -46,17 +68,65 @@ namespace osu.Game.Rulesets.Mania.Skinning.Argon
|
||||
{
|
||||
if (lookup is ManiaSkinConfigurationLookup maniaLookup)
|
||||
{
|
||||
int column = maniaLookup.ColumnIndex ?? 0;
|
||||
var stage = beatmap.GetStageForColumnIndex(column);
|
||||
|
||||
switch (maniaLookup.Lookup)
|
||||
{
|
||||
case LegacyManiaSkinConfigurationLookups.StagePaddingBottom:
|
||||
case LegacyManiaSkinConfigurationLookups.StagePaddingTop:
|
||||
return SkinUtils.As<TValue>(new Bindable<float>(30));
|
||||
|
||||
case LegacyManiaSkinConfigurationLookups.ColumnWidth:
|
||||
return SkinUtils.As<TValue>(new Bindable<float>(
|
||||
stage.IsSpecialColumn(column) ? 120 : 60
|
||||
));
|
||||
|
||||
case LegacyManiaSkinConfigurationLookups.ColumnBackgroundColour:
|
||||
int column = maniaLookup.ColumnIndex ?? 0;
|
||||
var stage = beatmap.GetStageForColumnIndex(column);
|
||||
|
||||
Color4 colour;
|
||||
|
||||
if (stage.IsSpecialColumn(column))
|
||||
return SkinUtils.As<TValue>(new Bindable<Color4>(Color4.Yellow));
|
||||
colour = new Color4(159, 101, 255, 255);
|
||||
else
|
||||
{
|
||||
switch (column % 8)
|
||||
{
|
||||
default:
|
||||
colour = new Color4(240, 216, 0, 255);
|
||||
break;
|
||||
|
||||
// TODO: Add actual colours.
|
||||
return SkinUtils.As<TValue>(new Bindable<Color4>(new Color4(RNG.NextSingle() * 0.5f, RNG.NextSingle() * 0.5f, RNG.NextSingle() * 0.5f, 1)));
|
||||
case 1:
|
||||
colour = new Color4(240, 101, 0, 255);
|
||||
break;
|
||||
|
||||
case 2:
|
||||
colour = new Color4(240, 0, 130, 255);
|
||||
break;
|
||||
|
||||
case 3:
|
||||
colour = new Color4(192, 0, 240, 255);
|
||||
break;
|
||||
|
||||
case 4:
|
||||
colour = new Color4(178, 0, 240, 255);
|
||||
break;
|
||||
|
||||
case 5:
|
||||
colour = new Color4(0, 96, 240, 255);
|
||||
break;
|
||||
|
||||
case 6:
|
||||
colour = new Color4(0, 226, 240, 255);
|
||||
break;
|
||||
|
||||
case 7:
|
||||
colour = new Color4(0, 240, 96, 255);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return SkinUtils.As<TValue>(new Bindable<Color4>(colour));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -74,13 +74,6 @@ namespace osu.Game.Rulesets.Mania.UI
|
||||
skin.SourceChanged += onSourceChanged;
|
||||
onSourceChanged();
|
||||
|
||||
AccentColour.BindValueChanged(colour =>
|
||||
{
|
||||
// Manual transfer as hit objects may be moved between column and unbinding is non-trivial.
|
||||
foreach (var obj in HitObjectContainer.Objects)
|
||||
obj.AccentColour.Value = colour.NewValue;
|
||||
}, true);
|
||||
|
||||
Drawable background = new SkinnableDrawable(new ManiaSkinComponent(ManiaSkinComponents.ColumnBackground), _ => new DefaultColumnBackground())
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
@ -149,7 +142,7 @@ namespace osu.Game.Rulesets.Mania.UI
|
||||
|
||||
DrawableManiaHitObject maniaObject = (DrawableManiaHitObject)drawableHitObject;
|
||||
|
||||
maniaObject.AccentColour.Value = AccentColour.Value;
|
||||
maniaObject.AccentColour.BindTo(AccentColour);
|
||||
maniaObject.CheckHittable = hitPolicy.IsHittable;
|
||||
}
|
||||
|
||||
|
@ -36,6 +36,8 @@ namespace osu.Game.Rulesets.Mania.UI
|
||||
|
||||
AutoSizeAxes = Axes.X;
|
||||
|
||||
Masking = true;
|
||||
|
||||
InternalChild = columns = new FillFlowContainer<Container>
|
||||
{
|
||||
RelativeSizeAxes = Axes.Y,
|
||||
|
@ -13,6 +13,7 @@ using osu.Game.Rulesets.Judgements;
|
||||
using osu.Game.Rulesets.Mania.Beatmaps;
|
||||
using osu.Game.Rulesets.Mania.Objects;
|
||||
using osu.Game.Rulesets.Mania.Objects.Drawables;
|
||||
using osu.Game.Rulesets.Mania.Skinning;
|
||||
using osu.Game.Rulesets.Mania.UI.Components;
|
||||
using osu.Game.Rulesets.Objects;
|
||||
using osu.Game.Rulesets.Objects.Drawables;
|
||||
@ -130,6 +131,37 @@ namespace osu.Game.Rulesets.Mania.UI
|
||||
}
|
||||
}
|
||||
|
||||
private ISkinSource currentSkin;
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(ISkinSource skin)
|
||||
{
|
||||
currentSkin = skin;
|
||||
|
||||
skin.SourceChanged += onSkinChanged;
|
||||
onSkinChanged();
|
||||
}
|
||||
|
||||
private void onSkinChanged()
|
||||
{
|
||||
float paddingTop = currentSkin.GetConfig<ManiaSkinConfigurationLookup, float>(new ManiaSkinConfigurationLookup(LegacyManiaSkinConfigurationLookups.StagePaddingTop))?.Value ?? 0;
|
||||
float paddingBottom = currentSkin.GetConfig<ManiaSkinConfigurationLookup, float>(new ManiaSkinConfigurationLookup(LegacyManiaSkinConfigurationLookups.StagePaddingBottom))?.Value ?? 0;
|
||||
|
||||
Padding = new MarginPadding
|
||||
{
|
||||
Top = paddingTop,
|
||||
Bottom = paddingBottom,
|
||||
};
|
||||
}
|
||||
|
||||
protected override void Dispose(bool isDisposing)
|
||||
{
|
||||
base.Dispose(isDisposing);
|
||||
|
||||
if (currentSkin != null)
|
||||
currentSkin.SourceChanged -= onSkinChanged;
|
||||
}
|
||||
|
||||
protected override void LoadComplete()
|
||||
{
|
||||
base.LoadComplete();
|
||||
|
@ -120,7 +120,7 @@ namespace osu.Game.Configuration
|
||||
// Gameplay
|
||||
SetDefault(OsuSetting.PositionalHitsounds, true); // replaced by level setting below, can be removed 20220703.
|
||||
SetDefault(OsuSetting.PositionalHitsoundsLevel, 0.2f, 0, 1);
|
||||
SetDefault(OsuSetting.DimLevel, 0.8, 0, 1, 0.01);
|
||||
SetDefault(OsuSetting.DimLevel, 0.7, 0, 1, 0.01);
|
||||
SetDefault(OsuSetting.BlurLevel, 0, 0, 1, 0.01);
|
||||
SetDefault(OsuSetting.LightenDuringBreaks, true);
|
||||
|
||||
|
@ -124,7 +124,7 @@ namespace osu.Game.Screens.Play.HUD
|
||||
float fadeBottom = scroll.Current + scroll.DrawHeight;
|
||||
float fadeTop = scroll.Current + panel_height;
|
||||
|
||||
if (scroll.Current <= 0) fadeTop -= panel_height;
|
||||
if (scroll.IsScrolledToStart()) fadeTop -= panel_height;
|
||||
if (!scroll.IsScrolledToEnd()) fadeBottom -= panel_height;
|
||||
|
||||
// logic is mostly shared with Leaderboard, copied here for simplicity.
|
||||
|
@ -76,6 +76,7 @@ namespace osu.Game.Screens.Play
|
||||
|
||||
req.Success += r =>
|
||||
{
|
||||
Logger.Log($"Score submission token retrieved ({r.ID})");
|
||||
token = r.ID;
|
||||
tcs.SetResult(true);
|
||||
};
|
||||
@ -91,6 +92,11 @@ namespace osu.Game.Screens.Play
|
||||
|
||||
void handleTokenFailure(Exception exception)
|
||||
{
|
||||
// This method may be invoked multiple times due to the Task.Wait call above.
|
||||
// We only really care about the first error.
|
||||
if (!tcs.TrySetResult(false))
|
||||
return;
|
||||
|
||||
if (HandleTokenRetrievalFailure(exception))
|
||||
{
|
||||
if (string.IsNullOrEmpty(exception.Message))
|
||||
@ -104,8 +110,12 @@ namespace osu.Game.Screens.Play
|
||||
this.Exit();
|
||||
});
|
||||
}
|
||||
|
||||
tcs.SetResult(false);
|
||||
else
|
||||
{
|
||||
// Gameplay is allowed to continue, but we still should keep track of the error.
|
||||
// In the future, this should be visible to the user in some way.
|
||||
Logger.Log($"Score submission token retrieval failed ({exception.Message})");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -42,6 +42,8 @@ namespace osu.Game.Skinning
|
||||
HitPosition,
|
||||
ScorePosition,
|
||||
LightPosition,
|
||||
StagePaddingTop,
|
||||
StagePaddingBottom,
|
||||
HitTargetImage,
|
||||
ShowJudgementLine,
|
||||
KeyImage,
|
||||
|
Loading…
Reference in New Issue
Block a user