diff --git a/ml_amt/.github/img_02.png b/ml_amt/.github/img_02.png deleted file mode 100644 index d5e1486..0000000 Binary files a/ml_amt/.github/img_02.png and /dev/null differ diff --git a/ml_amt/.github/img_03.png b/ml_amt/.github/img_03.png deleted file mode 100644 index 898b2ea..0000000 Binary files a/ml_amt/.github/img_03.png and /dev/null differ diff --git a/ml_amt/.github/img_04.png b/ml_amt/.github/img_04.png deleted file mode 100644 index aca0733..0000000 Binary files a/ml_amt/.github/img_04.png and /dev/null differ diff --git a/ml_amt/.github/img_05.png b/ml_amt/.github/img_05.png deleted file mode 100644 index e359c5f..0000000 Binary files a/ml_amt/.github/img_05.png and /dev/null differ diff --git a/ml_amt/.github/img_06.png b/ml_amt/.github/img_06.png deleted file mode 100644 index 02a1515..0000000 Binary files a/ml_amt/.github/img_06.png and /dev/null differ diff --git a/ml_amt/.github/img_07.png b/ml_amt/.github/img_07.png deleted file mode 100644 index bf9b3b6..0000000 Binary files a/ml_amt/.github/img_07.png and /dev/null differ diff --git a/ml_amt/.github/img_08.png b/ml_amt/.github/img_08.png deleted file mode 100644 index dd4462d..0000000 Binary files a/ml_amt/.github/img_08.png and /dev/null differ diff --git a/ml_amt/Main.cs b/ml_amt/Main.cs index 011a084..a95dc0e 100644 --- a/ml_amt/Main.cs +++ b/ml_amt/Main.cs @@ -13,10 +13,13 @@ namespace ml_amt ms_instance = this; Settings.Init(); - Settings.IKOverrideChange += this.OnIKOverrideChange; + Settings.IKOverrideCrouchChange += this.OnIKOverrideCrouchChange; Settings.CrouchLimitChange += this.OnCrouchLimitChange; - Settings.DetectPoseChange += this.OnDetectPoseChange; + Settings.IKOverrideProneChange += this.OnIKOverrideProneChange; Settings.ProneLimitChange += this.OnProneLimitChange; + Settings.PoseTransitionsChange += this.OnPoseTransitonsChange; + Settings.AdjustedMovementChange += this.OnAdjustedMovementChange; + Settings.IKOverrideFlyChange += this.OnIKOverrideFlyChange; HarmonyInstance.Patch( typeof(PlayerSetup).GetMethod(nameof(PlayerSetup.ClearAvatar)), @@ -38,33 +41,50 @@ namespace ml_amt yield return null; m_localTweaker = PlayerSetup.Instance.gameObject.AddComponent(); - m_localTweaker.SetIKOverride(Settings.IKOverride); + m_localTweaker.SetIKOverrideCrouch(Settings.IKOverrideCrouch); m_localTweaker.SetCrouchLimit(Settings.CrouchLimit); - m_localTweaker.SetDetectPose(Settings.DetectPose); + m_localTweaker.SetIKOverrideCrouch(Settings.IKOverrideProne); m_localTweaker.SetProneLimit(Settings.ProneLimit); + m_localTweaker.SetPoseTransitions(Settings.PoseTransitions); + m_localTweaker.SetAdjustedMovement(Settings.AdjustedMovement); + m_localTweaker.SetIKOverrideFly(Settings.IKOverrideFly); } - - - void OnIKOverrideChange(bool p_state) + + void OnIKOverrideCrouchChange(bool p_state) { if(m_localTweaker != null) - m_localTweaker.SetIKOverride(p_state); + m_localTweaker.SetIKOverrideCrouch(p_state); } void OnCrouchLimitChange(float p_value) { if(m_localTweaker != null) m_localTweaker.SetCrouchLimit(p_value); } - void OnDetectPoseChange(bool p_state) + void OnIKOverrideProneChange(bool p_state) { if(m_localTweaker != null) - m_localTweaker.SetDetectPose(p_state); + m_localTweaker.SetIKOverrideProne(p_state); } void OnProneLimitChange(float p_value) { if(m_localTweaker != null) m_localTweaker.SetProneLimit(p_value); } + void OnPoseTransitonsChange(bool p_state) + { + if(m_localTweaker != null) + m_localTweaker.SetPoseTransitions(p_state); + } + void OnAdjustedMovementChange(bool p_state) + { + if(m_localTweaker != null) + m_localTweaker.SetAdjustedMovement(p_state); + } + void OnIKOverrideFlyChange(bool p_state) + { + if(m_localTweaker != null) + m_localTweaker.SetIKOverrideFly(p_state); + } static void OnAvatarClear_Postfix() => ms_instance?.OnAvatarClear(); void OnAvatarClear() diff --git a/ml_amt/MotionTweaker.cs b/ml_amt/MotionTweaker.cs index dee04d2..2c48ae2 100644 --- a/ml_amt/MotionTweaker.cs +++ b/ml_amt/MotionTweaker.cs @@ -1,4 +1,5 @@ using ABI_RC.Core.Player; +using ABI_RC.Systems.MovementSystem; using RootMotion.FinalIK; using System.Collections.Generic; using UnityEngine; @@ -8,11 +9,14 @@ namespace ml_amt class MotionTweaker : MonoBehaviour { static System.Reflection.FieldInfo ms_rootVelocity = typeof(IKSolverVR).GetField("rootVelocity", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance); + static System.Reflection.FieldInfo ms_groundedRaw = typeof(MovementSystem).GetField("_isGroundedRaw", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance); enum ParameterType { - Upright + Upright, + GroundedRaw } + enum ParameterSyncType { Local, @@ -41,18 +45,21 @@ namespace ml_amt bool m_avatarReady = false; bool m_compatibleAvatar = false; - - bool m_ikOverride = true; - float m_currentUpright = 1f; + float m_upright = 1f; PoseState m_poseState = PoseState.Standing; + bool m_ikOverrideCrouch = true; float m_crouchLimit = 0.65f; bool m_customCrouchLimit = false; - bool m_detectPose = true; + bool m_ikOverrideProne = true; float m_proneLimit = 0.3f; bool m_customProneLimit = false; + bool m_poseTransitions = true; + bool m_adjustedMovement = true; + bool m_ikOverrideFly = true; + bool m_customLocomotionOffset = false; Vector3 m_locomotionOffset = Vector3.zero; @@ -71,36 +78,51 @@ namespace ml_amt Matrix4x4 l_hmdMatrix = PlayerSetup.Instance.transform.GetMatrix().inverse * (PlayerSetup.Instance._inVr ? PlayerSetup.Instance.vrHeadTracker.transform.GetMatrix() : PlayerSetup.Instance.desktopCameraRig.transform.GetMatrix()); float l_currentHeight = Mathf.Clamp((l_hmdMatrix * ms_pointVector).y, 0f, float.MaxValue); float l_avatarViewHeight = Mathf.Clamp(PlayerSetup.Instance.GetViewPointHeight() * PlayerSetup.Instance._avatar.transform.localScale.y, 0f, float.MaxValue); - m_currentUpright = Mathf.Clamp((((l_currentHeight > 0f) && (l_avatarViewHeight > 0f)) ? (l_currentHeight / l_avatarViewHeight) : 0f), 0f, 1f); - PoseState l_poseState = (m_currentUpright <= m_proneLimit) ? PoseState.Proning : ((m_currentUpright <= m_crouchLimit) ? PoseState.Crouching : PoseState.Standing); + m_upright = Mathf.Clamp((((l_currentHeight > 0f) && (l_avatarViewHeight > 0f)) ? (l_currentHeight / l_avatarViewHeight) : 0f), 0f, 1f); + PoseState l_poseState = (m_upright <= m_proneLimit) ? PoseState.Proning : ((m_upright <= m_crouchLimit) ? PoseState.Crouching : PoseState.Standing); if((m_vrIk != null) && m_vrIk.enabled) { - if(m_ikOverride && (m_poseState != l_poseState) && (l_poseState == PoseState.Standing)) - ms_rootVelocity.SetValue(m_vrIk.solver, Vector3.zero); + if(m_poseState != l_poseState) + { + // Weird fix of torso shaking + if(m_ikOverrideCrouch && (l_poseState == PoseState.Standing)) + ms_rootVelocity.SetValue(m_vrIk.solver, Vector3.zero); + if(m_ikOverrideProne && !m_ikOverrideCrouch && (l_poseState == PoseState.Crouching)) + ms_rootVelocity.SetValue(m_vrIk.solver, Vector3.zero); + } - if(m_detectPose && !m_compatibleAvatar && !PlayerSetup.Instance.fullBodyActive) + if(m_poseTransitions && !m_compatibleAvatar && !PlayerSetup.Instance.fullBodyActive) { switch(l_poseState) { case PoseState.Standing: { - PlayerSetup.Instance._movementSystem.ChangeCrouch(false); - PlayerSetup.Instance._movementSystem.ChangeProne(false); - PlayerSetup.Instance.animatorManager.SetAnimatorParameterBool("Crouching", false); // Forced to stop transitioning to standing locomotion - PlayerSetup.Instance.animatorManager.SetAnimatorParameterBool("Prone", false); // Forced to stop transitioning to standing locomotion + if(m_adjustedMovement) + { + MovementSystem.Instance.ChangeCrouch(false); // + MovementSystem.Instance.ChangeProne(false); // Affects movement speed + } + PlayerSetup.Instance.animatorManager.SetAnimatorParameterBool("Crouching", false); // + PlayerSetup.Instance.animatorManager.SetAnimatorParameterBool("Prone", false); // Force to stop transitioning to standing locomotion while moving } break; case PoseState.Crouching: - PlayerSetup.Instance._movementSystem.ChangeCrouch(true); + { + if(m_adjustedMovement) + MovementSystem.Instance.ChangeCrouch(true); + PlayerSetup.Instance.animatorManager.SetAnimatorParameterBool("Crouching", true); PlayerSetup.Instance.animatorManager.SetAnimatorParameterBool("Prone", false); - break; + } + break; case PoseState.Proning: { - PlayerSetup.Instance._movementSystem.ChangeProne(true); + if(m_adjustedMovement) + MovementSystem.Instance.ChangeProne(true); + PlayerSetup.Instance.animatorManager.SetAnimatorParameterBool("Crouching", false); PlayerSetup.Instance.animatorManager.SetAnimatorParameterBool("Prone", true); } @@ -122,10 +144,24 @@ namespace ml_amt switch(l_param.m_sync) { case ParameterSyncType.Local: - PlayerSetup.Instance._animator.SetFloat(l_param.m_hash, m_currentUpright); + PlayerSetup.Instance._animator.SetFloat(l_param.m_hash, m_upright); break; case ParameterSyncType.Synced: - PlayerSetup.Instance.changeAnimatorParam(l_param.m_name, m_currentUpright); + PlayerSetup.Instance.changeAnimatorParam(l_param.m_name, m_upright); + break; + } + } + break; + + case ParameterType.GroundedRaw: + { + switch(l_param.m_sync) + { + case ParameterSyncType.Local: + PlayerSetup.Instance._animator.SetBool(l_param.m_hash, (bool)ms_groundedRaw.GetValue(MovementSystem.Instance)); + break; + case ParameterSyncType.Synced: + PlayerSetup.Instance.changeAnimatorParam(l_param.m_name, (bool)ms_groundedRaw.GetValue(MovementSystem.Instance) ? 1f : 0f); break; } } @@ -207,45 +243,65 @@ namespace ml_amt void OnIKPreUpdate() { - if(m_ikOverride) - { - m_locomotionWeight = m_vrIk.solver.locomotion.weight; - if(m_poseState != PoseState.Standing) - m_vrIk.solver.locomotion.weight = 0f; - } + m_locomotionWeight = m_vrIk.solver.locomotion.weight; + + if((m_ikOverrideCrouch && (m_poseState != PoseState.Standing)) || (m_ikOverrideProne && (m_poseState == PoseState.Proning))) + m_vrIk.solver.locomotion.weight = 0f; + if(m_ikOverrideFly && MovementSystem.Instance.flying) + m_vrIk.solver.locomotion.weight = 0f; } void OnIKPostUpdate() { - if(m_ikOverride) - m_vrIk.solver.locomotion.weight = m_locomotionWeight; + m_vrIk.solver.locomotion.weight = m_locomotionWeight; } - public void SetIKOverride(bool p_state) + public void SetIKOverrideCrouch(bool p_state) { - m_ikOverride = p_state; + m_ikOverrideCrouch = p_state; } public void SetCrouchLimit(float p_value) { if(!m_customCrouchLimit) m_crouchLimit = Mathf.Clamp(p_value, 0f, 1f); } - public void SetDetectPose(bool p_state) + public void SetIKOverrideProne(bool p_state) { - m_detectPose = p_state; - - if(!m_detectPose && m_avatarReady && !m_compatibleAvatar && PlayerSetup.Instance._inVr) - { - PlayerSetup.Instance._movementSystem.ChangeCrouch(false); - PlayerSetup.Instance._movementSystem.ChangeProne(false); - PlayerSetup.Instance.animatorManager.SetAnimatorParameterBool("Crouching", false); - PlayerSetup.Instance.animatorManager.SetAnimatorParameterBool("Prone", false); - } + m_ikOverrideProne = p_state; } public void SetProneLimit(float p_value) { if(!m_customProneLimit) m_proneLimit = Mathf.Clamp(p_value, 0f, 1f); } + public void SetPoseTransitions(bool p_state) + { + m_poseTransitions = p_state; + + if(!m_poseTransitions && m_avatarReady && !m_compatibleAvatar && PlayerSetup.Instance._inVr) + { + if(m_adjustedMovement) + { + MovementSystem.Instance.ChangeCrouch(false); + MovementSystem.Instance.ChangeProne(false); + } + PlayerSetup.Instance.animatorManager.SetAnimatorParameterBool("Crouching", false); + PlayerSetup.Instance.animatorManager.SetAnimatorParameterBool("Prone", false); + } + } + public void SetAdjustedMovement(bool p_state) + { + m_adjustedMovement = p_state; + + if(!m_adjustedMovement && m_poseTransitions && m_avatarReady && !m_compatibleAvatar && PlayerSetup.Instance._inVr) + { + MovementSystem.Instance.ChangeCrouch(false); + MovementSystem.Instance.ChangeProne(false); + } + } + public void SetIKOverrideFly(bool p_state) + { + m_ikOverrideFly = p_state; + } } } diff --git a/ml_amt/Properties/AssemblyInfo.cs b/ml_amt/Properties/AssemblyInfo.cs index 13ce87b..eb375a6 100644 --- a/ml_amt/Properties/AssemblyInfo.cs +++ b/ml_amt/Properties/AssemblyInfo.cs @@ -1,10 +1,10 @@ using System.Reflection; [assembly: AssemblyTitle("AvatarMotionTweaker")] -[assembly: AssemblyVersion("1.0.8")] -[assembly: AssemblyFileVersion("1.0.8")] +[assembly: AssemblyVersion("1.0.9")] +[assembly: AssemblyFileVersion("1.0.9")] -[assembly: MelonLoader.MelonInfo(typeof(ml_amt.AvatarMotionTweaker), "AvatarMotionTweaker", "1.0.8", "SDraw", "https://github.com/SDraw/ml_mods_cvr")] +[assembly: MelonLoader.MelonInfo(typeof(ml_amt.AvatarMotionTweaker), "AvatarMotionTweaker", "1.0.9", "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_amt/README.md b/ml_amt/README.md index f811f6c..90ccbed 100644 --- a/ml_amt/README.md +++ b/ml_amt/README.md @@ -10,40 +10,29 @@ This mod adds features for AAS animator and avatar locomotion behaviour. # Usage Available mod's settings in `Settings - Implementation - Avatar Motion Tweaker`: -* **IK locomotion override:** disables legs locomotion/autostep upon HMD reaching height of `CrouchLimit`; default value - `true`. -* **Crouch limit:** defines first limit; default value - `65`. +* **IK override while crouching:** disables legs locomotion/autostep upon HMD reaching `Crouch limit`; default value - `true`. +* **Crouch limit:** defines crouch limit; default value - `65`. * Note: Can be overrided by avatar. For this avatar has to have child gameobject with name `CrouchLimit`, its Y-axis location will be used as limit, should be in range [0.0, 1.0]. -* **Detect pose (regular avatars):** forces regular avatars' animations to transit to crouching/proning animation states; default value - `true`. - * Note: Avatar is considered as regular if its animator doesn't have `Upright` parameter. -* **Prone limit (regular avatars):** defines second limit; default value - `30`. +* **IK override while crouching:** disables legs locomotion/autostep upon HMD reaching height of `Prone limit`; default value - `true`. +* **Prone limit:** defines second limit; default value - `30`. * Note: Can be overrided by avatar. For this avatar has to have child gameobject with name `ProneLimit`, its Y-axis location will be used as limit, should be in range [0.0, 1.0]. - * Note: Has no effect for mod compatible avatars. +* **IK override while flying:** disables legs locomotion/autostep in fly mode; default value - `true`. +* **Pose transitions:** allows regular avatars animator to transit in crouch/prone states; default value - `true`. + * Note: Avatar is considered as regular if its AAS animator doesn't have `Upright` parameter. +* **Adjusted pose movement speed:** scales movement speed upon crouching/proning; default value - `true`. + * Note: Requires enabled `Pose transitions` option. Available additional parameters for AAS animator: -* **`Upright`:** defines linear coefficient between current viewpoint height and avatar's viewpoint height. Range - [0.0,1.0] (0.0 - floor, 1.0 - full standing). +* **`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: Defining this parameter in AAS animator will consider avatar as compatible with mod. +* **`GroundedRaw`:** defines instant grounding state of player instead of delayed default parameter `Grounded`. + * Note: Can be set as local-only (not synced) if starts with `#` character. Additional avatars tweaks: * If avatar has child object with name `LocomotionOffset` its local position will be used for offsetting VRIK locomotion center. - -## Advanced usage in AAS animator for mixed desktop and VR -* To differentiate between desktop and VR players use `CVR Parameter Stream` component on avatar's root gameobject. As example, `InVR` and `InFBT` are boolean typed animator parameters: -![](.github/img_02.png) -* Add additional transitions between standing, crouching and proning blend trees: -![](.github/img_03.png) -* Add conditions for new VR transitions: - * Standing -> Crouching: - ![](.github/img_04.png) - * Crouching -> Standing: - ![](.github/img_05.png) - * Crouching -> Proning: - ![](.github/img_06.png) - * Proning -> Crouching: - ![](.github/img_07.png) -* Add condition check for all desktop transitions: -![](.github/img_08.png) # Notes * Usage of `Upright` parameter for transition between poses (standing/crouching/proning) in desktop mode is useless, because in this case your animations are updating value of `Upright` parameter, not the other way around. -* Please, keep your avatar root object at identity scale. Thank you. \ No newline at end of file +* **Adjusted pose movement speed** option isn't applied to compatible avatars, in progress. +* Please, keep your avatars' root object at identity scale. Thank you. diff --git a/ml_amt/Settings.cs b/ml_amt/Settings.cs index 1790502..b645775 100644 --- a/ml_amt/Settings.cs +++ b/ml_amt/Settings.cs @@ -9,34 +9,46 @@ namespace ml_amt { enum ModSetting { - IKOverride = 0, + IKOverrideCrouch = 0, CrouchLimit, - DetectPose, - ProneLimit + IKOverrideProne, + ProneLimit, + PoseTransitions, + AdjustedMovement, + IKOverrideFly }; - static bool ms_ikOverride = true; + static bool ms_ikOverrideCrouch = true; static float ms_crouchLimit = 0.65f; - static bool ms_detectPose = true; + static bool ms_ikOverrideProne = true; static float ms_proneLimit = 0.3f; + static bool ms_poseTransitions = true; + static bool ms_adjustedMovement = true; + static bool ms_ikOverrideFly = true; static MelonLoader.MelonPreferences_Category ms_category = null; static List ms_entries = null; - static public event Action IKOverrideChange; + static public event Action IKOverrideCrouchChange; static public event Action CrouchLimitChange; - static public event Action DetectPoseChange; + static public event Action IKOverrideProneChange; static public event Action ProneLimitChange; + static public event Action PoseTransitionsChange; + static public event Action AdjustedMovementChange; + static public event Action IKOverrideFlyChange; public static void Init() { ms_category = MelonLoader.MelonPreferences.CreateCategory("AMT"); ms_entries = new List(); - ms_entries.Add(ms_category.CreateEntry(ModSetting.IKOverride.ToString(), true)); + ms_entries.Add(ms_category.CreateEntry(ModSetting.IKOverrideCrouch.ToString(), true)); ms_entries.Add(ms_category.CreateEntry(ModSetting.CrouchLimit.ToString(), 65)); - ms_entries.Add(ms_category.CreateEntry(ModSetting.DetectPose.ToString(), true)); + ms_entries.Add(ms_category.CreateEntry(ModSetting.IKOverrideProne.ToString(), true)); ms_entries.Add(ms_category.CreateEntry(ModSetting.ProneLimit.ToString(), 30)); + ms_entries.Add(ms_category.CreateEntry(ModSetting.PoseTransitions.ToString(), true)); + ms_entries.Add(ms_category.CreateEntry(ModSetting.AdjustedMovement.ToString(), true)); + ms_entries.Add(ms_category.CreateEntry(ModSetting.IKOverrideFly.ToString(), true)); Load(); @@ -67,10 +79,13 @@ namespace ml_amt static void Load() { - ms_ikOverride = (bool)ms_entries[(int)ModSetting.IKOverride].BoxedValue; + ms_ikOverrideCrouch = (bool)ms_entries[(int)ModSetting.IKOverrideCrouch].BoxedValue; ms_crouchLimit = ((int)ms_entries[(int)ModSetting.CrouchLimit].BoxedValue) * 0.01f; - ms_detectPose = (bool)ms_entries[(int)ModSetting.DetectPose].BoxedValue; + ms_ikOverrideProne = (bool)ms_entries[(int)ModSetting.IKOverrideProne].BoxedValue; ms_proneLimit = ((int)ms_entries[(int)ModSetting.ProneLimit].BoxedValue) * 0.01f; + ms_poseTransitions = (bool)ms_entries[(int)ModSetting.PoseTransitions].BoxedValue; + ms_adjustedMovement = (bool)ms_entries[(int)ModSetting.AdjustedMovement].BoxedValue; + ms_ikOverrideFly = (bool)ms_entries[(int)ModSetting.IKOverrideFly].BoxedValue; } static void OnSliderUpdate(string p_name, string p_value) @@ -83,13 +98,15 @@ namespace ml_amt { ms_crouchLimit = int.Parse(p_value) * 0.01f; CrouchLimitChange?.Invoke(ms_crouchLimit); - } break; - + } + break; + case ModSetting.ProneLimit: { ms_proneLimit = int.Parse(p_value) * 0.01f; ProneLimitChange?.Invoke(ms_proneLimit); - } break; + } + break; } ms_entries[(int)l_setting].BoxedValue = int.Parse(p_value); @@ -102,16 +119,38 @@ namespace ml_amt { switch(l_setting) { - case ModSetting.IKOverride: + case ModSetting.IKOverrideCrouch: { - ms_ikOverride = bool.Parse(p_value); - IKOverrideChange?.Invoke(ms_ikOverride); - } break; + ms_ikOverrideCrouch = bool.Parse(p_value); + IKOverrideCrouchChange?.Invoke(ms_ikOverrideCrouch); + } + break; - case ModSetting.DetectPose: + case ModSetting.IKOverrideProne: { - ms_detectPose = bool.Parse(p_value); - DetectPoseChange?.Invoke(ms_detectPose); + ms_ikOverrideProne = bool.Parse(p_value); + IKOverrideProneChange?.Invoke(ms_ikOverrideProne); + } + break; + + case ModSetting.PoseTransitions: + { + ms_poseTransitions = bool.Parse(p_value); + PoseTransitionsChange?.Invoke(ms_poseTransitions); + } + break; + + case ModSetting.AdjustedMovement: + { + ms_adjustedMovement = bool.Parse(p_value); + AdjustedMovementChange?.Invoke(ms_adjustedMovement); + } + break; + + case ModSetting.IKOverrideFly: + { + ms_ikOverrideFly = bool.Parse(p_value); + IKOverrideFlyChange?.Invoke(ms_ikOverrideFly); } break; } @@ -119,24 +158,33 @@ namespace ml_amt } } + public static bool IKOverrideCrouch + { + get => ms_ikOverrideCrouch; + } public static float CrouchLimit { get => ms_crouchLimit; } - - public static bool IKOverride + public static bool IKOverrideProne { - get => ms_ikOverride; + get => ms_ikOverrideProne; } - - public static bool DetectPose - { - get => ms_detectPose; - } - public static float ProneLimit { get => ms_proneLimit; } + public static bool PoseTransitions + { + get => ms_poseTransitions; + } + public static bool AdjustedMovement + { + get => ms_adjustedMovement; + } + public static bool IKOverrideFly + { + get => ms_ikOverrideFly; + } } } diff --git a/ml_amt/resources/menu.js b/ml_amt/resources/menu.js index a541b22..5891d17 100644 --- a/ml_amt/resources/menu.js +++ b/ml_amt/resources/menu.js @@ -181,9 +181,9 @@ function inp_toggle_mod_amt(_obj, _callbackName) {
-
IK locomotion override:
+
IK override while crouching:
-
+
@@ -195,18 +195,39 @@ function inp_toggle_mod_amt(_obj, _callbackName) {
-
Detect pose (regular avatars):
+
IK override while proning:
-
+
-
Prone limit (regular avatars):
+
Prone limit:
+ +
+
IK override while flying:
+
+
+
+
+ +
+
Pose transitions:
+
+
+
+
+ +
+
Adjusted pose movement speed:
+
+
+
+
`; document.getElementById('settings-implementation').appendChild(l_block); diff --git a/ml_fpt/Main.cs b/ml_fpt/Main.cs index b27dbb2..a486260 100644 --- a/ml_fpt/Main.cs +++ b/ml_fpt/Main.cs @@ -9,17 +9,19 @@ namespace ml_fpt public class FourPointTracking : MelonLoader.MelonMod { static FourPointTracking ms_instance = null; + + bool m_ready = false; IndexIK m_indexIk = null; CVR_IK_Calibrator m_ikCalibrator = null; + RootMotion.FinalIK.VRIK m_vrIK = null; + RuntimeAnimatorController m_runtimeAnimator = null; - bool m_inCalibration = false; + bool m_calibrationActive = false; + object m_calibrationTask = null; + int m_hipsTrackerIndex = -1; - - RuntimeAnimatorController m_oldRuntimeAnimator = null; - RootMotion.FinalIK.VRIK m_origVrIk = null; - - bool m_playerReady = false; + Transform m_hips = null; public override void OnApplicationStart() { @@ -35,54 +37,6 @@ namespace ml_fpt MelonLoader.MelonCoroutines.Start(WaitForLocalPlayer()); } - public override void OnUpdate() - { - if(m_playerReady && m_inCalibration && (m_hipsTrackerIndex != -1)) - { - if(m_origVrIk != null) - m_origVrIk.enabled = false; - m_ikCalibrator.enabled = false; - m_indexIk.enabled = false; - - Transform l_hips = PlayerSetup.Instance._animator.GetBoneTransform(HumanBodyBones.Hips); - PlayerSetup.Instance._trackerManager.trackers[m_hipsTrackerIndex].ShowLine(true, l_hips); - - if((CVRInputManager.Instance.interactLeftValue > 0.9f) && (CVRInputManager.Instance.interactRightValue > 0.9f)) - { - PlayerSetup.Instance._trackerManager.trackers[m_hipsTrackerIndex].target.transform.position = l_hips.position; - PlayerSetup.Instance._trackerManager.trackers[m_hipsTrackerIndex].target.transform.rotation = l_hips.rotation; - - if((m_origVrIk != null) && (m_origVrIk.solver?.spine != null)) - { - m_origVrIk.solver.spine.pelvisTarget = PlayerSetup.Instance._trackerManager.trackers[m_hipsTrackerIndex].target; - m_origVrIk.solver.spine.pelvisPositionWeight = 1f; - m_origVrIk.solver.spine.pelvisRotationWeight = 1f; - m_origVrIk.solver.OnPreUpdate -= this.OverrideIKWeight; - m_origVrIk.solver.IKPositionWeight = 1f; - m_origVrIk.enabled = true; - } - - m_indexIk.enabled = true; - m_ikCalibrator.enabled = true; - - PlayerSetup.Instance._animator.runtimeAnimatorController = m_oldRuntimeAnimator; - - m_ikCalibrator.leftHandModel.SetActive(false); - m_ikCalibrator.rightHandModel.SetActive(false); - PlayerSetup.Instance._trackerManager.trackers[m_hipsTrackerIndex].ShowTracker(false); - PlayerSetup.Instance._trackerManager.trackers[m_hipsTrackerIndex].ShowLine(false); - CVR_InteractableManager.enableInteractions = true; - - if(PlayerSetup.Instance._avatar.GetComponent().avatarUsesAdvancedSettings) - PlayerSetup.Instance.LoadCurrentAvatarSettingsDefault(); - - Reset(); - - ShowHudNotification("Calibration completed"); - } - } - } - System.Collections.IEnumerator WaitForMainMenuView() { while(ViewManager.Instance == null) @@ -111,16 +65,16 @@ namespace ml_fpt m_indexIk = PlayerSetup.Instance.gameObject.GetComponent(); m_ikCalibrator = PlayerSetup.Instance.gameObject.GetComponent(); - m_playerReady = true; + m_ready = true; } void StartCalibration() { - if(m_playerReady && !m_inCalibration && PlayerSetup.Instance._inVr && !PlayerSetup.Instance.avatarIsLoading && PlayerSetup.Instance._animator.isHuman && !m_ikCalibrator.inFullbodyCalibration && !m_ikCalibrator.avatarCalibratedAsFullBody) + if(m_ready && !m_calibrationActive && PlayerSetup.Instance._inVr && !PlayerSetup.Instance.avatarIsLoading && PlayerSetup.Instance._animator.isHuman && !m_ikCalibrator.inFullbodyCalibration && !m_ikCalibrator.avatarCalibratedAsFullBody) { for(int i = 0; i < PlayerSetup.Instance._trackerManager.trackerNames.Length; i++) { - if(PlayerSetup.Instance._trackerManager.trackerNames[i] == "vive_tracker_waist") + if((PlayerSetup.Instance._trackerManager.trackerNames[i] == "vive_tracker_waist") && PlayerSetup.Instance._trackerManager.trackers[i].active) { m_hipsTrackerIndex = i; break; @@ -129,19 +83,22 @@ namespace ml_fpt if(m_hipsTrackerIndex != -1) { - m_oldRuntimeAnimator = PlayerSetup.Instance._animator.runtimeAnimatorController; + m_runtimeAnimator = PlayerSetup.Instance._animator.runtimeAnimatorController; PlayerSetup.Instance._animator.runtimeAnimatorController = PlayerSetup.Instance.tPoseAnimatorController; - m_origVrIk = PlayerSetup.Instance._animator.GetComponent(); - if(m_origVrIk != null) - m_origVrIk.solver.OnPreUpdate += this.OverrideIKWeight; + m_hips = PlayerSetup.Instance._animator.GetBoneTransform(HumanBodyBones.Hips); + m_vrIK = PlayerSetup.Instance._animator.GetComponent(); + + if(m_vrIK != null) + m_vrIK.solver.OnPreUpdate += this.OverrideIKWeight; m_ikCalibrator.leftHandModel.SetActive(true); m_ikCalibrator.rightHandModel.SetActive(true); PlayerSetup.Instance._trackerManager.trackers[m_hipsTrackerIndex].ShowTracker(true); CVR_InteractableManager.enableInteractions = false; - m_inCalibration = true; + m_calibrationActive = true; + m_calibrationTask = MelonLoader.MelonCoroutines.Start(CalibrationTask()); ViewManager.Instance.ForceUiStatus(false); ShowHudNotification("Calibration started"); @@ -152,19 +109,71 @@ namespace ml_fpt else ShowMenuAlert("Calibraton requirements aren't met: be in VR, be not in FBT or avatar calibration, humanoid avatar"); } - - void Reset() + + System.Collections.IEnumerator CalibrationTask() { - m_inCalibration = false; - m_hipsTrackerIndex = -1; - m_oldRuntimeAnimator = null; - m_origVrIk = null; + while(m_calibrationActive) + { + if(m_vrIK != null) + m_vrIK.enabled = false; + + m_ikCalibrator.enabled = false; + m_indexIk.enabled = false; + + PlayerSetup.Instance._trackerManager.trackers[m_hipsTrackerIndex].ShowLine(true, m_hips); + + if((CVRInputManager.Instance.interactLeftValue > 0.9f) && (CVRInputManager.Instance.interactRightValue > 0.9f)) + { + PlayerSetup.Instance._trackerManager.trackers[m_hipsTrackerIndex].target.transform.position = m_hips.position; + PlayerSetup.Instance._trackerManager.trackers[m_hipsTrackerIndex].target.transform.rotation = m_hips.rotation; + + if(m_vrIK != null) + { + m_vrIK.solver.spine.pelvisTarget = PlayerSetup.Instance._trackerManager.trackers[m_hipsTrackerIndex].target; + m_vrIK.solver.spine.pelvisPositionWeight = 1f; + m_vrIK.solver.spine.pelvisRotationWeight = 1f; + m_vrIK.solver.OnPreUpdate -= this.OverrideIKWeight; + m_vrIK.solver.IKPositionWeight = 1f; + m_vrIK.enabled = true; + } + + m_indexIk.enabled = true; + m_ikCalibrator.enabled = true; + PlayerSetup.Instance._animator.runtimeAnimatorController = m_runtimeAnimator; + + m_ikCalibrator.leftHandModel.SetActive(false); + m_ikCalibrator.rightHandModel.SetActive(false); + PlayerSetup.Instance._trackerManager.trackers[m_hipsTrackerIndex].ShowTracker(false); + PlayerSetup.Instance._trackerManager.trackers[m_hipsTrackerIndex].ShowLine(false); + CVR_InteractableManager.enableInteractions = true; + + Reset(); + + ShowHudNotification("Calibration completed"); + } + + yield return null; + } + + m_calibrationTask = null; // Idk if it's safe or not } void OverrideIKWeight() { - if(m_inCalibration && (m_origVrIk != null)) - m_origVrIk.solver.IKPositionWeight = 0f; + if(m_calibrationActive) + { + m_vrIK.solver.IKPositionWeight = 0f; + } + } + + void Reset() + { + m_vrIK = null; + m_runtimeAnimator = null; + m_calibrationActive = false; + m_calibrationTask = null; + m_hipsTrackerIndex = -1; + m_hips = null; } static void OnAvatarClear_Postfix() => ms_instance?.OnAvatarClear(); @@ -172,8 +181,11 @@ namespace ml_fpt { try { - if(m_inCalibration) + if(m_calibrationActive) { + if(m_calibrationTask != null) + MelonLoader.MelonCoroutines.Stop(m_calibrationTask); + m_indexIk.enabled = true; m_ikCalibrator.enabled = true; diff --git a/ml_fpt/Properties/AssemblyInfo.cs b/ml_fpt/Properties/AssemblyInfo.cs index 101a324..6528cc1 100644 --- a/ml_fpt/Properties/AssemblyInfo.cs +++ b/ml_fpt/Properties/AssemblyInfo.cs @@ -1,10 +1,10 @@ using System.Reflection; [assembly: AssemblyTitle("FourPointTracking")] -[assembly: AssemblyVersion("1.0.4")] -[assembly: AssemblyFileVersion("1.0.4")] +[assembly: AssemblyVersion("1.0.5")] +[assembly: AssemblyFileVersion("1.0.5")] -[assembly: MelonLoader.MelonInfo(typeof(ml_fpt.FourPointTracking), "FourPointTracking", "1.0.4", "SDraw", "https://github.com/SDraw/ml_mods_cvr")] +[assembly: MelonLoader.MelonInfo(typeof(ml_fpt.FourPointTracking), "FourPointTracking", "1.0.5", "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