NAK_CVR_Mods/.DepricatedMods/DesktopVRIK/IK/IKHandlers/IKHandlerDesktop.cs
2024-01-03 01:47:55 -06:00

126 lines
No EOL
4.4 KiB
C#

using ABI_RC.Core.Player;
using ABI_RC.Systems.IK.SubSystems;
using ABI_RC.Systems.MovementSystem;
using NAK.DesktopVRIK.IK.VRIKHelpers;
using RootMotion.FinalIK;
using UnityEngine;
namespace NAK.DesktopVRIK.IK.IKHandlers;
internal class IKHandlerDesktop : IKHandler
{
public IKHandlerDesktop(VRIK vrik)
{
_vrik = vrik;
_solver = vrik.solver;
}
#region Game Overrides
public override void OnInitializeIk()
{
_vrik.onPreSolverUpdate.AddListener(OnPreSolverUpdateDesktop);
}
#endregion
#region Weight Overrides
public override void UpdateWeights()
{
// Reset avatar local position
_vrik.transform.SetLocalPositionAndRotation(Vector3.zero, Quaternion.identity);
base.UpdateWeights();
}
public override void UpdateTracking()
{
BodySystem.TrackingEnabled = ShouldTrackAll();
BodySystem.TrackingLocomotionEnabled = BodySystem.TrackingEnabled && ShouldTrackLocomotion();
ResetSolverIfNeeded();
}
#endregion
#region VRIK Solver Events
private void OnPreSolverUpdateDesktop()
{
// Reset avatar local position
_vrik.transform.SetLocalPositionAndRotation(Vector3.zero, Quaternion.identity);
_solver.plantFeet = ModSettings.EntryPlantFeet.Value;
// Emulate old VRChat hip movement
if (ModSettings.EntryBodyLeanWeight.Value > 0)
{
float weightedAngle = ModSettings.EntryBodyLeanWeight.Value * (ModSettings.EntryProneThrusting.Value ? 1f: _solver.locomotion.weight);
float angle = IKManager.Instance._desktopCamera.localEulerAngles.x;
angle = angle > 180 ? angle - 360 : angle;
Quaternion rotation = Quaternion.AngleAxis(angle * weightedAngle, _vrik.transform.right);
_solver.spine.headRotationOffset *= rotation;
}
// Make root heading follow within a set limit
if (ModSettings.EntryBodyHeadingLimit.Value > 0)
{
float weightedAngleLimit = ModSettings.EntryBodyHeadingLimit.Value * _solver.locomotion.weight;
float deltaAngleRoot = Mathf.DeltaAngle(IKManager.Instance.transform.eulerAngles.y, _ikSimulatedRootAngle);
float absDeltaAngleRoot = Mathf.Abs(deltaAngleRoot);
if (absDeltaAngleRoot > weightedAngleLimit)
{
deltaAngleRoot = Mathf.Sign(deltaAngleRoot) * weightedAngleLimit;
_ikSimulatedRootAngle = Mathf.MoveTowardsAngle(_ikSimulatedRootAngle, IKManager.Instance.transform.eulerAngles.y, absDeltaAngleRoot - weightedAngleLimit);
}
_solver.spine.rootHeadingOffset = deltaAngleRoot;
if (ModSettings.EntryPelvisHeadingWeight.Value > 0)
{
_solver.spine.pelvisRotationOffset *= Quaternion.Euler(0f, deltaAngleRoot * ModSettings.EntryPelvisHeadingWeight.Value, 0f);
_solver.spine.chestRotationOffset *= Quaternion.Euler(0f, -deltaAngleRoot * ModSettings.EntryPelvisHeadingWeight.Value, 0f);
}
if (ModSettings.EntryChestHeadingWeight.Value > 0)
{
_solver.spine.chestRotationOffset *= Quaternion.Euler(0f, deltaAngleRoot * ModSettings.EntryChestHeadingWeight.Value, 0f);
}
}
}
#endregion
#region Private Methods
private bool ShouldTrackAll()
{
return !PlayerSetup.Instance._emotePlaying;
}
private bool ShouldTrackLocomotion()
{
bool isMoving = MovementSystem.Instance.movementVector.magnitude > 0f;
bool isGrounded = MovementSystem.Instance._isGrounded;
bool isCrouching = MovementSystem.Instance.crouching;
bool isProne = MovementSystem.Instance.prone;
bool isFlying = MovementSystem.Instance.flying;
bool isSitting = MovementSystem.Instance.sitting;
bool isSwimming = MovementSystem.Instance.GetSubmerged();
bool isStanding = PlayerSetup.Instance.avatarUpright >=
Mathf.Max(PlayerSetup.Instance.avatarProneLimit, PlayerSetup.Instance.avatarCrouchLimit);
return !(isMoving || isCrouching || isProne || isFlying || isSwimming || isSitting || !isGrounded || !isStanding);
}
private void ResetSolverIfNeeded()
{
if (_wasTrackingLocomotion == BodySystem.TrackingLocomotionEnabled) return;
_wasTrackingLocomotion = BodySystem.TrackingLocomotionEnabled;
Reset();
}
#endregion
}