JSL timestamped input

This commit is contained in:
minenice55 2023-07-06 22:51:24 -04:00
parent 7cd64de6ae
commit 7572106856
6 changed files with 146 additions and 69 deletions

View file

@ -66,24 +66,29 @@ namespace HeavenStudio.Games
public void Disable() { enabled = false; }
public void QueueDeletion() { markForDeletion = true; }
public bool IsCorrectInput() =>
//General inputs, both down and up
(PlayerInput.Pressed() && inputType.HasFlag(InputType.STANDARD_DOWN)) ||
(PlayerInput.AltPressed() && inputType.HasFlag(InputType.STANDARD_ALT_DOWN)) ||
(PlayerInput.GetAnyDirectionDown() && inputType.HasFlag(InputType.DIRECTION_DOWN)) ||
(PlayerInput.PressedUp() && inputType.HasFlag(InputType.STANDARD_UP)) ||
(PlayerInput.AltPressedUp() && inputType.HasFlag(InputType.STANDARD_ALT_UP)) ||
(PlayerInput.GetAnyDirectionUp() && inputType.HasFlag(InputType.DIRECTION_UP)) ||
//Specific directional inputs
(PlayerInput.GetSpecificDirectionDown(PlayerInput.DOWN) && inputType.HasFlag(InputType.DIRECTION_DOWN_DOWN)) ||
(PlayerInput.GetSpecificDirectionDown(PlayerInput.UP) && inputType.HasFlag(InputType.DIRECTION_UP_DOWN)) ||
(PlayerInput.GetSpecificDirectionDown(PlayerInput.LEFT) && inputType.HasFlag(InputType.DIRECTION_LEFT_DOWN)) ||
(PlayerInput.GetSpecificDirectionDown(PlayerInput.RIGHT) && inputType.HasFlag(InputType.DIRECTION_RIGHT_DOWN)) ||
public bool IsCorrectInput(out double dt)
{
dt = 0;
return (
//General inputs, both down and up
(PlayerInput.Pressed(out dt) && inputType.HasFlag(InputType.STANDARD_DOWN)) ||
(PlayerInput.AltPressed(out dt) && inputType.HasFlag(InputType.STANDARD_ALT_DOWN)) ||
(PlayerInput.GetAnyDirectionDown(out dt) && inputType.HasFlag(InputType.DIRECTION_DOWN)) ||
(PlayerInput.PressedUp(out dt) && inputType.HasFlag(InputType.STANDARD_UP)) ||
(PlayerInput.AltPressedUp(out dt) && inputType.HasFlag(InputType.STANDARD_ALT_UP)) ||
(PlayerInput.GetAnyDirectionUp(out dt) && inputType.HasFlag(InputType.DIRECTION_UP)) ||
//Specific directional inputs
(PlayerInput.GetSpecificDirectionDown(PlayerInput.DOWN, out dt) && inputType.HasFlag(InputType.DIRECTION_DOWN_DOWN)) ||
(PlayerInput.GetSpecificDirectionDown(PlayerInput.UP, out dt) && inputType.HasFlag(InputType.DIRECTION_UP_DOWN)) ||
(PlayerInput.GetSpecificDirectionDown(PlayerInput.LEFT, out dt) && inputType.HasFlag(InputType.DIRECTION_LEFT_DOWN)) ||
(PlayerInput.GetSpecificDirectionDown(PlayerInput.RIGHT, out dt) && inputType.HasFlag(InputType.DIRECTION_RIGHT_DOWN)) ||
(PlayerInput.GetSpecificDirectionUp(PlayerInput.DOWN) && inputType.HasFlag(InputType.DIRECTION_DOWN_UP)) ||
(PlayerInput.GetSpecificDirectionUp(PlayerInput.UP) && inputType.HasFlag(InputType.DIRECTION_UP_UP)) ||
(PlayerInput.GetSpecificDirectionUp(PlayerInput.LEFT) && inputType.HasFlag(InputType.DIRECTION_LEFT_UP)) ||
(PlayerInput.GetSpecificDirectionUp(PlayerInput.RIGHT) && inputType.HasFlag(InputType.DIRECTION_RIGHT_UP));
(PlayerInput.GetSpecificDirectionUp(PlayerInput.DOWN, out dt) && inputType.HasFlag(InputType.DIRECTION_DOWN_UP)) ||
(PlayerInput.GetSpecificDirectionUp(PlayerInput.UP, out dt) && inputType.HasFlag(InputType.DIRECTION_UP_UP)) ||
(PlayerInput.GetSpecificDirectionUp(PlayerInput.LEFT, out dt) && inputType.HasFlag(InputType.DIRECTION_LEFT_UP)) ||
(PlayerInput.GetSpecificDirectionUp(PlayerInput.RIGHT, out dt) && inputType.HasFlag(InputType.DIRECTION_RIGHT_UP))
);
}
public void CanHit(bool canHit)
{
@ -123,8 +128,9 @@ namespace HeavenStudio.Games
return;
}
if (!autoplayOnly && (IsHittable == null || IsHittable != null && IsHittable()) && IsCorrectInput())
if (!autoplayOnly && (IsHittable == null || IsHittable != null && IsHittable()) && IsCorrectInput(out double dt))
{
normalizedTime -= dt;
if (IsExpectingInputNow())
{
double stateProg = ((normalizedTime - Minigame.JustEarlyTime()) / (Minigame.JustLateTime() - Minigame.JustEarlyTime()) - 0.5f) * 2;
@ -235,7 +241,7 @@ namespace HeavenStudio.Games
{
if (OnHit != null && enabled)
{
if(canHit)
if (canHit)
{
double normalized = time - 1f;
int offset = Mathf.CeilToInt((float)normalized * 1000);

View file

@ -56,6 +56,10 @@ namespace HeavenStudio.InputSystem.Loaders
public static void DisposeJoyshocks()
{
foreach (InputJoyshock joyshock in InputJoyshock.joyshocks.Values)
{
joyshock.CleanUp();
}
JslDisconnectAndDisposeAll();
}
@ -182,7 +186,7 @@ namespace HeavenStudio.InputSystem
public struct JoyshockButtonState
{
public double time; // time passed since state
public double dt; // time passed since state
public bool pressed; // true if button is down
public bool isDelta; // true if the button changed state since last frame
}
@ -196,8 +200,7 @@ namespace HeavenStudio.InputSystem
protected List<TimestampedState> inputStack; // asynnc input events / polling should feed into this dict
protected List<TimestampedState> lastInputStack; // when processing input copy the inputStack to this dict
protected bool wantClearInputStack = false; // strobe from main thread to clear the input stack
protected double reportTime = 0; // same timeline as Time.timeSinceStartup
protected double lastReportTime = 0; // same timeline as Time.timeSinceStartup
protected double reportTime = 0;
public InputJoyshock(int handle)
{
@ -221,8 +224,7 @@ namespace HeavenStudio.InputSystem
{
js.inputStack.Clear();
js.wantClearInputStack = false;
js.totalReportDt = (js.lastReportTime*2) - js.reportTime;
js.lastReportTime = js.reportTime;
js.totalReportDt -= js.reportTime;
}
js.totalReportDt += deltaTime;
js.inputStack.Add(new TimestampedState
@ -256,25 +258,28 @@ namespace HeavenStudio.InputSystem
joyshocks.Add(joyshockHandle, this);
}
public void CleanUp()
{
JslSetPlayerNumber(joyshockHandle, 0);
JslSetLightColour(joyshockHandle, 0);
}
public override void UpdateState()
{
lastInputStack = new(inputStack);
wantClearInputStack = true;
reportTime = Time.realtimeSinceStartupAsDouble;
reportTime = totalReportDt;
// Debug.Log($"=== updating state for {joyshockName} id {joyshockHandle} ===");
for (int i = 0; i < buttonStates.Length; i++)
{
buttonStates[i].isDelta = false;
}
foreach(TimestampedState state in lastInputStack)
{
// Debug.Log($"checking state at {state.timestamp} ({reportTime - state.timestamp}s ago), input {state.input.buttons}");
joyBtStateCurrent = state.input;
for (int i = 0; i < buttonStates.Length; i++)
{
JoyshockButtonState st = buttonStates[i];
int bt = mappings[i];
if (otherHalf == null)
{
@ -294,12 +299,11 @@ namespace HeavenStudio.InputSystem
if (bt != -1)
{
bool pressed = BitwiseUtils.WantCurrent(state.input.buttons, 1 << bt);
if (pressed != st.pressed && !st.isDelta)
if (pressed != buttonStates[i].pressed && !buttonStates[i].isDelta)
{
Debug.Log($"button {i} ({bt}) state changed to {pressed}, was {st.pressed} (time {reportTime - state.timestamp}s ago)");
buttonStates[i].pressed = pressed;
buttonStates[i].isDelta = true;
buttonStates[i].time = reportTime - state.timestamp;
buttonStates[i].dt = reportTime - state.timestamp;
}
}
}
@ -408,14 +412,16 @@ namespace HeavenStudio.InputSystem
return buttonStates[button].pressed;
}
public override bool GetButtonDown(int button)
public override bool GetButtonDown(int button, out double dt)
{
dt = buttonStates[button].dt;
return buttonStates[button].pressed && buttonStates[button].isDelta;
}
public override bool GetButtonUp(int button)
public override bool GetButtonUp(int button, out double dt)
{
return (!buttonStates[button].pressed) && buttonStates[button].isDelta;
dt = buttonStates[button].dt;
return !buttonStates[button].pressed && buttonStates[button].isDelta;
}
public override float GetAxis(InputAxis axis)
@ -466,7 +472,7 @@ namespace HeavenStudio.InputSystem
return GetButton(bt) || BitwiseUtils.WantCurrent(directionStateCurrent, 1 << (int) direction);
}
public override bool GetHatDirectionDown(InputDirection direction)
public override bool GetHatDirectionDown(InputDirection direction, out double dt)
{
int bt;
switch (direction)
@ -484,12 +490,15 @@ namespace HeavenStudio.InputSystem
bt = mappings[3];
break;
default:
dt = 0;
return false;
}
return GetButtonDown(bt) || BitwiseUtils.WantCurrentAndNotLast(directionStateCurrent, directionStateLast, 1 << (int) direction);
bool btbool = GetButtonDown(bt, out dt);
if (!btbool) dt = 0;
return btbool || BitwiseUtils.WantCurrentAndNotLast(directionStateCurrent, directionStateLast, 1 << (int) direction);
}
public override bool GetHatDirectionUp(InputDirection direction)
public override bool GetHatDirectionUp(InputDirection direction, out double dt)
{
int bt;
switch (direction)
@ -507,9 +516,12 @@ namespace HeavenStudio.InputSystem
bt = mappings[3];
break;
default:
dt = 0;
return false;
}
return GetButtonUp(bt) || BitwiseUtils.WantNotCurrentAndLast(directionStateCurrent, directionStateLast, 1 << (int) direction);
bool btbool = GetButtonUp(bt, out dt);
if (!btbool) dt = 0;
return btbool || BitwiseUtils.WantNotCurrentAndLast(directionStateCurrent, directionStateLast, 1 << (int) direction);
}
public override void SetPlayer(int? playerNum)

View file

@ -113,13 +113,15 @@ namespace HeavenStudio.InputSystem
return Input.GetKey(mappings[button]);
}
public override bool GetButtonDown(int button)
public override bool GetButtonDown(int button, out double dt)
{
dt = 0;
return Input.GetKeyDown(mappings[button]);
}
public override bool GetButtonUp(int button)
public override bool GetButtonUp(int button, out double dt)
{
dt = 0;
return Input.GetKeyUp(mappings[button]);
}
@ -146,8 +148,9 @@ namespace HeavenStudio.InputSystem
}
}
public override bool GetHatDirectionDown(InputDirection direction)
public override bool GetHatDirectionDown(InputDirection direction, out double dt)
{
dt = 0;
switch (direction)
{
case InputDirection.Up:
@ -163,8 +166,9 @@ namespace HeavenStudio.InputSystem
}
}
public override bool GetHatDirectionUp(InputDirection direction)
public override bool GetHatDirectionUp(InputDirection direction, out double dt)
{
dt = 0;
switch (direction)
{
case InputDirection.Up:

View file

@ -162,12 +162,12 @@ namespace HeavenStudio.InputSystem
public abstract int GetLastButtonDown(); // Get the last button down
public abstract KeyCode GetLastKeyDown(); // Get the last key down (used for keyboards and other devices that use Keycode)
public abstract bool GetButton(int button); // is button currently pressed?
public abstract bool GetButtonDown(int button); // is button just pressed?
public abstract bool GetButtonUp(int button); // is button just released?
public abstract bool GetButtonDown(int button, out double dt); // is button just pressed?
public abstract bool GetButtonUp(int button, out double dt); // is button just released?
public abstract float GetAxis(InputAxis axis); // Get the value of an axis
public abstract bool GetHatDirection(InputDirection direction); // is direction active?
public abstract bool GetHatDirectionDown(InputDirection direction); // direction just became active?
public abstract bool GetHatDirectionUp(InputDirection direction); // direction just became inactive?
public abstract bool GetHatDirectionDown(InputDirection direction, out double dt); // direction just became active?
public abstract bool GetHatDirectionUp(InputDirection direction, out double dt); // direction just became inactive?
public abstract void SetPlayer(int? playerNum); // Set the player number (starts at 1, set to -1 or null for no player)
public abstract int? GetPlayer(); // Get the player number (null if no player)

View file

@ -191,13 +191,25 @@ namespace HeavenStudio
public static bool Pressed(bool includeDPad = false)
{
bool keyDown = GetInputController(1).GetButtonDown((int) InputController.ButtonsPad.PadE) || (includeDPad && GetAnyDirectionDown());
return keyDown && !GameManager.instance.autoplay && Conductor.instance.isPlaying && GameManager.instance.canInput ;
bool keyDown = GetInputController(1).GetButtonDown((int) InputController.ButtonsPad.PadE, out _) || (includeDPad && GetAnyDirectionDown());
return keyDown && !GameManager.instance.autoplay && Conductor.instance.isPlaying && GameManager.instance.canInput;
}
public static bool Pressed(out double dt, bool includeDPad = false)
{
bool keyDown = GetInputController(1).GetButtonDown((int) InputController.ButtonsPad.PadE, out dt) || (includeDPad && GetAnyDirectionDown());
return keyDown && !GameManager.instance.autoplay && Conductor.instance.isPlaying && GameManager.instance.canInput;
}
public static bool PressedUp(bool includeDPad = false)
{
bool keyUp = GetInputController(1).GetButtonUp((int) InputController.ButtonsPad.PadE) || (includeDPad && GetAnyDirectionUp());
bool keyUp = GetInputController(1).GetButtonUp((int) InputController.ButtonsPad.PadE, out _) || (includeDPad && GetAnyDirectionUp());
return keyUp && !GameManager.instance.autoplay && Conductor.instance.isPlaying && GameManager.instance.canInput;
}
public static bool PressedUp(out double dt, bool includeDPad = false)
{
bool keyUp = GetInputController(1).GetButtonUp((int) InputController.ButtonsPad.PadE, out dt) || (includeDPad && GetAnyDirectionUp());
return keyUp && !GameManager.instance.autoplay && Conductor.instance.isPlaying && GameManager.instance.canInput;
}
@ -210,13 +222,25 @@ namespace HeavenStudio
public static bool AltPressed()
{
bool down = GetInputController(1).GetButtonDown((int) InputController.ButtonsPad.PadS);
bool down = GetInputController(1).GetButtonDown((int) InputController.ButtonsPad.PadS, out _);
return down && PlayerHasControl();
}
public static bool AltPressed(out double dt)
{
bool down = GetInputController(1).GetButtonDown((int) InputController.ButtonsPad.PadS, out dt);
return down && PlayerHasControl();
}
public static bool AltPressedUp()
{
bool up = GetInputController(1).GetButtonUp((int) InputController.ButtonsPad.PadS);
bool up = GetInputController(1).GetButtonUp((int) InputController.ButtonsPad.PadS, out _);
return up && PlayerHasControl();
}
public static bool AltPressedUp(out double dt)
{
bool up = GetInputController(1).GetButtonUp((int) InputController.ButtonsPad.PadS, out dt);
return up && PlayerHasControl();
}
@ -231,23 +255,45 @@ namespace HeavenStudio
public static bool GetAnyDirectionDown()
{
InputController c = GetInputController(1);
return (c.GetHatDirectionDown((InputController.InputDirection) UP)
|| c.GetHatDirectionDown((InputController.InputDirection) DOWN)
|| c.GetHatDirectionDown((InputController.InputDirection) LEFT)
|| c.GetHatDirectionDown((InputController.InputDirection) RIGHT)
return (c.GetHatDirectionDown((InputController.InputDirection) UP, out _)
|| c.GetHatDirectionDown((InputController.InputDirection) DOWN, out _)
|| c.GetHatDirectionDown((InputController.InputDirection) LEFT, out _)
|| c.GetHatDirectionDown((InputController.InputDirection) RIGHT, out _)
) && PlayerHasControl();
}
public static bool GetAnyDirectionDown(out double dt)
{
InputController c = GetInputController(1);
bool r1 = c.GetHatDirectionDown((InputController.InputDirection)UP, out double d1);
bool r2 = c.GetHatDirectionDown((InputController.InputDirection)DOWN, out double d2);
bool r3 = c.GetHatDirectionDown((InputController.InputDirection)LEFT, out double d3);
bool r4 = c.GetHatDirectionDown((InputController.InputDirection)RIGHT, out double d4);
bool r = (r1 || r2 || r3 || r4) && PlayerHasControl();
dt = Math.Max(Math.Max(Math.Max(d1, d2), d3), d4);
return r;
}
public static bool GetAnyDirectionUp()
{
InputController c = GetInputController(1);
return (c.GetHatDirectionUp((InputController.InputDirection) UP)
|| c.GetHatDirectionUp((InputController.InputDirection) DOWN)
|| c.GetHatDirectionUp((InputController.InputDirection) LEFT)
|| c.GetHatDirectionUp((InputController.InputDirection) RIGHT)
) && PlayerHasControl();
return (c.GetHatDirectionUp((InputController.InputDirection) UP, out _)
|| c.GetHatDirectionUp((InputController.InputDirection) DOWN, out _)
|| c.GetHatDirectionUp((InputController.InputDirection) LEFT, out _)
|| c.GetHatDirectionUp((InputController.InputDirection) RIGHT, out _)
) && PlayerHasControl();
}
public static bool GetAnyDirectionUp(out double dt)
{
InputController c = GetInputController(1);
bool r1 = c.GetHatDirectionUp((InputController.InputDirection)UP, out double d1);
bool r2 = c.GetHatDirectionUp((InputController.InputDirection)DOWN, out double d2);
bool r3 = c.GetHatDirectionUp((InputController.InputDirection)LEFT, out double d3);
bool r4 = c.GetHatDirectionUp((InputController.InputDirection)RIGHT, out double d4);
bool r = (r1 || r2 || r3 || r4) && PlayerHasControl();
dt = Math.Max(Math.Max(Math.Max(d1, d2), d3), d4);
return r;
}
public static bool GetAnyDirection()
@ -258,7 +304,6 @@ namespace HeavenStudio
|| c.GetHatDirection((InputController.InputDirection) LEFT)
|| c.GetHatDirection((InputController.InputDirection) RIGHT)
) && PlayerHasControl();
}
public static bool GetSpecificDirection(int direction)
@ -268,12 +313,22 @@ namespace HeavenStudio
public static bool GetSpecificDirectionDown(int direction)
{
return GetInputController(1).GetHatDirectionDown((InputController.InputDirection) direction) && PlayerHasControl();
return GetInputController(1).GetHatDirectionDown((InputController.InputDirection) direction, out _) && PlayerHasControl();
}
public static bool GetSpecificDirectionUp(int direction)
{
return GetInputController(1).GetHatDirectionUp((InputController.InputDirection) direction) && PlayerHasControl();
return GetInputController(1).GetHatDirectionUp((InputController.InputDirection) direction, out _) && PlayerHasControl();
}
public static bool GetSpecificDirectionDown(int direction, out double dt)
{
return GetInputController(1).GetHatDirectionDown((InputController.InputDirection) direction, out dt) && PlayerHasControl();
}
public static bool GetSpecificDirectionUp(int direction, out double dt)
{
return GetInputController(1).GetHatDirectionUp((InputController.InputDirection) direction, out dt) && PlayerHasControl();
}
}
}

View file

@ -85,7 +85,7 @@ namespace HeavenStudio.Common
void Update()
{
if (isQuitting) return;
if (PlayerInput.GetInputController(1).GetButtonDown((int) InputController.ButtonsPad.PadPause))
if (PlayerInput.GetInputController(1).GetButtonDown((int) InputController.ButtonsPad.PadPause, out _))
{
if (isPaused)
{
@ -98,7 +98,7 @@ namespace HeavenStudio.Common
}
else if (isPaused && canPick && !settingsDialog.IsOpen)
{
if (Input.GetKeyDown(KeyCode.UpArrow) || PlayerInput.GetInputController(1).GetButtonDown((int)InputController.ButtonsPad.PadUp))
if (Input.GetKeyDown(KeyCode.UpArrow) || PlayerInput.GetInputController(1).GetButtonDown((int)InputController.ButtonsPad.PadUp, out _))
{
optionSelected--;
if (optionSelected < 0)
@ -107,7 +107,7 @@ namespace HeavenStudio.Common
}
ChooseOption((Options) optionSelected);
}
else if (Input.GetKeyDown(KeyCode.DownArrow) || PlayerInput.GetInputController(1).GetButtonDown((int)InputController.ButtonsPad.PadDown))
else if (Input.GetKeyDown(KeyCode.DownArrow) || PlayerInput.GetInputController(1).GetButtonDown((int)InputController.ButtonsPad.PadDown, out _))
{
optionSelected++;
if (optionSelected > optionHolder.transform.childCount - 1)
@ -116,7 +116,7 @@ namespace HeavenStudio.Common
}
ChooseOption((Options) optionSelected);
}
else if (Input.GetKeyDown(KeyCode.Return) || PlayerInput.GetInputController(1).GetButtonDown((int)InputController.ButtonsPad.PadE))
else if (Input.GetKeyDown(KeyCode.Return) || PlayerInput.GetInputController(1).GetButtonDown((int)InputController.ButtonsPad.PadE, out _))
{
UseOption((Options) optionSelected);
}