Merge pull request #137 from minenice55/controller-support

Controller Support
This commit is contained in:
minenice55 2022-07-24 18:43:26 -04:00 committed by GitHub
commit 0245cb2b1f
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
55 changed files with 7781 additions and 142 deletions

View file

@ -28,7 +28,7 @@ PluginImporter:
second:
enabled: 1
settings:
CPU: x86_64
CPU: AnyCPU
- first:
Standalone: OSXUniversal
second:

View file

@ -28,7 +28,7 @@ PluginImporter:
second:
enabled: 1
settings:
CPU: x86_64
CPU: AnyCPU
- first:
Standalone: OSXUniversal
second:

View file

@ -28,7 +28,7 @@ PluginImporter:
second:
enabled: 1
settings:
CPU: x86_64
CPU: AnyCPU
- first:
Standalone: OSXUniversal
second:

8
Assets/Plugins/JSL.meta Normal file
View file

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 5dfbaa1e85cf84f4c861f39c4d935a61
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,176 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using UnityEditor;
using UnityEngine;
public static class JSL
{
public const int ButtonMaskUp = 0;
public const int ButtonMaskDown = 1;
public const int ButtonMaskLeft = 2;
public const int ButtonMaskRight = 3;
public const int ButtonMaskPlus = 4;
public const int ButtonMaskOptions = 4;
public const int ButtonMaskMinus = 5;
public const int ButtonMaskShare = 5;
public const int ButtonMaskLClick = 6;
public const int ButtonMaskRClick = 7;
public const int ButtonMaskL = 8;
public const int ButtonMaskR = 9;
public const int ButtonMaskZL = 10;
public const int ButtonMaskZR = 11;
public const int ButtonMaskS = 12;
public const int ButtonMaskE = 13;
public const int ButtonMaskW = 14;
public const int ButtonMaskN = 15;
public const int ButtonMaskHome = 16;
public const int ButtonMaskPS = 16;
public const int ButtonMaskCapture = 17;
public const int ButtonMaskTouchpadClick = 17;
public const int ButtonMaskSL = 18;
public const int ButtonMaskSR = 19;
public const int TypeJoyConLeft = 1;
public const int TypeJoyConRight = 2;
public const int TypeProController = 3;
public const int TypeDualShock4 = 4;
public const int TypeDualSense = 5;
public const int SplitLeft = 1;
public const int SplitRight = 2;
public const int SplitFull = 3;
// PS5 Player maps for the DS Player Lightbar
public static readonly int[] DualSensePlayerMask = {
4,
10,
21,
27,
31
};
[StructLayout(LayoutKind.Sequential)]
public struct JOY_SHOCK_STATE
{
public int buttons;
public float lTrigger;
public float rTrigger;
public float stickLX;
public float stickLY;
public float stickRX;
public float stickRY;
}
[StructLayout(LayoutKind.Sequential)]
public struct IMU_STATE
{
public float accelX;
public float accelY;
public float accelZ;
public float gyroX;
public float gyroY;
public float gyroZ;
}
[StructLayout(LayoutKind.Sequential)]
public struct MOTION_STATE {
float quatW;
float quatX;
float quatY;
float quatZ;
float accelX;
float accelY;
float accelZ;
float gravX;
float gravY;
float gravZ;
}
[StructLayout(LayoutKind.Sequential)]
public struct TOUCH_STATE {
int t0Id;
int t1Id;
bool t0Down;
bool t1Down;
float t0X;
float t0Y;
float t1X;
float t1Y;
}
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();
[DllImport("JoyShockLibrary")]
public static extern int JslGetConnectedDeviceHandles(int[] deviceHandleArray, int size);
[DllImport("JoyShockLibrary")]
public static extern void JslDisconnectAndDisposeAll();
[DllImport("JoyShockLibrary", CallingConvention = CallingConvention.Cdecl)]
public static extern JOY_SHOCK_STATE JslGetSimpleState(int deviceId);
[DllImport("JoyShockLibrary", CallingConvention = CallingConvention.Cdecl)]
public static extern IMU_STATE JslGetIMUState(int deviceId);
[DllImport("JoyShockLibrary", CallingConvention = CallingConvention.Cdecl)]
public static extern MOTION_STATE JslGetMotionState(int deviceId);
[DllImport("JoyShockLibrary", CallingConvention = CallingConvention.Cdecl)]
public static extern TOUCH_STATE JslGetTouchState(int deviceId);
[DllImport("JoyShockLibrary")]
public static extern float JslGetStickStep(int deviceId);
[DllImport("JoyShockLibrary")]
public static extern float JslGetTriggerStep(int deviceId);
[DllImport("JoyShockLibrary")]
public static extern float JslGetPollRate(int deviceId);
[DllImport("JoyShockLibrary")]
public static extern float JslGetTouchId(int deviceId, bool secondTouch = false);
[DllImport("JoyShockLibrary")]
public static extern float JslGetTouchDown(int deviceId, bool secondTouch = false);
[DllImport("JoyShockLibrary")]
public static extern float JslGetTouchX(int deviceId, bool secondTouch = false);
[DllImport("JoyShockLibrary")]
public static extern float JslGetTouchY(int deviceId, bool secondTouch = false);
[DllImport("JoyShockLibrary")]
public static extern void JslResetContinuousCalibration(int deviceId);
[DllImport("JoyShockLibrary")]
public static extern void JslStartContinuousCalibration(int deviceId);
[DllImport("JoyShockLibrary")]
public static extern void JslPauseContinuousCalibration(int deviceId);
[DllImport("JoyShockLibrary")]
public static extern void JslGetCalibrationOffset(int deviceId, ref float xOffset, ref float yOffset, ref float zOffset);
[DllImport("JoyShockLibrary")]
public static extern void JslGetCalibrationOffset(int deviceId, float xOffset, float yOffset, float zOffset);
[DllImport("JoyShockLibrary")]
public static extern void JslSetCallback(EventCallback callback);
[DllImport("JoyShockLibrary")]
public static extern void JslSetTouchCallback(TouchCallback callback);
[DllImport("JoyShockLibrary")]
public static extern int JslGetControllerType(int deviceId);
[DllImport("JoyShockLibrary")]
public static extern int JslGetControllerSplitType(int deviceId);
[DllImport("JoyShockLibrary")]
public static extern int JslGetControllerColour(int deviceId);
[DllImport("JoyShockLibrary")]
public static extern int JslGetControllerButtonColour(int deviceId);
[DllImport("JoyShockLibrary")]
public static extern int JslGetControllerLeftGripColour(int deviceId);
[DllImport("JoyShockLibrary")]
public static extern int JslGetControllerRightGripColour(int deviceId);
[DllImport("JoyShockLibrary")]
public static extern void JslSetLightColour(int deviceId, int colour);
[DllImport("JoyShockLibrary")]
public static extern void JslSetRumble(int deviceId, int smallRumble, int bigRumble);
[DllImport("JoyShockLibrary")]
public static extern void JslSetRumbleFrequency(int deviceId, float smallRumble, float bigRumble, float smallFrequency, float bigFrequency);
[DllImport("JoyShockLibrary")]
public static extern void JslSetPlayerNumber(int deviceId, int number);
}

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: dce4133e93426bb40a13278c4f90e742
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,217 @@
// JoyShockLibrary.h - Contains declarations of functions
#pragma once
#if _MSC_VER // this is defined when compiling with Visual Studio
#define JOY_SHOCK_API __declspec(dllexport) // Visual Studio needs annotating exported functions with this
#else
#define JOY_SHOCK_API // XCode does not need annotating exported functions, so define is empty
#endif
#define JS_TYPE_JOYCON_LEFT 1
#define JS_TYPE_JOYCON_RIGHT 2
#define JS_TYPE_PRO_CONTROLLER 3
#define JS_TYPE_DS4 4
#define JS_TYPE_DS 5
#define JS_SPLIT_TYPE_LEFT 1
#define JS_SPLIT_TYPE_RIGHT 2
#define JS_SPLIT_TYPE_FULL 3
#define JSMASK_UP 0x00001
#define JSMASK_DOWN 0x00002
#define JSMASK_LEFT 0x00004
#define JSMASK_RIGHT 0x00008
#define JSMASK_PLUS 0x00010
#define JSMASK_OPTIONS 0x00010
#define JSMASK_MINUS 0x00020
#define JSMASK_SHARE 0x00020
#define JSMASK_LCLICK 0x00040
#define JSMASK_RCLICK 0x00080
#define JSMASK_L 0x00100
#define JSMASK_R 0x00200
#define JSMASK_ZL 0x00400
#define JSMASK_ZR 0x00800
#define JSMASK_S 0x01000
#define JSMASK_E 0x02000
#define JSMASK_W 0x04000
#define JSMASK_N 0x08000
#define JSMASK_HOME 0x10000
#define JSMASK_PS 0x10000
#define JSMASK_CAPTURE 0x20000
#define JSMASK_TOUCHPAD_CLICK 0x20000
#define JSMASK_MIC 0x40000
#define JSMASK_SL 0x40000
#define JSMASK_SR 0x80000
#define JSOFFSET_UP 0
#define JSOFFSET_DOWN 1
#define JSOFFSET_LEFT 2
#define JSOFFSET_RIGHT 3
#define JSOFFSET_PLUS 4
#define JSOFFSET_OPTIONS 4
#define JSOFFSET_MINUS 5
#define JSOFFSET_SHARE 5
#define JSOFFSET_LCLICK 6
#define JSOFFSET_RCLICK 7
#define JSOFFSET_L 8
#define JSOFFSET_R 9
#define JSOFFSET_ZL 10
#define JSOFFSET_ZR 11
#define JSOFFSET_S 12
#define JSOFFSET_E 13
#define JSOFFSET_W 14
#define JSOFFSET_N 15
#define JSOFFSET_HOME 16
#define JSOFFSET_PS 16
#define JSOFFSET_CAPTURE 17
#define JSOFFSET_TOUCHPAD_CLICK 17
#define JSOFFSET_MIC 18
#define JSOFFSET_SL 18
#define JSOFFSET_SR 19
// PS5 Player maps for the DS Player Lightbar
#define DS5_PLAYER_1 = 4
#define DS5_PLAYER_2 = 10
#define DS5_PLAYER_3 = 21
#define DS5_PLAYER_4 = 27
#define DS5_PLAYER_5 = 31
typedef struct JOY_SHOCK_STATE {
int buttons;
float lTrigger;
float rTrigger;
float stickLX;
float stickLY;
float stickRX;
float stickRY;
} JOY_SHOCK_STATE;
typedef struct IMU_STATE {
float accelX;
float accelY;
float accelZ;
float gyroX;
float gyroY;
float gyroZ;
} IMU_STATE;
typedef struct MOTION_STATE {
float quatW;
float quatX;
float quatY;
float quatZ;
float accelX;
float accelY;
float accelZ;
float gravX;
float gravY;
float gravZ;
} MOTION_STATE;
typedef struct TOUCH_STATE {
int t0Id;
int t1Id;
bool t0Down;
bool t1Down;
float t0X;
float t0Y;
float t1X;
float t1Y;
} TOUCH_STATE;
extern "C" JOY_SHOCK_API int JslConnectDevices();
extern "C" JOY_SHOCK_API int JslGetConnectedDeviceHandles(int* deviceHandleArray, int size);
extern "C" JOY_SHOCK_API void JslDisconnectAndDisposeAll();
// get buttons as bits in the following order, using North South East West to name face buttons to avoid ambiguity between Xbox and Nintendo layouts:
// 0x00001: up
// 0x00002: down
// 0x00004: left
// 0x00008: right
// 0x00010: plus
// 0x00020: minus
// 0x00040: left stick click
// 0x00080: right stick click
// 0x00100: L
// 0x00200: R
// ZL and ZR are reported as analogue inputs (GetLeftTrigger, GetRightTrigger), because DS4 and XBox controllers use analogue triggers, but we also have them as raw buttons
// 0x00400: ZL
// 0x00800: ZR
// 0x01000: S
// 0x02000: E
// 0x04000: W
// 0x08000: N
// 0x10000: home / PS
// 0x20000: capture / touchpad-click
// 0x40000: SL
// 0x80000: SR
// These are the best way to get all the buttons/triggers/sticks, gyro/accelerometer (IMU), orientation/acceleration/gravity (Motion), or touchpad
extern "C" JOY_SHOCK_API JOY_SHOCK_STATE JslGetSimpleState(int deviceId);
extern "C" JOY_SHOCK_API IMU_STATE JslGetIMUState(int deviceId);
extern "C" JOY_SHOCK_API MOTION_STATE JslGetMotionState(int deviceId);
extern "C" JOY_SHOCK_API TOUCH_STATE JslGetTouchState(int deviceId, bool previous = false);
extern "C" JOY_SHOCK_API bool JslGetTouchpadDimension(int deviceId, int &sizeX, int &sizeY);
extern "C" JOY_SHOCK_API int JslGetButtons(int deviceId);
// get thumbsticks
extern "C" JOY_SHOCK_API float JslGetLeftX(int deviceId);
extern "C" JOY_SHOCK_API float JslGetLeftY(int deviceId);
extern "C" JOY_SHOCK_API float JslGetRightX(int deviceId);
extern "C" JOY_SHOCK_API float JslGetRightY(int deviceId);
// get triggers. Switch controllers don't have analogue triggers, but will report 0.0 or 1.0 so they can be used in the same way as others
extern "C" JOY_SHOCK_API float JslGetLeftTrigger(int deviceId);
extern "C" JOY_SHOCK_API float JslGetRightTrigger(int deviceId);
// get gyro
extern "C" JOY_SHOCK_API float JslGetGyroX(int deviceId);
extern "C" JOY_SHOCK_API float JslGetGyroY(int deviceId);
extern "C" JOY_SHOCK_API float JslGetGyroZ(int deviceId);
// get accelerometor
extern "C" JOY_SHOCK_API float JslGetAccelX(int deviceId);
extern "C" JOY_SHOCK_API float JslGetAccelY(int deviceId);
extern "C" JOY_SHOCK_API float JslGetAccelZ(int deviceId);
// get touchpad
extern "C" JOY_SHOCK_API int JslGetTouchId(int deviceId, bool secondTouch = false);
extern "C" JOY_SHOCK_API bool JslGetTouchDown(int deviceId, bool secondTouch = false);
extern "C" JOY_SHOCK_API float JslGetTouchX(int deviceId, bool secondTouch = false);
extern "C" JOY_SHOCK_API float JslGetTouchY(int deviceId, bool secondTouch = false);
// analog parameters have different resolutions depending on device
extern "C" JOY_SHOCK_API float JslGetStickStep(int deviceId);
extern "C" JOY_SHOCK_API float JslGetTriggerStep(int deviceId);
extern "C" JOY_SHOCK_API float JslGetPollRate(int deviceId);
// calibration
extern "C" JOY_SHOCK_API void JslResetContinuousCalibration(int deviceId);
extern "C" JOY_SHOCK_API void JslStartContinuousCalibration(int deviceId);
extern "C" JOY_SHOCK_API void JslPauseContinuousCalibration(int deviceId);
extern "C" JOY_SHOCK_API void JslSetAutomaticCalibration(int deviceId, bool enabled);
extern "C" JOY_SHOCK_API void JslGetCalibrationOffset(int deviceId, float& xOffset, float& yOffset, float& zOffset);
extern "C" JOY_SHOCK_API void JslSetCalibrationOffset(int deviceId, float xOffset, float yOffset, float zOffset);
// this function will get called for each input event from each controller
extern "C" JOY_SHOCK_API void JslSetCallback(void(*callback)(int, JOY_SHOCK_STATE, JOY_SHOCK_STATE, IMU_STATE, IMU_STATE, float));
// this function will get called for each input event, even if touch data didn't update
extern "C" JOY_SHOCK_API void JslSetTouchCallback(void(*callback)(int, TOUCH_STATE, TOUCH_STATE, float));
// what kind of controller is this?
extern "C" JOY_SHOCK_API int JslGetControllerType(int deviceId);
// is this a left, right, or full controller?
extern "C" JOY_SHOCK_API int JslGetControllerSplitType(int deviceId);
// what colour is the controller (not all controllers support this; those that don't will report white)
extern "C" JOY_SHOCK_API int JslGetControllerColour(int deviceId);
extern "C" JOY_SHOCK_API int JslGetControllerButtonColour(int deviceId);
extern "C" JOY_SHOCK_API int JslGetControllerLeftGripColour(int deviceId);
extern "C" JOY_SHOCK_API int JslGetControllerRightGripColour(int deviceId);
// set controller light colour (not all controllers have a light whose colour can be set, but that just means nothing will be done when this is called -- no harm)
extern "C" JOY_SHOCK_API void JslSetLightColour(int deviceId, int colour);
// set controller rumble
extern "C" JOY_SHOCK_API void JslSetRumble(int deviceId, int smallRumble, int bigRumble);
extern "C" JOY_SHOCK_API void JslSetRumbleFrequency(int deviceId, float smallRumble, float bigRumble, float smallFrequency, float bigFrequency);
// set controller player number indicator (not all controllers have a number indicator which can be set, but that just means nothing will be done when this is called -- no harm)
extern "C" JOY_SHOCK_API void JslSetPlayerNumber(int deviceId, int number);

