1
0
mirror of https://github.com/ppy/osu.git synced 2024-09-23 18:47:28 +08:00
osu-lazer/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNote.cs

201 lines
6.5 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-02-21 18:04:31 +08:00
using osu.Framework.Bindables;
2018-04-13 17:19:50 +08:00
using osu.Framework.Graphics;
using osu.Game.Rulesets.Mania.Objects.Drawables.Pieces;
using osu.Framework.Graphics.Containers;
using osu.Framework.Input.Bindings;
using osu.Game.Rulesets.Objects;
using osu.Game.Rulesets.Objects.Drawables;
2018-04-13 17:19:50 +08:00
using osu.Game.Rulesets.Scoring;
using osu.Game.Rulesets.UI.Scrolling;
2018-04-13 17:19:50 +08:00
namespace osu.Game.Rulesets.Mania.Objects.Drawables
{
/// <summary>
/// Visualises a <see cref="HoldNote"/> hit object.
/// </summary>
public class DrawableHoldNote : DrawableManiaHitObject<HoldNote>, IKeyBindingHandler<ManiaAction>
{
public override bool DisplayResult => false;
2019-12-23 16:48:48 +08:00
public DrawableHoldNoteHead Head => headContainer.Child;
public DrawableHoldNoteTail Tail => tailContainer.Child;
private readonly Container<DrawableHoldNoteHead> headContainer;
private readonly Container<DrawableHoldNoteTail> tailContainer;
private readonly Container<DrawableHoldNoteTick> tickContainer;
2018-04-13 17:19:50 +08:00
private readonly BodyPiece bodyPiece;
/// <summary>
/// Time at which the user started holding this hold note. Null if the user is not holding this hold note.
/// </summary>
2019-12-23 17:48:14 +08:00
public double? HoldStartTime { get; private set; }
2018-04-13 17:19:50 +08:00
/// <summary>
/// Whether the hold note has been released too early and shouldn't give full score for the release.
/// </summary>
2019-12-23 17:48:14 +08:00
public bool HasBroken { get; private set; }
2018-04-13 17:19:50 +08:00
public DrawableHoldNote(HoldNote hitObject)
: base(hitObject)
2018-04-13 17:19:50 +08:00
{
RelativeSizeAxes = Axes.X;
AddRangeInternal(new Drawable[]
2018-04-13 17:19:50 +08:00
{
bodyPiece = new BodyPiece { RelativeSizeAxes = Axes.X },
tickContainer = new Container<DrawableHoldNoteTick> { RelativeSizeAxes = Axes.Both },
headContainer = new Container<DrawableHoldNoteHead> { RelativeSizeAxes = Axes.Both },
tailContainer = new Container<DrawableHoldNoteTail> { RelativeSizeAxes = Axes.Both },
});
2018-04-13 17:19:50 +08:00
2019-07-22 13:45:25 +08:00
AccentColour.BindValueChanged(colour =>
{
bodyPiece.AccentColour = colour.NewValue;
}, true);
2018-04-13 17:19:50 +08:00
}
protected override void AddNestedHitObject(DrawableHitObject hitObject)
{
base.AddNestedHitObject(hitObject);
2019-10-17 11:53:54 +08:00
switch (hitObject)
{
case DrawableHoldNoteHead head:
headContainer.Child = head;
break;
case DrawableHoldNoteTail tail:
tailContainer.Child = tail;
break;
case DrawableHoldNoteTick tick:
tickContainer.Add(tick);
break;
}
}
protected override void ClearNestedHitObjects()
{
base.ClearNestedHitObjects();
headContainer.Clear();
tailContainer.Clear();
tickContainer.Clear();
}
protected override DrawableHitObject CreateNestedHitObject(HitObject hitObject)
{
switch (hitObject)
{
case TailNote _:
return new DrawableHoldNoteTail(this)
{
Anchor = Anchor.TopCentre,
Origin = Anchor.TopCentre,
AccentColour = { BindTarget = AccentColour }
};
case Note _:
return new DrawableHoldNoteHead(this)
{
Anchor = Anchor.TopCentre,
Origin = Anchor.TopCentre,
AccentColour = { BindTarget = AccentColour }
};
case HoldNoteTick tick:
return new DrawableHoldNoteTick(tick)
{
HoldStartTime = () => HoldStartTime,
AccentColour = { BindTarget = AccentColour }
};
}
return base.CreateNestedHitObject(hitObject);
}
2019-02-21 17:56:34 +08:00
protected override void OnDirectionChanged(ValueChangedEvent<ScrollingDirection> e)
{
2019-02-21 17:56:34 +08:00
base.OnDirectionChanged(e);
2019-02-21 17:56:34 +08:00
bodyPiece.Anchor = bodyPiece.Origin = e.NewValue == ScrollingDirection.Up ? Anchor.TopLeft : Anchor.BottomLeft;
}
2018-04-13 17:19:50 +08:00
protected override void Update()
{
base.Update();
// Make the body piece not lie under the head note
bodyPiece.Y = (Direction.Value == ScrollingDirection.Up ? 1 : -1) * Head.Height / 2;
bodyPiece.Height = DrawHeight - Head.Height / 2 + Tail.Height / 2;
2018-04-13 17:19:50 +08:00
}
protected override void UpdateStateTransforms(ArmedState state)
{
using (BeginDelayedSequence(HitObject.Duration, true))
base.UpdateStateTransforms(state);
}
2019-12-23 16:48:48 +08:00
protected override void CheckForResult(bool userTriggered, double timeOffset)
{
2019-12-23 16:48:48 +08:00
if (Tail.AllJudged)
ApplyResult(r => r.Type = HitResult.Perfect);
2019-12-23 16:48:48 +08:00
if (Tail.Result.Type == HitResult.Miss)
HasBroken = true;
}
2018-04-13 17:19:50 +08:00
public bool OnPressed(ManiaAction action)
{
2019-12-23 16:48:48 +08:00
if (AllJudged)
2018-04-13 17:19:50 +08:00
return false;
if (action != Action.Value)
2018-04-13 17:19:50 +08:00
return false;
2019-12-23 16:48:48 +08:00
beginHoldAt(Time.Current - Head.HitObject.StartTime);
Head.UpdateResult();
2018-04-13 17:19:50 +08:00
return true;
}
2019-12-23 16:48:48 +08:00
private void beginHoldAt(double timeOffset)
{
if (timeOffset < -Head.HitObject.HitWindows.WindowFor(HitResult.Miss))
return;
HoldStartTime = Time.Current;
bodyPiece.Hitting = true;
}
public void OnReleased(ManiaAction action)
2018-04-13 17:19:50 +08:00
{
2019-12-23 16:48:48 +08:00
if (AllJudged)
return;
2018-04-13 17:19:50 +08:00
if (action != Action.Value)
return;
2018-04-13 17:19:50 +08:00
2019-12-23 16:48:48 +08:00
// Make sure a hold was started
if (HoldStartTime == null)
return;
2019-12-23 16:48:48 +08:00
Tail.UpdateResult();
endHold();
2018-04-13 17:19:50 +08:00
// If the key has been released too early, the user should not receive full score for the release
2018-05-20 18:22:42 +08:00
if (!Tail.IsHit)
HasBroken = true;
2018-04-13 17:19:50 +08:00
}
2019-12-23 16:48:48 +08:00
private void endHold()
{
HoldStartTime = null;
bodyPiece.Hitting = false;
}
2018-04-13 17:19:50 +08:00
}
}