mirror of
https://github.com/ppy/osu.git
synced 2025-02-03 01:22:58 +08:00
Merge pull request #8524 from smoogipoo/mania-hold-note-skinning
Add mania hold note skinning
This commit is contained in:
commit
b41bf783d0
@ -7,12 +7,12 @@ using osu.Game.Rulesets.Mania.Objects.Drawables.Pieces;
|
|||||||
|
|
||||||
namespace osu.Game.Rulesets.Mania.Edit.Blueprints.Components
|
namespace osu.Game.Rulesets.Mania.Edit.Blueprints.Components
|
||||||
{
|
{
|
||||||
public class EditBodyPiece : BodyPiece
|
public class EditBodyPiece : DefaultBodyPiece
|
||||||
{
|
{
|
||||||
[BackgroundDependencyLoader]
|
[BackgroundDependencyLoader]
|
||||||
private void load(OsuColour colours)
|
private void load(OsuColour colours)
|
||||||
{
|
{
|
||||||
AccentColour = colours.Yellow;
|
AccentColour.Value = colours.Yellow;
|
||||||
|
|
||||||
Background.Alpha = 0.5f;
|
Background.Alpha = 0.5f;
|
||||||
Foreground.Alpha = 0;
|
Foreground.Alpha = 0;
|
||||||
|
@ -4,13 +4,13 @@
|
|||||||
using osu.Framework.Allocation;
|
using osu.Framework.Allocation;
|
||||||
using osu.Framework.Bindables;
|
using osu.Framework.Bindables;
|
||||||
using osu.Framework.Graphics;
|
using osu.Framework.Graphics;
|
||||||
|
using osu.Framework.Graphics.Containers;
|
||||||
using osu.Framework.Graphics.Primitives;
|
using osu.Framework.Graphics.Primitives;
|
||||||
|
using osu.Framework.Graphics.Shapes;
|
||||||
using osu.Game.Graphics;
|
using osu.Game.Graphics;
|
||||||
using osu.Game.Rulesets.Mania.Objects.Drawables;
|
using osu.Game.Rulesets.Mania.Objects.Drawables;
|
||||||
using osu.Game.Rulesets.Mania.Objects.Drawables.Pieces;
|
|
||||||
using osu.Game.Rulesets.UI.Scrolling;
|
using osu.Game.Rulesets.UI.Scrolling;
|
||||||
using osuTK;
|
using osuTK;
|
||||||
using osuTK.Graphics;
|
|
||||||
|
|
||||||
namespace osu.Game.Rulesets.Mania.Edit.Blueprints
|
namespace osu.Game.Rulesets.Mania.Edit.Blueprints
|
||||||
{
|
{
|
||||||
@ -42,11 +42,18 @@ namespace osu.Game.Rulesets.Mania.Edit.Blueprints
|
|||||||
{
|
{
|
||||||
new HoldNoteNoteSelectionBlueprint(DrawableObject, HoldNotePosition.Start),
|
new HoldNoteNoteSelectionBlueprint(DrawableObject, HoldNotePosition.Start),
|
||||||
new HoldNoteNoteSelectionBlueprint(DrawableObject, HoldNotePosition.End),
|
new HoldNoteNoteSelectionBlueprint(DrawableObject, HoldNotePosition.End),
|
||||||
new BodyPiece
|
new Container
|
||||||
{
|
{
|
||||||
AccentColour = Color4.Transparent,
|
RelativeSizeAxes = Axes.Both,
|
||||||
BorderColour = colours.Yellow
|
BorderThickness = 1,
|
||||||
},
|
BorderColour = colours.Yellow,
|
||||||
|
Child = new Box
|
||||||
|
{
|
||||||
|
RelativeSizeAxes = Axes.Both,
|
||||||
|
Alpha = 0,
|
||||||
|
AlwaysPresent = true,
|
||||||
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -25,5 +25,6 @@ namespace osu.Game.Rulesets.Mania
|
|||||||
Note,
|
Note,
|
||||||
HoldNoteHead,
|
HoldNoteHead,
|
||||||
HoldNoteTail,
|
HoldNoteTail,
|
||||||
|
HoldNoteBody,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -10,6 +10,7 @@ using osu.Game.Rulesets.Objects;
|
|||||||
using osu.Game.Rulesets.Objects.Drawables;
|
using osu.Game.Rulesets.Objects.Drawables;
|
||||||
using osu.Game.Rulesets.Scoring;
|
using osu.Game.Rulesets.Scoring;
|
||||||
using osu.Game.Rulesets.UI.Scrolling;
|
using osu.Game.Rulesets.UI.Scrolling;
|
||||||
|
using osu.Game.Skinning;
|
||||||
|
|
||||||
namespace osu.Game.Rulesets.Mania.Objects.Drawables
|
namespace osu.Game.Rulesets.Mania.Objects.Drawables
|
||||||
{
|
{
|
||||||
@ -20,6 +21,10 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables
|
|||||||
{
|
{
|
||||||
public override bool DisplayResult => false;
|
public override bool DisplayResult => false;
|
||||||
|
|
||||||
|
public IBindable<bool> IsHitting => isHitting;
|
||||||
|
|
||||||
|
private readonly Bindable<bool> isHitting = new Bindable<bool>();
|
||||||
|
|
||||||
public DrawableHoldNoteHead Head => headContainer.Child;
|
public DrawableHoldNoteHead Head => headContainer.Child;
|
||||||
public DrawableHoldNoteTail Tail => tailContainer.Child;
|
public DrawableHoldNoteTail Tail => tailContainer.Child;
|
||||||
|
|
||||||
@ -27,7 +32,7 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables
|
|||||||
private readonly Container<DrawableHoldNoteTail> tailContainer;
|
private readonly Container<DrawableHoldNoteTail> tailContainer;
|
||||||
private readonly Container<DrawableHoldNoteTick> tickContainer;
|
private readonly Container<DrawableHoldNoteTick> tickContainer;
|
||||||
|
|
||||||
private readonly BodyPiece bodyPiece;
|
private readonly Drawable bodyPiece;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Time at which the user started holding this hold note. Null if the user is not holding this hold note.
|
/// Time at which the user started holding this hold note. Null if the user is not holding this hold note.
|
||||||
@ -44,18 +49,16 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables
|
|||||||
{
|
{
|
||||||
RelativeSizeAxes = Axes.X;
|
RelativeSizeAxes = Axes.X;
|
||||||
|
|
||||||
AddRangeInternal(new Drawable[]
|
AddRangeInternal(new[]
|
||||||
{
|
{
|
||||||
bodyPiece = new BodyPiece { RelativeSizeAxes = Axes.X },
|
bodyPiece = new SkinnableDrawable(new ManiaSkinComponent(ManiaSkinComponents.HoldNoteBody), _ => new DefaultBodyPiece())
|
||||||
|
{
|
||||||
|
RelativeSizeAxes = Axes.X
|
||||||
|
},
|
||||||
tickContainer = new Container<DrawableHoldNoteTick> { RelativeSizeAxes = Axes.Both },
|
tickContainer = new Container<DrawableHoldNoteTick> { RelativeSizeAxes = Axes.Both },
|
||||||
headContainer = new Container<DrawableHoldNoteHead> { RelativeSizeAxes = Axes.Both },
|
headContainer = new Container<DrawableHoldNoteHead> { RelativeSizeAxes = Axes.Both },
|
||||||
tailContainer = new Container<DrawableHoldNoteTail> { RelativeSizeAxes = Axes.Both },
|
tailContainer = new Container<DrawableHoldNoteTail> { RelativeSizeAxes = Axes.Both },
|
||||||
});
|
});
|
||||||
|
|
||||||
AccentColour.BindValueChanged(colour =>
|
|
||||||
{
|
|
||||||
bodyPiece.AccentColour = colour.NewValue;
|
|
||||||
}, true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void AddNestedHitObject(DrawableHitObject hitObject)
|
protected override void AddNestedHitObject(DrawableHitObject hitObject)
|
||||||
@ -168,7 +171,7 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
HoldStartTime = Time.Current;
|
HoldStartTime = Time.Current;
|
||||||
bodyPiece.Hitting = true;
|
isHitting.Value = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void OnReleased(ManiaAction action)
|
public void OnReleased(ManiaAction action)
|
||||||
@ -194,7 +197,7 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables
|
|||||||
private void endHold()
|
private void endHold()
|
||||||
{
|
{
|
||||||
HoldStartTime = null;
|
HoldStartTime = null;
|
||||||
bodyPiece.Hitting = false;
|
isHitting.Value = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,6 +2,9 @@
|
|||||||
// See the LICENCE file in the repository root for full licence text.
|
// See the LICENCE file in the repository root for full licence text.
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
|
using JetBrains.Annotations;
|
||||||
|
using osu.Framework.Allocation;
|
||||||
|
using osu.Framework.Bindables;
|
||||||
using osuTK.Graphics;
|
using osuTK.Graphics;
|
||||||
using osu.Framework.Extensions.Color4Extensions;
|
using osu.Framework.Extensions.Color4Extensions;
|
||||||
using osu.Framework.Graphics;
|
using osu.Framework.Graphics;
|
||||||
@ -9,26 +12,38 @@ using osu.Framework.Graphics.Containers;
|
|||||||
using osu.Framework.Graphics.Effects;
|
using osu.Framework.Graphics.Effects;
|
||||||
using osu.Framework.Graphics.Shapes;
|
using osu.Framework.Graphics.Shapes;
|
||||||
using osu.Framework.Layout;
|
using osu.Framework.Layout;
|
||||||
using osu.Game.Graphics;
|
using osu.Game.Rulesets.Objects.Drawables;
|
||||||
|
|
||||||
namespace osu.Game.Rulesets.Mania.Objects.Drawables.Pieces
|
namespace osu.Game.Rulesets.Mania.Objects.Drawables.Pieces
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Represents length-wise portion of a hold note.
|
/// Represents length-wise portion of a hold note.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class BodyPiece : Container, IHasAccentColour
|
public class DefaultBodyPiece : CompositeDrawable
|
||||||
{
|
{
|
||||||
private readonly Container subtractionLayer;
|
protected readonly Bindable<Color4> AccentColour = new Bindable<Color4>();
|
||||||
|
|
||||||
protected readonly Drawable Background;
|
private readonly LayoutValue subtractionCache = new LayoutValue(Invalidation.DrawSize);
|
||||||
protected readonly BufferedContainer Foreground;
|
private readonly IBindable<bool> isHitting = new Bindable<bool>();
|
||||||
private readonly BufferedContainer subtractionContainer;
|
|
||||||
|
|
||||||
public BodyPiece()
|
protected Drawable Background { get; private set; }
|
||||||
|
protected BufferedContainer Foreground { get; private set; }
|
||||||
|
|
||||||
|
private BufferedContainer subtractionContainer;
|
||||||
|
private Container subtractionLayer;
|
||||||
|
|
||||||
|
public DefaultBodyPiece()
|
||||||
{
|
{
|
||||||
|
RelativeSizeAxes = Axes.Both;
|
||||||
Blending = BlendingParameters.Additive;
|
Blending = BlendingParameters.Additive;
|
||||||
|
|
||||||
Children = new[]
|
AddLayout(subtractionCache);
|
||||||
|
}
|
||||||
|
|
||||||
|
[BackgroundDependencyLoader(true)]
|
||||||
|
private void load([CanBeNull] DrawableHitObject drawableObject)
|
||||||
|
{
|
||||||
|
InternalChildren = new[]
|
||||||
{
|
{
|
||||||
Background = new Box { RelativeSizeAxes = Axes.Both },
|
Background = new Box { RelativeSizeAxes = Axes.Both },
|
||||||
Foreground = new BufferedContainer
|
Foreground = new BufferedContainer
|
||||||
@ -66,43 +81,37 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables.Pieces
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
AddLayout(subtractionCache);
|
if (drawableObject != null)
|
||||||
}
|
|
||||||
|
|
||||||
protected override void LoadComplete()
|
|
||||||
{
|
{
|
||||||
base.LoadComplete();
|
var holdNote = (DrawableHoldNote)drawableObject;
|
||||||
|
|
||||||
updateAccentColour();
|
AccentColour.BindTo(drawableObject.AccentColour);
|
||||||
|
isHitting.BindTo(holdNote.IsHitting);
|
||||||
}
|
}
|
||||||
|
|
||||||
private Color4 accentColour;
|
AccentColour.BindValueChanged(onAccentChanged, true);
|
||||||
|
isHitting.BindValueChanged(_ => onAccentChanged(new ValueChangedEvent<Color4>(AccentColour.Value, AccentColour.Value)), true);
|
||||||
|
}
|
||||||
|
|
||||||
public Color4 AccentColour
|
private void onAccentChanged(ValueChangedEvent<Color4> accent)
|
||||||
{
|
{
|
||||||
get => accentColour;
|
Foreground.Colour = accent.NewValue.Opacity(0.5f);
|
||||||
set
|
Background.Colour = accent.NewValue.Opacity(0.7f);
|
||||||
|
|
||||||
|
const float animation_length = 50;
|
||||||
|
|
||||||
|
Foreground.ClearTransforms(false, nameof(Foreground.Colour));
|
||||||
|
|
||||||
|
if (isHitting.Value)
|
||||||
{
|
{
|
||||||
if (accentColour == value)
|
// wait for the next sync point
|
||||||
return;
|
double synchronisedOffset = animation_length * 2 - Time.Current % (animation_length * 2);
|
||||||
|
using (Foreground.BeginDelayedSequence(synchronisedOffset))
|
||||||
accentColour = value;
|
Foreground.FadeColour(accent.NewValue.Lighten(0.2f), animation_length).Then().FadeColour(Foreground.Colour, animation_length).Loop();
|
||||||
|
|
||||||
updateAccentColour();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool Hitting
|
subtractionCache.Invalidate();
|
||||||
{
|
|
||||||
get => hitting;
|
|
||||||
set
|
|
||||||
{
|
|
||||||
hitting = value;
|
|
||||||
updateAccentColour();
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
private readonly LayoutValue subtractionCache = new LayoutValue(Invalidation.DrawSize);
|
|
||||||
|
|
||||||
protected override void Update()
|
protected override void Update()
|
||||||
{
|
{
|
||||||
@ -125,30 +134,5 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables.Pieces
|
|||||||
subtractionCache.Validate();
|
subtractionCache.Validate();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool hitting;
|
|
||||||
|
|
||||||
private void updateAccentColour()
|
|
||||||
{
|
|
||||||
if (!IsLoaded)
|
|
||||||
return;
|
|
||||||
|
|
||||||
Foreground.Colour = AccentColour.Opacity(0.5f);
|
|
||||||
Background.Colour = AccentColour.Opacity(0.7f);
|
|
||||||
|
|
||||||
const float animation_length = 50;
|
|
||||||
|
|
||||||
Foreground.ClearTransforms(false, nameof(Foreground.Colour));
|
|
||||||
|
|
||||||
if (hitting)
|
|
||||||
{
|
|
||||||
// wait for the next sync point
|
|
||||||
double synchronisedOffset = animation_length * 2 - Time.Current % (animation_length * 2);
|
|
||||||
using (Foreground.BeginDelayedSequence(synchronisedOffset))
|
|
||||||
Foreground.FadeColour(AccentColour.Lighten(0.2f), animation_length).Then().FadeColour(Foreground.Colour, animation_length).Loop();
|
|
||||||
}
|
|
||||||
|
|
||||||
subtractionCache.Invalidate();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
93
osu.Game.Rulesets.Mania/Skinning/LegacyBodyPiece.cs
Normal file
93
osu.Game.Rulesets.Mania/Skinning/LegacyBodyPiece.cs
Normal file
@ -0,0 +1,93 @@
|
|||||||
|
// 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.Animations;
|
||||||
|
using osu.Game.Rulesets.Mania.Objects.Drawables;
|
||||||
|
using osu.Game.Rulesets.Mania.UI;
|
||||||
|
using osu.Game.Rulesets.Objects.Drawables;
|
||||||
|
using osu.Game.Rulesets.UI.Scrolling;
|
||||||
|
using osu.Game.Skinning;
|
||||||
|
using osuTK;
|
||||||
|
|
||||||
|
namespace osu.Game.Rulesets.Mania.Skinning
|
||||||
|
{
|
||||||
|
public class LegacyBodyPiece : LegacyManiaColumnElement
|
||||||
|
{
|
||||||
|
private readonly IBindable<ScrollingDirection> direction = new Bindable<ScrollingDirection>();
|
||||||
|
private readonly IBindable<bool> isHitting = new Bindable<bool>();
|
||||||
|
|
||||||
|
private Drawable sprite;
|
||||||
|
|
||||||
|
[Resolved(CanBeNull = true)]
|
||||||
|
private ManiaStage stage { get; set; }
|
||||||
|
|
||||||
|
[Resolved]
|
||||||
|
private Column column { get; set; }
|
||||||
|
|
||||||
|
public LegacyBodyPiece()
|
||||||
|
{
|
||||||
|
RelativeSizeAxes = Axes.Both;
|
||||||
|
}
|
||||||
|
|
||||||
|
[BackgroundDependencyLoader]
|
||||||
|
private void load(ISkinSource skin, IScrollingInfo scrollingInfo, DrawableHitObject drawableObject)
|
||||||
|
{
|
||||||
|
string imageName = skin.GetConfig<LegacyManiaSkinConfigurationLookup, string>(
|
||||||
|
new LegacyManiaSkinConfigurationLookup(stage?.Columns.Count ?? 4, LegacyManiaSkinConfigurationLookups.HoldNoteBodyImage, column.Index))?.Value
|
||||||
|
?? $"mania-note{FallbackColumnIndex}L";
|
||||||
|
|
||||||
|
sprite = skin.GetAnimation(imageName, true, true).With(d =>
|
||||||
|
{
|
||||||
|
if (d == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (d is TextureAnimation animation)
|
||||||
|
animation.IsPlaying = false;
|
||||||
|
|
||||||
|
d.Anchor = Anchor.TopCentre;
|
||||||
|
d.RelativeSizeAxes = Axes.Both;
|
||||||
|
d.Size = Vector2.One;
|
||||||
|
d.FillMode = FillMode.Stretch;
|
||||||
|
// Todo: Wrap
|
||||||
|
});
|
||||||
|
|
||||||
|
if (sprite != null)
|
||||||
|
InternalChild = sprite;
|
||||||
|
|
||||||
|
direction.BindTo(scrollingInfo.Direction);
|
||||||
|
direction.BindValueChanged(onDirectionChanged, true);
|
||||||
|
|
||||||
|
var holdNote = (DrawableHoldNote)drawableObject;
|
||||||
|
isHitting.BindTo(holdNote.IsHitting);
|
||||||
|
isHitting.BindValueChanged(onIsHittingChanged, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void onIsHittingChanged(ValueChangedEvent<bool> isHitting)
|
||||||
|
{
|
||||||
|
if (!(sprite is TextureAnimation animation))
|
||||||
|
return;
|
||||||
|
|
||||||
|
animation.IsPlaying = isHitting.NewValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void onDirectionChanged(ValueChangedEvent<ScrollingDirection> direction)
|
||||||
|
{
|
||||||
|
if (sprite == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (direction.NewValue == ScrollingDirection.Up)
|
||||||
|
{
|
||||||
|
sprite.Origin = Anchor.BottomCentre;
|
||||||
|
sprite.Scale = new Vector2(1, -1);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
sprite.Origin = Anchor.TopCentre;
|
||||||
|
sprite.Scale = Vector2.One;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -61,6 +61,9 @@ namespace osu.Game.Rulesets.Mania.Skinning
|
|||||||
|
|
||||||
case ManiaSkinComponents.HoldNoteTail:
|
case ManiaSkinComponents.HoldNoteTail:
|
||||||
return new LegacyHoldNoteTailPiece();
|
return new LegacyHoldNoteTailPiece();
|
||||||
|
|
||||||
|
case ManiaSkinComponents.HoldNoteBody:
|
||||||
|
return new LegacyBodyPiece();
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
@ -29,6 +29,7 @@ namespace osu.Game.Skinning
|
|||||||
KeyImageDown,
|
KeyImageDown,
|
||||||
NoteImage,
|
NoteImage,
|
||||||
HoldNoteHeadImage,
|
HoldNoteHeadImage,
|
||||||
HoldNoteTailImage
|
HoldNoteTailImage,
|
||||||
|
HoldNoteBodyImage,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user