View file

@ -0,0 +1,27 @@
fileFormatVersion: 2
guid: 129c872137ca57441bd8e920a0caceef
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:

View file

@ -0,0 +1,30 @@
### MIT License
Copyright 2018-2021 Julian Smart
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
---
This software incorporates some work from the following projects and their copyright holders, all also covered by the same MIT license, with the same permissions and disclaimers:
* mfosse's JoyCon-Driver (JoyCon driver), Copyright 2018 Matthew Fosse: https://github.com/mfosse/JoyCon-Driver
* chrippa's ds4drv (DualShock 4 driver), Copyright 2013-2014 Christopher Rosell: https://github.com/chrippa/ds4drv
* Ryochan7 and Jay2Kings' DS4Windows (DualShock 4 input mapper), Copyright 2019 Travis Nickles: https://github.com/Ryochan7/DS4Windows
---
This software also links to signal11's HIDAPI, and includes the source thereof in case it's needed for future builds. HIDAPI has its own permissive license: https://github.com/signal11/hidapi
HIDAPI - Multi-Platform library for
communication with HID devices.
Copyright 2009, Alan Ott, Signal 11 Software.
All Rights Reserved.
This software may be used by anyone for any reason so
long as the copyright notice in the source files
remains intact.

View file

@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: 8aac471e2ae4e2c4691e7ebf7305175f
TextScriptImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,179 @@
# JoyShockLibrary
The Sony PlayStation's DualShock 4, DualSense, Nintendo Switch Joy-Cons (used in pairs), and Nintendo Switch Pro Controller have much in common. They have many of the features expected of modern game controllers. They also have an incredibly versatile and underutilised input that their biggest rival (Microsoft's Xbox One controller) doesn't have: the gyro.
My goal with JoyShockLibrary is to enable game developers to support DS4, DS, Joy-Cons, and Pro Controllers natively in PC games. I've compiled the library for Windows, but it uses platform-agnostic tools, and my hope is that other developers would be able to get it working on other platforms (such as Linux or Mac) without too much trouble.
## Contents
* **[Releases](#releases)**
* **[Reference](#reference)**
* **[Structs](#structs)**
* **[Functions](#functions)**
* **[Known and Perceived Issues](#known-and-perceived-issues)**
* **[Backwards Compatibility](#backwards-compatibility)**
* **[Credits](#credits)**
* **[Helpful Resources](#helpful-resources)**
* **[License](#license)**
## Releases
The latest version of JoyShockLibrary can always be found [here](https://github.com/JibbSmart/JoyShockLibrary/releases). Included is a 64-bit dll and a 32-bit dll, both for Windows, and JoyShockLibrary.h and JoyShockLibrary.cs for using the dll in C/C++ and C\# (Unity), respectively.
## Reference
*JoyShockLibrary.h* has everything you need to use the library, but here's a breakdown of everything in there.
### Structs
**struct JOY\_SHOCK\_STATE** - This struct contains the state for all the sticks, buttons, and triggers on the controller. If you're just using JoyShockLibrary to be able to use Joy-Cons, Pro Controllers, DualSenses, and DualShock 4s similarly to how you'd use other devices, this has everything you need to know.
* **int buttons** contains the states of all the controller's buttons with the following masks:
* ```0x00001``` - d-pad ```up```
* ```0x00002``` - d-pad ```down```
* ```0x00004``` - d-pad ```left```
* ```0x00008``` - d-pad ```right```
* ```0x00010``` - ```+``` on Nintendo devices, ```Options``` on DS4
* ```0x00020``` - ```-``` on Nintendo devices, ```Share``` on DS4
* ```0x00040``` - ```left-stick click``` on Nintendo devices, ```L3``` on DS4
* ```0x00080``` - ```right-stick click``` on Nintendo devices, ```R3``` on DS4
* ```0x00100``` - ```L``` on Nintendo devices, ```L1``` on DS4
* ```0x00200``` - ```R``` on Nintendo devices, ```R1``` on DS4
* ```0x00400``` - ```ZL``` on Nintendo devices, ```L2``` on DS4
* ```0x00800``` - ```ZR``` on Nintendo devices, ```R2``` on DS4
* ```0x01000``` - the South face-button: ```B``` on Nintendo devices, ```⨉``` on DS4
* ```0x02000``` - the East face-button: ```A``` on Nintendo devices, ```○``` on DS4
* ```0x04000``` - the West face-button: ```Y``` on Nintendo devices, ```□``` on DS4
* ```0x08000``` - the North face-button: ```X``` on Nintendo devices, ```△``` on DS4
* ```0x10000``` - ```Home``` on Nintendo devices, ```PS``` on DS4
* ```0x20000``` - ```Capture``` on Nintendo devices, ```touchpad click``` on DS4, ```Create``` on DS5
* ```0x40000``` - ```SL``` on Nintendo Joy-Cons, ```Mic``` on DS5
* ```0x80000``` - ```SR``` on Nintendo Joy-Cons
* **float lTrigger** - how far has the left trigger been pressed? This will be 1 or 0 on Nintendo devices, which don't have analog triggers
* **float rTrigger** - how far has the right trigger been pressed? This will be 1 or 0 on Nintendo devices, which don't have analog triggers
* **float stickLX, stickLY** - left-stick X axis and Y axis, respectively, from -1 to 1
* **float stickRX, stickRX** - right-stick X axis and Y axis, respectively, from -1 to 1
**struct IMU_STATE** - Each supported device contains an IMU which has a 3-axis accelerometer and a 3-axis gyroscope. IMU\_STATE is where you find that info.
* **float accelX, accelY, accelZ** - accelerometer X axis, Y axis, and Z axis, respectively, in g (g-force).
* **float gyroX, gyroY, gyroZ** - gyroscope angular velocity X, Y, and Z, respectively, in dps (degrees per second), when correctly calibrated.
**struct MOTION_STATE** - The MOTION_STATE reports the orientation of the device as calculated using a sensor fusion solution to combine gyro and accelerometer data.
* **float quatW, quatX, quatY, quatZ** - a quaternion representing the orientation of the device.
* **float accelX, accelY, accelZ** - local acceleration after accounting for and removing the effect of gravity.
* **float gravX, gravY, gravZ** - local gravity direction.
### Functions
All these functions *should* be thread-safe, and none of them should cause any harm if given the wrong handle. If they do, please report this to me as an isuse.
**int JslConnectDevices()** - Register any connected devices. Returns the number of devices connected, which is helpful for getting the handles for those devices with the next function.
**int JslGetConnectedDeviceHandles(int\* deviceHandleArray, int size)** - Fills the array *deviceHandleArray* of size *size* with the handles for all connected devices, up to the length of the array. Use the length returned by *JslConnectDevices* to make sure you've got all connected devices' handles.
**void JslDisconnectAndDisposeAll()** - Disconnect devices, no longer polling them for input.
**JOY\_SHOCK\_STATE JslGetSimpleState(int deviceId)** - Get the latest button + trigger + stick state for the controller with the given id.
**IMU\_STATE JslGetIMUState(int deviceId)** - Get the latest accelerometer + gyroscope state for the controller with the given id.
**MOTION\_STATE JslGetMotionState(int deviceId)** - Get the latest motion state for the controller with the given id.
**TOUCH\_STATE JslGetTouchState(int deviceId)** - Get the latest touchpad state for the controller with the given id. Only DualShock 4s support this.
**int JslGetButtons(int deviceId)** - Get the latest button state for the controller with the given id. If you want more than just the buttons, it's more efficient to use JslGetSimpleState.
**float JslGetLeftX/JslGetLeftY/JslGetRightX/JslGetRightY(int deviceId)** - Get the latest stick state for the controller with the given id. If you want more than just a single stick axis, it's more efficient to use JslGetSimpleState.
**float JslGetLeftTrigger/JslGetRightTrigger(int deviceId)** - Get the latest trigger state for the controller with the given id. If you want more than just a single trigger, it's more efficient to use JslGetSimpleState.
**float JslGetGyroX/JslGetGyroY/JslGetGyroZ(int deviceId)** - Get the latest angular velocity for a given gyroscope axis. If you want more than just a single gyroscope axis velocity, it's more efficient to use JslGetIMUState.
**float JslGetAccelX/JslGetAccelY/JslGetAccelZ(int deviceId)** - Get the latest acceleration for a given axis. If you want more than just a accelerometer axis, it's more efficient to use JslGetIMUState.
**int JslGetTouchId(int deviceId, bool secondTouch=false)** - Get the last touch's id, which is a value in range of 0-127 that automaticaly increments whenever a new touch appears, for the controller with the given id. Only DualShock 4s support this. If you want more than just a touch's id, it's more efficient to use JslGetTouchState.
**bool JslGetTouchDown(int deviceId, bool secondTouch=false)** - Get the latest state of the touch being present on a touchpad for the controller with the given id. Only DualShock 4s support this. If you want more than just a presence of touch, it's more efficient to use JslGetTouchState.
**float JslGetTouchX/JslGetTouchY(int deviceId, bool secondTouch=false)** - Get the latest touch state for the controller with the given id. Only DualShock 4s support this. If you want more than just a single touch axis, it's more efficient to use JslGetTouchState.
**float JslGetStickStep(int deviceId)** - Different devices use different size data types and different ranges on those data types when reporting stick axes. For some calculations, it may be important to know the limits of the current device and work around them in different ways. This gives the smallest step size between two values for the given device's analog sticks.
**float JslGetTriggerStep(int deviceId)** - Some devices have analog triggers, some don't. For some calculations, it may be important to know the limits of the current device and work around them in different ways. This gives the smallest step size between two values for the given device's triggers, or 1.0 if they're actually just binary inputs.
**float JslGetTriggerStep(int deviceId)** - Some devices have analog triggers, some don't. For some calculations, it may be important to know the limits of the current device and work around them in different ways. This gives the smallest step size between two values for the given device's triggers, or 1.0 if they're actually just binary inputs.
**float JslGetPollRate(int deviceId)** - Different devices report back new information at different rates. For the given device, this gives how many times one would usually expect the device to report back per second.
**void JslResetContinuousCalibration(int deviceId)** - JoyShockLibrary has helpful functions for calibrating the gyroscope by averaging out its input over time. This deletes all calibration data that's been accumulated, if any, this session.
**void JslStartContinuousCalibration(int deviceId)** - Start collecting gyro data, recording the ongoing average and using that to offset gyro output.
**void JslPauseContinuousCalibration(int deviceId)** - Stop collecting gyro data, but don't delete it.
**void JslGetCalibrationOffset(int deviceId, float& xOffset, float& yOffset, float& zOffset)** - Get the calibrated offset value for the given device's gyro. You don't have to use it; all gyro output for this device is already being offset by this vector before leaving JoyShockLibrary.
**void JslSetCalibrationOffset(int deviceId, float xOffset, float yOffset, float zOffset)** - Manually set the calibrated offset value for the given device's gyro.
**void JslSetCallback(void(\*callback)(int, JOY\_SHOCK\_STATE, JOY\_SHOCK\_STATE, IMU\_STATE, IMU\_STATE, float))** - Set a callback function by which JoyShockLibrary can report the current state for each device. This callback will be given the *deviceId* for the reporting device, its current button + trigger + stick state, its previous button + trigger + stick state, its current accelerometer + gyro state, its previous accelerometer + gyro state, and the amount of time since the last report for this device (in seconds).
**void JslSetTouchCallback(void(\*callback)(int, TOUCH\_STATE, TOUCH\_STATE, float))** - Set a callback function by which JoyShockLibrary can report the current touchpad state for each device. Only DualShock 4s will use this. This callback will be given the *deviceId* for the reporting device, its current and previous touchpad states, and the amount of time since the last report for this device (in seconds).
**int JslGetControllerType(int deviceId)** - What type of controller is this device?
1. Left Joy-Con
2. Right Joy-Con
3. Switch Pro Controller
4. DualShock 4
5. DualSense
**int JslGetControllerSplitType(int deviceId)** - Is this a half-controller or full? If half, what kind?
1. Left half
2. Right half
3. Full controller
**int JslGetControllerColour(int deviceId)** - Get the colour of the controller. Only Nintendo devices support this. Others will report white.
**void JslSetLightColour(int deviceId, int colour)** - Set the light colour on the given controller. Only DualShock 4 and the DualSense support this. Players will often prefer to be able to disable the light, so make sure to give them that option, but when setting players up in a local multiplayer game, setting the light colour is a useful way to uniquely identify different controllers.
**void JslSetPlayerNumber(int deviceId, int number)** - Set the lights that indicate player number. This only works on Nintendo devices and the DualSense. NOTE: The DualSense sets each LED through a bitmask. Use the ```DS5_PLAYER_#``` definitions in the header file to get PS5-style lightbar formats.
Player 1: ```--x--```
Player 2: ```-x-x-```
Player 3: ```x-x-x```
Player 4: ```xx-xx```
Player 5: ```xxxxx```
**void JslSetRumble(int deviceId, int smallRumble, int bigRumble)** - DualShock 4s have two types of rumble, and they can be set at the same time with different intensities. These can be set from 0 to 255. Nintendo devices support rumble as well, but totally differently. They call it "HD rumble", and it's a great feature, but JoyShockLibrary doesn't yet support it.
## Known and Perceived Issues
### Bluetooth connectivity
Joy-Cons and Pro Controllers are normally only be connected by Bluetooth. Some Bluetooth adapters can't keep up with these devices, resulting in laggy input. This is especially common when more than one device is connected (such as when using a pair of Joy-Cons). There is nothing JoyShockMapper or JoyShockLibrary can do about this.
There is experimental support for connecting supported Switch controllers by USB now. Please let me know if you have any issues (or success!) with it.
### Gyro poll rate on Nintendo devices
The Nintendo devices report every 15ms, but their IMUs actually report every 5ms. Every 15ms report includes the last 3 gyro and accelerometer reports. When creating the latest IMU state for Nintendo devices, JoyShockLibrary averages out those 3 gyro and accelerometer reports, so that it can best include all that information in a sensible format. For things like controlling a cursor on a plane, this should be of little to no consequence, since the result is the same as adding all 3 reports separately over shorter time intervals. But for representing real 3D rotations of the controller, this causes the Nintendo devices to be *slightly* less accurate than they could be, because we're combining 3 rotations in a simplistic way.
In a future version I hope to either combine the 3 rotations in a way that works better in 3D, or to add a way for a single controller event to report several IMU events at the same time.
## Backwards Compatibility
JoyShockLibrary v2 changes the gyro and accelerometer axes from previous versions. Previous versions were inconsistent between gyro and accelerometer. When upgrading to JoyShockLibrary v2, in order to maintain previous behaviour:
* Invert Gyro X
* Swap Accel Z and Y
* Then invert Accel Z
## Credits
I'm Jibb Smart, and I made JoyShockLibrary. JoyShockLibrary has also benefited from the contributions of:
* Romeo Calota (Linux support + general portability improvements)
* RollinBarrel (touchpad support)
* Robin (wireless DS4/5 support)
JoyShockLibrary uses substantial portions of mfosse's [JoyCon-Driver](https://github.com/mfosse/JoyCon-Driver), a [vJoy](http://vjoystick.sourceforge.net/site/) feeder for most communication with Nintendo devices, building on it with info from dekuNukem's [Nintendo Switch Reverse Engineering](https://github.com/dekuNukem/Nintendo_Switch_Reverse_Engineering/) page in order to (for example) unpack all gyro and accelerometer samples from each report.
JoyShockLibrary's DualShock 4 support would likely not be possible without the info available on [PSDevWiki](https://www.psdevwiki.com/ps4/Main_Page) and [Eleccelerator Wiki](http://eleccelerator.com/wiki/index.php?title=DualShock_4). chrippa's [ds4drv](https://github.com/chrippa/ds4drv) was also a handy reference for getting rumble and lights working right away, and some changes have been made while referencing Ryochan7's [DS4Windows](https://github.com/Ryochan7/DS4Windows).
This software depends on signal11's [HIDAPI](https://github.com/signal11/hidapi) to connect to USB and Bluetooth devices.
## Helpful Resources
* [GyroWiki](http://gyrowiki.jibbsmart.com) - All about good gyro controls for games:
* Why gyro controls make gaming better;
* How developers can do a better job implementing gyro controls;
* How to use JoyShockLibrary;
* How gamers can play any PC game with gyro controls using [JoyShockMapper](https://github.com/JibbSmart/JoyShockMapper), which uses JoyShockLibrary to read from supported controllers.
## License
JoyShockLibrary is licensed under the MIT License - see [LICENSE.md](LICENSE.md).

View file

@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: 9e1b398aaf3d3a8429068830e3168b86
TextScriptImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 46ec8bf5775b6af429f16d7140f02d54
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

Binary file not shown.

View file

@ -0,0 +1,63 @@
fileFormatVersion: 2
guid: c84ef0f74efdfa149b54ff639acd7c7b
PluginImporter:
externalObjects: {}
serializedVersion: 2
iconMap: {}
executionOrder: {}
defineConstraints: []
isPreloaded: 0
isOverridable: 0
isExplicitlyReferenced: 0
validateReferences: 1
platformData:
- first:
: Any
second:
enabled: 0
settings:
Exclude Editor: 0
Exclude Linux64: 0
Exclude OSXUniversal: 0
Exclude Win: 1
Exclude Win64: 0
- first:
Any:
second:
enabled: 1
settings: {}
- first:
Editor: Editor
second:
enabled: 1
settings:
CPU: x86_64
DefaultValueInitialized: true
OS: AnyOS
- first:
Standalone: Linux64
second:
enabled: 1
settings:
CPU: None
- first:
Standalone: OSXUniversal
second:
enabled: 1
settings:
CPU: None
- first:
Standalone: Win
second:
enabled: 0
settings:
CPU: None
- first:
Standalone: Win64
second:
enabled: 1
settings:
CPU: x86_64
userData:
assetBundleName:
assetBundleVariant:

Binary file not shown.

View file

@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: 8290861ef07e2d74497c02c16ea45608
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

Binary file not shown.

View file

@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: 309dd656c95dd434ba2f1ccefa8b3ec0
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

Binary file not shown.

View file

@ -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:

View file

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 099214b717710f8468369d6cfe2f7135
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

Binary file not shown.

View file

@ -0,0 +1,63 @@
fileFormatVersion: 2
guid: c603b06f7fc73b9448935991b913d915
PluginImporter:
externalObjects: {}
serializedVersion: 2
iconMap: {}
executionOrder: {}
defineConstraints: []
isPreloaded: 0
isOverridable: 0
isExplicitlyReferenced: 0
validateReferences: 1
platformData:
- first:
: Any
second:
enabled: 0
settings:
Exclude Editor: 1
Exclude Linux64: 0
Exclude OSXUniversal: 0
Exclude Win: 0
Exclude Win64: 1
- first:
Any:
second:
enabled: 1
settings: {}
- first:
Editor: Editor
second:
enabled: 0
settings:
CPU: AnyCPU
DefaultValueInitialized: true
OS: AnyOS
- first:
Standalone: Linux64
second:
enabled: 1
settings:
CPU: None
- first:
Standalone: OSXUniversal
second:
enabled: 1
settings:
CPU: None
- first:
Standalone: Win
second:
enabled: 1
settings:
CPU: x86
- first:
Standalone: Win64
second:
enabled: 0
settings:
CPU: None
userData:
assetBundleName:
assetBundleVariant:

Binary file not shown.

View file

@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: 47521c369c3ab7849aeb7e479bad21ea
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

Binary file not shown.

View file

@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: 12b152ed16fe1eb4698be175f621ffe4
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: c9421977f50da33418300b1de2773909
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,150 @@
// Upgrade NOTE: replaced '_Object2World' with 'unity_ObjectToWorld'
// Upgrade NOTE: replaced '_World2Object' with 'unity_WorldToObject'
// Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClipPos(*)'
Shader "UI/ControllerShader"
{
Properties
{
_MainTex ("Sprite Texture", 2D) = "white" {}
_Color ("Tint", Color) = (1,1,1,1)
_BodyColor ("Body Colour", Color) = (1,1,1,1)
_BtnColor ("Button Colour", Color) = (1,1,1,1)
_LGripColor ("Left Grip Colour", Color) = (1,1,1,1)
_RGripColor ("Right Grip Colour", Color) = (1,1,1,1)
_StencilComp ("Stencil Comparison", Float) = 8
_Stencil ("Stencil ID", Float) = 0
_StencilOp ("Stencil Operation", Float) = 0
_StencilWriteMask ("Stencil Write Mask", Float) = 255
_StencilReadMask ("Stencil Read Mask", Float) = 255
_ColorMask ("Color Mask", Float) = 15
_ClipRect ("Clip Rect", vector) = (-32767, -32767, 32767, 32767)
[Toggle(UNITY_UI_ALPHACLIP)] _UseUIAlphaClip ("Use Alpha Clip", Float) = 0
}
SubShader
{
Tags
{
"Queue"="Transparent"
"IgnoreProjector"="True"
"RenderType"="Transparent"
"PreviewType"="Plane"
"CanUseSpriteAtlas"="True"
}
Stencil
{
Ref [_Stencil]
Comp [_StencilComp]
Pass [_StencilOp]
ReadMask [_StencilReadMask]
WriteMask [_StencilWriteMask]
}
Cull Off
Lighting Off
ZWrite Off
ZTest [unity_GUIZTestMode]
Blend SrcAlpha OneMinusSrcAlpha
ColorMask [_ColorMask]
Pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
#include "UnityUI.cginc"
#pragma multi_compile __ UNITY_UI_CLIP_RECT
#pragma multi_compile __ UNITY_UI_ALPHACLIP
struct appdata_t
{
float4 vertex : POSITION;
float4 color : COLOR;
float2 texcoord : TEXCOORD0;
};
sampler2D _MainTex;
fixed4 _Color;
fixed4 _BodyColor;
fixed4 _BtnColor;
fixed4 _LGripColor;
fixed4 _RGripColor;
fixed4 _TextureSampleAdd;
float4 _ClipRect;
float4 _MainTex_ST;
float4 _MainTex_TexelSize;
struct v2f
{
half2 texcoord : TEXCOORD0;
float3 worldPos : TEXCOORD1;
float3 localPos : TEXCOORD2;
float4 vertex : SV_POSITION;
fixed4 color : COLOR;
};
v2f vert(appdata_t IN)
{
v2f OUT;
OUT.vertex = UnityObjectToClipPos(IN.vertex);
float4 scaleVertex = float4(IN.vertex.xyz, 0); //By setting the last value to 0 it ignores the flipping ( loses relative position if sprite is flipped :( )
float4 wP = mul(unity_ObjectToWorld, scaleVertex); //Get the object to world vertex and store it
OUT.worldPos = wP.xyz; //For use in fragment shader
float4 lP = mul(unity_WorldToObject, scaleVertex); //Get the world to object vertex and store it
OUT.localPos = lP.xyz; //For use in fragment shader
OUT.texcoord = TRANSFORM_TEX(IN.texcoord, _MainTex);
OUT.color = IN.color;
return OUT;
}
fixed4 frag(v2f IN) : SV_Target
{
fixed4 t = tex2D(_MainTex, IN.texcoord)*IN.color;
//Calculate relative position
fixed2 relativeWorld = fixed2(IN.worldPos.x + IN.localPos.x, IN.worldPos.y + IN.localPos.y);
//This becomes the UV for the texture I want to apply to the sprite ( using the sprites width and height )
fixed2 relativePos = fixed2((relativeWorld.x + _MainTex_TexelSize.z), (relativeWorld.y + _MainTex_TexelSize.w));
fixed r = tex2D(_MainTex, IN.texcoord).r;
fixed g = tex2D(_MainTex, IN.texcoord).g;
fixed b = tex2D(_MainTex, IN.texcoord).b;
fixed lg = 0.0;
fixed rg = 0.0;
if (relativePos.x <= 0.5)
{
lg = b;
}
else
{
rg = b;
}
half4 color = _TextureSampleAdd + IN.color;
color.rgb = (r * _BodyColor.rgb) + (g * _BtnColor.rgb) + (lg * _LGripColor.rgb) + (rg * _RGripColor.rgb);
color.a = tex2D(_MainTex, IN.texcoord).a;
#ifdef UNITY_UI_CLIP_RECT
color.a *= UnityGet2DClipping(IN.worldPos.xy, _ClipRect);
#endif
#ifdef UNITY_UI_ALPHACLIP
clip (color.a - 0.001);
#endif
return color;
}
ENDCG
}
}
}

View file

@ -0,0 +1,10 @@
fileFormatVersion: 2
guid: cfe42e963af2b934bb427536d4d29068
ShaderImporter:
externalObjects: {}
defaultTextures: []
nonModifiableTextures: []
preprocessorOverride: 0
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,91 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!21 &2100000
Material:
serializedVersion: 6
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_Name: UIControllerMaterial
m_Shader: {fileID: 4800000, guid: cfe42e963af2b934bb427536d4d29068, type: 3}
m_ShaderKeywords:
m_LightmapFlags: 4
m_EnableInstancingVariants: 0
m_DoubleSidedGI: 0
m_CustomRenderQueue: -1
stringTagMap: {}
disabledShaderPasses: []
m_SavedProperties:
serializedVersion: 3
m_TexEnvs:
- _BumpMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _DetailAlbedoMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _DetailMask:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _DetailNormalMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _EmissionMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _MainTex:
m_Texture: {fileID: 2800000, guid: d44d97eed2a444b41be17f9737b43b5f, type: 3}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _MetallicGlossMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _OcclusionMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _ParallaxMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
m_Floats:
- _BumpScale: 1
- _ColorMask: 15
- _Cutoff: 0.5
- _DetailNormalMapScale: 1
- _DstBlend: 0
- _GlossMapScale: 1
- _Glossiness: 0.5
- _GlossyReflections: 1
- _Metallic: 0
- _Mode: 0
- _OcclusionStrength: 1
- _Parallax: 0.02
- _SmoothnessTextureChannel: 0
- _SpecularHighlights: 1
- _SrcBlend: 1
- _Stencil: 0
- _StencilComp: 8
- _StencilOp: 0
- _StencilReadMask: 255
- _StencilWriteMask: 255
- _UVSec: 0
- _UseUIAlphaClip: 0
- _ZWrite: 1
m_Colors:
- _BodyColor: {r: 0.11764706, g: 0.039215688, b: 0.039215688, a: 1}
- _BtnColor: {r: 0, g: 0.11764706, b: 0.11764706, a: 1}
- _ClipRect: {r: -32767, g: -32767, b: 32767, a: 32767}
- _Color: {r: 1, g: 1, b: 1, a: 1}
- _EmissionColor: {r: 0, g: 0, b: 0, a: 1}
- _LGripColor: {r: 0.039215688, g: 0.7254902, b: 0.9019608, a: 1}
- _RGripColor: {r: 1, g: 0.23529412, b: 0.15686275, a: 1}
- _Rect: {r: 0, g: 0, b: 1, a: 1}
m_BuildTextureStacks: []

View file

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 55b3a6672a0ec294d8f3edb9c1f94b36
NativeFormatImporter:
externalObjects: {}
mainObjectFileID: 2100000
userData:
assetBundleName:
assetBundleVariant:

Binary file not shown.

After

Width:  |  Height:  |  Size: 434 KiB

View file

@ -0,0 +1,276 @@
fileFormatVersion: 2
guid: d44d97eed2a444b41be17f9737b43b5f
TextureImporter:
internalIDToNameTable:
- first:
213: 6680111460237765715
second: pcKeyboard
- first:
213: -418123597310507147
second: sonyDualsense
- first:
213: -8353205122300186910
second: sonyDualShock
- first:
213: 997315915213647506
second: nxProcon
- first:
213: 8903944674802394384
second: nxJoyconPair
- first:
213: 9166690998051772148
second: nxJoyconR
- first:
213: 2557230542604182733
second: nxJoyconL
externalObjects: {}
serializedVersion: 11
mipmaps:
mipMapMode: 0
enableMipMap: 0
sRGBTexture: 1
linearTexture: 0
fadeOut: 0
borderMipMap: 0
mipMapsPreserveCoverage: 0
alphaTestReferenceValue: 0.5
mipMapFadeDistanceStart: 1
mipMapFadeDistanceEnd: 3
bumpmap:
convertToNormalMap: 0
externalNormalMap: 0
heightScale: 0.25
normalMapFilter: 0
isReadable: 0
streamingMipmaps: 0
streamingMipmapsPriority: 0
vTOnly: 0
grayScaleToAlpha: 0
generateCubemap: 6
cubemapConvolution: 0
seamlessCubemap: 0
textureFormat: 1
maxTextureSize: 2048
textureSettings:
serializedVersion: 2
filterMode: 1
aniso: 1
mipBias: 0
wrapU: 1
wrapV: 1
wrapW: 1
nPOTScale: 0
lightmap: 0
compressionQuality: 50
spriteMode: 2
spriteExtrude: 1
spriteMeshType: 0
alignment: 0
spritePivot: {x: 0.5, y: 0.5}
spritePixelsToUnits: 100
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
spriteGenerateFallbackPhysicsShape: 1
alphaUsage: 1
alphaIsTransparency: 1
spriteTessellationDetail: -1
textureType: 8
textureShape: 1
singleChannelComponent: 0
flipbookRows: 1
flipbookColumns: 1
maxTextureSizeSet: 0
compressionQualitySet: 0
textureFormatSet: 0
ignorePngGamma: 0
applyGammaDecoding: 0
platformSettings:
- serializedVersion: 3
buildTarget: DefaultTexturePlatform
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
- serializedVersion: 3
buildTarget: Standalone
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
spriteSheet:
serializedVersion: 2
sprites:
- serializedVersion: 2
name: pcKeyboard
rect:
serializedVersion: 2
x: 55
y: 3305
width: 1190
height: 692
alignment: 0
pivot: {x: 0.5, y: 0.5}
border: {x: 0, y: 0, z: 0, w: 0}
outline: []
physicsShape: []
tessellationDetail: 0
bones: []
spriteID: 35cec77faf584bc50800000000000000
internalID: 6680111460237765715
vertices: []
indices:
edges: []
weights: []
- serializedVersion: 2
name: sonyDualsense
rect:
serializedVersion: 2
x: 1425
y: 3183
width: 1250
height: 869
alignment: 0
pivot: {x: 0.5, y: 0.5}
border: {x: 0, y: 0, z: 0, w: 0}
outline: []
physicsShape: []
tessellationDetail: 0
bones: []
spriteID: 5774916bdc6823af0800000000000000
internalID: -418123597310507147
vertices: []
indices:
edges: []
weights: []
- serializedVersion: 2
name: sonyDualShock
rect:
serializedVersion: 2
x: 2779
y: 3189
width: 1258
height: 797
alignment: 0
pivot: {x: 0.5, y: 0.5}
border: {x: 0, y: 0, z: 0, w: 0}
outline: []
physicsShape: []
tessellationDetail: 0
bones: []
spriteID: 2eee25dc234731c80800000000000000
internalID: -8353205122300186910
vertices: []
indices:
edges: []
weights: []
- serializedVersion: 2
name: nxProcon
rect:
serializedVersion: 2
x: 31
y: 2131
width: 1212
height: 840
alignment: 0
pivot: {x: 0.5, y: 0.5}
border: {x: 0, y: 0, z: 0, w: 0}
outline: []
physicsShape: []
tessellationDetail: 0
bones: []
spriteID: 29e27277a8d27dd00800000000000000
internalID: 997315915213647506
vertices: []
indices:
edges: []
weights: []
- serializedVersion: 2
name: nxJoyconPair
rect:
serializedVersion: 2
x: 1599
y: 2069
width: 852
height: 924
alignment: 0
pivot: {x: 0.5, y: 0.5}
border: {x: 0, y: 0, z: 0, w: 0}
outline: []
physicsShape: []
tessellationDetail: 0
bones: []
spriteID: 015e351b18a219b70800000000000000
internalID: 8903944674802394384
vertices: []
indices:
edges: []
weights: []
- serializedVersion: 2
name: nxJoyconR
rect:
serializedVersion: 2
x: 2923
y: 2590
width: 922
height: 473
alignment: 0
pivot: {x: 0.5, y: 0.5}
border: {x: 0, y: 0, z: 0, w: 0}
outline: []
physicsShape: []
tessellationDetail: 0
bones: []
spriteID: 4f695a045e0a63f70800000000000000
internalID: 9166690998051772148
vertices: []
indices:
edges: []
weights: []
- serializedVersion: 2
name: nxJoyconL
rect:
serializedVersion: 2
x: 2925
y: 2048
width: 924
height: 473
alignment: 0
pivot: {x: 0.5, y: 0.5}
border: {x: 0, y: 0, z: 0, w: 0}
outline: []
physicsShape: []
tessellationDetail: 0
bones: []
spriteID: dc4a3b431ab1d7320800000000000000
internalID: 2557230542604182733
vertices: []
indices:
edges: []
weights: []
outline: []
physicsShape: []
bones: []
spriteID: 5e97eb03825dee720800000000000000
internalID: 0
vertices: []
indices:
edges: []
weights: []
secondaryTextures: []
spritePackingTag:
pSDRemoveMatte: 0
pSDShowRemoveMatteOption: 0
userData:
assetBundleName:
assetBundleVariant:

File diff suppressed because it is too large Load diff

View file

@ -198,6 +198,8 @@ namespace HeavenStudio
// LateUpdate works a bit better(?) but causes some bugs (like issues with bop animations).
private void Update()
{
PlayerInput.UpdateInputControllers();
if (BeatmapEntities() < 1) //bruh really you forgot to ckeck tempo changes
return;
if (!Conductor.instance.isPlaying)

View file

@ -122,6 +122,7 @@ namespace HeavenStudio.Games.Scripts_FanClub
{
animator.Play("FanFree", -1, 0);
stopBeat = false;
clappingStartTime = Single.MinValue;
}
}
}
@ -204,6 +205,7 @@ namespace HeavenStudio.Games.Scripts_FanClub
animator.Play("FanJump", -1, 0);
Jukebox.PlayOneShotGame("fanClub/play_jump");
jumpStartTime = cond.songPositionInBeats;
clappingStartTime = Single.MinValue;
stopCharge = false;
}

View file

@ -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();
}
}
}

View file

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: f0c2ca50a4b8a1b499a3efd717f1daaa
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: dc30ca18de2bbc24d984b036097fe60d
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,430 @@
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"
};
//TODO: see if single joy-con mappings differ from a normal pad (they don't!)
int[] mappings = new[]
{
ButtonMaskUp,
ButtonMaskDown,
ButtonMaskLeft,
ButtonMaskRight,
ButtonMaskS,
ButtonMaskE,
ButtonMaskW,
ButtonMaskN,
ButtonMaskL,
ButtonMaskR,
ButtonMaskPlus,
};
int[] mappingsSplitLeft = new[]
{
-1,
-1,
-1,
-1,
ButtonMaskLeft,
ButtonMaskDown,
ButtonMaskUp,
ButtonMaskRight,
ButtonMaskSL,
ButtonMaskSR,
ButtonMaskMinus,
};
int[] mappingsSplitRight = new[]
{
-1,
-1,
-1,
-1,
ButtonMaskE,
ButtonMaskN,
ButtonMaskS,
ButtonMaskW,
ButtonMaskSL,
ButtonMaskSR,
ButtonMaskPlus,
};
float stickDeadzone = 0.5f;
int joyshockHandle;
int type;
int splitType;
string joyshockName;
//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()
{
//buttons
joyBtStateLast = joyBtStateCurrent;
joyBtStateCurrent = JslGetSimpleState(joyshockHandle);
//stick direction state
//split controllers will need to be rotated to compensate
//left rotates counterclockwise, right rotates clockwise, all by 90 degrees
float xAxis = 0f;
float yAxis = 0f;
if (otherHalf == null)
{
switch (splitType)
{
case SplitLeft:
xAxis = -joyBtStateCurrent.stickLY;
yAxis = joyBtStateCurrent.stickLX;
break;
case SplitRight: //use the right stick instead
xAxis = joyBtStateCurrent.stickRY;
yAxis = -joyBtStateCurrent.stickRX;
break;
case SplitFull:
xAxis = joyBtStateCurrent.stickLX;
yAxis = joyBtStateCurrent.stickLY;
break;
}
}
else
{
xAxis = joyBtStateCurrent.stickLX;
yAxis = joyBtStateCurrent.stickLY;
}
directionStateLast = directionStateCurrent;
directionStateCurrent = 0;
directionStateCurrent |= ((yAxis >= stickDeadzone) ? (1 << ((int) InputDirection.Up)) : 0);
directionStateCurrent |= ((yAxis <= -stickDeadzone) ? (1 << ((int) InputDirection.Down)) : 0);
directionStateCurrent |= ((xAxis >= stickDeadzone) ? (1 << ((int) InputDirection.Right)) : 0);
directionStateCurrent |= ((xAxis <= -stickDeadzone) ? (1 << ((int) InputDirection.Left)) : 0);
//Debug.Log("stick direction: " + directionStateCurrent + "| x axis: " + xAxis + " y axis: " + yAxis);
}
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)
{
int bt = 0;
if (otherHalf == null)
{
if (splitType == SplitLeft)
{
bt = mappingsSplitLeft[button];
}
else if (splitType == SplitRight)
{
bt = mappingsSplitRight[button];
}
else
{
bt = mappings[button];
}
return BitwiseUtils.WantCurrent(joyBtStateCurrent.buttons, 1 << bt);
}
bt = mappings[button];
return BitwiseUtils.WantCurrent(joyBtStateCurrent.buttons, 1 << bt) || BitwiseUtils.WantCurrent(otherHalf.joyBtStateCurrent.buttons, 1 << bt);
}
public override bool GetButtonDown(int button)
{
int bt = 0;
if (otherHalf == null)
{
if (splitType == SplitLeft)
{
bt = mappingsSplitLeft[button];
}
else if (splitType == SplitRight)
{
bt = mappingsSplitRight[button];
}
else
{
bt = mappings[button];
}
return BitwiseUtils.WantCurrentAndNotLast(joyBtStateCurrent.buttons, joyBtStateLast.buttons, 1 << bt);
}
bt = mappings[button];
return BitwiseUtils.WantCurrentAndNotLast(joyBtStateCurrent.buttons, joyBtStateLast.buttons, 1 << bt) || BitwiseUtils.WantCurrentAndNotLast(otherHalf.joyBtStateCurrent.buttons, otherHalf.joyBtStateLast.buttons, 1 << bt);
}
public override bool GetButtonUp(int button)
{
int bt = 0;
if (otherHalf == null)
{
if (splitType == SplitLeft)
{
bt = mappingsSplitLeft[button];
}
else if (splitType == SplitRight)
{
bt = mappingsSplitRight[button];
}
else
{
bt = mappings[button];
}
return BitwiseUtils.WantNotCurrentAndLast(joyBtStateCurrent.buttons, joyBtStateLast.buttons, 1 << bt);
}
bt = mappings[button];
return BitwiseUtils.WantNotCurrentAndLast(joyBtStateCurrent.buttons, joyBtStateLast.buttons, 1 << bt) || BitwiseUtils.WantNotCurrentAndLast(otherHalf.joyBtStateCurrent.buttons, otherHalf.joyBtStateLast.buttons, 1 << bt);
}
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
int bt;
switch (direction)
{
case InputDirection.Up:
bt = mappings[0];
break;
case InputDirection.Down:
bt = mappings[1];
break;
case InputDirection.Left:
bt = mappings[2];
break;
case InputDirection.Right:
bt = mappings[3];
break;
default:
return false;
}
return GetButton(bt) || BitwiseUtils.WantCurrent(directionStateCurrent, 1 << (int) direction);
}
public override bool GetHatDirectionDown(InputDirection direction)
{
//todo: check analogue stick hat direction too
int bt;
switch (direction)
{
case InputDirection.Up:
bt = mappings[0];
break;
case InputDirection.Down:
bt = mappings[1];
break;
case InputDirection.Left:
bt = mappings[2];
break;
case InputDirection.Right:
bt = mappings[3];
break;
default:
return false;
}
return GetButtonDown(bt) || BitwiseUtils.WantCurrentAndNotLast(directionStateCurrent, directionStateLast, 1 << (int) direction);
}
public override bool GetHatDirectionUp(InputDirection direction)
{
//todo: check analogue stick hat direction too
int bt;
switch (direction)
{
case InputDirection.Up:
bt = mappings[0];
break;
case InputDirection.Down:
bt = mappings[1];
break;
case InputDirection.Left:
bt = mappings[2];
break;
case InputDirection.Right:
bt = mappings[3];
break;
default:
return false;
}
return GetButtonUp(bt) || BitwiseUtils.WantNotCurrentAndLast(directionStateCurrent, directionStateLast, 1 << (int) direction);
}
public override void SetPlayer(int? playerNum)
{
//TODO: dualshock 4 and dualsense lightbar colour support
if (playerNum == -1 || playerNum == null)
{
this.playerNum = null;
JslSetPlayerNumber(joyshockHandle, 0);
return;
}
this.playerNum = playerNum;
int ledMask = (int) this.playerNum;
if (type == TypeDualSense)
{
if (playerNum <= 4)
{
ledMask = DualSensePlayerMask[(int) this.playerNum];
}
}
JslSetPlayerNumber(joyshockHandle, ledMask);
}
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);
}
public void AssignOtherHalf(InputJoyshock otherHalf, bool force = false)
{
InputFeatures features = otherHalf.GetFeatures();
if (features.HasFlag(InputFeatures.Extra_SplitControllerLeft) || features.HasFlag(InputFeatures.Extra_SplitControllerRight))
{
//two-way link
this.otherHalf = otherHalf;
this.otherHalf.UnAssignOtherHalf(); //juste en cas
this.otherHalf.otherHalf = this;
this.otherHalf.SetPlayer(this.playerNum);
}
else if (force)
{
UnAssignOtherHalf();
}
}
public void UnAssignOtherHalf()
{
if (otherHalf != null)
{
this.otherHalf.otherHalf = null;
this.otherHalf.SetPlayer(-1);
}
otherHalf = null;
}
public InputJoyshock GetOtherHalf()
{
return otherHalf;
}
}
}

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: abe9a6a60f8629440a3cae605aca60a3
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -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 || playerNum == null)
{
this.playerNum = null;
return;
}
this.playerNum = (int) playerNum;
}
public override int? GetPlayer()
{
return playerNum;
}
}
}

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 19bccc8eebf390943a5c6d8bc59f4c7f
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,170 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
namespace HeavenStudio.InputSystem
{
/// <summary>
/// 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.
/// </summary>
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;
protected int directionStateCurrent = 0;
protected int directionStateLast = 0;
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
}
}

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: f940937684f598749af06c1297727c4b
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,247 @@
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<InputController> inputDevices;
public static int InitInputControllers()
{
inputDevices = new List<InputController>();
//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);
inputDevices.Add(joyshock);
}
}
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<InputController> 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 int GetInputControllerId(int player)
{
//select input controller id 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
//controller IDs are determined by connection order (the Keyboard is always first)
for (int i = 0; i < inputDevices.Count; i++)
{
if (inputDevices[i].GetPlayer() == player)
{
return i;
}
}
return -1;
}
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()
{
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)
) && playerHasControl();
}
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();
}
public static bool GetAnyDirection()
{
InputController c = GetInputController(1);
return (c.GetHatDirection((InputController.InputDirection) UP)
|| c.GetHatDirection((InputController.InputDirection) DOWN)
|| c.GetHatDirection((InputController.InputDirection) LEFT)
|| c.GetHatDirection((InputController.InputDirection) RIGHT)
) && 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();
}
}
}

