mirror of
https://github.com/NotAKidoS/NAK_CVR_Mods.git
synced 2025-09-02 06:19:22 +00:00
commit
4c614dd79f
7 changed files with 246 additions and 107 deletions
|
@ -1,30 +0,0 @@
|
||||||
using BTKUILib;
|
|
||||||
using BTKUILib.UIObjects;
|
|
||||||
using System.Runtime.CompilerServices;
|
|
||||||
|
|
||||||
namespace NAK.Melons.DesktopVRIK.BTKUI_Integration;
|
|
||||||
|
|
||||||
public static class BTKUI_Integration
|
|
||||||
{
|
|
||||||
[MethodImpl(MethodImplOptions.NoInlining)]
|
|
||||||
public static void Init()
|
|
||||||
{
|
|
||||||
Page miscPage = QuickMenuAPI.MiscTabPage;
|
|
||||||
Category CategoryUI = miscPage.AddCategory("DesktopVRIK");
|
|
||||||
|
|
||||||
var setting_Enabled = CategoryUI.AddToggle(DesktopVRIKMod.m_entryEnabled.DisplayName, DesktopVRIKMod.m_entryEnabled.Description, DesktopVRIKMod.m_entryEnabled.Value);
|
|
||||||
setting_Enabled.OnValueUpdated += b => DesktopVRIKMod.m_entryEnabled.Value = b;
|
|
||||||
|
|
||||||
var setting_EnforceViewPosition = CategoryUI.AddToggle(DesktopVRIKMod.m_entryEnforceViewPosition.DisplayName, DesktopVRIKMod.m_entryEnforceViewPosition.Description, DesktopVRIKMod.m_entryEnforceViewPosition.Value);
|
|
||||||
setting_EnforceViewPosition.OnValueUpdated += b => DesktopVRIKMod.m_entryEnforceViewPosition.Value = b;
|
|
||||||
|
|
||||||
var setting_DisableEmoteVRIK = CategoryUI.AddToggle(DesktopVRIKMod.m_entryEmoteVRIK.DisplayName, DesktopVRIKMod.m_entryEmoteVRIK.Description, DesktopVRIKMod.m_entryEmoteVRIK.Value);
|
|
||||||
setting_DisableEmoteVRIK.OnValueUpdated += b => DesktopVRIKMod.m_entryEmoteVRIK.Value = b;
|
|
||||||
|
|
||||||
var setting_DisableEmoteLookAtIK = CategoryUI.AddToggle(DesktopVRIKMod.m_entryEmoteLookAtIK.DisplayName, DesktopVRIKMod.m_entryEmoteLookAtIK.Description, DesktopVRIKMod.m_entryEmoteLookAtIK.Value);
|
|
||||||
setting_DisableEmoteLookAtIK.OnValueUpdated += b => DesktopVRIKMod.m_entryEmoteLookAtIK.Value = b;
|
|
||||||
|
|
||||||
var setting_EmulateHipMovementWeight = miscPage.AddSlider(DesktopVRIKMod.m_entryEmulateVRChatHipMovementWeight.DisplayName, DesktopVRIKMod.m_entryEmulateVRChatHipMovementWeight.Description, DesktopVRIKMod.m_entryEmulateVRChatHipMovementWeight.Value, 0f, 1f);
|
|
||||||
setting_EmulateHipMovementWeight.OnValueUpdated += f => DesktopVRIKMod.m_entryEmulateVRChatHipMovementWeight.Value = f;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -13,27 +13,22 @@ public class DesktopVRIK : MonoBehaviour
|
||||||
{
|
{
|
||||||
public static DesktopVRIK Instance;
|
public static DesktopVRIK Instance;
|
||||||
|
|
||||||
public static bool Setting_Enabled,
|
public static bool
|
||||||
|
Setting_Enabled,
|
||||||
Setting_EnforceViewPosition,
|
Setting_EnforceViewPosition,
|
||||||
Setting_EmoteVRIK,
|
Setting_EmoteVRIK,
|
||||||
Setting_EmoteLookAtIK;
|
Setting_EmoteLookAtIK;
|
||||||
public static float Setting_EmulateVRChatHipMovementWeight;
|
|
||||||
public static float Setting_HipThrustMultiplier = 0.1f;
|
public static float
|
||||||
|
Setting_BodyLeanWeight = 0.5f,
|
||||||
|
Setting_BodyAngleLimit = 0f;
|
||||||
|
|
||||||
public Transform viewpoint;
|
public Transform viewpoint;
|
||||||
public Vector3 initialCamPos;
|
public Vector3 eyeOffset;
|
||||||
|
|
||||||
Transform headIKTarget;
|
|
||||||
Transform avatarHeadBone;
|
|
||||||
|
|
||||||
void Start()
|
void Start()
|
||||||
{
|
{
|
||||||
Instance = this;
|
Instance = this;
|
||||||
// create the shared Head IK Target
|
|
||||||
headIKTarget = new GameObject("[DesktopVRIK] Head IK Target").transform;
|
|
||||||
headIKTarget.parent = PlayerSetup.Instance.transform;
|
|
||||||
headIKTarget.localPosition = new Vector3(0f, 1.8f, 0f);
|
|
||||||
headIKTarget.localRotation = Quaternion.identity;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void ChangeViewpointHandling(bool enabled)
|
public void ChangeViewpointHandling(bool enabled)
|
||||||
|
@ -45,51 +40,31 @@ public class DesktopVRIK : MonoBehaviour
|
||||||
PlayerSetup.Instance.desktopCamera.transform.localPosition = Vector3.zero;
|
PlayerSetup.Instance.desktopCamera.transform.localPosition = Vector3.zero;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
PlayerSetup.Instance.desktopCamera.transform.localPosition = initialCamPos;
|
PlayerSetup.Instance.desktopCamera.transform.localPosition = eyeOffset;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void AlternativeOnPreSolverUpdate()
|
public void AlternativeOnPreSolverUpdate()
|
||||||
{
|
{
|
||||||
//this order matters, rotation offset will be choppy if avatar is not cenetered first
|
//this order matters, rotation offset will be choppy if avatar is not cenetered first
|
||||||
|
|
||||||
if (headIKTarget != null && avatarHeadBone != null)
|
DesktopVRIK_Helper.Instance?.OnUpdateVRIK();
|
||||||
{
|
|
||||||
headIKTarget.position = new Vector3(headIKTarget.position.x, avatarHeadBone.position.y, headIKTarget.position.z);
|
|
||||||
}
|
|
||||||
|
|
||||||
//Reset avatar offset (VRIK will literally make you walk away from root otherwise)
|
//Reset avatar offset (VRIK will literally make you walk away from root otherwise)
|
||||||
IKSystem.vrik.transform.localPosition = Vector3.zero;
|
IKSystem.vrik.transform.localPosition = Vector3.zero;
|
||||||
IKSystem.vrik.transform.localRotation = Quaternion.identity;
|
IKSystem.vrik.transform.localRotation = Quaternion.identity;
|
||||||
|
|
||||||
float movementVector = (1 - MovementSystem.Instance.movementVector.magnitude);
|
|
||||||
IKSystem.vrik.solver.spine.positionWeight = Setting_HipThrustMultiplier * movementVector;
|
|
||||||
|
|
||||||
//VRChat hip movement emulation
|
|
||||||
if (Setting_EmulateVRChatHipMovementWeight != 0)
|
|
||||||
{
|
|
||||||
float angle = PlayerSetup.Instance.desktopCamera.transform.localEulerAngles.x;
|
|
||||||
if (angle > 180) angle -= 360;
|
|
||||||
float leanAmount = angle * movementVector * Setting_EmulateVRChatHipMovementWeight;
|
|
||||||
Quaternion rotation = Quaternion.AngleAxis(leanAmount, IKSystem.Instance.avatar.transform.right);
|
|
||||||
IKSystem.vrik.solver.AddRotationOffset(IKSolverVR.RotationOffset.Head, rotation);
|
|
||||||
}
|
|
||||||
|
|
||||||
IKSystem.vrik.solver.plantFeet = true;
|
IKSystem.vrik.solver.plantFeet = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Animator animator;
|
public Animator animator;
|
||||||
//public Quaternion originalRotation;
|
|
||||||
public RuntimeAnimatorController runtimeAnimatorController;
|
|
||||||
|
|
||||||
public VRIK AlternativeCalibration(CVRAvatar avatar)
|
public VRIK AlternativeCalibration(CVRAvatar avatar)
|
||||||
{
|
{
|
||||||
animator = avatar.GetComponent<Animator>();
|
animator = avatar.GetComponent<Animator>();
|
||||||
avatarHeadBone = animator.GetBoneTransform(HumanBodyBones.Head);
|
Transform avatarHeadBone = animator.GetBoneTransform(HumanBodyBones.Head);
|
||||||
|
|
||||||
//Stuff to make bad armatures work (Fuck you Default Robot Kyle)
|
//Stuff to make bad armatures work (Fuck you Default Robot Kyle)
|
||||||
avatar.transform.localPosition = Vector3.zero;
|
avatar.transform.localPosition = Vector3.zero;
|
||||||
//originalRotation = avatar.transform.rotation;
|
|
||||||
//avatar.transform.rotation = Quaternion.identity;
|
|
||||||
|
|
||||||
//ikpose layer (specified by avatar author)
|
//ikpose layer (specified by avatar author)
|
||||||
int ikposeLayerIndex = animator.GetLayerIndex("IKPose");
|
int ikposeLayerIndex = animator.GetLayerIndex("IKPose");
|
||||||
|
@ -104,22 +79,27 @@ public class DesktopVRIK : MonoBehaviour
|
||||||
animator.Update(0f);
|
animator.Update(0f);
|
||||||
}
|
}
|
||||||
|
|
||||||
//Generic VRIK calibration shit
|
|
||||||
VRIK vrik = avatar.gameObject.AddComponent<VRIK>();
|
VRIK vrik = avatar.gameObject.AddComponent<VRIK>();
|
||||||
vrik.AutoDetectReferences();
|
vrik.AutoDetectReferences();
|
||||||
|
|
||||||
|
//fuck toes
|
||||||
|
vrik.references.leftToes = null;
|
||||||
|
vrik.references.rightToes = null;
|
||||||
|
|
||||||
vrik.fixTransforms = true;
|
vrik.fixTransforms = true;
|
||||||
vrik.solver.plantFeet = false;
|
vrik.solver.plantFeet = false;
|
||||||
vrik.solver.locomotion.weight = 0f;
|
|
||||||
vrik.solver.locomotion.angleThreshold = 30f;
|
vrik.solver.locomotion.angleThreshold = 30f;
|
||||||
vrik.solver.locomotion.maxLegStretch = 0.75f;
|
vrik.solver.locomotion.maxLegStretch = 0.75f;
|
||||||
//nuke weights
|
vrik.solver.spine.minHeadHeight = -100f;
|
||||||
|
|
||||||
|
vrik.solver.spine.bodyRotStiffness = 0.15f;
|
||||||
vrik.solver.spine.headClampWeight = 1f;
|
vrik.solver.spine.headClampWeight = 1f;
|
||||||
vrik.solver.spine.minHeadHeight = 0f;
|
vrik.solver.spine.maintainPelvisPosition = 1f;
|
||||||
|
vrik.solver.spine.neckStiffness = 0f;
|
||||||
//calm ur ass
|
|
||||||
vrik.solver.spine.positionWeight = 0.1f;
|
|
||||||
|
|
||||||
|
vrik.solver.locomotion.weight = 0f;
|
||||||
|
vrik.solver.spine.bodyPosStiffness = 0f;
|
||||||
|
vrik.solver.spine.positionWeight = 0f;
|
||||||
vrik.solver.spine.pelvisPositionWeight = 0f;
|
vrik.solver.spine.pelvisPositionWeight = 0f;
|
||||||
vrik.solver.leftArm.positionWeight = 0f;
|
vrik.solver.leftArm.positionWeight = 0f;
|
||||||
vrik.solver.leftArm.rotationWeight = 0f;
|
vrik.solver.leftArm.rotationWeight = 0f;
|
||||||
|
@ -131,27 +111,26 @@ public class DesktopVRIK : MonoBehaviour
|
||||||
vrik.solver.rightLeg.rotationWeight = 0f;
|
vrik.solver.rightLeg.rotationWeight = 0f;
|
||||||
vrik.solver.IKPositionWeight = 0f;
|
vrik.solver.IKPositionWeight = 0f;
|
||||||
|
|
||||||
//ChilloutVR specific
|
|
||||||
BodySystem.TrackingLeftArmEnabled = false;
|
BodySystem.TrackingLeftArmEnabled = false;
|
||||||
BodySystem.TrackingRightArmEnabled = false;
|
BodySystem.TrackingRightArmEnabled = false;
|
||||||
BodySystem.TrackingLeftLegEnabled = false;
|
BodySystem.TrackingLeftLegEnabled = false;
|
||||||
BodySystem.TrackingRightLegEnabled = false;
|
BodySystem.TrackingRightLegEnabled = false;
|
||||||
BodySystem.TrackingPositionWeight = 0f;
|
BodySystem.TrackingPositionWeight = 0f;
|
||||||
IKSystem.Instance.headAnchorRotationOffset = Vector3.zero;
|
|
||||||
IKSystem.Instance.headAnchorPositionOffset = Vector3.zero;
|
|
||||||
|
|
||||||
//Custom funky AF head ik shit
|
//Custom funky AF head ik shit
|
||||||
foreach (Transform transform in headIKTarget)
|
foreach (Transform transform in DesktopVRIK_Helper.Instance.ik_HeadFollower)
|
||||||
{
|
{
|
||||||
if (transform.name == "Head IK Target")
|
if (transform.name == "Head IK Target")
|
||||||
{
|
{
|
||||||
Destroy(transform.gameObject);
|
Destroy(transform.gameObject);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
headIKTarget.position = avatarHeadBone.position;
|
|
||||||
headIKTarget.rotation = Quaternion.identity;
|
DesktopVRIK_Helper.Instance.avatar_HeadBone = avatarHeadBone;
|
||||||
VRIKCalibrator.CalibrateHead(vrik, headIKTarget.transform, IKSystem.Instance.headAnchorPositionOffset, IKSystem.Instance.headAnchorRotationOffset);
|
DesktopVRIK_Helper.Instance.ik_HeadFollower.position = avatarHeadBone.position;
|
||||||
headIKTarget.localRotation = Quaternion.identity;
|
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
|
//force immediate calibration before animator decides to fuck us
|
||||||
vrik.solver.SetToReferences(vrik.references);
|
vrik.solver.SetToReferences(vrik.references);
|
||||||
|
@ -167,17 +146,23 @@ public class DesktopVRIK : MonoBehaviour
|
||||||
}
|
}
|
||||||
|
|
||||||
//Find eyeoffset
|
//Find eyeoffset
|
||||||
initialCamPos = PlayerSetup.Instance.desktopCamera.transform.localPosition;
|
eyeOffset = PlayerSetup.Instance.desktopCamera.transform.localPosition;
|
||||||
viewpoint = avatarHeadBone.Find("LocalHeadPoint");
|
viewpoint = avatarHeadBone.Find("LocalHeadPoint");
|
||||||
ChangeViewpointHandling(Setting_EnforceViewPosition);
|
ChangeViewpointHandling(Setting_EnforceViewPosition);
|
||||||
|
|
||||||
if (vrik != null)
|
//reset ikpose layer
|
||||||
|
if (ikposeLayerIndex != -1)
|
||||||
{
|
{
|
||||||
vrik.onPreSolverUpdate.AddListener(new UnityAction(this.AlternativeOnPreSolverUpdate));
|
animator.SetLayerWeight(ikposeLayerIndex, 0f);
|
||||||
|
if (locoLayerIndex != -1)
|
||||||
|
{
|
||||||
|
animator.SetLayerWeight(locoLayerIndex, 1f);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//avatar.transform.rotation = originalRotation;
|
vrik?.onPreSolverUpdate.AddListener(new UnityAction(this.AlternativeOnPreSolverUpdate));
|
||||||
IKSystem.Instance.ResetIK();
|
|
||||||
|
DesktopVRIK_Helper.Instance?.OnResetIK();
|
||||||
|
|
||||||
return vrik;
|
return vrik;
|
||||||
}
|
}
|
||||||
|
|
108
DesktopVRIK/DesktopVRIK_Helper.cs
Normal file
108
DesktopVRIK/DesktopVRIK_Helper.cs
Normal file
|
@ -0,0 +1,108 @@
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -72,26 +72,47 @@ class PlayerSetupPatches
|
||||||
{
|
{
|
||||||
BodySystem.TrackingEnabled = !____emotePlaying;
|
BodySystem.TrackingEnabled = !____emotePlaying;
|
||||||
IKSystem.vrik.solver?.Reset();
|
IKSystem.vrik.solver?.Reset();
|
||||||
|
DesktopVRIK_Helper.Instance?.OnResetIK();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[HarmonyPostfix]
|
|
||||||
|
//should probably patch movement system instead
|
||||||
|
[HarmonyPrefix]
|
||||||
[HarmonyPatch(typeof(PlayerSetup), "HandleDesktopCameraPosition")]
|
[HarmonyPatch(typeof(PlayerSetup), "HandleDesktopCameraPosition")]
|
||||||
private static void Postfix_PlayerSetup_HandleDesktopCameraPosition(bool ignore, ref PlayerSetup __instance, ref MovementSystem ____movementSystem, ref int ___headBobbingLevel)
|
private static void Prefix_PlayerSetup_HandleDesktopCameraPosition
|
||||||
|
(
|
||||||
|
bool ignore,
|
||||||
|
ref PlayerSetup __instance,
|
||||||
|
ref MovementSystem
|
||||||
|
____movementSystem,
|
||||||
|
ref int ___headBobbingLevel
|
||||||
|
)
|
||||||
{
|
{
|
||||||
if (DesktopVRIK.Setting_Enabled && DesktopVRIK.Setting_EnforceViewPosition)
|
if (___headBobbingLevel != 2)
|
||||||
{
|
{
|
||||||
if (!____movementSystem.disableCameraControl || ignore)
|
return;
|
||||||
{
|
|
||||||
if (___headBobbingLevel == 2 && DesktopVRIK.Instance.viewpoint != null)
|
|
||||||
{
|
|
||||||
__instance.desktopCamera.transform.localPosition = Vector3.zero;
|
|
||||||
__instance.desktopCameraRig.transform.position = DesktopVRIK.Instance.viewpoint.position;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -118,7 +139,7 @@ class IKSystemPatches
|
||||||
____poseHandler.SetHumanPose(ref ___humanPose);
|
____poseHandler.SetHumanPose(ref ___humanPose);
|
||||||
|
|
||||||
____vrik = DesktopVRIK.Instance.AlternativeCalibration(avatar);
|
____vrik = DesktopVRIK.Instance.AlternativeCalibration(avatar);
|
||||||
IKSystem.Instance.ApplyAvatarScaleToIk(avatar.viewPosition.y);
|
IKSystem.Instance.ApplyAvatarScaleToIk(avatar.viewPosition.y);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
48
DesktopVRIK/Integrations/BTKUIAddon.cs
Normal file
48
DesktopVRIK/Integrations/BTKUIAddon.cs
Normal file
|
@ -0,0 +1,48 @@
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
|
@ -11,18 +11,21 @@ public class DesktopVRIKMod : MelonMod
|
||||||
internal static MelonPreferences_Entry<bool> m_entryEnabled,
|
internal static MelonPreferences_Entry<bool> m_entryEnabled,
|
||||||
m_entryEnforceViewPosition,
|
m_entryEnforceViewPosition,
|
||||||
m_entryEmoteVRIK,
|
m_entryEmoteVRIK,
|
||||||
m_entryEmoteLookAtIK,
|
m_entryEmoteLookAtIK;
|
||||||
m_entryAllowRootSlipping;
|
internal static MelonPreferences_Entry<float>
|
||||||
internal static MelonPreferences_Entry<float> m_entryEmulateVRChatHipMovementWeight;
|
m_entryBodyLeanWeight,
|
||||||
|
m_entryBodyAngleLimit;
|
||||||
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_entryEmulateVRChatHipMovementWeight = m_categoryDesktopVRIK.CreateEntry<float>("Body Movement Weight", 0.5f, description: "Emulates VRChat-like body movement when looking up/down. Set to 0 to disable.");
|
|
||||||
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_entryEmoteVRIK = m_categoryDesktopVRIK.CreateEntry<bool>("Disable Emote VRIK", true, description: "Disable VRIK while emoting. Only disable if you are ok with looking dumb.");
|
||||||
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_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_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)");
|
||||||
|
|
||||||
foreach (var setting in m_categoryDesktopVRIK.Entries)
|
foreach (var setting in m_categoryDesktopVRIK.Entries)
|
||||||
{
|
{
|
||||||
setting.OnEntryValueChangedUntyped.Subscribe(OnUpdateSettings);
|
setting.OnEntryValueChangedUntyped.Subscribe(OnUpdateSettings);
|
||||||
|
@ -32,7 +35,7 @@ public class DesktopVRIKMod : MelonMod
|
||||||
if (MelonMod.RegisteredMelons.Any(it => it.Info.Name == "BTKUILib"))
|
if (MelonMod.RegisteredMelons.Any(it => it.Info.Name == "BTKUILib"))
|
||||||
{
|
{
|
||||||
MelonLogger.Msg("Initializing BTKUILib support.");
|
MelonLogger.Msg("Initializing BTKUILib support.");
|
||||||
BTKUI_Integration.BTKUI_Integration.Init();
|
BTKUIAddon.Init();
|
||||||
}
|
}
|
||||||
|
|
||||||
//Apply patches (i stole)
|
//Apply patches (i stole)
|
||||||
|
@ -46,7 +49,10 @@ public class DesktopVRIKMod : MelonMod
|
||||||
{
|
{
|
||||||
while (PlayerSetup.Instance == null)
|
while (PlayerSetup.Instance == null)
|
||||||
yield return null;
|
yield return null;
|
||||||
|
|
||||||
|
DesktopVRIK_Helper.CreateInstance();
|
||||||
PlayerSetup.Instance.gameObject.AddComponent<DesktopVRIK>();
|
PlayerSetup.Instance.gameObject.AddComponent<DesktopVRIK>();
|
||||||
|
|
||||||
while (DesktopVRIK.Instance == null)
|
while (DesktopVRIK.Instance == null)
|
||||||
yield return null;
|
yield return null;
|
||||||
UpdateAllSettings();
|
UpdateAllSettings();
|
||||||
|
@ -56,7 +62,8 @@ public class DesktopVRIKMod : MelonMod
|
||||||
{
|
{
|
||||||
if (!DesktopVRIK.Instance) return;
|
if (!DesktopVRIK.Instance) return;
|
||||||
DesktopVRIK.Setting_Enabled = m_entryEnabled.Value;
|
DesktopVRIK.Setting_Enabled = m_entryEnabled.Value;
|
||||||
DesktopVRIK.Setting_EmulateVRChatHipMovementWeight = Mathf.Clamp01(m_entryEmulateVRChatHipMovementWeight.Value);
|
DesktopVRIK.Setting_BodyLeanWeight = Mathf.Clamp01(m_entryBodyLeanWeight.Value);
|
||||||
|
DesktopVRIK.Setting_BodyAngleLimit = Mathf.Clamp(m_entryBodyAngleLimit.Value, 0f, 90f);
|
||||||
DesktopVRIK.Setting_EmoteVRIK = m_entryEmoteVRIK.Value;
|
DesktopVRIK.Setting_EmoteVRIK = m_entryEmoteVRIK.Value;
|
||||||
DesktopVRIK.Setting_EmoteLookAtIK = m_entryEmoteLookAtIK.Value;
|
DesktopVRIK.Setting_EmoteLookAtIK = m_entryEmoteLookAtIK.Value;
|
||||||
DesktopVRIK.Instance.ChangeViewpointHandling(m_entryEnforceViewPosition.Value);
|
DesktopVRIK.Instance.ChangeViewpointHandling(m_entryEnforceViewPosition.Value);
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
{
|
{
|
||||||
"_id": 117,
|
"_id": 117,
|
||||||
"name": "DesktopVRIK",
|
"name": "DesktopVRIK",
|
||||||
"modversion": "2.0.2",
|
"modversion": "2.0.3",
|
||||||
"gameversion": "2022r170",
|
"gameversion": "2022r170",
|
||||||
"loaderversion": "0.5.7",
|
"loaderversion": "0.5.7",
|
||||||
"modtype": "Mod",
|
"modtype": "Mod",
|
||||||
|
@ -14,10 +14,10 @@
|
||||||
"feet"
|
"feet"
|
||||||
],
|
],
|
||||||
"requirements": [
|
"requirements": [
|
||||||
"None"
|
"BTKUILib"
|
||||||
],
|
],
|
||||||
"downloadlink": "https://github.com/NotAKidOnSteam/DesktopVRIK/releases/download/v2.0.2/DesktopVRIK.dll",
|
"downloadlink": "https://github.com/NotAKidOnSteam/DesktopVRIK/releases/download/v2.0.3/DesktopVRIK.dll",
|
||||||
"sourcelink": "https://github.com/NotAKidOnSteam/DesktopVRIK/",
|
"sourcelink": "https://github.com/NotAKidOnSteam/DesktopVRIK/",
|
||||||
"changelog": "- Fixed butt from slipping out underneath you and thrusting when leaning.\n- Fixed VRIK bleeding into locomotion animations.",
|
"changelog": "- Tweaks to VRIK settings so BetterInteractDesktop & PickupArmMovement better behave alongside VRIK.\n- Tweaks to BTKUI integration.",
|
||||||
"embedcolor": "9b59b6"
|
"embedcolor": "9b59b6"
|
||||||
}
|
}
|
Loading…
Add table
Add a link
Reference in a new issue