osu/osu.Game.Rulesets.Taiko/UI/DrumSamplePlayer.cs

154 lines
5.4 KiB
C#

// 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.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Framework.Input.Bindings;
using osu.Framework.Input.Events;
using osu.Game.Rulesets.Taiko.Objects;
using osu.Game.Rulesets.Taiko.Objects.Drawables;
using osu.Game.Rulesets.UI;
using osu.Game.Screens.Play;
namespace osu.Game.Rulesets.Taiko.UI
{
internal partial class DrumSamplePlayer : CompositeDrawable, IKeyBindingHandler<TaikoAction>
{
private DrumSampleTriggerSource leftCentreTrigger = null!;
private DrumSampleTriggerSource rightCentreTrigger = null!;
private DrumSampleTriggerSource leftRimTrigger = null!;
private DrumSampleTriggerSource rightRimTrigger = null!;
private DrumSampleTriggerSource strongCentreTrigger = null!;
private DrumSampleTriggerSource strongRimTrigger = null!;
private double lastHitTime;
private TaikoAction? lastAction;
[BackgroundDependencyLoader]
private void load(Playfield playfield)
{
var hitObjectContainer = playfield.HitObjectContainer;
InternalChildren = new Drawable[]
{
leftCentreTrigger = CreateTriggerSource(hitObjectContainer, SampleBalance.Left),
rightCentreTrigger = CreateTriggerSource(hitObjectContainer, SampleBalance.Right),
leftRimTrigger = CreateTriggerSource(hitObjectContainer, SampleBalance.Left),
rightRimTrigger = CreateTriggerSource(hitObjectContainer, SampleBalance.Right),
strongCentreTrigger = CreateTriggerSource(hitObjectContainer, SampleBalance.Centre),
strongRimTrigger = CreateTriggerSource(hitObjectContainer, SampleBalance.Centre)
};
}
protected virtual DrumSampleTriggerSource CreateTriggerSource(HitObjectContainer hitObjectContainer, SampleBalance balance)
=> new DrumSampleTriggerSource(hitObjectContainer);
public bool OnPressed(KeyBindingPressEvent<TaikoAction> e)
{
if ((Clock as IGameplayClock)?.IsRewinding == true)
return false;
HitType hitType;
DrumSampleTriggerSource triggerSource;
bool strong = checkStrongValidity(e.Action, lastAction, Time.Current - lastHitTime);
switch (e.Action)
{
case TaikoAction.LeftCentre:
hitType = HitType.Centre;
triggerSource = strong ? strongCentreTrigger : leftCentreTrigger;
break;
case TaikoAction.RightCentre:
hitType = HitType.Centre;
triggerSource = strong ? strongCentreTrigger : rightCentreTrigger;
break;
case TaikoAction.LeftRim:
hitType = HitType.Rim;
triggerSource = strong ? strongRimTrigger : leftRimTrigger;
break;
case TaikoAction.RightRim:
hitType = HitType.Rim;
triggerSource = strong ? strongRimTrigger : rightRimTrigger;
break;
default:
return false;
}
if (strong)
{
switch (hitType)
{
case HitType.Centre:
flushCenterTriggerSources();
break;
case HitType.Rim:
flushRimTriggerSources();
break;
}
}
Play(triggerSource, hitType, strong);
lastHitTime = Time.Current;
lastAction = e.Action;
return false;
}
protected virtual void Play(DrumSampleTriggerSource triggerSource, HitType hitType, bool strong) =>
triggerSource.Play(hitType, strong);
private bool checkStrongValidity(TaikoAction newAction, TaikoAction? lastAction, double timeBetweenActions)
{
if (lastAction == null)
return false;
if (timeBetweenActions < 0 || timeBetweenActions > DrawableHit.StrongNestedHit.SECOND_HIT_WINDOW)
return false;
switch (newAction)
{
case TaikoAction.LeftCentre:
return lastAction == TaikoAction.RightCentre;
case TaikoAction.RightCentre:
return lastAction == TaikoAction.LeftCentre;
case TaikoAction.LeftRim:
return lastAction == TaikoAction.RightRim;
case TaikoAction.RightRim:
return lastAction == TaikoAction.LeftRim;
default:
return false;
}
}
private void flushCenterTriggerSources()
{
leftCentreTrigger.StopAllPlayback();
rightCentreTrigger.StopAllPlayback();
strongCentreTrigger.StopAllPlayback();
}
private void flushRimTriggerSources()
{
leftRimTrigger.StopAllPlayback();
rightRimTrigger.StopAllPlayback();
strongRimTrigger.StopAllPlayback();
}
public void OnReleased(KeyBindingReleaseEvent<TaikoAction> e)
{
}
}
}