mirror of
https://github.com/ppy/osu.git
synced 2024-09-21 16:07:24 +08:00
Simplify implementation
This commit is contained in:
parent
7015cf0b1b
commit
b604eb6262
@ -2,7 +2,6 @@
|
|||||||
// See the LICENCE file in the repository root for full licence text.
|
// See the LICENCE file in the repository root for full licence text.
|
||||||
|
|
||||||
using NUnit.Framework;
|
using NUnit.Framework;
|
||||||
using osu.Framework.Allocation;
|
|
||||||
using osu.Framework.Graphics;
|
using osu.Framework.Graphics;
|
||||||
using osu.Framework.Testing;
|
using osu.Framework.Testing;
|
||||||
using osu.Game.Rulesets.Taiko.UI;
|
using osu.Game.Rulesets.Taiko.UI;
|
||||||
@ -13,9 +12,6 @@ namespace osu.Game.Rulesets.Taiko.Tests
|
|||||||
[TestFixture]
|
[TestFixture]
|
||||||
public class TestSceneDrumTouchInputArea : OsuTestScene
|
public class TestSceneDrumTouchInputArea : OsuTestScene
|
||||||
{
|
{
|
||||||
[Cached]
|
|
||||||
private TaikoInputManager taikoInputManager = new TaikoInputManager(new TaikoRuleset().RulesetInfo);
|
|
||||||
|
|
||||||
private DrumTouchInputArea drumTouchInputArea = null!;
|
private DrumTouchInputArea drumTouchInputArea = null!;
|
||||||
|
|
||||||
[SetUpSteps]
|
[SetUpSteps]
|
||||||
@ -23,19 +19,22 @@ namespace osu.Game.Rulesets.Taiko.Tests
|
|||||||
{
|
{
|
||||||
AddStep("create drum", () =>
|
AddStep("create drum", () =>
|
||||||
{
|
{
|
||||||
Children = new Drawable[]
|
Child = new TaikoInputManager(new TaikoRuleset().RulesetInfo)
|
||||||
{
|
{
|
||||||
new InputDrum
|
RelativeSizeAxes = Axes.Both,
|
||||||
|
Children = new Drawable[]
|
||||||
{
|
{
|
||||||
Anchor = Anchor.TopCentre,
|
new InputDrum
|
||||||
Origin = Anchor.TopCentre,
|
{
|
||||||
Height = 0.5f,
|
Anchor = Anchor.TopCentre,
|
||||||
},
|
Origin = Anchor.TopCentre,
|
||||||
drumTouchInputArea = new DrumTouchInputArea
|
Height = 0.2f,
|
||||||
{
|
},
|
||||||
Anchor = Anchor.BottomCentre,
|
drumTouchInputArea = new DrumTouchInputArea
|
||||||
Origin = Anchor.BottomCentre,
|
{
|
||||||
Height = 0.5f,
|
Anchor = Anchor.BottomCentre,
|
||||||
|
Origin = Anchor.BottomCentre,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
@ -39,8 +39,6 @@ namespace osu.Game.Rulesets.Taiko.UI
|
|||||||
|
|
||||||
private SkinnableDrawable scroller;
|
private SkinnableDrawable scroller;
|
||||||
|
|
||||||
private DrumTouchInputArea drumTouchInputArea;
|
|
||||||
|
|
||||||
public DrawableTaikoRuleset(Ruleset ruleset, IBeatmap beatmap, IReadOnlyList<Mod> mods = null)
|
public DrawableTaikoRuleset(Ruleset ruleset, IBeatmap beatmap, IReadOnlyList<Mod> mods = null)
|
||||||
: base(ruleset, beatmap, mods)
|
: base(ruleset, beatmap, mods)
|
||||||
{
|
{
|
||||||
@ -59,8 +57,7 @@ namespace osu.Game.Rulesets.Taiko.UI
|
|||||||
Depth = float.MaxValue
|
Depth = float.MaxValue
|
||||||
});
|
});
|
||||||
|
|
||||||
if ((drumTouchInputArea = CreateDrumTouchInputArea()) != null)
|
KeyBindingInputManager.Add(new DrumTouchInputArea());
|
||||||
KeyBindingInputManager.Add(drumTouchInputArea);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void UpdateAfterChildren()
|
protected override void UpdateAfterChildren()
|
||||||
@ -79,8 +76,6 @@ namespace osu.Game.Rulesets.Taiko.UI
|
|||||||
return ControlPoints[result];
|
return ControlPoints[result];
|
||||||
}
|
}
|
||||||
|
|
||||||
public DrumTouchInputArea CreateDrumTouchInputArea() => new DrumTouchInputArea();
|
|
||||||
|
|
||||||
public override PlayfieldAdjustmentContainer CreatePlayfieldAdjustmentContainer() => new TaikoPlayfieldAdjustmentContainer
|
public override PlayfieldAdjustmentContainer CreatePlayfieldAdjustmentContainer() => new TaikoPlayfieldAdjustmentContainer
|
||||||
{
|
{
|
||||||
LockPlayfieldAspect = { BindTarget = LockPlayfieldAspect }
|
LockPlayfieldAspect = { BindTarget = LockPlayfieldAspect }
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
// 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.
|
// See the LICENCE file in the repository root for full licence text.
|
||||||
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using osu.Framework.Allocation;
|
using osu.Framework.Allocation;
|
||||||
@ -13,152 +12,132 @@ using osu.Framework.Input.Bindings;
|
|||||||
using osu.Framework.Input.Events;
|
using osu.Framework.Input.Events;
|
||||||
using osu.Game.Graphics;
|
using osu.Game.Graphics;
|
||||||
using osuTK;
|
using osuTK;
|
||||||
|
using osuTK.Graphics;
|
||||||
|
using osuTK.Input;
|
||||||
|
|
||||||
namespace osu.Game.Rulesets.Taiko.UI
|
namespace osu.Game.Rulesets.Taiko.UI
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// An overlay that captures and displays Taiko mouse and touch input.
|
/// An overlay that captures and displays osu!taiko mouse and touch input.
|
||||||
/// The boundaries of this overlay defines the interactable area for touch input.
|
|
||||||
/// A secondary InputDrum is attached by this overlay, which defines the circular boundary which distinguishes "centre" from "rim" hits, and also displays input.
|
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class DrumTouchInputArea : Container
|
public class DrumTouchInputArea : Container
|
||||||
{
|
{
|
||||||
// The percent of the drum that extends past the bottom of the screen (set to 0.0f to show the full drum)
|
private readonly Circle outerCircle;
|
||||||
private const float offscreen_percent = 0.35f;
|
|
||||||
|
|
||||||
private readonly TouchInputDrum touchInputDrum;
|
|
||||||
private readonly Circle drumBackground;
|
|
||||||
|
|
||||||
private KeyBindingContainer<TaikoAction> keyBindingContainer = null!;
|
private KeyBindingContainer<TaikoAction> keyBindingContainer = null!;
|
||||||
|
|
||||||
// Which Taiko action was pressed by the last OnMouseDown event, so that the corresponding action can be released OnMouseUp even if the cursor position moved
|
private readonly Dictionary<TouchSource, TaikoAction> trackedTouches = new Dictionary<TouchSource, TaikoAction>();
|
||||||
private TaikoAction mouseAction;
|
private readonly Dictionary<MouseButton, TaikoAction> trackedMouseButtons = new Dictionary<MouseButton, TaikoAction>();
|
||||||
|
|
||||||
// A map of (Finger Index OnTouchDown -> Which Taiko action was pressed), so that the corresponding action can be released OnTouchUp is released even if the touch position moved
|
private readonly Container mainContent;
|
||||||
private readonly Dictionary<TouchSource, TaikoAction> touchActions = new Dictionary<TouchSource, TaikoAction>(Enum.GetNames(typeof(TouchSource)).Length);
|
|
||||||
|
|
||||||
private readonly Container visibleComponents;
|
private readonly Circle centreCircle;
|
||||||
|
|
||||||
public DrumTouchInputArea()
|
public DrumTouchInputArea()
|
||||||
{
|
{
|
||||||
RelativeSizeAxes = Axes.Both;
|
RelativeSizeAxes = Axes.X;
|
||||||
RelativePositionAxes = Axes.Both;
|
Height = 300;
|
||||||
|
|
||||||
|
Masking = true;
|
||||||
|
|
||||||
Children = new Drawable[]
|
Children = new Drawable[]
|
||||||
{
|
{
|
||||||
visibleComponents = new Container
|
mainContent = new Container
|
||||||
{
|
{
|
||||||
Alpha = 0.0f,
|
|
||||||
RelativeSizeAxes = Axes.Both,
|
RelativeSizeAxes = Axes.Both,
|
||||||
RelativePositionAxes = Axes.Both,
|
Height = 2,
|
||||||
Anchor = Anchor.BottomCentre,
|
|
||||||
Origin = Anchor.BottomCentre,
|
|
||||||
Children = new Drawable[]
|
Children = new Drawable[]
|
||||||
{
|
{
|
||||||
drumBackground = new Circle
|
outerCircle = new Circle
|
||||||
{
|
{
|
||||||
RelativeSizeAxes = Axes.Both,
|
|
||||||
RelativePositionAxes = Axes.Both,
|
|
||||||
Anchor = Anchor.Centre,
|
|
||||||
Origin = Anchor.Centre,
|
|
||||||
FillMode = FillMode.Fit,
|
FillMode = FillMode.Fit,
|
||||||
Alpha = 0.9f,
|
RelativeSizeAxes = Axes.Both,
|
||||||
},
|
|
||||||
touchInputDrum = new TouchInputDrum
|
|
||||||
{
|
|
||||||
Anchor = Anchor.Centre,
|
Anchor = Anchor.Centre,
|
||||||
Origin = Anchor.Centre,
|
Origin = Anchor.Centre,
|
||||||
},
|
},
|
||||||
|
centreCircle = new Circle
|
||||||
|
{
|
||||||
|
FillMode = FillMode.Fit,
|
||||||
|
RelativeSizeAxes = Axes.Both,
|
||||||
|
Anchor = Anchor.Centre,
|
||||||
|
Origin = Anchor.Centre,
|
||||||
|
Scale = new Vector2(0.5f),
|
||||||
|
},
|
||||||
|
new Box
|
||||||
|
{
|
||||||
|
FillMode = FillMode.Fit,
|
||||||
|
RelativeSizeAxes = Axes.Y,
|
||||||
|
Anchor = Anchor.Centre,
|
||||||
|
Origin = Anchor.Centre,
|
||||||
|
Colour = Color4.Black,
|
||||||
|
Width = 3,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void LoadComplete()
|
|
||||||
{
|
|
||||||
Padding = new MarginPadding
|
|
||||||
{
|
|
||||||
Top = TaikoPlayfield.DEFAULT_HEIGHT * 2f, // Visual elements should start right below the playfield
|
|
||||||
Bottom = -touchInputDrum.DrawHeight * offscreen_percent, // The drum should go past the bottom of the screen so that it can be wider
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
[BackgroundDependencyLoader]
|
[BackgroundDependencyLoader]
|
||||||
private void load(TaikoInputManager taikoInputManager, OsuColour colours)
|
private void load(TaikoInputManager taikoInputManager, OsuColour colours)
|
||||||
{
|
{
|
||||||
Debug.Assert(taikoInputManager?.KeyBindingContainer != null);
|
Debug.Assert(taikoInputManager.KeyBindingContainer != null);
|
||||||
|
|
||||||
keyBindingContainer = taikoInputManager.KeyBindingContainer;
|
keyBindingContainer = taikoInputManager.KeyBindingContainer;
|
||||||
|
|
||||||
drumBackground.Colour = colours.Gray0;
|
outerCircle.Colour = colours.Gray0;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override bool OnMouseDown(MouseDownEvent e)
|
protected override bool OnMouseDown(MouseDownEvent e)
|
||||||
{
|
{
|
||||||
ShowTouchControls();
|
mainContent.Show();
|
||||||
mouseAction = getTaikoActionFromInput(e.ScreenSpaceMouseDownPosition);
|
|
||||||
keyBindingContainer?.TriggerPressed(mouseAction);
|
TaikoAction taikoAction = getTaikoActionFromInput(e.ScreenSpaceMouseDownPosition);
|
||||||
|
|
||||||
|
trackedMouseButtons.Add(e.Button, taikoAction);
|
||||||
|
keyBindingContainer.TriggerPressed(taikoAction);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void OnMouseUp(MouseUpEvent e)
|
protected override void OnMouseUp(MouseUpEvent e)
|
||||||
{
|
{
|
||||||
keyBindingContainer?.TriggerReleased(mouseAction);
|
keyBindingContainer.TriggerReleased(trackedMouseButtons[e.Button]);
|
||||||
|
trackedMouseButtons.Remove(e.Button);
|
||||||
base.OnMouseUp(e);
|
base.OnMouseUp(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override bool OnTouchDown(TouchDownEvent e)
|
protected override bool OnTouchDown(TouchDownEvent e)
|
||||||
{
|
{
|
||||||
ShowTouchControls();
|
mainContent.Show();
|
||||||
|
|
||||||
TaikoAction taikoAction = getTaikoActionFromInput(e.ScreenSpaceTouchDownPosition);
|
TaikoAction taikoAction = getTaikoActionFromInput(e.ScreenSpaceTouchDownPosition);
|
||||||
touchActions.Add(e.Touch.Source, taikoAction);
|
|
||||||
keyBindingContainer?.TriggerPressed(touchActions[e.Touch.Source]);
|
trackedTouches.Add(e.Touch.Source, taikoAction);
|
||||||
|
keyBindingContainer.TriggerPressed(taikoAction);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void OnTouchUp(TouchUpEvent e)
|
protected override void OnTouchUp(TouchUpEvent e)
|
||||||
{
|
{
|
||||||
keyBindingContainer?.TriggerReleased(touchActions[e.Touch.Source]);
|
keyBindingContainer.TriggerReleased(trackedTouches[e.Touch.Source]);
|
||||||
touchActions.Remove(e.Touch.Source);
|
trackedTouches.Remove(e.Touch.Source);
|
||||||
base.OnTouchUp(e);
|
base.OnTouchUp(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override bool OnKeyDown(KeyDownEvent e)
|
protected override bool OnKeyDown(KeyDownEvent e)
|
||||||
{
|
{
|
||||||
HideTouchControls();
|
mainContent.Hide();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void ShowTouchControls()
|
|
||||||
{
|
|
||||||
visibleComponents.Animate(components => components.FadeIn(500, Easing.OutQuint));
|
|
||||||
}
|
|
||||||
|
|
||||||
public void HideTouchControls()
|
|
||||||
{
|
|
||||||
visibleComponents.Animate(components => components.FadeOut(2000, Easing.OutQuint));
|
|
||||||
}
|
|
||||||
|
|
||||||
private TaikoAction getTaikoActionFromInput(Vector2 inputPosition)
|
private TaikoAction getTaikoActionFromInput(Vector2 inputPosition)
|
||||||
{
|
{
|
||||||
bool centreHit = inputIsCenterHit(inputPosition);
|
bool centreHit = centreCircle.ScreenSpaceDrawQuad.Contains(inputPosition);
|
||||||
bool leftSide = inputIsOnLeftSide(inputPosition);
|
bool leftSide = ToLocalSpace(inputPosition).X < DrawWidth / 2;
|
||||||
|
|
||||||
return centreHit ? (leftSide ? TaikoAction.LeftCentre : TaikoAction.RightCentre) : (leftSide ? TaikoAction.LeftRim : TaikoAction.RightRim);
|
if (leftSide)
|
||||||
}
|
return centreHit ? TaikoAction.LeftCentre : TaikoAction.LeftRim;
|
||||||
|
|
||||||
private bool inputIsOnLeftSide(Vector2 inputPosition)
|
return centreHit ? TaikoAction.RightCentre : TaikoAction.RightRim;
|
||||||
{
|
|
||||||
Vector2 inputPositionToDrumCentreDelta = touchInputDrum.ToLocalSpace(inputPosition) - touchInputDrum.OriginPosition;
|
|
||||||
return inputPositionToDrumCentreDelta.X < 0f;
|
|
||||||
}
|
|
||||||
|
|
||||||
private bool inputIsCenterHit(Vector2 inputPosition)
|
|
||||||
{
|
|
||||||
Vector2 inputPositionToDrumCentreDelta = touchInputDrum.ToLocalSpace(inputPosition) - touchInputDrum.OriginPosition;
|
|
||||||
|
|
||||||
float inputDrumRadius = Math.Max(touchInputDrum.Width, touchInputDrum.DrawHeight) / 2f;
|
|
||||||
float centreRadius = (inputDrumRadius * touchInputDrum.CentreSize);
|
|
||||||
return inputPositionToDrumCentreDelta.Length <= centreRadius;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -66,7 +66,7 @@ namespace osu.Game.Rulesets.Taiko.UI
|
|||||||
[BackgroundDependencyLoader]
|
[BackgroundDependencyLoader]
|
||||||
private void load(OsuColour colours)
|
private void load(OsuColour colours)
|
||||||
{
|
{
|
||||||
inputDrum = new InputDrum()
|
inputDrum = new InputDrum
|
||||||
{
|
{
|
||||||
Anchor = Anchor.CentreLeft,
|
Anchor = Anchor.CentreLeft,
|
||||||
Origin = Anchor.CentreLeft,
|
Origin = Anchor.CentreLeft,
|
||||||
|
@ -11,7 +11,6 @@ using osu.Framework.Graphics.Textures;
|
|||||||
using osu.Framework.Input.Bindings;
|
using osu.Framework.Input.Bindings;
|
||||||
using osu.Framework.Input.Events;
|
using osu.Framework.Input.Events;
|
||||||
using osu.Game.Graphics;
|
using osu.Game.Graphics;
|
||||||
using osu.Game.Skinning;
|
|
||||||
using osuTK;
|
using osuTK;
|
||||||
|
|
||||||
namespace osu.Game.Rulesets.Taiko.UI
|
namespace osu.Game.Rulesets.Taiko.UI
|
||||||
@ -34,7 +33,7 @@ namespace osu.Game.Rulesets.Taiko.UI
|
|||||||
{
|
{
|
||||||
Children = new Drawable[]
|
Children = new Drawable[]
|
||||||
{
|
{
|
||||||
new SkinnableDrawable(new TaikoSkinComponent(TaikoSkinComponents.InputDrum), _ => new Container
|
new Container
|
||||||
{
|
{
|
||||||
RelativeSizeAxes = Axes.Both,
|
RelativeSizeAxes = Axes.Both,
|
||||||
FillMode = FillMode.Fit,
|
FillMode = FillMode.Fit,
|
||||||
@ -64,7 +63,7 @@ namespace osu.Game.Rulesets.Taiko.UI
|
|||||||
CentreAction = TaikoAction.RightCentre
|
CentreAction = TaikoAction.RightCentre
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user