mirror of
https://github.com/NotAKidoS/NAK_CVR_Mods.git
synced 2025-09-02 14:29:25 +00:00
rewrite
This commit is contained in:
parent
16e888c64d
commit
cbd65aa813
8 changed files with 635 additions and 539 deletions
|
@ -1,169 +1,149 @@
|
||||||
using ABI.CCK.Components;
|
using ABI_RC.Core.Player;
|
||||||
using ABI_RC.Core.Player;
|
|
||||||
using ABI_RC.Systems.IK;
|
using ABI_RC.Systems.IK;
|
||||||
using ABI_RC.Systems.IK.SubSystems;
|
using ABI_RC.Systems.IK.SubSystems;
|
||||||
using ABI_RC.Systems.MovementSystem;
|
using ABI_RC.Systems.MovementSystem;
|
||||||
using RootMotion.FinalIK;
|
using RootMotion.FinalIK;
|
||||||
|
using System.Reflection;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using UnityEngine.Events;
|
|
||||||
|
|
||||||
namespace NAK.Melons.DesktopVRIK;
|
namespace NAK.Melons.DesktopVRIK;
|
||||||
|
|
||||||
public class DesktopVRIK : MonoBehaviour
|
public class DesktopVRIK : MonoBehaviour
|
||||||
{
|
{
|
||||||
public static DesktopVRIK Instance;
|
public static DesktopVRIK Instance;
|
||||||
|
public DesktopVRIKCalibrator Calibrator;
|
||||||
|
|
||||||
public static bool
|
// DesktopVRIK Settings
|
||||||
Setting_Enabled,
|
public bool
|
||||||
Setting_EnforceViewPosition,
|
Setting_Enabled = true,
|
||||||
Setting_EmoteVRIK,
|
Setting_HipMovement = true,
|
||||||
Setting_EmoteLookAtIK;
|
Setting_ResetOnLand = true,
|
||||||
|
Setting_PlantFeet = true,
|
||||||
|
Setting_EnforceViewPosition;
|
||||||
|
public float
|
||||||
|
Setting_BodyLeanWeight,
|
||||||
|
Setting_BodyHeadingLimit,
|
||||||
|
Setting_PelvisHeadingWeight,
|
||||||
|
Setting_ChestHeadingWeight;
|
||||||
|
|
||||||
public static float
|
// Internal Stuff
|
||||||
Setting_BodyLeanWeight = 0.5f,
|
private float
|
||||||
Setting_BodyAngleLimit = 0f;
|
ik_SimulatedRootAngle;
|
||||||
|
private bool
|
||||||
public Transform viewpoint;
|
ms_lastGrounded,
|
||||||
public Vector3 eyeOffset;
|
ps_emoteIsPlaying;
|
||||||
|
static readonly FieldInfo ms_isGrounded = typeof(MovementSystem).GetField("_isGrounded", BindingFlags.NonPublic | BindingFlags.Instance);
|
||||||
|
|
||||||
void Start()
|
void Start()
|
||||||
{
|
{
|
||||||
|
Calibrator = new DesktopVRIKCalibrator();
|
||||||
Instance = this;
|
Instance = this;
|
||||||
|
DesktopVRIKMod.UpdateAllSettings();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void ChangeViewpointHandling(bool enabled)
|
public void OnSetupAvatarDesktop()
|
||||||
{
|
{
|
||||||
if (Setting_EnforceViewPosition == enabled) return;
|
if (!Setting_Enabled) return;
|
||||||
Setting_EnforceViewPosition = enabled;
|
Calibrator.SetupDesktopVRIK();
|
||||||
if (enabled)
|
ik_SimulatedRootAngle = transform.eulerAngles.y;
|
||||||
{
|
|
||||||
PlayerSetup.Instance.desktopCamera.transform.localPosition = Vector3.zero;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
PlayerSetup.Instance.desktopCamera.transform.localPosition = eyeOffset;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void AlternativeOnPreSolverUpdate()
|
//public void OnReCalibrateAvatar()
|
||||||
|
//{
|
||||||
|
// Calibrator.RecalibrateDesktopVRIK();
|
||||||
|
// ik_SimulatedRootAngle = transform.eulerAngles.y;
|
||||||
|
//}
|
||||||
|
|
||||||
|
public bool OnApplyAvatarScaleToIk(float height)
|
||||||
{
|
{
|
||||||
//this order matters, rotation offset will be choppy if avatar is not cenetered first
|
if (Calibrator.vrik != null)
|
||||||
|
{
|
||||||
DesktopVRIK_Helper.Instance?.OnUpdateVRIK();
|
Calibrator.vrik.solver.locomotion.footDistance = Calibrator.initialFootDistance * height;
|
||||||
|
Calibrator.vrik.solver.locomotion.stepThreshold = Calibrator.initialStepThreshold * height;
|
||||||
//Reset avatar offset (VRIK will literally make you walk away from root otherwise)
|
return true;
|
||||||
IKSystem.vrik.transform.localPosition = Vector3.zero;
|
}
|
||||||
IKSystem.vrik.transform.localRotation = Quaternion.identity;
|
return false;
|
||||||
|
|
||||||
IKSystem.vrik.solver.plantFeet = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public Animator animator;
|
public void OnPlayerSetupUpdate(bool isEmotePlaying)
|
||||||
|
|
||||||
public VRIK AlternativeCalibration(CVRAvatar avatar)
|
|
||||||
{
|
{
|
||||||
animator = avatar.GetComponent<Animator>();
|
bool changed = isEmotePlaying != ps_emoteIsPlaying;
|
||||||
Transform avatarHeadBone = animator.GetBoneTransform(HumanBodyBones.Head);
|
if (changed)
|
||||||
|
|
||||||
//Stuff to make bad armatures work (Fuck you Default Robot Kyle)
|
|
||||||
avatar.transform.localPosition = Vector3.zero;
|
|
||||||
|
|
||||||
//ikpose layer (specified by avatar author)
|
|
||||||
int ikposeLayerIndex = animator.GetLayerIndex("IKPose");
|
|
||||||
int locoLayerIndex = animator.GetLayerIndex("Locomotion/Emotes");
|
|
||||||
if (ikposeLayerIndex != -1)
|
|
||||||
{
|
{
|
||||||
animator.SetLayerWeight(ikposeLayerIndex, 1f);
|
ps_emoteIsPlaying = isEmotePlaying;
|
||||||
if (locoLayerIndex != -1)
|
Calibrator.vrik.transform.localPosition = Vector3.zero;
|
||||||
|
Calibrator.vrik.transform.localRotation = Quaternion.identity;
|
||||||
|
if (Calibrator.lookAtIK != null)
|
||||||
{
|
{
|
||||||
animator.SetLayerWeight(locoLayerIndex, 0f);
|
Calibrator.lookAtIK.enabled = !isEmotePlaying;
|
||||||
}
|
}
|
||||||
animator.Update(0f);
|
BodySystem.TrackingEnabled = !isEmotePlaying;
|
||||||
|
Calibrator.vrik.solver?.Reset();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void OnPreSolverUpdate()
|
||||||
|
{
|
||||||
|
if (ps_emoteIsPlaying) return;
|
||||||
|
|
||||||
|
bool isGrounded = (bool)ms_isGrounded.GetValue(MovementSystem.Instance);
|
||||||
|
|
||||||
|
// Calculate everything that affects weight
|
||||||
|
float weight = Calibrator.vrik.solver.IKPositionWeight;
|
||||||
|
weight *= (1 - MovementSystem.Instance.movementVector.magnitude);
|
||||||
|
weight *= isGrounded ? 1f : 0f;
|
||||||
|
|
||||||
|
// Reset avatar offset (VRIK will literally make you walk away from root otherwise)
|
||||||
|
Calibrator.vrik.transform.localPosition = Vector3.zero;
|
||||||
|
Calibrator.vrik.transform.localRotation = Quaternion.identity;
|
||||||
|
|
||||||
|
// Plant feet is nice for Desktop
|
||||||
|
Calibrator.vrik.solver.plantFeet = Setting_PlantFeet;
|
||||||
|
|
||||||
|
// This is nice for walk cycles
|
||||||
|
//Calibrator.vrik.solver.spine.rotateChestByHands = Setting_RotateChestByHands * weight;
|
||||||
|
|
||||||
|
//reset solver if weight changes dramatically
|
||||||
|
if (Setting_ResetOnLand)
|
||||||
|
{
|
||||||
|
if (isGrounded && !ms_lastGrounded)
|
||||||
|
{
|
||||||
|
Calibrator.vrik.solver.Reset();
|
||||||
|
}
|
||||||
|
ms_lastGrounded = isGrounded;
|
||||||
}
|
}
|
||||||
|
|
||||||
VRIK vrik = avatar.gameObject.AddComponent<VRIK>();
|
// Old VRChat hip movement emulation
|
||||||
vrik.AutoDetectReferences();
|
if (Setting_BodyLeanWeight > 0)
|
||||||
|
|
||||||
//fuck toes
|
|
||||||
vrik.references.leftToes = null;
|
|
||||||
vrik.references.rightToes = null;
|
|
||||||
|
|
||||||
vrik.fixTransforms = true;
|
|
||||||
vrik.solver.plantFeet = false;
|
|
||||||
vrik.solver.locomotion.angleThreshold = 30f;
|
|
||||||
vrik.solver.locomotion.maxLegStretch = 0.75f;
|
|
||||||
vrik.solver.spine.minHeadHeight = -100f;
|
|
||||||
|
|
||||||
vrik.solver.spine.bodyRotStiffness = 0.15f;
|
|
||||||
vrik.solver.spine.headClampWeight = 1f;
|
|
||||||
vrik.solver.spine.maintainPelvisPosition = 1f;
|
|
||||||
vrik.solver.spine.neckStiffness = 0f;
|
|
||||||
|
|
||||||
vrik.solver.locomotion.weight = 0f;
|
|
||||||
vrik.solver.spine.bodyPosStiffness = 0f;
|
|
||||||
vrik.solver.spine.positionWeight = 0f;
|
|
||||||
vrik.solver.spine.pelvisPositionWeight = 0f;
|
|
||||||
vrik.solver.leftArm.positionWeight = 0f;
|
|
||||||
vrik.solver.leftArm.rotationWeight = 0f;
|
|
||||||
vrik.solver.rightArm.positionWeight = 0f;
|
|
||||||
vrik.solver.rightArm.rotationWeight = 0f;
|
|
||||||
vrik.solver.leftLeg.positionWeight = 0f;
|
|
||||||
vrik.solver.leftLeg.rotationWeight = 0f;
|
|
||||||
vrik.solver.rightLeg.positionWeight = 0f;
|
|
||||||
vrik.solver.rightLeg.rotationWeight = 0f;
|
|
||||||
vrik.solver.IKPositionWeight = 0f;
|
|
||||||
|
|
||||||
BodySystem.TrackingLeftArmEnabled = false;
|
|
||||||
BodySystem.TrackingRightArmEnabled = false;
|
|
||||||
BodySystem.TrackingLeftLegEnabled = false;
|
|
||||||
BodySystem.TrackingRightLegEnabled = false;
|
|
||||||
BodySystem.TrackingPositionWeight = 0f;
|
|
||||||
|
|
||||||
//Custom funky AF head ik shit
|
|
||||||
foreach (Transform transform in DesktopVRIK_Helper.Instance.ik_HeadFollower)
|
|
||||||
{
|
{
|
||||||
if (transform.name == "Head IK Target")
|
float weightedAngle = Setting_BodyLeanWeight * weight;
|
||||||
{
|
float angle = PlayerSetup.Instance.desktopCamera.transform.localEulerAngles.x;
|
||||||
Destroy(transform.gameObject);
|
angle = (angle > 180) ? angle - 360 : angle;
|
||||||
}
|
Quaternion rotation = Quaternion.AngleAxis(angle * weightedAngle, IKSystem.Instance.avatar.transform.right);
|
||||||
|
Calibrator.vrik.solver.AddRotationOffset(IKSolverVR.RotationOffset.Head, rotation);
|
||||||
}
|
}
|
||||||
|
|
||||||
DesktopVRIK_Helper.Instance.avatar_HeadBone = avatarHeadBone;
|
// Make root heading follow within a set limit
|
||||||
DesktopVRIK_Helper.Instance.ik_HeadFollower.position = avatarHeadBone.position;
|
if (Setting_BodyHeadingLimit > 0)
|
||||||
DesktopVRIK_Helper.Instance.ik_HeadFollower.rotation = Quaternion.identity;
|
|
||||||
VRIKCalibrator.CalibrateHead(vrik, DesktopVRIK_Helper.Instance.ik_HeadFollower.transform, IKSystem.Instance.headAnchorPositionOffset, IKSystem.Instance.headAnchorRotationOffset);
|
|
||||||
DesktopVRIK_Helper.Instance.ik_HeadFollower.localRotation = Quaternion.identity;
|
|
||||||
|
|
||||||
//force immediate calibration before animator decides to fuck us
|
|
||||||
vrik.solver.SetToReferences(vrik.references);
|
|
||||||
vrik.solver.Initiate(vrik.transform);
|
|
||||||
|
|
||||||
if (ikposeLayerIndex != -1)
|
|
||||||
{
|
{
|
||||||
animator.SetLayerWeight(ikposeLayerIndex, 0f);
|
float weightedAngleLimit = Setting_BodyHeadingLimit * weight;
|
||||||
if (locoLayerIndex != -1)
|
float currentAngle = Mathf.DeltaAngle(transform.eulerAngles.y, ik_SimulatedRootAngle);
|
||||||
|
float angleMaxDelta = Mathf.Abs(currentAngle);
|
||||||
|
if (angleMaxDelta > weightedAngleLimit)
|
||||||
{
|
{
|
||||||
animator.SetLayerWeight(locoLayerIndex, 1f);
|
currentAngle = Mathf.Sign(currentAngle) * weightedAngleLimit;
|
||||||
|
ik_SimulatedRootAngle = Mathf.MoveTowardsAngle(ik_SimulatedRootAngle, transform.eulerAngles.y, angleMaxDelta - weightedAngleLimit);
|
||||||
|
}
|
||||||
|
Calibrator.vrik.solver.spine.rootHeadingOffset = currentAngle;
|
||||||
|
if (Setting_PelvisHeadingWeight > 0)
|
||||||
|
{
|
||||||
|
Calibrator.vrik.solver.AddRotationOffset(IKSolverVR.RotationOffset.Pelvis, new Vector3(0f, currentAngle * Setting_PelvisHeadingWeight, 0f));
|
||||||
|
Calibrator.vrik.solver.AddRotationOffset(IKSolverVR.RotationOffset.Chest, new Vector3(0f, -currentAngle * Setting_PelvisHeadingWeight, 0f));
|
||||||
|
}
|
||||||
|
if (Setting_ChestHeadingWeight > 0)
|
||||||
|
{
|
||||||
|
Calibrator.vrik.solver.AddRotationOffset(IKSolverVR.RotationOffset.Chest, new Vector3(0f, currentAngle * Setting_ChestHeadingWeight, 0f));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//Find eyeoffset
|
|
||||||
eyeOffset = PlayerSetup.Instance.desktopCamera.transform.localPosition;
|
|
||||||
viewpoint = avatarHeadBone.Find("LocalHeadPoint");
|
|
||||||
ChangeViewpointHandling(Setting_EnforceViewPosition);
|
|
||||||
|
|
||||||
//reset ikpose layer
|
|
||||||
if (ikposeLayerIndex != -1)
|
|
||||||
{
|
|
||||||
animator.SetLayerWeight(ikposeLayerIndex, 0f);
|
|
||||||
if (locoLayerIndex != -1)
|
|
||||||
{
|
|
||||||
animator.SetLayerWeight(locoLayerIndex, 1f);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
vrik?.onPreSolverUpdate.AddListener(new UnityAction(this.AlternativeOnPreSolverUpdate));
|
|
||||||
|
|
||||||
DesktopVRIK_Helper.Instance?.OnResetIK();
|
|
||||||
|
|
||||||
return vrik;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -18,9 +18,6 @@
|
||||||
<Reference Include="Assembly-CSharp-firstpass">
|
<Reference Include="Assembly-CSharp-firstpass">
|
||||||
<HintPath>C:\Program Files (x86)\Steam\steamapps\common\ChilloutVR\ChilloutVR_Data\Managed\Assembly-CSharp-firstpass.dll</HintPath>
|
<HintPath>C:\Program Files (x86)\Steam\steamapps\common\ChilloutVR\ChilloutVR_Data\Managed\Assembly-CSharp-firstpass.dll</HintPath>
|
||||||
</Reference>
|
</Reference>
|
||||||
<Reference Include="BTKUILib">
|
|
||||||
<HintPath>C:\Program Files (x86)\Steam\steamapps\common\ChilloutVR\Mods\BTKUILib.dll</HintPath>
|
|
||||||
</Reference>
|
|
||||||
<Reference Include="Cohtml.Runtime">
|
<Reference Include="Cohtml.Runtime">
|
||||||
<HintPath>C:\Program Files (x86)\Steam\steamapps\common\ChilloutVR\ChilloutVR_Data\Managed\Cohtml.Runtime.dll</HintPath>
|
<HintPath>C:\Program Files (x86)\Steam\steamapps\common\ChilloutVR\ChilloutVR_Data\Managed\Cohtml.Runtime.dll</HintPath>
|
||||||
</Reference>
|
</Reference>
|
||||||
|
@ -44,6 +41,10 @@
|
||||||
</Reference>
|
</Reference>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<Folder Include="Integrations\" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
<Target Name="Deploy" AfterTargets="Build">
|
<Target Name="Deploy" AfterTargets="Build">
|
||||||
<Copy SourceFiles="$(TargetPath)" DestinationFolder="C:\Program Files (x86)\Steam\steamapps\common\ChilloutVR\Mods\" />
|
<Copy SourceFiles="$(TargetPath)" DestinationFolder="C:\Program Files (x86)\Steam\steamapps\common\ChilloutVR\Mods\" />
|
||||||
<Message Text="Copied $(TargetPath) to C:\Program Files (x86)\Steam\steamapps\common\ChilloutVR\Mods\" Importance="high" />
|
<Message Text="Copied $(TargetPath) to C:\Program Files (x86)\Steam\steamapps\common\ChilloutVR\Mods\" Importance="high" />
|
||||||
|
|
450
DesktopVRIK/DesktopVRIKCalibrator.cs
Normal file
450
DesktopVRIK/DesktopVRIKCalibrator.cs
Normal file
|
@ -0,0 +1,450 @@
|
||||||
|
using ABI.CCK.Components;
|
||||||
|
using ABI_RC.Core;
|
||||||
|
using ABI_RC.Core.Base;
|
||||||
|
using ABI_RC.Core.Player;
|
||||||
|
using ABI_RC.Systems.IK;
|
||||||
|
using ABI_RC.Systems.IK.SubSystems;
|
||||||
|
using HarmonyLib;
|
||||||
|
using RootMotion.FinalIK;
|
||||||
|
using UnityEngine;
|
||||||
|
using UnityEngine.Events;
|
||||||
|
|
||||||
|
namespace NAK.Melons.DesktopVRIK;
|
||||||
|
|
||||||
|
public class DesktopVRIKCalibrator
|
||||||
|
{
|
||||||
|
public DesktopVRIKCalibrator()
|
||||||
|
{
|
||||||
|
// Get base game scripts.
|
||||||
|
ikSystem = IKSystem.Instance;
|
||||||
|
playerSetup = PlayerSetup.Instance;
|
||||||
|
|
||||||
|
// Get traverse to private shit in iksystem.
|
||||||
|
_vrikTraverse = Traverse.Create(ikSystem).Field("_vrik");
|
||||||
|
_avatarTraverse = Traverse.Create(ikSystem).Field("_avatar");
|
||||||
|
_animatorManagerTraverse = Traverse.Create(ikSystem).Field("_animatorManager");
|
||||||
|
_poseHandlerTraverse = Traverse.Create(ikSystem).Field("_poseHandler");
|
||||||
|
_avatarRootHeightTraverse = Traverse.Create(ikSystem).Field("_avatarRootHeight");
|
||||||
|
|
||||||
|
// Get traverse to private shit in playersetup.
|
||||||
|
_lookIKTraverse = Traverse.Create(playerSetup).Field("lookIK");
|
||||||
|
}
|
||||||
|
|
||||||
|
//Settings
|
||||||
|
public bool Setting_UseVRIKToes = true;
|
||||||
|
public bool Setting_FindUnmappedToes = true;
|
||||||
|
|
||||||
|
//DesktopVRIK
|
||||||
|
public CVRAvatar avatar;
|
||||||
|
public Animator animator;
|
||||||
|
public Transform avatarTransform;
|
||||||
|
public VRIK vrik;
|
||||||
|
public LookAtIK lookAtIK;
|
||||||
|
public HumanPoseHandler humanPoseHandler;
|
||||||
|
public HumanPose initialHumanPose;
|
||||||
|
public bool fixTransformsRequired;
|
||||||
|
public float initialFootDistance;
|
||||||
|
public float initialStepThreshold;
|
||||||
|
|
||||||
|
//Traverse
|
||||||
|
private IKSystem ikSystem;
|
||||||
|
private PlayerSetup playerSetup;
|
||||||
|
private Traverse _vrikTraverse;
|
||||||
|
private Traverse _lookIKTraverse;
|
||||||
|
private Traverse _avatarTraverse;
|
||||||
|
private Traverse _animatorManagerTraverse;
|
||||||
|
private Traverse _poseHandlerTraverse;
|
||||||
|
private Traverse _avatarRootHeightTraverse;
|
||||||
|
|
||||||
|
//public void RecalibrateDesktopVRIK()
|
||||||
|
//{
|
||||||
|
// if (avatar != null)
|
||||||
|
// {
|
||||||
|
// //calibrate VRIK
|
||||||
|
// CalibrateDesktopVRIK();
|
||||||
|
// }
|
||||||
|
// else
|
||||||
|
// {
|
||||||
|
// //we never calibrated
|
||||||
|
// SetupDesktopVRIK();
|
||||||
|
// }
|
||||||
|
//}
|
||||||
|
|
||||||
|
public void SetupDesktopVRIK()
|
||||||
|
{
|
||||||
|
//store avatar root transform & center it
|
||||||
|
avatar = playerSetup._avatar.GetComponent<CVRAvatar>();
|
||||||
|
animator = avatar.GetComponent<Animator>();
|
||||||
|
avatarTransform = avatar.transform;
|
||||||
|
avatarTransform.localPosition = Vector3.zero;
|
||||||
|
lookAtIK = _lookIKTraverse.GetValue<LookAtIK>();
|
||||||
|
|
||||||
|
//prepare for VRIK
|
||||||
|
PrepareIKSystem();
|
||||||
|
CalibrateDesktopVRIK();
|
||||||
|
|
||||||
|
//add presolver update listener
|
||||||
|
vrik.onPreSolverUpdate.AddListener(new UnityAction(DesktopVRIK.Instance.OnPreSolverUpdate));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void CalibrateDesktopVRIK()
|
||||||
|
{
|
||||||
|
//calibrate VRIK
|
||||||
|
PrepareAvatarVRIK();
|
||||||
|
SetAvatarIKPose(true);
|
||||||
|
CalculateInitialIKScaling();
|
||||||
|
CalibrateHeadIK();
|
||||||
|
ForceInitiateVRIKSolver();
|
||||||
|
SetAvatarIKPose(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void PrepareIKSystem()
|
||||||
|
{
|
||||||
|
// Get the animator manager and human pose handler
|
||||||
|
var animatorManager = _animatorManagerTraverse.GetValue<CVRAnimatorManager>();
|
||||||
|
humanPoseHandler = _poseHandlerTraverse.GetValue<HumanPoseHandler>();
|
||||||
|
|
||||||
|
// Store the avatar component
|
||||||
|
_avatarTraverse.SetValue(avatar);
|
||||||
|
|
||||||
|
// Set the animator for the IK system
|
||||||
|
ikSystem.animator = animator;
|
||||||
|
if (ikSystem.animator != null)
|
||||||
|
{
|
||||||
|
animatorManager.SetAnimator(ikSystem.animator, ikSystem.animator.runtimeAnimatorController);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set the avatar height float
|
||||||
|
float avatarHeight = ikSystem.vrPlaySpace.transform.InverseTransformPoint(avatarTransform.position).y;
|
||||||
|
_avatarRootHeightTraverse.SetValue(avatarHeight);
|
||||||
|
|
||||||
|
// Create a new human pose handler and dispose the old one
|
||||||
|
if (humanPoseHandler != null)
|
||||||
|
{
|
||||||
|
humanPoseHandler.Dispose();
|
||||||
|
_poseHandlerTraverse.SetValue(null);
|
||||||
|
}
|
||||||
|
humanPoseHandler = new HumanPoseHandler(ikSystem.animator.avatar, avatarTransform);
|
||||||
|
_poseHandlerTraverse.SetValue(humanPoseHandler);
|
||||||
|
|
||||||
|
// Find valid human bones
|
||||||
|
IKSystem.BoneExists.Clear();
|
||||||
|
foreach (HumanBodyBones bone in Enum.GetValues(typeof(HumanBodyBones)))
|
||||||
|
{
|
||||||
|
if (bone != HumanBodyBones.LastBone)
|
||||||
|
{
|
||||||
|
IKSystem.BoneExists.Add(bone, ikSystem.animator.GetBoneTransform(bone) != null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Prepare BodySystem for calibration
|
||||||
|
BodySystem.TrackingLeftArmEnabled = false;
|
||||||
|
BodySystem.TrackingRightArmEnabled = false;
|
||||||
|
BodySystem.TrackingLeftLegEnabled = false;
|
||||||
|
BodySystem.TrackingRightLegEnabled = false;
|
||||||
|
BodySystem.TrackingPositionWeight = 0f;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void PrepareAvatarVRIK()
|
||||||
|
{
|
||||||
|
//add and configure VRIK
|
||||||
|
vrik = avatar.gameObject.AddComponentIfMissing<VRIK>();
|
||||||
|
vrik.AutoDetectReferences();
|
||||||
|
ConfigureVRIKReferences();
|
||||||
|
_vrikTraverse.SetValue(vrik);
|
||||||
|
|
||||||
|
//in testing, not really needed
|
||||||
|
//only required if Setting_FindUnmappedToes
|
||||||
|
//and non-human mapped toes are found
|
||||||
|
vrik.fixTransforms = fixTransformsRequired;
|
||||||
|
|
||||||
|
//default solver settings
|
||||||
|
vrik.solver.locomotion.weight = 0f;
|
||||||
|
vrik.solver.locomotion.angleThreshold = 30f;
|
||||||
|
vrik.solver.locomotion.maxLegStretch = 0.75f;
|
||||||
|
vrik.solver.spine.minHeadHeight = 0f;
|
||||||
|
vrik.solver.IKPositionWeight = 1f;
|
||||||
|
//disable to not bleed into anims
|
||||||
|
vrik.solver.spine.chestClampWeight = 0f;
|
||||||
|
vrik.solver.spine.maintainPelvisPosition = 0f;
|
||||||
|
//for body leaning
|
||||||
|
vrik.solver.spine.neckStiffness = 0.0001f; //cannot be 0
|
||||||
|
vrik.solver.spine.bodyPosStiffness = 1f;
|
||||||
|
vrik.solver.spine.bodyRotStiffness = 0.2f;
|
||||||
|
//disable so avatar doesnt try and walk away
|
||||||
|
//fixes nameplate spazzing on remote
|
||||||
|
vrik.solver.locomotion.velocityFactor = 0f;
|
||||||
|
vrik.solver.locomotion.maxVelocity = 0f;
|
||||||
|
//disable so PAM & BID dont make body shake
|
||||||
|
vrik.solver.spine.rotateChestByHands = 0f;
|
||||||
|
//enable so knees on fucked models work better
|
||||||
|
vrik.solver.leftLeg.useAnimatedBendNormal = true;
|
||||||
|
vrik.solver.rightLeg.useAnimatedBendNormal = true;
|
||||||
|
//enable to prioritize LookAtIK
|
||||||
|
vrik.solver.spine.headClampWeight = 0.2f;
|
||||||
|
//disable to not go on tippytoes
|
||||||
|
vrik.solver.spine.positionWeight = 0f;
|
||||||
|
vrik.solver.spine.rotationWeight = 1f;
|
||||||
|
|
||||||
|
//vrik.solver.spine.maintainPelvisPosition = 1f;
|
||||||
|
//vrik.solver.locomotion.weight = 0f;
|
||||||
|
//vrik.solver.spine.positionWeight = 0f;
|
||||||
|
//vrik.solver.spine.pelvisPositionWeight = 0f;
|
||||||
|
//vrik.solver.leftArm.positionWeight = 0f;
|
||||||
|
//vrik.solver.leftArm.rotationWeight = 0f;
|
||||||
|
//vrik.solver.rightArm.positionWeight = 0f;
|
||||||
|
//vrik.solver.rightArm.rotationWeight = 0f;
|
||||||
|
//vrik.solver.leftLeg.positionWeight = 0f;
|
||||||
|
//vrik.solver.leftLeg.rotationWeight = 0f;
|
||||||
|
//vrik.solver.rightLeg.positionWeight = 0f;
|
||||||
|
//vrik.solver.rightLeg.rotationWeight = 0f;
|
||||||
|
//vrik.solver.IKPositionWeight = 0f;
|
||||||
|
|
||||||
|
//THESE ARE CONFIGURABLE IN GAME IK SETTINGS
|
||||||
|
//vrik.solver.leftLeg.target = null;
|
||||||
|
//vrik.solver.leftLeg.bendGoal = null;
|
||||||
|
//vrik.solver.leftLeg.positionWeight = 0f;
|
||||||
|
//vrik.solver.leftLeg.bendGoalWeight = 0f;
|
||||||
|
//vrik.solver.rightLeg.target = null;
|
||||||
|
//vrik.solver.rightLeg.bendGoal = null;
|
||||||
|
//vrik.solver.rightLeg.positionWeight = 0f;
|
||||||
|
//vrik.solver.rightLeg.bendGoalWeight = 0f;
|
||||||
|
//vrik.solver.spine.pelvisTarget = null;
|
||||||
|
//vrik.solver.spine.chestGoal = null;
|
||||||
|
//vrik.solver.spine.positionWeight = 0f;
|
||||||
|
//vrik.solver.spine.rotationWeight = 0f;
|
||||||
|
//vrik.solver.spine.pelvisPositionWeight = 0f;
|
||||||
|
//vrik.solver.spine.pelvisRotationWeight = 0f;
|
||||||
|
//vrik.solver.spine.chestGoalWeight = 0f;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void CalculateInitialIKScaling()
|
||||||
|
{
|
||||||
|
// Get distance between feets and thighs (fixes some weird armatures)
|
||||||
|
float footDistance = Vector3.Distance(vrik.references.leftFoot.position, vrik.references.rightFoot.position);
|
||||||
|
float thighDistance = Vector3.Distance(vrik.references.leftThigh.position, vrik.references.rightThigh.position);
|
||||||
|
float greatestDistance = Mathf.Min(footDistance, thighDistance);
|
||||||
|
initialFootDistance = greatestDistance * 0.5f;
|
||||||
|
initialStepThreshold = greatestDistance * 0.4f;
|
||||||
|
|
||||||
|
//set initial values now, as avatars without scaling dont apply it
|
||||||
|
vrik.solver.locomotion.footDistance = initialFootDistance;
|
||||||
|
vrik.solver.locomotion.stepThreshold = initialStepThreshold;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void CalibrateHeadIK()
|
||||||
|
{
|
||||||
|
// Lazy HeadIKTarget calibration
|
||||||
|
if (vrik.solver.spine.headTarget == null)
|
||||||
|
{
|
||||||
|
vrik.solver.spine.headTarget = new GameObject("Head IK Target").transform;
|
||||||
|
}
|
||||||
|
vrik.solver.spine.headTarget.parent = vrik.references.head;
|
||||||
|
vrik.solver.spine.headTarget.localPosition = Vector3.zero;
|
||||||
|
vrik.solver.spine.headTarget.localRotation = Quaternion.identity;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void SetAvatarIKPose(bool enforceTPose)
|
||||||
|
{
|
||||||
|
int ikposeLayerIndex = animator.GetLayerIndex("IKPose");
|
||||||
|
int locoLayerIndex = animator.GetLayerIndex("Locomotion/Emotes");
|
||||||
|
|
||||||
|
// Use custom IKPose if found.
|
||||||
|
if (ikposeLayerIndex != -1 && locoLayerIndex != -1)
|
||||||
|
{
|
||||||
|
animator.SetLayerWeight(ikposeLayerIndex, enforceTPose ? 1f : 0f);
|
||||||
|
animator.SetLayerWeight(locoLayerIndex, enforceTPose ? 0f : 1f);
|
||||||
|
animator.Update(0f);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Otherwise use DesktopVRIK IKPose & revert afterwards.
|
||||||
|
if (enforceTPose)
|
||||||
|
{
|
||||||
|
humanPoseHandler.GetHumanPose(ref initialHumanPose);
|
||||||
|
humanPoseHandler.GetHumanPose(ref ikSystem.humanPose);
|
||||||
|
for (int i = 0; i < IKPoseMuscles.Length; i++)
|
||||||
|
{
|
||||||
|
IKSystem.Instance.ApplyMuscleValue((MuscleIndex)i, IKPoseMuscles[i], ref ikSystem.humanPose.muscles);
|
||||||
|
}
|
||||||
|
humanPoseHandler.SetHumanPose(ref ikSystem.humanPose);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
humanPoseHandler.SetHumanPose(ref initialHumanPose);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ForceInitiateVRIKSolver()
|
||||||
|
{
|
||||||
|
//force immediate calibration before animator decides to fuck us
|
||||||
|
vrik.solver.SetToReferences(vrik.references);
|
||||||
|
vrik.solver.Initiate(vrik.transform);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ConfigureVRIKReferences()
|
||||||
|
{
|
||||||
|
fixTransformsRequired = false;
|
||||||
|
|
||||||
|
Transform leftShoulderBone = vrik.references.leftShoulder;
|
||||||
|
Transform rightShoulderBone = vrik.references.rightShoulder;
|
||||||
|
Transform assumedChest = leftShoulderBone?.parent;
|
||||||
|
|
||||||
|
// Repair chest & spine bone references (valve models were messed up)
|
||||||
|
if (assumedChest != null && rightShoulderBone.parent == assumedChest &&
|
||||||
|
vrik.references.chest != assumedChest)
|
||||||
|
{
|
||||||
|
vrik.references.chest = assumedChest;
|
||||||
|
vrik.references.spine = assumedChest.parent;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!Setting_UseVRIKToes)
|
||||||
|
{
|
||||||
|
vrik.references.leftToes = null;
|
||||||
|
vrik.references.rightToes = null;
|
||||||
|
}
|
||||||
|
else if (Setting_FindUnmappedToes)
|
||||||
|
{
|
||||||
|
Transform leftToes = vrik.references.leftToes;
|
||||||
|
Transform rightToes = vrik.references.rightToes;
|
||||||
|
if (leftToes == null && rightToes == null)
|
||||||
|
{
|
||||||
|
leftToes = FindUnmappedToe(vrik.references.leftFoot);
|
||||||
|
rightToes = FindUnmappedToe(vrik.references.rightFoot);
|
||||||
|
if (leftToes != null && rightToes != null)
|
||||||
|
{
|
||||||
|
fixTransformsRequired = true;
|
||||||
|
vrik.references.leftToes = leftToes;
|
||||||
|
vrik.references.rightToes = rightToes;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fix error when there is no finger bones
|
||||||
|
// Making up bullshit cause VRIK is evil otherwise
|
||||||
|
if (vrik.references.leftHand.childCount == 0)
|
||||||
|
{
|
||||||
|
vrik.solver.leftArm.wristToPalmAxis = Vector3.up;
|
||||||
|
vrik.solver.leftArm.palmToThumbAxis = -Vector3.forward;
|
||||||
|
}
|
||||||
|
if (vrik.references.rightHand.childCount == 0)
|
||||||
|
{
|
||||||
|
vrik.solver.rightArm.wristToPalmAxis = Vector3.up;
|
||||||
|
vrik.solver.rightArm.palmToThumbAxis = Vector3.forward;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private Transform FindUnmappedToe(Transform foot)
|
||||||
|
{
|
||||||
|
foreach (Transform bone in foot)
|
||||||
|
{
|
||||||
|
if (bone.name.ToLowerInvariant().Contains("toe") ||
|
||||||
|
bone.name.ToLowerInvariant().EndsWith("_end"))
|
||||||
|
{
|
||||||
|
return bone;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static readonly float[] IKPoseMuscles = new float[]
|
||||||
|
{
|
||||||
|
0.00133321f,
|
||||||
|
8.195831E-06f,
|
||||||
|
8.537738E-07f,
|
||||||
|
-0.002669832f,
|
||||||
|
-7.651234E-06f,
|
||||||
|
-0.001659694f,
|
||||||
|
0f,
|
||||||
|
0f,
|
||||||
|
0f,
|
||||||
|
0.04213953f,
|
||||||
|
0.0003007996f,
|
||||||
|
-0.008032114f,
|
||||||
|
-0.03059979f,
|
||||||
|
-0.0003182998f,
|
||||||
|
0.009640567f,
|
||||||
|
0f,
|
||||||
|
0f,
|
||||||
|
0f,
|
||||||
|
0f,
|
||||||
|
0f,
|
||||||
|
0f,
|
||||||
|
0.5768794f,
|
||||||
|
0.01061097f,
|
||||||
|
-0.1127839f,
|
||||||
|
0.9705755f,
|
||||||
|
0.07972051f,
|
||||||
|
-0.0268422f,
|
||||||
|
0.007237188f,
|
||||||
|
0f,
|
||||||
|
0.5768792f,
|
||||||
|
0.01056608f,
|
||||||
|
-0.1127519f,
|
||||||
|
0.9705756f,
|
||||||
|
0.07971933f,
|
||||||
|
-0.02682396f,
|
||||||
|
0.007229362f,
|
||||||
|
0f,
|
||||||
|
-5.651802E-06f,
|
||||||
|
-3.034899E-07f,
|
||||||
|
0.4100508f,
|
||||||
|
0.3610304f,
|
||||||
|
-0.0838329f,
|
||||||
|
0.9262537f,
|
||||||
|
0.1353517f,
|
||||||
|
-0.03578902f,
|
||||||
|
0.06005657f,
|
||||||
|
-4.95989E-06f,
|
||||||
|
-1.43007E-06f,
|
||||||
|
0.4096187f,
|
||||||
|
0.363263f,
|
||||||
|
-0.08205152f,
|
||||||
|
0.9250782f,
|
||||||
|
0.1345718f,
|
||||||
|
-0.03572125f,
|
||||||
|
0.06055461f,
|
||||||
|
-1.079177f,
|
||||||
|
0.2095419f,
|
||||||
|
0.6140652f,
|
||||||
|
0.6365265f,
|
||||||
|
0.6683931f,
|
||||||
|
-0.4764312f,
|
||||||
|
0.8099416f,
|
||||||
|
0.8099371f,
|
||||||
|
0.6658203f,
|
||||||
|
-0.7327053f,
|
||||||
|
0.8113618f,
|
||||||
|
0.8114051f,
|
||||||
|
0.6643661f,
|
||||||
|
-0.40341f,
|
||||||
|
0.8111364f,
|
||||||
|
0.8111367f,
|
||||||
|
0.6170399f,
|
||||||
|
-0.2524227f,
|
||||||
|
0.8138723f,
|
||||||
|
0.8110135f,
|
||||||
|
-1.079171f,
|
||||||
|
0.2095456f,
|
||||||
|
0.6140658f,
|
||||||
|
0.6365255f,
|
||||||
|
0.6683878f,
|
||||||
|
-0.4764301f,
|
||||||
|
0.8099402f,
|
||||||
|
0.8099376f,
|
||||||
|
0.6658241f,
|
||||||
|
-0.7327023f,
|
||||||
|
0.8113653f,
|
||||||
|
0.8113793f,
|
||||||
|
0.664364f,
|
||||||
|
-0.4034042f,
|
||||||
|
0.811136f,
|
||||||
|
0.8111364f,
|
||||||
|
0.6170469f,
|
||||||
|
-0.2524345f,
|
||||||
|
0.8138595f,
|
||||||
|
0.8110138f
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
|
@ -1,108 +0,0 @@
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using UnityEngine;
|
|
||||||
using ABI_RC.Core.Player;
|
|
||||||
using ABI_RC.Systems.IK;
|
|
||||||
using ABI_RC.Systems.IK.SubSystems;
|
|
||||||
using ABI_RC.Systems.MovementSystem;
|
|
||||||
using RootMotion.FinalIK;
|
|
||||||
|
|
||||||
namespace NAK.Melons.DesktopVRIK;
|
|
||||||
|
|
||||||
internal class DesktopVRIK_Helper : MonoBehaviour
|
|
||||||
{
|
|
||||||
public static DesktopVRIK_Helper Instance;
|
|
||||||
|
|
||||||
//Avatar
|
|
||||||
public Transform avatar_HeadBone;
|
|
||||||
|
|
||||||
//DesktopVRIK
|
|
||||||
public Transform ik_HeadFollower;
|
|
||||||
public Quaternion ik_HeadRotation;
|
|
||||||
|
|
||||||
public static void CreateInstance()
|
|
||||||
{
|
|
||||||
Transform helper = new GameObject("[DesktopVRIK] Virtual Rig").transform;
|
|
||||||
helper.parent = PlayerSetup.Instance.transform;
|
|
||||||
helper.localPosition = Vector3.zero;
|
|
||||||
helper.localRotation = Quaternion.identity;
|
|
||||||
helper.gameObject.AddComponent<DesktopVRIK_Helper>();
|
|
||||||
}
|
|
||||||
|
|
||||||
void Start()
|
|
||||||
{
|
|
||||||
Instance = this;
|
|
||||||
|
|
||||||
Transform headFollower = new GameObject("HeadBone_Follower").transform;
|
|
||||||
headFollower.parent = transform;
|
|
||||||
headFollower.localPosition = new Vector3(0f, 1.8f, 0f);
|
|
||||||
headFollower.localRotation = Quaternion.identity;
|
|
||||||
ik_HeadFollower = headFollower;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void OnUpdateVRIK()
|
|
||||||
{
|
|
||||||
if (avatar_HeadBone != null)
|
|
||||||
{
|
|
||||||
float globalWeight = (1 - MovementSystem.Instance.movementVector.magnitude);
|
|
||||||
globalWeight *= IKSystem.vrik.solver.locomotion.weight;
|
|
||||||
|
|
||||||
//the most important thing ever
|
|
||||||
//IKSystem.vrik.solver.spine.rotationWeight = globalWeight;
|
|
||||||
|
|
||||||
HeadIK_FollowPosition();
|
|
||||||
|
|
||||||
HeadIK_RotateWithWeight(globalWeight);
|
|
||||||
HeadIK_FollowWithinAngle(globalWeight);
|
|
||||||
ik_HeadFollower.rotation = ik_HeadRotation;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void OnResetIK()
|
|
||||||
{
|
|
||||||
ik_HeadRotation = Quaternion.Euler(transform.eulerAngles.x, transform.eulerAngles.y, transform.eulerAngles.z);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void HeadIK_FollowPosition()
|
|
||||||
{
|
|
||||||
ik_HeadFollower.position = new Vector3(transform.position.x, avatar_HeadBone.position.y, transform.position.z);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void HeadIK_FollowWithinAngle(float weight)
|
|
||||||
{
|
|
||||||
if (DesktopVRIK.Setting_BodyAngleLimit != 0)
|
|
||||||
{
|
|
||||||
float weightedAngle = DesktopVRIK.Setting_BodyAngleLimit * weight;
|
|
||||||
float currentAngle = Mathf.DeltaAngle(transform.eulerAngles.y, ik_HeadRotation.eulerAngles.y);
|
|
||||||
if (Mathf.Abs(currentAngle) > weightedAngle)
|
|
||||||
{
|
|
||||||
float fixedCurrentAngle = currentAngle > 0 ? currentAngle : -currentAngle;
|
|
||||||
float clampedAngle = Mathf.MoveTowardsAngle(ik_HeadRotation.eulerAngles.y, transform.eulerAngles.y, fixedCurrentAngle - weightedAngle);
|
|
||||||
ik_HeadRotation = Quaternion.Euler(ik_HeadRotation.eulerAngles.x, clampedAngle, 0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
ik_HeadRotation = Quaternion.Euler(ik_HeadRotation.eulerAngles.x, transform.eulerAngles.y, transform.eulerAngles.z);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void HeadIK_RotateWithWeight(float weight)
|
|
||||||
{
|
|
||||||
//VRChat hip movement emulation
|
|
||||||
if (DesktopVRIK.Setting_BodyLeanWeight != 0)
|
|
||||||
{
|
|
||||||
float angle = PlayerSetup.Instance.desktopCamera.transform.localEulerAngles.x;
|
|
||||||
if (angle > 180) angle -= 360;
|
|
||||||
float leanAmount = angle * weight * DesktopVRIK.Setting_BodyLeanWeight;
|
|
||||||
ik_HeadRotation = Quaternion.Euler(leanAmount * 0.33f, ik_HeadRotation.eulerAngles.y, 0);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
ik_HeadRotation = Quaternion.Euler(transform.eulerAngles.x, ik_HeadRotation.eulerAngles.y, transform.eulerAngles.z);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,34 +1,21 @@
|
||||||
using ABI.CCK.Components;
|
using ABI_RC.Core.Player;
|
||||||
using ABI_RC.Core.Player;
|
|
||||||
using ABI_RC.Core.Savior;
|
|
||||||
using ABI_RC.Systems.IK;
|
using ABI_RC.Systems.IK;
|
||||||
using ABI_RC.Systems.IK.SubSystems;
|
|
||||||
using ABI_RC.Systems.MovementSystem;
|
|
||||||
using HarmonyLib;
|
using HarmonyLib;
|
||||||
using RootMotion.FinalIK;
|
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
||||||
The process of calibrating VRIK is fucking painful.
|
The process of calibrating VRIK is fucking painful.
|
||||||
|
|
||||||
Immediatly doing GetHumanPose() and then SetHumanPose() fixed heels in ground for all avatars.
|
|
||||||
|
|
||||||
Setting the avatars rotation to identity, head rotation offset to head bone world rotation, and then calibrating head IK target (kinda) fixed only robot kyle.
|
|
||||||
|
|
||||||
Enforcing a TPose only fixed my ferret avatars right shoulder.
|
|
||||||
|
|
||||||
Mix and matching these, and changing order, fucks with random specific avatars with fucky armatures.
|
|
||||||
MOST AVATARS DONT EVEN CHANGE, ITS JUST THESE FEW SPECIFIC ONES
|
|
||||||
I NEED to look into an IKPose controller...
|
|
||||||
|
|
||||||
Avatars of Note:
|
Avatars of Note:
|
||||||
TurtleNeck Ferret- broken/inverted right shoulder
|
TurtleNeck Ferret- close feet, far shoulders, nonideal rig.
|
||||||
Space Robot Kyle- head ik target is rotated -90 90 0, so body/neck is fucked (Fuck you Default Robot Kyle)
|
Space Robot Kyle- the worst bone rolls on the planet, tpose/headikcalibration fixed it mostly... ish.
|
||||||
Exteratta- the knees bend backwards like a fucking chicken... what the fuck im enforcing a tpose nowww
|
Exteratta- knees bend backwards without proper tpose.
|
||||||
|
Chito- left foot is far back without proper tpose & foot ik distance, was uploaded in falling anim state.
|
||||||
|
Atlas (portal2)- Wide stance, proper feet distance needed to be calculated.
|
||||||
|
Freddy (gmod)- Doesn't have any fingers, wristToPalmAxis & palmToThumbAxis needed to be set manually.
|
||||||
|
|
||||||
Most other avatars play just fine. Never changes even when adding Tpose, rotating the avatar, headikrotationoffset, ect...
|
Most other avatars play just fine.
|
||||||
WHY (Fuck you Default Robot Kyle)
|
|
||||||
|
|
||||||
**/
|
**/
|
||||||
|
|
||||||
|
@ -36,210 +23,44 @@ namespace NAK.Melons.DesktopVRIK.HarmonyPatches;
|
||||||
|
|
||||||
class PlayerSetupPatches
|
class PlayerSetupPatches
|
||||||
{
|
{
|
||||||
private static bool emotePlayed = false;
|
|
||||||
|
|
||||||
[HarmonyPostfix]
|
[HarmonyPostfix]
|
||||||
[HarmonyPatch(typeof(PlayerSetup), "SetupAvatarGeneral")]
|
[HarmonyPatch(typeof(PlayerSetup), "SetupAvatarDesktop")]
|
||||||
static void SetupDesktopIKSystem(ref CVRAvatar ____avatarDescriptor, ref Animator ____animator)
|
static void Postfix_PlayerSetup_SetupAvatarDesktop(ref Animator ____animator)
|
||||||
{
|
{
|
||||||
if (!MetaPort.Instance.isUsingVr && DesktopVRIK.Setting_Enabled)
|
if (____animator != null && ____animator.avatar != null && ____animator.avatar.isHuman)
|
||||||
{
|
{
|
||||||
if (____avatarDescriptor != null && ____animator != null && ____animator.isHuman)
|
DesktopVRIK.Instance?.OnSetupAvatarDesktop();
|
||||||
{
|
|
||||||
//this will stop at the useless isVr return (the function is only ever called by vr anyways...)
|
|
||||||
IKSystem.Instance.InitializeAvatar(____avatarDescriptor);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[HarmonyPostfix]
|
[HarmonyPostfix]
|
||||||
[HarmonyPatch(typeof(PlayerSetup), "Update")]
|
[HarmonyPatch(typeof(PlayerSetup), "Update")]
|
||||||
private static void CorrectVRIK(ref bool ____emotePlaying, ref LookAtIK ___lookIK)
|
static void Postfix_PlayerSetup_Update(ref bool ____emotePlaying)
|
||||||
{
|
{
|
||||||
if (!MetaPort.Instance.isUsingVr && DesktopVRIK.Setting_Enabled)
|
DesktopVRIK.Instance?.OnPlayerSetupUpdate(____emotePlaying);
|
||||||
{
|
|
||||||
bool changed = ____emotePlaying != emotePlayed;
|
|
||||||
if (changed)
|
|
||||||
{
|
|
||||||
emotePlayed = ____emotePlaying;
|
|
||||||
IKSystem.vrik.transform.localPosition = Vector3.zero;
|
|
||||||
IKSystem.vrik.transform.localRotation = Quaternion.identity;
|
|
||||||
if (DesktopVRIK.Setting_EmoteLookAtIK && ___lookIK != null)
|
|
||||||
{
|
|
||||||
___lookIK.enabled = !____emotePlaying;
|
|
||||||
}
|
|
||||||
if (DesktopVRIK.Setting_EmoteVRIK)
|
|
||||||
{
|
|
||||||
BodySystem.TrackingEnabled = !____emotePlaying;
|
|
||||||
IKSystem.vrik.solver?.Reset();
|
|
||||||
DesktopVRIK_Helper.Instance?.OnResetIK();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//[HarmonyPostfix]
|
||||||
//should probably patch movement system instead
|
//[HarmonyPatch(typeof(PlayerSetup), "ReCalibrateAvatar")]
|
||||||
[HarmonyPrefix]
|
//static void Postfix_PlayerSetup_ReCalibrateAvatar()
|
||||||
[HarmonyPatch(typeof(PlayerSetup), "HandleDesktopCameraPosition")]
|
//{
|
||||||
private static void Prefix_PlayerSetup_HandleDesktopCameraPosition
|
// DesktopVRIK.Instance?.OnReCalibrateAvatar();
|
||||||
(
|
//}
|
||||||
bool ignore,
|
|
||||||
ref PlayerSetup __instance,
|
|
||||||
ref MovementSystem
|
|
||||||
____movementSystem,
|
|
||||||
ref int ___headBobbingLevel
|
|
||||||
)
|
|
||||||
{
|
|
||||||
if (___headBobbingLevel != 2)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!DesktopVRIK.Setting_Enabled || !DesktopVRIK.Setting_EnforceViewPosition)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (____movementSystem.disableCameraControl && !ignore)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (DesktopVRIK.Instance.viewpoint == null)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
__instance.desktopCamera.transform.position = DesktopVRIK.Instance.viewpoint.position;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class IKSystemPatches
|
class IKSystemPatches
|
||||||
{
|
{
|
||||||
[HarmonyPostfix]
|
[HarmonyPostfix]
|
||||||
[HarmonyPatch(typeof(IKSystem), "InitializeAvatar")]
|
[HarmonyPatch(typeof(IKSystem), "Start")]
|
||||||
private static void InitializeDesktopAvatarVRIK(CVRAvatar avatar, ref VRIK ____vrik, ref HumanPoseHandler ____poseHandler, ref HumanPose ___humanPose)
|
private static void Postfix_IKSystem_Start(ref IKSystem __instance)
|
||||||
{
|
{
|
||||||
if (!MetaPort.Instance.isUsingVr && DesktopVRIK.Setting_Enabled)
|
__instance.gameObject.AddComponent<DesktopVRIK>();
|
||||||
{
|
|
||||||
if (IKSystem.Instance.animator != null && IKSystem.Instance.animator.avatar != null && IKSystem.Instance.animator.avatar.isHuman)
|
|
||||||
{
|
|
||||||
if (____poseHandler == null)
|
|
||||||
{
|
|
||||||
____poseHandler = new HumanPoseHandler(IKSystem.Instance.animator.avatar, IKSystem.Instance.animator.transform);
|
|
||||||
}
|
|
||||||
|
|
||||||
____poseHandler.GetHumanPose(ref ___humanPose);
|
|
||||||
for (int i = 0; i < IKPoseMuscles.Length; i++)
|
|
||||||
{
|
|
||||||
IKSystem.Instance.ApplyMuscleValue((MuscleIndex)i, IKPoseMuscles[i], ref ___humanPose.muscles);
|
|
||||||
}
|
|
||||||
____poseHandler.SetHumanPose(ref ___humanPose);
|
|
||||||
|
|
||||||
____vrik = DesktopVRIK.Instance.AlternativeCalibration(avatar);
|
|
||||||
IKSystem.Instance.ApplyAvatarScaleToIk(avatar.viewPosition.y);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static readonly float[] IKPoseMuscles = new float[]
|
[HarmonyPrefix]
|
||||||
|
[HarmonyPatch(typeof(IKSystem), "ApplyAvatarScaleToIk")]
|
||||||
|
private static bool Prefix_IKSystem_ApplyAvatarScaleToIk(float height)
|
||||||
{
|
{
|
||||||
0.00133321f,
|
return !(bool)DesktopVRIK.Instance?.OnApplyAvatarScaleToIk(height);
|
||||||
8.195831E-06f,
|
}
|
||||||
8.537738E-07f,
|
|
||||||
-0.002669832f,
|
|
||||||
-7.651234E-06f,
|
|
||||||
-0.001659694f,
|
|
||||||
0f,
|
|
||||||
0f,
|
|
||||||
0f,
|
|
||||||
0.04213953f,
|
|
||||||
0.0003007996f,
|
|
||||||
-0.008032114f,
|
|
||||||
-0.03059979f,
|
|
||||||
-0.0003182998f,
|
|
||||||
0.009640567f,
|
|
||||||
0f,
|
|
||||||
0f,
|
|
||||||
0f,
|
|
||||||
0f,
|
|
||||||
0f,
|
|
||||||
0f,
|
|
||||||
0.5768794f,
|
|
||||||
0.01061097f,
|
|
||||||
-0.1127839f,
|
|
||||||
0.9705755f,
|
|
||||||
0.07972051f,
|
|
||||||
-0.0268422f,
|
|
||||||
0.007237188f,
|
|
||||||
0f,
|
|
||||||
0.5768792f,
|
|
||||||
0.01056608f,
|
|
||||||
-0.1127519f,
|
|
||||||
0.9705756f,
|
|
||||||
0.07971933f,
|
|
||||||
-0.02682396f,
|
|
||||||
0.007229362f,
|
|
||||||
0f,
|
|
||||||
-5.651802E-06f,
|
|
||||||
-3.034899E-07f,
|
|
||||||
0.4100508f,
|
|
||||||
0.3610304f,
|
|
||||||
-0.0838329f,
|
|
||||||
0.9262537f,
|
|
||||||
0.1353517f,
|
|
||||||
-0.03578902f,
|
|
||||||
0.06005657f,
|
|
||||||
-4.95989E-06f,
|
|
||||||
-1.43007E-06f,
|
|
||||||
0.4096187f,
|
|
||||||
0.363263f,
|
|
||||||
-0.08205152f,
|
|
||||||
0.9250782f,
|
|
||||||
0.1345718f,
|
|
||||||
-0.03572125f,
|
|
||||||
0.06055461f,
|
|
||||||
-1.079177f,
|
|
||||||
0.2095419f,
|
|
||||||
0.6140652f,
|
|
||||||
0.6365265f,
|
|
||||||
0.6683931f,
|
|
||||||
-0.4764312f,
|
|
||||||
0.8099416f,
|
|
||||||
0.8099371f,
|
|
||||||
0.6658203f,
|
|
||||||
-0.7327053f,
|
|
||||||
0.8113618f,
|
|
||||||
0.8114051f,
|
|
||||||
0.6643661f,
|
|
||||||
-0.40341f,
|
|
||||||
0.8111364f,
|
|
||||||
0.8111367f,
|
|
||||||
0.6170399f,
|
|
||||||
-0.2524227f,
|
|
||||||
0.8138723f,
|
|
||||||
0.8110135f,
|
|
||||||
-1.079171f,
|
|
||||||
0.2095456f,
|
|
||||||
0.6140658f,
|
|
||||||
0.6365255f,
|
|
||||||
0.6683878f,
|
|
||||||
-0.4764301f,
|
|
||||||
0.8099402f,
|
|
||||||
0.8099376f,
|
|
||||||
0.6658241f,
|
|
||||||
-0.7327023f,
|
|
||||||
0.8113653f,
|
|
||||||
0.8113793f,
|
|
||||||
0.664364f,
|
|
||||||
-0.4034042f,
|
|
||||||
0.811136f,
|
|
||||||
0.8111364f,
|
|
||||||
0.6170469f,
|
|
||||||
-0.2524345f,
|
|
||||||
0.8138595f,
|
|
||||||
0.8110138f
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,48 +0,0 @@
|
||||||
using BTKUILib;
|
|
||||||
using BTKUILib.UIObjects;
|
|
||||||
using System.Runtime.CompilerServices;
|
|
||||||
|
|
||||||
namespace NAK.Melons.DesktopVRIK;
|
|
||||||
|
|
||||||
public static class BTKUIAddon
|
|
||||||
{
|
|
||||||
[MethodImpl(MethodImplOptions.NoInlining)]
|
|
||||||
public static void Init()
|
|
||||||
{
|
|
||||||
//Add myself to the Misc Menu
|
|
||||||
|
|
||||||
Page miscPage = QuickMenuAPI.MiscTabPage;
|
|
||||||
Category miscCategory = miscPage.AddCategory(DesktopVRIKMod.SettingsCategory);
|
|
||||||
|
|
||||||
AddMelonToggle(ref miscCategory, DesktopVRIKMod.m_entryEnabled);
|
|
||||||
|
|
||||||
//Add my own page to not clog up Misc Menu
|
|
||||||
|
|
||||||
Page desktopVRIKPage = miscCategory.AddPage("DesktopVRIK Settings", "", "Configure the settings for DesktopVRIK.", "DesktopVRIK");
|
|
||||||
desktopVRIKPage.MenuTitle = "DesktopVRIK Settings";
|
|
||||||
desktopVRIKPage.MenuSubtitle = "Simplified settings for VRIK on Desktop.";
|
|
||||||
|
|
||||||
Category desktopVRIKCategory = desktopVRIKPage.AddCategory("DesktopVRIK");
|
|
||||||
|
|
||||||
AddMelonToggle(ref desktopVRIKCategory, DesktopVRIKMod.m_entryEnabled);
|
|
||||||
|
|
||||||
AddMelonToggle(ref desktopVRIKCategory, DesktopVRIKMod.m_entryEnforceViewPosition);
|
|
||||||
|
|
||||||
AddMelonToggle(ref desktopVRIKCategory, DesktopVRIKMod.m_entryEmoteVRIK);
|
|
||||||
|
|
||||||
AddMelonToggle(ref desktopVRIKCategory, DesktopVRIKMod.m_entryEmoteLookAtIK);
|
|
||||||
|
|
||||||
AddMelonSlider(ref desktopVRIKPage, DesktopVRIKMod.m_entryBodyLeanWeight, 0, 1f);
|
|
||||||
|
|
||||||
AddMelonSlider(ref desktopVRIKPage, DesktopVRIKMod.m_entryBodyAngleLimit, 0, 90f);
|
|
||||||
}
|
|
||||||
private static void AddMelonToggle(ref Category category, MelonLoader.MelonPreferences_Entry<bool> entry)
|
|
||||||
{
|
|
||||||
category.AddToggle(entry.DisplayName, entry.Description, entry.Value).OnValueUpdated += b => entry.Value = b;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void AddMelonSlider(ref Page page, MelonLoader.MelonPreferences_Entry<float> entry, float min, float max)
|
|
||||||
{
|
|
||||||
page.AddSlider(entry.DisplayName, entry.Description, entry.Value, min, max).OnValueUpdated += f => entry.Value = f;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,5 +1,4 @@
|
||||||
using ABI_RC.Core.Player;
|
using MelonLoader;
|
||||||
using MelonLoader;
|
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
|
|
||||||
namespace NAK.Melons.DesktopVRIK;
|
namespace NAK.Melons.DesktopVRIK;
|
||||||
|
@ -8,69 +7,71 @@ public class DesktopVRIKMod : MelonMod
|
||||||
{
|
{
|
||||||
internal const string SettingsCategory = "DesktopVRIK";
|
internal const string SettingsCategory = "DesktopVRIK";
|
||||||
internal static MelonPreferences_Category m_categoryDesktopVRIK;
|
internal static MelonPreferences_Category m_categoryDesktopVRIK;
|
||||||
internal static MelonPreferences_Entry<bool> m_entryEnabled,
|
internal static MelonPreferences_Entry<bool>
|
||||||
|
m_entryEnabled,
|
||||||
m_entryEnforceViewPosition,
|
m_entryEnforceViewPosition,
|
||||||
m_entryEmoteVRIK,
|
m_entryResetIKOnLand,
|
||||||
m_entryEmoteLookAtIK;
|
m_entryPlantFeet,
|
||||||
|
m_entryUseVRIKToes,
|
||||||
|
m_entryFindUnmappedToes;
|
||||||
internal static MelonPreferences_Entry<float>
|
internal static MelonPreferences_Entry<float>
|
||||||
m_entryBodyLeanWeight,
|
m_entryBodyLeanWeight,
|
||||||
m_entryBodyAngleLimit;
|
m_entryBodyHeadingLimit,
|
||||||
|
m_entryPelvisHeadingWeight,
|
||||||
|
m_entryChestHeadingWeight;
|
||||||
public override void OnInitializeMelon()
|
public override void OnInitializeMelon()
|
||||||
{
|
{
|
||||||
m_categoryDesktopVRIK = MelonPreferences.CreateCategory(SettingsCategory);
|
m_categoryDesktopVRIK = MelonPreferences.CreateCategory(SettingsCategory);
|
||||||
m_entryEnabled = m_categoryDesktopVRIK.CreateEntry<bool>("Enabled", true, description: "Toggle DesktopVRIK entirely. Requires avatar reload.");
|
m_entryEnabled = m_categoryDesktopVRIK.CreateEntry<bool>("Enabled", true, description: "Toggle DesktopVRIK entirely. Requires avatar reload.");
|
||||||
m_entryEnforceViewPosition = m_categoryDesktopVRIK.CreateEntry<bool>("Enforce View Position", false, description: "Corrects view position to use VRIK offsets.");
|
m_entryEnforceViewPosition = m_categoryDesktopVRIK.CreateEntry<bool>("Enforce View Position", false, description: "Corrects view position to use VRIK offsets.");
|
||||||
m_entryEmoteVRIK = m_categoryDesktopVRIK.CreateEntry<bool>("Disable Emote VRIK", true, description: "Disable VRIK while emoting. Only disable if you are ok with looking dumb.");
|
m_entryResetIKOnLand = m_categoryDesktopVRIK.CreateEntry<bool>("Reset IK On Land", true, description: "Reset Solver IK when landing on the ground.");
|
||||||
m_entryEmoteLookAtIK = m_categoryDesktopVRIK.CreateEntry<bool>("Disable Emote LookAtIK", true, description: "Disable LookAtIK while emoting. This setting doesn't really matter, as LookAtIK isn't networked while doing an emote.");
|
m_entryPlantFeet = m_categoryDesktopVRIK.CreateEntry<bool>("Enforce Plant Feet", true, description: "Forces VRIK Plant Feet enabled. This prevents the little hover when you stop moving.");
|
||||||
|
m_entryUseVRIKToes = m_categoryDesktopVRIK.CreateEntry<bool>("Use VRIK Toes", false, description: "Should VRIK use your humanoid toes for IK solving? This can cause your feet to idle behind you.");
|
||||||
|
m_entryFindUnmappedToes = m_categoryDesktopVRIK.CreateEntry<bool>("Find Unmapped Toes", false, description: "Should DesktopVRIK look for unmapped toe bones if humanoid rig does not have any?");
|
||||||
|
|
||||||
m_entryBodyLeanWeight = m_categoryDesktopVRIK.CreateEntry<float>("Body Lean Weight", 0.5f, description: "Emulates old VRChat-like body leaning when looking up/down. Set to 0 to disable.");
|
m_entryBodyLeanWeight = m_categoryDesktopVRIK.CreateEntry<float>("Body Lean Weight", 0.5f, description: "Emulates old VRChat-like body leaning when looking up/down. Set to 0 to disable.");
|
||||||
m_entryBodyAngleLimit = m_categoryDesktopVRIK.CreateEntry<float>("Body Angle Limit", 0f, description: "Emulates VRChat-like body and head offset when rotating left/right. Set to 0 to disable. (this setting only affects the feet due to chillout not setting up the player controller for VRIK)");
|
m_entryBodyHeadingLimit = m_categoryDesktopVRIK.CreateEntry<float>("Body Heading Limit", 20f, description: "Emulates VRChat-like body and head offset when rotating left/right. Set to 0 to disable.");
|
||||||
|
m_entryPelvisHeadingWeight = m_categoryDesktopVRIK.CreateEntry<float>("Pelvis Heading Weight", 0.25f, description: "How much the pelvis will face the heading limit. Set to 0 to align with head.");
|
||||||
|
m_entryChestHeadingWeight = m_categoryDesktopVRIK.CreateEntry<float>("Chest Heading Weight", 0.75f, description: "How much the chest will face the heading limit. Set to 0 to align with head.");
|
||||||
|
|
||||||
foreach (var setting in m_categoryDesktopVRIK.Entries)
|
foreach (var setting in m_categoryDesktopVRIK.Entries)
|
||||||
{
|
{
|
||||||
setting.OnEntryValueChangedUntyped.Subscribe(OnUpdateSettings);
|
setting.OnEntryValueChangedUntyped.Subscribe(OnUpdateSettings);
|
||||||
}
|
}
|
||||||
|
|
||||||
//BTKUILib Misc Support
|
|
||||||
if (MelonMod.RegisteredMelons.Any(it => it.Info.Name == "BTKUILib"))
|
|
||||||
{
|
|
||||||
MelonLogger.Msg("Initializing BTKUILib support.");
|
|
||||||
BTKUIAddon.Init();
|
|
||||||
}
|
|
||||||
|
|
||||||
//Apply patches (i stole)
|
|
||||||
ApplyPatches(typeof(HarmonyPatches.PlayerSetupPatches));
|
ApplyPatches(typeof(HarmonyPatches.PlayerSetupPatches));
|
||||||
ApplyPatches(typeof(HarmonyPatches.IKSystemPatches));
|
ApplyPatches(typeof(HarmonyPatches.IKSystemPatches));
|
||||||
|
|
||||||
MelonLoader.MelonCoroutines.Start(WaitForLocalPlayer());
|
InitializeIntegrations();
|
||||||
}
|
}
|
||||||
|
|
||||||
System.Collections.IEnumerator WaitForLocalPlayer()
|
internal static void UpdateAllSettings()
|
||||||
{
|
|
||||||
while (PlayerSetup.Instance == null)
|
|
||||||
yield return null;
|
|
||||||
|
|
||||||
DesktopVRIK_Helper.CreateInstance();
|
|
||||||
PlayerSetup.Instance.gameObject.AddComponent<DesktopVRIK>();
|
|
||||||
|
|
||||||
while (DesktopVRIK.Instance == null)
|
|
||||||
yield return null;
|
|
||||||
UpdateAllSettings();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void UpdateAllSettings()
|
|
||||||
{
|
{
|
||||||
if (!DesktopVRIK.Instance) return;
|
if (!DesktopVRIK.Instance) return;
|
||||||
DesktopVRIK.Setting_Enabled = m_entryEnabled.Value;
|
// DesktopVRIK Settings
|
||||||
DesktopVRIK.Setting_BodyLeanWeight = Mathf.Clamp01(m_entryBodyLeanWeight.Value);
|
DesktopVRIK.Instance.Setting_Enabled = m_entryEnabled.Value;
|
||||||
DesktopVRIK.Setting_BodyAngleLimit = Mathf.Clamp(m_entryBodyAngleLimit.Value, 0f, 90f);
|
DesktopVRIK.Instance.Setting_BodyLeanWeight = Mathf.Clamp01(m_entryBodyLeanWeight.Value);
|
||||||
DesktopVRIK.Setting_EmoteVRIK = m_entryEmoteVRIK.Value;
|
DesktopVRIK.Instance.Setting_ResetOnLand = m_entryResetIKOnLand.Value;
|
||||||
DesktopVRIK.Setting_EmoteLookAtIK = m_entryEmoteLookAtIK.Value;
|
DesktopVRIK.Instance.Setting_PlantFeet = m_entryPlantFeet.Value;
|
||||||
DesktopVRIK.Instance.ChangeViewpointHandling(m_entryEnforceViewPosition.Value);
|
DesktopVRIK.Instance.Setting_BodyHeadingLimit = Mathf.Clamp(m_entryBodyHeadingLimit.Value, 0f, 90f);
|
||||||
|
DesktopVRIK.Instance.Setting_PelvisHeadingWeight = (1f - Mathf.Clamp01(m_entryPelvisHeadingWeight.Value));
|
||||||
|
DesktopVRIK.Instance.Setting_ChestHeadingWeight = (1f - Mathf.Clamp01(m_entryChestHeadingWeight.Value));
|
||||||
|
// Calibration Settings
|
||||||
|
DesktopVRIK.Instance.Calibrator.Setting_UseVRIKToes = m_entryUseVRIKToes.Value;
|
||||||
|
DesktopVRIK.Instance.Calibrator.Setting_FindUnmappedToes = m_entryFindUnmappedToes.Value;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnUpdateSettings(object arg1, object arg2) => UpdateAllSettings();
|
private void OnUpdateSettings(object arg1, object arg2) => UpdateAllSettings();
|
||||||
|
|
||||||
|
private static void InitializeIntegrations()
|
||||||
|
{
|
||||||
|
//BTKUILib Misc Tab
|
||||||
|
if (MelonMod.RegisteredMelons.Any(it => it.Info.Name == "BTKUILib"))
|
||||||
|
{
|
||||||
|
MelonLogger.Msg("Initializing BTKUILib support.");
|
||||||
|
//BTKUIAddon.Init();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void ApplyPatches(Type type)
|
private void ApplyPatches(Type type)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
|
|
|
@ -1,8 +1,7 @@
|
||||||
using DesktopVRIK.Properties;
|
using MelonLoader;
|
||||||
using MelonLoader;
|
using NAK.Melons.DesktopVRIK.Properties;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
|
|
||||||
|
|
||||||
[assembly: AssemblyVersion(AssemblyInfoParams.Version)]
|
[assembly: AssemblyVersion(AssemblyInfoParams.Version)]
|
||||||
[assembly: AssemblyFileVersion(AssemblyInfoParams.Version)]
|
[assembly: AssemblyFileVersion(AssemblyInfoParams.Version)]
|
||||||
[assembly: AssemblyInformationalVersion(AssemblyInfoParams.Version)]
|
[assembly: AssemblyInformationalVersion(AssemblyInfoParams.Version)]
|
||||||
|
@ -24,9 +23,9 @@ using System.Reflection;
|
||||||
[assembly: MelonOptionalDependencies("BTKUILib")]
|
[assembly: MelonOptionalDependencies("BTKUILib")]
|
||||||
[assembly: HarmonyDontPatchAll]
|
[assembly: HarmonyDontPatchAll]
|
||||||
|
|
||||||
namespace DesktopVRIK.Properties;
|
namespace NAK.Melons.DesktopVRIK.Properties;
|
||||||
internal static class AssemblyInfoParams
|
internal static class AssemblyInfoParams
|
||||||
{
|
{
|
||||||
public const string Version = "2.0.5";
|
public const string Version = "4.0.0";
|
||||||
public const string Author = "NotAKidoS";
|
public const string Author = "NotAKidoS";
|
||||||
}
|
}
|
Loading…
Add table
Add a link
Reference in a new issue