diff --git a/README.md b/README.md index e35fe14..88d870e 100644 --- a/README.md +++ b/README.md @@ -3,20 +3,20 @@ Merged set of MelonLoader mods for ChilloutVR. **Table for game build 2023r172p1:** | Full name | Short name | Latest version | Available in [CVRMA](https://github.com/knah/CVRMelonAssistant) | |:---------:|:----------:|:--------------:| :----------------------------------------------------------------| -| [Avatar Motion Tweaker](/ml_amt/README.md) | ml_amt | 1.3.3 [:arrow_down:](../../releases/latest/download/ml_amt.dll)| ✔ Yes | -| [Desktop Head Tracking](/ml_dht/README.md)| ml_dht | - | ✔ Yes
:warning:Broken | -| [Leap Motion Extension](/ml_lme/README.md)| ml_lme | 1.4.3 [:arrow_down:](../../releases/latest/download/ml_lme.dll)| ✔ Yes | +| [Avatar Motion Tweaker](/ml_amt/README.md) | ml_amt | 1.3.4 [:arrow_down:](../../releases/latest/download/ml_amt.dll)| ✔ Yes
:hourglass_flowing_sand: Update review | +| [Leap Motion Extension](/ml_lme/README.md)| ml_lme | 1.4.4 [:arrow_down:](../../releases/latest/download/ml_lme.dll)| ✔ Yes
:hourglass_flowing_sand: Update review | | [Pickup Arm Movement](/ml_pam/README.md)| ml_pam | 1.0.8 [:arrow_down:](../../releases/latest/download/ml_pam.dll)| ✔ Yes | | [Player Movement Copycat](/ml_pmc/README.md)| ml_pmc | 1.0.3 [:arrow_down:](../../releases/latest/download/ml_pmc.dll)| ✔ Yes | -| [Player Ragdoll Mod](/ml_prm/README.md)| ml_prm | 1.0.11 [:arrow_down:](../../releases/latest/download/ml_prm.dll)| ✔ Yes
:hourglass_flowing_sand: Update review | | [Vive Extended Input](/ml_vei/README.md) | ml_vei | 1.0.0 [:arrow_down:](../../releases/latest/download/ml_vei.dll)| ✔ Yes | **Archived mods:** | Full name | Short name | Notes | |:---------:|:----------:|-------| -| Avatar Change Info | ml_aci | Superseded by `Extended Game Notifications` -| Desktop Reticle Switch | ml_drs | Boring functionality -| Extended Game Notifications | ml_egn | In-game feature sine 2023r172 update -| Four Point Tracking | ml_fpt | In-game feature since 2022r170 update -| Game Main Fixes | ml_gmf | In-game feature sine 2023r172 update +| Avatar Change Info | ml_aci | Superseded by `Extended Game Notifications` | +| Desktop Head Tracking | ml_dht | Unable to emulate fake data | +| Desktop Reticle Switch | ml_drs | Boring functionality | +| Extended Game Notifications | ml_egn | In-game feature sine 2023r172 update | +| Four Point Tracking | ml_fpt | In-game feature since 2022r170 update | +| Game Main Fixes | ml_gmf | In-game feature sine 2023r172 update | +| Player Ragdoll Mod | ml_prm | Unable to fix offset problems | | Server Connection Info | ml_sci | Superseded by `Extended Game Notifications` diff --git a/ml_dht/.github/img_01.png b/archived/ml_dht/.github/img_01.png similarity index 100% rename from ml_dht/.github/img_01.png rename to archived/ml_dht/.github/img_01.png diff --git a/ml_dht/HeadTracked.cs b/archived/ml_dht/HeadTracked.cs similarity index 97% rename from ml_dht/HeadTracked.cs rename to archived/ml_dht/HeadTracked.cs index 00b116d..915b104 100644 --- a/ml_dht/HeadTracked.cs +++ b/archived/ml_dht/HeadTracked.cs @@ -1,185 +1,185 @@ -using ABI.CCK.Components; -using ABI_RC.Core.Player; -using RootMotion.FinalIK; -using System.Reflection; -using UnityEngine; -using ViveSR.anipal.Lip; - -namespace ml_dht -{ - [DisallowMultipleComponent] - class HeadTracked : MonoBehaviour - { - static FieldInfo ms_emotePlaying = typeof(PlayerSetup).GetField("_emotePlaying", BindingFlags.NonPublic | BindingFlags.Instance); - - bool m_enabled = false; - bool m_headTracking = true; - bool m_blinking = true; - bool m_eyeTracking = true; - float m_smoothing = 0.5f; - bool m_mirrored = false; - bool m_faceOverride = true; - - CVRAvatar m_avatarDescriptor = null; - LookAtIK m_lookIK = null; - Transform m_headBone = null; - - Vector3 m_headPosition; - Quaternion m_headRotation; - Vector2 m_gazeDirection; - float m_blinkProgress = 0f; - Vector2 m_mouthShapes; - float m_eyebrowsProgress = 0f; - - Quaternion m_bindRotation; - Quaternion m_lastHeadRotation; - - // Unity events - void Start() - { - Settings.EnabledChange += this.SetEnabled; - Settings.HeadTrackingChange += this.SetHeadTracking; - Settings.EyeTrackingChange += this.SetEyeTracking; - Settings.BlinkingChange += this.SetBlinking; - Settings.SmoothingChange += this.SetSmoothing; - Settings.MirroredChange += this.SetMirrored; - Settings.FaceOverrideChange += this.SetFaceOverride; - } - - void OnDestroy() - { - Settings.EnabledChange -= this.SetEnabled; - Settings.HeadTrackingChange -= this.SetHeadTracking; - Settings.EyeTrackingChange -= this.SetEyeTracking; - Settings.BlinkingChange -= this.SetBlinking; - Settings.SmoothingChange -= this.SetSmoothing; - Settings.MirroredChange -= this.SetMirrored; - Settings.FaceOverrideChange -= this.SetFaceOverride; - } - - // Tracking updates - public void UpdateTrackingData(ref TrackingData p_data) - { - m_headPosition.Set(p_data.m_headPositionX * (m_mirrored ? -1f : 1f), p_data.m_headPositionY, p_data.m_headPositionZ); - m_headRotation.Set(p_data.m_headRotationX, p_data.m_headRotationY * (m_mirrored ? -1f : 1f), p_data.m_headRotationZ * (m_mirrored ? -1f : 1f), p_data.m_headRotationW); - m_gazeDirection.Set(m_mirrored ? (1f - p_data.m_gazeX) : p_data.m_gazeX, p_data.m_gazeY); - m_blinkProgress = p_data.m_blink; - m_mouthShapes.Set(p_data.m_mouthOpen, p_data.m_mouthShape); - m_eyebrowsProgress = p_data.m_brows; - } - - void OnLookIKPostUpdate() - { - if(m_enabled && m_headTracking && (m_headBone != null)) - { - m_lastHeadRotation = Quaternion.Slerp(m_lastHeadRotation, m_avatarDescriptor.transform.rotation * (m_headRotation * m_bindRotation), m_smoothing); - - if(!(bool)ms_emotePlaying.GetValue(PlayerSetup.Instance)) - m_headBone.rotation = m_lastHeadRotation; - } - } - - // Game events - internal void OnEyeControllerUpdate(CVREyeController p_component) - { - if(m_enabled) - { - // Gaze - if(m_eyeTracking) - { - Transform l_camera = PlayerSetup.Instance.GetActiveCamera().transform; - - p_component.manualViewTarget = true; - p_component.targetViewPosition = l_camera.position + l_camera.rotation * new Vector3((m_gazeDirection.x - 0.5f) * 2f, (m_gazeDirection.y - 0.5f) * 2f, 1f); - } - - // Blink - if(m_blinking) - { - p_component.manualBlinking = true; - p_component.blinkProgress = m_blinkProgress; - } - } - } - - internal void OnFaceTrackingUpdate(CVRFaceTracking p_component) - { - if(m_enabled && m_faceOverride) - { - if(m_avatarDescriptor != null) - m_avatarDescriptor.useVisemeLipsync = false; - - float l_weight = Mathf.Clamp01(Mathf.InverseLerp(0.25f, 1f, Mathf.Abs(m_mouthShapes.y))) * 100f; - - p_component.BlendShapeValues[(int)LipShape_v2.Jaw_Open] = m_mouthShapes.x * 100f; - p_component.BlendShapeValues[(int)LipShape_v2.Mouth_Pout] = ((m_mouthShapes.y > 0f) ? l_weight : 0f); - p_component.BlendShapeValues[(int)LipShape_v2.Mouth_Smile_Left] = ((m_mouthShapes.y < 0f) ? l_weight : 0f); - p_component.BlendShapeValues[(int)LipShape_v2.Mouth_Smile_Right] = ((m_mouthShapes.y < 0f) ? l_weight : 0f); - p_component.LipSyncWasUpdated = true; - p_component.UpdateLipShapes(); - } - } - - internal void OnSetupAvatar() - { - m_avatarDescriptor = PlayerSetup.Instance._avatar.GetComponent(); - m_headBone = PlayerSetup.Instance._animator.GetBoneTransform(HumanBodyBones.Head); - m_lookIK = PlayerSetup.Instance._avatar.GetComponent(); - - if(m_headBone != null) - m_bindRotation = (m_avatarDescriptor.transform.GetMatrix().inverse * m_headBone.GetMatrix()).rotation; - - if(m_lookIK != null) - m_lookIK.solver.OnPostUpdate += this.OnLookIKPostUpdate; - - } - internal void OnAvatarClear() - { - m_avatarDescriptor = null; - m_lookIK = null; - m_headBone = null; - m_lastHeadRotation = Quaternion.identity; - m_bindRotation = Quaternion.identity; - } - - // Settings - internal void SetEnabled(bool p_state) - { - if(m_enabled != p_state) - { - m_enabled = p_state; - if(m_enabled && m_headTracking) - m_lastHeadRotation = ((m_headBone != null) ? m_headBone.rotation : m_bindRotation); - } - } - internal void SetHeadTracking(bool p_state) - { - if(m_headTracking != p_state) - { - m_headTracking = p_state; - if(m_enabled && m_headTracking) - m_lastHeadRotation = ((m_headBone != null) ? m_headBone.rotation : m_bindRotation); - } - } - internal void SetEyeTracking(bool p_state) - { - m_eyeTracking = p_state; - } - internal void SetBlinking(bool p_state) - { - m_blinking = p_state; - } - internal void SetSmoothing(float p_value) - { - m_smoothing = 1f - Mathf.Clamp(p_value, 0f, 0.99f); - } - internal void SetMirrored(bool p_state) - { - m_mirrored = p_state; - } - internal void SetFaceOverride(bool p_state) - { - m_faceOverride = p_state; - } - } -} +using ABI.CCK.Components; +using ABI_RC.Core.Player; +using RootMotion.FinalIK; +using System.Reflection; +using UnityEngine; +using ViveSR.anipal.Lip; + +namespace ml_dht +{ + [DisallowMultipleComponent] + class HeadTracked : MonoBehaviour + { + static FieldInfo ms_emotePlaying = typeof(PlayerSetup).GetField("_emotePlaying", BindingFlags.NonPublic | BindingFlags.Instance); + + bool m_enabled = false; + bool m_headTracking = true; + bool m_blinking = true; + bool m_eyeTracking = true; + float m_smoothing = 0.5f; + bool m_mirrored = false; + bool m_faceOverride = true; + + CVRAvatar m_avatarDescriptor = null; + LookAtIK m_lookIK = null; + Transform m_headBone = null; + + Vector3 m_headPosition; + Quaternion m_headRotation; + Vector2 m_gazeDirection; + float m_blinkProgress = 0f; + Vector2 m_mouthShapes; + float m_eyebrowsProgress = 0f; + + Quaternion m_bindRotation; + Quaternion m_lastHeadRotation; + + // Unity events + void Start() + { + Settings.EnabledChange += this.SetEnabled; + Settings.HeadTrackingChange += this.SetHeadTracking; + Settings.EyeTrackingChange += this.SetEyeTracking; + Settings.BlinkingChange += this.SetBlinking; + Settings.SmoothingChange += this.SetSmoothing; + Settings.MirroredChange += this.SetMirrored; + Settings.FaceOverrideChange += this.SetFaceOverride; + } + + void OnDestroy() + { + Settings.EnabledChange -= this.SetEnabled; + Settings.HeadTrackingChange -= this.SetHeadTracking; + Settings.EyeTrackingChange -= this.SetEyeTracking; + Settings.BlinkingChange -= this.SetBlinking; + Settings.SmoothingChange -= this.SetSmoothing; + Settings.MirroredChange -= this.SetMirrored; + Settings.FaceOverrideChange -= this.SetFaceOverride; + } + + // Tracking updates + public void UpdateTrackingData(ref TrackingData p_data) + { + m_headPosition.Set(p_data.m_headPositionX * (m_mirrored ? -1f : 1f), p_data.m_headPositionY, p_data.m_headPositionZ); + m_headRotation.Set(p_data.m_headRotationX, p_data.m_headRotationY * (m_mirrored ? -1f : 1f), p_data.m_headRotationZ * (m_mirrored ? -1f : 1f), p_data.m_headRotationW); + m_gazeDirection.Set(m_mirrored ? (1f - p_data.m_gazeX) : p_data.m_gazeX, p_data.m_gazeY); + m_blinkProgress = p_data.m_blink; + m_mouthShapes.Set(p_data.m_mouthOpen, p_data.m_mouthShape); + m_eyebrowsProgress = p_data.m_brows; + } + + void OnLookIKPostUpdate() + { + if(m_enabled && m_headTracking && (m_headBone != null)) + { + m_lastHeadRotation = Quaternion.Slerp(m_lastHeadRotation, m_avatarDescriptor.transform.rotation * (m_headRotation * m_bindRotation), m_smoothing); + + if(!(bool)ms_emotePlaying.GetValue(PlayerSetup.Instance)) + m_headBone.rotation = m_lastHeadRotation; + } + } + + // Game events + internal void OnEyeControllerUpdate(CVREyeController p_component) + { + if(m_enabled) + { + // Gaze + if(m_eyeTracking) + { + Transform l_camera = PlayerSetup.Instance.GetActiveCamera().transform; + + p_component.manualViewTarget = true; + p_component.targetViewPosition = l_camera.position + l_camera.rotation * new Vector3((m_gazeDirection.x - 0.5f) * 2f, (m_gazeDirection.y - 0.5f) * 2f, 1f); + } + + // Blink + if(m_blinking) + { + p_component.manualBlinking = true; + p_component.blinkProgress = m_blinkProgress; + } + } + } + + internal void OnFaceTrackingUpdate(CVRFaceTracking p_component) + { + if(m_enabled && m_faceOverride) + { + if(m_avatarDescriptor != null) + m_avatarDescriptor.useVisemeLipsync = false; + + float l_weight = Mathf.Clamp01(Mathf.InverseLerp(0.25f, 1f, Mathf.Abs(m_mouthShapes.y))) * 100f; + + p_component.BlendShapeValues[(int)LipShape_v2.Jaw_Open] = m_mouthShapes.x * 100f; + p_component.BlendShapeValues[(int)LipShape_v2.Mouth_Pout] = ((m_mouthShapes.y > 0f) ? l_weight : 0f); + p_component.BlendShapeValues[(int)LipShape_v2.Mouth_Smile_Left] = ((m_mouthShapes.y < 0f) ? l_weight : 0f); + p_component.BlendShapeValues[(int)LipShape_v2.Mouth_Smile_Right] = ((m_mouthShapes.y < 0f) ? l_weight : 0f); + p_component.LipSyncWasUpdated = true; + p_component.UpdateLipShapes(); + } + } + + internal void OnSetupAvatar() + { + m_avatarDescriptor = PlayerSetup.Instance._avatar.GetComponent(); + m_headBone = PlayerSetup.Instance._animator.GetBoneTransform(HumanBodyBones.Head); + m_lookIK = PlayerSetup.Instance._avatar.GetComponent(); + + if(m_headBone != null) + m_bindRotation = (m_avatarDescriptor.transform.GetMatrix().inverse * m_headBone.GetMatrix()).rotation; + + if(m_lookIK != null) + m_lookIK.solver.OnPostUpdate += this.OnLookIKPostUpdate; + + } + internal void OnAvatarClear() + { + m_avatarDescriptor = null; + m_lookIK = null; + m_headBone = null; + m_lastHeadRotation = Quaternion.identity; + m_bindRotation = Quaternion.identity; + } + + // Settings + internal void SetEnabled(bool p_state) + { + if(m_enabled != p_state) + { + m_enabled = p_state; + if(m_enabled && m_headTracking) + m_lastHeadRotation = ((m_headBone != null) ? m_headBone.rotation : m_bindRotation); + } + } + internal void SetHeadTracking(bool p_state) + { + if(m_headTracking != p_state) + { + m_headTracking = p_state; + if(m_enabled && m_headTracking) + m_lastHeadRotation = ((m_headBone != null) ? m_headBone.rotation : m_bindRotation); + } + } + internal void SetEyeTracking(bool p_state) + { + m_eyeTracking = p_state; + } + internal void SetBlinking(bool p_state) + { + m_blinking = p_state; + } + internal void SetSmoothing(float p_value) + { + m_smoothing = 1f - Mathf.Clamp(p_value, 0f, 0.99f); + } + internal void SetMirrored(bool p_state) + { + m_mirrored = p_state; + } + internal void SetFaceOverride(bool p_state) + { + m_faceOverride = p_state; + } + } +} diff --git a/ml_dht/Main.cs b/archived/ml_dht/Main.cs similarity index 97% rename from ml_dht/Main.cs rename to archived/ml_dht/Main.cs index 8357b77..4246ff3 100644 --- a/ml_dht/Main.cs +++ b/archived/ml_dht/Main.cs @@ -1,146 +1,146 @@ -using ABI.CCK.Components; -using ABI_RC.Core.Player; -using System.Reflection; - -namespace ml_dht -{ - public class DesktopHeadTracking : MelonLoader.MelonMod - { - static DesktopHeadTracking ms_instance = null; - - MemoryMapReader m_mapReader = null; - byte[] m_buffer = null; - TrackingData m_trackingData; - - HeadTracked m_localTracked = null; - - public override void OnInitializeMelon() - { - if(ms_instance == null) - ms_instance = this; - - Settings.Init(); - - m_mapReader = new MemoryMapReader(); - m_buffer = new byte[1024]; - - m_mapReader.Open("head/data"); - - // Patches - HarmonyInstance.Patch( - typeof(PlayerSetup).GetMethod(nameof(PlayerSetup.ClearAvatar)), - null, - new HarmonyLib.HarmonyMethod(typeof(DesktopHeadTracking).GetMethod(nameof(OnAvatarClear_Postfix), BindingFlags.Static | BindingFlags.NonPublic)) - ); - HarmonyInstance.Patch( - typeof(PlayerSetup).GetMethod(nameof(PlayerSetup.SetupAvatar)), - null, - new HarmonyLib.HarmonyMethod(typeof(DesktopHeadTracking).GetMethod(nameof(OnSetupAvatar_Postfix), BindingFlags.Static | BindingFlags.NonPublic)) - ); - HarmonyInstance.Patch( - typeof(CVREyeController).GetMethod("Update", BindingFlags.Instance | BindingFlags.NonPublic), - null, - new HarmonyLib.HarmonyMethod(typeof(DesktopHeadTracking).GetMethod(nameof(OnEyeControllerUpdate_Postfix), BindingFlags.Static | BindingFlags.NonPublic)) - ); - HarmonyInstance.Patch( - typeof(CVRFaceTracking).GetMethod("Update", BindingFlags.Instance | BindingFlags.NonPublic), - null, - new HarmonyLib.HarmonyMethod(typeof(DesktopHeadTracking).GetMethod(nameof(OnFaceTrackingUpdate_Postfix), BindingFlags.Static | BindingFlags.NonPublic)) - ); - - MelonLoader.MelonCoroutines.Start(WaitForPlayer()); - } - - System.Collections.IEnumerator WaitForPlayer() - { - while(PlayerSetup.Instance == null) - yield return null; - - m_localTracked = PlayerSetup.Instance.gameObject.AddComponent(); - m_localTracked.SetEnabled(Settings.Enabled); - m_localTracked.SetHeadTracking(Settings.HeadTracking); - m_localTracked.SetEyeTracking(Settings.EyeTracking); - m_localTracked.SetBlinking(Settings.Blinking); - m_localTracked.SetMirrored(Settings.Mirrored); - m_localTracked.SetSmoothing(Settings.Smoothing); - m_localTracked.SetFaceOverride(Settings.FaceOverride); - } - - public override void OnDeinitializeMelon() - { - if(ms_instance == this) - ms_instance = null; - - m_mapReader?.Close(); - m_mapReader = null; - m_buffer = null; - m_localTracked = null; - } - - public override void OnUpdate() - { - if(Settings.Enabled && m_mapReader.Read(ref m_buffer)) - { - m_trackingData = TrackingData.ToObject(m_buffer); - if(m_localTracked != null) - m_localTracked.UpdateTrackingData(ref m_trackingData); - } - } - - static void OnSetupAvatar_Postfix() => ms_instance?.OnSetupAvatar(); - void OnSetupAvatar() - { - try - { - if(m_localTracked != null) - m_localTracked.OnSetupAvatar(); - } - catch(System.Exception e) - { - MelonLoader.MelonLogger.Error(e); - } - } - - static void OnAvatarClear_Postfix() => ms_instance?.OnAvatarClear(); - void OnAvatarClear() - { - try - { - if(m_localTracked != null) - m_localTracked.OnAvatarClear(); - } - catch(System.Exception e) - { - MelonLoader.MelonLogger.Error(e); - } - } - - static void OnEyeControllerUpdate_Postfix(ref CVREyeController __instance) => ms_instance?.OnEyeControllerUpdate(__instance); - void OnEyeControllerUpdate(CVREyeController p_component) - { - try - { - if(p_component.isLocal && (m_localTracked != null)) - m_localTracked.OnEyeControllerUpdate(p_component); - } - catch(System.Exception e) - { - MelonLoader.MelonLogger.Error(e); - } - } - - static void OnFaceTrackingUpdate_Postfix(ref CVRFaceTracking __instance) => ms_instance?.OnFaceTrackingUpdate(__instance); - void OnFaceTrackingUpdate(CVRFaceTracking p_component) - { - try - { - if(p_component.isLocal && (m_localTracked != null)) - m_localTracked.OnFaceTrackingUpdate(p_component); - } - catch(System.Exception e) - { - MelonLoader.MelonLogger.Error(e); - } - } - } +using ABI.CCK.Components; +using ABI_RC.Core.Player; +using System.Reflection; + +namespace ml_dht +{ + public class DesktopHeadTracking : MelonLoader.MelonMod + { + static DesktopHeadTracking ms_instance = null; + + MemoryMapReader m_mapReader = null; + byte[] m_buffer = null; + TrackingData m_trackingData; + + HeadTracked m_localTracked = null; + + public override void OnInitializeMelon() + { + if(ms_instance == null) + ms_instance = this; + + Settings.Init(); + + m_mapReader = new MemoryMapReader(); + m_buffer = new byte[1024]; + + m_mapReader.Open("head/data"); + + // Patches + HarmonyInstance.Patch( + typeof(PlayerSetup).GetMethod(nameof(PlayerSetup.ClearAvatar)), + null, + new HarmonyLib.HarmonyMethod(typeof(DesktopHeadTracking).GetMethod(nameof(OnAvatarClear_Postfix), BindingFlags.Static | BindingFlags.NonPublic)) + ); + HarmonyInstance.Patch( + typeof(PlayerSetup).GetMethod(nameof(PlayerSetup.SetupAvatar)), + null, + new HarmonyLib.HarmonyMethod(typeof(DesktopHeadTracking).GetMethod(nameof(OnSetupAvatar_Postfix), BindingFlags.Static | BindingFlags.NonPublic)) + ); + HarmonyInstance.Patch( + typeof(CVREyeController).GetMethod("Update", BindingFlags.Instance | BindingFlags.NonPublic), + null, + new HarmonyLib.HarmonyMethod(typeof(DesktopHeadTracking).GetMethod(nameof(OnEyeControllerUpdate_Postfix), BindingFlags.Static | BindingFlags.NonPublic)) + ); + HarmonyInstance.Patch( + typeof(CVRFaceTracking).GetMethod("Update", BindingFlags.Instance | BindingFlags.NonPublic), + null, + new HarmonyLib.HarmonyMethod(typeof(DesktopHeadTracking).GetMethod(nameof(OnFaceTrackingUpdate_Postfix), BindingFlags.Static | BindingFlags.NonPublic)) + ); + + MelonLoader.MelonCoroutines.Start(WaitForPlayer()); + } + + System.Collections.IEnumerator WaitForPlayer() + { + while(PlayerSetup.Instance == null) + yield return null; + + m_localTracked = PlayerSetup.Instance.gameObject.AddComponent(); + m_localTracked.SetEnabled(Settings.Enabled); + m_localTracked.SetHeadTracking(Settings.HeadTracking); + m_localTracked.SetEyeTracking(Settings.EyeTracking); + m_localTracked.SetBlinking(Settings.Blinking); + m_localTracked.SetMirrored(Settings.Mirrored); + m_localTracked.SetSmoothing(Settings.Smoothing); + m_localTracked.SetFaceOverride(Settings.FaceOverride); + } + + public override void OnDeinitializeMelon() + { + if(ms_instance == this) + ms_instance = null; + + m_mapReader?.Close(); + m_mapReader = null; + m_buffer = null; + m_localTracked = null; + } + + public override void OnUpdate() + { + if(Settings.Enabled && m_mapReader.Read(ref m_buffer)) + { + m_trackingData = TrackingData.ToObject(m_buffer); + if(m_localTracked != null) + m_localTracked.UpdateTrackingData(ref m_trackingData); + } + } + + static void OnSetupAvatar_Postfix() => ms_instance?.OnSetupAvatar(); + void OnSetupAvatar() + { + try + { + if(m_localTracked != null) + m_localTracked.OnSetupAvatar(); + } + catch(System.Exception e) + { + MelonLoader.MelonLogger.Error(e); + } + } + + static void OnAvatarClear_Postfix() => ms_instance?.OnAvatarClear(); + void OnAvatarClear() + { + try + { + if(m_localTracked != null) + m_localTracked.OnAvatarClear(); + } + catch(System.Exception e) + { + MelonLoader.MelonLogger.Error(e); + } + } + + static void OnEyeControllerUpdate_Postfix(ref CVREyeController __instance) => ms_instance?.OnEyeControllerUpdate(__instance); + void OnEyeControllerUpdate(CVREyeController p_component) + { + try + { + if(p_component.isLocal && (m_localTracked != null)) + m_localTracked.OnEyeControllerUpdate(p_component); + } + catch(System.Exception e) + { + MelonLoader.MelonLogger.Error(e); + } + } + + static void OnFaceTrackingUpdate_Postfix(ref CVRFaceTracking __instance) => ms_instance?.OnFaceTrackingUpdate(__instance); + void OnFaceTrackingUpdate(CVRFaceTracking p_component) + { + try + { + if(p_component.isLocal && (m_localTracked != null)) + m_localTracked.OnFaceTrackingUpdate(p_component); + } + catch(System.Exception e) + { + MelonLoader.MelonLogger.Error(e); + } + } + } } \ No newline at end of file diff --git a/ml_dht/MemoryMapReader.cs b/archived/ml_dht/MemoryMapReader.cs similarity index 100% rename from ml_dht/MemoryMapReader.cs rename to archived/ml_dht/MemoryMapReader.cs diff --git a/ml_dht/Properties/AssemblyInfo.cs b/archived/ml_dht/Properties/AssemblyInfo.cs similarity index 99% rename from ml_dht/Properties/AssemblyInfo.cs rename to archived/ml_dht/Properties/AssemblyInfo.cs index a4c8fbf..5982313 100644 --- a/ml_dht/Properties/AssemblyInfo.cs +++ b/archived/ml_dht/Properties/AssemblyInfo.cs @@ -1,4 +1,4 @@ -[assembly: MelonLoader.MelonInfo(typeof(ml_dht.DesktopHeadTracking), "DesktopHeadTracking", "1.1.2-ex", "SDraw", "https://github.com/SDraw/ml_mods_cvr")] -[assembly: MelonLoader.MelonGame(null, "ChilloutVR")] -[assembly: MelonLoader.MelonPlatform(MelonLoader.MelonPlatformAttribute.CompatiblePlatforms.WINDOWS_X64)] +[assembly: MelonLoader.MelonInfo(typeof(ml_dht.DesktopHeadTracking), "DesktopHeadTracking", "1.1.2-ex", "SDraw", "https://github.com/SDraw/ml_mods_cvr")] +[assembly: MelonLoader.MelonGame(null, "ChilloutVR")] +[assembly: MelonLoader.MelonPlatform(MelonLoader.MelonPlatformAttribute.CompatiblePlatforms.WINDOWS_X64)] [assembly: MelonLoader.MelonPlatformDomain(MelonLoader.MelonPlatformDomainAttribute.CompatibleDomains.MONO)] \ No newline at end of file diff --git a/ml_dht/README.md b/archived/ml_dht/README.md similarity index 98% rename from ml_dht/README.md rename to archived/ml_dht/README.md index ddfff6c..4388afb 100644 --- a/ml_dht/README.md +++ b/archived/ml_dht/README.md @@ -1,29 +1,29 @@ -# Desktop Head Tracking -This mod adds desktop head tracking based on data from memory-mapped file `head/data`. -Refer to `TrackingData.cs` for reference in case of implementing own software. - -[![](.github/img_01.png)](https://youtu.be/jgcFhSNi9DM) - -# Features -* Head rotation -* Eyes gaze direction -* Blinking -* Basic mouth shapes - -# Installation -* Install [latest MelonLoader](https://github.com/LavaGang/MelonLoader) -* Get [latest release DLL](../../../releases/latest): - * Put `ml_dht.dll` in `Mods` folder of game - -# Usage -Available mod's settings in `Settings - Implementation - Desktop Head Tracking`: -* **Enabled:** enables mod's activity; default value - `false`. -* **Use head tracking:** enables head tracking; default value - `true`. -* **Use eyes tracking:** uses eyes tracking from data; default value - `true`. -* **Use blinking:** uses blinking from data; default value - `true`. -* **Mirrored movement:** mirrors movement and gaze along 0YZ plane; default value - `false`. -* **Movement smoothing:** smoothing factor between new and old movement data; default value - `50`. -* **Override face tracking:** overrides and activates avatar's `VRC Face Tracking` components. List of used shapes: `Jaw_Open`, `Mouth_Pout`, `Mouth_Smile_Left`, `Mouth_Smile_Right`; default value - `true`. - -# Known compatible tracking software -* [VSeeFace](https://www.vseeface.icu) with [Tracking Data Parser mod](https://github.com/SDraw/ml_mods_vsf) +# Desktop Head Tracking +This mod adds desktop head tracking based on data from memory-mapped file `head/data`. +Refer to `TrackingData.cs` for reference in case of implementing own software. + +[![](.github/img_01.png)](https://youtu.be/jgcFhSNi9DM) + +# Features +* Head rotation +* Eyes gaze direction +* Blinking +* Basic mouth shapes + +# Installation +* Install [latest MelonLoader](https://github.com/LavaGang/MelonLoader) +* Get [latest release DLL](../../../releases/latest): + * Put `ml_dht.dll` in `Mods` folder of game + +# Usage +Available mod's settings in `Settings - Implementation - Desktop Head Tracking`: +* **Enabled:** enables mod's activity; default value - `false`. +* **Use head tracking:** enables head tracking; default value - `true`. +* **Use eyes tracking:** uses eyes tracking from data; default value - `true`. +* **Use blinking:** uses blinking from data; default value - `true`. +* **Mirrored movement:** mirrors movement and gaze along 0YZ plane; default value - `false`. +* **Movement smoothing:** smoothing factor between new and old movement data; default value - `50`. +* **Override face tracking:** overrides and activates avatar's `VRC Face Tracking` components. List of used shapes: `Jaw_Open`, `Mouth_Pout`, `Mouth_Smile_Left`, `Mouth_Smile_Right`; default value - `true`. + +# Known compatible tracking software +* [VSeeFace](https://www.vseeface.icu) with [Tracking Data Parser mod](https://github.com/SDraw/ml_mods_vsf) diff --git a/ml_dht/Scripts.cs b/archived/ml_dht/Scripts.cs similarity index 96% rename from ml_dht/Scripts.cs rename to archived/ml_dht/Scripts.cs index 2445a5b..0b1ccaf 100644 --- a/ml_dht/Scripts.cs +++ b/archived/ml_dht/Scripts.cs @@ -1,26 +1,26 @@ -using System; -using System.IO; -using System.Reflection; - -namespace ml_dht -{ - static class Scripts - { - public static string GetEmbeddedScript(string p_name) - { - string l_result = ""; - Assembly l_assembly = Assembly.GetExecutingAssembly(); - string l_assemblyName = l_assembly.GetName().Name; - - try - { - Stream l_libraryStream = l_assembly.GetManifestResourceStream(l_assemblyName + ".resources." + p_name); - StreamReader l_streadReader = new StreamReader(l_libraryStream); - l_result = l_streadReader.ReadToEnd(); - } - catch(Exception) { } - - return l_result; - } - } -} +using System; +using System.IO; +using System.Reflection; + +namespace ml_dht +{ + static class Scripts + { + public static string GetEmbeddedScript(string p_name) + { + string l_result = ""; + Assembly l_assembly = Assembly.GetExecutingAssembly(); + string l_assemblyName = l_assembly.GetName().Name; + + try + { + Stream l_libraryStream = l_assembly.GetManifestResourceStream(l_assemblyName + ".resources." + p_name); + StreamReader l_streadReader = new StreamReader(l_libraryStream); + l_result = l_streadReader.ReadToEnd(); + } + catch(Exception) { } + + return l_result; + } + } +} diff --git a/ml_dht/Settings.cs b/archived/ml_dht/Settings.cs similarity index 97% rename from ml_dht/Settings.cs rename to archived/ml_dht/Settings.cs index aaa92f1..db21eef 100644 --- a/ml_dht/Settings.cs +++ b/archived/ml_dht/Settings.cs @@ -1,163 +1,163 @@ -using ABI_RC.Core.InteractionSystem; -using System; -using System.Collections.Generic; - -namespace ml_dht -{ - static class Settings - { - enum ModSetting - { - Enabled = 0, - HeadTracking, - EyeTracking, - Blinking, - Mirrored, - Smoothing, - FaceOverride - } - - public static bool Enabled { get; private set; } = false; - public static bool HeadTracking { get; private set; } = true; - public static bool EyeTracking { get; private set; } = true; - public static bool Blinking { get; private set; } = true; - public static bool Mirrored { get; private set; } = false; - public static float Smoothing { get; private set; } = 0.5f; - public static bool FaceOverride { get; private set; } = true; - - static MelonLoader.MelonPreferences_Category ms_category = null; - static List ms_entries = null; - - static public event Action EnabledChange; - static public event Action HeadTrackingChange; - static public event Action EyeTrackingChange; - static public event Action BlinkingChange; - static public event Action MirroredChange; - static public event Action SmoothingChange; - static public event Action FaceOverrideChange; - - internal static void Init() - { - ms_category = MelonLoader.MelonPreferences.CreateCategory("DHT"); - - ms_entries = new List() - { - ms_category.CreateEntry(ModSetting.Enabled.ToString(), Enabled), - ms_category.CreateEntry(ModSetting.HeadTracking.ToString(), HeadTracking), - ms_category.CreateEntry(ModSetting.EyeTracking.ToString(), EyeTracking), - ms_category.CreateEntry(ModSetting.Blinking.ToString(), Blinking), - ms_category.CreateEntry(ModSetting.Mirrored.ToString(), Mirrored), - ms_category.CreateEntry(ModSetting.Smoothing.ToString(), (int)(Smoothing * 50f)), - ms_category.CreateEntry(ModSetting.FaceOverride.ToString(), FaceOverride) - }; - - Load(); - - MelonLoader.MelonCoroutines.Start(WaitMainMenuUi()); - } - - static System.Collections.IEnumerator WaitMainMenuUi() - { - while(ViewManager.Instance == null) - yield return null; - while(ViewManager.Instance.gameMenuView == null) - yield return null; - while(ViewManager.Instance.gameMenuView.Listener == null) - yield return null; - - ViewManager.Instance.gameMenuView.Listener.ReadyForBindings += () => - { - ViewManager.Instance.gameMenuView.View.BindCall("MelonMod_DHT_Call_InpSlider", new Action(OnSliderUpdate)); - ViewManager.Instance.gameMenuView.View.BindCall("MelonMod_DHT_Call_InpToggle", new Action(OnToggleUpdate)); - }; - ViewManager.Instance.gameMenuView.Listener.FinishLoad += (_) => - { - ViewManager.Instance.gameMenuView.View.ExecuteScript(Scripts.GetEmbeddedScript("menu.js")); - foreach(var l_entry in ms_entries) - ViewManager.Instance.gameMenuView.View.TriggerEvent("updateModSettingDHT", l_entry.DisplayName, l_entry.GetValueAsString()); - }; - } - - static void Load() - { - Enabled = (bool)ms_entries[(int)ModSetting.Enabled].BoxedValue; - HeadTracking = (bool)ms_entries[(int)ModSetting.HeadTracking].BoxedValue; - EyeTracking = (bool)ms_entries[(int)ModSetting.EyeTracking].BoxedValue; - Blinking = (bool)ms_entries[(int)ModSetting.Blinking].BoxedValue; - Mirrored = (bool)ms_entries[(int)ModSetting.Mirrored].BoxedValue; - Smoothing = ((int)ms_entries[(int)ModSetting.Smoothing].BoxedValue) * 0.01f; - FaceOverride = (bool)ms_entries[(int)ModSetting.FaceOverride].BoxedValue; - } - - static void OnSliderUpdate(string p_name, string p_value) - { - if(Enum.TryParse(p_name, out ModSetting l_setting)) - { - switch(l_setting) - { - case ModSetting.Smoothing: - { - Smoothing = int.Parse(p_value) * 0.01f; - SmoothingChange?.Invoke(Smoothing); - } - break; - } - - ms_entries[(int)l_setting].BoxedValue = int.Parse(p_value); - } - } - - static void OnToggleUpdate(string p_name, string p_value) - { - if(Enum.TryParse(p_name, out ModSetting l_setting)) - { - switch(l_setting) - { - case ModSetting.Enabled: - { - Enabled = bool.Parse(p_value); - EnabledChange?.Invoke(Enabled); - } - break; - - case ModSetting.HeadTracking: - { - HeadTracking = bool.Parse(p_value); - HeadTrackingChange?.Invoke(HeadTracking); - } - break; - - case ModSetting.EyeTracking: - { - EyeTracking = bool.Parse(p_value); - EyeTrackingChange?.Invoke(EyeTracking); - } - break; - - case ModSetting.Blinking: - { - Blinking = bool.Parse(p_value); - BlinkingChange?.Invoke(Blinking); - } - break; - - case ModSetting.Mirrored: - { - Mirrored = bool.Parse(p_value); - MirroredChange?.Invoke(Mirrored); - } - break; - - case ModSetting.FaceOverride: - { - FaceOverride = bool.Parse(p_value); - FaceOverrideChange?.Invoke(FaceOverride); - } - break; - } - - ms_entries[(int)l_setting].BoxedValue = bool.Parse(p_value); - } - } - } -} +using ABI_RC.Core.InteractionSystem; +using System; +using System.Collections.Generic; + +namespace ml_dht +{ + static class Settings + { + enum ModSetting + { + Enabled = 0, + HeadTracking, + EyeTracking, + Blinking, + Mirrored, + Smoothing, + FaceOverride + } + + public static bool Enabled { get; private set; } = false; + public static bool HeadTracking { get; private set; } = true; + public static bool EyeTracking { get; private set; } = true; + public static bool Blinking { get; private set; } = true; + public static bool Mirrored { get; private set; } = false; + public static float Smoothing { get; private set; } = 0.5f; + public static bool FaceOverride { get; private set; } = true; + + static MelonLoader.MelonPreferences_Category ms_category = null; + static List ms_entries = null; + + static public event Action EnabledChange; + static public event Action HeadTrackingChange; + static public event Action EyeTrackingChange; + static public event Action BlinkingChange; + static public event Action MirroredChange; + static public event Action SmoothingChange; + static public event Action FaceOverrideChange; + + internal static void Init() + { + ms_category = MelonLoader.MelonPreferences.CreateCategory("DHT"); + + ms_entries = new List() + { + ms_category.CreateEntry(ModSetting.Enabled.ToString(), Enabled), + ms_category.CreateEntry(ModSetting.HeadTracking.ToString(), HeadTracking), + ms_category.CreateEntry(ModSetting.EyeTracking.ToString(), EyeTracking), + ms_category.CreateEntry(ModSetting.Blinking.ToString(), Blinking), + ms_category.CreateEntry(ModSetting.Mirrored.ToString(), Mirrored), + ms_category.CreateEntry(ModSetting.Smoothing.ToString(), (int)(Smoothing * 50f)), + ms_category.CreateEntry(ModSetting.FaceOverride.ToString(), FaceOverride) + }; + + Load(); + + MelonLoader.MelonCoroutines.Start(WaitMainMenuUi()); + } + + static System.Collections.IEnumerator WaitMainMenuUi() + { + while(ViewManager.Instance == null) + yield return null; + while(ViewManager.Instance.gameMenuView == null) + yield return null; + while(ViewManager.Instance.gameMenuView.Listener == null) + yield return null; + + ViewManager.Instance.gameMenuView.Listener.ReadyForBindings += () => + { + ViewManager.Instance.gameMenuView.View.BindCall("MelonMod_DHT_Call_InpSlider", new Action(OnSliderUpdate)); + ViewManager.Instance.gameMenuView.View.BindCall("MelonMod_DHT_Call_InpToggle", new Action(OnToggleUpdate)); + }; + ViewManager.Instance.gameMenuView.Listener.FinishLoad += (_) => + { + ViewManager.Instance.gameMenuView.View.ExecuteScript(Scripts.GetEmbeddedScript("menu.js")); + foreach(var l_entry in ms_entries) + ViewManager.Instance.gameMenuView.View.TriggerEvent("updateModSettingDHT", l_entry.DisplayName, l_entry.GetValueAsString()); + }; + } + + static void Load() + { + Enabled = (bool)ms_entries[(int)ModSetting.Enabled].BoxedValue; + HeadTracking = (bool)ms_entries[(int)ModSetting.HeadTracking].BoxedValue; + EyeTracking = (bool)ms_entries[(int)ModSetting.EyeTracking].BoxedValue; + Blinking = (bool)ms_entries[(int)ModSetting.Blinking].BoxedValue; + Mirrored = (bool)ms_entries[(int)ModSetting.Mirrored].BoxedValue; + Smoothing = ((int)ms_entries[(int)ModSetting.Smoothing].BoxedValue) * 0.01f; + FaceOverride = (bool)ms_entries[(int)ModSetting.FaceOverride].BoxedValue; + } + + static void OnSliderUpdate(string p_name, string p_value) + { + if(Enum.TryParse(p_name, out ModSetting l_setting)) + { + switch(l_setting) + { + case ModSetting.Smoothing: + { + Smoothing = int.Parse(p_value) * 0.01f; + SmoothingChange?.Invoke(Smoothing); + } + break; + } + + ms_entries[(int)l_setting].BoxedValue = int.Parse(p_value); + } + } + + static void OnToggleUpdate(string p_name, string p_value) + { + if(Enum.TryParse(p_name, out ModSetting l_setting)) + { + switch(l_setting) + { + case ModSetting.Enabled: + { + Enabled = bool.Parse(p_value); + EnabledChange?.Invoke(Enabled); + } + break; + + case ModSetting.HeadTracking: + { + HeadTracking = bool.Parse(p_value); + HeadTrackingChange?.Invoke(HeadTracking); + } + break; + + case ModSetting.EyeTracking: + { + EyeTracking = bool.Parse(p_value); + EyeTrackingChange?.Invoke(EyeTracking); + } + break; + + case ModSetting.Blinking: + { + Blinking = bool.Parse(p_value); + BlinkingChange?.Invoke(Blinking); + } + break; + + case ModSetting.Mirrored: + { + Mirrored = bool.Parse(p_value); + MirroredChange?.Invoke(Mirrored); + } + break; + + case ModSetting.FaceOverride: + { + FaceOverride = bool.Parse(p_value); + FaceOverrideChange?.Invoke(FaceOverride); + } + break; + } + + ms_entries[(int)l_setting].BoxedValue = bool.Parse(p_value); + } + } + } +} diff --git a/ml_dht/TrackingData.cs b/archived/ml_dht/TrackingData.cs similarity index 100% rename from ml_dht/TrackingData.cs rename to archived/ml_dht/TrackingData.cs diff --git a/ml_dht/Utils.cs b/archived/ml_dht/Utils.cs similarity index 97% rename from ml_dht/Utils.cs rename to archived/ml_dht/Utils.cs index 638b9e4..bf8f374 100644 --- a/ml_dht/Utils.cs +++ b/archived/ml_dht/Utils.cs @@ -1,18 +1,18 @@ -using ABI_RC.Core.UI; -using System.Reflection; -using UnityEngine; - -namespace ml_dht -{ - static class Utils - { - static FieldInfo ms_cohtmlView = typeof(CohtmlControlledViewDisposable).GetField("_view", BindingFlags.NonPublic | BindingFlags.Instance); - - public static Matrix4x4 GetMatrix(this Transform p_transform, bool p_pos = true, bool p_rot = true, bool p_scl = false) - { - return Matrix4x4.TRS(p_pos ? p_transform.position : Vector3.zero, p_rot ? p_transform.rotation : Quaternion.identity, p_scl ? p_transform.localScale : Vector3.one); - } - - public static void ExecuteScript(this CohtmlControlledViewDisposable p_viewDisposable, string p_script) => ((cohtml.Net.View)ms_cohtmlView.GetValue(p_viewDisposable))?.ExecuteScript(p_script); - } -} +using ABI_RC.Core.UI; +using System.Reflection; +using UnityEngine; + +namespace ml_dht +{ + static class Utils + { + static FieldInfo ms_cohtmlView = typeof(CohtmlControlledViewDisposable).GetField("_view", BindingFlags.NonPublic | BindingFlags.Instance); + + public static Matrix4x4 GetMatrix(this Transform p_transform, bool p_pos = true, bool p_rot = true, bool p_scl = false) + { + return Matrix4x4.TRS(p_pos ? p_transform.position : Vector3.zero, p_rot ? p_transform.rotation : Quaternion.identity, p_scl ? p_transform.localScale : Vector3.one); + } + + public static void ExecuteScript(this CohtmlControlledViewDisposable p_viewDisposable, string p_script) => ((cohtml.Net.View)ms_cohtmlView.GetValue(p_viewDisposable))?.ExecuteScript(p_script); + } +} diff --git a/ml_dht/ml_dht.csproj b/archived/ml_dht/ml_dht.csproj similarity index 97% rename from ml_dht/ml_dht.csproj rename to archived/ml_dht/ml_dht.csproj index 32ef990..5bed49c 100644 --- a/ml_dht/ml_dht.csproj +++ b/archived/ml_dht/ml_dht.csproj @@ -1,71 +1,71 @@ - - - - netstandard2.1 - DesktopHeadTracking - SDraw - None - DesktopHeadTracking - 1.1.2 - x64 - - - - x64 - none - false - - - - - - - - - - - - - - D:\games\Steam\steamapps\common\ChilloutVR\MelonLoader\0Harmony.dll - false - - - D:\games\Steam\steamapps\common\ChilloutVR\ChilloutVR_Data\Managed\Assembly-CSharp.dll - false - - - D:\games\Steam\steamapps\common\ChilloutVR\ChilloutVR_Data\Managed\Assembly-CSharp-firstpass.dll - false - - - D:\games\Steam\steamapps\common\ChilloutVR\ChilloutVR_Data\Managed\cohtml.Net.dll - false - - - D:\games\Steam\steamapps\common\ChilloutVR\ChilloutVR_Data\Managed\Cohtml.Runtime.dll - false - - - D:\games\Steam\steamapps\common\ChilloutVR\MelonLoader\MelonLoader.dll - false - - - D:\games\Steam\steamapps\common\ChilloutVR\ChilloutVR_Data\Managed\UnityEngine.dll - false - - - D:\games\Steam\steamapps\common\ChilloutVR\ChilloutVR_Data\Managed\UnityEngine.AnimationModule.dll - false - - - D:\games\Steam\steamapps\common\ChilloutVR\ChilloutVR_Data\Managed\UnityEngine.CoreModule.dll - false - - - - - - - - + + + + netstandard2.1 + DesktopHeadTracking + SDraw + None + DesktopHeadTracking + 1.1.2 + x64 + + + + x64 + none + false + + + + + + + + + + + + + + D:\games\Steam\steamapps\common\ChilloutVR\MelonLoader\0Harmony.dll + false + + + D:\games\Steam\steamapps\common\ChilloutVR\ChilloutVR_Data\Managed\Assembly-CSharp.dll + false + + + D:\games\Steam\steamapps\common\ChilloutVR\ChilloutVR_Data\Managed\Assembly-CSharp-firstpass.dll + false + + + D:\games\Steam\steamapps\common\ChilloutVR\ChilloutVR_Data\Managed\cohtml.Net.dll + false + + + D:\games\Steam\steamapps\common\ChilloutVR\ChilloutVR_Data\Managed\Cohtml.Runtime.dll + false + + + D:\games\Steam\steamapps\common\ChilloutVR\MelonLoader\MelonLoader.dll + false + + + D:\games\Steam\steamapps\common\ChilloutVR\ChilloutVR_Data\Managed\UnityEngine.dll + false + + + D:\games\Steam\steamapps\common\ChilloutVR\ChilloutVR_Data\Managed\UnityEngine.AnimationModule.dll + false + + + D:\games\Steam\steamapps\common\ChilloutVR\ChilloutVR_Data\Managed\UnityEngine.CoreModule.dll + false + + + + + + + + diff --git a/ml_dht/resources/menu.js b/archived/ml_dht/resources/menu.js similarity index 97% rename from ml_dht/resources/menu.js rename to archived/ml_dht/resources/menu.js index 38f2b5c..37727c7 100644 --- a/ml_dht/resources/menu.js +++ b/archived/ml_dht/resources/menu.js @@ -1,245 +1,245 @@ -// Add settings -var g_modSettingsDHT = []; - -engine.on('updateModSettingDHT', function (_name, _value) { - for (var i = 0; i < g_modSettingsDHT.length; i++) { - if (g_modSettingsDHT[i].name == _name) { - g_modSettingsDHT[i].updateValue(_value); - break; - } - } -}); - -// Modified from original `inp` types, because I have no js knowledge to hook stuff -function inp_slider_mod_dht(_obj, _callbackName) { - this.obj = _obj; - this.callbackName = _callbackName; - this.minValue = parseFloat(_obj.getAttribute('data-min')); - this.maxValue = parseFloat(_obj.getAttribute('data-max')); - this.percent = 0; - this.value = parseFloat(_obj.getAttribute('data-current')); - this.dragActive = false; - this.name = _obj.id; - this.type = _obj.getAttribute('data-type'); - this.stepSize = _obj.getAttribute('data-stepSize') || 0; - this.format = _obj.getAttribute('data-format') || '{value}'; - - var self = this; - - if (this.stepSize != 0) - this.value = Math.round(this.value / this.stepSize) * this.stepSize; - else - this.value = Math.round(this.value); - - this.valueLabelBackground = document.createElement('div'); - this.valueLabelBackground.className = 'valueLabel background'; - this.valueLabelBackground.innerHTML = this.format.replace('{value}', this.value); - this.obj.appendChild(this.valueLabelBackground); - - this.valueBar = document.createElement('div'); - this.valueBar.className = 'valueBar'; - this.valueBar.setAttribute('style', 'width: ' + (((this.value - this.minValue) / (this.maxValue - this.minValue)) * 100) + '%;'); - this.obj.appendChild(this.valueBar); - - this.valueLabelForeground = document.createElement('div'); - this.valueLabelForeground.className = 'valueLabel foreground'; - this.valueLabelForeground.innerHTML = this.format.replace('{value}', this.value); - this.valueLabelForeground.setAttribute('style', 'width: ' + (1.0 / ((this.value - this.minValue) / (this.maxValue - this.minValue)) * 100) + '%;'); - this.valueBar.appendChild(this.valueLabelForeground); - - this.mouseDown = function (_e) { - self.dragActive = true; - self.mouseMove(_e, false); - } - - this.mouseMove = function (_e, _write) { - if (self.dragActive) { - var rect = _obj.getBoundingClientRect(); - var start = rect.left; - var end = rect.right; - self.percent = Math.min(Math.max((_e.clientX - start) / rect.width, 0), 1); - var value = self.percent; - value *= (self.maxValue - self.minValue); - value += self.minValue; - if (self.stepSize != 0) { - value = Math.round(value / self.stepSize); - self.value = value * self.stepSize; - self.percent = (self.value - self.minValue) / (self.maxValue - self.minValue); - } - else - self.value = Math.round(value); - - self.valueBar.setAttribute('style', 'width: ' + (self.percent * 100) + '%;'); - self.valueLabelForeground.setAttribute('style', 'width: ' + (1.0 / self.percent * 100) + '%;'); - self.valueLabelBackground.innerHTML = self.valueLabelForeground.innerHTML = self.format.replace('{value}', self.value); - - engine.call(self.callbackName, self.name, "" + self.value); - self.displayImperial(); - } - } - - this.mouseUp = function (_e) { - self.mouseMove(_e, true); - self.dragActive = false; - } - - _obj.addEventListener('mousedown', this.mouseDown); - document.addEventListener('mousemove', this.mouseMove); - document.addEventListener('mouseup', this.mouseUp); - - this.getValue = function () { - return self.value; - } - - this.updateValue = function (value) { - if (self.stepSize != 0) - self.value = Math.round(value * self.stepSize) / self.stepSize; - else - self.value = Math.round(value); - self.percent = (self.value - self.minValue) / (self.maxValue - self.minValue); - self.valueBar.setAttribute('style', 'width: ' + (self.percent * 100) + '%;'); - self.valueLabelForeground.setAttribute('style', 'width: ' + (1.0 / self.percent * 100) + '%;'); - self.valueLabelBackground.innerHTML = self.valueLabelForeground.innerHTML = self.format.replace('{value}', self.value); - self.displayImperial(); - } - - this.displayImperial = function () { - var displays = document.querySelectorAll('.imperialDisplay'); - for (var i = 0; i < displays.length; i++) { - var binding = displays[i].getAttribute('data-binding'); - if (binding == self.name) { - var realFeet = ((self.value * 0.393700) / 12); - var feet = Math.floor(realFeet); - var inches = Math.floor((realFeet - feet) * 12); - displays[i].innerHTML = feet + "'" + inches + ''''; - } - } - } - - return { - name: this.name, - value: this.getValue, - updateValue: this.updateValue - } -} - -// Modified from original `inp` types, because I have no js knowledge to hook stuff -function inp_toggle_mod_dht(_obj, _callbackName) { - this.obj = _obj; - this.callbackName = _callbackName; - this.value = _obj.getAttribute('data-current'); - this.name = _obj.id; - this.type = _obj.getAttribute('data-type'); - - var self = this; - - this.mouseDown = function (_e) { - self.value = self.value == "True" ? "False" : "True"; - self.updateState(); - } - - this.updateState = function () { - self.obj.classList.remove("checked"); - if (self.value == "True") { - self.obj.classList.add("checked"); - } - - engine.call(self.callbackName, self.name, self.value); - } - - _obj.addEventListener('mousedown', this.mouseDown); - - this.getValue = function () { - return self.value; - } - - this.updateValue = function (value) { - self.value = value; - - self.obj.classList.remove("checked"); - if (self.value == "True") { - self.obj.classList.add("checked"); - } - } - - this.updateValue(this.value); - - return { - name: this.name, - value: this.getValue, - updateValue: this.updateValue - } -} - -// Add own menu -{ - let l_block = document.createElement('div'); - l_block.innerHTML = ` -
-
Desktop Head Tracking
-
-
- -
-
Enabled:
-
-
-
-
- -
-
Use head tracking:
-
-
-
-
- -
-
Use eyes tracking:
-
-
-
-
- -
-
Use blinking:
-
-
-
-
- -
-
Mirrored movement:
-
-
-
-
- -
-
Movement smoothing:
-
-
-
-
- -
-
Override face tracking:
-
-
-
-
- `; - document.getElementById('settings-implementation').appendChild(l_block); - - // Update sliders in new menu block - let l_sliders = l_block.querySelectorAll('.inp_slider'); - for (var i = 0; i < l_sliders.length; i++) { - g_modSettingsDHT[g_modSettingsDHT.length] = new inp_slider_mod_dht(l_sliders[i], 'MelonMod_DHT_Call_InpSlider'); - } - - // Update toggles in new menu block - let l_toggles = l_block.querySelectorAll('.inp_toggle'); - for (var i = 0; i < l_toggles.length; i++) { - g_modSettingsDHT[g_modSettingsDHT.length] = new inp_toggle_mod_dht(l_toggles[i], 'MelonMod_DHT_Call_InpToggle'); - } -} +// Add settings +var g_modSettingsDHT = []; + +engine.on('updateModSettingDHT', function (_name, _value) { + for (var i = 0; i < g_modSettingsDHT.length; i++) { + if (g_modSettingsDHT[i].name == _name) { + g_modSettingsDHT[i].updateValue(_value); + break; + } + } +}); + +// Modified from original `inp` types, because I have no js knowledge to hook stuff +function inp_slider_mod_dht(_obj, _callbackName) { + this.obj = _obj; + this.callbackName = _callbackName; + this.minValue = parseFloat(_obj.getAttribute('data-min')); + this.maxValue = parseFloat(_obj.getAttribute('data-max')); + this.percent = 0; + this.value = parseFloat(_obj.getAttribute('data-current')); + this.dragActive = false; + this.name = _obj.id; + this.type = _obj.getAttribute('data-type'); + this.stepSize = _obj.getAttribute('data-stepSize') || 0; + this.format = _obj.getAttribute('data-format') || '{value}'; + + var self = this; + + if (this.stepSize != 0) + this.value = Math.round(this.value / this.stepSize) * this.stepSize; + else + this.value = Math.round(this.value); + + this.valueLabelBackground = document.createElement('div'); + this.valueLabelBackground.className = 'valueLabel background'; + this.valueLabelBackground.innerHTML = this.format.replace('{value}', this.value); + this.obj.appendChild(this.valueLabelBackground); + + this.valueBar = document.createElement('div'); + this.valueBar.className = 'valueBar'; + this.valueBar.setAttribute('style', 'width: ' + (((this.value - this.minValue) / (this.maxValue - this.minValue)) * 100) + '%;'); + this.obj.appendChild(this.valueBar); + + this.valueLabelForeground = document.createElement('div'); + this.valueLabelForeground.className = 'valueLabel foreground'; + this.valueLabelForeground.innerHTML = this.format.replace('{value}', this.value); + this.valueLabelForeground.setAttribute('style', 'width: ' + (1.0 / ((this.value - this.minValue) / (this.maxValue - this.minValue)) * 100) + '%;'); + this.valueBar.appendChild(this.valueLabelForeground); + + this.mouseDown = function (_e) { + self.dragActive = true; + self.mouseMove(_e, false); + } + + this.mouseMove = function (_e, _write) { + if (self.dragActive) { + var rect = _obj.getBoundingClientRect(); + var start = rect.left; + var end = rect.right; + self.percent = Math.min(Math.max((_e.clientX - start) / rect.width, 0), 1); + var value = self.percent; + value *= (self.maxValue - self.minValue); + value += self.minValue; + if (self.stepSize != 0) { + value = Math.round(value / self.stepSize); + self.value = value * self.stepSize; + self.percent = (self.value - self.minValue) / (self.maxValue - self.minValue); + } + else + self.value = Math.round(value); + + self.valueBar.setAttribute('style', 'width: ' + (self.percent * 100) + '%;'); + self.valueLabelForeground.setAttribute('style', 'width: ' + (1.0 / self.percent * 100) + '%;'); + self.valueLabelBackground.innerHTML = self.valueLabelForeground.innerHTML = self.format.replace('{value}', self.value); + + engine.call(self.callbackName, self.name, "" + self.value); + self.displayImperial(); + } + } + + this.mouseUp = function (_e) { + self.mouseMove(_e, true); + self.dragActive = false; + } + + _obj.addEventListener('mousedown', this.mouseDown); + document.addEventListener('mousemove', this.mouseMove); + document.addEventListener('mouseup', this.mouseUp); + + this.getValue = function () { + return self.value; + } + + this.updateValue = function (value) { + if (self.stepSize != 0) + self.value = Math.round(value * self.stepSize) / self.stepSize; + else + self.value = Math.round(value); + self.percent = (self.value - self.minValue) / (self.maxValue - self.minValue); + self.valueBar.setAttribute('style', 'width: ' + (self.percent * 100) + '%;'); + self.valueLabelForeground.setAttribute('style', 'width: ' + (1.0 / self.percent * 100) + '%;'); + self.valueLabelBackground.innerHTML = self.valueLabelForeground.innerHTML = self.format.replace('{value}', self.value); + self.displayImperial(); + } + + this.displayImperial = function () { + var displays = document.querySelectorAll('.imperialDisplay'); + for (var i = 0; i < displays.length; i++) { + var binding = displays[i].getAttribute('data-binding'); + if (binding == self.name) { + var realFeet = ((self.value * 0.393700) / 12); + var feet = Math.floor(realFeet); + var inches = Math.floor((realFeet - feet) * 12); + displays[i].innerHTML = feet + "'" + inches + ''''; + } + } + } + + return { + name: this.name, + value: this.getValue, + updateValue: this.updateValue + } +} + +// Modified from original `inp` types, because I have no js knowledge to hook stuff +function inp_toggle_mod_dht(_obj, _callbackName) { + this.obj = _obj; + this.callbackName = _callbackName; + this.value = _obj.getAttribute('data-current'); + this.name = _obj.id; + this.type = _obj.getAttribute('data-type'); + + var self = this; + + this.mouseDown = function (_e) { + self.value = self.value == "True" ? "False" : "True"; + self.updateState(); + } + + this.updateState = function () { + self.obj.classList.remove("checked"); + if (self.value == "True") { + self.obj.classList.add("checked"); + } + + engine.call(self.callbackName, self.name, self.value); + } + + _obj.addEventListener('mousedown', this.mouseDown); + + this.getValue = function () { + return self.value; + } + + this.updateValue = function (value) { + self.value = value; + + self.obj.classList.remove("checked"); + if (self.value == "True") { + self.obj.classList.add("checked"); + } + } + + this.updateValue(this.value); + + return { + name: this.name, + value: this.getValue, + updateValue: this.updateValue + } +} + +// Add own menu +{ + let l_block = document.createElement('div'); + l_block.innerHTML = ` +
+
Desktop Head Tracking
+
+
+ +
+
Enabled:
+
+
+
+
+ +
+
Use head tracking:
+
+
+
+
+ +
+
Use eyes tracking:
+
+
+
+
+ +
+
Use blinking:
+
+
+
+
+ +
+
Mirrored movement:
+
+
+
+
+ +
+
Movement smoothing:
+
+
+
+
+ +
+
Override face tracking:
+
+
+
+
+ `; + document.getElementById('settings-implementation').appendChild(l_block); + + // Update sliders in new menu block + let l_sliders = l_block.querySelectorAll('.inp_slider'); + for (var i = 0; i < l_sliders.length; i++) { + g_modSettingsDHT[g_modSettingsDHT.length] = new inp_slider_mod_dht(l_sliders[i], 'MelonMod_DHT_Call_InpSlider'); + } + + // Update toggles in new menu block + let l_toggles = l_block.querySelectorAll('.inp_toggle'); + for (var i = 0; i < l_toggles.length; i++) { + g_modSettingsDHT[g_modSettingsDHT.length] = new inp_toggle_mod_dht(l_toggles[i], 'MelonMod_DHT_Call_InpToggle'); + } +} diff --git a/ml_prm/AvatarBoolParameter.cs b/archived/ml_prm/AvatarBoolParameter.cs similarity index 96% rename from ml_prm/AvatarBoolParameter.cs rename to archived/ml_prm/AvatarBoolParameter.cs index b7a9535..cfc8fdb 100644 --- a/ml_prm/AvatarBoolParameter.cs +++ b/archived/ml_prm/AvatarBoolParameter.cs @@ -1,43 +1,43 @@ -using ABI_RC.Core; -using System.Text.RegularExpressions; -using UnityEngine; - -namespace ml_prm -{ - class AvatarBoolParameter - { - public readonly string m_name; - public readonly int m_hash = 0; - public readonly bool m_sync; - readonly CVRAnimatorManager m_manager = null; - - public AvatarBoolParameter(string p_name, CVRAnimatorManager p_manager) - { - m_name = p_name; - m_manager = p_manager; - - Regex l_regex = new Regex("^#?" + p_name + '$'); - foreach(var l_param in m_manager.animator.parameters) - { - if(l_regex.IsMatch(l_param.name) && (l_param.type == AnimatorControllerParameterType.Bool)) - { - m_name = l_param.name; - m_hash = l_param.nameHash; - m_sync = (l_param.name[0] != '#'); - break; - } - } - } - - public void SetValue(bool p_value) - { - if(m_hash != 0) - { - if(m_sync) - m_manager.SetAnimatorParameterBool(m_name, p_value); - else - m_manager.animator.SetBool(m_hash, p_value); - } - } - } -} +using ABI_RC.Core; +using System.Text.RegularExpressions; +using UnityEngine; + +namespace ml_prm +{ + class AvatarBoolParameter + { + public readonly string m_name; + public readonly int m_hash = 0; + public readonly bool m_sync; + readonly CVRAnimatorManager m_manager = null; + + public AvatarBoolParameter(string p_name, CVRAnimatorManager p_manager) + { + m_name = p_name; + m_manager = p_manager; + + Regex l_regex = new Regex("^#?" + p_name + '$'); + foreach(var l_param in m_manager.animator.parameters) + { + if(l_regex.IsMatch(l_param.name) && (l_param.type == AnimatorControllerParameterType.Bool)) + { + m_name = l_param.name; + m_hash = l_param.nameHash; + m_sync = (l_param.name[0] != '#'); + break; + } + } + } + + public void SetValue(bool p_value) + { + if(m_hash != 0) + { + if(m_sync) + m_manager.SetAnimatorParameterBool(m_name, p_value); + else + m_manager.animator.SetBool(m_hash, p_value); + } + } + } +} diff --git a/ml_prm/Main.cs b/archived/ml_prm/Main.cs similarity index 97% rename from ml_prm/Main.cs rename to archived/ml_prm/Main.cs index 785bfc2..d043e0b 100644 --- a/ml_prm/Main.cs +++ b/archived/ml_prm/Main.cs @@ -1,216 +1,216 @@ -using ABI.CCK.Components; -using ABI_RC.Core; -using ABI_RC.Core.InteractionSystem; -using ABI_RC.Core.Player; -using ABI_RC.Core.Util.AssetFiltering; -using ABI_RC.Systems.IK.SubSystems; -using ABI_RC.Systems.MovementSystem; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Reflection; - -namespace ml_prm -{ - public class PlayerRagdollMod : MelonLoader.MelonMod - { - static PlayerRagdollMod ms_instance = null; - - RagdollController m_localController = null; - - public override void OnInitializeMelon() - { - if(ms_instance == null) - ms_instance = this; - - Settings.Init(); - ModUi.Init(); - - HarmonyInstance.Patch( - typeof(PlayerSetup).GetMethod(nameof(PlayerSetup.ClearAvatar)), - null, - new HarmonyLib.HarmonyMethod(typeof(PlayerRagdollMod).GetMethod(nameof(OnAvatarClear_Postfix), BindingFlags.NonPublic | BindingFlags.Static)) - ); - HarmonyInstance.Patch( - typeof(PlayerSetup).GetMethod(nameof(PlayerSetup.SetupAvatar)), - null, - new HarmonyLib.HarmonyMethod(typeof(PlayerRagdollMod).GetMethod(nameof(OnSetupAvatar_Postfix), BindingFlags.Static | BindingFlags.NonPublic)) - ); - HarmonyInstance.Patch( - typeof(PlayerSetup).GetMethod("SetupIKScaling", BindingFlags.NonPublic | BindingFlags.Instance), - null, - new HarmonyLib.HarmonyMethod(typeof(PlayerRagdollMod).GetMethod(nameof(OnSetupIKScaling_Postfix), BindingFlags.Static | BindingFlags.NonPublic)) - ); - HarmonyInstance.Patch( - typeof(CVRSeat).GetMethod(nameof(CVRSeat.SitDown)), - new HarmonyLib.HarmonyMethod(typeof(PlayerRagdollMod).GetMethod(nameof(OnCVRSeatSitDown_Prefix), BindingFlags.Static | BindingFlags.NonPublic)), - null - ); - HarmonyInstance.Patch( - typeof(BodySystem).GetMethod(nameof(BodySystem.StartCalibration)), - new HarmonyLib.HarmonyMethod(typeof(PlayerRagdollMod).GetMethod(nameof(OnStartCalibration_Prefix), BindingFlags.Static | BindingFlags.NonPublic)), - null - ); - HarmonyInstance.Patch( - typeof(RootLogic).GetMethod(nameof(RootLogic.SpawnOnWorldInstance)), - new HarmonyLib.HarmonyMethod(typeof(PlayerRagdollMod).GetMethod(nameof(OnWorldSpawn_Prefix), BindingFlags.Static | BindingFlags.NonPublic)), - null - ); - HarmonyInstance.Patch( - typeof(CombatSystem).GetMethods().First(m => (!m.IsGenericMethod && m.Name == nameof(CombatSystem.Down))), - new HarmonyLib.HarmonyMethod(typeof(PlayerRagdollMod).GetMethod(nameof(OnCombatDown_Prefix), BindingFlags.Static | BindingFlags.NonPublic)), - null - ); - HarmonyInstance.Patch( - typeof(MovementSystem).GetMethod(nameof(MovementSystem.ChangeFlight)), - null, - new HarmonyLib.HarmonyMethod(typeof(PlayerRagdollMod).GetMethod(nameof(OnChangeFlight_Postfix), BindingFlags.Static | BindingFlags.NonPublic)) - ); - - // Whitelist the toggle script - (typeof(SharedFilter).GetField("_localComponentWhitelist", BindingFlags.NonPublic | BindingFlags.Static)?.GetValue(null) as HashSet)?.Add(typeof(RagdollToggle)); - - MelonLoader.MelonCoroutines.Start(WaitForLocalPlayer()); - } - - public override void OnDeinitializeMelon() - { - if(ms_instance == this) - ms_instance = null; - - m_localController = null; - } - - System.Collections.IEnumerator WaitForLocalPlayer() - { - while(PlayerSetup.Instance == null) - yield return null; - - m_localController = PlayerSetup.Instance.gameObject.AddComponent(); - ModUi.SwitchChange += this.OnSwitchActivation; - } - - void OnSwitchActivation() - { - if(m_localController != null) - m_localController.SwitchRagdoll(); - } - - // Patches - static void OnAvatarClear_Postfix() => ms_instance?.OnAvatarClear(); - void OnAvatarClear() - { - try - { - if(m_localController != null) - m_localController.OnAvatarClear(); - } - catch(Exception e) - { - MelonLoader.MelonLogger.Error(e); - } - } - - static void OnSetupAvatar_Postfix() => ms_instance?.OnSetupAvatar(); - void OnSetupAvatar() - { - try - { - if(m_localController != null) - m_localController.OnAvatarSetup(); - } - catch(Exception e) - { - MelonLoader.MelonLogger.Error(e); - } - } - - static void OnSetupIKScaling_Postfix(ref UnityEngine.Vector3 ___scaleDifference) => ms_instance?.OnSetupIKScaling(___scaleDifference.y); - void OnSetupIKScaling(float p_scaleDifference) - { - try - { - if(m_localController != null) - m_localController.OnAvatarScaling(1f + p_scaleDifference); - } - catch(Exception e) - { - MelonLoader.MelonLogger.Error(e); - } - } - - static void OnCVRSeatSitDown_Prefix(ref CVRSeat __instance) => ms_instance?.OnCVRSeatSitDown(__instance); - void OnCVRSeatSitDown(CVRSeat p_seat) - { - try - { - if(m_localController != null) - m_localController.OnSeatSitDown(p_seat); - } - catch(Exception e) - { - MelonLoader.MelonLogger.Error(e); - } - } - - static void OnStartCalibration_Prefix() => ms_instance?.OnStartCalibration(); - void OnStartCalibration() - { - try - { - if(m_localController != null) - m_localController.OnStartCalibration(); - } - catch(Exception e) - { - MelonLoader.MelonLogger.Error(e); - } - } - - static void OnWorldSpawn_Prefix() => ms_instance?.OnWorldSpawn(); - void OnWorldSpawn() - { - try - { - if(m_localController != null) - m_localController.OnWorldSpawn(); - } - catch(Exception e) - { - MelonLoader.MelonLogger.Error(e); - } - } - - static void OnCombatDown_Prefix(ref CombatSystem __instance) - { - if((__instance == CombatSystem.Instance) && !__instance.isDown) - ms_instance?.OnCombatDown(); - } - void OnCombatDown() - { - try - { - if(m_localController != null) - m_localController.OnCombatDown(); - } - catch(Exception e) - { - MelonLoader.MelonLogger.Error(e); - } - } - - static void OnChangeFlight_Postfix() => ms_instance?.OnChangeFlight(); - void OnChangeFlight() - { - try - { - if(m_localController != null) - m_localController.OnChangeFlight(); - } - catch(Exception e) - { - MelonLoader.MelonLogger.Error(e); - } - } - } -} +using ABI.CCK.Components; +using ABI_RC.Core; +using ABI_RC.Core.InteractionSystem; +using ABI_RC.Core.Player; +using ABI_RC.Core.Util.AssetFiltering; +using ABI_RC.Systems.IK.SubSystems; +using ABI_RC.Systems.MovementSystem; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Reflection; + +namespace ml_prm +{ + public class PlayerRagdollMod : MelonLoader.MelonMod + { + static PlayerRagdollMod ms_instance = null; + + RagdollController m_localController = null; + + public override void OnInitializeMelon() + { + if(ms_instance == null) + ms_instance = this; + + Settings.Init(); + ModUi.Init(); + + HarmonyInstance.Patch( + typeof(PlayerSetup).GetMethod(nameof(PlayerSetup.ClearAvatar)), + null, + new HarmonyLib.HarmonyMethod(typeof(PlayerRagdollMod).GetMethod(nameof(OnAvatarClear_Postfix), BindingFlags.NonPublic | BindingFlags.Static)) + ); + HarmonyInstance.Patch( + typeof(PlayerSetup).GetMethod(nameof(PlayerSetup.SetupAvatar)), + null, + new HarmonyLib.HarmonyMethod(typeof(PlayerRagdollMod).GetMethod(nameof(OnSetupAvatar_Postfix), BindingFlags.Static | BindingFlags.NonPublic)) + ); + HarmonyInstance.Patch( + typeof(PlayerSetup).GetMethod("SetupIKScaling", BindingFlags.NonPublic | BindingFlags.Instance), + null, + new HarmonyLib.HarmonyMethod(typeof(PlayerRagdollMod).GetMethod(nameof(OnSetupIKScaling_Postfix), BindingFlags.Static | BindingFlags.NonPublic)) + ); + HarmonyInstance.Patch( + typeof(CVRSeat).GetMethod(nameof(CVRSeat.SitDown)), + new HarmonyLib.HarmonyMethod(typeof(PlayerRagdollMod).GetMethod(nameof(OnCVRSeatSitDown_Prefix), BindingFlags.Static | BindingFlags.NonPublic)), + null + ); + HarmonyInstance.Patch( + typeof(BodySystem).GetMethod(nameof(BodySystem.StartCalibration)), + new HarmonyLib.HarmonyMethod(typeof(PlayerRagdollMod).GetMethod(nameof(OnStartCalibration_Prefix), BindingFlags.Static | BindingFlags.NonPublic)), + null + ); + HarmonyInstance.Patch( + typeof(RootLogic).GetMethod(nameof(RootLogic.SpawnOnWorldInstance)), + new HarmonyLib.HarmonyMethod(typeof(PlayerRagdollMod).GetMethod(nameof(OnWorldSpawn_Prefix), BindingFlags.Static | BindingFlags.NonPublic)), + null + ); + HarmonyInstance.Patch( + typeof(CombatSystem).GetMethods().First(m => (!m.IsGenericMethod && m.Name == nameof(CombatSystem.Down))), + new HarmonyLib.HarmonyMethod(typeof(PlayerRagdollMod).GetMethod(nameof(OnCombatDown_Prefix), BindingFlags.Static | BindingFlags.NonPublic)), + null + ); + HarmonyInstance.Patch( + typeof(MovementSystem).GetMethod(nameof(MovementSystem.ChangeFlight)), + null, + new HarmonyLib.HarmonyMethod(typeof(PlayerRagdollMod).GetMethod(nameof(OnChangeFlight_Postfix), BindingFlags.Static | BindingFlags.NonPublic)) + ); + + // Whitelist the toggle script + (typeof(SharedFilter).GetField("_localComponentWhitelist", BindingFlags.NonPublic | BindingFlags.Static)?.GetValue(null) as HashSet)?.Add(typeof(RagdollToggle)); + + MelonLoader.MelonCoroutines.Start(WaitForLocalPlayer()); + } + + public override void OnDeinitializeMelon() + { + if(ms_instance == this) + ms_instance = null; + + m_localController = null; + } + + System.Collections.IEnumerator WaitForLocalPlayer() + { + while(PlayerSetup.Instance == null) + yield return null; + + m_localController = PlayerSetup.Instance.gameObject.AddComponent(); + ModUi.SwitchChange += this.OnSwitchActivation; + } + + void OnSwitchActivation() + { + if(m_localController != null) + m_localController.SwitchRagdoll(); + } + + // Patches + static void OnAvatarClear_Postfix() => ms_instance?.OnAvatarClear(); + void OnAvatarClear() + { + try + { + if(m_localController != null) + m_localController.OnAvatarClear(); + } + catch(Exception e) + { + MelonLoader.MelonLogger.Error(e); + } + } + + static void OnSetupAvatar_Postfix() => ms_instance?.OnSetupAvatar(); + void OnSetupAvatar() + { + try + { + if(m_localController != null) + m_localController.OnAvatarSetup(); + } + catch(Exception e) + { + MelonLoader.MelonLogger.Error(e); + } + } + + static void OnSetupIKScaling_Postfix(ref UnityEngine.Vector3 ___scaleDifference) => ms_instance?.OnSetupIKScaling(___scaleDifference.y); + void OnSetupIKScaling(float p_scaleDifference) + { + try + { + if(m_localController != null) + m_localController.OnAvatarScaling(1f + p_scaleDifference); + } + catch(Exception e) + { + MelonLoader.MelonLogger.Error(e); + } + } + + static void OnCVRSeatSitDown_Prefix(ref CVRSeat __instance) => ms_instance?.OnCVRSeatSitDown(__instance); + void OnCVRSeatSitDown(CVRSeat p_seat) + { + try + { + if(m_localController != null) + m_localController.OnSeatSitDown(p_seat); + } + catch(Exception e) + { + MelonLoader.MelonLogger.Error(e); + } + } + + static void OnStartCalibration_Prefix() => ms_instance?.OnStartCalibration(); + void OnStartCalibration() + { + try + { + if(m_localController != null) + m_localController.OnStartCalibration(); + } + catch(Exception e) + { + MelonLoader.MelonLogger.Error(e); + } + } + + static void OnWorldSpawn_Prefix() => ms_instance?.OnWorldSpawn(); + void OnWorldSpawn() + { + try + { + if(m_localController != null) + m_localController.OnWorldSpawn(); + } + catch(Exception e) + { + MelonLoader.MelonLogger.Error(e); + } + } + + static void OnCombatDown_Prefix(ref CombatSystem __instance) + { + if((__instance == CombatSystem.Instance) && !__instance.isDown) + ms_instance?.OnCombatDown(); + } + void OnCombatDown() + { + try + { + if(m_localController != null) + m_localController.OnCombatDown(); + } + catch(Exception e) + { + MelonLoader.MelonLogger.Error(e); + } + } + + static void OnChangeFlight_Postfix() => ms_instance?.OnChangeFlight(); + void OnChangeFlight() + { + try + { + if(m_localController != null) + m_localController.OnChangeFlight(); + } + catch(Exception e) + { + MelonLoader.MelonLogger.Error(e); + } + } + } +} diff --git a/ml_prm/ModUi.cs b/archived/ml_prm/ModUi.cs similarity index 98% rename from ml_prm/ModUi.cs rename to archived/ml_prm/ModUi.cs index 2a77f31..cca7f58 100644 --- a/ml_prm/ModUi.cs +++ b/archived/ml_prm/ModUi.cs @@ -1,198 +1,198 @@ -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Reflection; - -namespace ml_prm -{ - static class ModUi - { - enum UiIndex - { - Hotkey = 0, - Gravity, - PointersReaction, - IgnoreLocal, - CombatReaction, - AutoRecover, - Slipperiness, - Bounciness, - ViewVelocity, - JumpRecover, - VelocityMultiplier, - MovementDrag, - AngularDrag, - RecoverDelay - } - - static public event Action SwitchChange; - - static List ms_uiElements = null; - - internal static void Init() - { - ms_uiElements = new List(); - - if(MelonLoader.MelonMod.RegisteredMelons.FirstOrDefault(m => m.Info.Name == "BTKUILib") != null) - CreateUi(); - } - - // Separated method, otherwise exception is thrown, funny CSharp and optional references, smh - static void CreateUi() - { - BTKUILib.QuickMenuAPI.PrepareIcon("PlayerRagdollMod", "PRM-Person", GetIconStream("person.png")); - - var l_modRoot = new BTKUILib.UIObjects.Page("PlayerRagdollMod", "MainPage", true, "PRM-Person"); - l_modRoot.MenuTitle = "Player Ragdoll Mod"; - l_modRoot.MenuSubtitle = "Become a ragdoll and change various settings for people amusement"; - - var l_modCategory = l_modRoot.AddCategory("Settings"); - - l_modCategory.AddButton("Switch ragdoll", "PRM-Person", "Switch between normal and ragdoll state").OnPress += () => SwitchChange?.Invoke(); - - ms_uiElements.Add(l_modCategory.AddToggle("Use hotkey", "Switch ragdoll mode with 'R' key", Settings.Hotkey)); - (ms_uiElements[(int)UiIndex.Hotkey] as BTKUILib.UIObjects.Components.ToggleButton).OnValueUpdated += (state) => OnToggleUpdate(UiIndex.Hotkey, state); - - ms_uiElements.Add(l_modCategory.AddToggle("Use gravity", "Apply gravity to ragdoll", Settings.Gravity)); - (ms_uiElements[(int)UiIndex.Gravity] as BTKUILib.UIObjects.Components.ToggleButton).OnValueUpdated += (state) => OnToggleUpdate(UiIndex.Gravity, state); - - ms_uiElements.Add(l_modCategory.AddToggle("Pointers reaction", "React to trigger colliders with CVRPointer component of 'ragdoll' type", Settings.PointersReaction)); - (ms_uiElements[(int)UiIndex.PointersReaction] as BTKUILib.UIObjects.Components.ToggleButton).OnValueUpdated += (state) => OnToggleUpdate(UiIndex.PointersReaction, state); - - ms_uiElements.Add(l_modCategory.AddToggle("Ignore local pointers", "Ignore local avatar's CVRPointer components of 'ragdoll' type", Settings.IgnoreLocal)); - (ms_uiElements[(int)UiIndex.IgnoreLocal] as BTKUILib.UIObjects.Components.ToggleButton).OnValueUpdated += (state) => OnToggleUpdate(UiIndex.IgnoreLocal, state); - - ms_uiElements.Add(l_modCategory.AddToggle("Combat reaction", "Ragdoll upon combat system death", Settings.CombatReaction)); - (ms_uiElements[(int)UiIndex.CombatReaction] as BTKUILib.UIObjects.Components.ToggleButton).OnValueUpdated += (state) => OnToggleUpdate(UiIndex.CombatReaction, state); - - ms_uiElements.Add(l_modCategory.AddToggle("Auto recover", "Automatically unragdoll after set recover delay", Settings.AutoRecover)); - (ms_uiElements[(int)UiIndex.AutoRecover] as BTKUILib.UIObjects.Components.ToggleButton).OnValueUpdated += (state) => OnToggleUpdate(UiIndex.AutoRecover, state); - - ms_uiElements.Add(l_modCategory.AddToggle("Slipperiness", "Enables/disables friction of ragdoll", Settings.Slipperiness)); - (ms_uiElements[(int)UiIndex.Slipperiness] as BTKUILib.UIObjects.Components.ToggleButton).OnValueUpdated += (state) => OnToggleUpdate(UiIndex.Slipperiness, state); - - ms_uiElements.Add(l_modCategory.AddToggle("Bounciness", "Enables/disables bounciness of ragdoll", Settings.Bounciness)); - (ms_uiElements[(int)UiIndex.Bounciness] as BTKUILib.UIObjects.Components.ToggleButton).OnValueUpdated += (state) => OnToggleUpdate(UiIndex.Bounciness, state); - - ms_uiElements.Add(l_modCategory.AddToggle("View direction velocity", "Apply velocity to camera view direction", Settings.ViewVelocity)); - (ms_uiElements[(int)UiIndex.ViewVelocity] as BTKUILib.UIObjects.Components.ToggleButton).OnValueUpdated += (state) => OnToggleUpdate(UiIndex.ViewVelocity, state); - - ms_uiElements.Add(l_modCategory.AddToggle("Jump recover", "Recover from ragdoll state by jumping", Settings.JumpRecover)); - (ms_uiElements[(int)UiIndex.JumpRecover] as BTKUILib.UIObjects.Components.ToggleButton).OnValueUpdated += (state) => OnToggleUpdate(UiIndex.JumpRecover, state); - - ms_uiElements.Add(l_modRoot.AddSlider("Velocity multiplier", "Velocity multiplier upon entering ragdoll state", Settings.VelocityMultiplier, 1f, 50f)); - (ms_uiElements[(int)UiIndex.VelocityMultiplier] as BTKUILib.UIObjects.Components.SliderFloat).OnValueUpdated += (value) => OnSliderUpdate(UiIndex.VelocityMultiplier, value); - - ms_uiElements.Add(l_modRoot.AddSlider("Movement drag", "Movement resistance", Settings.MovementDrag, 0f, 50f)); - (ms_uiElements[(int)UiIndex.MovementDrag] as BTKUILib.UIObjects.Components.SliderFloat).OnValueUpdated += (value) => OnSliderUpdate(UiIndex.MovementDrag, value); - - ms_uiElements.Add(l_modRoot.AddSlider("Angular movement drag", "Rotation movement resistance", Settings.AngularDrag, 0f, 50f)); - (ms_uiElements[(int)UiIndex.AngularDrag] as BTKUILib.UIObjects.Components.SliderFloat).OnValueUpdated += (value) => OnSliderUpdate(UiIndex.AngularDrag, value); - - ms_uiElements.Add(l_modRoot.AddSlider("Recover delay (seconds)", "Recover delay for automatic recover", Settings.RecoverDelay, 1f, 10f)); - (ms_uiElements[(int)UiIndex.RecoverDelay] as BTKUILib.UIObjects.Components.SliderFloat).OnValueUpdated += (value) => OnSliderUpdate(UiIndex.RecoverDelay, value); - - l_modCategory.AddButton("Reset settings", "", "Reset mod settings to default").OnPress += Reset; - } - - static void OnToggleUpdate(UiIndex p_index, bool p_state, bool p_force = false) - { - switch(p_index) - { - case UiIndex.Hotkey: - Settings.SetSetting(Settings.ModSetting.Hotkey, p_state); - break; - - case UiIndex.Gravity: - Settings.SetSetting(Settings.ModSetting.Gravity, p_state); - break; - - case UiIndex.PointersReaction: - Settings.SetSetting(Settings.ModSetting.PointersReaction, p_state); - break; - - case UiIndex.IgnoreLocal: - Settings.SetSetting(Settings.ModSetting.IgnoreLocal, p_state); - break; - - case UiIndex.CombatReaction: - Settings.SetSetting(Settings.ModSetting.CombatReaction, p_state); - break; - - case UiIndex.AutoRecover: - Settings.SetSetting(Settings.ModSetting.AutoRecover, p_state); - break; - - case UiIndex.Slipperiness: - Settings.SetSetting(Settings.ModSetting.Slipperiness, p_state); - break; - - case UiIndex.Bounciness: - Settings.SetSetting(Settings.ModSetting.Bounciness, p_state); - break; - - case UiIndex.ViewVelocity: - Settings.SetSetting(Settings.ModSetting.ViewVelocity, p_state); - break; - - case UiIndex.JumpRecover: - Settings.SetSetting(Settings.ModSetting.JumpRecover, p_state); - break; - } - - if(p_force) - (ms_uiElements[(int)p_index] as BTKUILib.UIObjects.Components.ToggleButton).ToggleValue = p_state; - } - - static void OnSliderUpdate(UiIndex p_index, float p_value, bool p_force = false) - { - switch(p_index) - { - case UiIndex.VelocityMultiplier: - Settings.SetSetting(Settings.ModSetting.VelocityMultiplier, p_value); - break; - - case UiIndex.MovementDrag: - Settings.SetSetting(Settings.ModSetting.MovementDrag, p_value); - break; - - case UiIndex.AngularDrag: - Settings.SetSetting(Settings.ModSetting.AngularDrag, p_value); - break; - - case UiIndex.RecoverDelay: - Settings.SetSetting(Settings.ModSetting.RecoverDelay, p_value); - break; - } - - if(p_force) - (ms_uiElements[(int)p_index] as BTKUILib.UIObjects.Components.SliderFloat).SetSliderValue(p_value); - } - - static void Reset() - { - OnToggleUpdate(UiIndex.Hotkey, true, true); - OnToggleUpdate(UiIndex.Gravity, true, true); - OnToggleUpdate(UiIndex.PointersReaction, true, true); - OnToggleUpdate(UiIndex.IgnoreLocal, true, true); - OnToggleUpdate(UiIndex.CombatReaction, true, true); - OnToggleUpdate(UiIndex.AutoRecover, false, true); - OnToggleUpdate(UiIndex.Slipperiness, false, true); - OnToggleUpdate(UiIndex.Bounciness, false, true); - OnToggleUpdate(UiIndex.ViewVelocity, false, true); - OnToggleUpdate(UiIndex.JumpRecover, false, true); - OnSliderUpdate(UiIndex.VelocityMultiplier, 2f, true); - OnSliderUpdate(UiIndex.MovementDrag, 2f, true); - OnSliderUpdate(UiIndex.AngularDrag, 2f, true); - OnSliderUpdate(UiIndex.RecoverDelay, 3f, true); - } - - static Stream GetIconStream(string p_name) - { - Assembly l_assembly = Assembly.GetExecutingAssembly(); - string l_assemblyName = l_assembly.GetName().Name; - return l_assembly.GetManifestResourceStream(l_assemblyName + ".resources." + p_name); - } - } -} +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Reflection; + +namespace ml_prm +{ + static class ModUi + { + enum UiIndex + { + Hotkey = 0, + Gravity, + PointersReaction, + IgnoreLocal, + CombatReaction, + AutoRecover, + Slipperiness, + Bounciness, + ViewVelocity, + JumpRecover, + VelocityMultiplier, + MovementDrag, + AngularDrag, + RecoverDelay + } + + static public event Action SwitchChange; + + static List ms_uiElements = null; + + internal static void Init() + { + ms_uiElements = new List(); + + if(MelonLoader.MelonMod.RegisteredMelons.FirstOrDefault(m => m.Info.Name == "BTKUILib") != null) + CreateUi(); + } + + // Separated method, otherwise exception is thrown, funny CSharp and optional references, smh + static void CreateUi() + { + BTKUILib.QuickMenuAPI.PrepareIcon("PlayerRagdollMod", "PRM-Person", GetIconStream("person.png")); + + var l_modRoot = new BTKUILib.UIObjects.Page("PlayerRagdollMod", "MainPage", true, "PRM-Person"); + l_modRoot.MenuTitle = "Player Ragdoll Mod"; + l_modRoot.MenuSubtitle = "Become a ragdoll and change various settings for people amusement"; + + var l_modCategory = l_modRoot.AddCategory("Settings"); + + l_modCategory.AddButton("Switch ragdoll", "PRM-Person", "Switch between normal and ragdoll state").OnPress += () => SwitchChange?.Invoke(); + + ms_uiElements.Add(l_modCategory.AddToggle("Use hotkey", "Switch ragdoll mode with 'R' key", Settings.Hotkey)); + (ms_uiElements[(int)UiIndex.Hotkey] as BTKUILib.UIObjects.Components.ToggleButton).OnValueUpdated += (state) => OnToggleUpdate(UiIndex.Hotkey, state); + + ms_uiElements.Add(l_modCategory.AddToggle("Use gravity", "Apply gravity to ragdoll", Settings.Gravity)); + (ms_uiElements[(int)UiIndex.Gravity] as BTKUILib.UIObjects.Components.ToggleButton).OnValueUpdated += (state) => OnToggleUpdate(UiIndex.Gravity, state); + + ms_uiElements.Add(l_modCategory.AddToggle("Pointers reaction", "React to trigger colliders with CVRPointer component of 'ragdoll' type", Settings.PointersReaction)); + (ms_uiElements[(int)UiIndex.PointersReaction] as BTKUILib.UIObjects.Components.ToggleButton).OnValueUpdated += (state) => OnToggleUpdate(UiIndex.PointersReaction, state); + + ms_uiElements.Add(l_modCategory.AddToggle("Ignore local pointers", "Ignore local avatar's CVRPointer components of 'ragdoll' type", Settings.IgnoreLocal)); + (ms_uiElements[(int)UiIndex.IgnoreLocal] as BTKUILib.UIObjects.Components.ToggleButton).OnValueUpdated += (state) => OnToggleUpdate(UiIndex.IgnoreLocal, state); + + ms_uiElements.Add(l_modCategory.AddToggle("Combat reaction", "Ragdoll upon combat system death", Settings.CombatReaction)); + (ms_uiElements[(int)UiIndex.CombatReaction] as BTKUILib.UIObjects.Components.ToggleButton).OnValueUpdated += (state) => OnToggleUpdate(UiIndex.CombatReaction, state); + + ms_uiElements.Add(l_modCategory.AddToggle("Auto recover", "Automatically unragdoll after set recover delay", Settings.AutoRecover)); + (ms_uiElements[(int)UiIndex.AutoRecover] as BTKUILib.UIObjects.Components.ToggleButton).OnValueUpdated += (state) => OnToggleUpdate(UiIndex.AutoRecover, state); + + ms_uiElements.Add(l_modCategory.AddToggle("Slipperiness", "Enables/disables friction of ragdoll", Settings.Slipperiness)); + (ms_uiElements[(int)UiIndex.Slipperiness] as BTKUILib.UIObjects.Components.ToggleButton).OnValueUpdated += (state) => OnToggleUpdate(UiIndex.Slipperiness, state); + + ms_uiElements.Add(l_modCategory.AddToggle("Bounciness", "Enables/disables bounciness of ragdoll", Settings.Bounciness)); + (ms_uiElements[(int)UiIndex.Bounciness] as BTKUILib.UIObjects.Components.ToggleButton).OnValueUpdated += (state) => OnToggleUpdate(UiIndex.Bounciness, state); + + ms_uiElements.Add(l_modCategory.AddToggle("View direction velocity", "Apply velocity to camera view direction", Settings.ViewVelocity)); + (ms_uiElements[(int)UiIndex.ViewVelocity] as BTKUILib.UIObjects.Components.ToggleButton).OnValueUpdated += (state) => OnToggleUpdate(UiIndex.ViewVelocity, state); + + ms_uiElements.Add(l_modCategory.AddToggle("Jump recover", "Recover from ragdoll state by jumping", Settings.JumpRecover)); + (ms_uiElements[(int)UiIndex.JumpRecover] as BTKUILib.UIObjects.Components.ToggleButton).OnValueUpdated += (state) => OnToggleUpdate(UiIndex.JumpRecover, state); + + ms_uiElements.Add(l_modRoot.AddSlider("Velocity multiplier", "Velocity multiplier upon entering ragdoll state", Settings.VelocityMultiplier, 1f, 50f)); + (ms_uiElements[(int)UiIndex.VelocityMultiplier] as BTKUILib.UIObjects.Components.SliderFloat).OnValueUpdated += (value) => OnSliderUpdate(UiIndex.VelocityMultiplier, value); + + ms_uiElements.Add(l_modRoot.AddSlider("Movement drag", "Movement resistance", Settings.MovementDrag, 0f, 50f)); + (ms_uiElements[(int)UiIndex.MovementDrag] as BTKUILib.UIObjects.Components.SliderFloat).OnValueUpdated += (value) => OnSliderUpdate(UiIndex.MovementDrag, value); + + ms_uiElements.Add(l_modRoot.AddSlider("Angular movement drag", "Rotation movement resistance", Settings.AngularDrag, 0f, 50f)); + (ms_uiElements[(int)UiIndex.AngularDrag] as BTKUILib.UIObjects.Components.SliderFloat).OnValueUpdated += (value) => OnSliderUpdate(UiIndex.AngularDrag, value); + + ms_uiElements.Add(l_modRoot.AddSlider("Recover delay (seconds)", "Recover delay for automatic recover", Settings.RecoverDelay, 1f, 10f)); + (ms_uiElements[(int)UiIndex.RecoverDelay] as BTKUILib.UIObjects.Components.SliderFloat).OnValueUpdated += (value) => OnSliderUpdate(UiIndex.RecoverDelay, value); + + l_modCategory.AddButton("Reset settings", "", "Reset mod settings to default").OnPress += Reset; + } + + static void OnToggleUpdate(UiIndex p_index, bool p_state, bool p_force = false) + { + switch(p_index) + { + case UiIndex.Hotkey: + Settings.SetSetting(Settings.ModSetting.Hotkey, p_state); + break; + + case UiIndex.Gravity: + Settings.SetSetting(Settings.ModSetting.Gravity, p_state); + break; + + case UiIndex.PointersReaction: + Settings.SetSetting(Settings.ModSetting.PointersReaction, p_state); + break; + + case UiIndex.IgnoreLocal: + Settings.SetSetting(Settings.ModSetting.IgnoreLocal, p_state); + break; + + case UiIndex.CombatReaction: + Settings.SetSetting(Settings.ModSetting.CombatReaction, p_state); + break; + + case UiIndex.AutoRecover: + Settings.SetSetting(Settings.ModSetting.AutoRecover, p_state); + break; + + case UiIndex.Slipperiness: + Settings.SetSetting(Settings.ModSetting.Slipperiness, p_state); + break; + + case UiIndex.Bounciness: + Settings.SetSetting(Settings.ModSetting.Bounciness, p_state); + break; + + case UiIndex.ViewVelocity: + Settings.SetSetting(Settings.ModSetting.ViewVelocity, p_state); + break; + + case UiIndex.JumpRecover: + Settings.SetSetting(Settings.ModSetting.JumpRecover, p_state); + break; + } + + if(p_force) + (ms_uiElements[(int)p_index] as BTKUILib.UIObjects.Components.ToggleButton).ToggleValue = p_state; + } + + static void OnSliderUpdate(UiIndex p_index, float p_value, bool p_force = false) + { + switch(p_index) + { + case UiIndex.VelocityMultiplier: + Settings.SetSetting(Settings.ModSetting.VelocityMultiplier, p_value); + break; + + case UiIndex.MovementDrag: + Settings.SetSetting(Settings.ModSetting.MovementDrag, p_value); + break; + + case UiIndex.AngularDrag: + Settings.SetSetting(Settings.ModSetting.AngularDrag, p_value); + break; + + case UiIndex.RecoverDelay: + Settings.SetSetting(Settings.ModSetting.RecoverDelay, p_value); + break; + } + + if(p_force) + (ms_uiElements[(int)p_index] as BTKUILib.UIObjects.Components.SliderFloat).SetSliderValue(p_value); + } + + static void Reset() + { + OnToggleUpdate(UiIndex.Hotkey, true, true); + OnToggleUpdate(UiIndex.Gravity, true, true); + OnToggleUpdate(UiIndex.PointersReaction, true, true); + OnToggleUpdate(UiIndex.IgnoreLocal, true, true); + OnToggleUpdate(UiIndex.CombatReaction, true, true); + OnToggleUpdate(UiIndex.AutoRecover, false, true); + OnToggleUpdate(UiIndex.Slipperiness, false, true); + OnToggleUpdate(UiIndex.Bounciness, false, true); + OnToggleUpdate(UiIndex.ViewVelocity, false, true); + OnToggleUpdate(UiIndex.JumpRecover, false, true); + OnSliderUpdate(UiIndex.VelocityMultiplier, 2f, true); + OnSliderUpdate(UiIndex.MovementDrag, 2f, true); + OnSliderUpdate(UiIndex.AngularDrag, 2f, true); + OnSliderUpdate(UiIndex.RecoverDelay, 3f, true); + } + + static Stream GetIconStream(string p_name) + { + Assembly l_assembly = Assembly.GetExecutingAssembly(); + string l_assemblyName = l_assembly.GetName().Name; + return l_assembly.GetManifestResourceStream(l_assemblyName + ".resources." + p_name); + } + } +} diff --git a/ml_prm/Properties/AssemblyInfo.cs b/archived/ml_prm/Properties/AssemblyInfo.cs similarity index 100% rename from ml_prm/Properties/AssemblyInfo.cs rename to archived/ml_prm/Properties/AssemblyInfo.cs diff --git a/ml_prm/README.md b/archived/ml_prm/README.md similarity index 100% rename from ml_prm/README.md rename to archived/ml_prm/README.md diff --git a/ml_prm/RagdollController.cs b/archived/ml_prm/RagdollController.cs similarity index 100% rename from ml_prm/RagdollController.cs rename to archived/ml_prm/RagdollController.cs diff --git a/ml_prm/RagdollToggle.cs b/archived/ml_prm/RagdollToggle.cs similarity index 97% rename from ml_prm/RagdollToggle.cs rename to archived/ml_prm/RagdollToggle.cs index 63343a2..77925f0 100644 --- a/ml_prm/RagdollToggle.cs +++ b/archived/ml_prm/RagdollToggle.cs @@ -1,12 +1,12 @@ -using UnityEngine; - -namespace ml_prm -{ - public class RagdollToggle : MonoBehaviour - { - [Tooltip("Whether or not is should use the isOn property to override the current Ragdoll State of the Avatar.")] - [SerializeField] public bool shouldOverride; - [Tooltip("Whether Ragdoll State is active or not on the Avatar. Requires shouldOverride to be true to work.")] - [SerializeField] public bool isOn; - } -} +using UnityEngine; + +namespace ml_prm +{ + public class RagdollToggle : MonoBehaviour + { + [Tooltip("Whether or not is should use the isOn property to override the current Ragdoll State of the Avatar.")] + [SerializeField] public bool shouldOverride; + [Tooltip("Whether Ragdoll State is active or not on the Avatar. Requires shouldOverride to be true to work.")] + [SerializeField] public bool isOn; + } +} diff --git a/ml_prm/RagdollTrigger.cs b/archived/ml_prm/RagdollTrigger.cs similarity index 100% rename from ml_prm/RagdollTrigger.cs rename to archived/ml_prm/RagdollTrigger.cs diff --git a/ml_prm/RagdollTriggerVolume.cs b/archived/ml_prm/RagdollTriggerVolume.cs similarity index 100% rename from ml_prm/RagdollTriggerVolume.cs rename to archived/ml_prm/RagdollTriggerVolume.cs diff --git a/ml_prm/Settings.cs b/archived/ml_prm/Settings.cs similarity index 97% rename from ml_prm/Settings.cs rename to archived/ml_prm/Settings.cs index d4e8f1d..71db949 100644 --- a/ml_prm/Settings.cs +++ b/archived/ml_prm/Settings.cs @@ -1,223 +1,223 @@ -using System; -using System.Collections.Generic; -using UnityEngine; - -namespace ml_prm -{ - static class Settings - { - public enum ModSetting - { - Hotkey = 0, - HotkeyKey, - VelocityMultiplier, - MovementDrag, - AngularDrag, - Gravity, - PointersReaction, - IgnoreLocal, - CombatReaction, - AutoRecover, - RecoverDelay, - Slipperiness, - Bounciness, - ViewVelocity, - JumpRecover - } - - public static bool Hotkey { get; private set; } = true; - public static KeyCode HotkeyKey { get; private set; } = KeyCode.R; - public static float VelocityMultiplier { get; private set; } = 2f; - public static float MovementDrag { get; private set; } = 2f; - public static float AngularDrag { get; private set; } = 2f; - public static bool Gravity { get; private set; } = true; - public static bool PointersReaction { get; private set; } = true; - public static bool IgnoreLocal { get; private set; } = true; - public static bool CombatReaction { get; private set; } = true; - public static bool AutoRecover { get; private set; } = false; - public static float RecoverDelay { get; private set; } = 3f; - public static bool Slipperiness { get; private set; } = false; - public static bool Bounciness { get; private set; } = false; - public static bool ViewVelocity { get; private set; } = false; - public static bool JumpRecover { get; private set; } = false; - - static public event Action HotkeyChange; - static public event Action HotkeyKeyChange; - static public event Action VelocityMultiplierChange; - static public event Action MovementDragChange; - static public event Action AngularDragChange; - static public event Action GravityChange; - static public event Action PointersReactionChange; - static public event Action IgnoreLocalChange; - static public event Action CombatReactionChange; - static public event Action AutoRecoverChange; - static public event Action RecoverDelayChange; - static public event Action SlipperinessChange; - static public event Action BouncinessChange; - static public event Action ViewVelocityChange; - static public event Action JumpRecoverChange; - - static MelonLoader.MelonPreferences_Category ms_category = null; - static List ms_entries = null; - - internal static void Init() - { - ms_category = MelonLoader.MelonPreferences.CreateCategory("PRM", "Player Ragdoll Mod"); - - ms_entries = new List() - { - ms_category.CreateEntry(ModSetting.Hotkey.ToString(), Hotkey, null, null, true), - ms_category.CreateEntry(ModSetting.HotkeyKey.ToString(), HotkeyKey, "Hotkey"), - ms_category.CreateEntry(ModSetting.VelocityMultiplier.ToString(), VelocityMultiplier, null, null, true), - ms_category.CreateEntry(ModSetting.MovementDrag.ToString(), MovementDrag, null, null, true), - ms_category.CreateEntry(ModSetting.AngularDrag.ToString(), AngularDrag, null, null, true), - ms_category.CreateEntry(ModSetting.Gravity.ToString(), Gravity, null, null, true), - ms_category.CreateEntry(ModSetting.PointersReaction.ToString(), PointersReaction, null, null, true), - ms_category.CreateEntry(ModSetting.IgnoreLocal.ToString(), IgnoreLocal, null, null, true), - ms_category.CreateEntry(ModSetting.CombatReaction.ToString(), CombatReaction, null, null, true), - ms_category.CreateEntry(ModSetting.AutoRecover.ToString(), AutoRecover, null, null, true), - ms_category.CreateEntry(ModSetting.RecoverDelay.ToString(), RecoverDelay, null, null, true), - ms_category.CreateEntry(ModSetting.Slipperiness.ToString(), Slipperiness, null, null, true), - ms_category.CreateEntry(ModSetting.Bounciness.ToString(), Bounciness, null, null, true), - ms_category.CreateEntry(ModSetting.ViewVelocity.ToString(), ViewVelocity, null, null, true), - ms_category.CreateEntry(ModSetting.JumpRecover.ToString(), JumpRecover, null, null, true) - }; - - ms_entries[(int)ModSetting.HotkeyKey].OnEntryValueChangedUntyped.Subscribe(OnMelonSettingSave_HotkeyKey); - - Hotkey = (bool)ms_entries[(int)ModSetting.Hotkey].BoxedValue; - HotkeyKey = (KeyCode)ms_entries[(int)ModSetting.HotkeyKey].BoxedValue; - VelocityMultiplier = Mathf.Clamp((float)ms_entries[(int)ModSetting.VelocityMultiplier].BoxedValue, 1f, 50f); - MovementDrag = Mathf.Clamp((float)ms_entries[(int)ModSetting.MovementDrag].BoxedValue, 0f, 50f); - AngularDrag = Mathf.Clamp((float)ms_entries[(int)ModSetting.AngularDrag].BoxedValue, 0f, 50f); - Gravity = (bool)ms_entries[(int)ModSetting.Gravity].BoxedValue; - PointersReaction = (bool)ms_entries[(int)ModSetting.PointersReaction].BoxedValue; - IgnoreLocal = (bool)ms_entries[(int)ModSetting.IgnoreLocal].BoxedValue; - CombatReaction = (bool)ms_entries[(int)ModSetting.CombatReaction].BoxedValue; - AutoRecover = (bool)ms_entries[(int)ModSetting.AutoRecover].BoxedValue; - RecoverDelay = Mathf.Clamp((float)ms_entries[(int)ModSetting.RecoverDelay].BoxedValue, 1f, 10f); - Slipperiness = (bool)ms_entries[(int)ModSetting.Slipperiness].BoxedValue; - Bounciness = (bool)ms_entries[(int)ModSetting.Bounciness].BoxedValue; - ViewVelocity = (bool)ms_entries[(int)ModSetting.ViewVelocity].BoxedValue; - JumpRecover = (bool)ms_entries[(int)ModSetting.JumpRecover].BoxedValue; - } - - static void OnMelonSettingSave_HotkeyKey(object p_oldValue, object p_newValue) - { - if(p_newValue is KeyCode) - { - HotkeyKey = (KeyCode)p_newValue; - HotkeyKeyChange?.Invoke(HotkeyKey); - } - } - - public static void SetSetting(ModSetting p_settings, object p_value) - { - switch(p_settings) - { - // Booleans - case ModSetting.Hotkey: - { - Hotkey = (bool)p_value; - HotkeyChange?.Invoke((bool)p_value); - } - break; - - case ModSetting.Gravity: - { - Gravity = (bool)p_value; - GravityChange?.Invoke((bool)p_value); - } - break; - - case ModSetting.PointersReaction: - { - PointersReaction = (bool)p_value; - PointersReactionChange?.Invoke((bool)p_value); - } - break; - - case ModSetting.IgnoreLocal: - { - IgnoreLocal = (bool)p_value; - IgnoreLocalChange?.Invoke((bool)p_value); - } - break; - - case ModSetting.CombatReaction: - { - CombatReaction = (bool)p_value; - CombatReactionChange?.Invoke((bool)p_value); - } - break; - - case ModSetting.AutoRecover: - { - AutoRecover = (bool)p_value; - AutoRecoverChange?.Invoke((bool)p_value); - } - break; - - case ModSetting.Slipperiness: - { - Slipperiness = (bool)p_value; - SlipperinessChange?.Invoke((bool)p_value); - } - break; - - case ModSetting.Bounciness: - { - Bounciness = (bool)p_value; - BouncinessChange?.Invoke((bool)p_value); - } - break; - - case ModSetting.ViewVelocity: - { - ViewVelocity = (bool)p_value; - ViewVelocityChange?.Invoke((bool)p_value); - } - break; - - case ModSetting.JumpRecover: - { - JumpRecover = (bool)p_value; - JumpRecoverChange?.Invoke((bool)p_value); - } - break; - - // Floats - case ModSetting.VelocityMultiplier: - { - VelocityMultiplier = (float)p_value; - VelocityMultiplierChange?.Invoke((float)p_value); - } - break; - - case ModSetting.MovementDrag: - { - MovementDrag = (float)p_value; - MovementDragChange?.Invoke((float)p_value); - } - break; - - case ModSetting.AngularDrag: - { - AngularDrag = (float)p_value; - AngularDragChange?.Invoke((float)p_value); - } - break; - - case ModSetting.RecoverDelay: - { - RecoverDelay = (float)p_value; - RecoverDelayChange?.Invoke((float)p_value); - } - break; - } - - if(ms_entries != null) - ms_entries[(int)p_settings].BoxedValue = p_value; - } - } -} +using System; +using System.Collections.Generic; +using UnityEngine; + +namespace ml_prm +{ + static class Settings + { + public enum ModSetting + { + Hotkey = 0, + HotkeyKey, + VelocityMultiplier, + MovementDrag, + AngularDrag, + Gravity, + PointersReaction, + IgnoreLocal, + CombatReaction, + AutoRecover, + RecoverDelay, + Slipperiness, + Bounciness, + ViewVelocity, + JumpRecover + } + + public static bool Hotkey { get; private set; } = true; + public static KeyCode HotkeyKey { get; private set; } = KeyCode.R; + public static float VelocityMultiplier { get; private set; } = 2f; + public static float MovementDrag { get; private set; } = 2f; + public static float AngularDrag { get; private set; } = 2f; + public static bool Gravity { get; private set; } = true; + public static bool PointersReaction { get; private set; } = true; + public static bool IgnoreLocal { get; private set; } = true; + public static bool CombatReaction { get; private set; } = true; + public static bool AutoRecover { get; private set; } = false; + public static float RecoverDelay { get; private set; } = 3f; + public static bool Slipperiness { get; private set; } = false; + public static bool Bounciness { get; private set; } = false; + public static bool ViewVelocity { get; private set; } = false; + public static bool JumpRecover { get; private set; } = false; + + static public event Action HotkeyChange; + static public event Action HotkeyKeyChange; + static public event Action VelocityMultiplierChange; + static public event Action MovementDragChange; + static public event Action AngularDragChange; + static public event Action GravityChange; + static public event Action PointersReactionChange; + static public event Action IgnoreLocalChange; + static public event Action CombatReactionChange; + static public event Action AutoRecoverChange; + static public event Action RecoverDelayChange; + static public event Action SlipperinessChange; + static public event Action BouncinessChange; + static public event Action ViewVelocityChange; + static public event Action JumpRecoverChange; + + static MelonLoader.MelonPreferences_Category ms_category = null; + static List ms_entries = null; + + internal static void Init() + { + ms_category = MelonLoader.MelonPreferences.CreateCategory("PRM", "Player Ragdoll Mod"); + + ms_entries = new List() + { + ms_category.CreateEntry(ModSetting.Hotkey.ToString(), Hotkey, null, null, true), + ms_category.CreateEntry(ModSetting.HotkeyKey.ToString(), HotkeyKey, "Hotkey"), + ms_category.CreateEntry(ModSetting.VelocityMultiplier.ToString(), VelocityMultiplier, null, null, true), + ms_category.CreateEntry(ModSetting.MovementDrag.ToString(), MovementDrag, null, null, true), + ms_category.CreateEntry(ModSetting.AngularDrag.ToString(), AngularDrag, null, null, true), + ms_category.CreateEntry(ModSetting.Gravity.ToString(), Gravity, null, null, true), + ms_category.CreateEntry(ModSetting.PointersReaction.ToString(), PointersReaction, null, null, true), + ms_category.CreateEntry(ModSetting.IgnoreLocal.ToString(), IgnoreLocal, null, null, true), + ms_category.CreateEntry(ModSetting.CombatReaction.ToString(), CombatReaction, null, null, true), + ms_category.CreateEntry(ModSetting.AutoRecover.ToString(), AutoRecover, null, null, true), + ms_category.CreateEntry(ModSetting.RecoverDelay.ToString(), RecoverDelay, null, null, true), + ms_category.CreateEntry(ModSetting.Slipperiness.ToString(), Slipperiness, null, null, true), + ms_category.CreateEntry(ModSetting.Bounciness.ToString(), Bounciness, null, null, true), + ms_category.CreateEntry(ModSetting.ViewVelocity.ToString(), ViewVelocity, null, null, true), + ms_category.CreateEntry(ModSetting.JumpRecover.ToString(), JumpRecover, null, null, true) + }; + + ms_entries[(int)ModSetting.HotkeyKey].OnEntryValueChangedUntyped.Subscribe(OnMelonSettingSave_HotkeyKey); + + Hotkey = (bool)ms_entries[(int)ModSetting.Hotkey].BoxedValue; + HotkeyKey = (KeyCode)ms_entries[(int)ModSetting.HotkeyKey].BoxedValue; + VelocityMultiplier = Mathf.Clamp((float)ms_entries[(int)ModSetting.VelocityMultiplier].BoxedValue, 1f, 50f); + MovementDrag = Mathf.Clamp((float)ms_entries[(int)ModSetting.MovementDrag].BoxedValue, 0f, 50f); + AngularDrag = Mathf.Clamp((float)ms_entries[(int)ModSetting.AngularDrag].BoxedValue, 0f, 50f); + Gravity = (bool)ms_entries[(int)ModSetting.Gravity].BoxedValue; + PointersReaction = (bool)ms_entries[(int)ModSetting.PointersReaction].BoxedValue; + IgnoreLocal = (bool)ms_entries[(int)ModSetting.IgnoreLocal].BoxedValue; + CombatReaction = (bool)ms_entries[(int)ModSetting.CombatReaction].BoxedValue; + AutoRecover = (bool)ms_entries[(int)ModSetting.AutoRecover].BoxedValue; + RecoverDelay = Mathf.Clamp((float)ms_entries[(int)ModSetting.RecoverDelay].BoxedValue, 1f, 10f); + Slipperiness = (bool)ms_entries[(int)ModSetting.Slipperiness].BoxedValue; + Bounciness = (bool)ms_entries[(int)ModSetting.Bounciness].BoxedValue; + ViewVelocity = (bool)ms_entries[(int)ModSetting.ViewVelocity].BoxedValue; + JumpRecover = (bool)ms_entries[(int)ModSetting.JumpRecover].BoxedValue; + } + + static void OnMelonSettingSave_HotkeyKey(object p_oldValue, object p_newValue) + { + if(p_newValue is KeyCode) + { + HotkeyKey = (KeyCode)p_newValue; + HotkeyKeyChange?.Invoke(HotkeyKey); + } + } + + public static void SetSetting(ModSetting p_settings, object p_value) + { + switch(p_settings) + { + // Booleans + case ModSetting.Hotkey: + { + Hotkey = (bool)p_value; + HotkeyChange?.Invoke((bool)p_value); + } + break; + + case ModSetting.Gravity: + { + Gravity = (bool)p_value; + GravityChange?.Invoke((bool)p_value); + } + break; + + case ModSetting.PointersReaction: + { + PointersReaction = (bool)p_value; + PointersReactionChange?.Invoke((bool)p_value); + } + break; + + case ModSetting.IgnoreLocal: + { + IgnoreLocal = (bool)p_value; + IgnoreLocalChange?.Invoke((bool)p_value); + } + break; + + case ModSetting.CombatReaction: + { + CombatReaction = (bool)p_value; + CombatReactionChange?.Invoke((bool)p_value); + } + break; + + case ModSetting.AutoRecover: + { + AutoRecover = (bool)p_value; + AutoRecoverChange?.Invoke((bool)p_value); + } + break; + + case ModSetting.Slipperiness: + { + Slipperiness = (bool)p_value; + SlipperinessChange?.Invoke((bool)p_value); + } + break; + + case ModSetting.Bounciness: + { + Bounciness = (bool)p_value; + BouncinessChange?.Invoke((bool)p_value); + } + break; + + case ModSetting.ViewVelocity: + { + ViewVelocity = (bool)p_value; + ViewVelocityChange?.Invoke((bool)p_value); + } + break; + + case ModSetting.JumpRecover: + { + JumpRecover = (bool)p_value; + JumpRecoverChange?.Invoke((bool)p_value); + } + break; + + // Floats + case ModSetting.VelocityMultiplier: + { + VelocityMultiplier = (float)p_value; + VelocityMultiplierChange?.Invoke((float)p_value); + } + break; + + case ModSetting.MovementDrag: + { + MovementDrag = (float)p_value; + MovementDragChange?.Invoke((float)p_value); + } + break; + + case ModSetting.AngularDrag: + { + AngularDrag = (float)p_value; + AngularDragChange?.Invoke((float)p_value); + } + break; + + case ModSetting.RecoverDelay: + { + RecoverDelay = (float)p_value; + RecoverDelayChange?.Invoke((float)p_value); + } + break; + } + + if(ms_entries != null) + ms_entries[(int)p_settings].BoxedValue = p_value; + } + } +} diff --git a/ml_prm/Utils.cs b/archived/ml_prm/Utils.cs similarity index 97% rename from ml_prm/Utils.cs rename to archived/ml_prm/Utils.cs index b9d1e48..8d16014 100644 --- a/ml_prm/Utils.cs +++ b/archived/ml_prm/Utils.cs @@ -1,39 +1,39 @@ -using ABI.CCK.Components; -using ABI_RC.Core.Savior; -using ABI_RC.Systems.MovementSystem; -using System.Reflection; -using UnityEngine; - -namespace ml_prm -{ - static class Utils - { - static readonly FieldInfo ms_groundedRaw = typeof(MovementSystem).GetField("_isGroundedRaw", BindingFlags.NonPublic | BindingFlags.Instance); - static readonly FieldInfo ms_appliedGravity = typeof(MovementSystem).GetField("_appliedGravity", BindingFlags.NonPublic | BindingFlags.Instance); - - public static bool IsInVR() => ((CheckVR.Instance != null) && CheckVR.Instance.hasVrDeviceLoaded); - public static bool IsWorldSafe() => ((CVRWorld.Instance != null) && CVRWorld.Instance.allowFlying); - public static float GetWorldMovementLimit() - { - float l_result = 1f; - if(CVRWorld.Instance != null) - { - l_result = CVRWorld.Instance.baseMovementSpeed; - l_result *= CVRWorld.Instance.sprintMultiplier; - l_result *= CVRWorld.Instance.inAirMovementMultiplier; - l_result *= CVRWorld.Instance.flyMultiplier; - } - return l_result; - } - - public static bool IsGrounded(this MovementSystem p_instance) => (bool)ms_groundedRaw.GetValue(p_instance); - public static Vector3 GetAppliedGravity(this MovementSystem p_instance) => (Vector3)ms_appliedGravity.GetValue(p_instance); - public static void SetAppliedGravity(this MovementSystem p_instance, Vector3 p_vec) => ms_appliedGravity.SetValue(p_instance, p_vec); - - public static void CopyGlobal(this Transform p_source, Transform p_target) - { - p_target.position = p_source.position; - p_target.rotation = p_source.rotation; - } - } -} +using ABI.CCK.Components; +using ABI_RC.Core.Savior; +using ABI_RC.Systems.MovementSystem; +using System.Reflection; +using UnityEngine; + +namespace ml_prm +{ + static class Utils + { + static readonly FieldInfo ms_groundedRaw = typeof(MovementSystem).GetField("_isGroundedRaw", BindingFlags.NonPublic | BindingFlags.Instance); + static readonly FieldInfo ms_appliedGravity = typeof(MovementSystem).GetField("_appliedGravity", BindingFlags.NonPublic | BindingFlags.Instance); + + public static bool IsInVR() => ((CheckVR.Instance != null) && CheckVR.Instance.hasVrDeviceLoaded); + public static bool IsWorldSafe() => ((CVRWorld.Instance != null) && CVRWorld.Instance.allowFlying); + public static float GetWorldMovementLimit() + { + float l_result = 1f; + if(CVRWorld.Instance != null) + { + l_result = CVRWorld.Instance.baseMovementSpeed; + l_result *= CVRWorld.Instance.sprintMultiplier; + l_result *= CVRWorld.Instance.inAirMovementMultiplier; + l_result *= CVRWorld.Instance.flyMultiplier; + } + return l_result; + } + + public static bool IsGrounded(this MovementSystem p_instance) => (bool)ms_groundedRaw.GetValue(p_instance); + public static Vector3 GetAppliedGravity(this MovementSystem p_instance) => (Vector3)ms_appliedGravity.GetValue(p_instance); + public static void SetAppliedGravity(this MovementSystem p_instance, Vector3 p_vec) => ms_appliedGravity.SetValue(p_instance, p_vec); + + public static void CopyGlobal(this Transform p_source, Transform p_target) + { + p_target.position = p_source.position; + p_target.rotation = p_source.rotation; + } + } +} diff --git a/ml_prm/ml_prm.csproj b/archived/ml_prm/ml_prm.csproj similarity index 100% rename from ml_prm/ml_prm.csproj rename to archived/ml_prm/ml_prm.csproj diff --git a/ml_prm/resources/person.png b/archived/ml_prm/resources/person.png similarity index 100% rename from ml_prm/resources/person.png rename to archived/ml_prm/resources/person.png diff --git a/ml_prm/vendor/RootMotion/ReadMe.md b/archived/ml_prm/vendor/RootMotion/README.md similarity index 100% rename from ml_prm/vendor/RootMotion/ReadMe.md rename to archived/ml_prm/vendor/RootMotion/README.md diff --git a/ml_prm/vendor/RootMotion/info.txt b/archived/ml_prm/vendor/RootMotion/info.txt similarity index 100% rename from ml_prm/vendor/RootMotion/info.txt rename to archived/ml_prm/vendor/RootMotion/info.txt diff --git a/ml_amt/Main.cs b/ml_amt/Main.cs index eabc99f..4c75be3 100644 --- a/ml_amt/Main.cs +++ b/ml_amt/Main.cs @@ -1,120 +1,118 @@ -using ABI.CCK.Components; -using ABI_RC.Core.Player; -using ABI_RC.Systems.IK.SubSystems; -using System; -using System.Collections; -using System.Reflection; - -namespace ml_amt -{ - public class AvatarMotionTweaker : MelonLoader.MelonMod - { - static AvatarMotionTweaker ms_instance = null; - - MotionTweaker m_localTweaker = null; - - public override void OnInitializeMelon() - { - if(ms_instance == null) - ms_instance = this; - - Settings.Init(); - - HarmonyInstance.Patch( - typeof(PlayerSetup).GetMethod(nameof(PlayerSetup.ClearAvatar)), - null, - new HarmonyLib.HarmonyMethod(typeof(AvatarMotionTweaker).GetMethod(nameof(OnAvatarClear_Postfix), BindingFlags.NonPublic | BindingFlags.Static)) - ); - HarmonyInstance.Patch( - typeof(PlayerSetup).GetMethod(nameof(PlayerSetup.SetupAvatar)), - null, - new HarmonyLib.HarmonyMethod(typeof(AvatarMotionTweaker).GetMethod(nameof(OnSetupAvatar_Postfix), BindingFlags.Static | BindingFlags.NonPublic)) - ); - HarmonyInstance.Patch( - typeof(BodySystem).GetMethod(nameof(BodySystem.Calibrate)), - null, - new HarmonyLib.HarmonyMethod(typeof(AvatarMotionTweaker).GetMethod(nameof(OnCalibrate_Postfix), BindingFlags.Static | BindingFlags.NonPublic)) - ); - HarmonyInstance.Patch( - typeof(PlayerSetup).GetMethod("SetPlaySpaceScale", BindingFlags.NonPublic | BindingFlags.Instance), - null, - new HarmonyLib.HarmonyMethod(typeof(AvatarMotionTweaker).GetMethod(nameof(OnPlayspaceScale_Postfix), BindingFlags.Static | BindingFlags.NonPublic)) - ); - - ModSupporter.Init(); - MelonLoader.MelonCoroutines.Start(WaitForLocalPlayer()); - } - - IEnumerator WaitForLocalPlayer() - { - while(PlayerSetup.Instance == null) - yield return null; - - m_localTweaker = PlayerSetup.Instance.gameObject.AddComponent(); - } - - public override void OnDeinitializeMelon() - { - if(ms_instance == this) - ms_instance = null; - - m_localTweaker = null; - } - - static void OnAvatarClear_Postfix() => ms_instance?.OnAvatarClear(); - void OnAvatarClear() - { - try - { - if(m_localTweaker != null) - m_localTweaker.OnAvatarClear(); - } - catch(Exception l_exception) - { - MelonLoader.MelonLogger.Error(l_exception); - } - } - - static void OnSetupAvatar_Postfix() => ms_instance?.OnSetupAvatar(); - void OnSetupAvatar() - { - try - { - if(m_localTweaker != null) - m_localTweaker.OnSetupAvatar(); - } - catch(Exception l_exception) - { - MelonLoader.MelonLogger.Error(l_exception); - } - } - - static void OnCalibrate_Postfix() => ms_instance?.OnCalibrate(); - void OnCalibrate() - { - try - { - if(m_localTweaker != null) - m_localTweaker.OnCalibrate(); - } - catch(Exception l_exception) - { - MelonLoader.MelonLogger.Error(l_exception); - } - } - - static void OnPlayspaceScale_Postfix() => ms_instance?.OnPlayspaceScale(); - void OnPlayspaceScale() - { - try - { - if(m_localTweaker != null) - m_localTweaker.OnPlayspaceScale(); - } - catch(Exception l_exception) - { - MelonLoader.MelonLogger.Error(l_exception); - } - } - } -} +using ABI_RC.Core.Player; +using ABI_RC.Systems.IK.SubSystems; +using System; +using System.Collections; +using System.Reflection; + +namespace ml_amt +{ + public class AvatarMotionTweaker : MelonLoader.MelonMod + { + static AvatarMotionTweaker ms_instance = null; + + MotionTweaker m_localTweaker = null; + + public override void OnInitializeMelon() + { + if(ms_instance == null) + ms_instance = this; + + Settings.Init(); + + HarmonyInstance.Patch( + typeof(PlayerSetup).GetMethod(nameof(PlayerSetup.ClearAvatar)), + null, + new HarmonyLib.HarmonyMethod(typeof(AvatarMotionTweaker).GetMethod(nameof(OnAvatarClear_Postfix), BindingFlags.NonPublic | BindingFlags.Static)) + ); + HarmonyInstance.Patch( + typeof(PlayerSetup).GetMethod(nameof(PlayerSetup.SetupAvatar)), + null, + new HarmonyLib.HarmonyMethod(typeof(AvatarMotionTweaker).GetMethod(nameof(OnSetupAvatar_Postfix), BindingFlags.Static | BindingFlags.NonPublic)) + ); + HarmonyInstance.Patch( + typeof(BodySystem).GetMethod(nameof(BodySystem.Calibrate)), + null, + new HarmonyLib.HarmonyMethod(typeof(AvatarMotionTweaker).GetMethod(nameof(OnCalibrate_Postfix), BindingFlags.Static | BindingFlags.NonPublic)) + ); + HarmonyInstance.Patch( + typeof(PlayerSetup).GetMethod("SetPlaySpaceScale", BindingFlags.NonPublic | BindingFlags.Instance), + null, + new HarmonyLib.HarmonyMethod(typeof(AvatarMotionTweaker).GetMethod(nameof(OnPlayspaceScale_Postfix), BindingFlags.Static | BindingFlags.NonPublic)) + ); + + MelonLoader.MelonCoroutines.Start(WaitForLocalPlayer()); + } + + IEnumerator WaitForLocalPlayer() + { + while(PlayerSetup.Instance == null) + yield return null; + + m_localTweaker = PlayerSetup.Instance.gameObject.AddComponent(); + } + + public override void OnDeinitializeMelon() + { + if(ms_instance == this) + ms_instance = null; + + m_localTweaker = null; + } + + static void OnAvatarClear_Postfix() => ms_instance?.OnAvatarClear(); + void OnAvatarClear() + { + try + { + if(m_localTweaker != null) + m_localTweaker.OnAvatarClear(); + } + catch(Exception l_exception) + { + MelonLoader.MelonLogger.Error(l_exception); + } + } + + static void OnSetupAvatar_Postfix() => ms_instance?.OnSetupAvatar(); + void OnSetupAvatar() + { + try + { + if(m_localTweaker != null) + m_localTweaker.OnSetupAvatar(); + } + catch(Exception l_exception) + { + MelonLoader.MelonLogger.Error(l_exception); + } + } + + static void OnCalibrate_Postfix() => ms_instance?.OnCalibrate(); + void OnCalibrate() + { + try + { + if(m_localTweaker != null) + m_localTweaker.OnCalibrate(); + } + catch(Exception l_exception) + { + MelonLoader.MelonLogger.Error(l_exception); + } + } + + static void OnPlayspaceScale_Postfix() => ms_instance?.OnPlayspaceScale(); + void OnPlayspaceScale() + { + try + { + if(m_localTweaker != null) + m_localTweaker.OnPlayspaceScale(); + } + catch(Exception l_exception) + { + MelonLoader.MelonLogger.Error(l_exception); + } + } + } +} diff --git a/ml_amt/ModSupporter.cs b/ml_amt/ModSupporter.cs deleted file mode 100644 index a453e86..0000000 --- a/ml_amt/ModSupporter.cs +++ /dev/null @@ -1,49 +0,0 @@ -using System.Collections; -using System.Linq; - -namespace ml_amt -{ - static class ModSupporter - { - static bool ms_ragdollMod = false; - static bool ms_copycatMod = false; - - public static void Init() - { - if(MelonLoader.MelonMod.RegisteredMelons.FirstOrDefault(m => m.Info.Name == "PlayerRagdollMod") != null) - MelonLoader.MelonCoroutines.Start(WaitForRagdollInstance()); - if(MelonLoader.MelonMod.RegisteredMelons.FirstOrDefault(m => m.Info.Name == "PlayerMovementCopycat") != null) - MelonLoader.MelonCoroutines.Start(WaitForCopycatInstance()); - } - - // PlayerRagdollMod support - static IEnumerator WaitForRagdollInstance() - { - while(ml_prm.RagdollController.Instance == null) - yield return null; - - ms_ragdollMod = true; - } - static bool IsRagdolled() => ml_prm.RagdollController.Instance.IsRagdolled(); - - // PlayerMovementCopycat support - static IEnumerator WaitForCopycatInstance() - { - while(ml_pmc.PoseCopycat.Instance == null) - yield return null; - - ms_copycatMod = true; - } - static bool IsCopycating() => ml_pmc.PoseCopycat.Instance.IsActive(); - - public static bool SkipHipsOverride() - { - bool l_result = false; - l_result |= (ms_ragdollMod && IsRagdolled()); - l_result |= (ms_copycatMod && IsCopycating()); - return l_result; - } - - - } -} diff --git a/ml_amt/MotionTweaker.cs b/ml_amt/MotionTweaker.cs index d5b8ca8..fd2418a 100644 --- a/ml_amt/MotionTweaker.cs +++ b/ml_amt/MotionTweaker.cs @@ -1,345 +1,316 @@ -using ABI_RC.Core.Player; -using ABI_RC.Systems.IK; -using ABI_RC.Systems.IK.SubSystems; -using ABI_RC.Systems.MovementSystem; -using RootMotion.FinalIK; -using System.Collections.Generic; -using UnityEngine; - -namespace ml_amt -{ - [DisallowMultipleComponent] - class MotionTweaker : MonoBehaviour - { - struct IKState - { - public float m_weight; - public float m_locomotionWeight; - public bool m_plantFeet; - public bool m_bendNormalLeft; - public bool m_bendNormalRight; - } - - static readonly Vector4 ms_pointVector = new Vector4(0f, 0f, 0f, 1f); - static readonly int ms_emoteHash = Animator.StringToHash("Emote"); - - IKState m_ikState; - VRIK m_vrIk = null; - int m_locomotionLayer = 0; - float m_avatarScale = 1f; - Vector3 m_locomotionOffset = Vector3.zero; // Original locomotion offset - Transform m_avatarHips = null; - bool m_inVR = false; - - bool m_avatarReady = false; - bool m_grounded = false; - bool m_groundedRaw = false; - bool m_moving = false; - bool m_locomotionOverride = false; - - bool m_ikOverrideFly = true; - bool m_ikOverrideJump = true; - - bool m_detectEmotes = true; - bool m_emoteActive = false; - - bool m_followHips = true; - Vector3 m_hipsToPlayer = Vector3.zero; - - Vector3 m_massCenter = Vector3.zero; - - Transform m_ikLimits = null; - - readonly List m_parameters = null; - - internal MotionTweaker() - { - m_parameters = new List(); - } - - // Unity events - void Start() - { - m_inVR = Utils.IsInVR(); - - SetCrouchLimit(Settings.CrouchLimit); - SetProneLimit(Settings.ProneLimit); - SetIKOverrideFly(Settings.IKOverrideFly); - SetIKOverrideJump(Settings.IKOverrideJump); - SetDetectEmotes(Settings.DetectEmotes); - SetFollowHips(Settings.FollowHips); - - Settings.CrouchLimitChange += this.SetCrouchLimit; - Settings.ProneLimitChange += this.SetProneLimit; - Settings.IKOverrideFlyChange += this.SetIKOverrideFly; - Settings.IKOverrideJumpChange += this.SetIKOverrideJump; - Settings.DetectEmotesChange += this.SetDetectEmotes; - Settings.FollowHipsChange += this.SetFollowHips; - Settings.MassCenterChange += this.OnMassCenterChange; - } - - void OnDestroy() - { - Settings.CrouchLimitChange -= this.SetCrouchLimit; - Settings.ProneLimitChange -= this.SetProneLimit; - Settings.IKOverrideFlyChange -= this.SetIKOverrideFly; - Settings.IKOverrideJumpChange -= this.SetIKOverrideJump; - Settings.DetectEmotesChange -= this.SetDetectEmotes; - Settings.FollowHipsChange -= this.SetFollowHips; - Settings.MassCenterChange -= this.OnMassCenterChange; - } - - void Update() - { - if(m_avatarReady) - { - m_grounded = MovementSystem.Instance.IsGrounded(); - m_groundedRaw = MovementSystem.Instance.IsGroundedRaw(); - m_moving = !Mathf.Approximately(MovementSystem.Instance.movementVector.magnitude, 0f); - - UpdateIKLimits(); - - if(m_avatarHips != null) - { - Vector4 l_hipsToPoint = (PlayerSetup.Instance.transform.GetMatrix().inverse * m_avatarHips.GetMatrix()) * ms_pointVector; - m_hipsToPlayer.Set(l_hipsToPoint.x, 0f, l_hipsToPoint.z); - } - - m_emoteActive = false; - if(m_detectEmotes && (m_locomotionLayer >= 0)) - { - AnimatorStateInfo l_animState = PlayerSetup.Instance._animator.GetCurrentAnimatorStateInfo(m_locomotionLayer); - m_emoteActive = (l_animState.tagHash == ms_emoteHash); - } - - if(m_parameters.Count > 0) - { - foreach(AvatarParameter l_param in m_parameters) - l_param.Update(this); - } - } - } - - // Game events - internal void OnAvatarClear() - { - m_vrIk = null; - m_locomotionLayer = -1; - m_grounded = false; - m_groundedRaw = false; - m_avatarReady = false; - m_avatarScale = 1f; - m_locomotionOffset = Vector3.zero; - m_emoteActive = false; - m_moving = false; - m_locomotionOverride = false; - m_hipsToPlayer = Vector3.zero; - m_avatarHips = null; - m_massCenter = Vector3.zero; - m_ikLimits = null; - m_parameters.Clear(); - - PlayerSetup.Instance.avatarCrouchLimit = Mathf.Clamp01(Settings.CrouchLimit); - PlayerSetup.Instance.avatarProneLimit = Mathf.Clamp01(Settings.ProneLimit); - } - - internal void OnSetupAvatar() - { - m_inVR = Utils.IsInVR(); - m_vrIk = PlayerSetup.Instance._avatar.GetComponent(); - m_locomotionLayer = PlayerSetup.Instance._animator.GetLayerIndex("Locomotion/Emotes"); - m_avatarHips = PlayerSetup.Instance._animator.GetBoneTransform(HumanBodyBones.Hips); - m_avatarScale = Mathf.Abs(PlayerSetup.Instance._avatar.transform.localScale.y); - - // Parse animator parameters - m_parameters.Add(new AvatarParameter(AvatarParameter.ParameterType.Upright, PlayerSetup.Instance.animatorManager)); - m_parameters.Add(new AvatarParameter(AvatarParameter.ParameterType.GroundedRaw, PlayerSetup.Instance.animatorManager)); - m_parameters.Add(new AvatarParameter(AvatarParameter.ParameterType.Moving, PlayerSetup.Instance.animatorManager)); - m_parameters.RemoveAll(p => !p.IsValid()); - - // Avatar custom IK limits - m_ikLimits = PlayerSetup.Instance._avatar.transform.Find("[IKLimits]"); - UpdateIKLimits(); - - // Apply VRIK tweaks - if(m_vrIk != null) - { - m_locomotionOffset = m_vrIk.solver.locomotion.offset; - m_massCenter = m_locomotionOffset; - - if(m_vrIk.solver.HasToes()) - { - Transform l_foot = PlayerSetup.Instance._animator.GetBoneTransform(HumanBodyBones.LeftFoot); - if(l_foot == null) - l_foot = PlayerSetup.Instance._animator.GetBoneTransform(HumanBodyBones.RightFoot); - - Transform l_toe = PlayerSetup.Instance._animator.GetBoneTransform(HumanBodyBones.LeftToes); - if(l_toe == null) - l_toe = PlayerSetup.Instance._animator.GetBoneTransform(HumanBodyBones.RightToes); - - if((l_foot != null) && (l_toe != null)) - { - Vector3 l_footPos = (PlayerSetup.Instance._avatar.transform.GetMatrix().inverse * l_foot.GetMatrix()) * ms_pointVector; - Vector3 l_toePos = (PlayerSetup.Instance._avatar.transform.GetMatrix().inverse * l_toe.GetMatrix()) * ms_pointVector; - m_massCenter = new Vector3(0f, 0f, l_toePos.z - l_footPos.z); - } - } - - m_vrIk.solver.locomotion.offset = (Settings.MassCenter ? m_massCenter : m_locomotionOffset); - - m_vrIk.onPreSolverUpdate.AddListener(this.OnIKPreUpdate); - m_vrIk.onPostSolverUpdate.AddListener(this.OnIKPostUpdate); - } - - m_avatarReady = true; - } - - internal void OnCalibrate() - { - if(m_avatarReady && (m_vrIk != null) && (m_vrIk.solver.spine.pelvisTarget != null) && (m_vrIk.solver.leftLeg.target == null) && (m_vrIk.solver.rightLeg.target == null)) - { - // Do not consider 4PT as FBT (!!!) - m_vrIk.solver.spine.bodyPosStiffness = 0.55f; - m_vrIk.solver.spine.bodyRotStiffness = 0.1f; - m_vrIk.solver.spine.neckStiffness = 0.5f; - m_vrIk.solver.spine.chestClampWeight = 0.55f; - m_vrIk.solver.spine.moveBodyBackWhenCrouching = 0.5f; - m_vrIk.solver.spine.maxRootAngle = 25f; - m_vrIk.fixTransforms = false; - - BodySystem.isCalibratedAsFullBody = false; - BodySystem.TrackingLeftLegEnabled = false; - BodySystem.TrackingRightLegEnabled = false; - BodySystem.TrackingLocomotionEnabled = true; - - IKSystem.Instance.applyOriginalHipRotation = true; - } - } - - internal void OnPlayspaceScale() - { - if((m_vrIk != null) && Settings.MassCenter) - m_vrIk.solver.locomotion.offset = m_massCenter * GetRelativeScale(); - } - - // IK events - void OnIKPreUpdate() - { - bool l_locomotionOverride = false; - - m_ikState.m_weight = m_vrIk.solver.IKPositionWeight; - m_ikState.m_locomotionWeight = m_vrIk.solver.locomotion.weight; - m_ikState.m_plantFeet = m_vrIk.solver.plantFeet; - m_ikState.m_bendNormalLeft = m_vrIk.solver.leftLeg.useAnimatedBendNormal; - m_ikState.m_bendNormalRight = m_vrIk.solver.rightLeg.useAnimatedBendNormal; - - if(m_detectEmotes && m_emoteActive) - m_vrIk.solver.IKPositionWeight = 0f; - - if(!BodySystem.isCalibratedAsFullBody) - { - if(PlayerSetup.Instance.avatarUpright <= PlayerSetup.Instance.avatarCrouchLimit) - { - m_vrIk.solver.leftLeg.useAnimatedBendNormal = true; - m_vrIk.solver.rightLeg.useAnimatedBendNormal = true; - l_locomotionOverride = true; - } - - if(m_ikOverrideFly && MovementSystem.Instance.flying) - { - m_vrIk.solver.locomotion.weight = 0f; - m_vrIk.solver.leftLeg.useAnimatedBendNormal = true; - m_vrIk.solver.rightLeg.useAnimatedBendNormal = true; - l_locomotionOverride = true; - } - if(m_ikOverrideJump && !m_grounded && !MovementSystem.Instance.flying) - { - m_vrIk.solver.locomotion.weight = 0f; - m_vrIk.solver.leftLeg.useAnimatedBendNormal = true; - m_vrIk.solver.rightLeg.useAnimatedBendNormal = true; - l_locomotionOverride = true; - } - } - - bool l_solverActive = !Mathf.Approximately(m_vrIk.solver.IKPositionWeight, 0f); - if(l_locomotionOverride && l_solverActive && (m_followHips && !MovementSystem.Instance.sitting) && (!m_moving || (PlayerSetup.Instance.avatarUpright <= PlayerSetup.Instance.avatarCrouchLimit)) && m_inVR && !BodySystem.isCalibratedAsFullBody && !ModSupporter.SkipHipsOverride()) - { - m_vrIk.solver.plantFeet = false; - if((IKSystem.VrikRootController != null) && !MovementSystem.Instance.sitting) - IKSystem.VrikRootController.enabled = false; - PlayerSetup.Instance._avatar.transform.localPosition = m_hipsToPlayer; - } - - if(m_locomotionOverride && !l_locomotionOverride) - { - m_vrIk.solver.Reset(); - if((IKSystem.VrikRootController != null) && !MovementSystem.Instance.sitting) - IKSystem.VrikRootController.enabled = true; - } - m_locomotionOverride = l_locomotionOverride; - } - - void OnIKPostUpdate() - { - m_vrIk.solver.IKPositionWeight = m_ikState.m_weight; - m_vrIk.solver.locomotion.weight = m_ikState.m_locomotionWeight; - m_vrIk.solver.plantFeet = m_ikState.m_plantFeet; - m_vrIk.solver.leftLeg.useAnimatedBendNormal = m_ikState.m_bendNormalLeft; - m_vrIk.solver.rightLeg.useAnimatedBendNormal = m_ikState.m_bendNormalRight; - } - - // Settings - internal void SetCrouchLimit(float p_value) - { - if(m_ikLimits == null) - PlayerSetup.Instance.avatarCrouchLimit = Mathf.Clamp01(p_value); - } - internal void SetProneLimit(float p_value) - { - if(m_ikLimits == null) - PlayerSetup.Instance.avatarProneLimit = Mathf.Clamp01(p_value); - } - internal void SetIKOverrideFly(bool p_state) - { - m_ikOverrideFly = p_state; - } - internal void SetIKOverrideJump(bool p_state) - { - m_ikOverrideJump = p_state; - } - internal void SetDetectEmotes(bool p_state) - { - m_detectEmotes = p_state; - } - internal void SetFollowHips(bool p_state) - { - m_followHips = p_state; - } - void OnMassCenterChange(bool p_state) - { - if(m_vrIk != null) - m_vrIk.solver.locomotion.offset = (Settings.MassCenter ? (m_massCenter * GetRelativeScale()) : m_locomotionOffset); - } - - // Arbitrary - float GetRelativeScale() - { - return ((m_avatarScale > 0f) ? (PlayerSetup.Instance._avatar.transform.localScale.y / m_avatarScale) : 0f); - } - - void UpdateIKLimits() - { - if(m_ikLimits != null) - { - Vector3 l_values = m_ikLimits.localPosition; - PlayerSetup.Instance.avatarCrouchLimit = Mathf.Clamp01(l_values.x); - PlayerSetup.Instance.avatarProneLimit = Mathf.Clamp01(l_values.y); - } - } - - // Parameters access - public float GetUpright() => PlayerSetup.Instance.avatarUpright; - public bool GetGroundedRaw() => m_groundedRaw; - public bool GetMoving() => m_moving; - } -} +using ABI_RC.Core.Player; +using ABI_RC.Systems.IK; +using ABI_RC.Systems.IK.SubSystems; +using ABI_RC.Systems.MovementSystem; +using RootMotion.FinalIK; +using System.Collections.Generic; +using UnityEngine; + +namespace ml_amt +{ + [DisallowMultipleComponent] + class MotionTweaker : MonoBehaviour + { + struct IKState + { + public float m_weight; + public float m_locomotionWeight; + public bool m_plantFeet; + public bool m_bendNormalLeft; + public bool m_bendNormalRight; + } + + static readonly Vector4 ms_pointVector = new Vector4(0f, 0f, 0f, 1f); + static readonly int ms_emoteHash = Animator.StringToHash("Emote"); + + IKState m_ikState; + VRIK m_vrIk = null; + int m_locomotionLayer = 0; + float m_avatarScale = 1f; + Vector3 m_locomotionOffset = Vector3.zero; // Original locomotion offset + bool m_inVR = false; + + bool m_avatarReady = false; + bool m_grounded = false; + bool m_groundedRaw = false; + bool m_moving = false; + bool m_locomotionOverride = false; + + bool m_ikOverrideFly = true; + bool m_ikOverrideJump = true; + + bool m_detectEmotes = true; + bool m_emoteActive = false; + + Vector3 m_massCenter = Vector3.zero; + + Transform m_ikLimits = null; + + readonly List m_parameters = null; + + internal MotionTweaker() + { + m_parameters = new List(); + } + + // Unity events + void Start() + { + m_inVR = Utils.IsInVR(); + + SetCrouchLimit(Settings.CrouchLimit); + SetProneLimit(Settings.ProneLimit); + SetIKOverrideFly(Settings.IKOverrideFly); + SetIKOverrideJump(Settings.IKOverrideJump); + SetDetectEmotes(Settings.DetectEmotes); + + Settings.CrouchLimitChange += this.SetCrouchLimit; + Settings.ProneLimitChange += this.SetProneLimit; + Settings.IKOverrideFlyChange += this.SetIKOverrideFly; + Settings.IKOverrideJumpChange += this.SetIKOverrideJump; + Settings.DetectEmotesChange += this.SetDetectEmotes; + Settings.MassCenterChange += this.OnMassCenterChange; + } + + void OnDestroy() + { + Settings.CrouchLimitChange -= this.SetCrouchLimit; + Settings.ProneLimitChange -= this.SetProneLimit; + Settings.IKOverrideFlyChange -= this.SetIKOverrideFly; + Settings.IKOverrideJumpChange -= this.SetIKOverrideJump; + Settings.DetectEmotesChange -= this.SetDetectEmotes; + Settings.MassCenterChange -= this.OnMassCenterChange; + } + + void Update() + { + if(m_avatarReady) + { + m_grounded = MovementSystem.Instance.IsGrounded(); + m_groundedRaw = MovementSystem.Instance.IsGroundedRaw(); + m_moving = !Mathf.Approximately(MovementSystem.Instance.movementVector.magnitude, 0f); + + UpdateIKLimits(); + + m_emoteActive = false; + if(m_detectEmotes && (m_locomotionLayer >= 0)) + { + AnimatorStateInfo l_animState = PlayerSetup.Instance._animator.GetCurrentAnimatorStateInfo(m_locomotionLayer); + m_emoteActive = (l_animState.tagHash == ms_emoteHash); + } + + if(m_parameters.Count > 0) + { + foreach(AvatarParameter l_param in m_parameters) + l_param.Update(this); + } + } + } + + // Game events + internal void OnAvatarClear() + { + m_vrIk = null; + m_locomotionLayer = -1; + m_grounded = false; + m_groundedRaw = false; + m_avatarReady = false; + m_avatarScale = 1f; + m_locomotionOffset = Vector3.zero; + m_emoteActive = false; + m_moving = false; + m_locomotionOverride = false; + m_massCenter = Vector3.zero; + m_ikLimits = null; + m_parameters.Clear(); + + PlayerSetup.Instance.avatarCrouchLimit = Mathf.Clamp01(Settings.CrouchLimit); + PlayerSetup.Instance.avatarProneLimit = Mathf.Clamp01(Settings.ProneLimit); + } + + internal void OnSetupAvatar() + { + m_inVR = Utils.IsInVR(); + m_vrIk = PlayerSetup.Instance._avatar.GetComponent(); + m_locomotionLayer = PlayerSetup.Instance._animator.GetLayerIndex("Locomotion/Emotes"); + m_avatarScale = Mathf.Abs(PlayerSetup.Instance._avatar.transform.localScale.y); + + // Parse animator parameters + m_parameters.Add(new AvatarParameter(AvatarParameter.ParameterType.Upright, PlayerSetup.Instance.animatorManager)); + m_parameters.Add(new AvatarParameter(AvatarParameter.ParameterType.GroundedRaw, PlayerSetup.Instance.animatorManager)); + m_parameters.Add(new AvatarParameter(AvatarParameter.ParameterType.Moving, PlayerSetup.Instance.animatorManager)); + m_parameters.RemoveAll(p => !p.IsValid()); + + // Avatar custom IK limits + m_ikLimits = PlayerSetup.Instance._avatar.transform.Find("[IKLimits]"); + UpdateIKLimits(); + + // Apply VRIK tweaks + if(m_vrIk != null) + { + m_locomotionOffset = m_vrIk.solver.locomotion.offset; + m_massCenter = m_locomotionOffset; + + if(m_vrIk.solver.HasToes()) + { + Transform l_foot = PlayerSetup.Instance._animator.GetBoneTransform(HumanBodyBones.LeftFoot); + if(l_foot == null) + l_foot = PlayerSetup.Instance._animator.GetBoneTransform(HumanBodyBones.RightFoot); + + Transform l_toe = PlayerSetup.Instance._animator.GetBoneTransform(HumanBodyBones.LeftToes); + if(l_toe == null) + l_toe = PlayerSetup.Instance._animator.GetBoneTransform(HumanBodyBones.RightToes); + + if((l_foot != null) && (l_toe != null)) + { + Vector3 l_footPos = (PlayerSetup.Instance._avatar.transform.GetMatrix().inverse * l_foot.GetMatrix()) * ms_pointVector; + Vector3 l_toePos = (PlayerSetup.Instance._avatar.transform.GetMatrix().inverse * l_toe.GetMatrix()) * ms_pointVector; + m_massCenter = new Vector3(0f, 0f, l_toePos.z - l_footPos.z); + } + } + + m_vrIk.solver.locomotion.offset = (Settings.MassCenter ? m_massCenter : m_locomotionOffset); + + m_vrIk.onPreSolverUpdate.AddListener(this.OnIKPreUpdate); + m_vrIk.onPostSolverUpdate.AddListener(this.OnIKPostUpdate); + } + + m_avatarReady = true; + } + + internal void OnCalibrate() + { + if(m_avatarReady && (m_vrIk != null) && (m_vrIk.solver.spine.pelvisTarget != null) && (m_vrIk.solver.leftLeg.target == null) && (m_vrIk.solver.rightLeg.target == null)) + { + // Do not consider 4PT as FBT (!!!) + m_vrIk.solver.spine.bodyPosStiffness = 0.55f; + m_vrIk.solver.spine.bodyRotStiffness = 0.1f; + m_vrIk.solver.spine.neckStiffness = 0.5f; + m_vrIk.solver.spine.chestClampWeight = 0.55f; + m_vrIk.solver.spine.moveBodyBackWhenCrouching = 0.5f; + m_vrIk.solver.spine.maxRootAngle = 25f; + m_vrIk.fixTransforms = false; + + BodySystem.isCalibratedAsFullBody = false; + BodySystem.TrackingLeftLegEnabled = false; + BodySystem.TrackingRightLegEnabled = false; + BodySystem.TrackingLocomotionEnabled = true; + + IKSystem.Instance.applyOriginalHipRotation = true; + } + } + + internal void OnPlayspaceScale() + { + if((m_vrIk != null) && Settings.MassCenter) + m_vrIk.solver.locomotion.offset = m_massCenter * GetRelativeScale(); + } + + // IK events + void OnIKPreUpdate() + { + bool l_locomotionOverride = false; + + m_ikState.m_weight = m_vrIk.solver.IKPositionWeight; + m_ikState.m_locomotionWeight = m_vrIk.solver.locomotion.weight; + m_ikState.m_plantFeet = m_vrIk.solver.plantFeet; + m_ikState.m_bendNormalLeft = m_vrIk.solver.leftLeg.useAnimatedBendNormal; + m_ikState.m_bendNormalRight = m_vrIk.solver.rightLeg.useAnimatedBendNormal; + + if(m_detectEmotes && m_emoteActive) + m_vrIk.solver.IKPositionWeight = 0f; + + if(!BodySystem.isCalibratedAsFullBody) + { + if(PlayerSetup.Instance.avatarUpright <= PlayerSetup.Instance.avatarCrouchLimit) + { + m_vrIk.solver.leftLeg.useAnimatedBendNormal = true; + m_vrIk.solver.rightLeg.useAnimatedBendNormal = true; + l_locomotionOverride = true; + } + + if(m_ikOverrideFly && MovementSystem.Instance.flying) + { + m_vrIk.solver.locomotion.weight = 0f; + m_vrIk.solver.leftLeg.useAnimatedBendNormal = true; + m_vrIk.solver.rightLeg.useAnimatedBendNormal = true; + l_locomotionOverride = true; + } + if(m_ikOverrideJump && !m_grounded && !MovementSystem.Instance.flying) + { + m_vrIk.solver.locomotion.weight = 0f; + m_vrIk.solver.leftLeg.useAnimatedBendNormal = true; + m_vrIk.solver.rightLeg.useAnimatedBendNormal = true; + l_locomotionOverride = true; + } + } + + if(m_locomotionOverride && !l_locomotionOverride) + { + m_vrIk.solver.Reset(); + if((IKSystem.VrikRootController != null) && !MovementSystem.Instance.sitting) + IKSystem.VrikRootController.enabled = true; + } + m_locomotionOverride = l_locomotionOverride; + } + + void OnIKPostUpdate() + { + m_vrIk.solver.IKPositionWeight = m_ikState.m_weight; + m_vrIk.solver.locomotion.weight = m_ikState.m_locomotionWeight; + m_vrIk.solver.plantFeet = m_ikState.m_plantFeet; + m_vrIk.solver.leftLeg.useAnimatedBendNormal = m_ikState.m_bendNormalLeft; + m_vrIk.solver.rightLeg.useAnimatedBendNormal = m_ikState.m_bendNormalRight; + } + + // Settings + internal void SetCrouchLimit(float p_value) + { + if(m_ikLimits == null) + PlayerSetup.Instance.avatarCrouchLimit = Mathf.Clamp01(p_value); + } + internal void SetProneLimit(float p_value) + { + if(m_ikLimits == null) + PlayerSetup.Instance.avatarProneLimit = Mathf.Clamp01(p_value); + } + internal void SetIKOverrideFly(bool p_state) + { + m_ikOverrideFly = p_state; + } + internal void SetIKOverrideJump(bool p_state) + { + m_ikOverrideJump = p_state; + } + internal void SetDetectEmotes(bool p_state) + { + m_detectEmotes = p_state; + } + void OnMassCenterChange(bool p_state) + { + if(m_vrIk != null) + m_vrIk.solver.locomotion.offset = (Settings.MassCenter ? (m_massCenter * GetRelativeScale()) : m_locomotionOffset); + } + + // Arbitrary + float GetRelativeScale() + { + return ((m_avatarScale > 0f) ? (PlayerSetup.Instance._avatar.transform.localScale.y / m_avatarScale) : 0f); + } + + void UpdateIKLimits() + { + if(m_ikLimits != null) + { + Vector3 l_values = m_ikLimits.localPosition; + PlayerSetup.Instance.avatarCrouchLimit = Mathf.Clamp01(l_values.x); + PlayerSetup.Instance.avatarProneLimit = Mathf.Clamp01(l_values.y); + } + } + + // Parameters access + public float GetUpright() => PlayerSetup.Instance.avatarUpright; + public bool GetGroundedRaw() => m_groundedRaw; + public bool GetMoving() => m_moving; + } +} diff --git a/ml_amt/Properties/AssemblyInfo.cs b/ml_amt/Properties/AssemblyInfo.cs index f4eb9c9..9b8413d 100644 --- a/ml_amt/Properties/AssemblyInfo.cs +++ b/ml_amt/Properties/AssemblyInfo.cs @@ -1,5 +1,4 @@ -[assembly: MelonLoader.MelonInfo(typeof(ml_amt.AvatarMotionTweaker), "AvatarMotionTweaker", "1.3.3", "SDraw", "https://github.com/SDraw/ml_mods_cvr")] -[assembly: MelonLoader.MelonGame(null, "ChilloutVR")] -[assembly: MelonLoader.MelonOptionalDependencies("ml_prm", "ml_pmc")] -[assembly: MelonLoader.MelonPlatform(MelonLoader.MelonPlatformAttribute.CompatiblePlatforms.WINDOWS_X64)] -[assembly: MelonLoader.MelonPlatformDomain(MelonLoader.MelonPlatformDomainAttribute.CompatibleDomains.MONO)] +[assembly: MelonLoader.MelonInfo(typeof(ml_amt.AvatarMotionTweaker), "AvatarMotionTweaker", "1.3.4", "SDraw", "https://github.com/SDraw/ml_mods_cvr")] +[assembly: MelonLoader.MelonGame(null, "ChilloutVR")] +[assembly: MelonLoader.MelonPlatform(MelonLoader.MelonPlatformAttribute.CompatiblePlatforms.WINDOWS_X64)] +[assembly: MelonLoader.MelonPlatformDomain(MelonLoader.MelonPlatformDomainAttribute.CompatibleDomains.MONO)] diff --git a/ml_amt/README.md b/ml_amt/README.md index b3186c7..dfa5702 100644 --- a/ml_amt/README.md +++ b/ml_amt/README.md @@ -1,36 +1,33 @@ -# Avatar Motion Tweaker -This mod adds features for AAS animator and avatar locomotion behaviour. - -![](.github/img_01.png) - -# Installation -* Install [latest MelonLoader](https://github.com/LavaGang/MelonLoader) -* Get [latest release DLL](../../../releases/latest): - * Put `ml_amt.dll` in `Mods` folder of game - -# Usage -Available mod's settings in `Settings - IK - Avatar Motion Tweaker`: -* **Crouch limit:** defines crouch limit; default value - `75`. -* **Prone limit:** defines prone limit; default value - `40`. -* **IK override while flying:** disables legs locomotion/autostep in fly mode; default value - `true`. -* **IK override while jumping:** disables legs locomotion/autostep in jump; default value - `true`. -* **Follow hips on IK override:** adjusts avatar position to overcome animation snapping on IK override; default value - `true`. - * Note: Works best with animations that have root transform position (XZ) based on center of mass. - * Note: Made for four point tracking (head, hands and hips) in mind. -* **Detect animations emote tag:** disables avatar's IK entirely if current animator state has `Emote` tag; default value - `true`. - * Note: Created as example for [propoused game feature](https://feedback.abinteractive.net/p/disabling-vr-ik-for-emotes-via-animator-state-tag-7b80d963-053a-41c0-86ac-e3d53c61c1e2). -* **Adjusted locomotion mass center:** automatically changes IK locomotion center if avatar has toe bones; default value - `true`. - * Note: Compatible with [DesktopVRIK](https://github.com/NotAKidOnSteam/DesktopVRIK) and [FuckToes](https://github.com/NotAKidOnSteam/FuckToes). - -Available additional parameters for AAS animator: -* **`Upright`:** defines linear coefficient between current viewpoint height and avatar's viewpoint height; float, range - [0.0, 1.0]. - * Note: Can be set as local-only (not synced) if starts with `#` character. - * Note: Shouldn't be used for transitions between poses in desktop mode. In desktop mode its value is driven by avatar animations. Use `CVR Parameter Stream` for detecting desktop/VR modes and change AAS animator transitions accordingly. -* **`GroundedRaw`:** defines instant grounding state of player instead of delayed default parameter `Grounded`; boolean. - * Note: Can be set as local-only (not synced) if starts with `#` character. -* **`Moving`:** defines movement state of player; boolean. - * Note: Can be set as local-only (not synced) if starts with `#` character. - -Additional mod's behaviour: -* Overrides and fixes IK behaviour in 4PT mode (head, hands and hips). +# Avatar Motion Tweaker +This mod adds features for AAS animator and avatar locomotion behaviour. + +![](.github/img_01.png) + +# Installation +* Install [latest MelonLoader](https://github.com/LavaGang/MelonLoader) +* Get [latest release DLL](../../../releases/latest): + * Put `ml_amt.dll` in `Mods` folder of game + +# Usage +Available mod's settings in `Settings - IK - Avatar Motion Tweaker`: +* **Crouch limit:** defines crouch limit; default value - `75`. +* **Prone limit:** defines prone limit; default value - `40`. +* **IK override while flying:** disables legs locomotion/autostep in fly mode; default value - `true`. +* **IK override while jumping:** disables legs locomotion/autostep in jump; default value - `true`. +* **Detect animations emote tag:** disables avatar's IK entirely if current animator state has `Emote` tag; default value - `true`. + * Note: Created as example for [propoused game feature](https://feedback.abinteractive.net/p/disabling-vr-ik-for-emotes-via-animator-state-tag-7b80d963-053a-41c0-86ac-e3d53c61c1e2). +* **Adjusted locomotion mass center:** automatically changes IK locomotion center if avatar has toe bones; default value - `true`. + * Note: Compatible with [DesktopVRIK](https://github.com/NotAKidOnSteam/DesktopVRIK) and [FuckToes](https://github.com/NotAKidOnSteam/FuckToes). + +Available additional parameters for AAS animator: +* **`Upright`:** defines linear coefficient between current viewpoint height and avatar's viewpoint height; float, range - [0.0, 1.0]. + * Note: Can be set as local-only (not synced) if starts with `#` character. + * Note: Shouldn't be used for transitions between poses in desktop mode. In desktop mode its value is driven by avatar animations. Use `CVR Parameter Stream` for detecting desktop/VR modes and change AAS animator transitions accordingly. +* **`GroundedRaw`:** defines instant grounding state of player instead of delayed default parameter `Grounded`; boolean. + * Note: Can be set as local-only (not synced) if starts with `#` character. +* **`Moving`:** defines movement state of player; boolean. + * Note: Can be set as local-only (not synced) if starts with `#` character. + +Additional mod's behaviour: +* Overrides and fixes IK behaviour in 4PT mode (head, hands and hips). * Avatars can have controlled IK crouch and prone limits. For that create `[IKLimits]` GameObject parented to avatar's root. Its local X and Y positions will be used as crouch and prone limits respectively and can be changed via animations. Values should be in range of [0;1]. \ No newline at end of file diff --git a/ml_amt/Settings.cs b/ml_amt/Settings.cs index 7400bca..4f914f0 100644 --- a/ml_amt/Settings.cs +++ b/ml_amt/Settings.cs @@ -1,159 +1,148 @@ -using ABI_RC.Core.InteractionSystem; -using System; -using System.Collections.Generic; - -namespace ml_amt -{ - static class Settings - { - enum ModSetting - { - CrouchLimit, - ProneLimit, - IKOverrideFly, - IKOverrideJump, - DetectEmotes, - FollowHips, - MassCenter - }; - - public static float CrouchLimit { get; private set; } = 0.75f; - public static float ProneLimit { get; private set; } = 0.4f; - public static bool IKOverrideFly { get; private set; } = true; - public static bool IKOverrideJump { get; private set; } = true; - public static bool DetectEmotes { get; private set; } = true; - public static bool FollowHips { get; private set; } = true; - public static bool MassCenter { get; private set; } = true; - - static MelonLoader.MelonPreferences_Category ms_category = null; - static List ms_entries = null; - - static public event Action CrouchLimitChange; - static public event Action ProneLimitChange; - static public event Action IKOverrideFlyChange; - static public event Action IKOverrideJumpChange; - static public event Action DetectEmotesChange; - static public event Action FollowHipsChange; - static public event Action MassCenterChange; - - internal static void Init() - { - ms_category = MelonLoader.MelonPreferences.CreateCategory("AMT", null, true); - - ms_entries = new List() - { - ms_category.CreateEntry(ModSetting.CrouchLimit.ToString(), (int)(CrouchLimit * 100f)), - ms_category.CreateEntry(ModSetting.ProneLimit.ToString(), (int)(ProneLimit * 100f)), - ms_category.CreateEntry(ModSetting.IKOverrideFly.ToString(), IKOverrideFly), - ms_category.CreateEntry(ModSetting.IKOverrideJump.ToString(), IKOverrideJump), - ms_category.CreateEntry(ModSetting.DetectEmotes.ToString(), DetectEmotes), - ms_category.CreateEntry(ModSetting.FollowHips.ToString(), FollowHips), - ms_category.CreateEntry(ModSetting.MassCenter.ToString(), MassCenter) - }; - - CrouchLimit = ((int)ms_entries[(int)ModSetting.CrouchLimit].BoxedValue) * 0.01f; - ProneLimit = ((int)ms_entries[(int)ModSetting.ProneLimit].BoxedValue) * 0.01f; - IKOverrideFly = (bool)ms_entries[(int)ModSetting.IKOverrideFly].BoxedValue; - IKOverrideJump = (bool)ms_entries[(int)ModSetting.IKOverrideJump].BoxedValue; - DetectEmotes = (bool)ms_entries[(int)ModSetting.DetectEmotes].BoxedValue; - FollowHips = (bool)ms_entries[(int)ModSetting.FollowHips].BoxedValue; - MassCenter = (bool)ms_entries[(int)ModSetting.MassCenter].BoxedValue; - - MelonLoader.MelonCoroutines.Start(WaitMainMenuUi()); - } - - static System.Collections.IEnumerator WaitMainMenuUi() - { - while(ViewManager.Instance == null) - yield return null; - while(ViewManager.Instance.gameMenuView == null) - yield return null; - while(ViewManager.Instance.gameMenuView.Listener == null) - yield return null; - - ViewManager.Instance.gameMenuView.Listener.ReadyForBindings += () => - { - ViewManager.Instance.gameMenuView.View.BindCall("OnSliderUpdate_" + ms_category.Identifier, new Action(OnSliderUpdate)); - ViewManager.Instance.gameMenuView.View.BindCall("OnToggleUpdate_" + ms_category.Identifier, new Action(OnToggleUpdate)); - }; - ViewManager.Instance.gameMenuView.Listener.FinishLoad += (_) => - { - ViewManager.Instance.gameMenuView.View.ExecuteScript(Scripts.GetEmbeddedScript("mods_extension.js")); - ViewManager.Instance.gameMenuView.View.ExecuteScript(Scripts.GetEmbeddedScript("mod_menu.js")); - foreach(var l_entry in ms_entries) - ViewManager.Instance.gameMenuView.View.TriggerEvent("updateModSetting", ms_category.Identifier, l_entry.DisplayName, l_entry.GetValueAsString()); - }; - } - - static void OnSliderUpdate(string p_name, string p_value) - { - if(Enum.TryParse(p_name, out ModSetting l_setting)) - { - switch(l_setting) - { - case ModSetting.CrouchLimit: - { - CrouchLimit = int.Parse(p_value) * 0.01f; - CrouchLimitChange?.Invoke(CrouchLimit); - } - break; - - case ModSetting.ProneLimit: - { - ProneLimit = int.Parse(p_value) * 0.01f; - ProneLimitChange?.Invoke(ProneLimit); - } - break; - } - - ms_entries[(int)l_setting].BoxedValue = int.Parse(p_value); - } - } - - static void OnToggleUpdate(string p_name, string p_value) - { - if(Enum.TryParse(p_name, out ModSetting l_setting)) - { - switch(l_setting) - { - case ModSetting.IKOverrideFly: - { - IKOverrideFly = bool.Parse(p_value); - IKOverrideFlyChange?.Invoke(IKOverrideFly); - } - break; - - case ModSetting.IKOverrideJump: - { - IKOverrideJump = bool.Parse(p_value); - IKOverrideJumpChange?.Invoke(IKOverrideJump); - } - break; - - case ModSetting.DetectEmotes: - { - DetectEmotes = bool.Parse(p_value); - DetectEmotesChange?.Invoke(DetectEmotes); - } - break; - - case ModSetting.FollowHips: - { - FollowHips = bool.Parse(p_value); - FollowHipsChange?.Invoke(FollowHips); - } - break; - - case ModSetting.MassCenter: - { - MassCenter = bool.Parse(p_value); - MassCenterChange?.Invoke(MassCenter); - } - break; - } - - ms_entries[(int)l_setting].BoxedValue = bool.Parse(p_value); - } - } - } -} +using ABI_RC.Core.InteractionSystem; +using System; +using System.Collections.Generic; + +namespace ml_amt +{ + static class Settings + { + enum ModSetting + { + CrouchLimit, + ProneLimit, + IKOverrideFly, + IKOverrideJump, + DetectEmotes, + FollowHips, + MassCenter + }; + + public static float CrouchLimit { get; private set; } = 0.75f; + public static float ProneLimit { get; private set; } = 0.4f; + public static bool IKOverrideFly { get; private set; } = true; + public static bool IKOverrideJump { get; private set; } = true; + public static bool DetectEmotes { get; private set; } = true; + public static bool MassCenter { get; private set; } = true; + + static MelonLoader.MelonPreferences_Category ms_category = null; + static List ms_entries = null; + + static public event Action CrouchLimitChange; + static public event Action ProneLimitChange; + static public event Action IKOverrideFlyChange; + static public event Action IKOverrideJumpChange; + static public event Action DetectEmotesChange; + static public event Action MassCenterChange; + + internal static void Init() + { + ms_category = MelonLoader.MelonPreferences.CreateCategory("AMT", null, true); + + ms_entries = new List() + { + ms_category.CreateEntry(ModSetting.CrouchLimit.ToString(), (int)(CrouchLimit * 100f)), + ms_category.CreateEntry(ModSetting.ProneLimit.ToString(), (int)(ProneLimit * 100f)), + ms_category.CreateEntry(ModSetting.IKOverrideFly.ToString(), IKOverrideFly), + ms_category.CreateEntry(ModSetting.IKOverrideJump.ToString(), IKOverrideJump), + ms_category.CreateEntry(ModSetting.DetectEmotes.ToString(), DetectEmotes), + ms_category.CreateEntry(ModSetting.MassCenter.ToString(), MassCenter) + }; + + CrouchLimit = ((int)ms_entries[(int)ModSetting.CrouchLimit].BoxedValue) * 0.01f; + ProneLimit = ((int)ms_entries[(int)ModSetting.ProneLimit].BoxedValue) * 0.01f; + IKOverrideFly = (bool)ms_entries[(int)ModSetting.IKOverrideFly].BoxedValue; + IKOverrideJump = (bool)ms_entries[(int)ModSetting.IKOverrideJump].BoxedValue; + DetectEmotes = (bool)ms_entries[(int)ModSetting.DetectEmotes].BoxedValue; + MassCenter = (bool)ms_entries[(int)ModSetting.MassCenter].BoxedValue; + + MelonLoader.MelonCoroutines.Start(WaitMainMenuUi()); + } + + static System.Collections.IEnumerator WaitMainMenuUi() + { + while(ViewManager.Instance == null) + yield return null; + while(ViewManager.Instance.gameMenuView == null) + yield return null; + while(ViewManager.Instance.gameMenuView.Listener == null) + yield return null; + + ViewManager.Instance.gameMenuView.Listener.ReadyForBindings += () => + { + ViewManager.Instance.gameMenuView.View.BindCall("OnSliderUpdate_" + ms_category.Identifier, new Action(OnSliderUpdate)); + ViewManager.Instance.gameMenuView.View.BindCall("OnToggleUpdate_" + ms_category.Identifier, new Action(OnToggleUpdate)); + }; + ViewManager.Instance.gameMenuView.Listener.FinishLoad += (_) => + { + ViewManager.Instance.gameMenuView.View.ExecuteScript(Scripts.GetEmbeddedScript("mods_extension.js")); + ViewManager.Instance.gameMenuView.View.ExecuteScript(Scripts.GetEmbeddedScript("mod_menu.js")); + foreach(var l_entry in ms_entries) + ViewManager.Instance.gameMenuView.View.TriggerEvent("updateModSetting", ms_category.Identifier, l_entry.DisplayName, l_entry.GetValueAsString()); + }; + } + + static void OnSliderUpdate(string p_name, string p_value) + { + if(Enum.TryParse(p_name, out ModSetting l_setting)) + { + switch(l_setting) + { + case ModSetting.CrouchLimit: + { + CrouchLimit = int.Parse(p_value) * 0.01f; + CrouchLimitChange?.Invoke(CrouchLimit); + } + break; + + case ModSetting.ProneLimit: + { + ProneLimit = int.Parse(p_value) * 0.01f; + ProneLimitChange?.Invoke(ProneLimit); + } + break; + } + + ms_entries[(int)l_setting].BoxedValue = int.Parse(p_value); + } + } + + static void OnToggleUpdate(string p_name, string p_value) + { + if(Enum.TryParse(p_name, out ModSetting l_setting)) + { + switch(l_setting) + { + case ModSetting.IKOverrideFly: + { + IKOverrideFly = bool.Parse(p_value); + IKOverrideFlyChange?.Invoke(IKOverrideFly); + } + break; + + case ModSetting.IKOverrideJump: + { + IKOverrideJump = bool.Parse(p_value); + IKOverrideJumpChange?.Invoke(IKOverrideJump); + } + break; + + case ModSetting.DetectEmotes: + { + DetectEmotes = bool.Parse(p_value); + DetectEmotesChange?.Invoke(DetectEmotes); + } + break; + + case ModSetting.MassCenter: + { + MassCenter = bool.Parse(p_value); + MassCenterChange?.Invoke(MassCenter); + } + break; + } + + ms_entries[(int)l_setting].BoxedValue = bool.Parse(p_value); + } + } + } +} diff --git a/ml_amt/ml_amt.csproj b/ml_amt/ml_amt.csproj index 8ccfc4b..4a087bb 100644 --- a/ml_amt/ml_amt.csproj +++ b/ml_amt/ml_amt.csproj @@ -1,95 +1,87 @@ - - - - netstandard2.1 - SDraw - None - AvatarMotionTweaker - AvatarMotionTweaker - 1.3.3 - x64 - ml_amt - - - - x64 - 4 - none - false - false - TRACE - - - - - - - - - - - - - - - - - - - - - - D:\Games\Steam\steamapps\common\ChilloutVR\MelonLoader\net35\0Harmony.dll - false - - - D:\games\Steam\steamapps\common\ChilloutVR\ChilloutVR_Data\Managed\Assembly-CSharp.dll - false - - - D:\games\Steam\steamapps\common\ChilloutVR\ChilloutVR_Data\Managed\Assembly-CSharp-firstpass.dll - false - - - D:\games\Steam\steamapps\common\ChilloutVR\ChilloutVR_Data\Managed\cohtml.Net.dll - false - - - D:\games\Steam\steamapps\common\ChilloutVR\ChilloutVR_Data\Managed\Cohtml.Runtime.dll - false - - - D:\Games\Steam\steamapps\common\ChilloutVR\MelonLoader\net35\MelonLoader.dll - false - - - D:\games\Steam\steamapps\common\ChilloutVR\Mods\ml_pmc.dll - false - - - D:\games\Steam\steamapps\common\ChilloutVR\Mods\ml_prm.dll - false - - - D:\games\Steam\steamapps\common\ChilloutVR\ChilloutVR_Data\Managed\UnityEngine.dll - false - - - D:\games\Steam\steamapps\common\ChilloutVR\ChilloutVR_Data\Managed\UnityEngine.AnimationModule.dll - false - - - D:\games\Steam\steamapps\common\ChilloutVR\ChilloutVR_Data\Managed\UnityEngine.CoreModule.dll - false - - - D:\games\Steam\steamapps\common\ChilloutVR\ChilloutVR_Data\Managed\UnityEngine.PhysicsModule.dll - false - - - - - - - - + + + + netstandard2.1 + SDraw + None + AvatarMotionTweaker + AvatarMotionTweaker + 1.3.4 + x64 + ml_amt + + + + x64 + 4 + none + false + false + TRACE + + + + + + + + + + + + + + + + + + + + + + D:\Games\Steam\steamapps\common\ChilloutVR\MelonLoader\net35\0Harmony.dll + false + + + D:\games\Steam\steamapps\common\ChilloutVR\ChilloutVR_Data\Managed\Assembly-CSharp.dll + false + + + D:\games\Steam\steamapps\common\ChilloutVR\ChilloutVR_Data\Managed\Assembly-CSharp-firstpass.dll + false + + + D:\games\Steam\steamapps\common\ChilloutVR\ChilloutVR_Data\Managed\cohtml.Net.dll + false + + + D:\games\Steam\steamapps\common\ChilloutVR\ChilloutVR_Data\Managed\Cohtml.Runtime.dll + false + + + D:\Games\Steam\steamapps\common\ChilloutVR\MelonLoader\net35\MelonLoader.dll + false + + + D:\games\Steam\steamapps\common\ChilloutVR\ChilloutVR_Data\Managed\UnityEngine.dll + false + + + D:\games\Steam\steamapps\common\ChilloutVR\ChilloutVR_Data\Managed\UnityEngine.AnimationModule.dll + false + + + D:\games\Steam\steamapps\common\ChilloutVR\ChilloutVR_Data\Managed\UnityEngine.CoreModule.dll + false + + + D:\games\Steam\steamapps\common\ChilloutVR\ChilloutVR_Data\Managed\UnityEngine.PhysicsModule.dll + false + + + + + + + + diff --git a/ml_amt/resources/mod_menu.js b/ml_amt/resources/mod_menu.js index f0aa5e1..aab2153 100644 --- a/ml_amt/resources/mod_menu.js +++ b/ml_amt/resources/mod_menu.js @@ -1,68 +1,61 @@ -// Add own menu -{ - let l_block = document.createElement('div'); - l_block.innerHTML = ` -
-
Avatar Motion Tweaker
-
-
- -
-
Crouch limit:
-
-
-
-
- -
-
Prone limit:
-
-
-
-
- -
-
IK override while flying:
-
-
-
-
- -
-
IK override while jumping:
-
-
-
-
- -
-
Follow hips on IK override:
-
-
-
-
- -
-
Detect animations emote tag:
-
-
-
-
- -
-
Adjusted locomotion mass center:
-
-
-
-
- `; - document.getElementById('settings-ik').appendChild(l_block); - - // Toggles - for (let l_toggle of l_block.querySelectorAll('.inp_toggle')) - modsExtension.addSetting('AMT', l_toggle.id, modsExtension.createToggle(l_toggle, 'OnToggleUpdate_AMT')); - - // Sliders - for (let l_slider of l_block.querySelectorAll('.inp_slider')) - modsExtension.addSetting('AMT', l_slider.id, modsExtension.createSlider(l_slider, 'OnSliderUpdate_AMT')); -} +// Add own menu +{ + let l_block = document.createElement('div'); + l_block.innerHTML = ` +
+
Avatar Motion Tweaker
+
+
+ +
+
Crouch limit:
+
+
+
+
+ +
+
Prone limit:
+
+
+
+
+ +
+
IK override while flying:
+
+
+
+
+ +
+
Follow hips on IK override:
+
+
+
+
+ +
+
Detect animations emote tag:
+
+
+
+
+ +
+
Adjusted locomotion mass center:
+
+
+
+
+ `; + document.getElementById('settings-ik').appendChild(l_block); + + // Toggles + for (let l_toggle of l_block.querySelectorAll('.inp_toggle')) + modsExtension.addSetting('AMT', l_toggle.id, modsExtension.createToggle(l_toggle, 'OnToggleUpdate_AMT')); + + // Sliders + for (let l_slider of l_block.querySelectorAll('.inp_slider')) + modsExtension.addSetting('AMT', l_slider.id, modsExtension.createSlider(l_slider, 'OnSliderUpdate_AMT')); +} diff --git a/ml_lme/LeapInput.cs b/ml_lme/LeapInput.cs index e0a4a09..db15cf8 100644 --- a/ml_lme/LeapInput.cs +++ b/ml_lme/LeapInput.cs @@ -1,506 +1,506 @@ -using ABI_RC.Core.InteractionSystem; -using ABI_RC.Core.Player; -using ABI_RC.Core.Savior; -using ABI_RC.Systems.IK; -using ABI_RC.Systems.InputManagement; -using System.Collections; -using UnityEngine; - -namespace ml_lme -{ - class LeapInput : CVRInputModule - { - bool m_inVR = false; - bool m_gripToGrab = true; - - bool m_handVisibleLeft = false; - bool m_handVisibleRight = false; - ControllerRay m_handRayLeft = null; - ControllerRay m_handRayRight = null; - LineRenderer m_lineLeft = null; - LineRenderer m_lineRight = null; - bool m_interactLeft = false; - bool m_interactRight = false; - bool m_gripLeft = false; - bool m_gripRight = false; - - ~LeapInput() - { - Settings.EnabledChange -= this.OnEnableChange; - Settings.InteractionChange -= this.OnInteractionChange; - Settings.GesturesChange -= this.OnGesturesChange; - Settings.FingersOnlyChange -= this.OnFingersOnlyChange; - - MetaPort.Instance.settings.settingBoolChanged.RemoveListener(this.OnGameSettingBoolChange); - } - - public override void ModuleAdded() - { - base.ModuleAdded(); - base.InputEnabled = Settings.Enabled; - base.HapticFeedback = false; - - m_inVR = Utils.IsInVR(); - - m_handRayLeft = LeapTracking.Instance.GetLeftHand().gameObject.AddComponent(); - m_handRayLeft.hand = true; - m_handRayLeft.generalMask = -1485; - m_handRayLeft.isInteractionRay = true; - m_handRayLeft.triggerGazeEvents = false; - m_handRayLeft.holderRoot = m_handRayLeft.gameObject; - m_handRayLeft.attachmentDistance = 0f; - - m_lineLeft = m_handRayLeft.gameObject.AddComponent(); - m_lineLeft.endWidth = 1f; - m_lineLeft.startWidth = 1f; - m_lineLeft.textureMode = LineTextureMode.Tile; - m_lineLeft.useWorldSpace = false; - m_lineLeft.widthMultiplier = 1f; - m_lineLeft.allowOcclusionWhenDynamic = false; - m_lineLeft.shadowCastingMode = UnityEngine.Rendering.ShadowCastingMode.Off; - m_lineLeft.enabled = false; - m_lineLeft.receiveShadows = false; - m_handRayLeft.lineRenderer = m_lineLeft; - - m_handRayRight = LeapTracking.Instance.GetRightHand().gameObject.AddComponent(); - m_handRayRight.hand = false; - m_handRayRight.generalMask = -1485; - m_handRayRight.isInteractionRay = true; - m_handRayRight.triggerGazeEvents = false; - m_handRayRight.holderRoot = m_handRayRight.gameObject; - m_handRayRight.attachmentDistance = 0f; - - m_lineRight = m_handRayRight.gameObject.AddComponent(); - m_lineRight.endWidth = 1f; - m_lineRight.startWidth = 1f; - m_lineRight.textureMode = LineTextureMode.Tile; - m_lineRight.useWorldSpace = false; - m_lineRight.widthMultiplier = 1f; - m_lineRight.allowOcclusionWhenDynamic = false; - m_lineRight.shadowCastingMode = UnityEngine.Rendering.ShadowCastingMode.Off; - m_lineRight.enabled = false; - m_lineRight.receiveShadows = false; - m_handRayRight.lineRenderer = m_lineRight; - - Settings.EnabledChange += this.OnEnableChange; - Settings.InteractionChange += this.OnInteractionChange; - Settings.GesturesChange += this.OnGesturesChange; - Settings.FingersOnlyChange += this.OnFingersOnlyChange; - - OnEnableChange(Settings.Enabled); - OnInteractionChange(Settings.Interaction); - OnGesturesChange(Settings.Gestures); - OnFingersOnlyChange(Settings.FingersOnly); - - MelonLoader.MelonCoroutines.Start(WaitForSettings()); - MelonLoader.MelonCoroutines.Start(WaitForMaterial()); - } - - IEnumerator WaitForSettings() - { - while(MetaPort.Instance == null) - yield return null; - while(MetaPort.Instance.settings == null) - yield return null; - - m_gripToGrab = MetaPort.Instance.settings.GetSettingsBool("ControlUseGripToGrab", true); - MetaPort.Instance.settings.settingBoolChanged.AddListener(this.OnGameSettingBoolChange); - } - - IEnumerator WaitForMaterial() - { - while(PlayerSetup.Instance == null) - yield return null; - while(PlayerSetup.Instance.leftRay == null) - yield return null; - while(PlayerSetup.Instance.leftRay.lineRenderer == null) - yield return null; - - m_lineLeft.material = PlayerSetup.Instance.leftRay.lineRenderer.material; - m_lineLeft.gameObject.layer = PlayerSetup.Instance.leftRay.gameObject.layer; - m_lineRight.material = PlayerSetup.Instance.leftRay.lineRenderer.material; - m_lineRight.gameObject.layer = PlayerSetup.Instance.leftRay.gameObject.layer; - } - - public override void UpdateInput() - { - if(base.InputEnabled) - { - LeapParser.LeapData l_data = LeapManager.Instance.GetLatestData(); - - if(l_data.m_leftHand.m_present) - { - m_handVisibleLeft = true; - - SetFingersInput(l_data.m_leftHand, true); - - if(Settings.Gestures) - { - base._inputManager.gestureLeftRaw = 0f; - - // Finger Point & Finger Gun - if((base._inputManager.fingerCurlLeftIndex < 0.2f) && (base._inputManager.fingerCurlLeftMiddle > 0.75f) && - (base._inputManager.fingerCurlLeftRing > 0.75f) && (base._inputManager.fingerCurlLeftPinky > 0.75f)) - { - base._inputManager.gestureLeftRaw = (base._inputManager.fingerCurlLeftThumb >= 0.5f) ? 4f : 3f; - } - - // Peace Sign - if((base._inputManager.fingerCurlLeftIndex < 0.2f) && (base._inputManager.fingerCurlLeftMiddle < 0.2f) && - (base._inputManager.fingerCurlLeftRing > 0.75f) && (base._inputManager.fingerCurlLeftPinky > 0.75f)) - { - base._inputManager.gestureLeftRaw = 5f; - } - - // Rock and Roll - if((base._inputManager.fingerCurlLeftIndex < 0.2f) && (base._inputManager.fingerCurlLeftMiddle > 0.75f) && - (base._inputManager.fingerCurlLeftRing > 0.75f) && (base._inputManager.fingerCurlLeftPinky < 0.5f)) - { - base._inputManager.gestureLeftRaw = 6f; - } - - // Fist & Thumbs Up - if((base._inputManager.fingerCurlLeftIndex > 0.5f) && (base._inputManager.fingerCurlLeftMiddle > 0.5f) && - (base._inputManager.fingerCurlLeftRing > 0.5f) && (base._inputManager.fingerCurlLeftPinky > 0.5f)) - { - base._inputManager.gestureLeftRaw = (base._inputManager.fingerCurlLeftThumb >= 0.5f) ? ((l_data.m_leftHand.m_grabStrength - 0.5f) * 2f) : 2f; - } - - // Open Hand - if((base._inputManager.fingerCurlLeftIndex < 0.2f) && (base._inputManager.fingerCurlLeftMiddle < 0.2f) && - (base._inputManager.fingerCurlLeftRing < 0.2f) && (base._inputManager.fingerCurlLeftPinky < 0.2f)) - { - base._inputManager.gestureLeftRaw = -1f; - } - - base._inputManager.gestureLeft = base._inputManager.gestureLeftRaw; - } - } - else - { - if(m_handVisibleLeft) - { - ResetFingers(true); - if(Settings.Gestures) - ResetGestures(true); - } - - m_handVisibleLeft = false; - } - - if(l_data.m_rightHand.m_present) - { - m_handVisibleRight = true; - - SetFingersInput(l_data.m_rightHand, false); - - if(Settings.Gestures) - { - base._inputManager.gestureRightRaw = 0f; - - // Finger Point & Finger Gun - if((base._inputManager.fingerCurlRightIndex < 0.2f) && (base._inputManager.fingerCurlRightMiddle > 0.75f) && - (base._inputManager.fingerCurlRightRing > 0.75f) && (base._inputManager.fingerCurlRightPinky > 0.75f)) - { - base._inputManager.gestureRightRaw = (base._inputManager.fingerCurlRightThumb >= 0.5f) ? 4f : 3f; - } - - // Peace Sign - if((base._inputManager.fingerCurlRightIndex < 0.2f) && (base._inputManager.fingerCurlRightMiddle < 0.2f) && - (base._inputManager.fingerCurlRightRing > 0.75f) && (base._inputManager.fingerCurlRightPinky > 0.75f)) - { - base._inputManager.gestureRightRaw = 5f; - } - - // Rock and Roll - if((base._inputManager.fingerCurlRightIndex < 0.2f) && (base._inputManager.fingerCurlRightMiddle > 0.75f) && - (base._inputManager.fingerCurlRightRing > 0.75f) && (base._inputManager.fingerCurlRightPinky < 0.5f)) - { - base._inputManager.gestureRightRaw = 6f; - } - - // Fist & Thumbs Up - if((base._inputManager.fingerCurlRightIndex > 0.5f) && (base._inputManager.fingerCurlRightMiddle > 0.5f) && - (base._inputManager.fingerCurlRightRing > 0.5f) && (base._inputManager.fingerCurlRightPinky > 0.5f)) - { - base._inputManager.gestureRightRaw = (base._inputManager.fingerCurlRightThumb >= 0.5f) ? ((l_data.m_rightHand.m_grabStrength - 0.5f) * 2f) : 2f; - } - - // Open Hand - if((base._inputManager.fingerCurlRightIndex < 0.2f) && (base._inputManager.fingerCurlRightMiddle < 0.2f) && - (base._inputManager.fingerCurlRightRing < 0.2f) && (base._inputManager.fingerCurlRightPinky < 0.2f)) - { - base._inputManager.gestureRightRaw = -1f; - } - - base._inputManager.gestureRight = base._inputManager.gestureRightRaw; - } - } - else - { - if(m_handVisibleRight) - { - ResetFingers(false); - if(Settings.Gestures) - ResetGestures(false); - } - - m_handVisibleRight = false; - } - - if(!ModSupporter.SkipFingersOverride() && (!m_inVR || !Utils.AreKnucklesInUse())) - SetGameFingersTracking(m_handVisibleRight || m_handVisibleLeft); - - base.UpdateInput(); - } - } - - public override void Update_Interaction() - { - if(Settings.Interaction) - { - LeapParser.LeapData l_data = LeapManager.Instance.GetLatestData(); - - if(m_handVisibleLeft && (!m_inVR || !Utils.IsLeftHandTracked()) && !Settings.FingersOnly) - { - float l_strength = l_data.m_leftHand.m_grabStrength; - - float l_interactValue = 0f; - if(m_gripToGrab) - l_interactValue = Mathf.Clamp01(Mathf.InverseLerp(Mathf.Min(Settings.GripThreadhold, Settings.InteractThreadhold), Mathf.Max(Settings.GripThreadhold, Settings.InteractThreadhold), l_strength)); - else - l_interactValue = Mathf.Clamp01(Mathf.InverseLerp(0f, Settings.InteractThreadhold, l_strength)); - base._inputManager.interactLeftValue = Mathf.Max(l_interactValue, base._inputManager.interactLeftValue); - - if(m_interactLeft != (l_strength > Settings.InteractThreadhold)) - { - m_interactLeft = (l_strength > Settings.InteractThreadhold); - base._inputManager.interactLeftDown |= m_interactLeft; - base._inputManager.interactLeftUp |= !m_interactLeft; - } - - float l_gripValue = Mathf.Clamp01(Mathf.InverseLerp(0f, Settings.GripThreadhold, l_strength)); - base._inputManager.gripLeftValue = Mathf.Max(l_gripValue, base._inputManager.gripLeftValue); - if(m_gripLeft != (l_strength > Settings.GripThreadhold)) - { - m_gripLeft = (l_strength > Settings.GripThreadhold); - base._inputManager.gripLeftDown |= m_gripLeft; - base._inputManager.gripLeftUp |= !m_gripLeft; - } - } - - if(m_handVisibleRight && (!m_inVR || !Utils.IsRightHandTracked()) && !Settings.FingersOnly) - { - float l_strength = l_data.m_rightHand.m_grabStrength; - - float l_interactValue = 0f; - if(m_gripToGrab) - l_interactValue = Mathf.Clamp01(Mathf.InverseLerp(Mathf.Min(Settings.GripThreadhold, Settings.InteractThreadhold), Mathf.Max(Settings.GripThreadhold, Settings.InteractThreadhold), l_strength)); - else - l_interactValue = Mathf.Clamp01(Mathf.InverseLerp(0f, Settings.InteractThreadhold, l_strength)); - base._inputManager.interactRightValue = Mathf.Max(l_interactValue, base._inputManager.interactRightValue); - - if(m_interactRight != (l_strength > Settings.InteractThreadhold)) - { - m_interactRight = (l_strength > Settings.InteractThreadhold); - base._inputManager.interactRightDown |= m_interactRight; - base._inputManager.interactRightUp |= !m_interactRight; - } - - float l_gripValue = Mathf.Clamp01(Mathf.InverseLerp(0f, Settings.GripThreadhold, l_strength)); - base._inputManager.gripRightValue = Mathf.Max(l_gripValue, base._inputManager.gripRightValue); - if(m_gripRight != (l_strength > Settings.GripThreadhold)) - { - m_gripRight = (l_strength > Settings.GripThreadhold); - base._inputManager.gripRightDown |= m_gripRight; - base._inputManager.gripRightUp |= !m_gripRight; - } - } - - ToggleHandRay(m_handVisibleLeft && (!m_inVR || !Utils.IsLeftHandTracked()) && !Settings.FingersOnly, true); - ToggleHandRay(m_handVisibleRight && (!m_inVR || !Utils.IsRightHandTracked()) && !Settings.FingersOnly, false); - } - } - - // Settings changes - void OnEnableChange(bool p_state) - { - base.InputEnabled = p_state; - - m_handVisibleLeft &= p_state; - m_handVisibleRight &= p_state; - - if(!p_state) - { - ResetFingers(true); - ResetFingers(false); - - if(Settings.Gestures) - { - ResetGestures(true); - ResetGestures(false); - } - - // Reset to default, FreedomFingers can go brrr, player should press funny controller button two times - SetGameFingersTracking(m_inVR && Utils.AreKnucklesInUse() && !CVRInputManager._moduleXR.GestureToggleValue); - } - - OnInteractionChange(Settings.Interaction); - } - - void OnInteractionChange(bool p_state) - { - bool l_state = (p_state && Settings.Enabled && !Settings.FingersOnly); - - ToggleHandRay(l_state, true); - ToggleHandRay(l_state, false); - - if(!l_state) - { - m_handRayLeft.DropObject(true); - m_handRayLeft.ClearGrabbedObject(); - - m_handRayRight.DropObject(true); - m_handRayRight.ClearGrabbedObject(); - - m_interactLeft = false; - m_interactRight = false; - m_gripLeft = false; - m_gripRight = false; - } - } - - void OnGesturesChange(bool p_state) - { - base._inputManager.gestureLeft = 0f; - base._inputManager.gestureLeftRaw = 0f; - base._inputManager.gestureRight = 0f; - base._inputManager.gestureRightRaw = 0f; - } - - void OnFingersOnlyChange(bool p_state) - { - OnInteractionChange(Settings.Interaction); - } - - // Game events - internal void OnAvatarSetup() - { - m_inVR = Utils.IsInVR(); - } - - internal void OnRayScale(float p_scale) - { - m_handRayLeft.SetRayScale(p_scale); - m_handRayRight.SetRayScale(p_scale); - } - - // Arbitrary - void SetFingersInput(LeapParser.HandData p_hand, bool p_left) - { - // Game has spreads in range of [0;1], but mod now operates in range of [-1;1] - // So spreads will be normalized towards game's range - if(p_left) - { - base._inputManager.fingerCurlLeftThumb = p_hand.m_bends[0]; - base._inputManager.fingerCurlLeftIndex = p_hand.m_bends[1]; - base._inputManager.fingerCurlLeftMiddle = p_hand.m_bends[2]; - base._inputManager.fingerCurlLeftRing = p_hand.m_bends[3]; - base._inputManager.fingerCurlLeftPinky = p_hand.m_bends[4]; - base._inputManager.fingerSpreadLeftThumb = 1f - (p_hand.m_spreads[0] * 0.5f + 0.5f); - base._inputManager.fingerSpreadLeftIndex = 1f - (p_hand.m_spreads[1] * 0.5f + 0.5f); - base._inputManager.fingerSpreadLeftMiddle = 1f - (p_hand.m_spreads[2] * 0.5f + 0.5f); - base._inputManager.fingerSpreadLeftRing = 1f - (p_hand.m_spreads[3] * 0.5f + 0.5f); - base._inputManager.fingerSpreadLeftPinky = 1f - (p_hand.m_spreads[4] * 0.5f + 0.5f); - } - else - { - base._inputManager.fingerCurlRightThumb = p_hand.m_bends[0]; - base._inputManager.fingerCurlRightIndex = p_hand.m_bends[1]; - base._inputManager.fingerCurlRightMiddle = p_hand.m_bends[2]; - base._inputManager.fingerCurlRightRing = p_hand.m_bends[3]; - base._inputManager.fingerCurlRightPinky = p_hand.m_bends[4]; - base._inputManager.fingerSpreadRightThumb = 1f - (p_hand.m_spreads[0] * 0.5f + 0.5f); - base._inputManager.fingerSpreadRightIndex = 1f - (p_hand.m_spreads[1] * 0.5f + 0.5f); - base._inputManager.fingerSpreadRightMiddle = 1f - (p_hand.m_spreads[2] * 0.5f + 0.5f); - base._inputManager.fingerSpreadRightRing = 1f - (p_hand.m_spreads[3] * 0.5f + 0.5f); - base._inputManager.fingerSpreadRightPinky = 1f - (p_hand.m_spreads[4] * 0.5f + 0.5f); - } - } - - void ResetFingers(bool p_left) - { - if(p_left) - { - base._inputManager.fingerCurlLeftThumb = 0f; - base._inputManager.fingerCurlLeftIndex = 0f; - base._inputManager.fingerCurlLeftMiddle = 0f; - base._inputManager.fingerCurlLeftRing = 0f; - base._inputManager.fingerCurlLeftPinky = 0f; - base._inputManager.fingerSpreadLeftThumb = 0.5f; - base._inputManager.fingerSpreadLeftIndex = 0.5f; - base._inputManager.fingerSpreadLeftMiddle = 0.5f; - base._inputManager.fingerSpreadLeftRing = 0.5f; - base._inputManager.fingerSpreadLeftPinky = 0.5f; - } - else - { - base._inputManager.fingerCurlRightThumb = 0f; - base._inputManager.fingerCurlRightIndex = 0f; - base._inputManager.fingerCurlRightMiddle = 0f; - base._inputManager.fingerCurlRightRing = 0f; - base._inputManager.fingerCurlRightPinky = 0f; - base._inputManager.fingerSpreadRightThumb = 0.5f; - base._inputManager.fingerSpreadRightIndex = 0.5f; - base._inputManager.fingerSpreadRightMiddle = 0.5f; - base._inputManager.fingerSpreadRightRing = 0.5f; - base._inputManager.fingerSpreadRightPinky = 0.5f; - } - } - - void ResetGestures(bool p_left) - { - if(p_left) - { - base._inputManager.gestureLeft = 0f; - base._inputManager.gestureLeftRaw = 0f; - } - else - { - base._inputManager.gestureRight = 0f; - base._inputManager.gestureRightRaw = 0f; - } - } - - void ToggleHandRay(bool p_state, bool p_left) - { - if(p_left) - { - m_handRayLeft.enabled = p_state; - ((MonoBehaviour)m_handRayLeft).enabled = p_state; - m_lineLeft.enabled = p_state; - m_lineLeft.forceRenderingOff = !p_state; - } - else - { - m_handRayRight.enabled = p_state; - ((MonoBehaviour)m_handRayRight).enabled = p_state; - m_lineRight.enabled = p_state; - m_lineRight.forceRenderingOff = !p_state; - } - } - - // Game settings - void OnGameSettingBoolChange(string p_name, bool p_state) - { - if(p_name == "ControlUseGripToGrab") - m_gripToGrab = p_state; - } - - void SetGameFingersTracking(bool p_state) - { - base._inputManager.individualFingerTracking = p_state; - IKSystem.Instance.FingerSystem.controlActive = base._inputManager.individualFingerTracking; - } - } -} +using ABI_RC.Core.InteractionSystem; +using ABI_RC.Core.Player; +using ABI_RC.Core.Savior; +using ABI_RC.Systems.IK; +using ABI_RC.Systems.InputManagement; +using System.Collections; +using UnityEngine; + +namespace ml_lme +{ + class LeapInput : CVRInputModule + { + bool m_inVR = false; + bool m_gripToGrab = true; + + bool m_handVisibleLeft = false; + bool m_handVisibleRight = false; + ControllerRay m_handRayLeft = null; + ControllerRay m_handRayRight = null; + LineRenderer m_lineLeft = null; + LineRenderer m_lineRight = null; + bool m_interactLeft = false; + bool m_interactRight = false; + bool m_gripLeft = false; + bool m_gripRight = false; + + ~LeapInput() + { + Settings.EnabledChange -= this.OnEnableChange; + Settings.InteractionChange -= this.OnInteractionChange; + Settings.GesturesChange -= this.OnGesturesChange; + Settings.FingersOnlyChange -= this.OnFingersOnlyChange; + + MetaPort.Instance.settings.settingBoolChanged.RemoveListener(this.OnGameSettingBoolChange); + } + + public override void ModuleAdded() + { + base.ModuleAdded(); + base.InputEnabled = Settings.Enabled; + base.HapticFeedback = false; + + m_inVR = Utils.IsInVR(); + + m_handRayLeft = LeapTracking.Instance.GetLeftHand().gameObject.AddComponent(); + m_handRayLeft.hand = true; + m_handRayLeft.generalMask = -1485; + m_handRayLeft.isInteractionRay = true; + m_handRayLeft.triggerGazeEvents = false; + m_handRayLeft.holderRoot = m_handRayLeft.gameObject; + m_handRayLeft.attachmentDistance = 0f; + + m_lineLeft = m_handRayLeft.gameObject.AddComponent(); + m_lineLeft.endWidth = 1f; + m_lineLeft.startWidth = 1f; + m_lineLeft.textureMode = LineTextureMode.Tile; + m_lineLeft.useWorldSpace = false; + m_lineLeft.widthMultiplier = 1f; + m_lineLeft.allowOcclusionWhenDynamic = false; + m_lineLeft.shadowCastingMode = UnityEngine.Rendering.ShadowCastingMode.Off; + m_lineLeft.enabled = false; + m_lineLeft.receiveShadows = false; + m_handRayLeft.lineRenderer = m_lineLeft; + + m_handRayRight = LeapTracking.Instance.GetRightHand().gameObject.AddComponent(); + m_handRayRight.hand = false; + m_handRayRight.generalMask = -1485; + m_handRayRight.isInteractionRay = true; + m_handRayRight.triggerGazeEvents = false; + m_handRayRight.holderRoot = m_handRayRight.gameObject; + m_handRayRight.attachmentDistance = 0f; + + m_lineRight = m_handRayRight.gameObject.AddComponent(); + m_lineRight.endWidth = 1f; + m_lineRight.startWidth = 1f; + m_lineRight.textureMode = LineTextureMode.Tile; + m_lineRight.useWorldSpace = false; + m_lineRight.widthMultiplier = 1f; + m_lineRight.allowOcclusionWhenDynamic = false; + m_lineRight.shadowCastingMode = UnityEngine.Rendering.ShadowCastingMode.Off; + m_lineRight.enabled = false; + m_lineRight.receiveShadows = false; + m_handRayRight.lineRenderer = m_lineRight; + + Settings.EnabledChange += this.OnEnableChange; + Settings.InteractionChange += this.OnInteractionChange; + Settings.GesturesChange += this.OnGesturesChange; + Settings.FingersOnlyChange += this.OnFingersOnlyChange; + + OnEnableChange(Settings.Enabled); + OnInteractionChange(Settings.Interaction); + OnGesturesChange(Settings.Gestures); + OnFingersOnlyChange(Settings.FingersOnly); + + MelonLoader.MelonCoroutines.Start(WaitForSettings()); + MelonLoader.MelonCoroutines.Start(WaitForMaterial()); + } + + IEnumerator WaitForSettings() + { + while(MetaPort.Instance == null) + yield return null; + while(MetaPort.Instance.settings == null) + yield return null; + + m_gripToGrab = MetaPort.Instance.settings.GetSettingsBool("ControlUseGripToGrab", true); + MetaPort.Instance.settings.settingBoolChanged.AddListener(this.OnGameSettingBoolChange); + } + + IEnumerator WaitForMaterial() + { + while(PlayerSetup.Instance == null) + yield return null; + while(PlayerSetup.Instance.vrRayLeft == null) + yield return null; + while(PlayerSetup.Instance.vrRayLeft.lineRenderer == null) + yield return null; + + m_lineLeft.material = PlayerSetup.Instance.vrRayLeft.lineRenderer.material; + m_lineLeft.gameObject.layer = PlayerSetup.Instance.vrRayLeft.gameObject.layer; + m_lineRight.material = PlayerSetup.Instance.vrRayLeft.lineRenderer.material; + m_lineRight.gameObject.layer = PlayerSetup.Instance.vrRayLeft.gameObject.layer; + } + + public override void UpdateInput() + { + if(base.InputEnabled) + { + LeapParser.LeapData l_data = LeapManager.Instance.GetLatestData(); + + if(l_data.m_leftHand.m_present) + { + m_handVisibleLeft = true; + + SetFingersInput(l_data.m_leftHand, true); + + if(Settings.Gestures) + { + base._inputManager.gestureLeftRaw = 0f; + + // Finger Point & Finger Gun + if((base._inputManager.fingerCurlLeftIndex < 0.2f) && (base._inputManager.fingerCurlLeftMiddle > 0.75f) && + (base._inputManager.fingerCurlLeftRing > 0.75f) && (base._inputManager.fingerCurlLeftPinky > 0.75f)) + { + base._inputManager.gestureLeftRaw = (base._inputManager.fingerCurlLeftThumb >= 0.5f) ? 4f : 3f; + } + + // Peace Sign + if((base._inputManager.fingerCurlLeftIndex < 0.2f) && (base._inputManager.fingerCurlLeftMiddle < 0.2f) && + (base._inputManager.fingerCurlLeftRing > 0.75f) && (base._inputManager.fingerCurlLeftPinky > 0.75f)) + { + base._inputManager.gestureLeftRaw = 5f; + } + + // Rock and Roll + if((base._inputManager.fingerCurlLeftIndex < 0.2f) && (base._inputManager.fingerCurlLeftMiddle > 0.75f) && + (base._inputManager.fingerCurlLeftRing > 0.75f) && (base._inputManager.fingerCurlLeftPinky < 0.5f)) + { + base._inputManager.gestureLeftRaw = 6f; + } + + // Fist & Thumbs Up + if((base._inputManager.fingerCurlLeftIndex > 0.5f) && (base._inputManager.fingerCurlLeftMiddle > 0.5f) && + (base._inputManager.fingerCurlLeftRing > 0.5f) && (base._inputManager.fingerCurlLeftPinky > 0.5f)) + { + base._inputManager.gestureLeftRaw = (base._inputManager.fingerCurlLeftThumb >= 0.5f) ? ((l_data.m_leftHand.m_grabStrength - 0.5f) * 2f) : 2f; + } + + // Open Hand + if((base._inputManager.fingerCurlLeftIndex < 0.2f) && (base._inputManager.fingerCurlLeftMiddle < 0.2f) && + (base._inputManager.fingerCurlLeftRing < 0.2f) && (base._inputManager.fingerCurlLeftPinky < 0.2f)) + { + base._inputManager.gestureLeftRaw = -1f; + } + + base._inputManager.gestureLeft = base._inputManager.gestureLeftRaw; + } + } + else + { + if(m_handVisibleLeft) + { + ResetFingers(true); + if(Settings.Gestures) + ResetGestures(true); + } + + m_handVisibleLeft = false; + } + + if(l_data.m_rightHand.m_present) + { + m_handVisibleRight = true; + + SetFingersInput(l_data.m_rightHand, false); + + if(Settings.Gestures) + { + base._inputManager.gestureRightRaw = 0f; + + // Finger Point & Finger Gun + if((base._inputManager.fingerCurlRightIndex < 0.2f) && (base._inputManager.fingerCurlRightMiddle > 0.75f) && + (base._inputManager.fingerCurlRightRing > 0.75f) && (base._inputManager.fingerCurlRightPinky > 0.75f)) + { + base._inputManager.gestureRightRaw = (base._inputManager.fingerCurlRightThumb >= 0.5f) ? 4f : 3f; + } + + // Peace Sign + if((base._inputManager.fingerCurlRightIndex < 0.2f) && (base._inputManager.fingerCurlRightMiddle < 0.2f) && + (base._inputManager.fingerCurlRightRing > 0.75f) && (base._inputManager.fingerCurlRightPinky > 0.75f)) + { + base._inputManager.gestureRightRaw = 5f; + } + + // Rock and Roll + if((base._inputManager.fingerCurlRightIndex < 0.2f) && (base._inputManager.fingerCurlRightMiddle > 0.75f) && + (base._inputManager.fingerCurlRightRing > 0.75f) && (base._inputManager.fingerCurlRightPinky < 0.5f)) + { + base._inputManager.gestureRightRaw = 6f; + } + + // Fist & Thumbs Up + if((base._inputManager.fingerCurlRightIndex > 0.5f) && (base._inputManager.fingerCurlRightMiddle > 0.5f) && + (base._inputManager.fingerCurlRightRing > 0.5f) && (base._inputManager.fingerCurlRightPinky > 0.5f)) + { + base._inputManager.gestureRightRaw = (base._inputManager.fingerCurlRightThumb >= 0.5f) ? ((l_data.m_rightHand.m_grabStrength - 0.5f) * 2f) : 2f; + } + + // Open Hand + if((base._inputManager.fingerCurlRightIndex < 0.2f) && (base._inputManager.fingerCurlRightMiddle < 0.2f) && + (base._inputManager.fingerCurlRightRing < 0.2f) && (base._inputManager.fingerCurlRightPinky < 0.2f)) + { + base._inputManager.gestureRightRaw = -1f; + } + + base._inputManager.gestureRight = base._inputManager.gestureRightRaw; + } + } + else + { + if(m_handVisibleRight) + { + ResetFingers(false); + if(Settings.Gestures) + ResetGestures(false); + } + + m_handVisibleRight = false; + } + + if(!ModSupporter.SkipFingersOverride() && (!m_inVR || !Utils.AreKnucklesInUse())) + SetGameFingersTracking(m_handVisibleRight || m_handVisibleLeft); + + base.UpdateInput(); + } + } + + public override void Update_Interaction() + { + if(Settings.Interaction) + { + LeapParser.LeapData l_data = LeapManager.Instance.GetLatestData(); + + if(m_handVisibleLeft && (!m_inVR || !Utils.IsLeftHandTracked()) && !Settings.FingersOnly) + { + float l_strength = l_data.m_leftHand.m_grabStrength; + + float l_interactValue = 0f; + if(m_gripToGrab) + l_interactValue = Mathf.Clamp01(Mathf.InverseLerp(Mathf.Min(Settings.GripThreadhold, Settings.InteractThreadhold), Mathf.Max(Settings.GripThreadhold, Settings.InteractThreadhold), l_strength)); + else + l_interactValue = Mathf.Clamp01(Mathf.InverseLerp(0f, Settings.InteractThreadhold, l_strength)); + base._inputManager.interactLeftValue = Mathf.Max(l_interactValue, base._inputManager.interactLeftValue); + + if(m_interactLeft != (l_strength > Settings.InteractThreadhold)) + { + m_interactLeft = (l_strength > Settings.InteractThreadhold); + base._inputManager.interactLeftDown |= m_interactLeft; + base._inputManager.interactLeftUp |= !m_interactLeft; + } + + float l_gripValue = Mathf.Clamp01(Mathf.InverseLerp(0f, Settings.GripThreadhold, l_strength)); + base._inputManager.gripLeftValue = Mathf.Max(l_gripValue, base._inputManager.gripLeftValue); + if(m_gripLeft != (l_strength > Settings.GripThreadhold)) + { + m_gripLeft = (l_strength > Settings.GripThreadhold); + base._inputManager.gripLeftDown |= m_gripLeft; + base._inputManager.gripLeftUp |= !m_gripLeft; + } + } + + if(m_handVisibleRight && (!m_inVR || !Utils.IsRightHandTracked()) && !Settings.FingersOnly) + { + float l_strength = l_data.m_rightHand.m_grabStrength; + + float l_interactValue = 0f; + if(m_gripToGrab) + l_interactValue = Mathf.Clamp01(Mathf.InverseLerp(Mathf.Min(Settings.GripThreadhold, Settings.InteractThreadhold), Mathf.Max(Settings.GripThreadhold, Settings.InteractThreadhold), l_strength)); + else + l_interactValue = Mathf.Clamp01(Mathf.InverseLerp(0f, Settings.InteractThreadhold, l_strength)); + base._inputManager.interactRightValue = Mathf.Max(l_interactValue, base._inputManager.interactRightValue); + + if(m_interactRight != (l_strength > Settings.InteractThreadhold)) + { + m_interactRight = (l_strength > Settings.InteractThreadhold); + base._inputManager.interactRightDown |= m_interactRight; + base._inputManager.interactRightUp |= !m_interactRight; + } + + float l_gripValue = Mathf.Clamp01(Mathf.InverseLerp(0f, Settings.GripThreadhold, l_strength)); + base._inputManager.gripRightValue = Mathf.Max(l_gripValue, base._inputManager.gripRightValue); + if(m_gripRight != (l_strength > Settings.GripThreadhold)) + { + m_gripRight = (l_strength > Settings.GripThreadhold); + base._inputManager.gripRightDown |= m_gripRight; + base._inputManager.gripRightUp |= !m_gripRight; + } + } + + ToggleHandRay(m_handVisibleLeft && (!m_inVR || !Utils.IsLeftHandTracked()) && !Settings.FingersOnly, true); + ToggleHandRay(m_handVisibleRight && (!m_inVR || !Utils.IsRightHandTracked()) && !Settings.FingersOnly, false); + } + } + + // Settings changes + void OnEnableChange(bool p_state) + { + base.InputEnabled = p_state; + + m_handVisibleLeft &= p_state; + m_handVisibleRight &= p_state; + + if(!p_state) + { + ResetFingers(true); + ResetFingers(false); + + if(Settings.Gestures) + { + ResetGestures(true); + ResetGestures(false); + } + + // Reset to default, FreedomFingers can go brrr, player should press funny controller button two times + SetGameFingersTracking(m_inVR && Utils.AreKnucklesInUse() && !CVRInputManager._moduleXR.GestureToggleValue); + } + + OnInteractionChange(Settings.Interaction); + } + + void OnInteractionChange(bool p_state) + { + bool l_state = (p_state && Settings.Enabled && !Settings.FingersOnly); + + ToggleHandRay(l_state, true); + ToggleHandRay(l_state, false); + + if(!l_state) + { + m_handRayLeft.DropObject(true); + m_handRayLeft.ClearGrabbedObject(); + + m_handRayRight.DropObject(true); + m_handRayRight.ClearGrabbedObject(); + + m_interactLeft = false; + m_interactRight = false; + m_gripLeft = false; + m_gripRight = false; + } + } + + void OnGesturesChange(bool p_state) + { + base._inputManager.gestureLeft = 0f; + base._inputManager.gestureLeftRaw = 0f; + base._inputManager.gestureRight = 0f; + base._inputManager.gestureRightRaw = 0f; + } + + void OnFingersOnlyChange(bool p_state) + { + OnInteractionChange(Settings.Interaction); + } + + // Game events + internal void OnAvatarSetup() + { + m_inVR = Utils.IsInVR(); + } + + internal void OnRayScale(float p_scale) + { + m_handRayLeft.SetRayScale(p_scale); + m_handRayRight.SetRayScale(p_scale); + } + + // Arbitrary + void SetFingersInput(LeapParser.HandData p_hand, bool p_left) + { + // Game has spreads in range of [0;1], but mod now operates in range of [-1;1] + // So spreads will be normalized towards game's range + if(p_left) + { + base._inputManager.fingerCurlLeftThumb = p_hand.m_bends[0]; + base._inputManager.fingerCurlLeftIndex = p_hand.m_bends[1]; + base._inputManager.fingerCurlLeftMiddle = p_hand.m_bends[2]; + base._inputManager.fingerCurlLeftRing = p_hand.m_bends[3]; + base._inputManager.fingerCurlLeftPinky = p_hand.m_bends[4]; + base._inputManager.fingerSpreadLeftThumb = 1f - (p_hand.m_spreads[0] * 0.5f + 0.5f); + base._inputManager.fingerSpreadLeftIndex = 1f - (p_hand.m_spreads[1] * 0.5f + 0.5f); + base._inputManager.fingerSpreadLeftMiddle = 1f - (p_hand.m_spreads[2] * 0.5f + 0.5f); + base._inputManager.fingerSpreadLeftRing = 1f - (p_hand.m_spreads[3] * 0.5f + 0.5f); + base._inputManager.fingerSpreadLeftPinky = 1f - (p_hand.m_spreads[4] * 0.5f + 0.5f); + } + else + { + base._inputManager.fingerCurlRightThumb = p_hand.m_bends[0]; + base._inputManager.fingerCurlRightIndex = p_hand.m_bends[1]; + base._inputManager.fingerCurlRightMiddle = p_hand.m_bends[2]; + base._inputManager.fingerCurlRightRing = p_hand.m_bends[3]; + base._inputManager.fingerCurlRightPinky = p_hand.m_bends[4]; + base._inputManager.fingerSpreadRightThumb = 1f - (p_hand.m_spreads[0] * 0.5f + 0.5f); + base._inputManager.fingerSpreadRightIndex = 1f - (p_hand.m_spreads[1] * 0.5f + 0.5f); + base._inputManager.fingerSpreadRightMiddle = 1f - (p_hand.m_spreads[2] * 0.5f + 0.5f); + base._inputManager.fingerSpreadRightRing = 1f - (p_hand.m_spreads[3] * 0.5f + 0.5f); + base._inputManager.fingerSpreadRightPinky = 1f - (p_hand.m_spreads[4] * 0.5f + 0.5f); + } + } + + void ResetFingers(bool p_left) + { + if(p_left) + { + base._inputManager.fingerCurlLeftThumb = 0f; + base._inputManager.fingerCurlLeftIndex = 0f; + base._inputManager.fingerCurlLeftMiddle = 0f; + base._inputManager.fingerCurlLeftRing = 0f; + base._inputManager.fingerCurlLeftPinky = 0f; + base._inputManager.fingerSpreadLeftThumb = 0.5f; + base._inputManager.fingerSpreadLeftIndex = 0.5f; + base._inputManager.fingerSpreadLeftMiddle = 0.5f; + base._inputManager.fingerSpreadLeftRing = 0.5f; + base._inputManager.fingerSpreadLeftPinky = 0.5f; + } + else + { + base._inputManager.fingerCurlRightThumb = 0f; + base._inputManager.fingerCurlRightIndex = 0f; + base._inputManager.fingerCurlRightMiddle = 0f; + base._inputManager.fingerCurlRightRing = 0f; + base._inputManager.fingerCurlRightPinky = 0f; + base._inputManager.fingerSpreadRightThumb = 0.5f; + base._inputManager.fingerSpreadRightIndex = 0.5f; + base._inputManager.fingerSpreadRightMiddle = 0.5f; + base._inputManager.fingerSpreadRightRing = 0.5f; + base._inputManager.fingerSpreadRightPinky = 0.5f; + } + } + + void ResetGestures(bool p_left) + { + if(p_left) + { + base._inputManager.gestureLeft = 0f; + base._inputManager.gestureLeftRaw = 0f; + } + else + { + base._inputManager.gestureRight = 0f; + base._inputManager.gestureRightRaw = 0f; + } + } + + void ToggleHandRay(bool p_state, bool p_left) + { + if(p_left) + { + m_handRayLeft.enabled = p_state; + ((MonoBehaviour)m_handRayLeft).enabled = p_state; + m_lineLeft.enabled = p_state; + m_lineLeft.forceRenderingOff = !p_state; + } + else + { + m_handRayRight.enabled = p_state; + ((MonoBehaviour)m_handRayRight).enabled = p_state; + m_lineRight.enabled = p_state; + m_lineRight.forceRenderingOff = !p_state; + } + } + + // Game settings + void OnGameSettingBoolChange(string p_name, bool p_state) + { + if(p_name == "ControlUseGripToGrab") + m_gripToGrab = p_state; + } + + void SetGameFingersTracking(bool p_state) + { + base._inputManager.individualFingerTracking = p_state; + IKSystem.Instance.FingerSystem.controlActive = base._inputManager.individualFingerTracking; + } + } +} diff --git a/ml_lme/Properties/AssemblyInfo.cs b/ml_lme/Properties/AssemblyInfo.cs index b7c503d..24aa9cb 100644 --- a/ml_lme/Properties/AssemblyInfo.cs +++ b/ml_lme/Properties/AssemblyInfo.cs @@ -1,6 +1,6 @@ -[assembly: MelonLoader.MelonInfo(typeof(ml_lme.LeapMotionExtension), "LeapMotionExtension", "1.4.3", "SDraw", "https://github.com/SDraw/ml_mods_cvr")] -[assembly: MelonLoader.MelonGame(null, "ChilloutVR")] -[assembly: MelonLoader.MelonOptionalDependencies("ml_pmc")] -[assembly: MelonLoader.MelonPlatform(MelonLoader.MelonPlatformAttribute.CompatiblePlatforms.WINDOWS_X64)] -[assembly: MelonLoader.MelonPlatformDomain(MelonLoader.MelonPlatformDomainAttribute.CompatibleDomains.MONO)] -[assembly: MelonLoader.MelonAdditionalCredits("NotAKidOnSteam")] +[assembly: MelonLoader.MelonInfo(typeof(ml_lme.LeapMotionExtension), "LeapMotionExtension", "1.4.4", "SDraw", "https://github.com/SDraw/ml_mods_cvr")] +[assembly: MelonLoader.MelonGame(null, "ChilloutVR")] +[assembly: MelonLoader.MelonOptionalDependencies("ml_pmc")] +[assembly: MelonLoader.MelonPlatform(MelonLoader.MelonPlatformAttribute.CompatiblePlatforms.WINDOWS_X64)] +[assembly: MelonLoader.MelonPlatformDomain(MelonLoader.MelonPlatformDomainAttribute.CompatibleDomains.MONO)] +[assembly: MelonLoader.MelonAdditionalCredits("NotAKidOnSteam")] diff --git a/ml_lme/Utils.cs b/ml_lme/Utils.cs index ed3b80d..a3888db 100644 --- a/ml_lme/Utils.cs +++ b/ml_lme/Utils.cs @@ -1,50 +1,50 @@ -using ABI_RC.Core.Savior; -using ABI_RC.Core.UI; -using ABI_RC.Systems.InputManagement; -using System.Reflection; -using UnityEngine; - -namespace ml_lme -{ - static class Utils - { - static readonly FieldInfo ms_view = typeof(CohtmlControlledViewWrapper).GetField("_view", BindingFlags.NonPublic | BindingFlags.Instance); - - public static bool IsInVR() => ((CheckVR.Instance != null) && CheckVR.Instance.hasVrDeviceLoaded); - public static bool AreKnucklesInUse() => ((CVRInputManager.Instance._leftController == ABI_RC.Systems.InputManagement.XR.EXRControllerType.Index) || (CVRInputManager.Instance._rightController == ABI_RC.Systems.InputManagement.XR.EXRControllerType.Index)); - public static bool IsLeftHandTracked() => (CVRInputManager.Instance._leftController != ABI_RC.Systems.InputManagement.XR.EXRControllerType.None); - public static bool IsRightHandTracked() => (CVRInputManager.Instance._rightController != ABI_RC.Systems.InputManagement.XR.EXRControllerType.None); - - public static Matrix4x4 GetMatrix(this Transform p_transform, bool p_pos = true, bool p_rot = true, bool p_scl = false) - { - return Matrix4x4.TRS(p_pos ? p_transform.position : Vector3.zero, p_rot ? p_transform.rotation : Quaternion.identity, p_scl ? p_transform.lossyScale : Vector3.one); - } - - public static void ShowHUDNotification(string p_title, string p_message, string p_small = "", bool p_immediate = false) - { - if(CohtmlHud.Instance != null) - { - if(p_immediate) - CohtmlHud.Instance.ViewDropTextImmediate(p_title, p_message, p_small); - else - CohtmlHud.Instance.ViewDropText(p_title, p_message, p_small); - } - } - - static public void ExecuteScript(this CohtmlControlledViewWrapper p_instance, string p_script) => ((cohtml.Net.View)ms_view.GetValue(p_instance)).ExecuteScript(p_script); - - public static void Swap(ref T lhs, ref T rhs) - { - T temp = lhs; - lhs = rhs; - rhs = temp; - } - - public static float InverseLerpUnclamped(float a, float b, float value) - { - if(a != b) - return (value - a) / (b - a); - return 0f; - } - } -} +using ABI_RC.Core.Savior; +using ABI_RC.Core.UI; +using ABI_RC.Systems.InputManagement; +using System.Reflection; +using UnityEngine; + +namespace ml_lme +{ + static class Utils + { + static readonly FieldInfo ms_view = typeof(CohtmlControlledViewWrapper).GetField("_view", BindingFlags.NonPublic | BindingFlags.Instance); + + public static bool IsInVR() => ((CheckVR.Instance != null) && CheckVR.Instance.hasVrDeviceLoaded); + public static bool AreKnucklesInUse() => ((CVRInputManager.Instance._leftController == ABI_RC.Systems.InputManagement.XR.eXRControllerType.Index) || (CVRInputManager.Instance._rightController == ABI_RC.Systems.InputManagement.XR.eXRControllerType.Index)); + public static bool IsLeftHandTracked() => (CVRInputManager.Instance._leftController != ABI_RC.Systems.InputManagement.XR.eXRControllerType.None); + public static bool IsRightHandTracked() => (CVRInputManager.Instance._rightController != ABI_RC.Systems.InputManagement.XR.eXRControllerType.None); + + public static Matrix4x4 GetMatrix(this Transform p_transform, bool p_pos = true, bool p_rot = true, bool p_scl = false) + { + return Matrix4x4.TRS(p_pos ? p_transform.position : Vector3.zero, p_rot ? p_transform.rotation : Quaternion.identity, p_scl ? p_transform.lossyScale : Vector3.one); + } + + public static void ShowHUDNotification(string p_title, string p_message, string p_small = "", bool p_immediate = false) + { + if(CohtmlHud.Instance != null) + { + if(p_immediate) + CohtmlHud.Instance.ViewDropTextImmediate(p_title, p_message, p_small); + else + CohtmlHud.Instance.ViewDropText(p_title, p_message, p_small); + } + } + + static public void ExecuteScript(this CohtmlControlledViewWrapper p_instance, string p_script) => ((cohtml.Net.View)ms_view.GetValue(p_instance)).ExecuteScript(p_script); + + public static void Swap(ref T lhs, ref T rhs) + { + T temp = lhs; + lhs = rhs; + rhs = temp; + } + + public static float InverseLerpUnclamped(float a, float b, float value) + { + if(a != b) + return (value - a) / (b - a); + return 0f; + } + } +} diff --git a/ml_lme/ml_lme.csproj b/ml_lme/ml_lme.csproj index ca3804c..3360e4c 100644 --- a/ml_lme/ml_lme.csproj +++ b/ml_lme/ml_lme.csproj @@ -1,103 +1,103 @@ - - - - netstandard2.1 - x64 - LeapMotionExtension - 1.4.3 - SDraw - None - LeapMotionExtension - - - - none - false - - - - - - - - - - - - - - - - - - - - - resources/LeapC.dll - - - - - - D:\Games\Steam\steamapps\common\ChilloutVR\MelonLoader\net35\0Harmony.dll - false - - - D:\games\Steam\steamapps\common\ChilloutVR\ChilloutVR_Data\Managed\Assembly-CSharp.dll - false - - - D:\games\Steam\steamapps\common\ChilloutVR\ChilloutVR_Data\Managed\Assembly-CSharp-firstpass.dll - false - - - D:\games\Steam\steamapps\common\ChilloutVR\ChilloutVR_Data\Managed\cohtml.Net.dll - false - - - D:\games\Steam\steamapps\common\ChilloutVR\ChilloutVR_Data\Managed\Cohtml.Runtime.dll - false - - - D:\Games\Steam\steamapps\common\ChilloutVR\MelonLoader\net35\MelonLoader.dll - false - - - D:\games\Steam\steamapps\common\ChilloutVR\Mods\ml_pmc.dll - false - - - D:\games\Steam\steamapps\common\ChilloutVR\ChilloutVR_Data\Managed\UnityEngine.dll - false - - - D:\games\Steam\steamapps\common\ChilloutVR\ChilloutVR_Data\Managed\UnityEngine.AnimationModule.dll - false - - - D:\games\Steam\steamapps\common\ChilloutVR\ChilloutVR_Data\Managed\UnityEngine.AssetBundleModule.dll - false - - - D:\games\Steam\steamapps\common\ChilloutVR\ChilloutVR_Data\Managed\UnityEngine.CoreModule.dll - false - - - D:\games\Steam\steamapps\common\ChilloutVR\ChilloutVR_Data\Managed\UnityEngine.XRModule.dll - false - - - - - - - - - - - - - - - - + + + + netstandard2.1 + x64 + LeapMotionExtension + 1.4.4 + SDraw + None + LeapMotionExtension + + + + none + false + + + + + + + + + + + + + + + + + + + + + resources/LeapC.dll + + + + + + D:\Games\Steam\steamapps\common\ChilloutVR\MelonLoader\net35\0Harmony.dll + false + + + D:\games\Steam\steamapps\common\ChilloutVR\ChilloutVR_Data\Managed\Assembly-CSharp.dll + false + + + D:\games\Steam\steamapps\common\ChilloutVR\ChilloutVR_Data\Managed\Assembly-CSharp-firstpass.dll + false + + + D:\games\Steam\steamapps\common\ChilloutVR\ChilloutVR_Data\Managed\cohtml.Net.dll + false + + + D:\games\Steam\steamapps\common\ChilloutVR\ChilloutVR_Data\Managed\Cohtml.Runtime.dll + false + + + D:\Games\Steam\steamapps\common\ChilloutVR\MelonLoader\net35\MelonLoader.dll + false + + + D:\games\Steam\steamapps\common\ChilloutVR\Mods\ml_pmc.dll + false + + + D:\games\Steam\steamapps\common\ChilloutVR\ChilloutVR_Data\Managed\UnityEngine.dll + false + + + D:\games\Steam\steamapps\common\ChilloutVR\ChilloutVR_Data\Managed\UnityEngine.AnimationModule.dll + false + + + D:\games\Steam\steamapps\common\ChilloutVR\ChilloutVR_Data\Managed\UnityEngine.AssetBundleModule.dll + false + + + D:\games\Steam\steamapps\common\ChilloutVR\ChilloutVR_Data\Managed\UnityEngine.CoreModule.dll + false + + + D:\games\Steam\steamapps\common\ChilloutVR\ChilloutVR_Data\Managed\UnityEngine.XRModule.dll + false + + + + + + + + + + + + + + + + diff --git a/ml_pam/ArmMover.cs b/ml_pam/ArmMover.cs index 6091e3b..de0c12e 100644 --- a/ml_pam/ArmMover.cs +++ b/ml_pam/ArmMover.cs @@ -1,299 +1,299 @@ -using ABI.CCK.Components; -using ABI_RC.Core.InteractionSystem; -using ABI_RC.Core.Player; -using RootMotion.FinalIK; -using System.Reflection; -using UnityEngine; - -namespace ml_pam -{ - [DisallowMultipleComponent] - class ArmMover : MonoBehaviour - { - const float c_offsetLimit = 0.5f; - - static readonly float[] ms_tposeMuscles = typeof(ABI_RC.Systems.IK.SubSystems.BodySystem).GetField("TPoseMuscles", BindingFlags.Static | BindingFlags.NonPublic).GetValue(null) as float[]; - static readonly Vector4 ms_pointVector = new Vector4(0f, 0f, 0f, 1f); - static readonly Quaternion ms_offsetRight = Quaternion.Euler(0f, 0f, 90f); - static readonly Quaternion ms_offsetRightDesktop = Quaternion.Euler(0f, 270f, 0f); - static readonly Quaternion ms_palmToLeft = Quaternion.Euler(0f, 0f, -90f); - - bool m_inVR = false; - VRIK m_vrIK = null; - Vector2 m_armWeight = Vector2.zero; - Transform m_origRightHand = null; - float m_playspaceScale = 1f; - - bool m_enabled = true; - ArmIK m_armIK = null; - Transform m_target = null; - Transform m_rotationTarget = null; - CVRPickupObject m_pickup = null; - Matrix4x4 m_offset = Matrix4x4.identity; - bool m_targetActive = false; - - // Unity events - void Start() - { - m_inVR = Utils.IsInVR(); - - m_target = new GameObject("ArmPickupTarget").transform; - m_target.parent = PlayerSetup.Instance.GetActiveCamera().transform; - m_target.localPosition = Vector3.zero; - m_target.localRotation = Quaternion.identity; - - m_rotationTarget = new GameObject("RotationTarget").transform; - m_rotationTarget.parent = m_target; - m_rotationTarget.localPosition = new Vector3(c_offsetLimit * Settings.GrabOffset, 0f, 0f); - m_rotationTarget.localRotation = Quaternion.identity; - - m_enabled = Settings.Enabled; - - Settings.EnabledChange += this.SetEnabled; - Settings.GrabOffsetChange += this.SetGrabOffset; - } - - void OnDestroy() - { - Settings.EnabledChange -= this.SetEnabled; - Settings.GrabOffsetChange -= this.SetGrabOffset; - } - - void Update() - { - if(m_enabled && !ReferenceEquals(m_pickup, null)) - { - if(m_pickup != null) - { - Matrix4x4 l_result = m_pickup.transform.GetMatrix() * m_offset; - m_target.position = l_result * ms_pointVector; - } - else - this.OnPickupDrop(m_pickup); - } - } - - // IK updates - void OnIKPreUpdate() - { - m_armWeight.Set(m_vrIK.solver.rightArm.positionWeight, m_vrIK.solver.rightArm.rotationWeight); - - if(m_targetActive && (Mathf.Approximately(m_armWeight.x, 0f) || Mathf.Approximately(m_armWeight.y, 0f))) - { - m_vrIK.solver.rightArm.positionWeight = 1f; - m_vrIK.solver.rightArm.rotationWeight = 1f; - } - } - void OnIKPostUpdate() - { - m_vrIK.solver.rightArm.positionWeight = m_armWeight.x; - m_vrIK.solver.rightArm.rotationWeight = m_armWeight.y; - } - - // Settings - void SetEnabled(bool p_state) - { - m_enabled = p_state; - - RefreshArmIK(); - if(m_enabled) - RestorePickup(); - else - RestoreVRIK(); - } - - void SetGrabOffset(float p_value) - { - if(m_rotationTarget != null) - m_rotationTarget.localPosition = new Vector3(c_offsetLimit * m_playspaceScale * p_value, 0f, 0f); - } - - // Game events - internal void OnAvatarClear() - { - m_vrIK = null; - m_origRightHand = null; - m_armIK = null; - m_targetActive = false; - } - - internal void OnAvatarSetup() - { - // Recheck if user could switch to VR - if(m_inVR != Utils.IsInVR()) - { - m_target.parent = PlayerSetup.Instance.GetActiveCamera().transform; - m_target.localPosition = Vector3.zero; - m_target.localRotation = Quaternion.identity; - } - - m_inVR = Utils.IsInVR(); - m_vrIK = PlayerSetup.Instance._animator.GetComponent(); - - if(PlayerSetup.Instance._animator.isHuman) - { - Vector3 l_hipsPos = Vector3.zero; - Transform l_hips = PlayerSetup.Instance._animator.GetBoneTransform(HumanBodyBones.Hips); - if(l_hips != null) - l_hipsPos = l_hips.localPosition; - - HumanPose l_currentPose = new HumanPose(); - HumanPoseHandler l_poseHandler = null; - - if(!m_inVR) - { - l_poseHandler = new HumanPoseHandler(PlayerSetup.Instance._animator.avatar, PlayerSetup.Instance._avatar.transform); - l_poseHandler.GetHumanPose(ref l_currentPose); - - HumanPose l_tPose = new HumanPose - { - bodyPosition = l_currentPose.bodyPosition, - bodyRotation = l_currentPose.bodyRotation, - muscles = new float[l_currentPose.muscles.Length] - }; - for(int i = 0; i < l_tPose.muscles.Length; i++) - l_tPose.muscles[i] = ms_tposeMuscles[i]; - - l_poseHandler.SetHumanPose(ref l_tPose); - } - - Transform l_hand = PlayerSetup.Instance._animator.GetBoneTransform(HumanBodyBones.RightHand); - if(l_hand != null) - m_rotationTarget.localRotation = (ms_palmToLeft * (m_inVR ? ms_offsetRight : ms_offsetRightDesktop)) * (PlayerSetup.Instance._avatar.transform.GetMatrix().inverse * l_hand.GetMatrix()).rotation; - - if(m_vrIK == null) - { - Transform l_chest = PlayerSetup.Instance._animator.GetBoneTransform(HumanBodyBones.UpperChest); - if(l_chest == null) - l_chest = PlayerSetup.Instance._animator.GetBoneTransform(HumanBodyBones.Chest); - if(l_chest == null) - l_chest = PlayerSetup.Instance._animator.GetBoneTransform(HumanBodyBones.Spine); - - m_armIK = PlayerSetup.Instance._avatar.AddComponent(); - m_armIK.solver.isLeft = false; - m_armIK.solver.SetChain( - l_chest, - PlayerSetup.Instance._animator.GetBoneTransform(HumanBodyBones.RightShoulder), - PlayerSetup.Instance._animator.GetBoneTransform(HumanBodyBones.RightUpperArm), - PlayerSetup.Instance._animator.GetBoneTransform(HumanBodyBones.RightLowerArm), - l_hand, - PlayerSetup.Instance._animator.transform - ); - m_armIK.solver.arm.target = m_rotationTarget; - m_armIK.solver.arm.positionWeight = 1f; - m_armIK.solver.arm.rotationWeight = 1f; - m_armIK.solver.IKPositionWeight = 0f; - m_armIK.solver.IKRotationWeight = 0f; - m_armIK.enabled = m_enabled; - } - else - { - m_origRightHand = m_vrIK.solver.rightArm.target; - m_vrIK.solver.OnPreUpdate += this.OnIKPreUpdate; - m_vrIK.solver.OnPostUpdate += this.OnIKPostUpdate; - } - - l_poseHandler?.SetHumanPose(ref l_currentPose); - l_poseHandler?.Dispose(); - - if(l_hips != null) - l_hips.localPosition = l_hipsPos; - } - - if(m_enabled) - RestorePickup(); - } - - internal void OnPickupGrab(CVRPickupObject p_pickup, ControllerRay p_ray, Vector3 p_hit) - { - if(p_ray == ViewManager.Instance.desktopControllerRay) - { - m_pickup = p_pickup; - - // Set offsets - if(m_pickup.gripType == CVRPickupObject.GripType.Origin) - { - if(m_pickup.ikReference != null) - m_offset = (m_pickup.transform.GetMatrix().inverse * m_pickup.ikReference.GetMatrix()); - else - { - if(m_pickup.gripOrigin != null) - m_offset = m_pickup.transform.GetMatrix().inverse * m_pickup.gripOrigin.GetMatrix(); - } - } - else - m_offset = m_pickup.transform.GetMatrix().inverse * Matrix4x4.Translate(p_hit); - - if(m_enabled) - { - if((m_vrIK != null) && !m_targetActive) - { - m_vrIK.solver.rightArm.target = m_rotationTarget; - m_targetActive = true; - } - - if(m_armIK != null) - { - m_armIK.solver.IKPositionWeight = 1f; - m_armIK.solver.IKRotationWeight = 1f; - } - } - } - } - - internal void OnPickupDrop(CVRPickupObject p_pickup) - { - if(m_pickup == p_pickup) - { - m_pickup = null; - - if(m_enabled) - { - RestoreVRIK(); - - if(m_armIK != null) - { - m_armIK.solver.IKPositionWeight = 0f; - m_armIK.solver.IKRotationWeight = 0f; - } - } - } - } - - internal void OnPlayspaceScale(float p_relation) - { - m_playspaceScale = p_relation; - SetGrabOffset(Settings.GrabOffset); - } - - // Arbitrary - void RestorePickup() - { - if((m_vrIK != null) && (m_pickup != null)) - { - m_vrIK.solver.rightArm.target = m_rotationTarget; - m_targetActive = true; - } - if((m_armIK != null) && (m_pickup != null)) - { - m_armIK.solver.IKPositionWeight = 1f; - m_armIK.solver.IKRotationWeight = 1f; - } - } - - void RestoreVRIK() - { - if((m_vrIK != null) && m_targetActive) - { - m_vrIK.solver.rightArm.target = m_origRightHand; - m_targetActive = false; - } - } - - void RefreshArmIK() - { - if(m_armIK != null) - m_armIK.enabled = m_enabled; - } - } -} +using ABI.CCK.Components; +using ABI_RC.Core.InteractionSystem; +using ABI_RC.Core.Player; +using RootMotion.FinalIK; +using System.Reflection; +using UnityEngine; + +namespace ml_pam +{ + [DisallowMultipleComponent] + class ArmMover : MonoBehaviour + { + const float c_offsetLimit = 0.5f; + + static readonly float[] ms_tposeMuscles = typeof(ABI_RC.Systems.IK.SubSystems.BodySystem).GetField("TPoseMuscles", BindingFlags.Static | BindingFlags.NonPublic).GetValue(null) as float[]; + static readonly Vector4 ms_pointVector = new Vector4(0f, 0f, 0f, 1f); + static readonly Quaternion ms_offsetRight = Quaternion.Euler(0f, 0f, 90f); + static readonly Quaternion ms_offsetRightDesktop = Quaternion.Euler(0f, 270f, 0f); + static readonly Quaternion ms_palmToLeft = Quaternion.Euler(0f, 0f, -90f); + + bool m_inVR = false; + VRIK m_vrIK = null; + Vector2 m_armWeight = Vector2.zero; + Transform m_origRightHand = null; + float m_playspaceScale = 1f; + + bool m_enabled = true; + ArmIK m_armIK = null; + Transform m_target = null; + Transform m_rotationTarget = null; + CVRPickupObject m_pickup = null; + Matrix4x4 m_offset = Matrix4x4.identity; + bool m_targetActive = false; + + // Unity events + void Start() + { + m_inVR = Utils.IsInVR(); + + m_target = new GameObject("ArmPickupTarget").transform; + m_target.parent = PlayerSetup.Instance.GetActiveCamera().transform; + m_target.localPosition = Vector3.zero; + m_target.localRotation = Quaternion.identity; + + m_rotationTarget = new GameObject("RotationTarget").transform; + m_rotationTarget.parent = m_target; + m_rotationTarget.localPosition = new Vector3(c_offsetLimit * Settings.GrabOffset, 0f, 0f); + m_rotationTarget.localRotation = Quaternion.identity; + + m_enabled = Settings.Enabled; + + Settings.EnabledChange += this.SetEnabled; + Settings.GrabOffsetChange += this.SetGrabOffset; + } + + void OnDestroy() + { + Settings.EnabledChange -= this.SetEnabled; + Settings.GrabOffsetChange -= this.SetGrabOffset; + } + + void Update() + { + if(m_enabled && !ReferenceEquals(m_pickup, null)) + { + if(m_pickup != null) + { + Matrix4x4 l_result = m_pickup.transform.GetMatrix() * m_offset; + m_target.position = l_result * ms_pointVector; + } + else + this.OnPickupDrop(m_pickup); + } + } + + // IK updates + void OnIKPreUpdate() + { + m_armWeight.Set(m_vrIK.solver.rightArm.positionWeight, m_vrIK.solver.rightArm.rotationWeight); + + if(m_targetActive && (Mathf.Approximately(m_armWeight.x, 0f) || Mathf.Approximately(m_armWeight.y, 0f))) + { + m_vrIK.solver.rightArm.positionWeight = 1f; + m_vrIK.solver.rightArm.rotationWeight = 1f; + } + } + void OnIKPostUpdate() + { + m_vrIK.solver.rightArm.positionWeight = m_armWeight.x; + m_vrIK.solver.rightArm.rotationWeight = m_armWeight.y; + } + + // Settings + void SetEnabled(bool p_state) + { + m_enabled = p_state; + + RefreshArmIK(); + if(m_enabled) + RestorePickup(); + else + RestoreVRIK(); + } + + void SetGrabOffset(float p_value) + { + if(m_rotationTarget != null) + m_rotationTarget.localPosition = new Vector3(c_offsetLimit * m_playspaceScale * p_value, 0f, 0f); + } + + // Game events + internal void OnAvatarClear() + { + m_vrIK = null; + m_origRightHand = null; + m_armIK = null; + m_targetActive = false; + } + + internal void OnAvatarSetup() + { + // Recheck if user could switch to VR + if(m_inVR != Utils.IsInVR()) + { + m_target.parent = PlayerSetup.Instance.GetActiveCamera().transform; + m_target.localPosition = Vector3.zero; + m_target.localRotation = Quaternion.identity; + } + + m_inVR = Utils.IsInVR(); + m_vrIK = PlayerSetup.Instance._animator.GetComponent(); + + if(PlayerSetup.Instance._animator.isHuman) + { + Vector3 l_hipsPos = Vector3.zero; + Transform l_hips = PlayerSetup.Instance._animator.GetBoneTransform(HumanBodyBones.Hips); + if(l_hips != null) + l_hipsPos = l_hips.localPosition; + + HumanPose l_currentPose = new HumanPose(); + HumanPoseHandler l_poseHandler = null; + + if(!m_inVR) + { + l_poseHandler = new HumanPoseHandler(PlayerSetup.Instance._animator.avatar, PlayerSetup.Instance._avatar.transform); + l_poseHandler.GetHumanPose(ref l_currentPose); + + HumanPose l_tPose = new HumanPose + { + bodyPosition = l_currentPose.bodyPosition, + bodyRotation = l_currentPose.bodyRotation, + muscles = new float[l_currentPose.muscles.Length] + }; + for(int i = 0; i < l_tPose.muscles.Length; i++) + l_tPose.muscles[i] = ms_tposeMuscles[i]; + + l_poseHandler.SetHumanPose(ref l_tPose); + } + + Transform l_hand = PlayerSetup.Instance._animator.GetBoneTransform(HumanBodyBones.RightHand); + if(l_hand != null) + m_rotationTarget.localRotation = (ms_palmToLeft * (m_inVR ? ms_offsetRight : ms_offsetRightDesktop)) * (PlayerSetup.Instance._avatar.transform.GetMatrix().inverse * l_hand.GetMatrix()).rotation; + + if(m_vrIK == null) + { + Transform l_chest = PlayerSetup.Instance._animator.GetBoneTransform(HumanBodyBones.UpperChest); + if(l_chest == null) + l_chest = PlayerSetup.Instance._animator.GetBoneTransform(HumanBodyBones.Chest); + if(l_chest == null) + l_chest = PlayerSetup.Instance._animator.GetBoneTransform(HumanBodyBones.Spine); + + m_armIK = PlayerSetup.Instance._avatar.AddComponent(); + m_armIK.solver.isLeft = false; + m_armIK.solver.SetChain( + l_chest, + PlayerSetup.Instance._animator.GetBoneTransform(HumanBodyBones.RightShoulder), + PlayerSetup.Instance._animator.GetBoneTransform(HumanBodyBones.RightUpperArm), + PlayerSetup.Instance._animator.GetBoneTransform(HumanBodyBones.RightLowerArm), + l_hand, + PlayerSetup.Instance._animator.transform + ); + m_armIK.solver.arm.target = m_rotationTarget; + m_armIK.solver.arm.positionWeight = 1f; + m_armIK.solver.arm.rotationWeight = 1f; + m_armIK.solver.IKPositionWeight = 0f; + m_armIK.solver.IKRotationWeight = 0f; + m_armIK.enabled = m_enabled; + } + else + { + m_origRightHand = m_vrIK.solver.rightArm.target; + m_vrIK.solver.OnPreUpdate += this.OnIKPreUpdate; + m_vrIK.solver.OnPostUpdate += this.OnIKPostUpdate; + } + + l_poseHandler?.SetHumanPose(ref l_currentPose); + l_poseHandler?.Dispose(); + + if(l_hips != null) + l_hips.localPosition = l_hipsPos; + } + + if(m_enabled) + RestorePickup(); + } + + internal void OnPickupGrab(CVRPickupObject p_pickup, ControllerRay p_ray, Vector3 p_hit) + { + if(p_ray == ViewManager.Instance.desktopControllerRay) + { + m_pickup = p_pickup; + + // Set offsets + if(m_pickup.gripType == CVRPickupObject.GripType.Origin) + { + if(m_pickup.ikReference != null) + m_offset = (m_pickup.transform.GetMatrix().inverse * m_pickup.ikReference.GetMatrix()); + else + { + if(m_pickup.gripOrigin != null) + m_offset = m_pickup.transform.GetMatrix().inverse * m_pickup.gripOrigin.GetMatrix(); + } + } + else + m_offset = m_pickup.transform.GetMatrix().inverse * Matrix4x4.Translate(p_hit); + + if(m_enabled) + { + if((m_vrIK != null) && !m_targetActive) + { + m_vrIK.solver.rightArm.target = m_rotationTarget; + m_targetActive = true; + } + + if(m_armIK != null) + { + m_armIK.solver.IKPositionWeight = 1f; + m_armIK.solver.IKRotationWeight = 1f; + } + } + } + } + + internal void OnPickupDrop(CVRPickupObject p_pickup) + { + if(m_pickup == p_pickup) + { + m_pickup = null; + + if(m_enabled) + { + RestoreVRIK(); + + if(m_armIK != null) + { + m_armIK.solver.IKPositionWeight = 0f; + m_armIK.solver.IKRotationWeight = 0f; + } + } + } + } + + internal void OnPlayspaceScale(float p_relation) + { + m_playspaceScale = p_relation; + SetGrabOffset(Settings.GrabOffset); + } + + // Arbitrary + void RestorePickup() + { + if((m_vrIK != null) && (m_pickup != null)) + { + m_vrIK.solver.rightArm.target = m_rotationTarget; + m_targetActive = true; + } + if((m_armIK != null) && (m_pickup != null)) + { + m_armIK.solver.IKPositionWeight = 1f; + m_armIK.solver.IKRotationWeight = 1f; + } + } + + void RestoreVRIK() + { + if((m_vrIK != null) && m_targetActive) + { + m_vrIK.solver.rightArm.target = m_origRightHand; + m_targetActive = false; + } + } + + void RefreshArmIK() + { + if(m_armIK != null) + m_armIK.enabled = m_enabled; + } + } +} diff --git a/ml_pmc/Utils.cs b/ml_pmc/Utils.cs index 0b93404..19fc92c 100644 --- a/ml_pmc/Utils.cs +++ b/ml_pmc/Utils.cs @@ -1,79 +1,79 @@ -using ABI.CCK.Components; -using ABI_RC.Core.Player; -using ABI_RC.Core.Savior; -using ABI_RC.Systems.InputManagement; -using System.Linq; -using System.Reflection; -using UnityEngine; - -namespace ml_pmc -{ - static class Utils - { - static readonly (int, int)[] ms_sideMuscles = new (int, int)[] - { - (29,21), (30,22), (31,23), (32,24), (33,25), (34,26), (35,27), (36,28), - (46,37), (47,38), (48,39), (49,40), (50,41), (51,42), (52,43), (53,44), (54,45), - (75,55), (76,56), (77,57), (78,58), (79,59), (80,60), (81,61), (82,62), (83,63), (84,64), - (85,65), (86,66), (87,67), (88,68), (89, 69), (90,70), (91,71), (92,72), (93,73), (94,74) - }; - static readonly int[] ms_centralMuscles = new int[] { 1, 2, 4, 5, 7, 8, 10, 11, 13, 14, 16, 18, 20 }; - - public static bool IsInVR() => ((CheckVR.Instance != null) && CheckVR.Instance.hasVrDeviceLoaded); - public static bool AreKnucklesInUse() => ((CVRInputManager.Instance._leftController == ABI_RC.Systems.InputManagement.XR.EXRControllerType.Index) || (CVRInputManager.Instance._rightController == ABI_RC.Systems.InputManagement.XR.EXRControllerType.Index)); - - public static bool IsWorldSafe() => ((CVRWorld.Instance != null) && CVRWorld.Instance.allowFlying); - public static bool IsCombatSafe() => ((CombatSystem.Instance == null) || !CombatSystem.Instance.isDown); - - public static float GetWorldMovementLimit() - { - float l_result = 1f; - if(CVRWorld.Instance != null) - { - l_result = CVRWorld.Instance.baseMovementSpeed; - l_result *= CVRWorld.Instance.sprintMultiplier; - l_result *= CVRWorld.Instance.inAirMovementMultiplier; - l_result *= CVRWorld.Instance.flyMultiplier; - } - return l_result; - } - - public static Matrix4x4 GetMatrix(this Transform p_transform, bool p_pos = true, bool p_rot = true, bool p_scl = false) - { - return Matrix4x4.TRS(p_pos ? p_transform.position : Vector3.zero, p_rot ? p_transform.rotation : Quaternion.identity, p_scl ? p_transform.lossyScale : Vector3.one); - } - - public static void CopyTo(this HumanPose p_source, ref HumanPose p_target) - { - p_target.bodyPosition = p_source.bodyPosition; - p_target.bodyRotation = p_source.bodyRotation; - - int l_count = Mathf.Min(p_source.muscles.Length, p_target.muscles.Length); - for(int i = 0; i < l_count; i++) - p_target.muscles[i] = p_source.muscles[i]; - } - - public static void MirrorPose(ref HumanPose p_pose) - { - int l_count = p_pose.muscles.Length; - foreach(var l_pair in ms_sideMuscles) - { - if((l_count > l_pair.Item1) && (l_count > l_pair.Item2)) - { - float l_temp = p_pose.muscles[l_pair.Item1]; - p_pose.muscles[l_pair.Item1] = p_pose.muscles[l_pair.Item2]; - p_pose.muscles[l_pair.Item2] = l_temp; - } - } - foreach(int l_index in ms_centralMuscles) - { - if(l_count > l_index) - p_pose.muscles[l_index] *= -1f; - } - - p_pose.bodyRotation.x *= -1f; - p_pose.bodyRotation.w *= -1f; - p_pose.bodyPosition.x *= -1f; - } - } -} +using ABI.CCK.Components; +using ABI_RC.Core.Player; +using ABI_RC.Core.Savior; +using ABI_RC.Systems.InputManagement; +using System.Linq; +using System.Reflection; +using UnityEngine; + +namespace ml_pmc +{ + static class Utils + { + static readonly (int, int)[] ms_sideMuscles = new (int, int)[] + { + (29,21), (30,22), (31,23), (32,24), (33,25), (34,26), (35,27), (36,28), + (46,37), (47,38), (48,39), (49,40), (50,41), (51,42), (52,43), (53,44), (54,45), + (75,55), (76,56), (77,57), (78,58), (79,59), (80,60), (81,61), (82,62), (83,63), (84,64), + (85,65), (86,66), (87,67), (88,68), (89, 69), (90,70), (91,71), (92,72), (93,73), (94,74) + }; + static readonly int[] ms_centralMuscles = new int[] { 1, 2, 4, 5, 7, 8, 10, 11, 13, 14, 16, 18, 20 }; + + public static bool IsInVR() => ((CheckVR.Instance != null) && CheckVR.Instance.hasVrDeviceLoaded); + public static bool AreKnucklesInUse() => ((CVRInputManager.Instance._leftController == ABI_RC.Systems.InputManagement.XR.eXRControllerType.Index) || (CVRInputManager.Instance._rightController == ABI_RC.Systems.InputManagement.XR.eXRControllerType.Index)); + + public static bool IsWorldSafe() => ((CVRWorld.Instance != null) && CVRWorld.Instance.allowFlying); + public static bool IsCombatSafe() => ((CombatSystem.Instance == null) || !CombatSystem.Instance.isDown); + + public static float GetWorldMovementLimit() + { + float l_result = 1f; + if(CVRWorld.Instance != null) + { + l_result = CVRWorld.Instance.baseMovementSpeed; + l_result *= CVRWorld.Instance.sprintMultiplier; + l_result *= CVRWorld.Instance.inAirMovementMultiplier; + l_result *= CVRWorld.Instance.flyMultiplier; + } + return l_result; + } + + public static Matrix4x4 GetMatrix(this Transform p_transform, bool p_pos = true, bool p_rot = true, bool p_scl = false) + { + return Matrix4x4.TRS(p_pos ? p_transform.position : Vector3.zero, p_rot ? p_transform.rotation : Quaternion.identity, p_scl ? p_transform.lossyScale : Vector3.one); + } + + public static void CopyTo(this HumanPose p_source, ref HumanPose p_target) + { + p_target.bodyPosition = p_source.bodyPosition; + p_target.bodyRotation = p_source.bodyRotation; + + int l_count = Mathf.Min(p_source.muscles.Length, p_target.muscles.Length); + for(int i = 0; i < l_count; i++) + p_target.muscles[i] = p_source.muscles[i]; + } + + public static void MirrorPose(ref HumanPose p_pose) + { + int l_count = p_pose.muscles.Length; + foreach(var l_pair in ms_sideMuscles) + { + if((l_count > l_pair.Item1) && (l_count > l_pair.Item2)) + { + float l_temp = p_pose.muscles[l_pair.Item1]; + p_pose.muscles[l_pair.Item1] = p_pose.muscles[l_pair.Item2]; + p_pose.muscles[l_pair.Item2] = l_temp; + } + } + foreach(int l_index in ms_centralMuscles) + { + if(l_count > l_index) + p_pose.muscles[l_index] *= -1f; + } + + p_pose.bodyRotation.x *= -1f; + p_pose.bodyRotation.w *= -1f; + p_pose.bodyPosition.x *= -1f; + } + } +} diff --git a/ml_vei/Main.cs b/ml_vei/Main.cs index 7379cbe..dcf0cb3 100644 --- a/ml_vei/Main.cs +++ b/ml_vei/Main.cs @@ -1,56 +1,56 @@ -using ABI_RC.Systems.InputManagement; -using ABI_RC.Systems.InputManagement.XR; -using System; -using System.Reflection; - -namespace ml_vei -{ - public class ViveExtendedInput : MelonLoader.MelonMod - { - public override void OnInitializeMelon() - { - Settings.Init(); - - HarmonyInstance.Patch( - typeof(CVRXRModule).GetMethod("Update_Gestures_Vive", BindingFlags.NonPublic | BindingFlags.Instance), - null, - new HarmonyLib.HarmonyMethod(typeof(ViveExtendedInput).GetMethod(nameof(OnViveGesturesUpdate_Postfix), BindingFlags.Static | BindingFlags.NonPublic)) - ); - } - - static void OnViveGesturesUpdate_Postfix(ref CVRXRModule __instance) - { - try - { - if(Settings.Gestures) - { - float l_mag = ((!__instance.HasEmoteOverride) ? __instance.Primary2DAxis : __instance.EmoteOverride).magnitude; - if(__instance.ViveDirectionPressed && (l_mag >= CVRInputManager.VrViveGestureDeadZone)) - { - if(Settings.GripTrigger) - { - switch(Settings.AxisPriority) - { - case Settings.PriorityAxis.Grip: - __instance.GestureRaw = ((__instance.Grip > 0.5f) ? -1f : __instance.Trigger); - break; - - case Settings.PriorityAxis.Trigger: - __instance.GestureRaw = (!UnityEngine.Mathf.Approximately(__instance.Trigger, 0f) ? __instance.Trigger : ((__instance.Grip > 0.5f) ? -1f : 0f)); - break; - } - } - else - __instance.GestureRaw = 0f; - - __instance.Gesture = __instance.GestureRaw; - } - } - } - catch(Exception e) - { - MelonLoader.MelonLogger.Error(e); - } - } - } -} +using ABI_RC.Systems.InputManagement; +using ABI_RC.Systems.InputManagement.XR; +using System; +using System.Reflection; + +namespace ml_vei +{ + public class ViveExtendedInput : MelonLoader.MelonMod + { + public override void OnInitializeMelon() + { + Settings.Init(); + + HarmonyInstance.Patch( + typeof(CVRXRModule).GetMethod("Update_Gestures_Vive", BindingFlags.NonPublic | BindingFlags.Instance), + null, + new HarmonyLib.HarmonyMethod(typeof(ViveExtendedInput).GetMethod(nameof(OnViveGesturesUpdate_Postfix), BindingFlags.Static | BindingFlags.NonPublic)) + ); + } + + static void OnViveGesturesUpdate_Postfix(ref CVRXRModule __instance) + { + try + { + if(Settings.Gestures) + { + float l_mag = ((!__instance.HasEmoteOverride) ? __instance.Primary2DAxis : __instance.EmoteOverride).magnitude; + if(__instance.ViveDirectionPressed && (l_mag >= CVRInputManager.VrViveGestureDeadZone)) + { + if(Settings.GripTrigger) + { + switch(Settings.AxisPriority) + { + case Settings.PriorityAxis.Grip: + __instance.GestureRaw = ((__instance.Grip > 0.5f) ? -1f : __instance.Trigger); + break; + + case Settings.PriorityAxis.Trigger: + __instance.GestureRaw = (!UnityEngine.Mathf.Approximately(__instance.Trigger, 0f) ? __instance.Trigger : ((__instance.Grip > 0.5f) ? -1f : 0f)); + break; + } + } + else + __instance.GestureRaw = 0f; + + __instance.Gesture = __instance.GestureRaw; + } + } + } + catch(Exception e) + { + MelonLoader.MelonLogger.Error(e); + } + } + } +}