From 0f485ccaa3ea6138dcd90136ce9bb2f874cc25e0 Mon Sep 17 00:00:00 2001 From: NotAKidoS <37721153+NotAKidOnSteam@users.noreply.github.com> Date: Fri, 13 Jan 2023 23:48:21 -0600 Subject: [PATCH] its working (FUCK) --- DesktopVRIK/AsserHandler.cs | 95 +++++++++++++++++++ DesktopVRIK/DesktopVRIK.cs | 116 ++++++++++++++++++++++- DesktopVRIK/DesktopVRIK.csproj | 8 ++ DesktopVRIK/HarmonyPatches.cs | 12 +-- DesktopVRIK/Main.cs | 1 + DesktopVRIK/resources/IKPose.assetbundle | Bin 0 -> 5847 bytes 6 files changed, 221 insertions(+), 11 deletions(-) create mode 100644 DesktopVRIK/AsserHandler.cs create mode 100644 DesktopVRIK/resources/IKPose.assetbundle diff --git a/DesktopVRIK/AsserHandler.cs b/DesktopVRIK/AsserHandler.cs new file mode 100644 index 0000000..b5e5c7d --- /dev/null +++ b/DesktopVRIK/AsserHandler.cs @@ -0,0 +1,95 @@ +using System.Reflection; +using UnityEngine; +using Object = UnityEngine.Object; + +/* + + Kindly stolen from SDraw's leap motion mod. (MIT) + https://github.com/SDraw/ml_mods_cvr/blob/master/ml_lme/AssetsHandler.cs + + *thank u sdraw, i wont be murderer now* + +*/ + +namespace NAK.Melons.DesktopVRIK; + +static class AssetsHandler +{ + static readonly List ms_assets = new List() + { + "IKPose.assetbundle" + }; + + static Dictionary ms_loadedAssets = new Dictionary(); + static Dictionary ms_loadedObjects = new Dictionary(); + + public static void Load() + { + Assembly l_assembly = Assembly.GetExecutingAssembly(); + string l_assemblyName = l_assembly.GetName().Name; + + foreach (string l_assetName in ms_assets) + { + try + { + Stream l_assetStream = l_assembly.GetManifestResourceStream(l_assemblyName + ".resources." + l_assetName); + if (l_assetStream != null) + { + MemoryStream l_memorySteam = new MemoryStream((int)l_assetStream.Length); + l_assetStream.CopyTo(l_memorySteam); + AssetBundle l_assetBundle = AssetBundle.LoadFromMemory(l_memorySteam.ToArray(), 0); + if (l_assetBundle != null) + { + l_assetBundle.hideFlags |= HideFlags.DontUnloadUnusedAsset; + ms_loadedAssets.Add(l_assetName, l_assetBundle); + } + else + MelonLoader.MelonLogger.Warning("Unable to load bundled '" + l_assetName + "' asset"); + } + else + MelonLoader.MelonLogger.Warning("Unable to get bundled '" + l_assetName + "' asset stream"); + } + catch (System.Exception e) + { + MelonLoader.MelonLogger.Warning("Unable to load bundled '" + l_assetName + "' asset, reason: " + e.Message); + } + } + } + + public static Object GetAsset(string p_name) + { + Object l_result = null; + if (ms_loadedObjects.ContainsKey(p_name)) + { + l_result = UnityEngine.Object.Instantiate(ms_loadedObjects[p_name]); + //l_result.SetActive(true); + l_result.hideFlags |= HideFlags.DontUnloadUnusedAsset; + } + else + { + foreach (var l_pair in ms_loadedAssets) + { + if (l_pair.Value.Contains(p_name)) + { + Object l_bundledObject = (Object)l_pair.Value.LoadAsset(p_name, typeof(Object)); + if (l_bundledObject != null) + { + ms_loadedObjects.Add(p_name, l_bundledObject); + l_result = UnityEngine.Object.Instantiate(l_bundledObject); + //l_result.SetActive(true); + l_result.hideFlags |= HideFlags.DontUnloadUnusedAsset; + } + break; + } + } + } + return l_result; + } + + public static void Unload() + { + foreach (var l_pair in ms_loadedAssets) + UnityEngine.Object.Destroy(l_pair.Value); + ms_loadedAssets.Clear(); + } +} \ No newline at end of file diff --git a/DesktopVRIK/DesktopVRIK.cs b/DesktopVRIK/DesktopVRIK.cs index c2c5b36..64bf02b 100644 --- a/DesktopVRIK/DesktopVRIK.cs +++ b/DesktopVRIK/DesktopVRIK.cs @@ -16,15 +16,28 @@ public class DesktopVRIK : MonoBehaviour public static bool Setting_Enabled, Setting_EnforceViewPosition, Setting_EmoteVRIK, - Setting_EmoteLookAtIK; + Setting_EmoteLookAtIK, + Setting_AllowRootSlipping, + Setting_TestIKPoseController; public static float Setting_EmulateVRChatHipMovementWeight; public Transform viewpoint; public Vector3 initialCamPos; + Transform headIKTarget; + Transform avatarHeadBone; + + RuntimeAnimatorController ikposeController; + void Start() { Instance = this; + ikposeController = (RuntimeAnimatorController)AssetsHandler.GetAsset("Assets/BundledAssets/IKPose/IKPose.controller"); + // 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) @@ -172,4 +185,105 @@ public class DesktopVRIK : MonoBehaviour newTarget.transform.localRotation = Quaternion.identity; return newTarget.transform; } + + public void AlternativeOnPreSolverUpdate() + { + //this order matters, rotation offset will be choppy if avatar is not cenetered first + + if (headIKTarget != null && avatarHeadBone != null) + { + headIKTarget.position = new Vector3(headIKTarget.position.x, avatarHeadBone.position.y, headIKTarget.position.z); + } + + if (!Setting_AllowRootSlipping) + { + //Reset avatar offset (VRIK will literally make you walk away from root otherwise) + IKSystem.vrik.transform.localPosition = Vector3.zero; + IKSystem.vrik.transform.localRotation = Quaternion.identity; + } + + //VRChat hip movement emulation + if (Setting_EmulateVRChatHipMovementWeight != 0) + { + float angle = PlayerSetup.Instance.desktopCamera.transform.localEulerAngles.x; + if (angle > 180) angle -= 360; + float leanAmount = angle * (1 - MovementSystem.Instance.movementVector.magnitude) * 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; + } + + public Animator animator; + public Quaternion originalRotation; + public RuntimeAnimatorController runtimeAnimatorController; + + public VRIK AlternativeCalibration(CVRAvatar avatar) + { + animator = avatar.GetComponent(); + avatarHeadBone = animator.GetBoneTransform(HumanBodyBones.Head); + + //Stuff to make bad armatures work (Fuck you Default Robot Kyle) + avatar.transform.localPosition = Vector3.zero; + originalRotation = avatar.transform.rotation; + avatar.transform.rotation = Quaternion.identity; + + //force immediate calibration before animator decides to fuck us + VRIK vrik = avatar.gameObject.AddComponent(); + vrik.AutoDetectReferences(); + vrik.solver.SetToReferences(vrik.references); + vrik.solver.Initiate(vrik.transform); + + if (Setting_TestIKPoseController) + { + //Destroy(vrik); + return vrik; + } + + //Generic VRIK calibration shit + + vrik.fixTransforms = true; + vrik.solver.plantFeet = false; + vrik.solver.locomotion.weight = 0f; + vrik.solver.locomotion.angleThreshold = 30f; + vrik.solver.locomotion.maxLegStretch = 0.75f; + //nuke weights + vrik.solver.spine.headClampWeight = 0f; + vrik.solver.spine.minHeadHeight = 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; + + //ChilloutVR specific + BodySystem.TrackingLeftArmEnabled = false; + BodySystem.TrackingRightArmEnabled = false; + BodySystem.TrackingLeftLegEnabled = false; + BodySystem.TrackingRightLegEnabled = false; + IKSystem.Instance.headAnchorRotationOffset = Vector3.zero; + IKSystem.Instance.headAnchorPositionOffset = Vector3.zero; + + //Custom funky AF head ik shit + headIKTarget.position = avatarHeadBone.position; + headIKTarget.rotation = Quaternion.identity; + VRIKCalibrator.CalibrateHead(vrik, headIKTarget.transform, IKSystem.Instance.headAnchorPositionOffset, IKSystem.Instance.headAnchorRotationOffset); + headIKTarget.localRotation = Quaternion.identity; + + if (vrik != null) + { + vrik.onPreSolverUpdate.AddListener(new UnityAction(this.AlternativeOnPreSolverUpdate)); + } + + avatar.transform.rotation = originalRotation; + IKSystem.Instance.ResetIK(); + + return vrik; + } } \ No newline at end of file diff --git a/DesktopVRIK/DesktopVRIK.csproj b/DesktopVRIK/DesktopVRIK.csproj index c432ed3..8442204 100644 --- a/DesktopVRIK/DesktopVRIK.csproj +++ b/DesktopVRIK/DesktopVRIK.csproj @@ -8,6 +8,14 @@ false + + + + + + + + C:\Program Files (x86)\Steam\steamapps\common\ChilloutVR\MelonLoader\0Harmony.dll diff --git a/DesktopVRIK/HarmonyPatches.cs b/DesktopVRIK/HarmonyPatches.cs index 8ceb5a3..9a00ec2 100644 --- a/DesktopVRIK/HarmonyPatches.cs +++ b/DesktopVRIK/HarmonyPatches.cs @@ -105,8 +105,6 @@ class IKSystemPatches { if (IKSystem.Instance.animator != null && IKSystem.Instance.animator.avatar != null && IKSystem.Instance.animator.avatar.isHuman) { - IKSystem.Instance.animator.enabled = false; - //why the fuck does this fix bad armatures and heels in ground ??? (this one is suprisingly not because of Default Robot Kyle) ... (Fuck you Default Robot Kyle) if (____poseHandler == null) { @@ -120,14 +118,8 @@ class IKSystemPatches } ____poseHandler.SetHumanPose(ref ___humanPose); - //need IKSystem to see VRIK component for setup - if (____vrik == null) - { - ____vrik = avatar.gameObject.AddComponent(); - } - - //now I calibrate DesktopVRIK - DesktopVRIK.Instance.CalibrateDesktopVRIK(avatar); + ____vrik = DesktopVRIK.Instance.AlternativeCalibration(avatar); + IKSystem.Instance.ApplyAvatarScaleToIk(avatar.viewPosition.y); } } } diff --git a/DesktopVRIK/Main.cs b/DesktopVRIK/Main.cs index e236813..dcc7ebd 100644 --- a/DesktopVRIK/Main.cs +++ b/DesktopVRIK/Main.cs @@ -43,6 +43,7 @@ public class DesktopVRIKMod : MelonMod System.Collections.IEnumerator WaitForLocalPlayer() { + AssetsHandler.Load(); while (PlayerSetup.Instance == null) yield return null; PlayerSetup.Instance.gameObject.AddComponent(); diff --git a/DesktopVRIK/resources/IKPose.assetbundle b/DesktopVRIK/resources/IKPose.assetbundle new file mode 100644 index 0000000000000000000000000000000000000000..156c7e0042ca69d778ed505929dfde316f33ad22 GIT binary patch literal 5847 zcmV;|7AWaeZfSIRMpFO)000LyE_g0@05UK!IW9CVGcjf{000000000M*8l(jK>z>% zTL1t6LjV8(00000000000000U009890RRA;qyPXGRscZ`00;p902%=B7ytxAK|(Dz zHDWk9Vq-LAW@2PzGBPw|VK_1}I5aXgV`4F6Vq!A@T>tjt8ymzOwYHqQho01E=DNGdQ(`dg)QR-iU%D3f!G>xYoo z{>pR|<1;F}$2L}?OH0i;CB13pC%!lwL#O%|=lSJ-jo7b%0%mRt8H!jRd=ZH0LiNSS zt01m63vu3XPMG+uF_O#}!>c0)FP-&B0O^Zcfal7Ne|ZwwSW(V(?xD8R7DwU9Y0H}8 zyJQd7?YRtMuy$m$9h$zj10M$UF%bv_K|ZMC*KJ{Y0`VtL`L6W6pL#bVZf4@syv`5N zUmSm9D>YaP&VLLPGLd5)2K+y{fL?KS zf&!R@Q4lz^|3?G zER+Vnso z3p1$Yr-j9D!UhDYhm45Ib<^*8<_Iaecn`cucjkx#SIk?D_Q#vsuM`kh-}_WR#c5OxZc>h5I=@mng3*P z2huI`vzv5qAOxn(ES0~&c_&z~1!3Gu;roOMhFRDqUdecT(xp+CTJ$5U8&)jDbRaYt z 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