View file

@ -1,5 +1,5 @@
fileFormatVersion: 2
guid: 9503627b14bba414cae0fbc5da9e4120
guid: ff41ce113a3b89f4892e362c8ef3d773
MonoImporter:
externalObjects: {}
serializedVersion: 2

View file

@ -0,0 +1,263 @@
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using TMPro;
using HeavenStudio;
using HeavenStudio.Util;
using HeavenStudio.InputSystem;
using static JSL;
namespace HeavenStudio.Editor
{
public class ControllerSettings : MonoBehaviour
{
[SerializeField] private TMP_Text numConnectedLabel;
[SerializeField] private TMP_Text currentControllerLabel;
[SerializeField] private TMP_Dropdown controllersDropdown;
[SerializeField] private GameObject pairSearchItem;
[SerializeField] private GameObject autoSearchLabel;
[SerializeField] private GameObject pairSearchLabel;
[SerializeField] private TMP_Text pairingLabel;
[SerializeField] private List<GameObject> controllerIcons;
[SerializeField] private Material controllerMat;
private bool isAutoSearching = false;
private bool isPairSearching = false;
private bool pairSelectLR = false; //true = left, false = right
private void Start() {
numConnectedLabel.text = "Connected: " + PlayerInput.GetNumControllersConnected();
currentControllerLabel.text = "Current Controller: " + PlayerInput.GetInputController(1).GetDeviceName();
PopulateControllersDropdown();
ShowControllerIcon(PlayerInput.GetInputController(1));
controllersDropdown.onValueChanged.AddListener(delegate
{
InputController lastController = PlayerInput.GetInputController(1);
InputController newController = PlayerInput.GetInputControllers()[controllersDropdown.value];
lastController.SetPlayer(-1);
newController.SetPlayer(1);
if (typeof(InputJoyshock) == lastController.GetType()) {
InputJoyshock con = (InputJoyshock) lastController;
con.UnAssignOtherHalf();
}
if (typeof(InputJoyshock) == newController.GetType()) {
InputJoyshock con = (InputJoyshock) newController;
StartCoroutine(SelectionVibrate(con));
con.UnAssignOtherHalf();
}
currentControllerLabel.text = "Current Controller: " + newController.GetDeviceName();
ShowControllerIcon(newController);
InputController.InputFeatures features = newController.GetFeatures();
if (features.HasFlag(InputController.InputFeatures.Extra_SplitControllerLeft) || features.HasFlag(InputController.InputFeatures.Extra_SplitControllerRight))
{
pairSelectLR = !features.HasFlag(InputController.InputFeatures.Extra_SplitControllerLeft);
pairSearchItem.SetActive(true);
StartPairSearch();
}
else
{
pairSearchItem.SetActive(false);
CancelPairSearch();
}
});
}
private void Update() {
if (isAutoSearching) {
var controllers = PlayerInput.GetInputControllers();
foreach (var controller in controllers) {
if (controller.GetLastButtonDown() > 0 || controller.GetLastKeyDown() > 0) {
InputController lastController = PlayerInput.GetInputController(1);
lastController.SetPlayer(-1);
controller.SetPlayer(1);
isAutoSearching = false;
autoSearchLabel.SetActive(false);
controllersDropdown.value = PlayerInput.GetInputControllerId(1);
if (typeof(InputJoyshock) == lastController.GetType()) {
((InputJoyshock)lastController).UnAssignOtherHalf();
}
if (typeof(InputJoyshock) == controller.GetType()) {
InputJoyshock con = (InputJoyshock) controller;
StartCoroutine(SelectionVibrate(con));
con.UnAssignOtherHalf();
}
currentControllerLabel.text = "Current Controller: " + controller.GetDeviceName();
ShowControllerIcon(controller);
InputController.InputFeatures features = controller.GetFeatures();
if (features.HasFlag(InputController.InputFeatures.Extra_SplitControllerLeft) || features.HasFlag(InputController.InputFeatures.Extra_SplitControllerRight))
{
pairSelectLR = !features.HasFlag(InputController.InputFeatures.Extra_SplitControllerLeft);
pairSearchItem.SetActive(true);
StartPairSearch();
}
else
{
pairSearchItem.SetActive(false);
CancelPairSearch();
}
}
}
}
else if (isPairSearching) {
var controllers = PlayerInput.GetInputControllers();
InputController.InputFeatures lrFlag = pairSelectLR ? InputController.InputFeatures.Extra_SplitControllerLeft : InputController.InputFeatures.Extra_SplitControllerRight;
foreach (var controller in controllers) {
if (controller == PlayerInput.GetInputController(1)) continue;
InputController.InputFeatures features = controller.GetFeatures();
if (!features.HasFlag(lrFlag)) continue;
if (controller.GetLastButtonDown() > 0 || controller.GetLastKeyDown() > 0) {
InputJoyshock con = (InputJoyshock) PlayerInput.GetInputController(1);
con.AssignOtherHalf((InputJoyshock) controller);
isPairSearching = false;
pairSearchLabel.SetActive(false);
currentControllerLabel.text = "Current Controller: " + controller.GetDeviceName();
pairingLabel.text = "Joy-Con (L / R) Selected\nPairing Successful!";
ShowControllerIcon(controller);
StartCoroutine(SelectionVibrate(con));
StartCoroutine(SelectionVibrate((InputJoyshock) controller));
}
}
}
}
public void StartAutoSearch() {
if (!isPairSearching)
{
autoSearchLabel.SetActive(true);
isAutoSearching = true;
}
}
public void StartPairSearch() {
if (!isAutoSearching) {
pairSearchLabel.SetActive(true);
isPairSearching = true;
pairingLabel.text = "Joy-Con (L / R) Selected\nPairing Second Joy-Con...";
}
}
public void CancelPairSearch() {
if (isPairSearching) {
pairSearchLabel.SetActive(false);
isPairSearching = false;
pairingLabel.text = "Joy-Con (L / R) Selected\nPairing was cancelled.";
}
}
public void SearchAndConnectControllers()
{
int connected = PlayerInput.InitInputControllers();
numConnectedLabel.text = "Connected: " + connected;
currentControllerLabel.text = "Current Controller: " + PlayerInput.GetInputController(1).GetDeviceName();
PopulateControllersDropdown();
}
public void PopulateControllersDropdown()
{
List<TMP_Dropdown.OptionData> dropDownData = new List<TMP_Dropdown.OptionData>();
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 ShowControllerIcon(InputController controller)
{
string name = controller.GetDeviceName();
foreach (var icon in controllerIcons)
{
if (icon.name == name)
{
icon.SetActive(true);
}
else
{
icon.SetActive(false);
}
}
//setup material
Color colour;
switch (name)
{
case "Keyboard":
controllerMat.SetColor("_BodyColor", ColorUtility.TryParseHtmlString("#F4F4F4", out colour) ? colour : Color.white);
break;
case "Joy-Con (L)":
case "Joy-Con (R)":
InputJoyshock joy = (InputJoyshock) controller;
controllerMat.SetColor("_BodyColor", BitwiseUtils.IntToRgb(JslGetControllerColour(joy.GetHandle())));
controllerMat.SetColor("_BtnColor", BitwiseUtils.IntToRgb(JslGetControllerButtonColour(joy.GetHandle())));
controllerMat.SetColor("_LGripColor", ColorUtility.TryParseHtmlString("#2F353A", out colour) ? colour : Color.white);
controllerMat.SetColor("_RGripColor", ColorUtility.TryParseHtmlString("#2F353A", out colour) ? colour : Color.white);
break;
case "Joy-Con Pair":
joy = (InputJoyshock) controller;
int joySide = JslGetControllerSplitType(joy.GetHandle());
controllerMat.SetColor("_BodyColor", BitwiseUtils.IntToRgb(joySide == SplitRight ? JslGetControllerButtonColour(joy.GetHandle()) : JslGetControllerButtonColour(joy.GetOtherHalf().GetHandle())));
controllerMat.SetColor("_BtnColor", BitwiseUtils.IntToRgb(joySide == SplitLeft ? JslGetControllerButtonColour(joy.GetHandle()) : JslGetControllerButtonColour(joy.GetOtherHalf().GetHandle())));
controllerMat.SetColor("_LGripColor", BitwiseUtils.IntToRgb(joySide == SplitLeft ? JslGetControllerColour(joy.GetHandle()) : JslGetControllerColour(joy.GetOtherHalf().GetHandle())));
controllerMat.SetColor("_RGripColor", BitwiseUtils.IntToRgb(joySide == SplitRight ? JslGetControllerColour(joy.GetHandle()) : JslGetControllerColour(joy.GetOtherHalf().GetHandle())));
break;
case "Pro Controller":
joy = (InputJoyshock) controller;
controllerMat.SetColor("_BodyColor", BitwiseUtils.IntToRgb(JslGetControllerColour(joy.GetHandle())));
controllerMat.SetColor("_BtnColor", BitwiseUtils.IntToRgb(JslGetControllerButtonColour(joy.GetHandle())));
controllerMat.SetColor("_LGripColor", BitwiseUtils.IntToRgb(JslGetControllerLeftGripColour(joy.GetHandle())));
controllerMat.SetColor("_RGripColor", BitwiseUtils.IntToRgb(JslGetControllerRightGripColour(joy.GetHandle())));
break;
//TODO: dualshock 4 and dualsense lightbar colour support
case "DualShock 4":
controllerMat.SetColor("_BodyColor", ColorUtility.TryParseHtmlString("#E1E2E4", out colour) ? colour : Color.white);
controllerMat.SetColor("_BtnColor", ColorUtility.TryParseHtmlString("#414246", out colour) ? colour : Color.white);
controllerMat.SetColor("_LGripColor", ColorUtility.TryParseHtmlString("#1E6EFA", out colour) ? colour : Color.white);
controllerMat.SetColor("_RGripColor", ColorUtility.TryParseHtmlString("#1E6EFA", out colour) ? colour : Color.white);
break;
case "DualSense":
controllerMat.SetColor("_BodyColor", ColorUtility.TryParseHtmlString("#DEE0EB", out colour) ? colour : Color.white);
controllerMat.SetColor("_BtnColor", ColorUtility.TryParseHtmlString("#272D39", out colour) ? colour : Color.white);
controllerMat.SetColor("_LGripColor", ColorUtility.TryParseHtmlString("#1E6EFA", out colour) ? colour : Color.white);
controllerMat.SetColor("_RGripColor", ColorUtility.TryParseHtmlString("#1E6EFA", out colour) ? colour : Color.white);
break;
default:
controllerMat.SetColor("_BodyColor", new Color(1, 1, 1, 1));
controllerMat.SetColor("_BtnColor", new Color(1, 1, 1, 1));
controllerMat.SetColor("_LGripColor", new Color(1, 1, 1, 1));
controllerMat.SetColor("_RGripColor", new Color(1, 1, 1, 1));
break;
}
}
IEnumerator SelectionVibrate(InputJoyshock controller)
{
JslSetRumbleFrequency(controller.GetHandle(), 0.4f, 0.3f, 80f, 160f);
yield return new WaitForSeconds(0.15f);
JslSetRumbleFrequency(controller.GetHandle(), 0f, 0f, 0f, 0f);
yield return new WaitForSeconds(0.05f);
JslSetRumbleFrequency(controller.GetHandle(), 0.45f, 0.45f, 160f, 320f);
yield return new WaitForSeconds(0.25f);
JslSetRumbleFrequency(controller.GetHandle(), 0f, 0f, 0f, 0f);
}
}
}

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 10d59ed8edc40a448a61794f93c74ccd
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -68,7 +68,7 @@ namespace HeavenStudio.Editor
public void OnVolLabelChanged()
{
volSlider.value = (float)System.Math.Round(System.Convert.ToSingle(volLabel.text), 2);
volSlider.value = (float)System.Math.Round(System.Convert.ToSingle(volLabel.text) / 100f, 2);
GlobalGameManager.ChangeMasterVolume(volSlider.value);
}
}

