From 6433dd7c7863cbab5f51cedfa81686bfe8750a90 Mon Sep 17 00:00:00 2001 From: NotAKidoS <37721153+NotAKidOnSteam@users.noreply.github.com> Date: Sat, 14 Jan 2023 01:21:49 -0600 Subject: [PATCH] a --- DesktopVRIK/AsserHandler.cs | 95 ----------------------- DesktopVRIK/DesktopVRIK.cs | 60 ++++++-------- DesktopVRIK/DesktopVRIK.csproj | 8 -- DesktopVRIK/HarmonyPatches.cs | 2 +- DesktopVRIK/Main.cs | 3 - DesktopVRIK/format.json | 2 +- DesktopVRIK/resources/IKPose.assetbundle | Bin 5847 -> 0 bytes 7 files changed, 25 insertions(+), 145 deletions(-) delete mode 100644 DesktopVRIK/AsserHandler.cs delete mode 100644 DesktopVRIK/resources/IKPose.assetbundle diff --git a/DesktopVRIK/AsserHandler.cs b/DesktopVRIK/AsserHandler.cs deleted file mode 100644 index b5e5c7d..0000000 --- a/DesktopVRIK/AsserHandler.cs +++ /dev/null @@ -1,95 +0,0 @@ -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 f329628..f00ad95 100644 --- a/DesktopVRIK/DesktopVRIK.cs +++ b/DesktopVRIK/DesktopVRIK.cs @@ -16,9 +16,7 @@ public class DesktopVRIK : MonoBehaviour public static bool Setting_Enabled, Setting_EnforceViewPosition, Setting_EmoteVRIK, - Setting_EmoteLookAtIK, - Setting_AllowRootSlipping, - Setting_TestIKPoseController; + Setting_EmoteLookAtIK; public static float Setting_EmulateVRChatHipMovementWeight; public Transform viewpoint; @@ -27,12 +25,9 @@ public class DesktopVRIK : MonoBehaviour 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; @@ -61,12 +56,9 @@ public class DesktopVRIK : MonoBehaviour 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; - } + //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) @@ -96,18 +88,18 @@ public class DesktopVRIK : MonoBehaviour //avatar.transform.rotation = Quaternion.identity; //ikpose layer (specified by avatar author) - int? ikposeLayerIndex = PlayerSetup.Instance.animatorManager.GetAnimatorLayerIndex("IKPose"); - int? locoLayerIndex = PlayerSetup.Instance.animatorManager.GetAnimatorLayerIndex("Locomotion/Emotes"); + //int? ikposeLayerIndex = PlayerSetup.Instance.animatorManager.GetAnimatorLayerIndex("IKPose"); + //int? locoLayerIndex = PlayerSetup.Instance.animatorManager.GetAnimatorLayerIndex("Locomotion/Emotes"); - if (ikposeLayerIndex != -1) - { - PlayerSetup.Instance.animatorManager.SetAnimatorLayerWeight("IKPose", 1f); - if (locoLayerIndex != -1) - { - PlayerSetup.Instance.animatorManager.SetAnimatorLayerWeight("Locomotion/Emotes", 0f); - } - IKSystem.Instance.animator.Update(0f); - } + //if (ikposeLayerIndex != -1) + //{ + // PlayerSetup.Instance.animatorManager.SetAnimatorLayerWeight("IKPose", 1f); + // if (locoLayerIndex != -1) + // { + // PlayerSetup.Instance.animatorManager.SetAnimatorLayerWeight("Locomotion/Emotes", 0f); + // } + // IKSystem.Instance.animator.Update(0f); + //} //Generic VRIK calibration shit VRIK vrik = avatar.gameObject.AddComponent(); @@ -157,20 +149,14 @@ public class DesktopVRIK : MonoBehaviour vrik.solver.SetToReferences(vrik.references); vrik.solver.Initiate(vrik.transform); - if (ikposeLayerIndex != -1) - { - PlayerSetup.Instance.animatorManager.SetAnimatorLayerWeight("IKPose", 0f); - if (locoLayerIndex != -1) - { - PlayerSetup.Instance.animatorManager.SetAnimatorLayerWeight("Locomotion/Emotes", 1f); - } - } - - if (Setting_TestIKPoseController) - { - animator.enabled = false; - return vrik; - } + //if (ikposeLayerIndex != -1) + //{ + // PlayerSetup.Instance.animatorManager.SetAnimatorLayerWeight("IKPose", 0f); + // if (locoLayerIndex != -1) + // { + // PlayerSetup.Instance.animatorManager.SetAnimatorLayerWeight("Locomotion/Emotes", 1f); + // } + //} //Find eyeoffset initialCamPos = PlayerSetup.Instance.desktopCamera.transform.localPosition; diff --git a/DesktopVRIK/DesktopVRIK.csproj b/DesktopVRIK/DesktopVRIK.csproj index 8442204..c432ed3 100644 --- a/DesktopVRIK/DesktopVRIK.csproj +++ b/DesktopVRIK/DesktopVRIK.csproj @@ -8,14 +8,6 @@ false - - - - - - - - C:\Program Files (x86)\Steam\steamapps\common\ChilloutVR\MelonLoader\0Harmony.dll diff --git a/DesktopVRIK/HarmonyPatches.cs b/DesktopVRIK/HarmonyPatches.cs index 9a00ec2..9d8c7b2 100644 --- a/DesktopVRIK/HarmonyPatches.cs +++ b/DesktopVRIK/HarmonyPatches.cs @@ -117,7 +117,7 @@ class IKSystemPatches 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); } diff --git a/DesktopVRIK/Main.cs b/DesktopVRIK/Main.cs index d77a5ae..8fd3cc4 100644 --- a/DesktopVRIK/Main.cs +++ b/DesktopVRIK/Main.cs @@ -22,7 +22,6 @@ public class DesktopVRIKMod : MelonMod m_entryEnforceViewPosition = m_categoryDesktopVRIK.CreateEntry("Enforce View Position", false, description: "Corrects view position to use VRIK offsets."); m_entryEmoteVRIK = m_categoryDesktopVRIK.CreateEntry("Disable Emote VRIK", true, description: "Disable VRIK while emoting. Only disable if you are ok with looking dumb."); m_entryEmoteLookAtIK = m_categoryDesktopVRIK.CreateEntry("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_entryAllowRootSlipping = m_categoryDesktopVRIK.CreateEntry("Allow Root Slipping", false, description: "Allows avatar root to slip out from under itself, to emulate more wacky VRChat behavior."); foreach (var setting in m_categoryDesktopVRIK.Entries) { @@ -45,7 +44,6 @@ public class DesktopVRIKMod : MelonMod System.Collections.IEnumerator WaitForLocalPlayer() { - AssetsHandler.Load(); while (PlayerSetup.Instance == null) yield return null; PlayerSetup.Instance.gameObject.AddComponent(); @@ -61,7 +59,6 @@ public class DesktopVRIKMod : MelonMod DesktopVRIK.Setting_EmulateVRChatHipMovementWeight = Mathf.Clamp01(m_entryEmulateVRChatHipMovementWeight.Value); DesktopVRIK.Setting_EmoteVRIK = m_entryEmoteVRIK.Value; DesktopVRIK.Setting_EmoteLookAtIK = m_entryEmoteLookAtIK.Value; - DesktopVRIK.Setting_AllowRootSlipping = m_entryAllowRootSlipping.Value; DesktopVRIK.Instance.ChangeViewpointHandling(m_entryEnforceViewPosition.Value); } diff --git a/DesktopVRIK/format.json b/DesktopVRIK/format.json index ba61c32..b13d3cf 100644 --- a/DesktopVRIK/format.json +++ b/DesktopVRIK/format.json @@ -18,6 +18,6 @@ ], "downloadlink": "https://github.com/NotAKidOnSteam/DesktopVRIK/releases/download/v2.0.0/DesktopVRIK.dll", "sourcelink": "https://github.com/NotAKidOnSteam/DesktopVRIK/", - "changelog": "- Simplified VRIK calibration to avoid low heel issue.\n- Removed rushed compatibility mode.\n- Added checks for valid Humanoid rigs.\n- Added PlantFeet & EnforceViewPosition Settings.\n- Added Weight option for the VRChat-like hip movement.\n- Simplified config, added BTKUILib support.\n- Reworked calibration to support almost every avatar.\n- Added custom avatar-defined IKPose support.", + "changelog": "- Simplified VRIK calibration to avoid low heel issue.\n- Added checks for valid Humanoid rigs.\n- Added PlantFeet & EnforceViewPosition Settings.\n- Added Weight option for the VRChat-like hip movement.\n- Simplified config, added BTKUILib support.\n- Reworked calibration to support almost every avatar.", "embedcolor": "9b59b6" } \ No newline at end of file diff --git a/DesktopVRIK/resources/IKPose.assetbundle b/DesktopVRIK/resources/IKPose.assetbundle deleted file mode 100644 index 156c7e0042ca69d778ed505929dfde316f33ad22..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 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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