1
0
mirror of https://github.com/ppy/osu.git synced 2024-12-15 08:22:56 +08:00
osu-lazer/osu.Game/Screens/Play/HUD/LegacyComboCounter.cs

273 lines
8.2 KiB
C#
Raw Normal View History

// 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.
2018-04-13 17:19:50 +08:00
2020-10-14 16:51:03 +08:00
using osu.Framework.Allocation;
using osu.Framework.Bindables;
2018-04-13 17:19:50 +08:00
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
2020-10-14 16:51:03 +08:00
using osu.Framework.Graphics.Sprites;
using osu.Game.Rulesets.Scoring;
2020-10-14 16:51:03 +08:00
using osu.Game.Skinning;
using osuTK;
2018-04-13 17:19:50 +08:00
namespace osu.Game.Screens.Play.HUD
{
/// <summary>
/// Uses the 'x' symbol and has a pop-out effect while rolling over.
/// </summary>
public class LegacyComboCounter : CompositeDrawable, ISkinnableDrawable
2018-04-13 17:19:50 +08:00
{
public Bindable<int> Current { get; } = new BindableInt { MinValue = 0 };
2018-04-13 17:19:50 +08:00
private uint scheduledPopOutCurrentId;
private const double pop_out_duration = 150;
private const double fade_out_duration = 100;
/// <summary>
/// Duration in milliseconds for the counter roll-up animation for each element.
/// </summary>
private const double rolling_duration = 20;
private readonly Drawable popOutCount;
private readonly Drawable displayedCountSpriteText;
2018-04-13 17:19:50 +08:00
private int previousValue;
private int displayedCount;
2018-04-13 17:19:50 +08:00
private bool isRolling;
[Resolved]
private ISkinSource skin { get; set; }
private readonly Container counterContainer;
2021-05-31 05:07:29 +08:00
/// <summary>
/// Hides the combo counter internally without affecting its <see cref="SkinnableInfo"/>.
2021-05-31 05:07:29 +08:00
/// </summary>
/// <remarks>
/// This is used for rulesets that provide their own combo counter and don't want this HUD one to be visible,
2021-05-31 05:07:29 +08:00
/// without potentially affecting the user's selected skin.
/// </remarks>
public bool HiddenByRulesetImplementation
{
set => counterContainer.Alpha = value ? 1 : 0;
}
public bool UsesFixedAnchor { get; set; }
public LegacyComboCounter()
{
AutoSizeAxes = Axes.Both;
Anchor = Anchor.BottomLeft;
Origin = Anchor.BottomLeft;
Margin = new MarginPadding(10);
2020-10-14 18:15:52 +08:00
Scale = new Vector2(1.2f);
InternalChild = counterContainer = new Container
{
AutoSizeAxes = Axes.Both,
AlwaysPresent = true,
Children = new[]
{
popOutCount = new LegacySpriteText(LegacyFont.Combo)
{
Alpha = 0,
Margin = new MarginPadding(0.05f),
Blending = BlendingParameters.Additive,
},
displayedCountSpriteText = new LegacySpriteText(LegacyFont.Combo)
{
Alpha = 0,
},
}
};
}
/// <summary>
/// Value shown at the current moment.
/// </summary>
public virtual int DisplayedCount
2020-10-14 16:51:03 +08:00
{
get => displayedCount;
private set
{
if (displayedCount.Equals(value))
return;
2020-10-14 16:51:03 +08:00
if (isRolling)
onDisplayedCountRolling(displayedCount, value);
else if (displayedCount + 1 == value)
onDisplayedCountIncrement(value);
else
onDisplayedCountChange(value);
displayedCount = value;
}
}
[BackgroundDependencyLoader]
private void load(ScoreProcessor scoreProcessor)
{
Current.BindTo(scoreProcessor.Combo);
2020-10-14 16:51:03 +08:00
}
2018-04-13 17:19:50 +08:00
protected override void LoadComplete()
{
base.LoadComplete();
((IHasText)displayedCountSpriteText).Text = formatCount(Current.Value);
counterContainer.Anchor = Anchor;
counterContainer.Origin = Origin;
displayedCountSpriteText.Anchor = Anchor;
displayedCountSpriteText.Origin = Origin;
popOutCount.Anchor = Anchor;
popOutCount.Origin = Origin;
2018-04-13 17:19:50 +08:00
Current.BindValueChanged(combo => updateCount(combo.NewValue == 0), true);
2018-04-13 17:19:50 +08:00
}
private void updateCount(bool rolling)
2018-04-13 17:19:50 +08:00
{
int prev = previousValue;
previousValue = Current.Value;
if (!IsLoaded)
return;
2018-04-13 17:19:50 +08:00
if (!rolling)
{
FinishTransforms(false, nameof(DisplayedCount));
isRolling = false;
DisplayedCount = prev;
2018-04-13 17:19:50 +08:00
if (prev + 1 == Current.Value)
onCountIncrement(prev, Current.Value);
else
onCountChange(prev, Current.Value);
}
else
{
onCountRolling(displayedCount, Current.Value);
isRolling = true;
}
2018-04-13 17:19:50 +08:00
}
private void transformPopOut(int newValue)
2018-04-13 17:19:50 +08:00
{
((IHasText)popOutCount).Text = formatCount(newValue);
popOutCount.ScaleTo(1.6f);
popOutCount.FadeTo(0.75f);
popOutCount.MoveTo(Vector2.Zero);
2021-07-05 23:52:39 +08:00
popOutCount.ScaleTo(1, pop_out_duration);
popOutCount.FadeOut(pop_out_duration);
popOutCount.MoveTo(displayedCountSpriteText.Position, pop_out_duration);
2018-04-13 17:19:50 +08:00
}
private void transformNoPopOut(int newValue)
2018-04-13 17:19:50 +08:00
{
((IHasText)displayedCountSpriteText).Text = formatCount(newValue);
displayedCountSpriteText.ScaleTo(1);
2018-04-13 17:19:50 +08:00
}
private void transformPopOutSmall(int newValue)
2018-04-13 17:19:50 +08:00
{
((IHasText)displayedCountSpriteText).Text = formatCount(newValue);
displayedCountSpriteText.ScaleTo(1.1f);
2021-07-05 23:52:39 +08:00
displayedCountSpriteText.ScaleTo(1, pop_out_duration);
2018-04-13 17:19:50 +08:00
}
private void scheduledPopOutSmall(uint id)
2018-04-13 17:19:50 +08:00
{
// Too late; scheduled task invalidated
if (id != scheduledPopOutCurrentId)
2018-04-13 17:19:50 +08:00
return;
DisplayedCount++;
}
private void onCountIncrement(int currentValue, int newValue)
2018-04-13 17:19:50 +08:00
{
scheduledPopOutCurrentId++;
2018-04-13 17:19:50 +08:00
if (DisplayedCount < currentValue)
DisplayedCount++;
displayedCountSpriteText.Show();
2018-04-13 17:19:50 +08:00
transformPopOut(newValue);
uint newTaskId = scheduledPopOutCurrentId;
2018-04-13 17:19:50 +08:00
Scheduler.AddDelayed(delegate
{
scheduledPopOutSmall(newTaskId);
}, pop_out_duration);
2018-04-13 17:19:50 +08:00
}
private void onCountRolling(int currentValue, int newValue)
2018-04-13 17:19:50 +08:00
{
scheduledPopOutCurrentId++;
2018-04-13 17:19:50 +08:00
// Hides displayed count if was increasing from 0 to 1 but didn't finish
if (currentValue == 0 && newValue == 0)
displayedCountSpriteText.FadeOut(fade_out_duration);
2018-04-13 17:19:50 +08:00
transformRoll(currentValue, newValue);
2018-04-13 17:19:50 +08:00
}
private void onCountChange(int currentValue, int newValue)
2018-04-13 17:19:50 +08:00
{
scheduledPopOutCurrentId++;
2018-04-13 17:19:50 +08:00
if (newValue == 0)
displayedCountSpriteText.FadeOut();
2018-04-13 17:19:50 +08:00
DisplayedCount = newValue;
2018-04-13 17:19:50 +08:00
}
private void onDisplayedCountRolling(int currentValue, int newValue)
2018-04-13 17:19:50 +08:00
{
if (newValue == 0)
displayedCountSpriteText.FadeOut(fade_out_duration);
else
displayedCountSpriteText.Show();
2018-04-13 17:19:50 +08:00
transformNoPopOut(newValue);
2018-04-13 17:19:50 +08:00
}
private void onDisplayedCountChange(int newValue)
2018-04-13 17:19:50 +08:00
{
displayedCountSpriteText.FadeTo(newValue == 0 ? 0 : 1);
transformNoPopOut(newValue);
2018-04-13 17:19:50 +08:00
}
private void onDisplayedCountIncrement(int newValue)
{
displayedCountSpriteText.Show();
transformPopOutSmall(newValue);
}
private void transformRoll(int currentValue, int newValue) =>
2021-07-05 23:52:39 +08:00
this.TransformTo(nameof(DisplayedCount), newValue, getProportionalDuration(currentValue, newValue));
private string formatCount(int count) => $@"{count}x";
private double getProportionalDuration(int currentValue, int newValue)
{
double difference = currentValue > newValue ? currentValue - newValue : newValue - currentValue;
return difference * rolling_duration;
}
2018-04-13 17:19:50 +08:00
}
}