View file

@ -1,127 +0,0 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
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;
// 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
public static bool Pressed(bool includeDPad = false)
{
bool keyDown = Input.GetKeyDown(KeyCode.Z) || (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) || (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) || (includeDPad && GetAnyDirection());
return pressing && !GameManager.instance.autoplay && Conductor.instance.isPlaying && GameManager.instance.canInput;
}
public static bool AltPressed()
{
return Input.GetKeyDown(KeyCode.X) && playerHasControl();
}
public static bool AltPressedUp()
{
return Input.GetKeyUp(KeyCode.X) && playerHasControl();
}
public static bool AltPressing()
{
return Input.GetKey(KeyCode.X) && playerHasControl();
}
//Directions
public static bool GetAnyDirectionDown()
{
return (Input.GetKeyDown(KeyCode.UpArrow)
|| Input.GetKeyDown(KeyCode.DownArrow)
|| Input.GetKeyDown(KeyCode.LeftArrow)
|| Input.GetKeyDown(KeyCode.RightArrow)) && playerHasControl();
}
public static bool GetAnyDirectionUp()
{
return (Input.GetKeyUp(KeyCode.UpArrow)
|| Input.GetKeyUp(KeyCode.DownArrow)
|| Input.GetKeyUp(KeyCode.LeftArrow)
|| Input.GetKeyUp(KeyCode.RightArrow)) && playerHasControl();
}
public static bool GetAnyDirection()
{
return (Input.GetKey(KeyCode.UpArrow)
|| Input.GetKey(KeyCode.DownArrow)
|| Input.GetKey(KeyCode.LeftArrow)
|| Input.GetKey(KeyCode.RightArrow)) && playerHasControl();
}
public static bool GetSpecificDirectionDown(int direction)
{
KeyCode targetCode = getKeyCode(direction);
if (targetCode == KeyCode.None) return false;
return Input.GetKeyDown(targetCode) && playerHasControl();
}
public static bool GetSpecificDirectionUp(int direction)
{
KeyCode targetCode = getKeyCode(direction);
if (targetCode == KeyCode.None) return false;
return Input.GetKeyUp(targetCode) && 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;
}
}
}

