Skip to content

Commit

Permalink
Rework input handling to allow for axis support (YARC-Official#177)
Browse files Browse the repository at this point in the history
* Allow processing and mapping of axis controls as buttons

* Adjust input strategies to work in terms of floats

* Encapsulate control mapping handling

* Rework mapping system
NOTE: Some binding strings have changed in order to keep the styles consistent.
Users will need to rebind the affected controls.

* Add helper methods for getting mapping values

* Detect multiple controls being active when binding controls

* Fix cancellation handling
  • Loading branch information
TheNathannator authored Apr 23, 2023
1 parent 593671c commit 8c3acfc
Show file tree
Hide file tree
Showing 11 changed files with 330 additions and 160 deletions.
82 changes: 82 additions & 0 deletions Assets/Script/Input/ControlBinding.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
using UnityEngine.InputSystem;
using UnityEngine.InputSystem.Controls;
using UnityEngine.InputSystem.LowLevel;

namespace YARG.Input {
public enum BindingType {
BUTTON,
AXIS
}

public class ControlBinding {
public const float DEFAULT_PRESS_THRESHOLD = 0.75f; // TODO: Remove once control calibration is added

public BindingType Type { get; }
public string DisplayName { get; }
public string BindingKey { get; }

private InputControl<float> _control;
public InputControl<float> Control {
get => _control;
set {
_control = value;
if (value is ButtonControl button) {
pressPoint = button.pressPointOrDefault;
}
}
}

private (float previous, float current) _state;
public (float previous, float current) State => _state;

private float pressPoint = DEFAULT_PRESS_THRESHOLD;

public ControlBinding(BindingType type, string displayName, string bindingKey) {
Type = type;
DisplayName = displayName;
BindingKey = bindingKey;
}

public bool IsPressed() {
// Ignore if unmapped
if (_control == null) {
return false;
}

return _state.current >= pressPoint;
}

public bool WasPressed() {
// Ignore if unmapped
if (_control == null) {
return false;
}

return _state.previous < pressPoint && _state.current >= pressPoint;
}

public bool WasReleased() {
// Ignore if unmapped
if (_control == null) {
return false;
}

return _state.previous >= pressPoint && _state.current < pressPoint;
}

public void UpdateState(InputEventPtr eventPtr) {
// Ignore if unmapped
if (_control == null) {
return;
}

// Progress state history forward
_state.previous = _state.current;
// Don't check pressed state unless there was a value change
// Controls not changed in a delta state event (which MIDI devices use) will report the wrong value
if (_control.HasValueChangeInEvent(eventPtr)) {
_state.current = _control.ReadValueFromEvent(eventPtr);
}
}
}
}
11 changes: 11 additions & 0 deletions Assets/Script/Input/ControlBinding.cs.meta

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

64 changes: 37 additions & 27 deletions Assets/Script/Input/DrumsInputStrategy.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,72 +5,82 @@

namespace YARG.Input {
public class DrumsInputStrategy : InputStrategy {
public static readonly string[] MAPPING_NAMES = new string[] {
"red_pad",
"yellow_pad",
"blue_pad",
"green_pad",
"yellow_cymbal",
"blue_cymbal",
"green_cymbal",
"kick",
"kick_alt"
};
public const string RED_PAD = "red_pad";
public const string YELLOW_PAD = "yellow_pad";
public const string BLUE_PAD = "blue_pad";
public const string GREEN_PAD = "green_pad";

public const string YELLOW_CYMBAL = "yellow_cymbal";
public const string BLUE_CYMBAL = "blue_cymbal";
public const string GREEN_CYMBAL = "green_cymbal";

public const string KICK = "kick";
public const string KICK_ALT = "kick_alt";

private List<NoteInfo> botChart;

public delegate void DrumHitAction(int drum, bool cymbal);

public event DrumHitAction DrumHitEvent;

public override string[] GetMappingNames() {
return MAPPING_NAMES;
}
protected override Dictionary<string, ControlBinding> GetMappings() => new() {
{ RED_PAD, new(BindingType.BUTTON, "Red Pad", RED_PAD) },
{ YELLOW_PAD, new(BindingType.BUTTON, "Yellow Pad", YELLOW_PAD) },
{ BLUE_PAD, new(BindingType.BUTTON, "Blue Pad", BLUE_PAD) },
{ GREEN_PAD, new(BindingType.BUTTON, "Green Pad", GREEN_PAD) },

{ YELLOW_CYMBAL, new(BindingType.BUTTON, "Yellow Cymbal", YELLOW_CYMBAL) },
{ BLUE_CYMBAL, new(BindingType.BUTTON, "Blue Cymbal", BLUE_CYMBAL) },
{ GREEN_CYMBAL, new(BindingType.BUTTON, "Green Cymbal", GREEN_CYMBAL) },

{ KICK, new(BindingType.BUTTON, "Kick", KICK) },
{ KICK_ALT, new(BindingType.BUTTON, "Kick Alt", KICK_ALT) }
};

protected override void UpdatePlayerMode() {
// Deal with drum inputs

if (WasMappingPressed("red_pad")) {
if (WasMappingPressed(RED_PAD)) {
DrumHitEvent?.Invoke(0, false);
CallGenericCalbirationEvent();
}

if (WasMappingPressed("yellow_pad")) {
if (WasMappingPressed(YELLOW_PAD)) {
DrumHitEvent?.Invoke(1, false);
CallGenericCalbirationEvent();
}

if (WasMappingPressed("blue_pad")) {
if (WasMappingPressed(BLUE_PAD)) {
DrumHitEvent?.Invoke(2, false);
CallGenericCalbirationEvent();
}

if (WasMappingPressed("green_pad")) {
if (WasMappingPressed(GREEN_PAD)) {
DrumHitEvent?.Invoke(3, false);
CallGenericCalbirationEvent();
}

if (WasMappingPressed("yellow_cymbal")) {
if (WasMappingPressed(YELLOW_CYMBAL)) {
DrumHitEvent?.Invoke(1, true);
CallGenericCalbirationEvent();
}

if (WasMappingPressed("blue_cymbal")) {
if (WasMappingPressed(BLUE_CYMBAL)) {
DrumHitEvent?.Invoke(2, true);
CallGenericCalbirationEvent();
}

if (WasMappingPressed("green_cymbal")) {
if (WasMappingPressed(GREEN_CYMBAL)) {
DrumHitEvent?.Invoke(3, true);
CallGenericCalbirationEvent();
}

if (WasMappingPressed("kick")) {
if (WasMappingPressed(KICK)) {
DrumHitEvent?.Invoke(4, false);
CallGenericCalbirationEvent();
}

if (WasMappingPressed("kick_alt")) {
if (WasMappingPressed(KICK_ALT)) {
DrumHitEvent?.Invoke(4, false);
CallGenericCalbirationEvent();
}
Expand Down Expand Up @@ -106,10 +116,10 @@ public void ActivateStarpower() {
}

protected override void UpdateNavigationMode() {
CallGenericNavigationEventForButton("yellow_pad", NavigationType.UP);
CallGenericNavigationEventForButton("blue_pad", NavigationType.DOWN);
CallGenericNavigationEventForButton("green_pad", NavigationType.PRIMARY);
CallGenericNavigationEventForButton("red_pad", NavigationType.SECONDARY);
CallGenericNavigationEventForButton(YELLOW_PAD, NavigationType.UP);
CallGenericNavigationEventForButton(BLUE_PAD, NavigationType.DOWN);
CallGenericNavigationEventForButton(GREEN_PAD, NavigationType.PRIMARY);
CallGenericNavigationEventForButton(RED_PAD, NavigationType.SECONDARY);
}

public override string[] GetAllowedInstruments() {
Expand Down
76 changes: 46 additions & 30 deletions Assets/Script/Input/FiveFretInputStrategy.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,17 @@

namespace YARG.Input {
public class FiveFretInputStrategy : InputStrategy {
public static readonly string[] MAPPING_NAMES = new string[] {
"green",
"red",
"yellow",
"blue",
"orange",
"strumUp",
"strumDown",
"starpower",
"pause"
};
public const string GREEN = "green";
public const string RED = "red";
public const string YELLOW = "yellow";
public const string BLUE = "blue";
public const string ORANGE = "orange";

public const string STRUM_UP = "strum_up";
public const string STRUM_DOWN = "strum_down";

public const string STAR_POWER = "star_power";
public const string PAUSE = "pause";

private List<NoteInfo> botChart;

Expand All @@ -24,40 +24,56 @@ public class FiveFretInputStrategy : InputStrategy {
public event FretChangeAction FretChangeEvent;
public event StrumAction StrumEvent;

public override string[] GetMappingNames() {
return MAPPING_NAMES;
}
protected override Dictionary<string, ControlBinding> GetMappings() => new() {
{ GREEN, new(BindingType.BUTTON, "Green", GREEN) },
{ RED, new(BindingType.BUTTON, "Red", RED) },
{ YELLOW, new(BindingType.BUTTON, "Yellow", YELLOW) },
{ BLUE, new(BindingType.BUTTON, "Blue", BLUE) },
{ ORANGE, new(BindingType.BUTTON, "Orange", ORANGE) },

{ STRUM_UP, new(BindingType.BUTTON, "Strum Up", STRUM_UP) },
{ STRUM_DOWN, new(BindingType.BUTTON, "Strum Down", STRUM_DOWN) },

{ STAR_POWER, new(BindingType.BUTTON, "Star Power", STAR_POWER) },
{ PAUSE, new(BindingType.BUTTON, "Pause", PAUSE) },
};

public override void InitializeBotMode(object rawChart) {
botChart = (List<NoteInfo>) rawChart;
}

protected override void UpdatePlayerMode() {
// Deal with fret inputs

for (int i = 0; i < 5; i++) {
if (WasMappingPressed(MAPPING_NAMES[i])) {
FretChangeEvent?.Invoke(true, i);
} else if (WasMappingReleased(MAPPING_NAMES[i])) {
FretChangeEvent?.Invoke(false, i);
void HandleFret(string mapping, int index) {
if (WasMappingPressed(mapping)) {
FretChangeEvent?.Invoke(true, index);
} else if (WasMappingReleased(mapping)) {
FretChangeEvent?.Invoke(false, index);
}
}

// Deal with fret inputs

HandleFret(GREEN, 0);
HandleFret(RED, 1);
HandleFret(YELLOW, 2);
HandleFret(BLUE, 3);
HandleFret(ORANGE, 4);

// Deal with strumming

if (WasMappingPressed("strumUp")) {
if (WasMappingPressed(STRUM_UP)) {
StrumEvent?.Invoke();
CallGenericCalbirationEvent();
}

if (WasMappingPressed("strumDown")) {
if (WasMappingPressed(STRUM_DOWN)) {
StrumEvent?.Invoke();
CallGenericCalbirationEvent();
}

// Starpower

if (WasMappingPressed("starpower")) {
if (WasMappingPressed(STAR_POWER)) {
CallStarpowerEvent();
}
}
Expand Down Expand Up @@ -96,14 +112,14 @@ protected override void UpdateBotMode() {
}

protected override void UpdateNavigationMode() {
CallGenericNavigationEventForButton("strumUp", NavigationType.UP);
CallGenericNavigationEventForButton("strumDown", NavigationType.DOWN);
CallGenericNavigationEventForButton(STRUM_UP, NavigationType.UP);
CallGenericNavigationEventForButton(STRUM_DOWN, NavigationType.DOWN);

CallGenericNavigationEventForButton("green", NavigationType.PRIMARY);
CallGenericNavigationEventForButton("red", NavigationType.SECONDARY);
CallGenericNavigationEventForButton("yellow", NavigationType.TERTIARY);
CallGenericNavigationEventForButton(GREEN, NavigationType.PRIMARY);
CallGenericNavigationEventForButton(RED, NavigationType.SECONDARY);
CallGenericNavigationEventForButton(YELLOW, NavigationType.TERTIARY);

if (WasMappingPressed("pause")) {
if (WasMappingPressed(PAUSE)) {
CallPauseEvent();
}
}
Expand Down
Loading

0 comments on commit 8c3acfc

Please sign in to comment.