mirror of
https://github.com/ppy/osu.git
synced 2024-11-11 13:37:25 +08:00
Implement legacy slider body for classic skins (#7243)
Implement legacy slider body for classic skins Co-authored-by: Dean Herbert <pe@ppy.sh>
This commit is contained in:
commit
726abaddc3
@ -11,6 +11,7 @@ using osu.Game.Configuration;
|
||||
using osu.Game.Rulesets.Mods;
|
||||
using osu.Game.Rulesets.Objects.Drawables;
|
||||
using osu.Game.Rulesets.Osu.Objects.Drawables;
|
||||
using osu.Game.Rulesets.Osu.Objects.Drawables.Pieces;
|
||||
|
||||
namespace osu.Game.Rulesets.Osu.Mods
|
||||
{
|
||||
@ -54,13 +55,8 @@ namespace osu.Game.Rulesets.Osu.Mods
|
||||
break;
|
||||
|
||||
case DrawableSlider slider:
|
||||
slider.AccentColour.BindValueChanged(_ =>
|
||||
{
|
||||
//will trigger on skin change.
|
||||
slider.Body.AccentColour = slider.AccentColour.Value.Opacity(0);
|
||||
slider.Body.BorderColour = slider.AccentColour.Value;
|
||||
}, true);
|
||||
|
||||
slider.Body.OnSkinChanged += () => applySliderState(slider);
|
||||
applySliderState(slider);
|
||||
break;
|
||||
|
||||
case DrawableSpinner spinner:
|
||||
@ -69,5 +65,11 @@ namespace osu.Game.Rulesets.Osu.Mods
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private void applySliderState(DrawableSlider slider)
|
||||
{
|
||||
((PlaySliderBody)slider.Body.Drawable).AccentColour = slider.AccentColour.Value.Opacity(0);
|
||||
((PlaySliderBody)slider.Body.Drawable).BorderColour = slider.AccentColour.Value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -9,6 +9,7 @@ using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Sprites;
|
||||
using osu.Framework.MathUtils;
|
||||
using osu.Game.Rulesets.Objects.Drawables;
|
||||
using osu.Game.Rulesets.Osu.Objects.Drawables.Pieces;
|
||||
using osu.Game.Rulesets.Scoring;
|
||||
using osuTK;
|
||||
using osu.Game.Skinning;
|
||||
@ -98,7 +99,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
|
||||
public void UpdateSnakingPosition(Vector2 start, Vector2 end)
|
||||
{
|
||||
bool isRepeatAtEnd = repeatPoint.RepeatIndex % 2 == 0;
|
||||
List<Vector2> curve = drawableSlider.Body.CurrentCurve;
|
||||
List<Vector2> curve = ((PlaySliderBody)drawableSlider.Body.Drawable).CurrentCurve;
|
||||
|
||||
Position = isRepeatAtEnd ? end : start;
|
||||
|
||||
|
@ -11,7 +11,6 @@ using osu.Framework.Allocation;
|
||||
using osu.Framework.Bindables;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Game.Rulesets.Objects;
|
||||
using osu.Game.Rulesets.Osu.Configuration;
|
||||
using osu.Game.Rulesets.Osu.Skinning;
|
||||
using osu.Game.Rulesets.Scoring;
|
||||
using osuTK.Graphics;
|
||||
@ -24,8 +23,10 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
|
||||
public DrawableSliderHead HeadCircle => headContainer.Child;
|
||||
public DrawableSliderTail TailCircle => tailContainer.Child;
|
||||
|
||||
public readonly SnakingSliderBody Body;
|
||||
public readonly SliderBall Ball;
|
||||
public readonly SkinnableDrawable Body;
|
||||
|
||||
private PlaySliderBody sliderBody => Body.Drawable as PlaySliderBody;
|
||||
|
||||
private readonly Container<DrawableSliderHead> headContainer;
|
||||
private readonly Container<DrawableSliderTail> tailContainer;
|
||||
@ -37,10 +38,6 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
|
||||
private readonly IBindable<Vector2> positionBindable = new Bindable<Vector2>();
|
||||
private readonly IBindable<int> stackHeightBindable = new Bindable<int>();
|
||||
private readonly IBindable<float> scaleBindable = new Bindable<float>();
|
||||
private readonly IBindable<int> pathVersion = new Bindable<int>();
|
||||
|
||||
[Resolved(CanBeNull = true)]
|
||||
private OsuRulesetConfigManager config { get; set; }
|
||||
|
||||
public DrawableSlider(Slider s)
|
||||
: base(s)
|
||||
@ -51,7 +48,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
|
||||
|
||||
InternalChildren = new Drawable[]
|
||||
{
|
||||
Body = new SnakingSliderBody(s),
|
||||
Body = new SkinnableDrawable(new OsuSkinComponent(OsuSkinComponents.SliderBody), _ => new DefaultSliderBody(), confineMode: ConfineMode.NoScaling),
|
||||
tickContainer = new Container<DrawableSliderTick> { RelativeSizeAxes = Axes.Both },
|
||||
repeatContainer = new Container<DrawableRepeatPoint> { RelativeSizeAxes = Axes.Both },
|
||||
Ball = new SliderBall(s, this)
|
||||
@ -70,28 +67,16 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
|
||||
[BackgroundDependencyLoader]
|
||||
private void load()
|
||||
{
|
||||
config?.BindWith(OsuRulesetSetting.SnakingInSliders, Body.SnakingIn);
|
||||
config?.BindWith(OsuRulesetSetting.SnakingOutSliders, Body.SnakingOut);
|
||||
|
||||
positionBindable.BindValueChanged(_ => Position = HitObject.StackedPosition);
|
||||
stackHeightBindable.BindValueChanged(_ => Position = HitObject.StackedPosition);
|
||||
scaleBindable.BindValueChanged(scale =>
|
||||
{
|
||||
updatePathRadius();
|
||||
Ball.Scale = new Vector2(scale.NewValue);
|
||||
});
|
||||
scaleBindable.BindValueChanged(scale => Ball.Scale = new Vector2(scale.NewValue));
|
||||
|
||||
positionBindable.BindTo(HitObject.PositionBindable);
|
||||
stackHeightBindable.BindTo(HitObject.StackHeightBindable);
|
||||
scaleBindable.BindTo(HitObject.ScaleBindable);
|
||||
pathVersion.BindTo(slider.Path.Version);
|
||||
|
||||
pathVersion.BindValueChanged(_ => Body.Refresh());
|
||||
|
||||
AccentColour.BindValueChanged(colour =>
|
||||
{
|
||||
Body.AccentColour = colour.NewValue;
|
||||
|
||||
foreach (var drawableHitObject in NestedHitObjects)
|
||||
drawableHitObject.AccentColour.Value = colour.NewValue;
|
||||
}, true);
|
||||
@ -169,16 +154,16 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
|
||||
double completionProgress = Math.Clamp((Time.Current - slider.StartTime) / slider.Duration, 0, 1);
|
||||
|
||||
Ball.UpdateProgress(completionProgress);
|
||||
Body.UpdateProgress(completionProgress);
|
||||
sliderBody?.UpdateProgress(completionProgress);
|
||||
|
||||
foreach (DrawableHitObject hitObject in NestedHitObjects)
|
||||
{
|
||||
if (hitObject is ITrackSnaking s) s.UpdateSnakingPosition(slider.Path.PositionAt(Body.SnakedStart ?? 0), slider.Path.PositionAt(Body.SnakedEnd ?? 0));
|
||||
if (hitObject is ITrackSnaking s) s.UpdateSnakingPosition(slider.Path.PositionAt(sliderBody?.SnakedStart ?? 0), slider.Path.PositionAt(sliderBody?.SnakedEnd ?? 0));
|
||||
if (hitObject is IRequireTracking t) t.Tracking = Ball.Tracking;
|
||||
}
|
||||
|
||||
Size = Body.Size;
|
||||
OriginPosition = Body.PathOffset;
|
||||
Size = sliderBody?.Size ?? Vector2.Zero;
|
||||
OriginPosition = sliderBody?.PathOffset ?? Vector2.Zero;
|
||||
|
||||
if (DrawSize != Vector2.Zero)
|
||||
{
|
||||
@ -192,28 +177,17 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
|
||||
public override void OnKilled()
|
||||
{
|
||||
base.OnKilled();
|
||||
Body.RecyclePath();
|
||||
sliderBody?.RecyclePath();
|
||||
}
|
||||
|
||||
private float sliderPathRadius;
|
||||
|
||||
protected override void ApplySkin(ISkinSource skin, bool allowFallback)
|
||||
{
|
||||
base.ApplySkin(skin, allowFallback);
|
||||
|
||||
Body.BorderSize = skin.GetConfig<OsuSkinConfiguration, float>(OsuSkinConfiguration.SliderBorderSize)?.Value ?? SliderBody.DEFAULT_BORDER_SIZE;
|
||||
sliderPathRadius = skin.GetConfig<OsuSkinConfiguration, float>(OsuSkinConfiguration.SliderPathRadius)?.Value ?? OsuHitObject.OBJECT_RADIUS;
|
||||
updatePathRadius();
|
||||
|
||||
Body.AccentColour = skin.GetConfig<OsuSkinColour, Color4>(OsuSkinColour.SliderTrackOverride)?.Value ?? AccentColour.Value;
|
||||
Body.BorderColour = skin.GetConfig<OsuSkinColour, Color4>(OsuSkinColour.SliderBorder)?.Value ?? Color4.White;
|
||||
|
||||
bool allowBallTint = skin.GetConfig<OsuSkinConfiguration, bool>(OsuSkinConfiguration.AllowSliderBallTint)?.Value ?? false;
|
||||
Ball.Colour = allowBallTint ? AccentColour.Value : Color4.White;
|
||||
}
|
||||
|
||||
private void updatePathRadius() => Body.PathRadius = slider.Scale * sliderPathRadius;
|
||||
|
||||
protected override void CheckForResult(bool userTriggered, double timeOffset)
|
||||
{
|
||||
if (userTriggered || Time.Current < slider.EndTime)
|
||||
@ -264,6 +238,10 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
|
||||
|
||||
public Drawable ProxiedLayer => HeadCircle.ProxiedLayer;
|
||||
|
||||
public override bool ReceivePositionalInputAt(Vector2 screenSpacePos) => Body.ReceivePositionalInputAt(screenSpacePos);
|
||||
public override bool ReceivePositionalInputAt(Vector2 screenSpacePos) => sliderBody?.ReceivePositionalInputAt(screenSpacePos) ?? base.ReceivePositionalInputAt(screenSpacePos);
|
||||
|
||||
private class DefaultSliderBody : PlaySliderBody
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,70 @@
|
||||
// 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.Lines;
|
||||
using osuTK.Graphics;
|
||||
|
||||
namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces
|
||||
{
|
||||
public abstract class DrawableSliderPath : SmoothPath
|
||||
{
|
||||
protected const float BORDER_PORTION = 0.128f;
|
||||
protected const float GRADIENT_PORTION = 1 - BORDER_PORTION;
|
||||
|
||||
private const float border_max_size = 8f;
|
||||
private const float border_min_size = 0f;
|
||||
|
||||
private Color4 borderColour = Color4.White;
|
||||
|
||||
public Color4 BorderColour
|
||||
{
|
||||
get => borderColour;
|
||||
set
|
||||
{
|
||||
if (borderColour == value)
|
||||
return;
|
||||
|
||||
borderColour = value;
|
||||
|
||||
InvalidateTexture();
|
||||
}
|
||||
}
|
||||
|
||||
private Color4 accentColour = Color4.White;
|
||||
|
||||
public Color4 AccentColour
|
||||
{
|
||||
get => accentColour;
|
||||
set
|
||||
{
|
||||
if (accentColour == value)
|
||||
return;
|
||||
|
||||
accentColour = value;
|
||||
|
||||
InvalidateTexture();
|
||||
}
|
||||
}
|
||||
|
||||
private float borderSize = 1;
|
||||
|
||||
public float BorderSize
|
||||
{
|
||||
get => borderSize;
|
||||
set
|
||||
{
|
||||
if (borderSize == value)
|
||||
return;
|
||||
|
||||
if (value < border_min_size || value > border_max_size)
|
||||
return;
|
||||
|
||||
borderSize = value;
|
||||
|
||||
InvalidateTexture();
|
||||
}
|
||||
}
|
||||
|
||||
protected float CalculatedBorderPortion => BorderSize * BORDER_PORTION;
|
||||
}
|
||||
}
|
@ -0,0 +1,57 @@
|
||||
// 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.Game.Rulesets.Objects.Drawables;
|
||||
using osu.Game.Rulesets.Osu.Configuration;
|
||||
using osu.Game.Rulesets.Osu.Skinning;
|
||||
using osu.Game.Skinning;
|
||||
using osuTK.Graphics;
|
||||
|
||||
namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces
|
||||
{
|
||||
public abstract class PlaySliderBody : SnakingSliderBody
|
||||
{
|
||||
private IBindable<float> scaleBindable;
|
||||
private IBindable<int> pathVersion;
|
||||
private IBindable<Color4> accentColour;
|
||||
|
||||
[Resolved]
|
||||
private DrawableHitObject drawableObject { get; set; }
|
||||
|
||||
[Resolved(CanBeNull = true)]
|
||||
private OsuRulesetConfigManager config { get; set; }
|
||||
|
||||
private Slider slider;
|
||||
private float defaultPathRadius;
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(ISkinSource skin)
|
||||
{
|
||||
slider = (Slider)drawableObject.HitObject;
|
||||
defaultPathRadius = skin.GetConfig<OsuSkinConfiguration, float>(OsuSkinConfiguration.SliderPathRadius)?.Value ?? OsuHitObject.OBJECT_RADIUS;
|
||||
|
||||
scaleBindable = slider.ScaleBindable.GetBoundCopy();
|
||||
scaleBindable.BindValueChanged(_ => updatePathRadius(), true);
|
||||
|
||||
pathVersion = slider.Path.Version.GetBoundCopy();
|
||||
pathVersion.BindValueChanged(_ => Refresh());
|
||||
|
||||
accentColour = drawableObject.AccentColour.GetBoundCopy();
|
||||
accentColour.BindValueChanged(accent => updateAccentColour(skin, accent.NewValue), true);
|
||||
|
||||
config?.BindWith(OsuRulesetSetting.SnakingInSliders, SnakingIn);
|
||||
config?.BindWith(OsuRulesetSetting.SnakingOutSliders, SnakingOut);
|
||||
|
||||
BorderSize = skin.GetConfig<OsuSkinConfiguration, float>(OsuSkinConfiguration.SliderBorderSize)?.Value ?? 1;
|
||||
BorderColour = skin.GetConfig<OsuSkinColour, Color4>(OsuSkinColour.SliderBorder)?.Value ?? Color4.White;
|
||||
}
|
||||
|
||||
private void updatePathRadius()
|
||||
=> PathRadius = defaultPathRadius * scaleBindable.Value;
|
||||
|
||||
private void updateAccentColour(ISkinSource skin, Color4 defaultAccentColour)
|
||||
=> AccentColour = skin.GetConfig<OsuSkinColour, Color4>(OsuSkinColour.SliderTrackOverride)?.Value ?? defaultAccentColour;
|
||||
}
|
||||
}
|
@ -3,6 +3,7 @@
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics.Lines;
|
||||
using osuTK;
|
||||
@ -12,9 +13,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces
|
||||
{
|
||||
public abstract class SliderBody : CompositeDrawable
|
||||
{
|
||||
public const float DEFAULT_BORDER_SIZE = 1;
|
||||
|
||||
private SliderPath path;
|
||||
private DrawableSliderPath path;
|
||||
|
||||
protected Path Path => path;
|
||||
|
||||
@ -80,19 +79,19 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initialises a new <see cref="SliderPath"/>, releasing all resources retained by the old one.
|
||||
/// Initialises a new <see cref="DrawableSliderPath"/>, releasing all resources retained by the old one.
|
||||
/// </summary>
|
||||
public virtual void RecyclePath()
|
||||
{
|
||||
InternalChild = path = new SliderPath
|
||||
InternalChild = path = CreateSliderPath().With(p =>
|
||||
{
|
||||
Position = path?.Position ?? Vector2.Zero,
|
||||
PathRadius = path?.PathRadius ?? 10,
|
||||
AccentColour = path?.AccentColour ?? Color4.White,
|
||||
BorderColour = path?.BorderColour ?? Color4.White,
|
||||
BorderSize = path?.BorderSize ?? DEFAULT_BORDER_SIZE,
|
||||
Vertices = path?.Vertices ?? Array.Empty<Vector2>()
|
||||
};
|
||||
p.Position = path?.Position ?? Vector2.Zero;
|
||||
p.PathRadius = path?.PathRadius ?? 10;
|
||||
p.AccentColour = path?.AccentColour ?? Color4.White;
|
||||
p.BorderColour = path?.BorderColour ?? Color4.White;
|
||||
p.BorderSize = path?.BorderSize ?? 1;
|
||||
p.Vertices = path?.Vertices ?? Array.Empty<Vector2>();
|
||||
});
|
||||
}
|
||||
|
||||
public override bool ReceivePositionalInputAt(Vector2 screenSpacePos) => path.ReceivePositionalInputAt(screenSpacePos);
|
||||
@ -103,77 +102,20 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces
|
||||
/// <param name="vertices">The vertices</param>
|
||||
protected void SetVertices(IReadOnlyList<Vector2> vertices) => path.Vertices = vertices;
|
||||
|
||||
private class SliderPath : SmoothPath
|
||||
protected virtual DrawableSliderPath CreateSliderPath() => new DefaultDrawableSliderPath();
|
||||
|
||||
private class DefaultDrawableSliderPath : DrawableSliderPath
|
||||
{
|
||||
private const float border_max_size = 8f;
|
||||
private const float border_min_size = 0f;
|
||||
|
||||
private const float border_portion = 0.128f;
|
||||
private const float gradient_portion = 1 - border_portion;
|
||||
|
||||
private const float opacity_at_centre = 0.3f;
|
||||
private const float opacity_at_edge = 0.8f;
|
||||
|
||||
private Color4 borderColour = Color4.White;
|
||||
|
||||
public Color4 BorderColour
|
||||
{
|
||||
get => borderColour;
|
||||
set
|
||||
{
|
||||
if (borderColour == value)
|
||||
return;
|
||||
|
||||
borderColour = value;
|
||||
|
||||
InvalidateTexture();
|
||||
}
|
||||
}
|
||||
|
||||
private Color4 accentColour = Color4.White;
|
||||
|
||||
public Color4 AccentColour
|
||||
{
|
||||
get => accentColour;
|
||||
set
|
||||
{
|
||||
if (accentColour == value)
|
||||
return;
|
||||
|
||||
accentColour = value;
|
||||
|
||||
InvalidateTexture();
|
||||
}
|
||||
}
|
||||
|
||||
private float borderSize = DEFAULT_BORDER_SIZE;
|
||||
|
||||
public float BorderSize
|
||||
{
|
||||
get => borderSize;
|
||||
set
|
||||
{
|
||||
if (borderSize == value)
|
||||
return;
|
||||
|
||||
if (value < border_min_size || value > border_max_size)
|
||||
return;
|
||||
|
||||
borderSize = value;
|
||||
|
||||
InvalidateTexture();
|
||||
}
|
||||
}
|
||||
|
||||
private float calculatedBorderPortion => BorderSize * border_portion;
|
||||
|
||||
protected override Color4 ColourAt(float position)
|
||||
{
|
||||
if (calculatedBorderPortion != 0f && position <= calculatedBorderPortion)
|
||||
if (CalculatedBorderPortion != 0f && position <= CalculatedBorderPortion)
|
||||
return BorderColour;
|
||||
|
||||
position -= calculatedBorderPortion;
|
||||
return new Color4(AccentColour.R, AccentColour.G, AccentColour.B, (opacity_at_edge - (opacity_at_edge - opacity_at_centre) * position / gradient_portion) * AccentColour.A);
|
||||
position -= CalculatedBorderPortion;
|
||||
return new Color4(AccentColour.R, AccentColour.G, AccentColour.B, (opacity_at_edge - (opacity_at_edge - opacity_at_centre) * position / GRADIENT_PORTION) * AccentColour.A);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -6,6 +6,7 @@ using System.Collections.Generic;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Bindables;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Game.Rulesets.Objects.Drawables;
|
||||
using osu.Game.Rulesets.Objects.Types;
|
||||
using osuTK;
|
||||
|
||||
@ -50,16 +51,13 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces
|
||||
/// </summary>
|
||||
private Vector2 snakedPathOffset;
|
||||
|
||||
private readonly Slider slider;
|
||||
|
||||
public SnakingSliderBody(Slider slider)
|
||||
{
|
||||
this.slider = slider;
|
||||
}
|
||||
private Slider slider;
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load()
|
||||
private void load(DrawableHitObject drawableObject)
|
||||
{
|
||||
slider = (Slider)drawableObject.HitObject;
|
||||
|
||||
Refresh();
|
||||
}
|
||||
|
||||
|
@ -14,6 +14,7 @@ namespace osu.Game.Rulesets.Osu
|
||||
ReverseArrow,
|
||||
HitCircleText,
|
||||
SliderFollowCircle,
|
||||
SliderBall
|
||||
SliderBall,
|
||||
SliderBody,
|
||||
}
|
||||
}
|
||||
|
47
osu.Game.Rulesets.Osu/Skinning/LegacySliderBody.cs
Normal file
47
osu.Game.Rulesets.Osu/Skinning/LegacySliderBody.cs
Normal file
@ -0,0 +1,47 @@
|
||||
// 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.Extensions.Color4Extensions;
|
||||
using osu.Framework.MathUtils;
|
||||
using osu.Game.Rulesets.Osu.Objects.Drawables.Pieces;
|
||||
using osuTK.Graphics;
|
||||
|
||||
namespace osu.Game.Rulesets.Osu.Skinning
|
||||
{
|
||||
public class LegacySliderBody : PlaySliderBody
|
||||
{
|
||||
protected override DrawableSliderPath CreateSliderPath() => new LegacyDrawableSliderPath();
|
||||
|
||||
private class LegacyDrawableSliderPath : DrawableSliderPath
|
||||
{
|
||||
public new Color4 AccentColour => new Color4(base.AccentColour.R, base.AccentColour.G, base.AccentColour.B, base.AccentColour.A * 0.70f);
|
||||
|
||||
protected override Color4 ColourAt(float position)
|
||||
{
|
||||
if (CalculatedBorderPortion != 0f && position <= CalculatedBorderPortion)
|
||||
return BorderColour;
|
||||
|
||||
position -= BORDER_PORTION;
|
||||
|
||||
Color4 outerColour = AccentColour.Darken(0.1f);
|
||||
Color4 innerColour = lighten(AccentColour, 0.5f);
|
||||
|
||||
return Interpolation.ValueAt(position / GRADIENT_PORTION, outerColour, innerColour, 0, 1);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Lightens a colour in a way more friendly to dark or strong colours.
|
||||
/// </summary>
|
||||
private static Color4 lighten(Color4 color, float amount)
|
||||
{
|
||||
amount *= 0.5f;
|
||||
return new Color4(
|
||||
Math.Min(1, color.R * (1 + 0.5f * amount) + 1 * amount),
|
||||
Math.Min(1, color.G * (1 + 0.5f * amount) + 1 * amount),
|
||||
Math.Min(1, color.B * (1 + 0.5f * amount) + 1 * amount),
|
||||
color.A);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -73,6 +73,12 @@ namespace osu.Game.Rulesets.Osu.Skinning
|
||||
|
||||
return null;
|
||||
|
||||
case OsuSkinComponents.SliderBody:
|
||||
if (hasHitCircle.Value)
|
||||
return new LegacySliderBody();
|
||||
|
||||
return null;
|
||||
|
||||
case OsuSkinComponents.HitCircle:
|
||||
if (hasHitCircle.Value)
|
||||
return new LegacyMainCirclePiece();
|
||||
|
@ -12,6 +12,11 @@ namespace osu.Game.Skinning
|
||||
/// </summary>
|
||||
public abstract class SkinReloadableDrawable : CompositeDrawable
|
||||
{
|
||||
/// <summary>
|
||||
/// Invoked when <see cref="CurrentSkin"/> has changed.
|
||||
/// </summary>
|
||||
public event Action OnSkinChanged;
|
||||
|
||||
/// <summary>
|
||||
/// The current skin source.
|
||||
/// </summary>
|
||||
@ -43,12 +48,18 @@ namespace osu.Game.Skinning
|
||||
private void onChange() =>
|
||||
// schedule required to avoid calls after disposed.
|
||||
// note that this has the side-effect of components only performing a skin change when they are alive.
|
||||
Scheduler.AddOnce(() => SkinChanged(CurrentSkin, allowDefaultFallback));
|
||||
Scheduler.AddOnce(skinChanged);
|
||||
|
||||
protected override void LoadAsyncComplete()
|
||||
{
|
||||
base.LoadAsyncComplete();
|
||||
skinChanged();
|
||||
}
|
||||
|
||||
private void skinChanged()
|
||||
{
|
||||
SkinChanged(CurrentSkin, allowDefaultFallback);
|
||||
OnSkinChanged?.Invoke();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -66,6 +77,8 @@ namespace osu.Game.Skinning
|
||||
|
||||
if (CurrentSkin != null)
|
||||
CurrentSkin.SourceChanged -= onChange;
|
||||
|
||||
OnSkinChanged = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user