mirror of
https://github.com/Raicuparta/nomai-vr.git
synced 2025-12-11 20:15:08 +01:00
Added Snap Turning (#556)
* Added Snap Turning - Disabled by default, can be enabled in settings - Amount per input can be defined in settings (current range is 15 - 90 degrees) - Default input action is the right thumb stick (same as smooth turn) * Moved snap turn from slider to selector for settings * Fixed snap turning with smooth HUD/Helmet - Previously, the smooth HUD/Helmet would uncomfortably move a long distance after you snap turn - Now, if smooth HUD and snap turning are both enabled, the helmet snap turns for a frame, then resumes it's previous behavior * Disable snap turning while in zero-g --------- Co-authored-by: Raicuparta <Raicuparta@users.noreply.github.com>
This commit is contained in:
parent
28a335a38d
commit
aefee463b0
@ -17,6 +17,8 @@ namespace NomaiVR.ModConfig
|
||||
bool PreventClipping { get; }
|
||||
bool FlashlightGesture { get; }
|
||||
bool ControllerOrientedMovement { get; }
|
||||
bool SnapTurning { get; }
|
||||
string SnapTurnIncrement { get; }
|
||||
bool AutoHideToolbelt { get; }
|
||||
float ToolbeltHeight { get; }
|
||||
float HudScale { get; }
|
||||
|
||||
@ -19,6 +19,8 @@ namespace NomaiVR.ModConfig
|
||||
public static bool PreventClipping => settingsProvider.PreventClipping;
|
||||
public static bool FlashlightGesture => settingsProvider.FlashlightGesture;
|
||||
public static bool ControllerOrientedMovement => settingsProvider.ControllerOrientedMovement;
|
||||
public static bool SnapTurning => settingsProvider.SnapTurning;
|
||||
public static string SnapTurnIncrement => settingsProvider.SnapTurnIncrement;
|
||||
public static bool AutoHideToolbelt => settingsProvider.AutoHideToolbelt;
|
||||
public static float ToolbeltHeight => settingsProvider.ToolbeltHeight;
|
||||
public static float HudScale => settingsProvider.HudScale;
|
||||
|
||||
@ -18,6 +18,8 @@ namespace NomaiVR.ModConfig
|
||||
public bool PreventClipping { get; private set; }
|
||||
public bool FlashlightGesture { get; private set; }
|
||||
public bool ControllerOrientedMovement { get; private set; }
|
||||
public bool SnapTurning { get; private set; }
|
||||
public string SnapTurnIncrement { get; private set; }
|
||||
public bool AutoHideToolbelt { get; private set; }
|
||||
public float ToolbeltHeight { get; private set; }
|
||||
public float HudScale { get; private set; }
|
||||
@ -38,6 +40,8 @@ namespace NomaiVR.ModConfig
|
||||
VibrationStrength = config.GetSettingsValue<float>("vibrationIntensity");
|
||||
ShowHelmet = config.GetSettingsValue<bool>("helmetVisibility");
|
||||
ControllerOrientedMovement = config.GetSettingsValue<bool>("movementControllerOriented");
|
||||
SnapTurning = config.GetSettingsValue<bool>("snapTurning");
|
||||
SnapTurnIncrement = config.GetSettingsValue<string>("snapTurnIncrement");
|
||||
EnableGesturePrompts = config.GetSettingsValue<bool>("showGesturePrompts");
|
||||
EnableHandLaser = config.GetSettingsValue<bool>("showHandLaser");
|
||||
EnableFeetMarker = config.GetSettingsValue<bool>("showFeetMarker");
|
||||
|
||||
@ -78,6 +78,25 @@
|
||||
"yes": "Controller",
|
||||
"no": "Head"
|
||||
},
|
||||
"snapTurning": {
|
||||
"type": "toggle",
|
||||
"value": false,
|
||||
"title": "Snap turning",
|
||||
"yes": "Enabled",
|
||||
"no": "Disabled"
|
||||
},
|
||||
"snapTurnIncrement": {
|
||||
"type": "selector",
|
||||
"value": "45",
|
||||
"options": [
|
||||
"15",
|
||||
"30",
|
||||
"45",
|
||||
"60",
|
||||
"90"
|
||||
],
|
||||
"title": "Snap turn increment"
|
||||
},
|
||||
"showGesturePrompts": {
|
||||
"type": "toggle",
|
||||
"value": true,
|
||||
|
||||
@ -14,6 +14,8 @@ namespace NomaiVR.Player
|
||||
|
||||
public class Behaviour : MonoBehaviour
|
||||
{
|
||||
public static Action OnSnapTurn;
|
||||
|
||||
private Transform cameraParent;
|
||||
private static Transform playArea;
|
||||
private static OWCamera playerCamera;
|
||||
@ -22,6 +24,10 @@ namespace NomaiVR.Player
|
||||
private static PlayerCharacterController playerController;
|
||||
private static Autopilot autopilot;
|
||||
private readonly SteamVR_Action_Boolean recenterAction = SteamVR_Actions._default.Recenter;
|
||||
private static readonly SteamVR_Action_Vector2 turnAction = SteamVR_Actions._default.Look;
|
||||
private static readonly float snapTurnInputThreshold = 0.15f;
|
||||
private static bool isSnapTurnInCooldown = false;
|
||||
private float lastTurnTime;
|
||||
|
||||
internal void Start()
|
||||
{
|
||||
@ -95,12 +101,23 @@ namespace NomaiVR.Player
|
||||
}
|
||||
|
||||
UpdateRecenter();
|
||||
|
||||
if (ModSettings.SnapTurning)
|
||||
{
|
||||
// Check if time has passed and input stick was returned to neutral
|
||||
if (isSnapTurnInCooldown && Time.time - lastTurnTime > 0.05f && Mathf.Abs(turnAction.axis.x) < snapTurnInputThreshold)
|
||||
{
|
||||
isSnapTurnInCooldown = false;
|
||||
lastTurnTime = Time.time;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class Patch : NomaiVRPatch
|
||||
{
|
||||
public override void ApplyPatches()
|
||||
{
|
||||
Postfix<OWInput>(nameof(OWInput.GetAxisValue), nameof(PostGetAxisValue));
|
||||
Postfix<PlayerCharacterController>(nameof(PlayerCharacterController.UpdateTurning), nameof(PostCharacterTurning));
|
||||
Postfix<JetpackThrusterController>(nameof(JetpackThrusterController.FixedUpdate), nameof(PostThrusterUpdate));
|
||||
Prefix<OWCamera>("set_" + nameof(OWCamera.fieldOfView), nameof(PatchOwCameraFOV));
|
||||
@ -136,11 +153,25 @@ namespace NomaiVR.Player
|
||||
return;
|
||||
}
|
||||
|
||||
if (ModSettings.SnapTurning && !PlayerState.InZeroG())
|
||||
{
|
||||
float turnInput = turnAction.axis.x;
|
||||
|
||||
// If snap turning, only do the snap turn, skip reorienting the play area
|
||||
if (!isSnapTurnInCooldown && Mathf.Abs(turnInput) > snapTurnInputThreshold)
|
||||
{
|
||||
isSnapTurnInCooldown = true;
|
||||
float sign = Mathf.Sign(turnInput);
|
||||
Quaternion snapRotation = Quaternion.AngleAxis(GetSnapTurnIncrement() * sign, playerBody.transform.up);
|
||||
var fromToSnap = Quaternion.FromToRotation(playerBody.transform.forward, snapRotation * playerBody.transform.forward);
|
||||
|
||||
rotationSetter(fromToSnap * playerBody.transform.rotation);
|
||||
OnSnapTurn?.Invoke();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
var rotationSource = isControllerOriented ? LaserPointer.Behaviour.MovementLaser : playerCamera.transform;
|
||||
|
||||
var fromTo = Quaternion.FromToRotation(playerBody.transform.forward, Vector3.ProjectOnPlane(rotationSource.transform.forward, playerBody.transform.up));
|
||||
|
||||
var magnitude = 0f;
|
||||
if (!isControllerOriented)
|
||||
{
|
||||
@ -154,6 +185,7 @@ namespace NomaiVR.Player
|
||||
}
|
||||
}
|
||||
|
||||
var fromTo = Quaternion.FromToRotation(playerBody.transform.forward, Vector3.ProjectOnPlane(rotationSource.transform.forward, playerBody.transform.up));
|
||||
var targetRotation = fromTo * playerBody.transform.rotation;
|
||||
var inverseRotation = Quaternion.Inverse(fromTo) * playArea.rotation;
|
||||
|
||||
@ -170,6 +202,20 @@ namespace NomaiVR.Player
|
||||
}
|
||||
}
|
||||
|
||||
// Override vanilla input handling for disabling turning while snap turning is enabled
|
||||
private static void PostGetAxisValue(ref Vector2 __result, IInputCommands command, InputMode mask)
|
||||
{
|
||||
if (!ModSettings.SnapTurning || (OWInput.GetInputMode() != InputMode.Character))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (command.CommandType == InputConsts.InputCommandType.LOOK)
|
||||
{
|
||||
__result = Vector2.zero;
|
||||
}
|
||||
}
|
||||
|
||||
private static bool PatchOwCameraFOV(OWCamera __instance)
|
||||
{
|
||||
//Prevents changing the fov of VR cameras
|
||||
@ -183,6 +229,25 @@ namespace NomaiVR.Player
|
||||
if (__instance.mainCamera.stereoEnabled) __result = CameraHelper.GetScaledFieldOfView(__instance.mainCamera);
|
||||
return !__instance.mainCamera.stereoEnabled;
|
||||
}
|
||||
|
||||
private static float GetSnapTurnIncrement()
|
||||
{
|
||||
switch(ModSettings.SnapTurnIncrement)
|
||||
{
|
||||
case "15":
|
||||
return 15f;
|
||||
case "30":
|
||||
return 30f;
|
||||
case "45":
|
||||
return 45f;
|
||||
case "60":
|
||||
return 60f;
|
||||
case "90":
|
||||
return 90f;
|
||||
default:
|
||||
return 45f;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
using NomaiVR.ModConfig;
|
||||
using NomaiVR.Player;
|
||||
using UnityEngine;
|
||||
|
||||
namespace NomaiVR.UI
|
||||
@ -8,19 +9,22 @@ namespace NomaiVR.UI
|
||||
private Quaternion lastFrameRotation;
|
||||
private const float speed = 0.5f;
|
||||
private bool smoothEnabled = true;
|
||||
private bool snapEnabled = false;
|
||||
private bool snapTurnedLastFrame = false;
|
||||
|
||||
private void Start()
|
||||
{
|
||||
lastFrameRotation = transform.rotation;
|
||||
|
||||
SetSmoothEnabled();
|
||||
RefreshEnabledSettings();
|
||||
|
||||
ModSettings.OnConfigChange += SetSmoothEnabled;
|
||||
ModSettings.OnConfigChange += RefreshEnabledSettings;
|
||||
}
|
||||
|
||||
private void OnDestroy()
|
||||
{
|
||||
ModSettings.OnConfigChange -= SetSmoothEnabled;
|
||||
ModSettings.OnConfigChange -= RefreshEnabledSettings;
|
||||
PlayerBodyPosition.Behaviour.OnSnapTurn -= OnSnapTurn;
|
||||
}
|
||||
|
||||
private void LateUpdate()
|
||||
@ -32,23 +36,41 @@ namespace NomaiVR.UI
|
||||
|
||||
var targetRotation = Camera.main.transform.rotation;
|
||||
|
||||
if (smoothEnabled)
|
||||
if (!smoothEnabled)
|
||||
{
|
||||
transform.rotation = targetRotation;
|
||||
}
|
||||
else if (snapEnabled && snapTurnedLastFrame)
|
||||
{
|
||||
snapTurnedLastFrame = false;
|
||||
transform.rotation = targetRotation;
|
||||
}
|
||||
else
|
||||
{
|
||||
var difference = Mathf.Abs(Quaternion.Angle(lastFrameRotation, targetRotation));
|
||||
var step = speed * Time.unscaledDeltaTime * difference * difference;
|
||||
transform.rotation = Quaternion.RotateTowards(lastFrameRotation, targetRotation, step);
|
||||
}
|
||||
else
|
||||
{
|
||||
transform.rotation = targetRotation;
|
||||
}
|
||||
|
||||
lastFrameRotation = transform.rotation;
|
||||
}
|
||||
|
||||
private void SetSmoothEnabled()
|
||||
private void RefreshEnabledSettings()
|
||||
{
|
||||
smoothEnabled = ModSettings.HudSmoothFollow;
|
||||
snapEnabled = ModSettings.SnapTurning;
|
||||
|
||||
PlayerBodyPosition.Behaviour.OnSnapTurn -= OnSnapTurn;
|
||||
|
||||
if (snapEnabled)
|
||||
{
|
||||
PlayerBodyPosition.Behaviour.OnSnapTurn += OnSnapTurn;
|
||||
}
|
||||
}
|
||||
|
||||
private void OnSnapTurn()
|
||||
{
|
||||
snapTurnedLastFrame = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user