diff --git a/ml_amt/GameEvents.cs b/ml_amt/GameEvents.cs index 00cb0f8..8400096 100644 --- a/ml_amt/GameEvents.cs +++ b/ml_amt/GameEvents.cs @@ -15,8 +15,6 @@ namespace ml_amt public void Invoke() => m_action?.Invoke(); } - public static readonly GameEvent OnAvatarSetup = new GameEvent(); - public static readonly GameEvent OnAvatarClear = new GameEvent(); public static readonly GameEvent OnAvatarReuse = new GameEvent(); public static readonly GameEvent OnPlayspaceScale = new GameEvent(); @@ -24,18 +22,6 @@ namespace ml_amt { try { - p_instance.Patch( - typeof(PlayerSetup).GetMethod(nameof(PlayerSetup.ClearAvatar), BindingFlags.Instance | BindingFlags.Public), - null, - new HarmonyLib.HarmonyMethod(typeof(GameEvents).GetMethod(nameof(OnAvatarClear_Postfix), BindingFlags.Static | BindingFlags.NonPublic)) - ); - - p_instance.Patch( - typeof(PlayerSetup).GetMethod(nameof(PlayerSetup.SetupAvatar), BindingFlags.Instance | BindingFlags.Public), - null, - new HarmonyLib.HarmonyMethod(typeof(GameEvents).GetMethod(nameof(OnSetupAvatar_Postfix), BindingFlags.Static | BindingFlags.NonPublic)) - ); - p_instance.Patch( typeof(IKSystem).GetMethod(nameof(IKSystem.ReinitializeAvatar), BindingFlags.Instance | BindingFlags.Public), null, @@ -54,30 +40,6 @@ namespace ml_amt } } - static void OnAvatarClear_Postfix() - { - try - { - OnAvatarClear.Invoke(); - } - catch(Exception e) - { - MelonLoader.MelonLogger.Error(e); - } - } - - static void OnSetupAvatar_Postfix() - { - try - { - OnAvatarSetup.Invoke(); - } - catch(Exception l_exception) - { - MelonLoader.MelonLogger.Error(l_exception); - } - } - static void OnAvatarReinitialize_Postfix() { try diff --git a/ml_amt/MotionTweaker.cs b/ml_amt/MotionTweaker.cs index 9c01ef5..e81097f 100644 --- a/ml_amt/MotionTweaker.cs +++ b/ml_amt/MotionTweaker.cs @@ -1,5 +1,7 @@ -using ABI_RC.Core.Player; +using ABI.CCK.Components; +using ABI_RC.Core.Player; using ABI_RC.Core.Util.AnimatorManager; +using ABI_RC.Systems.GameEventSystem; using ABI_RC.Systems.IK.SubSystems; using ABI_RC.Systems.Movement; using RootMotion.FinalIK; @@ -59,8 +61,8 @@ namespace ml_amt Settings.OnProneLimitChanged.AddListener(this.OnProneLimitChanged); Settings.OnMassCenterChanged.AddListener(this.OnMassCenterChanged); - GameEvents.OnAvatarSetup.AddListener(this.OnAvatarSetup); - GameEvents.OnAvatarClear.AddListener(this.OnAvatarClear); + CVRGameEventSystem.Avatar.OnLocalAvatarLoad.AddListener(this.OnAvatarSetup); + CVRGameEventSystem.Avatar.OnLocalAvatarClear.AddListener(this.OnAvatarClear); GameEvents.OnAvatarReuse.AddListener(this.OnAvatarReuse); GameEvents.OnPlayspaceScale.AddListener(this.OnPlayspaceScale); } @@ -78,8 +80,8 @@ namespace ml_amt Settings.OnProneLimitChanged.RemoveListener(this.OnProneLimitChanged); Settings.OnMassCenterChanged.RemoveListener(this.OnMassCenterChanged); - GameEvents.OnAvatarSetup.RemoveListener(this.OnAvatarSetup); - GameEvents.OnAvatarClear.RemoveListener(this.OnAvatarClear); + CVRGameEventSystem.Avatar.OnLocalAvatarLoad.RemoveListener(this.OnAvatarSetup); + CVRGameEventSystem.Avatar.OnLocalAvatarClear.RemoveListener(this.OnAvatarClear); GameEvents.OnAvatarReuse.RemoveListener(this.OnAvatarReuse); GameEvents.OnPlayspaceScale.RemoveListener(this.OnPlayspaceScale); } @@ -96,68 +98,82 @@ namespace ml_amt } // Game events - void OnAvatarClear() + void OnAvatarClear(CVRAvatar p_avatar) { - m_vrIk = null; - m_avatarReady = false; - m_avatarScale = 1f; - m_locomotionOffset = Vector3.zero; - m_massCenter = Vector3.zero; - m_ikLimits = null; - m_parameters.Clear(); + try + { + m_vrIk = null; + m_avatarReady = false; + m_avatarScale = 1f; + m_locomotionOffset = Vector3.zero; + m_massCenter = Vector3.zero; + m_ikLimits = null; + m_parameters.Clear(); - BetterBetterCharacterController.Instance.avatarCrouchLimit = Mathf.Clamp01(Settings.CrouchLimit); - BetterBetterCharacterController.Instance.avatarProneLimit = Mathf.Clamp01(Settings.ProneLimit); + BetterBetterCharacterController.Instance.avatarCrouchLimit = Mathf.Clamp01(Settings.CrouchLimit); + BetterBetterCharacterController.Instance.avatarProneLimit = Mathf.Clamp01(Settings.ProneLimit); + } + catch(System.Exception e) + { + MelonLoader.MelonLogger.Error(e); + } } - void OnAvatarSetup() + void OnAvatarSetup(CVRAvatar p_avatar) { - Utils.SetAvatarTPose(); - - m_vrIk = PlayerSetup.Instance._avatar.GetComponent(); - m_avatarScale = Mathf.Abs(PlayerSetup.Instance._avatar.transform.localScale.y); - - // Parse animator parameters - m_parameters.Add(new AvatarParameter(AvatarParameter.ParameterType.Moving, PlayerSetup.Instance.animatorManager)); - m_parameters.Add(new AvatarParameter(AvatarParameter.ParameterType.MovementSpeed, PlayerSetup.Instance.animatorManager)); - m_parameters.Add(new AvatarParameter(AvatarParameter.ParameterType.Velocity, 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) + try { - m_locomotionOffset = m_vrIk.solver.locomotion.offset; - m_massCenter = m_locomotionOffset; + Utils.SetAvatarTPose(); - if(m_vrIk.solver.HasToes()) + m_vrIk = PlayerSetup.Instance.AvatarObject.GetComponent(); + m_avatarScale = Mathf.Abs(PlayerSetup.Instance.AvatarTransform.localScale.y); + + // Parse animator parameters + m_parameters.Add(new AvatarParameter(AvatarParameter.ParameterType.Moving, PlayerSetup.Instance.AnimatorManager)); + m_parameters.Add(new AvatarParameter(AvatarParameter.ParameterType.MovementSpeed, PlayerSetup.Instance.AnimatorManager)); + m_parameters.Add(new AvatarParameter(AvatarParameter.ParameterType.Velocity, PlayerSetup.Instance.AnimatorManager)); + m_parameters.RemoveAll(p => !p.IsValid()); + + // Avatar custom IK limits + m_ikLimits = PlayerSetup.Instance.AvatarTransform.Find("[IKLimits]"); + UpdateIKLimits(); + + // Apply VRIK tweaks + if(m_vrIk != null) { - Transform l_foot = PlayerSetup.Instance._animator.GetBoneTransform(HumanBodyBones.LeftFoot); - if(l_foot == null) - l_foot = PlayerSetup.Instance._animator.GetBoneTransform(HumanBodyBones.RightFoot); + m_locomotionOffset = m_vrIk.solver.locomotion.offset; + m_massCenter = m_locomotionOffset; - 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)) + if(m_vrIk.solver.HasToes()) { - Vector3 l_footPos = (PlayerSetup.Instance._avatar.transform.GetMatrix().inverse * l_foot.GetMatrix()).GetPosition(); - Vector3 l_toePos = (PlayerSetup.Instance._avatar.transform.GetMatrix().inverse * l_toe.GetMatrix()).GetPosition(); - m_massCenter = new Vector3(0f, 0f, l_toePos.z - l_footPos.z); + 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.AvatarTransform.GetMatrix().inverse * l_foot.GetMatrix()).GetPosition(); + Vector3 l_toePos = (PlayerSetup.Instance.AvatarTransform.GetMatrix().inverse * l_toe.GetMatrix()).GetPosition(); + 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.OnIKPreSolverUpdate); + m_vrIk.onPostSolverUpdate.AddListener(this.OnIKPostSolverUpdate); } - m_vrIk.solver.locomotion.offset = (Settings.MassCenter ? m_massCenter : m_locomotionOffset); - - m_vrIk.onPreSolverUpdate.AddListener(this.OnIKPreSolverUpdate); - m_vrIk.onPostSolverUpdate.AddListener(this.OnIKPostSolverUpdate); + m_avatarReady = true; + } + catch(System.Exception e) + { + MelonLoader.MelonLogger.Error(e); } - - m_avatarReady = true; } void OnPlayspaceScale() @@ -171,7 +187,7 @@ namespace ml_amt // Old VRIK is destroyed by game Utils.SetAvatarTPose(); - m_vrIk = PlayerSetup.Instance._animator.GetComponent(); + m_vrIk = PlayerSetup.Instance.AvatarObject.GetComponent(); if(m_vrIk != null) { m_vrIk.solver.locomotion.offset = (Settings.MassCenter ? m_massCenter : m_locomotionOffset); @@ -241,7 +257,7 @@ namespace ml_amt // Arbitrary float GetRelativeScale() { - return ((m_avatarScale > 0f) ? (PlayerSetup.Instance._avatar.transform.localScale.y / m_avatarScale) : 0f); + return ((m_avatarScale > 0f) ? (PlayerSetup.Instance.AvatarTransform.localScale.y / m_avatarScale) : 0f); } void UpdateIKLimits() @@ -258,7 +274,7 @@ namespace ml_amt public bool IsMoving() => BetterBetterCharacterController.Instance.IsMoving(); public float GetMovementSpeed() { - AvatarAnimatorManager l_animatorManager = PlayerSetup.Instance.animatorManager; + AvatarAnimatorManager l_animatorManager = PlayerSetup.Instance.AnimatorManager; return Mathf.Sqrt(l_animatorManager.MovementX * l_animatorManager.MovementX + l_animatorManager.MovementY * l_animatorManager.MovementY); } public float GetVelocity() => BetterBetterCharacterController.Instance.velocity.magnitude; diff --git a/ml_amt/Settings.cs b/ml_amt/Settings.cs index 8d91703..fdf8711 100644 --- a/ml_amt/Settings.cs +++ b/ml_amt/Settings.cs @@ -65,31 +65,31 @@ namespace ml_amt { while(ViewManager.Instance == null) yield return null; - while(ViewManager.Instance.gameMenuView == null) + while(ViewManager.Instance.cohtmlView == null) yield return null; - while(ViewManager.Instance.gameMenuView.Listener == null) + while(ViewManager.Instance.cohtmlView.Listener == null) yield return null; - ViewManager.Instance.gameMenuView.Listener.ReadyForBindings += () => + ViewManager.Instance.cohtmlView.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.cohtmlView.View.BindCall("OnSliderUpdate_" + ms_category.Identifier, new Action(OnSliderUpdate)); + ViewManager.Instance.cohtmlView.View.BindCall("OnToggleUpdate_" + ms_category.Identifier, new Action(OnToggleUpdate)); }; - ViewManager.Instance.gameMenuView.Listener.FinishLoad += (_) => + ViewManager.Instance.cohtmlView.Listener.FinishLoad += (_) => { - ViewManager.Instance.gameMenuView.View.ExecuteScript(ResourcesHandler.GetEmbeddedResource("mods_extension.js")); - ViewManager.Instance.gameMenuView.View.ExecuteScript(ResourcesHandler.GetEmbeddedResource("mod_menu.js")); + ViewManager.Instance.cohtmlView.View.ExecuteScript(ResourcesHandler.GetEmbeddedResource("mods_extension.js")); + ViewManager.Instance.cohtmlView.View.ExecuteScript(ResourcesHandler.GetEmbeddedResource("mod_menu.js")); MelonLoader.MelonCoroutines.Start(UpdateMenuSettings()); }; } static System.Collections.IEnumerator UpdateMenuSettings() { - while(!ViewManager.Instance.IsReady || !ViewManager.Instance.IsMainMenuOpen) + while(!ViewManager.Instance.IsReady || !ViewManager.Instance.IsViewShown) yield return null; foreach(var l_entry in ms_entries) - ViewManager.Instance.gameMenuView.View.TriggerEvent("updateModSetting", ms_category.Identifier, l_entry.DisplayName, l_entry.GetValueAsString()); + ViewManager.Instance.cohtmlView.View.TriggerEvent("updateModSetting", ms_category.Identifier, l_entry.DisplayName, l_entry.GetValueAsString()); } static void OnSliderUpdate(string p_name, string p_value) diff --git a/ml_amt/Utils.cs b/ml_amt/Utils.cs index 79b1130..6cd79d3 100644 --- a/ml_amt/Utils.cs +++ b/ml_amt/Utils.cs @@ -22,11 +22,11 @@ namespace ml_amt public static void SetAvatarTPose() { - if(PlayerSetup.Instance._animator.isHuman) + if(PlayerSetup.Instance.Animator.isHuman) { IKSystem.Instance.SetAvatarPose(IKSystem.AvatarPose.TPose); - PlayerSetup.Instance._avatar.transform.localPosition = Vector3.zero; - PlayerSetup.Instance._avatar.transform.localRotation = Quaternion.identity; + PlayerSetup.Instance.AvatarTransform.localPosition = Vector3.zero; + PlayerSetup.Instance.AvatarTransform.localRotation = Quaternion.identity; } } diff --git a/ml_asl/Settings.cs b/ml_asl/Settings.cs index ed3b2cd..3da7a1e 100644 --- a/ml_asl/Settings.cs +++ b/ml_asl/Settings.cs @@ -44,30 +44,30 @@ namespace ml_asl { while(ViewManager.Instance == null) yield return null; - while(ViewManager.Instance.gameMenuView == null) + while(ViewManager.Instance.cohtmlView == null) yield return null; - while(ViewManager.Instance.gameMenuView.Listener == null) + while(ViewManager.Instance.cohtmlView.Listener == null) yield return null; - ViewManager.Instance.gameMenuView.Listener.ReadyForBindings += () => + ViewManager.Instance.cohtmlView.Listener.ReadyForBindings += () => { - ViewManager.Instance.gameMenuView.View.BindCall("OnToggleUpdate_" + ms_category.Identifier, new Action(OnToggleUpdate)); + ViewManager.Instance.cohtmlView.View.BindCall("OnToggleUpdate_" + ms_category.Identifier, new Action(OnToggleUpdate)); }; - ViewManager.Instance.gameMenuView.Listener.FinishLoad += (_) => + ViewManager.Instance.cohtmlView.Listener.FinishLoad += (_) => { - ViewManager.Instance.gameMenuView.View.ExecuteScript(ResourcesHandler.GetEmbeddedResource("mods_extension.js")); - ViewManager.Instance.gameMenuView.View.ExecuteScript(ResourcesHandler.GetEmbeddedResource("mod_menu.js")); + ViewManager.Instance.cohtmlView.View.ExecuteScript(ResourcesHandler.GetEmbeddedResource("mods_extension.js")); + ViewManager.Instance.cohtmlView.View.ExecuteScript(ResourcesHandler.GetEmbeddedResource("mod_menu.js")); MelonLoader.MelonCoroutines.Start(UpdateMenuSettings()); }; } static System.Collections.IEnumerator UpdateMenuSettings() { - while(!ViewManager.Instance.IsReady || !ViewManager.Instance.IsMainMenuOpen) + while(!ViewManager.Instance.IsReady || !ViewManager.Instance.IsViewShown) yield return null; foreach(var l_entry in ms_entries) - ViewManager.Instance.gameMenuView.View.TriggerEvent("updateModSetting", ms_category.Identifier, l_entry.DisplayName, l_entry.GetValueAsString()); + ViewManager.Instance.cohtmlView.View.TriggerEvent("updateModSetting", ms_category.Identifier, l_entry.DisplayName, l_entry.GetValueAsString()); } static void OnToggleUpdate(string p_name, string p_value) diff --git a/ml_bft/FingerSystem.cs b/ml_bft/FingerSystem.cs index 3a56cde..f7286d9 100644 --- a/ml_bft/FingerSystem.cs +++ b/ml_bft/FingerSystem.cs @@ -1,5 +1,7 @@ -using ABI_RC.Core.Player; +using ABI.CCK.Components; +using ABI_RC.Core.Player; using ABI_RC.Core.Savior; +using ABI_RC.Systems.GameEventSystem; using ABI_RC.Systems.IK; using ABI_RC.Systems.InputManagement; using System.Collections.Generic; @@ -92,8 +94,8 @@ namespace ml_bft m_pose = new HumanPose(); m_lastValues = new float[40]; - GameEvents.OnAvatarSetup.AddListener(this.OnAvatarSetup); - GameEvents.OnAvatarClear.AddListener(this.OnAvatarClear); + CVRGameEventSystem.Avatar.OnLocalAvatarLoad.AddListener(this.OnAvatarSetup); + CVRGameEventSystem.Avatar.OnLocalAvatarClear.AddListener(this.OnAvatarClear); GameEvents.OnAvatarReuse.AddListener(this.OnAvatarReuse); GameEvents.OnIKSystemLateUpdate.AddListener(this.OnIKSystemLateUpdate); } @@ -106,113 +108,129 @@ namespace ml_bft m_rightFingerOffsets.Clear(); m_ready = false; - GameEvents.OnAvatarSetup.RemoveListener(this.OnAvatarSetup); - GameEvents.OnAvatarClear.RemoveListener(this.OnAvatarClear); + CVRGameEventSystem.Avatar.OnLocalAvatarLoad.RemoveListener(this.OnAvatarSetup); + CVRGameEventSystem.Avatar.OnLocalAvatarClear.RemoveListener(this.OnAvatarClear); GameEvents.OnAvatarReuse.RemoveListener(this.OnAvatarReuse); GameEvents.OnIKSystemLateUpdate.RemoveListener(this.OnIKSystemLateUpdate); } - internal void OnAvatarSetup() + internal void OnAvatarSetup(CVRAvatar p_avatar) { - Animator l_animator = PlayerSetup.Instance._animator; - if(l_animator.isHuman) + try { - Utils.SetAvatarTPose(); - InputHandler.Instance.Rebind(PlayerSetup.Instance.transform.rotation); - - foreach(var l_tuple in ms_fingersChains) + Animator l_animator = PlayerSetup.Instance.Animator; + if(l_animator.isHuman) { - ReorientateTowards( - PlayerSetup.Instance.transform, - l_animator.GetBoneTransform(l_tuple.Item1), - (l_tuple.Item2 != HumanBodyBones.LastBone) ? l_animator.GetBoneTransform(l_tuple.Item2) : null, - InputHandler.Instance.GetSourceForBone(l_tuple.Item1, l_tuple.Item3), - InputHandler.Instance.GetSourceForBone(l_tuple.Item2, l_tuple.Item3), - PlaneType.OXZ - ); - ReorientateTowards( - PlayerSetup.Instance.transform, - l_animator.GetBoneTransform(l_tuple.Item1), - (l_tuple.Item2 != HumanBodyBones.LastBone) ? l_animator.GetBoneTransform(l_tuple.Item2) : null, - InputHandler.Instance.GetSourceForBone(l_tuple.Item1, l_tuple.Item3), - InputHandler.Instance.GetSourceForBone(l_tuple.Item2, l_tuple.Item3), - PlaneType.OYX - ); - } + IKSystem.Instance.SetAvatarPose(IKSystem.AvatarPose.TPose); + PlayerSetup.Instance.AvatarTransform.localPosition = Vector3.zero; + PlayerSetup.Instance.AvatarTransform.localRotation = Quaternion.identity; - // Bind hands - m_leftHandOffset.m_source = l_animator.GetBoneTransform(HumanBodyBones.LeftHand); - m_leftHandOffset.m_target = InputHandler.Instance.GetSourceForBone(HumanBodyBones.LeftHand, true); - if((m_leftHandOffset.m_source != null) && (m_leftHandOffset.m_target != null)) - m_leftHandOffset.m_offset = Quaternion.Inverse(m_leftHandOffset.m_source.rotation) * m_leftHandOffset.m_target.rotation; - - m_rightHandOffset.m_source = l_animator.GetBoneTransform(HumanBodyBones.RightHand); - m_rightHandOffset.m_target = InputHandler.Instance.GetSourceForBone(HumanBodyBones.RightHand, false); - if((m_rightHandOffset.m_source != null) && (m_rightHandOffset.m_target != null)) - m_rightHandOffset.m_offset = Quaternion.Inverse(m_rightHandOffset.m_source.rotation) * m_rightHandOffset.m_target.rotation; - - // Bind fingers - foreach(HumanBodyBones p_bone in ms_leftFingerBones) - { - Transform l_avatarBone = l_animator.GetBoneTransform(p_bone); - Transform l_controllerBone = InputHandler.Instance.GetSourceForBone(p_bone, true); - if((l_avatarBone != null) && (l_controllerBone != null)) + InputHandler.Instance.Rebind(PlayerSetup.Instance.transform.rotation); + foreach(var l_tuple in ms_fingersChains) { - RotationOffset l_offset = new RotationOffset(); - l_offset.m_source = l_controllerBone; - l_offset.m_target = l_avatarBone; - l_offset.m_offset = Quaternion.Inverse(l_controllerBone.rotation) * l_avatarBone.rotation; - m_leftFingerOffsets.Add(l_offset); + ReorientateTowards( + PlayerSetup.Instance.transform, + l_animator.GetBoneTransform(l_tuple.Item1), + (l_tuple.Item2 != HumanBodyBones.LastBone) ? l_animator.GetBoneTransform(l_tuple.Item2) : null, + InputHandler.Instance.GetSourceForBone(l_tuple.Item1, l_tuple.Item3), + InputHandler.Instance.GetSourceForBone(l_tuple.Item2, l_tuple.Item3), + PlaneType.OXZ + ); + ReorientateTowards( + PlayerSetup.Instance.transform, + l_animator.GetBoneTransform(l_tuple.Item1), + (l_tuple.Item2 != HumanBodyBones.LastBone) ? l_animator.GetBoneTransform(l_tuple.Item2) : null, + InputHandler.Instance.GetSourceForBone(l_tuple.Item1, l_tuple.Item3), + InputHandler.Instance.GetSourceForBone(l_tuple.Item2, l_tuple.Item3), + PlaneType.OYX + ); } - } - foreach(HumanBodyBones p_bone in ms_rightFingerBones) - { - Transform l_avatarBone = l_animator.GetBoneTransform(p_bone); - Transform l_controllerBone = InputHandler.Instance.GetSourceForBone(p_bone, false); - if((l_avatarBone != null) && (l_controllerBone != null)) - { - RotationOffset l_offset = new RotationOffset(); - l_offset.m_source = l_controllerBone; - l_offset.m_target = l_avatarBone; - l_offset.m_offset = Quaternion.Inverse(l_controllerBone.rotation) * l_avatarBone.rotation; - m_rightFingerOffsets.Add(l_offset); - } - } - m_ready = ((m_leftFingerOffsets.Count > 0) || (m_rightFingerOffsets.Count > 0)); + // Bind hands + m_leftHandOffset.m_source = l_animator.GetBoneTransform(HumanBodyBones.LeftHand); + m_leftHandOffset.m_target = InputHandler.Instance.GetSourceForBone(HumanBodyBones.LeftHand, true); + if((m_leftHandOffset.m_source != null) && (m_leftHandOffset.m_target != null)) + m_leftHandOffset.m_offset = Quaternion.Inverse(m_leftHandOffset.m_source.rotation) * m_leftHandOffset.m_target.rotation; + + m_rightHandOffset.m_source = l_animator.GetBoneTransform(HumanBodyBones.RightHand); + m_rightHandOffset.m_target = InputHandler.Instance.GetSourceForBone(HumanBodyBones.RightHand, false); + if((m_rightHandOffset.m_source != null) && (m_rightHandOffset.m_target != null)) + m_rightHandOffset.m_offset = Quaternion.Inverse(m_rightHandOffset.m_source.rotation) * m_rightHandOffset.m_target.rotation; + + // Bind fingers + foreach(HumanBodyBones p_bone in ms_leftFingerBones) + { + Transform l_avatarBone = l_animator.GetBoneTransform(p_bone); + Transform l_controllerBone = InputHandler.Instance.GetSourceForBone(p_bone, true); + if((l_avatarBone != null) && (l_controllerBone != null)) + { + RotationOffset l_offset = new RotationOffset(); + l_offset.m_source = l_controllerBone; + l_offset.m_target = l_avatarBone; + l_offset.m_offset = Quaternion.Inverse(l_controllerBone.rotation) * l_avatarBone.rotation; + m_leftFingerOffsets.Add(l_offset); + } + } + foreach(HumanBodyBones p_bone in ms_rightFingerBones) + { + Transform l_avatarBone = l_animator.GetBoneTransform(p_bone); + Transform l_controllerBone = InputHandler.Instance.GetSourceForBone(p_bone, false); + if((l_avatarBone != null) && (l_controllerBone != null)) + { + RotationOffset l_offset = new RotationOffset(); + l_offset.m_source = l_controllerBone; + l_offset.m_target = l_avatarBone; + l_offset.m_offset = Quaternion.Inverse(l_controllerBone.rotation) * l_avatarBone.rotation; + m_rightFingerOffsets.Add(l_offset); + } + } + + m_ready = ((m_leftFingerOffsets.Count > 0) || (m_rightFingerOffsets.Count > 0)); + } + } + catch(System.Exception e) + { + MelonLoader.MelonLogger.Error(e); } } - internal void OnAvatarClear() + internal void OnAvatarClear(CVRAvatar p_avatar) { - m_ready = false; - m_pose = new HumanPose(); + try + { + m_ready = false; + m_pose = new HumanPose(); - m_leftHandOffset.Reset(); - m_rightHandOffset.Reset(); + m_leftHandOffset.Reset(); + m_rightHandOffset.Reset(); - m_leftFingerOffsets.Clear(); - m_rightFingerOffsets.Clear(); + m_leftFingerOffsets.Clear(); + m_rightFingerOffsets.Clear(); + } + catch(System.Exception e) + { + MelonLoader.MelonLogger.Error(e); + } } internal void OnAvatarReuse() { - OnAvatarClear(); - OnAvatarSetup(); + OnAvatarClear(PlayerSetup.Instance.AvatarDescriptor); + OnAvatarSetup(PlayerSetup.Instance.AvatarDescriptor); } internal void OnIKSystemLateUpdate(HumanPoseHandler p_handler, Transform p_hips) { if(m_ready && MetaPort.Instance.isUsingVr && (p_handler != null) && Settings.SkeletalInput) { - if(CVRInputManager.Instance._leftController != ABI_RC.Systems.InputManagement.XR.eXRControllerType.None) + if(CVRInputManager.Instance.IsLeftControllerTracking()) { Quaternion l_turnBack = (m_leftHandOffset.m_source.rotation * m_leftHandOffset.m_offset) * Quaternion.Inverse(m_leftHandOffset.m_target.rotation); foreach(var l_offset in m_leftFingerOffsets) l_offset.m_target.rotation = l_turnBack * (l_offset.m_source.rotation * l_offset.m_offset); } - if(CVRInputManager.Instance._rightController != ABI_RC.Systems.InputManagement.XR.eXRControllerType.None) + if(CVRInputManager.Instance.IsRightControllerTracking()) { Quaternion l_turnBack = (m_rightHandOffset.m_source.rotation * m_rightHandOffset.m_offset) * Quaternion.Inverse(m_rightHandOffset.m_target.rotation); foreach(var l_offset in m_rightFingerOffsets) diff --git a/ml_bft/GameEvents.cs b/ml_bft/GameEvents.cs index 58ea46a..0b3d7a6 100644 --- a/ml_bft/GameEvents.cs +++ b/ml_bft/GameEvents.cs @@ -24,8 +24,6 @@ namespace ml_bft public void Invoke(T1 p_objA, T2 p_objB) => m_action?.Invoke(p_objA, p_objB); } - public static readonly GameEvent OnAvatarSetup = new GameEvent(); - public static readonly GameEvent OnAvatarClear = new GameEvent(); public static readonly GameEvent OnAvatarReuse = new GameEvent(); public static readonly GameEvent OnInputUpdate = new GameEvent(); public static readonly GameEvent OnIKSystemLateUpdate = new GameEvent(); @@ -34,18 +32,6 @@ namespace ml_bft { try { - p_instance.Patch( - typeof(PlayerSetup).GetMethod(nameof(PlayerSetup.SetupAvatar), BindingFlags.Instance | BindingFlags.Public), - null, - new HarmonyLib.HarmonyMethod(typeof(GameEvents).GetMethod(nameof(OnSetupAvatar_Postfix), BindingFlags.Static | BindingFlags.NonPublic)) - ); - - p_instance.Patch( - typeof(PlayerSetup).GetMethod(nameof(PlayerSetup.ClearAvatar), BindingFlags.Instance | BindingFlags.Public), - null, - new HarmonyLib.HarmonyMethod(typeof(GameEvents).GetMethod(nameof(OnAvatarClear_Postfix), BindingFlags.Static | BindingFlags.NonPublic)) - ); - p_instance.Patch( typeof(IKSystem).GetMethod(nameof(IKSystem.ReinitializeAvatar), BindingFlags.Instance | BindingFlags.Public), null, @@ -70,30 +56,6 @@ namespace ml_bft } } - static void OnAvatarClear_Postfix() - { - try - { - OnAvatarClear.Invoke(); - } - catch(Exception e) - { - MelonLoader.MelonLogger.Error(e); - } - } - - static void OnSetupAvatar_Postfix() - { - try - { - OnAvatarSetup.Invoke(); - } - catch(Exception l_exception) - { - MelonLoader.MelonLogger.Error(l_exception); - } - } - static void OnAvatarReinitialize_Postfix() { try diff --git a/ml_bft/Settings.cs b/ml_bft/Settings.cs index 6f41d7b..84f7ee8 100644 --- a/ml_bft/Settings.cs +++ b/ml_bft/Settings.cs @@ -64,31 +64,31 @@ namespace ml_bft { while(ViewManager.Instance == null) yield return null; - while(ViewManager.Instance.gameMenuView == null) + while(ViewManager.Instance.cohtmlView == null) yield return null; - while(ViewManager.Instance.gameMenuView.Listener == null) + while(ViewManager.Instance.cohtmlView.Listener == null) yield return null; - ViewManager.Instance.gameMenuView.Listener.ReadyForBindings += () => + ViewManager.Instance.cohtmlView.Listener.ReadyForBindings += () => { - ViewManager.Instance.gameMenuView.View.BindCall("OnToggleUpdate_" + ms_category.Identifier, new Action(OnToggleUpdate)); - ViewManager.Instance.gameMenuView.View.BindCall("OnDropdownUpdate_" + ms_category.Identifier, new Action(OnDropdownUpdate)); + ViewManager.Instance.cohtmlView.View.BindCall("OnToggleUpdate_" + ms_category.Identifier, new Action(OnToggleUpdate)); + ViewManager.Instance.cohtmlView.View.BindCall("OnDropdownUpdate_" + ms_category.Identifier, new Action(OnDropdownUpdate)); }; - ViewManager.Instance.gameMenuView.Listener.FinishLoad += (_) => + ViewManager.Instance.cohtmlView.Listener.FinishLoad += (_) => { - ViewManager.Instance.gameMenuView.View.ExecuteScript(ResourcesHandler.GetEmbeddedResource("mods_extension.js")); - ViewManager.Instance.gameMenuView.View.ExecuteScript(ResourcesHandler.GetEmbeddedResource("mod_menu.js")); + ViewManager.Instance.cohtmlView.View.ExecuteScript(ResourcesHandler.GetEmbeddedResource("mods_extension.js")); + ViewManager.Instance.cohtmlView.View.ExecuteScript(ResourcesHandler.GetEmbeddedResource("mod_menu.js")); MelonLoader.MelonCoroutines.Start(UpdateMenuSettings()); }; } static System.Collections.IEnumerator UpdateMenuSettings() { - while(!ViewManager.Instance.IsReady || !ViewManager.Instance.IsMainMenuOpen) + while(!ViewManager.Instance.IsReady || !ViewManager.Instance.IsViewShown) yield return null; foreach(var l_entry in ms_entries) - ViewManager.Instance.gameMenuView.View.TriggerEvent("updateModSetting", ms_category.Identifier, l_entry.DisplayName, l_entry.GetValueAsString()); + ViewManager.Instance.cohtmlView.View.TriggerEvent("updateModSetting", ms_category.Identifier, l_entry.DisplayName, l_entry.GetValueAsString()); } static void OnToggleUpdate(string p_name, string p_value) diff --git a/ml_bft/Utils.cs b/ml_bft/Utils.cs index 688febf..cfdbfd7 100644 --- a/ml_bft/Utils.cs +++ b/ml_bft/Utils.cs @@ -17,12 +17,5 @@ namespace ml_bft public static bool IsInVR() => ((MetaPort.Instance != null) && MetaPort.Instance.isUsingVr); 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 void SetAvatarTPose() - { - IKSystem.Instance.SetAvatarPose(IKSystem.AvatarPose.TPose); - PlayerSetup.Instance._avatar.transform.localPosition = Vector3.zero; - PlayerSetup.Instance._avatar.transform.localRotation = Quaternion.identity; - } } } diff --git a/ml_dht/GameEvents.cs b/ml_dht/GameEvents.cs index 56e8043..03f2d3d 100644 --- a/ml_dht/GameEvents.cs +++ b/ml_dht/GameEvents.cs @@ -35,8 +35,6 @@ namespace ml_dht public void Invoke(T1 p_objA, T2 p_objB) => m_action?.Invoke(p_objA, p_objB); } - public static readonly GameEvent OnAvatarSetup = new GameEvent(); - public static readonly GameEvent OnAvatarClear = new GameEvent(); public static readonly GameEvent OnAvatarReuse = new GameEvent(); public static readonly GameEvent OnEyeControllerUpdate = new GameEvent(); public static readonly GameEvent OnFaceTrackingUpdate = new GameEvent(); @@ -47,18 +45,6 @@ namespace ml_dht { try { - p_instance.Patch( - typeof(PlayerSetup).GetMethod(nameof(PlayerSetup.ClearAvatar), BindingFlags.Instance | BindingFlags.Public), - null, - new HarmonyLib.HarmonyMethod(typeof(GameEvents).GetMethod(nameof(OnAvatarClear_Postfix), BindingFlags.Static | BindingFlags.NonPublic)) - ); - - p_instance.Patch( - typeof(PlayerSetup).GetMethod(nameof(PlayerSetup.SetupAvatar), BindingFlags.Instance | BindingFlags.Public), - null, - new HarmonyLib.HarmonyMethod(typeof(GameEvents).GetMethod(nameof(OnSetupAvatar_Postfix), BindingFlags.Static | BindingFlags.NonPublic)) - ); - p_instance.Patch( typeof(IKSystem).GetMethod(nameof(IKSystem.ReinitializeAvatar), BindingFlags.Instance | BindingFlags.Public), null, @@ -92,30 +78,6 @@ namespace ml_dht } } - static void OnSetupAvatar_Postfix() - { - try - { - OnAvatarSetup.Invoke(); - } - catch(Exception e) - { - MelonLoader.MelonLogger.Error(e); - } - } - - static void OnAvatarClear_Postfix() - { - try - { - OnAvatarClear.Invoke(); - } - catch(Exception e) - { - MelonLoader.MelonLogger.Error(e); - } - } - static void OnAvatarReinitialize_Postfix() { try diff --git a/ml_dht/HeadTracked.cs b/ml_dht/HeadTracked.cs index 17b9e98..858241d 100644 --- a/ml_dht/HeadTracked.cs +++ b/ml_dht/HeadTracked.cs @@ -2,6 +2,7 @@ using ABI_RC.Core.Player; using ABI_RC.Core.Player.EyeMovement; using ABI_RC.Systems.FaceTracking; +using ABI_RC.Systems.GameEventSystem; using ABI_RC.Systems.IK; using ABI_RC.Systems.VRModeSwitch; using RootMotion.FinalIK; @@ -69,8 +70,8 @@ namespace ml_dht Settings.OnHeadTrackingChanged.AddListener(this.OnEnabledOrHeadTrackingChanged); Settings.OnSmoothingChanged.AddListener(this.OnSmoothingChanged); - GameEvents.OnAvatarClear.AddListener(this.OnAvatarClear); - GameEvents.OnAvatarSetup.AddListener(this.OnAvatarSetup); + CVRGameEventSystem.Avatar.OnLocalAvatarLoad.AddListener(this.OnAvatarSetup); + CVRGameEventSystem.Avatar.OnLocalAvatarClear.AddListener(this.OnAvatarClear); GameEvents.OnAvatarReuse.AddListener(this.OnAvatarReuse); GameEvents.OnEyeControllerUpdate.AddListener(this.OnEyeControllerUpdate); GameEvents.OnFaceTrackingUpdate.AddListener(this.UpdateFaceTracking); @@ -89,8 +90,8 @@ namespace ml_dht Settings.OnHeadTrackingChanged.RemoveListener(this.OnEnabledOrHeadTrackingChanged); Settings.OnSmoothingChanged.RemoveListener(this.OnSmoothingChanged); - GameEvents.OnAvatarClear.RemoveListener(this.OnAvatarClear); - GameEvents.OnAvatarSetup.RemoveListener(this.OnAvatarSetup); + CVRGameEventSystem.Avatar.OnLocalAvatarLoad.RemoveListener(this.OnAvatarSetup); + CVRGameEventSystem.Avatar.OnLocalAvatarClear.RemoveListener(this.OnAvatarClear); GameEvents.OnAvatarReuse.RemoveListener(this.OnAvatarReuse); GameEvents.OnEyeControllerUpdate.RemoveListener(this.OnEyeControllerUpdate); GameEvents.OnFaceTrackingUpdate.RemoveListener(this.UpdateFaceTracking); @@ -131,45 +132,59 @@ namespace ml_dht { m_lastHeadRotation = Quaternion.Slerp(m_lastHeadRotation, m_avatarDescriptor.transform.rotation * (m_headRotation * m_bindRotation), m_smoothing); - if(!PlayerSetup.Instance.IsEmotePlaying()) + if(!PlayerSetup.Instance.IsEmotePlaying) m_headBone.rotation = m_lastHeadRotation; } } // Game events - internal void OnAvatarSetup() + internal void OnAvatarSetup(CVRAvatar p_avatar) { - m_camera = PlayerSetup.Instance.GetActiveCamera().transform; - m_avatarDescriptor = PlayerSetup.Instance._avatar.GetComponent(); - - if(PlayerSetup.Instance._animator.isHuman) + try { - IKSystem.Instance.SetAvatarPose(IKSystem.AvatarPose.TPose); - PlayerSetup.Instance._avatar.transform.localPosition = Vector3.zero; - PlayerSetup.Instance._avatar.transform.localRotation = Quaternion.identity; + m_camera = PlayerSetup.Instance.activeCam.transform; + m_avatarDescriptor = PlayerSetup.Instance.AvatarObject.GetComponent(); - m_headBone = PlayerSetup.Instance._animator.GetBoneTransform(HumanBodyBones.Head); - if(m_headBone != null) - m_bindRotation = Quaternion.Inverse(m_avatarDescriptor.transform.rotation) * m_headBone.rotation; + if(PlayerSetup.Instance.Animator.isHuman) + { + IKSystem.Instance.SetAvatarPose(IKSystem.AvatarPose.TPose); + PlayerSetup.Instance.AvatarTransform.localPosition = Vector3.zero; + PlayerSetup.Instance.AvatarTransform.localRotation = Quaternion.identity; - m_lookIK = PlayerSetup.Instance._avatar.GetComponent(); - if(m_lookIK != null) - m_lookIK.onPostSolverUpdate.AddListener(this.OnLookIKPostUpdate); + m_headBone = PlayerSetup.Instance.Animator.GetBoneTransform(HumanBodyBones.Head); + if(m_headBone != null) + m_bindRotation = Quaternion.Inverse(m_avatarDescriptor.transform.rotation) * m_headBone.rotation; + + m_lookIK = PlayerSetup.Instance.AvatarObject.GetComponent(); + if(m_lookIK != null) + m_lookIK.onPostSolverUpdate.AddListener(this.OnLookIKPostUpdate); + } + } + catch(Exception e) + { + MelonLoader.MelonLogger.Error(e); } } - void OnAvatarClear() + void OnAvatarClear(CVRAvatar p_avatar) { - m_avatarDescriptor = null; - m_lookIK = null; - m_headBone = null; - m_lastHeadRotation = Quaternion.identity; - m_bindRotation = Quaternion.identity; + try + { + m_avatarDescriptor = null; + m_lookIK = null; + m_headBone = null; + m_lastHeadRotation = Quaternion.identity; + m_bindRotation = Quaternion.identity; + } + catch(Exception e) + { + MelonLoader.MelonLogger.Error(e); + } } void OnAvatarReuse() { - m_camera = PlayerSetup.Instance.GetActiveCamera().transform; + m_camera = PlayerSetup.Instance.activeCam.transform; - m_lookIK = PlayerSetup.Instance._avatar.GetComponent(); + m_lookIK = PlayerSetup.Instance.AvatarObject.GetComponent(); if(m_lookIK != null) m_lookIK.onPostSolverUpdate.AddListener(this.OnLookIKPostUpdate); } diff --git a/ml_dht/Settings.cs b/ml_dht/Settings.cs index 203b898..31e7f0b 100644 --- a/ml_dht/Settings.cs +++ b/ml_dht/Settings.cs @@ -74,31 +74,31 @@ namespace ml_dht { while(ViewManager.Instance == null) yield return null; - while(ViewManager.Instance.gameMenuView == null) + while(ViewManager.Instance.cohtmlView == null) yield return null; - while(ViewManager.Instance.gameMenuView.Listener == null) + while(ViewManager.Instance.cohtmlView.Listener == null) yield return null; - ViewManager.Instance.gameMenuView.Listener.ReadyForBindings += () => + ViewManager.Instance.cohtmlView.Listener.ReadyForBindings += () => { - ViewManager.Instance.gameMenuView.View.BindCall("OnToggleUpdate_" + ms_category.Identifier, new Action(OnToggleUpdate)); - ViewManager.Instance.gameMenuView.View.BindCall("OnSliderUpdate_" + ms_category.Identifier, new Action(OnSliderUpdate)); + ViewManager.Instance.cohtmlView.View.BindCall("OnToggleUpdate_" + ms_category.Identifier, new Action(OnToggleUpdate)); + ViewManager.Instance.cohtmlView.View.BindCall("OnSliderUpdate_" + ms_category.Identifier, new Action(OnSliderUpdate)); }; - ViewManager.Instance.gameMenuView.Listener.FinishLoad += (_) => + ViewManager.Instance.cohtmlView.Listener.FinishLoad += (_) => { - ViewManager.Instance.gameMenuView.View.ExecuteScript(ResourcesHandler.GetEmbeddedResource("mods_extension.js")); - ViewManager.Instance.gameMenuView.View.ExecuteScript(ResourcesHandler.GetEmbeddedResource("mod_menu.js")); + ViewManager.Instance.cohtmlView.View.ExecuteScript(ResourcesHandler.GetEmbeddedResource("mods_extension.js")); + ViewManager.Instance.cohtmlView.View.ExecuteScript(ResourcesHandler.GetEmbeddedResource("mod_menu.js")); MelonLoader.MelonCoroutines.Start(UpdateMenuSettings()); }; } static System.Collections.IEnumerator UpdateMenuSettings() { - while(!ViewManager.Instance.IsReady || !ViewManager.Instance.IsMainMenuOpen) + while(!ViewManager.Instance.IsReady || !ViewManager.Instance.IsViewShown) yield return null; foreach(var l_entry in ms_entries) - ViewManager.Instance.gameMenuView.View.TriggerEvent("updateModSetting", ms_category.Identifier, l_entry.DisplayName, l_entry.GetValueAsString()); + ViewManager.Instance.cohtmlView.View.TriggerEvent("updateModSetting", ms_category.Identifier, l_entry.DisplayName, l_entry.GetValueAsString()); } static void OnSliderUpdate(string p_name, string p_value) diff --git a/ml_lme/GameEvents.cs b/ml_lme/GameEvents.cs index c3191b5..281b9eb 100644 --- a/ml_lme/GameEvents.cs +++ b/ml_lme/GameEvents.cs @@ -23,8 +23,6 @@ namespace ml_lme public void Invoke(T1 p_obj) => m_action?.Invoke(p_obj); } - public static readonly GameEvent OnAvatarSetup = new GameEvent(); - public static readonly GameEvent OnAvatarClear = new GameEvent(); public static readonly GameEvent OnAvatarReuse = new GameEvent(); public static readonly GameEvent OnRayScale = new GameEvent(); public static readonly GameEvent OnPlayspaceScale = new GameEvent(); @@ -34,18 +32,6 @@ namespace ml_lme { try { - p_instance.Patch( - typeof(PlayerSetup).GetMethod(nameof(PlayerSetup.ClearAvatar), BindingFlags.Instance | BindingFlags.Public), - null, - new HarmonyLib.HarmonyMethod(typeof(GameEvents).GetMethod(nameof(OnAvatarClear_Postfix), BindingFlags.Static | BindingFlags.NonPublic)) - ); - - p_instance.Patch( - typeof(PlayerSetup).GetMethod(nameof(PlayerSetup.SetupAvatar), BindingFlags.Instance | BindingFlags.Public), - null, - new HarmonyLib.HarmonyMethod(typeof(GameEvents).GetMethod(nameof(OnSetupAvatar_Postfix), BindingFlags.Static | BindingFlags.NonPublic)) - ); - p_instance.Patch( typeof(IKSystem).GetMethod(nameof(IKSystem.ReinitializeAvatar), BindingFlags.Instance | BindingFlags.Public), null, @@ -53,7 +39,7 @@ namespace ml_lme ); p_instance.Patch( - typeof(PlayerSetup).GetMethod(nameof(PlayerSetup.SetControllerRayScale), BindingFlags.Instance | BindingFlags.Public), + typeof(PlayerSetup).GetMethod("SetControllerRayScale", BindingFlags.Instance | BindingFlags.NonPublic), null, new HarmonyLib.HarmonyMethod(typeof(GameEvents).GetMethod(nameof(OnRayScale_Postfix), BindingFlags.Static | BindingFlags.NonPublic)) ); @@ -76,30 +62,6 @@ namespace ml_lme } } - static void OnAvatarClear_Postfix() - { - try - { - OnAvatarClear.Invoke(); - } - catch(Exception e) - { - MelonLoader.MelonLogger.Error(e); - } - } - - static void OnSetupAvatar_Postfix() - { - try - { - OnAvatarSetup.Invoke(); - } - catch(Exception e) - { - MelonLoader.MelonLogger.Error(e); - } - } - static void OnAvatarReinitialize_Postfix() { try diff --git a/ml_lme/LeapInput.cs b/ml_lme/LeapInput.cs index b361737..2273bb2 100644 --- a/ml_lme/LeapInput.cs +++ b/ml_lme/LeapInput.cs @@ -40,7 +40,6 @@ namespace ml_lme m_handRayLeft.isInteractionRay = true; m_handRayLeft.triggerHoverEvents = false; m_handRayLeft.attachmentDistance = 0f; - m_handRayLeft.uiMask = 32; m_handRayLeft.isDesktopRay = !m_inVR; m_lineLeft = m_handRayLeft.gameObject.AddComponent(); @@ -61,7 +60,6 @@ namespace ml_lme m_handRayRight.isInteractionRay = true; m_handRayRight.triggerHoverEvents = false; m_handRayRight.attachmentDistance = 0f; - m_handRayRight.uiMask = 32; m_handRayRight.isDesktopRay = !m_inVR; m_lineRight = m_handRayRight.gameObject.AddComponent(); @@ -120,12 +118,10 @@ namespace ml_lme m_lineLeft.material = PlayerSetup.Instance.vrRayLeft.lineRenderer.material; m_lineLeft.gameObject.layer = PlayerSetup.Instance.vrRayLeft.gameObject.layer; - m_handRayLeft.highlightMaterial = PlayerSetup.Instance.vrRayLeft.highlightMaterial; m_handRayLeft.SetVRActive(m_inVR); m_lineRight.material = PlayerSetup.Instance.vrRayLeft.lineRenderer.material; m_lineRight.gameObject.layer = PlayerSetup.Instance.vrRayLeft.gameObject.layer; - m_handRayRight.highlightMaterial = PlayerSetup.Instance.vrRayLeft.highlightMaterial; m_handRayRight.SetVRActive(m_inVR); } @@ -655,7 +651,7 @@ namespace ml_lme void SetGameFingersTracking(bool p_state) { base._inputManager.individualFingerTracking = p_state; - IKSystem.Instance.FingerSystem.controlActive = base._inputManager.individualFingerTracking; + IKSystem.Instance.FingerSystem.ControlActive = base._inputManager.individualFingerTracking; } } } diff --git a/ml_lme/LeapTracked.cs b/ml_lme/LeapTracked.cs index 0d9cccb..211fc4c 100644 --- a/ml_lme/LeapTracked.cs +++ b/ml_lme/LeapTracked.cs @@ -1,4 +1,6 @@ -using ABI_RC.Core.Player; +using ABI.CCK.Components; +using ABI_RC.Core.Player; +using ABI_RC.Systems.GameEventSystem; using ABI_RC.Systems.IK; using RootMotion.FinalIK; using System.Collections.Generic; @@ -148,8 +150,8 @@ namespace ml_lme Settings.OnFingersOnlyChanged.AddListener(this.OnEnabledOrFingersOnlyChanged); Settings.OnTrackElbowsChanged.AddListener(this.OnTrackElbowsChanged); - GameEvents.OnAvatarClear.AddListener(this.OnAvatarClear); - GameEvents.OnAvatarSetup.AddListener(this.OnAvatarSetup); + CVRGameEventSystem.Avatar.OnLocalAvatarLoad.AddListener(this.OnAvatarSetup); + CVRGameEventSystem.Avatar.OnLocalAvatarClear.AddListener(this.OnAvatarClear); GameEvents.OnAvatarReuse.AddListener(this.OnAvatarReuse); } @@ -174,8 +176,8 @@ namespace ml_lme Settings.OnFingersOnlyChanged.RemoveListener(this.OnEnabledOrFingersOnlyChanged); Settings.OnTrackElbowsChanged.RemoveListener(this.OnTrackElbowsChanged); - GameEvents.OnAvatarClear.RemoveListener(this.OnAvatarClear); - GameEvents.OnAvatarSetup.RemoveListener(this.OnAvatarSetup); + CVRGameEventSystem.Avatar.OnLocalAvatarLoad.RemoveListener(this.OnAvatarSetup); + CVRGameEventSystem.Avatar.OnLocalAvatarClear.RemoveListener(this.OnAvatarClear); GameEvents.OnAvatarReuse.RemoveListener(this.OnAvatarReuse); } @@ -255,65 +257,79 @@ namespace ml_lme } // Game events - void OnAvatarClear() + void OnAvatarClear(CVRAvatar p_avatar) { - m_vrIK = null; - m_hips = null; - m_leftArmIK = null; - m_rightArmIK = null; - m_leftTargetActive = false; - m_rightTargetActive = false; + try + { + m_vrIK = null; + m_hips = null; + m_leftArmIK = null; + m_rightArmIK = null; + m_leftTargetActive = false; + m_rightTargetActive = false; - m_poseHandler?.Dispose(); - m_poseHandler = null; + m_poseHandler?.Dispose(); + m_poseHandler = null; - m_leftHandTarget.localPosition = Vector3.zero; - m_leftHandTarget.localRotation = Quaternion.identity; - m_rightHandTarget.localPosition = Vector3.zero; - m_rightHandTarget.localRotation = Quaternion.identity; + m_leftHandTarget.localPosition = Vector3.zero; + m_leftHandTarget.localRotation = Quaternion.identity; + m_rightHandTarget.localPosition = Vector3.zero; + m_rightHandTarget.localRotation = Quaternion.identity; - m_leftHandOffset.Reset(); - m_rightHandOffset.Reset(); + m_leftHandOffset.Reset(); + m_rightHandOffset.Reset(); - m_leftFingerOffsets.Clear(); - m_rightFingerOffsets.Clear(); + m_leftFingerOffsets.Clear(); + m_rightFingerOffsets.Clear(); + } + catch(System.Exception e) + { + MelonLoader.MelonLogger.Error(e); + } } - void OnAvatarSetup() + void OnAvatarSetup(CVRAvatar p_avatar) { - Animator l_animator = PlayerSetup.Instance._animator; - if(l_animator.isHuman) + try { - Utils.SetAvatarTPose(); - - m_poseHandler = new HumanPoseHandler(l_animator.avatar, l_animator.transform); - m_poseHandler.GetHumanPose(ref m_pose); - - m_hips = l_animator.GetBoneTransform(HumanBodyBones.Hips); - - m_leftHandOffset.m_source = l_animator.GetBoneTransform(HumanBodyBones.LeftHand); - m_leftHandTarget.localRotation = ms_offsetLeft * (Quaternion.Inverse(l_animator.transform.rotation) * m_leftHandOffset.m_source.rotation); - - m_rightHandOffset.m_source = l_animator.GetBoneTransform(HumanBodyBones.RightHand); - m_rightHandTarget.localRotation = ms_offsetRight * (Quaternion.Inverse(l_animator.transform.rotation) * m_rightHandOffset.m_source.rotation); - - ParseFingersBones(); - - m_vrIK = l_animator.GetComponent(); - if(m_vrIK != null) + Animator l_animator = PlayerSetup.Instance.Animator; + if(l_animator.isHuman) { - m_vrIK.onPreSolverUpdate.AddListener(this.OnIKPreSolverUpdate); - m_vrIK.onPostSolverUpdate.AddListener(this.OnIKPostSolverUpdate); + Utils.SetAvatarTPose(); + + m_poseHandler = new HumanPoseHandler(l_animator.avatar, l_animator.transform); + m_poseHandler.GetHumanPose(ref m_pose); + + m_hips = l_animator.GetBoneTransform(HumanBodyBones.Hips); + + m_leftHandOffset.m_source = l_animator.GetBoneTransform(HumanBodyBones.LeftHand); + m_leftHandTarget.localRotation = ms_offsetLeft * (Quaternion.Inverse(l_animator.transform.rotation) * m_leftHandOffset.m_source.rotation); + + m_rightHandOffset.m_source = l_animator.GetBoneTransform(HumanBodyBones.RightHand); + m_rightHandTarget.localRotation = ms_offsetRight * (Quaternion.Inverse(l_animator.transform.rotation) * m_rightHandOffset.m_source.rotation); + + ParseFingersBones(); + + m_vrIK = l_animator.GetComponent(); + if(m_vrIK != null) + { + m_vrIK.onPreSolverUpdate.AddListener(this.OnIKPreSolverUpdate); + m_vrIK.onPostSolverUpdate.AddListener(this.OnIKPostSolverUpdate); + } + else + SetupArmIK(); } - else - SetupArmIK(); + } + catch(System.Exception e) + { + MelonLoader.MelonLogger.Error(e); } } void OnAvatarReuse() { // Old VRIK is destroyed by game - m_vrIK = PlayerSetup.Instance._animator.GetComponent(); + m_vrIK = PlayerSetup.Instance.AvatarObject.GetComponent(); if(Utils.IsInVR()) RemoveArmIK(); @@ -409,7 +425,7 @@ namespace ml_lme void SetupArmIK() { - Animator l_animator = PlayerSetup.Instance._animator; + Animator l_animator = PlayerSetup.Instance.Animator; Transform l_chest = l_animator.GetBoneTransform(HumanBodyBones.UpperChest); if(l_chest == null) l_chest = l_animator.GetBoneTransform(HumanBodyBones.Chest); @@ -472,7 +488,7 @@ namespace ml_lme LeapTracking.Instance.Rebind(PlayerSetup.Instance.transform.rotation); // Align rotations of leap fingers to avatar fingers - Animator l_animator = PlayerSetup.Instance._animator; + Animator l_animator = PlayerSetup.Instance.Animator; LeapHand l_leapLeft = LeapTracking.Instance.GetLeftHand(); LeapHand l_leapRight = LeapTracking.Instance.GetRightHand(); // Try to "fix" rotations, slightly inaccurate after 0YX plane rotation diff --git a/ml_lme/LeapTracking.cs b/ml_lme/LeapTracking.cs index eb96377..8b4aba6 100644 --- a/ml_lme/LeapTracking.cs +++ b/ml_lme/LeapTracking.cs @@ -136,7 +136,7 @@ namespace ml_lme { if(Settings.Enabled) { - Transform l_camera = PlayerSetup.Instance.GetActiveCamera().transform; + Transform l_camera = PlayerSetup.Instance.activeCam.transform; m_root.position = l_camera.position; m_root.rotation = (Settings.HeadAttach ? l_camera.rotation : PlayerSetup.Instance.GetPlayerRotation()); diff --git a/ml_lme/Settings.cs b/ml_lme/Settings.cs index 172ed7d..d8dbedb 100644 --- a/ml_lme/Settings.cs +++ b/ml_lme/Settings.cs @@ -146,32 +146,32 @@ namespace ml_lme { while(ViewManager.Instance == null) yield return null; - while(ViewManager.Instance.gameMenuView == null) + while(ViewManager.Instance.cohtmlView == null) yield return null; - while(ViewManager.Instance.gameMenuView.Listener == null) + while(ViewManager.Instance.cohtmlView.Listener == null) yield return null; - ViewManager.Instance.gameMenuView.Listener.ReadyForBindings += () => + ViewManager.Instance.cohtmlView.Listener.ReadyForBindings += () => { - ViewManager.Instance.gameMenuView.View.BindCall("OnToggleUpdate_" + ms_category.Identifier, new Action(OnToggleUpdate)); - ViewManager.Instance.gameMenuView.View.BindCall("OnSliderUpdate_" + ms_category.Identifier, new Action(OnSliderUpdate)); - ViewManager.Instance.gameMenuView.View.BindCall("OnDropdownUpdate_" + ms_category.Identifier, new Action(OnDropdownUpdate)); + ViewManager.Instance.cohtmlView.View.BindCall("OnToggleUpdate_" + ms_category.Identifier, new Action(OnToggleUpdate)); + ViewManager.Instance.cohtmlView.View.BindCall("OnSliderUpdate_" + ms_category.Identifier, new Action(OnSliderUpdate)); + ViewManager.Instance.cohtmlView.View.BindCall("OnDropdownUpdate_" + ms_category.Identifier, new Action(OnDropdownUpdate)); }; - ViewManager.Instance.gameMenuView.Listener.FinishLoad += (_) => + ViewManager.Instance.cohtmlView.Listener.FinishLoad += (_) => { - ViewManager.Instance.gameMenuView.View.ExecuteScript(ResourcesHandler.GetEmbeddedResource("mods_extension.js")); - ViewManager.Instance.gameMenuView.View.ExecuteScript(ResourcesHandler.GetEmbeddedResource("mod_menu.js")); + ViewManager.Instance.cohtmlView.View.ExecuteScript(ResourcesHandler.GetEmbeddedResource("mods_extension.js")); + ViewManager.Instance.cohtmlView.View.ExecuteScript(ResourcesHandler.GetEmbeddedResource("mod_menu.js")); MelonLoader.MelonCoroutines.Start(UpdateMenuSettings()); }; } static System.Collections.IEnumerator UpdateMenuSettings() { - while(!ViewManager.Instance.IsReady || !ViewManager.Instance.IsMainMenuOpen) + while(!ViewManager.Instance.IsReady || !ViewManager.Instance.IsViewShown) yield return null; foreach(var l_entry in ms_entries) - ViewManager.Instance.gameMenuView.View.TriggerEvent("updateModSetting", ms_category.Identifier, l_entry.DisplayName, l_entry.GetValueAsString()); + ViewManager.Instance.cohtmlView.View.TriggerEvent("updateModSetting", ms_category.Identifier, l_entry.DisplayName, l_entry.GetValueAsString()); } static void OnToggleUpdate(string p_name, string p_value) diff --git a/ml_lme/Utils.cs b/ml_lme/Utils.cs index 55b0b8b..e653fde 100644 --- a/ml_lme/Utils.cs +++ b/ml_lme/Utils.cs @@ -59,8 +59,8 @@ namespace ml_lme public static void SetAvatarTPose() { IKSystem.Instance.SetAvatarPose(IKSystem.AvatarPose.TPose); - PlayerSetup.Instance._avatar.transform.localPosition = Vector3.zero; - PlayerSetup.Instance._avatar.transform.localRotation = Quaternion.identity; + PlayerSetup.Instance.AvatarTransform.localPosition = Vector3.zero; + PlayerSetup.Instance.AvatarTransform.localRotation = Quaternion.identity; } public static void Swap(ref T lhs, ref T rhs) diff --git a/ml_mods_cvr.sln b/ml_mods_cvr.sln index 1a8e1ef..df44b4a 100644 --- a/ml_mods_cvr.sln +++ b/ml_mods_cvr.sln @@ -32,6 +32,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ml_ppu", "ml_ppu\ml_ppu.csp EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ml_vet", "ml_vet\ml_vet.csproj", "{8DB32590-FC5B-46A8-9747-344E86B18ACF}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ml_pah", "ml_pah\ml_pah.csproj", "{C4659F60-3FED-4F43-88E4-969907D4C7A6}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|x64 = Debug|x64 @@ -83,6 +85,9 @@ Global {8DB32590-FC5B-46A8-9747-344E86B18ACF}.Debug|x64.Build.0 = Debug|x64 {8DB32590-FC5B-46A8-9747-344E86B18ACF}.Release|x64.ActiveCfg = Release|x64 {8DB32590-FC5B-46A8-9747-344E86B18ACF}.Release|x64.Build.0 = Release|x64 + {C4659F60-3FED-4F43-88E4-969907D4C7A6}.Debug|x64.ActiveCfg = Debug|x64 + {C4659F60-3FED-4F43-88E4-969907D4C7A6}.Release|x64.ActiveCfg = Release|x64 + {C4659F60-3FED-4F43-88E4-969907D4C7A6}.Release|x64.Build.0 = Release|x64 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/ml_pah/AvatarEntry.cs b/ml_pah/AvatarEntry.cs new file mode 100644 index 0000000..ee940ff --- /dev/null +++ b/ml_pah/AvatarEntry.cs @@ -0,0 +1,14 @@ +using System; + +namespace ml_pah +{ + [Serializable] + class AvatarEntry + { + public string m_id; + public string m_name; + public string m_imageUrl; + public DateTime m_lastUsageDate; + public bool m_cached = false; + } +} diff --git a/ml_pah/HistoryManager.cs b/ml_pah/HistoryManager.cs new file mode 100644 index 0000000..cd3d68c --- /dev/null +++ b/ml_pah/HistoryManager.cs @@ -0,0 +1,205 @@ +using ABI_RC.Core.Networking.API; +using ABI_RC.Core.Networking.API.Responses; +using Newtonsoft.Json; +using System; +using System.Collections; +using System.Collections.Generic; +using System.IO; +using System.Threading.Tasks; + +namespace ml_pah +{ + static class HistoryManager + { + internal class EntriesUpdateEvent + { + event Action m_action; + public void AddListener(Action p_listener) => m_action += p_listener; + public void RemoveListener(Action p_listener) => m_action -= p_listener; + public void Invoke() => m_action?.Invoke(); + } + + public static readonly EntriesUpdateEvent OnEntriesUpdated = new EntriesUpdateEvent(); + + static bool ms_initialized = false; + static string ms_historyPath; + readonly static List ms_avatarEntries = new List(); + + static int ms_lastTick = 0; + + // Init + internal static void Initialize() + { + if(!ms_initialized) + { + ms_historyPath = Path.Combine(MelonLoader.Utils.MelonEnvironment.UserDataDirectory, "PlayerAvatarHistory.json"); + + try + { + if(File.Exists(ms_historyPath)) + { + string l_json = File.ReadAllText(ms_historyPath); + List l_entries = JsonConvert.DeserializeObject>(l_json); + if(l_entries != null) + { + ms_avatarEntries.AddRange(l_entries); + LimitEntries(); + ms_avatarEntries.Sort((a, b) => a.m_lastUsageDate.CompareTo(b.m_lastUsageDate)); + } + } + } + catch(Exception e) + { + MelonLoader.MelonLogger.Error(e); + } + + ms_lastTick = Environment.TickCount; + Settings.OnAutosaveTimeChanged.AddListener(OnAutosaveTimeChanged); + + ms_initialized = true; + } + } + + internal static void Shutdown() + { + if(ms_initialized) + { + SaveHistory(); + + Settings.OnAutosaveTimeChanged.RemoveListener(OnAutosaveTimeChanged); + + ms_initialized = false; + } + } + + // Update + public static void Update() + { + if(ms_initialized && (Settings.AutosaveTime > 0)) + { + int l_tick = Environment.TickCount; + if((l_tick - ms_lastTick) >= (Settings.AutosaveTime * 60000)) + { + MelonLoader.MelonCoroutines.Start(AutosaveCoroutine()); + ms_lastTick = l_tick; + } + } + } + + // Entries + internal static List GetAvatarEntries() => ms_avatarEntries; + + internal static void AddEntry(string p_id) + { + if(ms_initialized) + { + int l_index = ms_avatarEntries.FindIndex(l_entry => l_entry.m_id == p_id); + if(l_index != -1) + { + ms_avatarEntries[l_index].m_lastUsageDate = DateTime.Now; + + if(l_index != 0) + { + // Move in list + AvatarEntry l_entry = ms_avatarEntries[l_index]; + ms_avatarEntries.RemoveAt(l_index); + ms_avatarEntries.Insert(0, l_entry); + + OnEntriesUpdated?.Invoke(); + } + } + else + { + AvatarEntry l_entry = new AvatarEntry(); + l_entry.m_id = p_id; + l_entry.m_name = "Loading ..."; + l_entry.m_lastUsageDate = DateTime.Now; + + MelonLoader.MelonCoroutines.Start(RequestAvatarInfo(l_entry)); + } + } + } + + // History + internal static void ClearHistory() => ms_avatarEntries.Clear(); + + internal static void SaveHistory() + { + if(ms_initialized) + { + try + { + string l_json = JsonConvert.SerializeObject(ms_avatarEntries, Formatting.Indented); + File.WriteAllText(ms_historyPath, l_json); + } + catch(Exception e) + { + MelonLoader.MelonLogger.Error(e); + } + } + } + + static IEnumerator AutosaveCoroutine() + { + List l_listCopy = new List(); + l_listCopy.AddRange(ms_avatarEntries); + + Task l_task = Task.Run(() => AutosaveTask(l_listCopy)); + while(!l_task.IsCompleted) + yield return null; + } + + static async Task AutosaveTask(List p_entries) + { + try + { + string l_json = JsonConvert.SerializeObject(p_entries, Formatting.Indented); + File.WriteAllText(ms_historyPath, l_json); + } + catch(Exception e) + { + MelonLoader.MelonLogger.Error(e); + } + + await Task.Delay(1); + } + + // Network request + static IEnumerator RequestAvatarInfo(AvatarEntry p_entry) + { + Task l_task = Task.Run(() => RequestAvatarInfoTask(p_entry)); + while(!l_task.IsCompleted) + yield return null; + + ms_avatarEntries.Insert(0, p_entry); + LimitEntries(); + OnEntriesUpdated?.Invoke(); + } + + static async Task RequestAvatarInfoTask(AvatarEntry p_entry) + { + BaseResponse l_baseResponse = await ApiConnection.MakeRequest(ApiConnection.ApiOperation.AvatarDetail, new { avatarID = p_entry.m_id }); + if(l_baseResponse != null) + { + if(!l_baseResponse.IsSuccessStatusCode) return; + p_entry.m_name = l_baseResponse.Data.Name; + p_entry.m_imageUrl = l_baseResponse.Data.ImageUrl; + p_entry.m_cached = true; + } + } + + // Settings + static void OnAutosaveTimeChanged(int p_value) + { + ms_lastTick = Environment.TickCount; + } + + // Utility + static void LimitEntries() + { + int l_currentLimit = Settings.AvatarsLimit; + while(ms_avatarEntries.Count > l_currentLimit) + ms_avatarEntries.RemoveAt(ms_avatarEntries.Count - 1); + } + } +} diff --git a/ml_pah/Main.cs b/ml_pah/Main.cs new file mode 100644 index 0000000..528c1f8 --- /dev/null +++ b/ml_pah/Main.cs @@ -0,0 +1,59 @@ +using ABI.CCK.Components; +using ABI_RC.Core; +using System; +using System.Collections; +using ABI_RC.Systems.GameEventSystem; + +namespace ml_pah +{ + public class PlayerAvatarHistory : MelonLoader.MelonMod + { + public override void OnInitializeMelon() + { + Settings.Init(); + HistoryManager.Initialize(); + ModUi.Initialize(); + MelonLoader.MelonCoroutines.Start(WaitForRootLogic()); + } + + public override void OnDeinitializeMelon() + { + CVRGameEventSystem.Avatar.OnLocalAvatarLoad.RemoveListener(this.OnLocalAvatarLoad); + HistoryManager.OnEntriesUpdated.RemoveListener(this.OnHistoryEntriesUpdated); + + ModUi.Shutdown(); + HistoryManager.Shutdown(); + } + + IEnumerator WaitForRootLogic() + { + while(RootLogic.Instance == null) + yield return null; + + CVRGameEventSystem.Avatar.OnLocalAvatarLoad.AddListener(this.OnLocalAvatarLoad); + HistoryManager.OnEntriesUpdated.AddListener(this.OnHistoryEntriesUpdated); + } + + public override void OnUpdate() + { + HistoryManager.Update(); + } + + // Game events + void OnLocalAvatarLoad(CVRAvatar p_avatar) + { + try + { + if((p_avatar.AssetInfo != null) && (p_avatar.AssetInfo.objectId.Length > 0)) + HistoryManager.AddEntry(p_avatar.AssetInfo.objectId); + } + catch(Exception e) + { + MelonLoader.MelonLogger.Error(e); + } + } + + // Mod events + void OnHistoryEntriesUpdated() => ModUi.UpdateAvatarsList(); + } +} diff --git a/ml_pah/ModUi.cs b/ml_pah/ModUi.cs new file mode 100644 index 0000000..a7aa3b9 --- /dev/null +++ b/ml_pah/ModUi.cs @@ -0,0 +1,131 @@ +using ABI_RC.Core.EventSystem; +using ABI_RC.Core.InteractionSystem; +using BTKUILib.UIObjects; +using BTKUILib.UIObjects.Components; +using System.Collections.Generic; +using System.IO; +using System.Reflection; + +namespace ml_pah +{ + static class ModUi + { + readonly static string ms_namespace = typeof(ModUi).Namespace; + static bool ms_initialized = false; + + static Page ms_page = null; + + static Category ms_settingsCategory = null; + static Button ms_settingsClearButton = null; + static Button ms_settingSaveButton = null; + static SliderFloat ms_settingsEntriesLimit = null; + static SliderFloat ms_settingsAutosaveTime = null; + + static Category ms_buttonsCategory = null; + static readonly List