// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. using System.Collections.Generic; using System.Diagnostics; using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; using osu.Framework.Input.Bindings; using osu.Framework.Input.Events; using osu.Game.Graphics; using osuTK; using osuTK.Graphics; namespace osu.Game.Rulesets.Taiko.UI { /// /// An overlay that captures and displays osu!taiko mouse and touch input. /// public class DrumTouchInputArea : Container { private KeyBindingContainer keyBindingContainer = null!; private readonly Dictionary trackedActions = new Dictionary(); private Container mainContent = null!; private Circle centreCircle = null!; private Circle outerCircle = null!; [BackgroundDependencyLoader] private void load(TaikoInputManager taikoInputManager, OsuColour colours) { Debug.Assert(taikoInputManager.KeyBindingContainer != null); keyBindingContainer = taikoInputManager.KeyBindingContainer; // Container should handle input everywhere. RelativeSizeAxes = Axes.Both; Children = new Drawable[] { new Container { Anchor = Anchor.BottomCentre, Origin = Anchor.BottomCentre, RelativeSizeAxes = Axes.X, Height = 300, Y = 20, Masking = true, FillMode = FillMode.Fit, Children = new Drawable[] { mainContent = new Container { RelativeSizeAxes = Axes.Both, Height = 2, Children = new Drawable[] { outerCircle = new Circle { FillMode = FillMode.Fit, Colour = colours.BlueDarker, RelativeSizeAxes = Axes.Both, Anchor = Anchor.Centre, Origin = Anchor.Centre, }, centreCircle = new Circle { FillMode = FillMode.Fit, Colour = colours.YellowDark, RelativeSizeAxes = Axes.Both, Anchor = Anchor.Centre, Origin = Anchor.Centre, Scale = new Vector2(0.8f), }, new Box { Colour = colours.BlueDarker, RelativeSizeAxes = Axes.Y, Height = 0.9f, Anchor = Anchor.BottomCentre, Origin = Anchor.BottomCentre, Width = 7, }, } }, } }, }; } protected override bool OnKeyDown(KeyDownEvent e) { // Hide whenever the keyboard is used. mainContent.Hide(); return false; } protected override bool OnMouseDown(MouseDownEvent e) { handleDown(e.Button, e.ScreenSpaceMousePosition); return true; } protected override void OnMouseUp(MouseUpEvent e) { handleUp(e.Button); base.OnMouseUp(e); } protected override bool OnTouchDown(TouchDownEvent e) { handleDown(e.Touch.Source, e.ScreenSpaceTouchDownPosition); return true; } protected override void OnTouchUp(TouchUpEvent e) { handleUp(e.Touch.Source); base.OnTouchUp(e); } private void handleDown(object source, Vector2 position) { mainContent.Show(); TaikoAction taikoAction = getTaikoActionFromInput(position); switch (taikoAction) { case TaikoAction.LeftCentre: case TaikoAction.RightCentre: centreCircle.FlashColour(Color4.White, 2000, Easing.OutQuint); break; case TaikoAction.LeftRim: case TaikoAction.RightRim: outerCircle.FlashColour(Color4.White, 2000, Easing.OutQuint); break; } trackedActions.Add(source, taikoAction); keyBindingContainer.TriggerPressed(taikoAction); } private void handleUp(object source) { keyBindingContainer.TriggerReleased(trackedActions[source]); trackedActions.Remove(source); } private TaikoAction getTaikoActionFromInput(Vector2 inputPosition) { bool centreHit = centreCircle.Contains(inputPosition); bool leftSide = ToLocalSpace(inputPosition).X < DrawWidth / 2; if (leftSide) return centreHit ? TaikoAction.LeftCentre : TaikoAction.LeftRim; return centreHit ? TaikoAction.RightCentre : TaikoAction.RightRim; } } }