diff --git a/Assets/Plugins/JSL/JoyShockLibrary.cs b/Assets/Plugins/JSL/JoyShockLibrary.cs
index 20cddac06..73acb8037 100644
--- a/Assets/Plugins/JSL/JoyShockLibrary.cs
+++ b/Assets/Plugins/JSL/JoyShockLibrary.cs
@@ -43,11 +43,13 @@ public static class JSL
public const int SplitFull = 3;
// PS5 Player maps for the DS Player Lightbar
- public const int DS5P1 = 4;
- public const int DS5P2 = 10;
- public const int DS5P3 = 21;
- public const int DS5P4 = 27;
- public const int DS5P5 = 31;
+ public static readonly int[] DualSensePlayerMask = {
+ 4,
+ 10,
+ 21,
+ 27,
+ 31
+ };
[StructLayout(LayoutKind.Sequential)]
public struct JOY_SHOCK_STATE
@@ -100,6 +102,8 @@ public static class JSL
public delegate void EventCallback(int handle, JOY_SHOCK_STATE state, JOY_SHOCK_STATE lastState,
IMU_STATE imuState, IMU_STATE lastImuState, float deltaTime);
+
+ public delegate void TouchCallback(int handle, TOUCH_STATE state, TOUCH_STATE lastState, float deltaTime);
[DllImport("JoyShockLibrary")]
public static extern int JslConnectDevices();
@@ -147,7 +151,7 @@ public static class JSL
[DllImport("JoyShockLibrary")]
public static extern void JslSetCallback(EventCallback callback);
[DllImport("JoyShockLibrary")]
- public static extern void JslSetTouchCallback(EventCallback callback);
+ public static extern void JslSetTouchCallback(TouchCallback callback);
[DllImport("JoyShockLibrary")]
public static extern int JslGetControllerType(int deviceId);
diff --git a/Assets/Plugins/JSL/x64/libJoyShockLibrary.so b/Assets/Plugins/JSL/x64/libJoyShockLibrary.so
new file mode 100644
index 000000000..e8d0a5152
Binary files /dev/null and b/Assets/Plugins/JSL/x64/libJoyShockLibrary.so differ
diff --git a/Assets/Plugins/JSL/x64/libJoyShockLibrary.so.meta b/Assets/Plugins/JSL/x64/libJoyShockLibrary.so.meta
new file mode 100644
index 000000000..92c1e3709
--- /dev/null
+++ b/Assets/Plugins/JSL/x64/libJoyShockLibrary.so.meta
@@ -0,0 +1,27 @@
+fileFormatVersion: 2
+guid: c785dbfac2c67974fa1cce056df6404d
+PluginImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ iconMap: {}
+ executionOrder: {}
+ defineConstraints: []
+ isPreloaded: 0
+ isOverridable: 0
+ isExplicitlyReferenced: 0
+ validateReferences: 1
+ platformData:
+ - first:
+ Any:
+ second:
+ enabled: 1
+ settings: {}
+ - first:
+ Editor: Editor
+ second:
+ enabled: 0
+ settings:
+ DefaultValueInitialized: true
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/Scripts/GameManager.cs b/Assets/Scripts/GameManager.cs
index f09a73af1..c59834950 100644
--- a/Assets/Scripts/GameManager.cs
+++ b/Assets/Scripts/GameManager.cs
@@ -198,7 +198,7 @@ namespace HeavenStudio
// LateUpdate works a bit better(?) but causes some bugs (like issues with bop animations).
private void Update()
{
- PlayerInput.UpdateJoyShocks();
+ PlayerInput.UpdateInputControllers();
if (BeatmapEntities() < 1) //bruh really you forgot to ckeck tempo changes
return;
@@ -528,12 +528,5 @@ namespace HeavenStudio
{
HeavenStudio.GameCamera.ResetAdditionalTransforms();
}
-
- void OnApplicationQuit()
- {
- Debug.Log("Disconnecting JoyShocks...");
- JSL.JslSetCallback(null);
- JSL.JslDisconnectAndDisposeAll();
- }
}
}
\ No newline at end of file
diff --git a/Assets/Scripts/GlobalGameManager.cs b/Assets/Scripts/GlobalGameManager.cs
index 64afc14e1..5492cab12 100644
--- a/Assets/Scripts/GlobalGameManager.cs
+++ b/Assets/Scripts/GlobalGameManager.cs
@@ -59,6 +59,7 @@ namespace HeavenStudio
DontDestroyOnLoad(this.gameObject);
instance = this;
Starpelly.OS.ChangeWindowTitle("Heaven Studio DEMO");
+ PlayerInput.InitInputControllers();
}
public static GameObject CreateFade()
@@ -141,5 +142,11 @@ namespace HeavenStudio
MasterVolume = value;
AudioListener.volume = MasterVolume;
}
+
+ void OnApplicationQuit()
+ {
+ Debug.Log("Disconnecting JoyShocks...");
+ PlayerInput.DisconnectJoyshocks();
+ }
}
}
diff --git a/Assets/Scripts/InputSystem.meta b/Assets/Scripts/InputSystem.meta
new file mode 100644
index 000000000..ba6524269
--- /dev/null
+++ b/Assets/Scripts/InputSystem.meta
@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: f0c2ca50a4b8a1b499a3efd717f1daaa
+folderAsset: yes
+DefaultImporter:
+ externalObjects: {}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/Scripts/InputSystem/ControllerTypes.meta b/Assets/Scripts/InputSystem/ControllerTypes.meta
new file mode 100644
index 000000000..721163c81
--- /dev/null
+++ b/Assets/Scripts/InputSystem/ControllerTypes.meta
@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: dc30ca18de2bbc24d984b036097fe60d
+folderAsset: yes
+DefaultImporter:
+ externalObjects: {}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/Scripts/InputSystem/ControllerTypes/InputJoyshock.cs b/Assets/Scripts/InputSystem/ControllerTypes/InputJoyshock.cs
new file mode 100644
index 000000000..d2cf11159
--- /dev/null
+++ b/Assets/Scripts/InputSystem/ControllerTypes/InputJoyshock.cs
@@ -0,0 +1,258 @@
+using System.Collections;
+using System.Collections.Generic;
+using UnityEngine;
+using HeavenStudio.Util;
+
+using static JSL;
+
+namespace HeavenStudio.InputSystem
+{
+ public class InputJoyshock : InputController
+ {
+ static string[] joyShockNames =
+ {
+ "Unknown",
+ "Joy-Con (L)",
+ "Joy-Con (R)",
+ "Pro Controller",
+ "DualShock 4",
+ "DualSense"
+ };
+
+ int[] mappings = new int[]
+ {
+ ButtonMaskUp,
+ ButtonMaskDown,
+ ButtonMaskLeft,
+ ButtonMaskRight,
+ ButtonMaskS,
+ ButtonMaskE,
+ ButtonMaskW,
+ ButtonMaskN,
+ ButtonMaskL,
+ ButtonMaskR,
+ ButtonMaskPlus,
+ };
+
+ int joyshockHandle;
+ int type;
+ int splitType;
+ string joyshockName;
+
+ InputDirection hatDirectionCurrent;
+ InputDirection hatDirectionLast;
+
+ //buttons, sticks, triggers
+ JOY_SHOCK_STATE joyBtStateCurrent, joyBtStateLast;
+ //gyro and accelerometer
+ IMU_STATE joyImuStateCurrent, joyImuStateLast;
+ //touchpad
+ TOUCH_STATE joyTouchStateCurrent, joyTouchStateLast;
+
+ InputJoyshock otherHalf;
+
+ public InputJoyshock(int handle)
+ {
+ joyshockHandle = handle;
+ }
+
+ public override void InitializeController()
+ {
+ joyBtStateCurrent = new JOY_SHOCK_STATE();
+ joyBtStateLast = new JOY_SHOCK_STATE();
+ joyImuStateCurrent = new IMU_STATE();
+ joyImuStateLast = new IMU_STATE();
+ joyTouchStateCurrent = new TOUCH_STATE();
+ joyTouchStateLast = new TOUCH_STATE();
+
+ //FUTURE: remappable controls
+
+ type = JslGetControllerType(joyshockHandle);
+ joyshockName = joyShockNames[type];
+
+ splitType = JslGetControllerSplitType(joyshockHandle);
+ }
+
+ public override void UpdateState()
+ {
+ joyBtStateLast = joyBtStateCurrent;
+ joyBtStateCurrent = JslGetSimpleState(joyshockHandle);
+ }
+
+ public override string GetDeviceName()
+ {
+ if (otherHalf != null)
+ return "Joy-Con Pair";
+ return joyshockName;
+ }
+
+ public override InputFeatures GetFeatures()
+ {
+ InputFeatures features = InputFeatures.Style_Pad | InputFeatures.Style_Baton;
+ switch (type)
+ {
+ case TypeJoyConLeft:
+ features |= InputFeatures.Readable_ShellColour | InputFeatures.Readable_ButtonColour | InputFeatures.Writable_PlayerLED | InputFeatures.Extra_SplitControllerLeft | InputFeatures.Extra_HDRumble;
+ break;
+ case TypeJoyConRight:
+ features |= InputFeatures.Readable_ShellColour | InputFeatures.Readable_ButtonColour | InputFeatures.Writable_PlayerLED | InputFeatures.Extra_SplitControllerRight | InputFeatures.Extra_HDRumble;
+ break;
+ case TypeProController:
+ features |= InputFeatures.Readable_ShellColour | InputFeatures.Readable_ButtonColour | InputFeatures.Readable_LeftGripColour | InputFeatures.Readable_RightGripColour | InputFeatures.Writable_PlayerLED | InputFeatures.Extra_HDRumble;
+ break;
+ case TypeDualShock4:
+ features |= InputFeatures.Readable_AnalogueTriggers | InputFeatures.Readable_Pointer | InputFeatures.Writable_LightBar;
+ break;
+ case TypeDualSense:
+ features |= InputFeatures.Readable_AnalogueTriggers | InputFeatures.Readable_Pointer | InputFeatures.Writable_PlayerLED | InputFeatures.Writable_LightBar;
+ break;
+ }
+ features |= InputFeatures.Readable_MotionSensor | InputFeatures.Extra_Rumble | InputFeatures.Style_Pad | InputFeatures.Style_Baton | InputFeatures.Style_Touch;
+ return features;
+ }
+
+ public override int GetLastButtonDown()
+ {
+ return BitwiseUtils.FirstSetBit(joyBtStateCurrent.buttons & joyBtStateLast.buttons);
+ }
+
+ public override KeyCode GetLastKeyDown()
+ {
+ return KeyCode.None;
+ }
+
+ public override bool GetButton(int button)
+ {
+ return BitwiseUtils.WantCurrent(joyBtStateCurrent.buttons, mappings[button]);
+ }
+
+ public override bool GetButtonDown(int button)
+ {
+ return BitwiseUtils.WantCurrentAndNotLast(joyBtStateCurrent.buttons, joyBtStateLast.buttons, mappings[button]);
+ }
+
+ public override bool GetButtonUp(int button)
+ {
+ return BitwiseUtils.WantNotCurrentAndLast(joyBtStateCurrent.buttons, joyBtStateLast.buttons, mappings[button]);
+ }
+
+ public override float GetAxis(InputAxis axis)
+ {
+ switch (axis)
+ {
+ case InputAxis.AxisLTrigger:
+ return joyBtStateCurrent.lTrigger;
+ case InputAxis.AxisRTrigger:
+ return joyBtStateCurrent.rTrigger;
+ case InputAxis.AxisLStickX:
+ return joyBtStateCurrent.stickLX;
+ case InputAxis.AxisLStickY:
+ return joyBtStateCurrent.stickLY;
+ case InputAxis.AxisRStickX:
+ return joyBtStateCurrent.stickRX;
+ case InputAxis.AxisRStickY:
+ return joyBtStateCurrent.stickRY;
+ case InputAxis.TouchpadX: //isn't updated for now, so always returns 0f
+ //return joyTouchStateCurrent.t0X;
+ case InputAxis.TouchpadY:
+ //return joyTouchStateCurrent.t0Y;
+ default:
+ return 0f;
+ }
+ }
+
+ public override bool GetHatDirection(InputDirection direction)
+ {
+ //todo: check analogue stick hat direction too
+ switch (direction)
+ {
+ case InputDirection.Up:
+ return BitwiseUtils.WantCurrent(joyBtStateCurrent.buttons, ButtonMaskUp);
+ case InputDirection.Down:
+ return BitwiseUtils.WantCurrent(joyBtStateCurrent.buttons, ButtonMaskDown);
+ case InputDirection.Left:
+ return BitwiseUtils.WantCurrent(joyBtStateCurrent.buttons, ButtonMaskLeft);
+ case InputDirection.Right:
+ return BitwiseUtils.WantCurrent(joyBtStateCurrent.buttons, ButtonMaskRight);
+ default:
+ return false;
+ }
+ }
+
+ public override bool GetHatDirectionDown(InputDirection direction)
+ {
+ //todo: check analogue stick hat direction too
+ switch (direction)
+ {
+ case InputDirection.Up:
+ return BitwiseUtils.WantCurrentAndNotLast(joyBtStateCurrent.buttons, joyBtStateLast.buttons, ButtonMaskUp);
+ case InputDirection.Down:
+ return BitwiseUtils.WantCurrentAndNotLast(joyBtStateCurrent.buttons, joyBtStateLast.buttons, ButtonMaskDown);
+ case InputDirection.Left:
+ return BitwiseUtils.WantCurrentAndNotLast(joyBtStateCurrent.buttons, joyBtStateLast.buttons, ButtonMaskLeft);
+ case InputDirection.Right:
+ return BitwiseUtils.WantCurrentAndNotLast(joyBtStateCurrent.buttons, joyBtStateLast.buttons, ButtonMaskRight);
+ default:
+ return false;
+ }
+ }
+
+ public override bool GetHatDirectionUp(InputDirection direction)
+ {
+ //todo: check analogue stick hat direction too
+ switch (direction)
+ {
+ case InputDirection.Up:
+ return BitwiseUtils.WantNotCurrentAndLast(joyBtStateCurrent.buttons, joyBtStateLast.buttons, ButtonMaskUp);
+ case InputDirection.Down:
+ return BitwiseUtils.WantNotCurrentAndLast(joyBtStateCurrent.buttons, joyBtStateLast.buttons, ButtonMaskDown);
+ case InputDirection.Left:
+ return BitwiseUtils.WantNotCurrentAndLast(joyBtStateCurrent.buttons, joyBtStateLast.buttons, ButtonMaskLeft);
+ case InputDirection.Right:
+ return BitwiseUtils.WantNotCurrentAndLast(joyBtStateCurrent.buttons, joyBtStateLast.buttons, ButtonMaskRight);
+ default:
+ return false;
+ }
+ }
+
+ public override void SetPlayer(int playerNum)
+ {
+ if (playerNum == -1)
+ {
+ this.playerNum = null;
+ JslSetPlayerNumber(joyshockHandle, 0);
+ return;
+ }
+ if (type == TypeDualSense)
+ {
+ if (playerNum <= 4)
+ {
+ playerNum = DualSensePlayerMask[playerNum];
+ }
+ }
+ JslSetPlayerNumber(joyshockHandle, playerNum);
+ this.playerNum = playerNum;
+ }
+
+ public override int? GetPlayer()
+ {
+ return this.playerNum;
+ }
+
+ public int GetHandle()
+ {
+ return joyshockHandle;
+ }
+
+ public void DisconnectJoyshock()
+ {
+ if (otherHalf != null)
+ {
+ otherHalf = null;
+ }
+ JslSetRumble(joyshockHandle, 0, 0);
+ JslSetLightColour(joyshockHandle, 0);
+ JslSetPlayerNumber(joyshockHandle, 0);
+ }
+ }
+}
\ No newline at end of file
diff --git a/Assets/Scripts/InputSystem/ControllerTypes/InputJoyshock.cs.meta b/Assets/Scripts/InputSystem/ControllerTypes/InputJoyshock.cs.meta
new file mode 100644
index 000000000..e89224df0
--- /dev/null
+++ b/Assets/Scripts/InputSystem/ControllerTypes/InputJoyshock.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: abe9a6a60f8629440a3cae605aca60a3
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/Scripts/InputSystem/ControllerTypes/InputKeyboard.cs b/Assets/Scripts/InputSystem/ControllerTypes/InputKeyboard.cs
new file mode 100644
index 000000000..601bf8547
--- /dev/null
+++ b/Assets/Scripts/InputSystem/ControllerTypes/InputKeyboard.cs
@@ -0,0 +1,154 @@
+using System.Collections;
+using System.Collections.Generic;
+using UnityEngine;
+
+using static JSL;
+
+namespace HeavenStudio.InputSystem
+{
+ public class InputKeyboard : InputController
+ {
+ static KeyCode[] keyCodes = (KeyCode[]) System.Enum.GetValues(typeof(UnityEngine.KeyCode));
+
+ //FUTURE: remappable controls
+ //KeyCode[] mappings = new KeyCode[Enum.GetNames(typeof(ButtonsPad)).Length];
+ KeyCode[] mappings = new KeyCode[]
+ {
+ KeyCode.UpArrow,
+ KeyCode.DownArrow,
+ KeyCode.LeftArrow,
+ KeyCode.RightArrow,
+ KeyCode.X,
+ KeyCode.Z,
+ KeyCode.C,
+ KeyCode.V,
+ KeyCode.S,
+ KeyCode.D,
+ KeyCode.Return,
+ };
+
+ InputDirection hatDirectionCurrent;
+ InputDirection hatDirectionLast;
+
+ public override void InitializeController()
+ {
+ //FUTURE: remappable controls
+ }
+
+ public override void UpdateState()
+ {
+ // Update the state of the controller
+ }
+
+ public override string GetDeviceName()
+ {
+ return "Keyboard";
+ }
+
+ public override InputFeatures GetFeatures()
+ {
+ return InputFeatures.Readable_StringInput | InputFeatures.Style_Pad | InputFeatures.Style_Baton;
+ }
+
+ public override int GetLastButtonDown()
+ {
+ return 0;
+ }
+
+ public override KeyCode GetLastKeyDown()
+ {
+ for(KeyCode i = keyCodes[1]; i <= KeyCode.Menu; i++) {
+ if (Input.GetKeyDown(i))
+ return i;
+ }
+ return KeyCode.None;
+ }
+
+ public override bool GetButton(int button)
+ {
+ return Input.GetKey(mappings[button]);
+ }
+
+ public override bool GetButtonDown(int button)
+ {
+ return Input.GetKeyDown(mappings[button]);
+ }
+
+ public override bool GetButtonUp(int button)
+ {
+ return Input.GetKeyUp(mappings[button]);
+ }
+
+ public override float GetAxis(InputAxis axis)
+ {
+ return 0;
+ }
+
+ //todo: directionals
+ public override bool GetHatDirection(InputDirection direction)
+ {
+ switch (direction)
+ {
+ case InputDirection.Up:
+ return Input.GetKey(KeyCode.UpArrow);
+ case InputDirection.Down:
+ return Input.GetKey(KeyCode.DownArrow);
+ case InputDirection.Left:
+ return Input.GetKey(KeyCode.LeftArrow);
+ case InputDirection.Right:
+ return Input.GetKey(KeyCode.RightArrow);
+ default:
+ return false;
+ }
+ }
+
+ public override bool GetHatDirectionDown(InputDirection direction)
+ {
+ switch (direction)
+ {
+ case InputDirection.Up:
+ return Input.GetKeyDown(KeyCode.UpArrow);
+ case InputDirection.Down:
+ return Input.GetKeyDown(KeyCode.DownArrow);
+ case InputDirection.Left:
+ return Input.GetKeyDown(KeyCode.LeftArrow);
+ case InputDirection.Right:
+ return Input.GetKeyDown(KeyCode.RightArrow);
+ default:
+ return false;
+ }
+ }
+
+ public override bool GetHatDirectionUp(InputDirection direction)
+ {
+ switch (direction)
+ {
+ case InputDirection.Up:
+ return Input.GetKeyUp(KeyCode.UpArrow);
+ case InputDirection.Down:
+ return Input.GetKeyUp(KeyCode.DownArrow);
+ case InputDirection.Left:
+ return Input.GetKeyUp(KeyCode.LeftArrow);
+ case InputDirection.Right:
+ return Input.GetKeyUp(KeyCode.RightArrow);
+ default:
+ return false;
+ }
+ }
+
+ public override void SetPlayer(int playerNum)
+ {
+ if (playerNum == -1)
+ {
+ this.playerNum = null;
+ return;
+ }
+ this.playerNum = playerNum;
+ }
+
+ public override int? GetPlayer()
+ {
+ return playerNum;
+ }
+ }
+}
\ No newline at end of file
diff --git a/Assets/Scripts/InputSystem/ControllerTypes/InputKeyboard.cs.meta b/Assets/Scripts/InputSystem/ControllerTypes/InputKeyboard.cs.meta
new file mode 100644
index 000000000..038696ccd
--- /dev/null
+++ b/Assets/Scripts/InputSystem/ControllerTypes/InputKeyboard.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 19bccc8eebf390943a5c6d8bc59f4c7f
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/Scripts/InputSystem/InputController.cs b/Assets/Scripts/InputSystem/InputController.cs
new file mode 100644
index 000000000..5996f23ed
--- /dev/null
+++ b/Assets/Scripts/InputSystem/InputController.cs
@@ -0,0 +1,168 @@
+using System.Collections;
+using System.Collections.Generic;
+using UnityEngine;
+
+namespace HeavenStudio.InputSystem
+{
+ ///
+ /// Generic class to allow adapting any type and combination of HIDs to a universal controller format.
+ /// Specifically designed for Heaven Studio, but can be adapted to any use.
+ ///
+ public abstract class InputController
+ {
+ //Buttons and Axis used by most controllers
+ public enum InputButtons : int
+ {
+ ButtonPadUp = 0,
+ ButtonPadDown = 1,
+ ButtonPadLeft = 2,
+ ButtonPadRight = 3,
+ ButtonPlus = 4,
+ ButtonOptions = 4,
+ ButtonMinus = 5,
+ ButtonShare = 5,
+ ButtonLClick = 6,
+ ButtonRClick = 7,
+ ButtonL = 8,
+ ButtonR = 9,
+ ButtonZL = 10,
+ ButtonZR = 11,
+ ButtonFaceS = 12,
+ ButtonFaceE = 13,
+ ButtonFaceW = 14,
+ ButtonFaceN = 15,
+ ButtonHome = 16,
+ ButtonPS = 16,
+ ButtonCapture = 17,
+ ButtonTouchpadClick = 17,
+ ButtonSL = 18,
+ ButtonSR = 19,
+ }
+ public enum InputAxis : int
+ {
+ AxisLTrigger = 4,
+ AxisRTrigger = 5,
+ AxisLStickX = 0,
+ AxisLStickY = 1,
+ AxisRStickX = 2,
+ AxisRStickY = 3,
+ TouchpadX = 6,
+ TouchpadY = 7
+ }
+
+ //D-Pad directions, usable to adapt analogue sticks to cardinal directions
+ public enum InputDirection : int
+ {
+ Up = 0,
+ Right = 1,
+ Down = 2,
+ Left = 3,
+ }
+
+ //Common specific controller features
+ [System.Flags]
+ public enum InputFeatures
+ {
+ //readable properties
+ Readable_ShellColour,
+ Readable_ButtonColour,
+ Readable_LeftGripColour,
+ Readable_RightGripColour,
+ Readable_AnalogueTriggers,
+ Readable_StringInput,
+ Readable_Pointer,
+ Readable_MotionSensor,
+
+ //writable properties
+ Writable_PlayerLED,
+ Writable_LightBar,
+ Writable_Chroma,
+ Writable_Speaker,
+
+ //other / "special" properties
+ Extra_SplitControllerLeft,
+ Extra_SplitControllerRight,
+ Extra_Rumble,
+ Extra_HDRumble,
+
+ //supported control styles
+ Style_Pad,
+ Style_Baton,
+ Style_Touch
+ };
+
+ //Following enums are specific to Heaven Studio, can be removed in other applications
+ //Control styles in Heaven Studio
+ public enum ControlStyles
+ {
+ Pad,
+ Baton,
+ Touch
+ }
+
+ //buttons used in Heaven Studio gameplay (Pad Style)
+ public enum ButtonsPad : int
+ {
+ PadUp = 0,
+ PadDown = 1,
+ PadLeft = 2,
+ PadRight = 3,
+ PadS = 4,
+ PadE = 5,
+ PadW = 6,
+ PadN = 7,
+ PadL = 8,
+ PadR = 9,
+ PadPause = 10,
+ }
+
+ //FUTURE: buttons used in Heaven Studio gameplay ("Form Baton" / WiiMote Style)
+ public enum ButtonsBaton : int
+ {
+ BatonS = 0, //-- all these...
+ BatonE = 1, // |
+ BatonW = 2, // |
+ BatonN = 3, //--
+ BatonA = 4, // < ...map to this, but are directional
+ BatonB = 5, // should never be used alone
+ Baton1 = 6,
+ Baton2 = 7,
+ BatonPause = 8,
+ }
+
+ //FUTURE: buttons used in Heaven Studio gameplay (Touch Style)
+ public enum ButtonsTouch : int
+ {
+ TouchL = 0,
+ TouchR = 1,
+ TouchTap = 2,
+ TouchFlick = 3,
+ TouchButtonL = 4,
+ TouchButtonR = 4,
+ }
+
+ protected int? playerNum;
+
+ public abstract void InitializeController();
+ public abstract void UpdateState(); // Update the state of the controller
+
+ public abstract string GetDeviceName(); // Get the name of the controller
+ public abstract InputFeatures GetFeatures(); // Get the features of the controller
+
+ 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 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 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)
+
+ //public abstract Sprite GetDisplayIcon(); //"big icon" for the controller in the settings menu
+ //public abstract Sprite GetPlaybackIcon(); //"small icon" for the controller during playback
+ }
+}
\ No newline at end of file
diff --git a/Assets/Scripts/InputSystem/InputController.cs.meta b/Assets/Scripts/InputSystem/InputController.cs.meta
new file mode 100644
index 000000000..56dcf1177
--- /dev/null
+++ b/Assets/Scripts/InputSystem/InputController.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: f940937684f598749af06c1297727c4b
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/Scripts/InputSystem/PlayerInput.cs b/Assets/Scripts/InputSystem/PlayerInput.cs
new file mode 100644
index 000000000..7b50cdaa1
--- /dev/null
+++ b/Assets/Scripts/InputSystem/PlayerInput.cs
@@ -0,0 +1,227 @@
+using System.Collections;
+using System.Collections.Generic;
+using UnityEngine;
+using HeavenStudio.InputSystem;
+
+using static JSL;
+
+namespace HeavenStudio
+{
+ public class PlayerInput
+ {
+ //Clockwise
+ public const int UP = 0;
+ public const int RIGHT = 1;
+ public const int DOWN = 2;
+ public const int LEFT = 3;
+
+ ///////////////////////////////
+ ////TEMPORARY JSL FUNCTIONS////
+ ///////////////////////////////
+
+ static int jslDevicesFound = 0;
+ static int jslDevicesConnected = 0;
+ static int[] jslDeviceHandles;
+
+ static List inputDevices;
+
+ public static int InitInputControllers()
+ {
+ inputDevices = new List();
+ //Keyboard setup
+ InputKeyboard keyboard = new InputKeyboard();
+ keyboard.SetPlayer(1);
+ keyboard.InitializeController();
+ inputDevices.Add(keyboard);
+ //end Keyboard setup
+
+ //JoyShock setup
+ Debug.Log("Flushing possible JoyShocks...");
+ DisconnectJoyshocks();
+
+ jslDevicesFound = JslConnectDevices();
+ if (jslDevicesFound > 0)
+ {
+ jslDeviceHandles = new int[jslDevicesFound];
+ jslDevicesConnected = JslGetConnectedDeviceHandles(jslDeviceHandles, jslDevicesFound);
+ if (jslDevicesConnected < jslDevicesFound)
+ {
+ Debug.Log("Found " + jslDevicesFound + " JoyShocks, but only " + jslDevicesConnected + " are connected.");
+ }
+ else
+ {
+ Debug.Log("Found " + jslDevicesFound + " JoyShocks.");
+ Debug.Log("Connected " + jslDevicesConnected + " JoyShocks.");
+ }
+
+ foreach (int i in jslDeviceHandles)
+ {
+ Debug.Log("Setting up JoyShock: ( Handle " + i + ", type " + JslGetControllerType(i) + " )");
+ InputJoyshock joyshock = new InputJoyshock(i);
+ joyshock.InitializeController();
+ joyshock.SetPlayer(inputDevices.Count + 1);
+ }
+ }
+ else
+ {
+ Debug.Log("No JoyShocks found.");
+ }
+ //end JoyShock setup
+
+ //TODO: XInput setup (boo)
+ //end XInput setup
+
+ return inputDevices.Count;
+ }
+
+ public static int GetNumControllersConnected()
+ {
+ return inputDevices.Count;
+ }
+
+ public static List GetInputControllers()
+ {
+ return inputDevices;
+ }
+
+ public static InputController GetInputController(int player)
+ {
+ //select input controller that has player field set to player
+ //this will return the first controller that has that player number in the case of controller pairs (eg. Joy-Cons)
+ //so such controllers should have a reference to the other controller in the pair
+ foreach (InputController i in inputDevices)
+ {
+ if (i.GetPlayer() == player)
+ {
+ return i;
+ }
+ }
+ return null;
+ }
+
+ public static void UpdateInputControllers()
+ {
+ foreach (InputController i in inputDevices)
+ {
+ i.UpdateState();
+ }
+ }
+
+ public static void DisconnectJoyshocks()
+ {
+ if (jslDeviceHandles != null && jslDevicesConnected > 0 && jslDeviceHandles.Length > 0)
+ {
+ foreach (InputController i in inputDevices)
+ {
+ if (typeof(InputJoyshock) == i.GetType())
+ {
+ InputJoyshock joy = (InputJoyshock)i;
+ joy.DisconnectJoyshock();
+ }
+ }
+ }
+ JslDisconnectAndDisposeAll();
+ jslDevicesFound = 0;
+ jslDevicesConnected = 0;
+ }
+
+ // The autoplay isn't activated AND
+ // The song is actually playing AND
+ // The GameManager allows you to Input
+ public static bool playerHasControl()
+ {
+ return !GameManager.instance.autoplay && Conductor.instance.isPlaying && GameManager.instance.canInput;
+ }
+
+ /*--------------------*/
+ /* MAIN INPUT METHODS */
+ /*--------------------*/
+
+ // BUTTONS
+ //TODO: refactor for controller and custom binds, currently uses temporary button checks
+
+ 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 ;
+ }
+
+ public static bool PressedUp(bool includeDPad = false)
+ {
+ bool keyUp = GetInputController(1).GetButtonUp((int) InputController.ButtonsPad.PadE) || (includeDPad && GetAnyDirectionUp());
+ return keyUp && !GameManager.instance.autoplay && Conductor.instance.isPlaying && GameManager.instance.canInput;
+ }
+
+ public static bool Pressing(bool includeDPad = false)
+ {
+ bool pressing = GetInputController(1).GetButton((int) InputController.ButtonsPad.PadE) || (includeDPad && GetAnyDirection());
+ return pressing && !GameManager.instance.autoplay && Conductor.instance.isPlaying && GameManager.instance.canInput;
+ }
+
+
+ public static bool AltPressed()
+ {
+ bool down = GetInputController(1).GetButtonDown((int) InputController.ButtonsPad.PadS);
+ return down && playerHasControl();
+ }
+
+ public static bool AltPressedUp()
+ {
+ bool up = GetInputController(1).GetButtonUp((int) InputController.ButtonsPad.PadS);
+ return up && playerHasControl();
+ }
+
+ public static bool AltPressing()
+ {
+ bool pressing = GetInputController(1).GetButton((int) InputController.ButtonsPad.PadS);
+ return pressing && playerHasControl();
+ }
+
+ //Directions
+
+ public static bool GetAnyDirectionDown()
+ {
+ return (GetInputController(1).GetButtonDown((int) InputController.ButtonsPad.PadUp)
+ || GetInputController(1).GetButtonDown((int) InputController.ButtonsPad.PadDown)
+ || GetInputController(1).GetButtonDown((int) InputController.ButtonsPad.PadLeft)
+ || GetInputController(1).GetButtonDown((int) InputController.ButtonsPad.PadRight)
+ ) && playerHasControl();
+
+ }
+
+ public static bool GetAnyDirectionUp()
+ {
+ return (GetInputController(1).GetButtonUp((int) InputController.ButtonsPad.PadUp)
+ || GetInputController(1).GetButtonUp((int) InputController.ButtonsPad.PadDown)
+ || GetInputController(1).GetButtonUp((int) InputController.ButtonsPad.PadLeft)
+ || GetInputController(1).GetButtonUp((int) InputController.ButtonsPad.PadRight)
+ ) && playerHasControl();
+
+ }
+
+ public static bool GetAnyDirection()
+ {
+ return (GetInputController(1).GetButton((int) InputController.ButtonsPad.PadUp)
+ || GetInputController(1).GetButton((int) InputController.ButtonsPad.PadDown)
+ || GetInputController(1).GetButton((int) InputController.ButtonsPad.PadLeft)
+ || GetInputController(1).GetButton((int) InputController.ButtonsPad.PadRight)
+ ) && playerHasControl();
+
+ }
+
+ public static bool GetSpecificDirection(int direction)
+ {
+ return GetInputController(1).GetHatDirection((InputController.InputDirection) direction) && playerHasControl();
+ }
+
+ public static bool GetSpecificDirectionDown(int direction)
+ {
+ return GetInputController(1).GetHatDirectionDown((InputController.InputDirection) direction) && playerHasControl();
+ }
+
+ public static bool GetSpecificDirectionUp(int direction)
+ {
+ return GetInputController(1).GetHatDirectionUp((InputController.InputDirection) direction) && playerHasControl();
+ }
+ }
+}
\ No newline at end of file
diff --git a/Assets/Scripts/PlayerInput.cs.meta b/Assets/Scripts/InputSystem/PlayerInput.cs.meta
similarity index 83%
rename from Assets/Scripts/PlayerInput.cs.meta
rename to Assets/Scripts/InputSystem/PlayerInput.cs.meta
index 831b948c3..dcfc46fb9 100644
--- a/Assets/Scripts/PlayerInput.cs.meta
+++ b/Assets/Scripts/InputSystem/PlayerInput.cs.meta
@@ -1,5 +1,5 @@
fileFormatVersion: 2
-guid: 9503627b14bba414cae0fbc5da9e4120
+guid: ff41ce113a3b89f4892e362c8ef3d773
MonoImporter:
externalObjects: {}
serializedVersion: 2
diff --git a/Assets/Scripts/LevelEditor/SettingsDialog/Tabs/ControllerSettings.cs b/Assets/Scripts/LevelEditor/SettingsDialog/Tabs/ControllerSettings.cs
index f36340623..721f99ed3 100644
--- a/Assets/Scripts/LevelEditor/SettingsDialog/Tabs/ControllerSettings.cs
+++ b/Assets/Scripts/LevelEditor/SettingsDialog/Tabs/ControllerSettings.cs
@@ -1,8 +1,12 @@
+using System;
+using System.Collections;
+using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using TMPro;
using HeavenStudio;
+using HeavenStudio.InputSystem;
using static JSL;
namespace HeavenStudio.Editor
@@ -11,13 +15,52 @@ namespace HeavenStudio.Editor
{
[SerializeField] private TMP_Text numConnectedLabel;
[SerializeField] private TMP_Text currentControllerLabel;
+ [SerializeField] private TMP_Dropdown controllersDropdown;
+ [SerializeField] private TMP_Dropdown splitControllersDropdown;
+
+ private void Start() {
+ numConnectedLabel.text = "Connected: " + PlayerInput.GetNumControllersConnected();
+ currentControllerLabel.text = "Current Controller: " + PlayerInput.GetInputController(1).GetDeviceName();
+ }
public void SearchAndConnectControllers()
{
- int connected = PlayerInput.InitJoyShocks();
+ int connected = PlayerInput.InitInputControllers();
numConnectedLabel.text = "Connected: " + connected;
- //do this better
- currentControllerLabel.text = "Current Controller: " + PlayerInput.GetJoyShockName(0);
+ currentControllerLabel.text = "Current Controller: " + PlayerInput.GetInputController(1).GetDeviceName();
+ }
+
+ public void populateControllersDropdown()
+ {
+ List dropDownData = new List();
+ var vals = PlayerInput.GetInputControllers();
+ for (int i = 0; i < vals.Count; i++)
+ {
+ TMP_Dropdown.OptionData optionData = new TMP_Dropdown.OptionData();
+ optionData.text = vals[i].GetDeviceName();
+ dropDownData.Add(optionData);
+ }
+ controllersDropdown.AddOptions(dropDownData);
+ controllersDropdown.value = 0;
+ }
+
+ public void populateSplitControllersDropdown()
+ {
+ List dropDownData = new List();
+ var vals = PlayerInput.GetInputControllers();
+ InputController.InputFeatures features;
+ for (int i = 0; i < vals.Count; i++)
+ {
+ features = vals[i].GetFeatures();
+ if (features.HasFlag(InputController.InputFeatures.Extra_SplitControllerLeft) || features.HasFlag(InputController.InputFeatures.Extra_SplitControllerRight))
+ {
+ TMP_Dropdown.OptionData optionData = new TMP_Dropdown.OptionData();
+ optionData.text = vals[i].GetDeviceName();
+ dropDownData.Add(optionData);
+ }
+ }
+ splitControllersDropdown.AddOptions(dropDownData);
+ splitControllersDropdown.value = 0;
}
}
}
\ No newline at end of file
diff --git a/Assets/Scripts/PlayerInput.cs b/Assets/Scripts/PlayerInput.cs
deleted file mode 100644
index 7ebf0d8b8..000000000
--- a/Assets/Scripts/PlayerInput.cs
+++ /dev/null
@@ -1,319 +0,0 @@
-using System.Collections;
-using System.Collections.Generic;
-using UnityEngine;
-
-using static JSL;
-
-namespace HeavenStudio
-{
- public class PlayerInput
- {
- ///////////////////////////////
- ////TEMPORARY JSL FUNCTIONS////
- ///////////////////////////////
- static string[] joyShockNames =
- {
- "Unknown",
- "Joy-Con (L)",
- "Joy-Con (R)",
- "Pro Controller",
- "DualShock 4",
- "DualSense"
- };
-
- static int numDevicesFound = 0;
- static int numDevicesConnected = 0;
- static int[] deviceHandles;
-
- static Dictionary joyBtStateCurrent;
- static Dictionary joyBtStateLast;
-
- static Dictionary joyImuStateCurrent;
- static Dictionary joyImuStateLast;
-
- public static int InitJoyShocks()
- {
- //flush old joyshocks
- Debug.Log("Flushing possible JoyShocks...");
- JslDisconnectAndDisposeAll();
-
- numDevicesFound = 0;
- numDevicesConnected = 0;
-
- numDevicesFound = JslConnectDevices();
- if (numDevicesFound > 0)
- {
- deviceHandles = new int[numDevicesFound];
- numDevicesConnected = JslGetConnectedDeviceHandles(deviceHandles, numDevicesFound);
- joyBtStateCurrent = new Dictionary();
- joyBtStateLast = new Dictionary();
- if (numDevicesConnected < numDevicesFound)
- {
- Debug.Log("Found " + numDevicesFound + " JoyShocks, but only " + numDevicesConnected + " are connected.");
- }
- else
- {
- Debug.Log("Found " + numDevicesFound + " JoyShocks.");
- Debug.Log("Connected " + numDevicesConnected + " JoyShocks.");
- }
-
- foreach (int i in deviceHandles)
- {
- Debug.Log("Setting up JoyShock: " + joyShockNames[JslGetControllerType(i)] + " ( Player " + i + ", type " + JslGetControllerType(i) + " )");
- }
- return numDevicesConnected;
- }
- else
- {
- Debug.Log("No JoyShocks found.");
- return 0;
- }
- }
-
- public static string GetJoyShockName(int playerNum)
- {
- return joyShockNames[JslGetControllerType(deviceHandles[playerNum])];
- }
-
- public static void UpdateJoyShocks()
- {
- if (deviceHandles == null || numDevicesConnected == 0) return;
- foreach (var id in deviceHandles)
- {
- if (joyBtStateCurrent.ContainsKey(id))
- {
- joyBtStateLast[id] = joyBtStateCurrent[id];
- }
- else
- {
- joyBtStateLast[id] = new JOY_SHOCK_STATE();
- }
- joyBtStateCurrent[id] = JslGetSimpleState(id);
- }
- }
-
- //TODO: refactor to allow controller selection (and for split controllers, multiple controllers)
- static bool GetJoyBtDown(int bt)
- {
- if (deviceHandles == null || numDevicesConnected <= 0) // <= player number in the future
- {
- return false;
- }
- bt = 1 << bt;
- int p1Id = deviceHandles[0];
- try
- {
- int curBt = joyBtStateCurrent[p1Id].buttons;
- int oldBt = joyBtStateLast[p1Id].buttons;
- return ((curBt & bt) == bt) && ((oldBt & bt) != bt);
- }
- catch (System.Exception)
- {
- return false;
- }
- }
- static bool GetJoyBt(int bt)
- {
- if (deviceHandles == null || numDevicesConnected <= 0) // <= player number in the future
- {
- return false;
- }
- bt = 1 << bt;
- int p1Id = deviceHandles[0];
- try
- {
- int curBt = joyBtStateCurrent[p1Id].buttons;
- return (curBt & bt) == bt;
- }
- catch (System.Exception)
- {
- return false;
- }
-
- }
-
- static bool GetJoyBtUp(int bt)
- {
- if (deviceHandles == null || numDevicesConnected <= 0) // <= player number in the future
- {
- return false;
- }
- bt = 1 << bt;
- int p1Id = deviceHandles[0];
- try
- {
- int curBt = joyBtStateCurrent[p1Id].buttons;
- int oldBt = joyBtStateLast[p1Id].buttons;
- return ((curBt & bt) != bt) && ((oldBt & bt) == bt);
- }
- catch (System.Exception)
- {
- return false;
- }
-
- }
-
- ////END TEMPORARY JSL FUNCTIONS
- ///////////////////////////////
-
- //Clockwise
- public const int UP = 0;
- public const int RIGHT = 1;
- public const int DOWN = 2;
- public const int LEFT = 3;
-
- // The autoplay isn't activated AND
- // The song is actually playing AND
- // The GameManager allows you to Input
- public static bool playerHasControl()
- {
- return !GameManager.instance.autoplay && Conductor.instance.isPlaying && GameManager.instance.canInput;
- }
-
- /*--------------------*/
- /* MAIN INPUT METHODS */
- /*--------------------*/
-
- // BUTTONS
- //TODO: refactor for controller and custom binds, currently uses temporary button checks
-
- public static bool Pressed(bool includeDPad = false)
- {
- bool keyDown = Input.GetKeyDown(KeyCode.Z) || GetJoyBtDown(ButtonMaskE) || (includeDPad && GetAnyDirectionDown());
- return keyDown && !GameManager.instance.autoplay && Conductor.instance.isPlaying && GameManager.instance.canInput ;
- }
-
- public static bool PressedUp(bool includeDPad = false)
- {
- bool keyUp = Input.GetKeyUp(KeyCode.Z) || GetJoyBtUp(ButtonMaskE) || (includeDPad && GetAnyDirectionUp());
- return keyUp && !GameManager.instance.autoplay && Conductor.instance.isPlaying && GameManager.instance.canInput;
- }
-
- public static bool Pressing(bool includeDPad = false)
- {
- bool pressing = Input.GetKey(KeyCode.Z) || GetJoyBt(ButtonMaskE) || (includeDPad && GetAnyDirection());
- return pressing && !GameManager.instance.autoplay && Conductor.instance.isPlaying && GameManager.instance.canInput;
- }
-
-
- public static bool AltPressed()
- {
- bool down = Input.GetKeyDown(KeyCode.X) || GetJoyBtDown(ButtonMaskS);
- return down && playerHasControl();
- }
-
- public static bool AltPressedUp()
- {
- bool up = Input.GetKeyUp(KeyCode.X) || GetJoyBtUp(ButtonMaskS);
- return up && playerHasControl();
- }
-
- public static bool AltPressing()
- {
- bool pressing = Input.GetKey(KeyCode.X) || GetJoyBt(ButtonMaskS);
- return pressing && playerHasControl();
- }
-
- //Directions
-
- public static bool GetAnyDirectionDown()
- {
- return (Input.GetKeyDown(KeyCode.UpArrow)
- || Input.GetKeyDown(KeyCode.DownArrow)
- || Input.GetKeyDown(KeyCode.LeftArrow)
- || Input.GetKeyDown(KeyCode.RightArrow)
-
- || GetJoyBtDown(ButtonMaskUp)
- || GetJoyBtDown(ButtonMaskDown)
- || GetJoyBtDown(ButtonMaskLeft)
- || GetJoyBtDown(ButtonMaskRight)
- ) && playerHasControl();
-
- }
-
- public static bool GetAnyDirectionUp()
- {
- return (Input.GetKeyUp(KeyCode.UpArrow)
- || Input.GetKeyUp(KeyCode.DownArrow)
- || Input.GetKeyUp(KeyCode.LeftArrow)
- || Input.GetKeyUp(KeyCode.RightArrow)
-
- || GetJoyBtUp(ButtonMaskUp)
- || GetJoyBtUp(ButtonMaskDown)
- || GetJoyBtUp(ButtonMaskLeft)
- || GetJoyBtUp(ButtonMaskRight)
- ) && playerHasControl();
-
- }
-
- public static bool GetAnyDirection()
- {
- return (Input.GetKey(KeyCode.UpArrow)
- || Input.GetKey(KeyCode.DownArrow)
- || Input.GetKey(KeyCode.LeftArrow)
- || Input.GetKey(KeyCode.RightArrow)
-
- || GetJoyBt(ButtonMaskUp)
- || GetJoyBt(ButtonMaskDown)
- || GetJoyBt(ButtonMaskLeft)
- || GetJoyBt(ButtonMaskRight)
- ) && playerHasControl();
-
- }
-
- public static bool GetSpecificDirectionDown(int direction)
- {
- KeyCode targetCode = getKeyCode(direction);
- if (targetCode == KeyCode.None) return false;
-
- int targetMask = getButtonMask(direction);
- if (targetMask == 0) return false;
- return (Input.GetKeyDown(targetCode) || GetJoyBtDown(targetMask)) && playerHasControl();
- }
-
- public static bool GetSpecificDirectionUp(int direction)
- {
- KeyCode targetCode = getKeyCode(direction);
- if (targetCode == KeyCode.None) return false;
-
- int targetMask = getButtonMask(direction);
- if (targetMask == 0) return false;
-
- return (Input.GetKeyUp(targetCode) || GetJoyBtUp(targetMask)) && playerHasControl();
- }
-
-
- private static KeyCode getKeyCode(int direction)
- {
- KeyCode targetKeyCode;
-
- switch (direction)
- {
- case PlayerInput.UP: targetKeyCode = KeyCode.UpArrow; break;
- case PlayerInput.DOWN: targetKeyCode = KeyCode.DownArrow; break;
- case PlayerInput.LEFT: targetKeyCode = KeyCode.LeftArrow; break;
- case PlayerInput.RIGHT: targetKeyCode = KeyCode.RightArrow; break;
- default: targetKeyCode = KeyCode.None; break;
- }
-
- return targetKeyCode;
- }
-
- private static int getButtonMask(int direction)
- {
- int targetKeyCode;
-
- switch (direction)
- {
- case PlayerInput.UP: targetKeyCode = ButtonMaskUp; break;
- case PlayerInput.DOWN: targetKeyCode = ButtonMaskDown; break;
- case PlayerInput.LEFT: targetKeyCode = ButtonMaskLeft; break;
- case PlayerInput.RIGHT: targetKeyCode = ButtonMaskRight; break;
- default: targetKeyCode = -1; break;
- }
-
- return targetKeyCode;
- }
-
- }
-}
\ No newline at end of file
diff --git a/Assets/Scripts/Util/BitwiseUtils.cs b/Assets/Scripts/Util/BitwiseUtils.cs
new file mode 100644
index 000000000..df5c98b97
--- /dev/null
+++ b/Assets/Scripts/Util/BitwiseUtils.cs
@@ -0,0 +1,50 @@
+using System;
+using System.Collections;
+using System.Collections.Generic;
+
+namespace HeavenStudio.Util
+{
+ public static class BitwiseUtils
+ {
+ ///
+ /// Returns the value of the lowest set bit in the given integer.
+ ///
+ /// The integer to check.
+ public static int FirstSetBit(int num)
+ {
+ return num & (-num);
+ }
+
+ ///
+ /// Returns true if the wanted bit is set in the given integer.
+ ///
+ /// The integer to check.
+ /// The bit(s) to check for.
+ public static bool WantCurrent(int num, int want)
+ {
+ return (num & want) == want;
+ }
+
+ ///
+ /// Returns true if the wanted bit is set in the first integer, and not in the second.
+ ///
+ /// The first integer to check.
+ /// The second integer to check.
+ /// The bit(s) to check for.
+ public static bool WantCurrentAndNotLast(int num1, int num2, int want)
+ {
+ return ((num1 & want) == want) && ((num2 & want) != want);
+ }
+
+ ///
+ /// Returns true if the wanted bit is not set in the first integer, but set in the second.
+ ///
+ /// The first integer to check.
+ /// The second integer to check.
+ /// The bit(s) to check for.
+ public static bool WantNotCurrentAndLast(int num1, int num2, int want)
+ {
+ return ((num1 & want) != want) && ((num2 & want) == want);
+ }
+ }
+}
\ No newline at end of file
diff --git a/Assets/Scripts/Util/BitwiseUtils.cs.meta b/Assets/Scripts/Util/BitwiseUtils.cs.meta
new file mode 100644
index 000000000..5b00a3b63
--- /dev/null
+++ b/Assets/Scripts/Util/BitwiseUtils.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 18f088a4c3c17b143a1985f3cee5d90a
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant: