1
0
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:
Dan Balasescu 2022-10-07 20:45:56 +09:00
commit d63f196626
20 changed files with 852 additions and 51 deletions

View File

@ -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)

View File

@ -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;
}));
})
},

View File

@ -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;

View 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);
}
}
}

View 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);
}
}
}

View File

@ -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[]
{

View 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);
}
});
}
}
}

View File

@ -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);
}
}
}

View 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
};
}
}
}
}
}

View File

@ -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);

View 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);
}
}
}

View File

@ -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;
}
}
}

View File

@ -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));
}
}

View File

@ -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;
}

View File

@ -36,6 +36,8 @@ namespace osu.Game.Rulesets.Mania.UI
AutoSizeAxes = Axes.X;
Masking = true;
InternalChild = columns = new FillFlowContainer<Container>
{
RelativeSizeAxes = Axes.Y,

View File

@ -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();

View File

@ -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);

View File

@ -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.

View File

@ -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})");
}
}
}

View File

@ -42,6 +42,8 @@ namespace osu.Game.Skinning
HitPosition,
ScorePosition,
LightPosition,
StagePaddingTop,
StagePaddingBottom,
HitTargetImage,
ShowJudgementLine,
KeyImage,