diff --git a/Assets/Scripts/InputSystem/ControllerTypes/InputJoyconPair.cs b/Assets/Scripts/InputSystem/ControllerTypes/InputJoyconPair.cs index a31c9772e..faaabd099 100644 --- a/Assets/Scripts/InputSystem/ControllerTypes/InputJoyconPair.cs +++ b/Assets/Scripts/InputSystem/ControllerTypes/InputJoyconPair.cs @@ -56,199 +56,369 @@ namespace HeavenStudio.InputSystem { public class InputJoyconPair : InputController { + static readonly string[] nsConButtonNames = new[] + { + "Up", + "Down", + "Left", + "Right", + "Plus", + "Minus", + "Left Stick Click", + "Right Stick Click", + "L", + "R", + "ZL", + "ZR", + "B", + "A", + "Y", + "X", + "Home", + "Capture", + "", // mic on playstation, unused here + "SL", + "SR", + "Stick Up", + "Stick Down", + "Stick Left", + "Stick Right", + }; + + static int[] defaultMappings + { + get + { + return new[] + { + ButtonMaskUp, + ButtonMaskDown, + ButtonMaskLeft, + ButtonMaskRight, + ButtonMaskS, + ButtonMaskE, + ButtonMaskW, + ButtonMaskN, + ButtonMaskL, + ButtonMaskR, + ButtonMaskPlus, + -1 + }; + } + } + + InputJoyshock leftController, rightController; + bool pairIsPossible = false; + + public void SetLeftController(InputJoyshock leftController) + { + this.leftController = leftController; + } + + public void SetRightController(InputJoyshock rightController) + { + this.rightController = rightController; + } + + public bool HasControllers() + { + return leftController != null && rightController != null; + } + public override bool GetAction(ControlStyles style, int action) { - throw new NotImplementedException(); + if (leftController == null || rightController == null) + { + return false; + } + return leftController.GetAction(style, action) || rightController.GetAction(style, action); } public override bool GetActionDown(ControlStyles style, int action, out double dt) { - throw new NotImplementedException(); + if (leftController == null || rightController == null) + { + dt = 0; + return false; + } + return leftController.GetActionDown(style, action, out dt) || rightController.GetActionDown(style, action, out dt); } public override bool GetActionUp(ControlStyles style, int action, out double dt) { - throw new NotImplementedException(); + if (leftController == null || rightController == null) + { + dt = 0; + return false; + } + return leftController.GetActionUp(style, action, out dt) || rightController.GetActionUp(style, action, out dt); } public override float GetAxis(InputAxis axis) { - throw new NotImplementedException(); + if (leftController == null || rightController == null) + { + return 0; + } + return leftController.GetAxis(axis) + rightController.GetAxis(axis); } public override int GetBindingsVersion() { - throw new NotImplementedException(); + return 0; } public override string[] GetButtonNames() { - throw new NotImplementedException(); + return nsConButtonNames; } public override ControlBindings GetCurrentBindings() { - throw new NotImplementedException(); + return currentBindings; } public override bool GetCurrentStyleSupported() { - throw new NotImplementedException(); + return PlayerInput.CurrentControlStyle is ControlStyles.Pad; // or ControlStyles.Baton } public override ControlBindings GetDefaultBindings() { - throw new NotImplementedException(); + ControlBindings binds = new ControlBindings + { + Pad = defaultMappings, + version = GetBindingsVersion(), + PointerSensitivity = 3 + }; + return binds; } public override ControlStyles GetDefaultStyle() { - throw new NotImplementedException(); + return ControlStyles.Pad; } public override string GetDeviceName() { - throw new NotImplementedException(); + return "Joy-Con Pair"; } public override InputFeatures GetFeatures() { - throw new NotImplementedException(); + if (leftController == null || rightController == null) + { + return 0; + } + InputFeatures features = leftController.GetFeatures() | rightController.GetFeatures(); + return features; } public override bool GetFlick(out double dt) { - throw new NotImplementedException(); + if (leftController == null || rightController == null) + { + dt = 0; + return false; + } + return leftController.GetFlick(out dt) || rightController.GetFlick(out dt); } public override bool GetHatDirection(InputDirection direction) { - throw new NotImplementedException(); + if (leftController == null || rightController == null) + { + return false; + } + return leftController.GetHatDirection(direction) || rightController.GetHatDirection(direction); } public override bool GetHatDirectionDown(InputDirection direction, out double dt) { - throw new NotImplementedException(); + if (leftController == null || rightController == null) + { + dt = 0; + return false; + } + return leftController.GetHatDirectionDown(direction, out dt) || rightController.GetHatDirectionDown(direction, out dt); } public override bool GetHatDirectionUp(InputDirection direction, out double dt) { - throw new NotImplementedException(); + if (leftController == null || rightController == null) + { + dt = 0; + return false; + } + return leftController.GetHatDirectionUp(direction, out dt) || rightController.GetHatDirectionUp(direction, out dt); } public override bool GetIsActionUnbindable(int action, ControlStyles style) { - throw new NotImplementedException(); + return false; } public override bool GetIsConnected() { - throw new NotImplementedException(); + if (leftController == null || rightController == null) + { + return false; + } + return leftController.GetIsConnected() && rightController.GetIsConnected(); } public override bool GetIsPoorConnection() { - throw new NotImplementedException(); + if (leftController == null || rightController == null) + { + return false; + } + return leftController.GetIsPoorConnection() || rightController.GetIsPoorConnection(); } public override int GetLastActionDown() { - throw new NotImplementedException(); + if (leftController == null || rightController == null) + { + return -1; + } + return Math.Max(leftController.GetLastActionDown(), rightController.GetLastActionDown()); } public override int GetLastButtonDown(bool strict = false) { - throw new NotImplementedException(); + if (strict || leftController == null || rightController == null) + { + return -1; + } + return Math.Max(leftController.GetLastButtonDown(strict), rightController.GetLastButtonDown(strict)); } public override int? GetPlayer() { - throw new NotImplementedException(); + if (leftController == null || rightController == null) + { + return null; + } + return playerNum; } public override Vector2 GetPointer() { - throw new NotImplementedException(); + Camera cam = GameManager.instance.CursorCam; + Vector3 rawPointerPos = Input.mousePosition; + rawPointerPos.z = Mathf.Abs(cam.gameObject.transform.position.z); + return cam.ScreenToWorldPoint(rawPointerPos); } public override bool GetPointerLeftRight() { - throw new NotImplementedException(); + return false; } public override bool GetSlide(out double dt) { - throw new NotImplementedException(); + dt = 0; + return false; } public override bool GetSqueeze() { - throw new NotImplementedException(); + return false; } public override bool GetSqueezeDown(out double dt) { - throw new NotImplementedException(); + dt = 0; + return false; } public override bool GetSqueezeUp(out double dt) { - throw new NotImplementedException(); + dt = 0; + return false; } public override Vector3 GetVector(InputVector vector) { - throw new NotImplementedException(); + if (leftController == null || rightController == null) + { + return Vector3.zero; + } + return leftController.GetVector(vector) + rightController.GetVector(vector); } public override void InitializeController() { - throw new NotImplementedException(); + leftController = null; + rightController = null; } public override void OnSelected() { - throw new NotImplementedException(); + if (leftController == null || rightController == null) + { + return; + } + leftController.OnSelected(); + leftController.SetRotatedStickMode(false); + rightController.OnSelected(); + rightController.SetRotatedStickMode(false); + } + + async void SelectionVibrate(int handle) + { + JslSetRumbleFrequency(handle, 0.5f, 0.5f, 80f, 160f); + await Task.Delay(100); + JslSetRumbleFrequency(handle, 0f, 0f, 160f, 320f); } public override void RecentrePointer() { - throw new NotImplementedException(); } public override void ResetBindings() { - throw new NotImplementedException(); + currentBindings = GetDefaultBindings(); } public override void SetCurrentBindings(ControlBindings newBinds) { - throw new NotImplementedException(); + currentBindings = newBinds; } public override void SetMaterialProperties(Material m) { - throw new NotImplementedException(); + Color colour; + m.SetColor("_BodyColor", ColorUtility.TryParseHtmlString("#2F353A", out colour) ? colour : Color.white); + m.SetColor("_BtnColor", ColorUtility.TryParseHtmlString("#2F353A", out colour) ? colour : Color.white); + m.SetColor("_LGripColor", leftController.GetBodyColor()); + m.SetColor("_RGripColor", rightController.GetBodyColor()); } public override void SetPlayer(int? playerNum) { - throw new NotImplementedException(); + if (leftController != null) + { + leftController.SetPlayer(playerNum); + } + if (rightController != null) + { + rightController.SetPlayer(playerNum); + } } public override void TogglePointerLock(bool locked) { - throw new NotImplementedException(); } public override ControlBindings UpdateBindings(ControlBindings lastBinds) { - throw new NotImplementedException(); + return lastBinds; } public override void UpdateState() { - throw new NotImplementedException(); } } } \ No newline at end of file diff --git a/Assets/Scripts/InputSystem/ControllerTypes/InputJoyshock.cs b/Assets/Scripts/InputSystem/ControllerTypes/InputJoyshock.cs index 098bc347b..cf36d21f6 100644 --- a/Assets/Scripts/InputSystem/ControllerTypes/InputJoyshock.cs +++ b/Assets/Scripts/InputSystem/ControllerTypes/InputJoyshock.cs @@ -11,14 +11,25 @@ namespace HeavenStudio.InputSystem.Loaders { public static class InputJoyshockInitializer { + static bool failedJsl = false; [LoadOrder(2)] public static InputController[] Initialize() { + failedJsl = false; InputJoyshock.joyshocks = new(); PlayerInput.PlayerInputCleanUp += DisposeJoyshocks; PlayerInput.PlayerInputRefresh.Add(Refresh); - InputJoyshock.JslEventInit(); + try + { + InputJoyshock.JslEventInit(); + } + catch (Exception e) + { + Debug.LogError("Failed to initialize JoyShockLibrary: " + e.Message); + failedJsl = true; + return null; + } InputController[] controllers; int jslDevicesFound = 0; @@ -57,16 +68,18 @@ namespace HeavenStudio.InputSystem.Loaders public static void DisposeJoyshocks() { + if (failedJsl) return; foreach (InputJoyshock joyshock in InputJoyshock.joyshocks.Values) { joyshock.CleanUp(); } - JslSetCallback(null); JslDisconnectAndDisposeAll(); + JslSetCallback(null); } public static InputController[] Refresh() { + if (failedJsl) return null; InputJoyshock.joyshocks.Clear(); InputController[] controllers; int jslDevicesFound = 0; @@ -299,6 +312,7 @@ namespace HeavenStudio.InputSystem int lightbarColour; string joyshockName; DateTime startTime; + bool joyConWantRotatedStick; //buttons, sticks, triggers JoyshockButtonState[] actionStates = new JoyshockButtonState[BINDS_MAX]; @@ -471,6 +485,25 @@ namespace HeavenStudio.InputSystem xAxis = joyBtStateCurrent.stickLX; yAxis = joyBtStateCurrent.stickLY; + if (joyConWantRotatedStick && splitType != SplitFull) + { + float tempX = xAxis; + float tempY = yAxis; + switch (splitType) + { + case SplitLeft: + xAxis = -tempY; + yAxis = tempX; + break; + case SplitRight: + xAxis = joyBtStateCurrent.stickRX; + yAxis = joyBtStateCurrent.stickRY; + xAxis = tempY; + yAxis = -tempX; + break; + } + } + directionStateLast = directionStateCurrent; directionStateCurrent = 0; directionStateCurrent |= ((yAxis >= stickDeadzone) ? (1 << ((int)InputDirection.Up)) : 0); @@ -484,6 +517,7 @@ namespace HeavenStudio.InputSystem public override void OnSelected() { + SetRotatedStickMode(true); Task.Run(() => SelectionVibrate()); } @@ -570,7 +604,7 @@ namespace HeavenStudio.InputSystem break; } binds.PointerSensitivity = 3; - binds.version = 1; + binds.version = GetBindingsVersion(); return binds; } @@ -690,7 +724,7 @@ namespace HeavenStudio.InputSystem case InputAxis.AxisRStickY: return joyBtStateCurrent.stickRY; case InputAxis.PointerX: //isn't updated for now, so always returns 0f - //return joyTouchStateCurrent.t0X; + //return joyTouchStateCurrent.t0X; case InputAxis.PointerY: //return joyTouchStateCurrent.t0Y; default: @@ -864,6 +898,11 @@ namespace HeavenStudio.InputSystem return type; } + public void SetRotatedStickMode(bool rotated) + { + joyConWantRotatedStick = rotated; + } + public void SetLightbarColour(Color color) { lightbarColour = BitwiseUtils.RgbToInt(color); diff --git a/Assets/Scripts/SourceGenerators/MinigameLoaderGenerator.cs b/Assets/Scripts/SourceGenerators/MinigameLoaderGenerator.cs index a686aa5a9..1e0c3bf9f 100644 --- a/Assets/Scripts/SourceGenerators/MinigameLoaderGenerator.cs +++ b/Assets/Scripts/SourceGenerators/MinigameLoaderGenerator.cs @@ -83,7 +83,6 @@ namespace {context.TargetClass.Namespace} string fullMethodLabel = $"{callingClass}.{method}"; sb.Append($@" - Debug.Log(""Running game loader {callingClass}""); game = {fullMethodLabel}(eventCaller); if (game != null) {{ diff --git a/Assets/Scripts/UI/SettingsDialog/Tabs/ControllerSettings.cs b/Assets/Scripts/UI/SettingsDialog/Tabs/ControllerSettings.cs index 65581b452..7af09e09c 100644 --- a/Assets/Scripts/UI/SettingsDialog/Tabs/ControllerSettings.cs +++ b/Assets/Scripts/UI/SettingsDialog/Tabs/ControllerSettings.cs @@ -113,9 +113,32 @@ namespace HeavenStudio.Editor } } } - // else if (isPairSearching) - // { - // } + else if (currentController is InputJoyconPair) + { + InputJoyconPair pair = (InputJoyconPair)currentController; + if (!pair.HasControllers()) + { + List controllers = PlayerInput.GetInputControllers() + .Select(x => x as InputJoyshock) + .Where(x => x != null && x.GetJoyshockType() is TypeJoyConLeft or TypeJoyConRight) + .ToList(); + foreach (var possibleController in controllers) + { + if (possibleController.GetLastButtonDown(true) == ButtonMaskZL && possibleController.GetJoyshockType() is TypeJoyConLeft) + { + pair.SetLeftController(possibleController); + } + else if (possibleController.GetLastButtonDown(true) == ButtonMaskZR && possibleController.GetJoyshockType() is TypeJoyConRight) + { + pair.SetRightController(possibleController); + } + } + if (pair.HasControllers()) + { + pairSearchItem.SetActive(false); + } + } + } } } @@ -179,6 +202,17 @@ namespace HeavenStudio.Editor stylesDropdown.SetValueWithoutNotify((int)PlayerInput.CurrentControlStyle); } + newController.OnSelected(); + + if (newController is InputJoyconPair) + { + pairSearchItem.SetActive(true); + } + else + { + pairSearchItem.SetActive(false); + } + UpdateControlStyleMapping(); ShowControllerBinds(newController); ShowControllerIcon(newController); @@ -197,7 +231,12 @@ namespace HeavenStudio.Editor public void StartBindSingle(int bt) { CancelBind(); - if (PlayerInput.GetInputController(1).GetIsActionUnbindable(bt, PlayerInput.CurrentControlStyle)) + InputController currentController = PlayerInput.GetInputController(1); + if (currentController.GetIsActionUnbindable(bt, PlayerInput.CurrentControlStyle)) + { + return; + } + if (currentController is InputJoyconPair && !(currentController as InputJoyconPair).HasControllers()) { return; } @@ -220,9 +259,14 @@ namespace HeavenStudio.Editor public void StartBindAll() { CancelBind(); + InputController currentController = PlayerInput.GetInputController(1); + if (currentController is InputJoyconPair && !(currentController as InputJoyconPair).HasControllers()) + { + return; + } bindAllMode = true; currentBindingBt = -1; - AdvanceAutoBind(PlayerInput.GetInputController(1)); + AdvanceAutoBind(currentController); } public void CancelBind()