View file

@ -0,0 +1,63 @@
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
namespace HeavenStudio.Util
{
public static class BitwiseUtils
{
/// <summary>
/// Returns the value of the lowest set bit in the given integer.
/// </summary>
/// <param name="num">The integer to check.</param>
public static int FirstSetBit(int num)
{
return num & (-num);
}
/// <summary>
/// Returns true if the wanted bit is set in the given integer.
/// </summary>
/// <param name="num">The integer to check.</param>
/// <param name="want">The bit(s) to check for.</param>
public static bool WantCurrent(int num, int want)
{
if (want <= 0) return false;
return (num & want) == want;
}
/// <summary>
/// Returns true if the wanted bit is set in the first integer, and not in the second.
/// </summary>
/// <param name="num1">The first integer to check.</param>
/// <param name="num2">The second integer to check.</param>
/// <param name="want">The bit(s) to check for.</param>
public static bool WantCurrentAndNotLast(int num1, int num2, int want)
{
if (want <= 0) return false;
return ((num1 & want) == want) && ((num2 & want) != want);
}
/// <summary>
/// Returns true if the wanted bit is not set in the first integer, but set in the second.
/// </summary>
/// <param name="num1">The first integer to check.</param>
/// <param name="num2">The second integer to check.</param>
/// <param name="want">The bit(s) to check for.</param>
public static bool WantNotCurrentAndLast(int num1, int num2, int want)
{
if (want <= 0) return false;
return ((num1 & want) != want) && ((num2 & want) == want);
}
public static Color IntToRgb(int value)
{
var red = ( value >> 16 ) & 255;
var green = ( value >> 8 ) & 255;
var blue = ( value >> 0 ) & 255;
return new Color(red/255f, green/255f, blue/255f);
}
}
}

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 18f088a4c3c17b143a1985f3cee5d90a
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant: