1
0
mirror of https://github.com/ppy/osu.git synced 2024-11-12 01:07:25 +08:00
osu-lazer/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SliderBall.cs

189 lines
6.9 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
2019-01-21 09:57:14 +08:00
using System;
2018-04-13 17:19:50 +08:00
using System.Linq;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Shapes;
2018-10-02 11:02:47 +08:00
using osu.Framework.Input.Events;
2018-04-13 17:19:50 +08:00
using osu.Game.Rulesets.Objects.Types;
2018-11-20 15:51:59 +08:00
using osuTK.Graphics;
using osu.Game.Skinning;
2018-11-20 15:51:59 +08:00
using osuTK;
2018-04-13 17:19:50 +08:00
namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces
{
public class SliderBall : CircularContainer, ISliderProgress
{
private const float width = 128;
private Color4 accentColour = Color4.Black;
2018-07-31 15:13:52 +08:00
2019-01-21 09:57:14 +08:00
public Func<OsuAction?> GetInitialHitAction;
2018-04-13 17:19:50 +08:00
/// <summary>
/// The colour that is used for the slider ball.
/// </summary>
public Color4 AccentColour
{
get { return accentColour; }
set
{
accentColour = value;
if (drawableBall != null)
drawableBall.Colour = value;
2018-04-13 17:19:50 +08:00
}
}
private readonly Slider slider;
public readonly Drawable FollowCircle;
private Drawable drawableBall;
private readonly DrawableSlider drawableSlider;
2018-04-13 17:19:50 +08:00
public SliderBall(Slider slider, DrawableSlider drawableSlider = null)
2018-04-13 17:19:50 +08:00
{
this.drawableSlider = drawableSlider;
2018-04-13 17:19:50 +08:00
this.slider = slider;
Masking = true;
AutoSizeAxes = Axes.Both;
Blending = BlendingMode.Additive;
Origin = Anchor.Centre;
Children = new[]
2018-04-13 17:19:50 +08:00
{
FollowCircle = new Container
2018-04-13 17:19:50 +08:00
{
Origin = Anchor.Centre,
Anchor = Anchor.Centre,
Width = width,
Height = width,
Alpha = 0,
Child = new SkinnableDrawable("Play/osu/sliderfollowcircle", _ => new CircularContainer
{
RelativeSizeAxes = Axes.Both,
Masking = true,
BorderThickness = 5,
BorderColour = Color4.Orange,
Blending = BlendingMode.Additive,
Child = new Box
{
Colour = Color4.Orange,
RelativeSizeAxes = Axes.Both,
Alpha = 0.2f,
}
}),
2018-04-13 17:19:50 +08:00
},
new CircularContainer
{
Masking = true,
AutoSizeAxes = Axes.Both,
Origin = Anchor.Centre,
Anchor = Anchor.Centre,
Alpha = 1,
Child = new Container
2018-04-13 17:19:50 +08:00
{
Width = width,
Height = width,
// TODO: support skin filename animation (sliderb0, sliderb1...)
Child = new SkinnableDrawable("Play/osu/sliderb", _ => new CircularContainer
2018-04-13 17:19:50 +08:00
{
Masking = true,
RelativeSizeAxes = Axes.Both,
BorderThickness = 10,
BorderColour = Color4.White,
Alpha = 1,
Child = drawableBall = new Box
{
Colour = AccentColour,
RelativeSizeAxes = Axes.Both,
Alpha = 0.4f,
}
}),
2018-04-13 17:19:50 +08:00
}
}
};
}
private Vector2? lastScreenSpaceMousePosition;
2018-04-13 17:19:50 +08:00
2018-10-02 11:02:47 +08:00
protected override bool OnMouseDown(MouseDownEvent e)
2018-04-13 17:19:50 +08:00
{
lastScreenSpaceMousePosition = e.ScreenSpaceMousePosition;
2018-10-02 11:02:47 +08:00
return base.OnMouseDown(e);
2018-04-13 17:19:50 +08:00
}
2018-10-02 11:02:47 +08:00
protected override bool OnMouseUp(MouseUpEvent e)
2018-04-13 17:19:50 +08:00
{
lastScreenSpaceMousePosition = e.ScreenSpaceMousePosition;
2018-10-02 11:02:47 +08:00
return base.OnMouseUp(e);
2018-04-13 17:19:50 +08:00
}
2018-10-02 11:02:47 +08:00
protected override bool OnMouseMove(MouseMoveEvent e)
2018-04-13 17:19:50 +08:00
{
lastScreenSpaceMousePosition = e.ScreenSpaceMousePosition;
2018-10-02 11:02:47 +08:00
return base.OnMouseMove(e);
2018-04-13 17:19:50 +08:00
}
public override void ClearTransformsAfter(double time, bool propagateChildren = false, string targetMember = null)
{
// Consider the case of rewinding - children's transforms are handled internally, so propagating down
// any further will cause weirdness with the Tracking bool below. Let's not propagate further at this point.
base.ClearTransformsAfter(time, false, targetMember);
}
private bool tracking;
2018-07-31 15:13:52 +08:00
2018-04-13 17:19:50 +08:00
public bool Tracking
{
get { return tracking; }
private set
{
if (value == tracking)
return;
tracking = value;
FollowCircle.ScaleTo(tracking ? 2f : 1, 300, Easing.OutQuint);
FollowCircle.FadeTo(tracking ? 1f : 0, 300, Easing.OutQuint);
2018-04-13 17:19:50 +08:00
}
}
2019-01-21 09:57:14 +08:00
private bool canCurrentlyTrack => Time.Current >= slider.StartTime && Time.Current < slider.EndTime && lastScreenSpaceMousePosition.HasValue && base.ReceivePositionalInputAt(lastScreenSpaceMousePosition.Value);
/// <summary>
/// The point in time up to which we need to include the key which was used to press the head circle in tracking conditions.
/// </summary>
private double? initialHitConditionDismissed;
2018-04-13 17:19:50 +08:00
protected override void Update()
{
base.Update();
2019-01-21 09:57:14 +08:00
var initialHitAction = GetInitialHitAction();
if (initialHitAction == null)
initialHitConditionDismissed = null;
if (canCurrentlyTrack)
2018-04-13 17:19:50 +08:00
{
2019-01-21 09:57:14 +08:00
var pressed = drawableSlider?.OsuActionInputManager?.PressedActions;
2019-01-21 13:47:27 +08:00
if (initialHitAction != null && !pressed.Contains(initialHitAction == OsuAction.RightButton ? OsuAction.LeftButton : OsuAction.RightButton))
2019-01-21 09:57:14 +08:00
initialHitConditionDismissed = Time.Current;
// Make sure to use the base version of ReceivePositionalInputAt so that we correctly check the position.
2019-01-21 13:47:27 +08:00
Tracking = drawableSlider?.OsuActionInputManager?.PressedActions.Any(x => !initialHitAction.HasValue || (initialHitConditionDismissed.HasValue && initialHitConditionDismissed.Value < Time.Current) ? x == OsuAction.LeftButton || x == OsuAction.RightButton : x == initialHitAction) ?? false;
2019-01-21 09:57:14 +08:00
}
else
{
Tracking = false;
2018-04-13 17:19:50 +08:00
}
}
public void UpdateProgress(double completionProgress)
{
Position = slider.CurvePositionAt(completionProgress);
}
}
}