From 46668f87fb07e88a22d8d5e68a6985ffde909e60 Mon Sep 17 00:00:00 2001 From: Ricardo Date: Tue, 8 Feb 2022 20:38:59 +0100 Subject: [PATCH] No longer forcing minimal UI, showing decent prompts everywhere, including tutorials. (#157) * Decent prompts now * Hide reticule and examine prompts * Hide read prompt too * Tutorials! * Remove extra spaces from prompts * Cleanup * Fix scroll prompts * Hide map and compass prompts * Show jogging tutorial instead of zoom. * Hide one of the settings tab prompts * Show cancel in inventory prompt * Scale down UI * Auto update prompts when connecting controllers. (#161) * Auto update prompts when connecting controllers. * Check specific sources * Revert logs changes --- TwoForksVr/src/LaserPointer/VrLaser.cs | 14 ++-- TwoForksVr/src/Limbs/VrHand.cs | 6 +- .../src/Locomotion/TeleportController.cs | 10 +-- .../src/Locomotion/TurningController.cs | 8 +-- .../src/Settings/Patches/SettingsPatches.cs | 15 ---- TwoForksVr/src/Tools/ToolPicker.cs | 14 ++-- .../UI/Patches/CanvasToWorldSpacePatches.cs | 2 +- .../src/UI/Patches/SettingsMenuPatches.cs | 27 +++++++ TwoForksVr/src/UI/Patches/TutorialPatches.cs | 70 +++++++++++++++++++ TwoForksVr/src/UI/Patches/UIPatches.cs | 21 ++++++ TwoForksVr/src/VrCamera/VrCameraManager.cs | 4 +- .../src/VrInput/ActionInputs/ActionInput.cs | 40 +++++++++-- .../ActionInputs/ActionInputDefinitions.cs | 46 ++++++++---- .../ActionInputs/BooleanActionInput.cs | 21 ++++-- .../VrInput/ActionInputs/EmptyActionInput.cs | 18 ++++- .../src/VrInput/ActionInputs/IActionInput.cs | 15 ++-- .../VrInput/ActionInputs/SingleActionInput.cs | 15 ---- .../ActionInputs/Vector2ActionInput.cs | 19 ++++- TwoForksVr/src/VrInput/BindingsManager.cs | 30 ++++++-- .../src/VrInput/Patches/BindingsPatches.cs | 12 ++++ .../VrInput/Patches/InputPromptsPatches.cs | 28 +++++--- TwoForksVr/src/VrInput/VirtualKey.cs | 17 +++-- 22 files changed, 338 insertions(+), 114 deletions(-) create mode 100644 TwoForksVr/src/UI/Patches/SettingsMenuPatches.cs create mode 100644 TwoForksVr/src/UI/Patches/TutorialPatches.cs delete mode 100644 TwoForksVr/src/VrInput/ActionInputs/SingleActionInput.cs diff --git a/TwoForksVr/src/LaserPointer/VrLaser.cs b/TwoForksVr/src/LaserPointer/VrLaser.cs index 628d291b..006af3dc 100644 --- a/TwoForksVr/src/LaserPointer/VrLaser.cs +++ b/TwoForksVr/src/LaserPointer/VrLaser.cs @@ -1,5 +1,5 @@ using TwoForksVr.Helpers; -using TwoForksVr.VrInput; +using TwoForksVr.VrInput.ActionInputs; using UnityEngine; using Valve.VR; @@ -8,7 +8,7 @@ namespace TwoForksVr.LaserPointer public class VrLaser : MonoBehaviour { private const float laserLength = 1f; - private readonly SteamVR_Action_Boolean inputAction = BindingsManager.ActionSet.Interact; + private readonly IActionInput actionInput = ActionInputDefinitions.Interact; private bool ignoreNextInput; private LaserInputModule inputModule; @@ -61,7 +61,7 @@ private void Update() private void UpdateLaserParent(SteamVR_Input_Sources inputSource, Transform hand) { - if (!inputAction.GetStateDown(inputSource) || transform.parent == hand) return; + if (!actionInput.GetButtonDown(inputSource) || transform.parent == hand) return; ignoreNextInput = true; transform.SetParent(hand, false); } @@ -87,13 +87,13 @@ private bool HasCurrentTarget() private void UpdateLaserVisibility() { lineRenderer.enabled = - HasCurrentTarget() || BindingsManager.ActionSet.Interact.state; + HasCurrentTarget() || ActionInputDefinitions.Interact.AxisValue != 0; } public bool ClickDown() { if (ignoreNextInput) return false; - return inputAction.stateDown; + return actionInput.ButtonDown; } public bool ClickUp() @@ -104,12 +104,12 @@ public bool ClickUp() return false; } - return inputAction.stateUp; + return actionInput.ButtonUp; } public bool IsClicking() { - return inputAction.state; + return actionInput.ButtonValue; } } } \ No newline at end of file diff --git a/TwoForksVr/src/Limbs/VrHand.cs b/TwoForksVr/src/Limbs/VrHand.cs index 4439bdc4..4f2f4f9e 100644 --- a/TwoForksVr/src/Limbs/VrHand.cs +++ b/TwoForksVr/src/Limbs/VrHand.cs @@ -1,6 +1,6 @@ using TwoForksVr.Assets; using TwoForksVr.Helpers; -using TwoForksVr.VrInput; +using TwoForksVr.VrInput.ActionInputs; using UnityEngine; using Valve.VR; @@ -49,12 +49,12 @@ private void SetUpPose() if (isLeft) { pose.inputSource = SteamVR_Input_Sources.LeftHand; - pose.poseAction = BindingsManager.ActionSet.PoseLeftHand; + pose.poseAction = ActionInputDefinitions.ActionSet.PoseLeftHand; } else { pose.inputSource = SteamVR_Input_Sources.RightHand; - pose.poseAction = BindingsManager.ActionSet.PoseRightHand; + pose.poseAction = ActionInputDefinitions.ActionSet.PoseRightHand; } } diff --git a/TwoForksVr/src/Locomotion/TeleportController.cs b/TwoForksVr/src/Locomotion/TeleportController.cs index 8be6bef9..2d9df14e 100644 --- a/TwoForksVr/src/Locomotion/TeleportController.cs +++ b/TwoForksVr/src/Locomotion/TeleportController.cs @@ -2,7 +2,7 @@ using TwoForksVr.Limbs; using TwoForksVr.Settings; using TwoForksVr.Stage; -using TwoForksVr.VrInput; +using TwoForksVr.VrInput.ActionInputs; using UnityEngine; using Valve.VR; @@ -11,7 +11,7 @@ namespace TwoForksVr.Locomotion public class TeleportController : MonoBehaviour { private const float triggerTeleportSquareDistance = 0.3f; - private static readonly SteamVR_Action_Boolean teleportInput = BindingsManager.ActionSet.Teleport; + private static readonly IActionInput teleportInput = ActionInputDefinitions.Teleport; private VrLimbManager limbManager; private vgPlayerNavigationController navigationController; private TeleportArc teleportArc; @@ -36,8 +36,8 @@ public void SetUp(vgPlayerController playerController) private void Update() { - if (teleportInput.GetStateDown(SteamVR_Input_Sources.LeftHand)) SetHand(limbManager.LeftHand); - if (teleportInput.GetStateDown(SteamVR_Input_Sources.RightHand)) SetHand(limbManager.RightHand); + if (teleportInput.GetButtonDown(SteamVR_Input_Sources.LeftHand)) SetHand(limbManager.LeftHand); + if (teleportInput.GetButtonDown(SteamVR_Input_Sources.RightHand)) SetHand(limbManager.RightHand); UpdateArc(); UpdatePlayerRotation(); } @@ -61,7 +61,7 @@ public bool IsNextToTeleportMarker(Transform objectTransform) public bool IsTeleporting() { return VrSettings.Teleport.Value && - teleportInput.GetState(SteamVR_Input_Sources.Any) && navigationController && + teleportInput.ButtonValue && navigationController && navigationController.enabled && !vgPauseManager.Instance.isPaused; } diff --git a/TwoForksVr/src/Locomotion/TurningController.cs b/TwoForksVr/src/Locomotion/TurningController.cs index d7fc7e06..4628cf49 100644 --- a/TwoForksVr/src/Locomotion/TurningController.cs +++ b/TwoForksVr/src/Locomotion/TurningController.cs @@ -2,7 +2,7 @@ using TwoForksVr.Settings; using TwoForksVr.Stage; using TwoForksVr.VrCamera; -using TwoForksVr.VrInput; +using TwoForksVr.VrInput.ActionInputs; using UnityEngine; namespace TwoForksVr.Locomotion @@ -45,13 +45,13 @@ private void Update() private void UpdateSnapTurning() { - if (BindingsManager.ActionSet.SnapTurnLeft.stateDown) + if (ActionInputDefinitions.SnapTurnLeft.ButtonDown) { stage.FadeToBlack(); Invoke(nameof(SnapTurnLeft), FadeOverlay.Duration); } - if (BindingsManager.ActionSet.SnapTurnRight.stateDown) + if (ActionInputDefinitions.SnapTurnRight.ButtonDown) { stage.FadeToBlack(); Invoke(nameof(SnapTurnRight), FadeOverlay.Duration); @@ -62,7 +62,7 @@ private void UpdateSmoothTurning() { navigationController.transform.Rotate( Vector3.up, - BindingsManager.ActionSet.Rotate.axis.x * smoothRotationSpeed * Time.unscaledDeltaTime); + ActionInputDefinitions.RotateX.AxisValue * smoothRotationSpeed * Time.unscaledDeltaTime); } private void SnapTurnLeft() diff --git a/TwoForksVr/src/Settings/Patches/SettingsPatches.cs b/TwoForksVr/src/Settings/Patches/SettingsPatches.cs index a39d2a99..331c4221 100644 --- a/TwoForksVr/src/Settings/Patches/SettingsPatches.cs +++ b/TwoForksVr/src/Settings/Patches/SettingsPatches.cs @@ -15,13 +15,6 @@ private static void ForceDisableHeadBob(ref bool value) value = false; } - [HarmonyPrefix] - [HarmonyPatch(typeof(vgSettingsManager), nameof(vgSettingsManager.minimalInterface), MethodType.Setter)] - private static void ForceEnableMinimalInterface(ref bool value) - { - value = true; - } - [HarmonyPrefix] [HarmonyPatch(typeof(vgSettingsManager), nameof(vgSettingsManager.MotionBlurQuality), MethodType.Setter)] private static void ForceNoMotionBlur(ref int value) @@ -45,13 +38,5 @@ private static bool HideResolutionOptions() { return false; } - - [HarmonyPrefix] - [HarmonyPatch(typeof(vgSettingsMenuController), nameof(vgSettingsMenuController.Start))] - private static void RemoveControlsTab(vgSettingsMenuController __instance) - { - __instance.screens.RemoveAt(2); - Object.Destroy(__instance.selectionGroup.buttonElements[2].gameObject); - } } } \ No newline at end of file diff --git a/TwoForksVr/src/Tools/ToolPicker.cs b/TwoForksVr/src/Tools/ToolPicker.cs index b566180d..173b8e87 100644 --- a/TwoForksVr/src/Tools/ToolPicker.cs +++ b/TwoForksVr/src/Tools/ToolPicker.cs @@ -1,7 +1,7 @@ using System.Collections.Generic; using TwoForksVr.Assets; using TwoForksVr.Helpers; -using TwoForksVr.VrInput; +using TwoForksVr.VrInput.ActionInputs; using UnityEngine; using Valve.VR; @@ -11,7 +11,7 @@ public class ToolPicker : MonoBehaviour { private const float minSquareDistance = 0.03f; - private readonly SteamVR_Action_Boolean input = BindingsManager.ActionSet.ToolPicker; + private readonly IActionInput input = ActionInputDefinitions.ToolPicker; private ToolPickerItem hoveredTool; private Transform leftHand; private Transform rightHand; @@ -41,11 +41,11 @@ private void Start() private void Update() { - if (input.GetState(SteamVR_Input_Sources.RightHand)) UpdateSelectedTool(rightHand); - if (input.GetState(SteamVR_Input_Sources.LeftHand)) UpdateSelectedTool(leftHand); - if (input.GetStateDown(SteamVR_Input_Sources.RightHand)) OpenToolPicker(rightHand); - if (input.GetStateDown(SteamVR_Input_Sources.LeftHand)) OpenToolPicker(leftHand); - if (input.stateUp) CloseToolPicker(); + if (input.GetButtonValue(SteamVR_Input_Sources.RightHand)) UpdateSelectedTool(rightHand); + if (input.GetButtonValue(SteamVR_Input_Sources.LeftHand)) UpdateSelectedTool(leftHand); + if (input.GetButtonDown(SteamVR_Input_Sources.RightHand)) OpenToolPicker(rightHand); + if (input.GetButtonDown(SteamVR_Input_Sources.LeftHand)) OpenToolPicker(leftHand); + if (input.ButtonUp) CloseToolPicker(); } private void SetUpTools() diff --git a/TwoForksVr/src/UI/Patches/CanvasToWorldSpacePatches.cs b/TwoForksVr/src/UI/Patches/CanvasToWorldSpacePatches.cs index 5e9eb0ae..45c4d401 100644 --- a/TwoForksVr/src/UI/Patches/CanvasToWorldSpacePatches.cs +++ b/TwoForksVr/src/UI/Patches/CanvasToWorldSpacePatches.cs @@ -58,7 +58,7 @@ private static void MoveCanvasesToWorldSpace(CanvasScaler __instance) if (canvas.GetComponent()) AttachedUi.Create(canvas, StageInstance.GetInteractiveUiTarget(), 0.002f); else - AttachedUi.Create(canvas, StageInstance.GetStaticUiTarget(), 0.0005f); + AttachedUi.Create(canvas, StageInstance.GetStaticUiTarget(), 0.0004f); } catch (Exception exception) { diff --git a/TwoForksVr/src/UI/Patches/SettingsMenuPatches.cs b/TwoForksVr/src/UI/Patches/SettingsMenuPatches.cs new file mode 100644 index 00000000..13b2d3de --- /dev/null +++ b/TwoForksVr/src/UI/Patches/SettingsMenuPatches.cs @@ -0,0 +1,27 @@ +using HarmonyLib; +using UnityEngine; + +// Some of the available game settings don't go well with VR. +// These patches force some settings to certain values to prevent VR funkyness. +namespace TwoForksVr.UI.Patches +{ + [HarmonyPatch] + public class SettingsMenuPatches + { + [HarmonyPrefix] + [HarmonyPatch(typeof(vgSettingsMenuController), nameof(vgSettingsMenuController.Start))] + private static void RemoveUnusedSettingsElements(vgSettingsMenuController __instance) + { + // Rmove control settings screen. + __instance.screens.RemoveAt(2); + + // Remove control settings tab. + Object.Destroy(__instance.selectionGroup.buttonElements[2].gameObject); + + // Remove one of the tab input prompts. + // Since the input prompts have been patched to use VR control names, both of these prompts (left and right) + // were saying the same thing (something like "Right Stick"). So we can remove one of them. + __instance.selectionGroup.transform.Find("ButtonContainer").GetChild(0).gameObject.SetActive(false); + } + } +} \ No newline at end of file diff --git a/TwoForksVr/src/UI/Patches/TutorialPatches.cs b/TwoForksVr/src/UI/Patches/TutorialPatches.cs new file mode 100644 index 00000000..e2eff42f --- /dev/null +++ b/TwoForksVr/src/UI/Patches/TutorialPatches.cs @@ -0,0 +1,70 @@ +using System.Collections.Generic; +using HarmonyLib; +using TMPro; +using TwoForksVr.Helpers; +using TwoForksVr.VrInput; +using UnityEngine; + +namespace TwoForksVr.UI.Patches +{ + [HarmonyPatch] + public static class TutorialPatches + { + private static readonly Dictionary tutorialTextMap = new Dictionary + { + {"textRadio", $"Hold [{VirtualKey.Radio}] to activate radio."}, + {"textRadio_select_dialog", $"[{VirtualKey.ScrollUpDown}] to select dialog."}, + {"textUse_radio", $"Release [{VirtualKey.Radio}] to talk to Delilah."}, + {"textInspect_object", "Look at hand to inspect objects."}, + {"textInspect_object_move", ""}, + {"textRadio_object", $"Aim with hand and hold [{VirtualKey.Radio}] to talk about targeted object."}, + {"textJournal_examine", "Look at hand to inspect journal."}, + {"textJournal_stow", $"[{VirtualKey.StoreObject}] to keep journal."}, + {"textCompass", $"Hold [{VirtualKey.ToolPicker}] to select compass from tool picker."}, + {"textFlashlight", $"Hold [{VirtualKey.ToolPicker}] to select flashlight from tool picker."}, + {"textMap", $"Hold [{VirtualKey.ToolPicker}] to select map from tool picker."}, + {"textJog_toggle", $"[{VirtualKey.Jog}] to toggle jogging."}, + {"textMantle", $"[{VirtualKey.LocomotionAction}] to climb over obstructions."}, + {"textUse_object", $"Aim with hand and press [{VirtualKey.Use}] to use objects."}, + {"textInventory_open", $"Hold [{VirtualKey.ToolPicker}] to select notes inventory from the tool picker."}, + {"textInventory_browse", "Use hand laser to browse notes."}, + {"textInventory_read", $"[{VirtualKey.StoreObject}] to store note"}, + {"textCamera", $"Hold [{VirtualKey.ToolPicker}] to select camera from tool picker."}, + {"textCamera_picture", $"[{VirtualKey.Use}] to take a picture."}, + {"textCamera_lower", $"Press [{VirtualKey.ToolPicker}] to lower camera."}, + {"textWaveReceiver", $"Hold [{VirtualKey.ToolPicker}] to select wave receiver from tool picker."}, + {"textRadio_concept", $"Hold [{VirtualKey.Radio}] to radio about current subject of interest."}, + {"textRadio_heldobject", $"Hold [{VirtualKey.Radio}] to talk about currently held object."}, + + // There's no zooming in VR. Couldn't figure out an easy way to hide the whole tutorial box, + // so I'm just showing the jogging tutorial instead. + {"textZoom", $"[{VirtualKey.Jog}] to toggle jogging."}, + + // Unused tutorial text. + {"Text", ""} + }; + + [HarmonyPrefix] + [HarmonyPatch(typeof(vgHudManager), nameof(vgHudManager.Awake))] + private static void SetUpTutorials(vgHudManager __instance) + { + var tutorialObject = + __instance.transform.Find( + "uGUI Root/HUD/SafeZoner/BottomCenterGroup/TutorialPopup/TutorialPopupParent/TutorialObject"); + + Logs.LogInfo($"Found {tutorialObject.childCount} tutorials"); + foreach (Transform child in tutorialObject) + { + Logs.LogInfo($"{child.name}: {child.GetComponent().text}"); + tutorialTextMap.TryGetValue(child.name, out var tutorialString); + if (tutorialString == null) + { + Logs.LogError($"No tutorial text found for {child.name}"); + continue; + } + + child.GetComponent().text = tutorialString; + } + } + } +} \ No newline at end of file diff --git a/TwoForksVr/src/UI/Patches/UIPatches.cs b/TwoForksVr/src/UI/Patches/UIPatches.cs index bd1f690a..f2481cc3 100644 --- a/TwoForksVr/src/UI/Patches/UIPatches.cs +++ b/TwoForksVr/src/UI/Patches/UIPatches.cs @@ -67,5 +67,26 @@ private static void PreventTextFromDrawingOnTop(TextMeshProUGUI __instance) Logs.LogWarning($"Error in TMPro Patch ({__instance.name}): {exception}"); } } + + [HarmonyPostfix] + [HarmonyPatch(typeof(vgHudManager), nameof(vgHudManager.Awake))] + private static void HideHudElements(vgHudManager __instance) + { + __instance.readObjectButtonGroup.transform.parent.Find("ExamineItem").gameObject.SetActive(false); + __instance.readObjectButtonGroup.SetActive(false); + + // Dummy object is just so the hud manager still has a valid reference after we destroy the object. + __instance.readObjectButtonGroup = new GameObject("Dummy"); + __instance.readObjectButtonGroup.transform.SetParent(__instance.transform, false); + + var safeZoner = __instance.transform.Find("uGUI Root/HUD/SafeZoner"); + var reticule = safeZoner.Find("ReticuleGroup/ReticuleParent/ReticuleCanvasGroup/Reticule"); + reticule.GetComponent().enabled = false; + reticule.Find("ReticuleLarge").GetComponent().enabled = false; + + var bottomLeftObjects = safeZoner.Find("BottomLeftObjects"); + bottomLeftObjects.Find("CompassOnScreenTooltip").gameObject.SetActive(false); + bottomLeftObjects.Find("MapOnScreenTooltip").gameObject.SetActive(false); + } } } \ No newline at end of file diff --git a/TwoForksVr/src/VrCamera/VrCameraManager.cs b/TwoForksVr/src/VrCamera/VrCameraManager.cs index ac2cced7..c227d9b9 100644 --- a/TwoForksVr/src/VrCamera/VrCameraManager.cs +++ b/TwoForksVr/src/VrCamera/VrCameraManager.cs @@ -1,6 +1,6 @@ using TwoForksVr.Helpers; using TwoForksVr.Stage; -using TwoForksVr.VrInput; +using TwoForksVr.VrInput.ActionInputs; using UnityEngine; using UnityEngine.XR; using UnityStandardAssets.ImageEffects; @@ -42,7 +42,7 @@ private void Start() private void Update() { - if (BindingsManager.ActionSet.Recenter.stateDown) RecenterPosition(true); + if (ActionInputDefinitions.Recenter.ButtonDown) RecenterPosition(true); UpdateCulling(); } diff --git a/TwoForksVr/src/VrInput/ActionInputs/ActionInput.cs b/TwoForksVr/src/VrInput/ActionInputs/ActionInput.cs index 1d85051a..ddcf3214 100644 --- a/TwoForksVr/src/VrInput/ActionInputs/ActionInput.cs +++ b/TwoForksVr/src/VrInput/ActionInputs/ActionInput.cs @@ -5,6 +5,8 @@ namespace TwoForksVr.VrInput.ActionInputs public abstract class ActionInput : IActionInput where TAction : ISteamVR_Action_In { protected readonly TAction SpecificAction; + protected bool IsEitherHandValue; + protected string PromptSuffixValue; protected ActionInput(TAction action) { @@ -12,10 +14,38 @@ protected ActionInput(TAction action) } public ISteamVR_Action_In Action => SpecificAction; - public bool Active => Action.active; - public abstract float Value { get; } - public abstract bool ValueUp { get; } - public abstract bool ValueDown { get; } - public SteamVR_Input_Sources ActiveSource => Action?.activeDevice ?? SteamVR_Input_Sources.Any; + public float AxisValue => GetAxisValue(); + public bool ButtonValue => GetButtonValue(); + public bool ButtonUp => GetButtonUp(); + public bool ButtonDown => GetButtonDown(); + public bool IsEitherHand => IsEitherHandValue; + public string PromptSuffix => PromptSuffixValue; + + public SteamVR_Input_Sources ActiveSource => + Action != null && Action.active ? Action.activeDevice : SteamVR_Input_Sources.Any; + + public float GetAxisValue(SteamVR_Input_Sources source = SteamVR_Input_Sources.Any) + { + return Action.active ? GetValue(source) : 0; + } + + public bool GetButtonValue(SteamVR_Input_Sources source = SteamVR_Input_Sources.Any) + { + return Action.active && GetValue(source) != 0; + } + + public bool GetButtonUp(SteamVR_Input_Sources source = SteamVR_Input_Sources.Any) + { + return Action.active && GetValueUp(source); + } + + public bool GetButtonDown(SteamVR_Input_Sources source = SteamVR_Input_Sources.Any) + { + return Action.active && GetValueDown(source); + } + + protected abstract float GetValue(SteamVR_Input_Sources source); + protected abstract bool GetValueUp(SteamVR_Input_Sources source); + protected abstract bool GetValueDown(SteamVR_Input_Sources source); } } \ No newline at end of file diff --git a/TwoForksVr/src/VrInput/ActionInputs/ActionInputDefinitions.cs b/TwoForksVr/src/VrInput/ActionInputs/ActionInputDefinitions.cs index c153bb44..da3073f7 100644 --- a/TwoForksVr/src/VrInput/ActionInputs/ActionInputDefinitions.cs +++ b/TwoForksVr/src/VrInput/ActionInputs/ActionInputDefinitions.cs @@ -1,50 +1,66 @@ -namespace TwoForksVr.VrInput.ActionInputs +using Valve.VR; + +namespace TwoForksVr.VrInput.ActionInputs { public static class ActionInputDefinitions { + public static readonly SteamVR_Input_ActionSet_default ActionSet = SteamVR_Actions._default; + public static readonly EmptyActionInput Empty = new EmptyActionInput(); public static readonly BooleanActionInput Cancel = - new BooleanActionInput(BindingsManager.ActionSet.Cancel); + new BooleanActionInput(ActionSet.Cancel); public static readonly BooleanActionInput Grip = - new BooleanActionInput(BindingsManager.ActionSet.Grip); + new BooleanActionInput(ActionSet.Grip); public static readonly BooleanActionInput Radio = - new BooleanActionInput(BindingsManager.ActionSet.Radio); + new BooleanActionInput(ActionSet.Radio); public static readonly BooleanActionInput Interact = - new BooleanActionInput(BindingsManager.ActionSet.Interact); + new BooleanActionInput(ActionSet.Interact, "", true); public static readonly BooleanActionInput Jog = - new BooleanActionInput(BindingsManager.ActionSet.Jog); + new BooleanActionInput(ActionSet.Jog); public static readonly BooleanActionInput UIUp = - new BooleanActionInput(BindingsManager.ActionSet.UIUp); + new BooleanActionInput(ActionSet.UIUp); public static readonly BooleanActionInput UIDown = - new BooleanActionInput(BindingsManager.ActionSet.UIDown); + new BooleanActionInput(ActionSet.UIDown); public static readonly BooleanActionInput NextPage = - new BooleanActionInput(BindingsManager.ActionSet.NextPage); + new BooleanActionInput(ActionSet.NextPage); public static readonly BooleanActionInput PreviousPage = - new BooleanActionInput(BindingsManager.ActionSet.PreviousPage); + new BooleanActionInput(ActionSet.PreviousPage); public static readonly Vector2ActionInput MoveX = - new Vector2ActionInput(BindingsManager.ActionSet.Move); + new Vector2ActionInput(ActionSet.Move); public static readonly Vector2ActionInput MoveY = - new Vector2ActionInput(BindingsManager.ActionSet.Move, true); + new Vector2ActionInput(ActionSet.Move, true); public static readonly Vector2ActionInput RotateX = - new Vector2ActionInput(BindingsManager.ActionSet.Rotate); + new Vector2ActionInput(ActionSet.Rotate); public static readonly Vector2ActionInput RotateY = - new Vector2ActionInput(BindingsManager.ActionSet.Rotate, true); + new Vector2ActionInput(ActionSet.Rotate, true); public static readonly BooleanActionInput Recenter = - new BooleanActionInput(BindingsManager.ActionSet.Recenter); + new BooleanActionInput(ActionSet.Recenter); + + public static readonly BooleanActionInput ToolPicker = + new BooleanActionInput(ActionSet.ToolPicker); + + public static readonly BooleanActionInput Teleport = + new BooleanActionInput(ActionSet.Teleport); + + public static readonly BooleanActionInput SnapTurnLeft = + new BooleanActionInput(ActionSet.SnapTurnLeft); + + public static readonly BooleanActionInput SnapTurnRight = + new BooleanActionInput(ActionSet.SnapTurnRight); } } \ No newline at end of file diff --git a/TwoForksVr/src/VrInput/ActionInputs/BooleanActionInput.cs b/TwoForksVr/src/VrInput/ActionInputs/BooleanActionInput.cs index 6340eee3..0997ade8 100644 --- a/TwoForksVr/src/VrInput/ActionInputs/BooleanActionInput.cs +++ b/TwoForksVr/src/VrInput/ActionInputs/BooleanActionInput.cs @@ -4,13 +4,26 @@ namespace TwoForksVr.VrInput.ActionInputs { public class BooleanActionInput : ActionInput { - public BooleanActionInput(SteamVR_Action_Boolean action) : + public BooleanActionInput(SteamVR_Action_Boolean action, string promptSuffix = "", bool isEitherHand = false) : base(action) { + PromptSuffixValue = promptSuffix; + IsEitherHandValue = isEitherHand; } - public override float Value => SpecificAction.state ? 1 : 0; - public override bool ValueUp => SpecificAction.stateUp; - public override bool ValueDown => SpecificAction.stateDown; + protected override float GetValue(SteamVR_Input_Sources source) + { + return SpecificAction.GetState(source) ? 1 : 0; + } + + protected override bool GetValueUp(SteamVR_Input_Sources source) + { + return SpecificAction.GetStateUp(source); + } + + protected override bool GetValueDown(SteamVR_Input_Sources source) + { + return SpecificAction.GetStateDown(source); + } } } \ No newline at end of file diff --git a/TwoForksVr/src/VrInput/ActionInputs/EmptyActionInput.cs b/TwoForksVr/src/VrInput/ActionInputs/EmptyActionInput.cs index 1a4779fe..e3345ec9 100644 --- a/TwoForksVr/src/VrInput/ActionInputs/EmptyActionInput.cs +++ b/TwoForksVr/src/VrInput/ActionInputs/EmptyActionInput.cs @@ -9,9 +9,21 @@ public EmptyActionInput(string texturePath = null) : base(null) TexturePath = texturePath; } - public override float Value => 0; public string TexturePath { get; } - public override bool ValueUp => false; - public override bool ValueDown => false; + + protected override float GetValue(SteamVR_Input_Sources source) + { + return 0; + } + + protected override bool GetValueUp(SteamVR_Input_Sources source) + { + return false; + } + + protected override bool GetValueDown(SteamVR_Input_Sources source) + { + return false; + } } } \ No newline at end of file diff --git a/TwoForksVr/src/VrInput/ActionInputs/IActionInput.cs b/TwoForksVr/src/VrInput/ActionInputs/IActionInput.cs index fd24ab71..b27f192e 100644 --- a/TwoForksVr/src/VrInput/ActionInputs/IActionInput.cs +++ b/TwoForksVr/src/VrInput/ActionInputs/IActionInput.cs @@ -5,10 +5,17 @@ namespace TwoForksVr.VrInput.ActionInputs public interface IActionInput { ISteamVR_Action_In Action { get; } - bool Active { get; } - float Value { get; } - bool ValueUp { get; } - bool ValueDown { get; } + float AxisValue { get; } + bool ButtonValue { get; } + bool ButtonUp { get; } + bool ButtonDown { get; } + bool IsEitherHand { get; } + string PromptSuffix { get; } SteamVR_Input_Sources ActiveSource { get; } + + float GetAxisValue(SteamVR_Input_Sources source); + bool GetButtonValue(SteamVR_Input_Sources source); + bool GetButtonUp(SteamVR_Input_Sources source); + bool GetButtonDown(SteamVR_Input_Sources source); } } \ No newline at end of file diff --git a/TwoForksVr/src/VrInput/ActionInputs/SingleActionInput.cs b/TwoForksVr/src/VrInput/ActionInputs/SingleActionInput.cs deleted file mode 100644 index 311e1a44..00000000 --- a/TwoForksVr/src/VrInput/ActionInputs/SingleActionInput.cs +++ /dev/null @@ -1,15 +0,0 @@ -using Valve.VR; - -namespace TwoForksVr.VrInput.ActionInputs -{ - public class SingleActionInput : ActionInput - { - public SingleActionInput(SteamVR_Action_Single action) : base(action) - { - } - - public override float Value => SpecificAction.axis; - public override bool ValueUp => false; - public override bool ValueDown => false; - } -} \ No newline at end of file diff --git a/TwoForksVr/src/VrInput/ActionInputs/Vector2ActionInput.cs b/TwoForksVr/src/VrInput/ActionInputs/Vector2ActionInput.cs index b7bae65e..553efe5a 100644 --- a/TwoForksVr/src/VrInput/ActionInputs/Vector2ActionInput.cs +++ b/TwoForksVr/src/VrInput/ActionInputs/Vector2ActionInput.cs @@ -13,9 +13,22 @@ public Vector2ActionInput(SteamVR_Action_Vector2 action, bool yOnly = false, TextureModifier = textureModifier; } - public override float Value => yOnly ? SpecificAction.axis.y : SpecificAction.axis.x; public string TextureModifier { get; } - public override bool ValueUp => false; - public override bool ValueDown => false; + + protected override float GetValue(SteamVR_Input_Sources source) + { + var axis = SpecificAction.GetAxis(source); + return yOnly ? axis.y : axis.x; + } + + protected override bool GetValueUp(SteamVR_Input_Sources source) + { + return false; + } + + protected override bool GetValueDown(SteamVR_Input_Sources source) + { + return false; + } } } \ No newline at end of file diff --git a/TwoForksVr/src/VrInput/BindingsManager.cs b/TwoForksVr/src/VrInput/BindingsManager.cs index 40880b3a..a0ea3589 100644 --- a/TwoForksVr/src/VrInput/BindingsManager.cs +++ b/TwoForksVr/src/VrInput/BindingsManager.cs @@ -9,10 +9,8 @@ namespace TwoForksVr.VrInput { public class BindingsManager : MonoBehaviour { - public static SteamVR_Input_ActionSet_default ActionSet = SteamVR_Actions._default; public Dictionary ActionMap { get; private set; } - public static BindingsManager Create(VrStage stage) { var instance = stage.gameObject.AddComponent(); @@ -43,8 +41,28 @@ private void Awake() {VirtualKey.MoveForwardKeyboard, ActionInputDefinitions.UIUp}, {VirtualKey.MoveBackwardKeyboard, ActionInputDefinitions.UIDown}, {VirtualKey.StrafeRightKeyboard, ActionInputDefinitions.NextPage}, - {VirtualKey.StrafeLeftKeyboard, ActionInputDefinitions.PreviousPage} + {VirtualKey.StrafeLeftKeyboard, ActionInputDefinitions.PreviousPage}, + + // Unused for actually controlling stuff, but used for the input prompts. + {VirtualKey.ScrollUpDown, ActionInputDefinitions.UIUp}, + {VirtualKey.ToolPicker, ActionInputDefinitions.ToolPicker}, + {VirtualKey.Inventory, ActionInputDefinitions.Cancel} }; + + SteamVR_Events.System(EVREventType.VREvent_Input_BindingsUpdated).Listen(HandleVrBindingsUpdated); + } + + private void OnDestroy() + { + SteamVR_Events.System(EVREventType.VREvent_Input_BindingsUpdated).Remove(HandleVrBindingsUpdated); + } + + private static void HandleVrBindingsUpdated(VREvent_t arg0) + { + if (!vgInputManager.Instance) return; + + // This resets the input prompts. The layout choice argument isn't actually used. + vgInputManager.Instance.SetControllerLayout(vgControllerLayoutChoice.KeyboardMouse); } public float GetValue(string virtualKey) @@ -52,7 +70,7 @@ public float GetValue(string virtualKey) ActionMap.TryGetValue(virtualKey, out var actionInput); if (actionInput == null) return 0; - return actionInput.Value; + return actionInput.AxisValue; } public bool GetUp(string virtualKey) @@ -60,7 +78,7 @@ public bool GetUp(string virtualKey) ActionMap.TryGetValue(virtualKey, out var actionInput); if (actionInput == null) return false; - return actionInput.ValueUp; + return actionInput.ButtonUp; } public bool GetDown(string virtualKey) @@ -68,7 +86,7 @@ public bool GetDown(string virtualKey) ActionMap.TryGetValue(virtualKey, out var actionInput); if (actionInput == null) return false; - return actionInput.ValueDown; + return actionInput.ButtonDown; } } } \ No newline at end of file diff --git a/TwoForksVr/src/VrInput/Patches/BindingsPatches.cs b/TwoForksVr/src/VrInput/Patches/BindingsPatches.cs index 1b092fe8..313b7a8f 100644 --- a/TwoForksVr/src/VrInput/Patches/BindingsPatches.cs +++ b/TwoForksVr/src/VrInput/Patches/BindingsPatches.cs @@ -13,6 +13,12 @@ public class BindingsPatches : TwoForksVrPatch private const float outerDeadzone = 0.5f; private const float innerDeadzone = 0.1f; + private static readonly HashSet ignoredVirtualKeys = new HashSet + { + VirtualKey.ScrollUpDown, + VirtualKey.Inventory + }; + private static readonly Dictionary> replacementCommandMap = new Dictionary> { @@ -146,6 +152,12 @@ private static void FixCommandsAhhhhhhh(LinkedList stack) foreach (var inputContext in stack) foreach (var commandMapping in inputContext.commandMap) { + if (ignoredVirtualKeys.Contains(commandMapping.virtualKey)) + { + commandMapping.commands.Clear(); + continue; + } + replacementCommandMap.TryGetValue(commandMapping.virtualKey, out var commandReplacements); if (commandReplacements == null) continue; diff --git a/TwoForksVr/src/VrInput/Patches/InputPromptsPatches.cs b/TwoForksVr/src/VrInput/Patches/InputPromptsPatches.cs index fd2cb3d7..11ab37f3 100644 --- a/TwoForksVr/src/VrInput/Patches/InputPromptsPatches.cs +++ b/TwoForksVr/src/VrInput/Patches/InputPromptsPatches.cs @@ -1,5 +1,5 @@ +using System.Globalization; using HarmonyLib; -using TwoForksVr.Helpers; using Valve.VR; namespace TwoForksVr.VrInput.Patches @@ -7,28 +7,40 @@ namespace TwoForksVr.VrInput.Patches [HarmonyPatch] public class InputPromptsPatches : TwoForksVrPatch { + private static readonly TextInfo textInfo = new CultureInfo("en-US", false).TextInfo; + [HarmonyPrefix] [HarmonyPatch(typeof(vgButtonIconMap), nameof(vgButtonIconMap.GetIconName))] private static bool ReplacePromptIconsWithVrButtonText(ref string __result, string id) { var inputAction = StageInstance.GetInputAction(id); - if (inputAction == null) + if (inputAction?.Action == null || !inputAction.Action.active) + { + __result = "n/a"; + return false; + } + + var source = inputAction.ActiveSource; + var hand = ""; + if (!inputAction.IsEitherHand) { - Logs.LogWarning($"Failed to find actionInput for virtual key {id}"); - return true; + if (source == SteamVR_Input_Sources.RightHand) hand = "right "; + if (source == SteamVR_Input_Sources.LeftHand) hand = "left "; } - __result = inputAction.Action.GetLocalizedOriginPart(SteamVR_Input_Sources.Any, - EVRInputStringBits.VRInputString_InputSource); + var name = inputAction.Action.GetRenderModelComponentName(inputAction.ActiveSource); + name = name.Replace("button_", ""); + name = name.Replace("thumb", ""); + __result = textInfo.ToTitleCase($"{hand}{name}{inputAction.PromptSuffix}"); return false; } [HarmonyPrefix] [HarmonyPatch(typeof(vgButtonIconMap), nameof(vgButtonIconMap.HasIcon))] - private static bool ReplacePromptIconsWithVrButtonText(ref bool __result, string id) + private static bool CheckHasIconFromVrInputs(ref bool __result, string id) { - __result = StageInstance.GetInputAction(id) != null; + __result = true; return false; } } diff --git a/TwoForksVr/src/VrInput/VirtualKey.cs b/TwoForksVr/src/VrInput/VirtualKey.cs index 8e946a10..5d2019f4 100644 --- a/TwoForksVr/src/VrInput/VirtualKey.cs +++ b/TwoForksVr/src/VrInput/VirtualKey.cs @@ -8,7 +8,6 @@ public struct VirtualKey public const string LocomotionAction = "LocomotionActionButton"; public const string Use = "UseButton"; public const string Jog = "JogButton"; - public const string Camera = "CameraButton"; public const string StoreObject = "StoreObjectButton"; public const string Cancel = "CancelButton"; public const string Pause = "PauseButton"; @@ -18,14 +17,19 @@ public struct VirtualKey public const string LookXAxisStick = "LookXAxis_Stick"; public const string MoveXAxis = "MoveXAxis"; public const string MoveYAxis = "MoveYAxis"; + public const string MoveForwardKeyboard = "MoveForwardKeyboard"; + public const string MoveBackwardKeyboard = "MoveBackwardKeyboard"; + public const string StrafeLeftKeyboard = "StrafeLeftKeyboard"; + public const string StrafeRightKeyboard = "StrafeRightKeyboard"; - // These are unused in VR, since they can be done with gestures + // These are unused in VR, since they can be done with gestures or menus. public const string Zoom = "ZoomButton"; public const string Map = "MapButton"; public const string MapRegion = "MapRegionButton"; public const string Flashlight = "FlashlightButton"; public const string ReadMode = "ReadModeButton"; public const string Inventory = "InventoryButton"; + public const string Camera = "CameraButton"; // These I don't know what they're for. public const string UIRightStickHorizontal = "UIRightStickHorizontal"; @@ -37,14 +41,9 @@ public struct VirtualKey // These are mouse/keyboard only. public const string LookXAxisMouse = "LookXAxis_Mouse"; public const string LookYAxisMouse = "LookYAxis_Mouse"; - public const string MoveForwardKeyboard = "MoveForwardKeyboard"; - public const string MoveBackwardKeyboard = "MoveBackwardKeyboard"; - public const string StrafeLeftKeyboard = "StrafeLeftKeyboard"; - public const string StrafeRightKeyboard = "StrafeRightKeyboard"; // These I just don't need. public const string LookYAxisStick = "LookYAxis_Stick"; - public const string ScrollUpDown = "ScrollUpDown"; public const string ItemsLeftRight = "ItemsLeftRight"; public const string ItemsUpDown = "ItemsUpDown"; public const string QuickSave = "QuickSaveButton"; @@ -68,5 +67,9 @@ public struct VirtualKey public const string PressDemo3 = "PressDemo3"; public const string PressDemo4 = "PressDemo4"; public const string TakeDebugScreenshot = "TakeDebugScreenshot"; + + // These are special cases, virtual keys created specifically for VR, just for the prompts. + public const string ToolPicker = "ToolPickerButton"; + public const string ScrollUpDown = "ScrollUpDown"; } } \ No newline at end of file