mirror of
https://github.com/hanetzer/sdraw_mods_cvr.git
synced 2025-09-03 18:39:23 +00:00
ArmIK usage
Elbows tracking Tracking without VR controllers
This commit is contained in:
parent
3b33dc0cfb
commit
7fcfb04e0f
11 changed files with 238 additions and 121 deletions
|
@ -8,5 +8,5 @@ Merged set of MelonLoader mods for ChilloutVR.
|
|||
| Desktop Head Tracking | ml_dht | 1.0.6 | Yes | Working |
|
||||
| Desktop Reticle Switch | ml_drs | 1.0.0 | Yes | Working |
|
||||
| Four Point Tracking | ml_fpt | 1.0.8 | Yes | Working |
|
||||
| Leap Motion Extension | ml_lme | 1.2.2 | On review | Working |
|
||||
| Leap Motion Extension | ml_lme | 1.2.3 | On review | Working |
|
||||
| Server Connection Info | ml_sci | 1.0.2 | Yes | Working |
|
||||
|
|
|
@ -22,6 +22,7 @@ namespace ml_lme
|
|||
public bool[] m_handsPresenses = null;
|
||||
public Vector3[] m_handsPositons = null;
|
||||
public Quaternion[] m_handsRotations = null;
|
||||
public Vector3[] m_elbowPositions = null;
|
||||
public float[] m_leftFingersBends = null;
|
||||
public float[] m_leftFingersSpreads = null;
|
||||
public float[] m_rightFingersBends = null;
|
||||
|
@ -32,6 +33,7 @@ namespace ml_lme
|
|||
m_handsPresenses = new bool[ms_handsCount];
|
||||
m_handsPositons = new Vector3[ms_handsCount];
|
||||
m_handsRotations = new Quaternion[ms_handsCount];
|
||||
m_elbowPositions = new Vector3[ms_handsCount];
|
||||
m_leftFingersBends = new float[ms_fingersCount];
|
||||
m_leftFingersSpreads = new float[ms_fingersCount];
|
||||
m_rightFingersBends = new float[ms_fingersCount];
|
||||
|
@ -61,6 +63,7 @@ namespace ml_lme
|
|||
p_data.m_handsPresenses[l_sideID] = true;
|
||||
FillHandPosition(l_hand, ref p_data.m_handsPositons[l_sideID]);
|
||||
FillHandRotation(l_hand, ref p_data.m_handsRotations[l_sideID]);
|
||||
FillElbowPosition(l_hand, ref p_data.m_elbowPositions[l_sideID]);
|
||||
switch(l_sideID)
|
||||
{
|
||||
case 0:
|
||||
|
@ -96,6 +99,13 @@ namespace ml_lme
|
|||
p_rot.w = p_hand.Rotation.w;
|
||||
}
|
||||
|
||||
static void FillElbowPosition(Leap.Hand p_hand, ref Vector3 p_pos)
|
||||
{
|
||||
p_pos.x = p_hand.Arm.ElbowPosition.x;
|
||||
p_pos.y = p_hand.Arm.ElbowPosition.y;
|
||||
p_pos.z = p_hand.Arm.ElbowPosition.z;
|
||||
}
|
||||
|
||||
static void FillFingerBends(Leap.Hand p_hand, ref float[] p_bends)
|
||||
{
|
||||
foreach(Leap.Finger l_finger in p_hand.Fingers)
|
||||
|
|
|
@ -1,66 +0,0 @@
|
|||
using UnityEngine;
|
||||
|
||||
namespace ml_lme
|
||||
{
|
||||
[DisallowMultipleComponent]
|
||||
class LeapIK : MonoBehaviour
|
||||
{
|
||||
bool m_enabled = true;
|
||||
bool m_fingersOnly = false;
|
||||
|
||||
Animator m_animator = null;
|
||||
Transform m_leftHand = null;
|
||||
Transform m_rightHand = null;
|
||||
|
||||
float m_leftHandWeight = 0f;
|
||||
float m_rightHandWeight = 0f;
|
||||
|
||||
bool m_leftHandVisible = false;
|
||||
bool m_rightHandVisible = false;
|
||||
|
||||
void Start()
|
||||
{
|
||||
m_animator = this.GetComponent<Animator>();
|
||||
}
|
||||
|
||||
void OnAnimatorIK()
|
||||
{
|
||||
if(m_enabled && !m_fingersOnly && (m_animator != null))
|
||||
{
|
||||
if(m_leftHand != null)
|
||||
{
|
||||
m_leftHandWeight = Mathf.Lerp(m_leftHandWeight, m_leftHandVisible ? 1f : 0f, 0.25f);
|
||||
m_animator.SetIKPositionWeight(AvatarIKGoal.LeftHand, m_leftHandWeight);
|
||||
m_animator.SetIKRotationWeight(AvatarIKGoal.LeftHand, m_leftHandWeight);
|
||||
m_animator.SetIKPosition(AvatarIKGoal.LeftHand, m_leftHand.position);
|
||||
m_animator.SetIKRotation(AvatarIKGoal.LeftHand, m_leftHand.rotation);
|
||||
}
|
||||
|
||||
if(m_rightHand != null)
|
||||
{
|
||||
m_rightHandWeight = Mathf.Lerp(m_rightHandWeight, m_rightHandVisible ? 1f : 0f, 0.25f);
|
||||
m_animator.SetIKPositionWeight(AvatarIKGoal.RightHand, m_rightHandWeight);
|
||||
m_animator.SetIKRotationWeight(AvatarIKGoal.RightHand, m_rightHandWeight);
|
||||
m_animator.SetIKPosition(AvatarIKGoal.RightHand, m_rightHand.position);
|
||||
m_animator.SetIKRotation(AvatarIKGoal.RightHand, m_rightHand.rotation);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void SetEnabled(bool p_state) => m_enabled = p_state;
|
||||
|
||||
public void SetFingersOnly(bool p_state) => m_fingersOnly = p_state;
|
||||
|
||||
public void SetHands(Transform p_left, Transform p_right)
|
||||
{
|
||||
m_leftHand = p_left;
|
||||
m_rightHand = p_right;
|
||||
}
|
||||
|
||||
public void SetHandsVisibility(bool p_left, bool p_right)
|
||||
{
|
||||
m_leftHandVisible = p_left;
|
||||
m_rightHandVisible = p_right;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -2,6 +2,7 @@
|
|||
using ABI_RC.Core.Savior;
|
||||
using ABI_RC.Systems.IK;
|
||||
using RootMotion.FinalIK;
|
||||
using System.Reflection;
|
||||
using UnityEngine;
|
||||
|
||||
namespace ml_lme
|
||||
|
@ -9,20 +10,28 @@ namespace ml_lme
|
|||
[DisallowMultipleComponent]
|
||||
class LeapTracked : MonoBehaviour
|
||||
{
|
||||
static readonly float[] ms_tposeMuscles = typeof(ABI_RC.Systems.IK.SubSystems.BodySystem).GetField("TPoseMuscles", BindingFlags.Static | BindingFlags.NonPublic).GetValue(null) as float[];
|
||||
static readonly Quaternion ms_offsetLeft = Quaternion.Euler(0f, 0f, 270f);
|
||||
static readonly Quaternion ms_offsetRight = Quaternion.Euler(0f, 0f, 90f);
|
||||
static readonly Quaternion ms_offsetLeftDesktop = Quaternion.Euler(0f, 90f, 0f);
|
||||
static readonly Quaternion ms_offsetRightDesktop = Quaternion.Euler(0f, 270f, 0f);
|
||||
|
||||
IndexIK m_indexIK = null;
|
||||
VRIK m_vrIK = null;
|
||||
Vector2 m_armsWeights = Vector2.zero;
|
||||
|
||||
bool m_enabled = true;
|
||||
bool m_fingersOnly = false;
|
||||
bool m_trackElbows = true;
|
||||
|
||||
LeapIK m_leapIK = null;
|
||||
ArmIK m_leftIK = null;
|
||||
ArmIK m_rightIK = null;
|
||||
Transform m_leftHand = null;
|
||||
Transform m_rightHand = null;
|
||||
Transform m_leftHandTarget = null;
|
||||
Transform m_rightHandTarget = null;
|
||||
Transform m_leftElbow = null;
|
||||
Transform m_rightElbow = null;
|
||||
bool m_leftTargetActive = false;
|
||||
bool m_rightTargetActive = false;
|
||||
|
||||
|
@ -56,8 +65,11 @@ namespace ml_lme
|
|||
CVRInputManager.Instance.individualFingerTracking = (m_enabled || Utils.AreKnucklesInUse());
|
||||
}
|
||||
|
||||
if(m_leapIK != null)
|
||||
m_leapIK.SetEnabled(m_enabled);
|
||||
if((m_leftIK != null) && (m_rightIK != null))
|
||||
{
|
||||
m_leftIK.enabled = (m_enabled && !m_fingersOnly);
|
||||
m_rightIK.enabled = (m_enabled && !m_fingersOnly);
|
||||
}
|
||||
|
||||
if(!m_enabled || m_fingersOnly)
|
||||
RestoreIK();
|
||||
|
@ -67,25 +79,55 @@ namespace ml_lme
|
|||
{
|
||||
m_fingersOnly = p_state;
|
||||
|
||||
if(m_leapIK != null)
|
||||
m_leapIK.SetFingersOnly(m_fingersOnly);
|
||||
if((m_leftIK != null) && (m_rightIK != null))
|
||||
{
|
||||
m_leftIK.enabled = (m_enabled && !m_fingersOnly);
|
||||
m_rightIK.enabled = (m_enabled && !m_fingersOnly);
|
||||
}
|
||||
|
||||
if(!m_enabled || m_fingersOnly)
|
||||
RestoreIK();
|
||||
}
|
||||
|
||||
public void SetHands(Transform p_left, Transform p_right)
|
||||
public void SetTrackElbows(bool p_state)
|
||||
{
|
||||
m_trackElbows = p_state;
|
||||
|
||||
if((m_leftIK != null) && (m_rightIK != null))
|
||||
{
|
||||
m_leftIK.solver.arm.bendGoalWeight = (m_trackElbows ? 1f : 0f);
|
||||
m_rightIK.solver.arm.bendGoalWeight = (m_trackElbows ? 1f : 0f);
|
||||
}
|
||||
|
||||
if(m_vrIK != null)
|
||||
{
|
||||
if(m_leftTargetActive)
|
||||
m_vrIK.solver.leftArm.bendGoalWeight = (m_trackElbows ? 1f : 0f);
|
||||
if(m_rightTargetActive)
|
||||
m_vrIK.solver.rightArm.bendGoalWeight = (m_trackElbows ? 1f : 0f);
|
||||
}
|
||||
}
|
||||
|
||||
public void SetTransforms(Transform p_left, Transform p_right, Transform p_leftElbow, Transform p_rightElbow)
|
||||
{
|
||||
m_leftHand = p_left;
|
||||
m_rightHand = p_right;
|
||||
|
||||
m_leftElbow = p_leftElbow;
|
||||
m_rightElbow = p_rightElbow;
|
||||
}
|
||||
|
||||
public void UpdateTracking(GestureMatcher.GesturesData p_gesturesData)
|
||||
{
|
||||
if(m_enabled && (m_indexIK != null))
|
||||
{
|
||||
if(m_leapIK != null)
|
||||
m_leapIK.SetHandsVisibility(p_gesturesData.m_handsPresenses[0], p_gesturesData.m_handsPresenses[1]);
|
||||
if((m_leftIK != null) && (m_rightIK != null))
|
||||
{
|
||||
m_leftIK.solver.IKPositionWeight = Mathf.Lerp(m_leftIK.solver.IKPositionWeight, (p_gesturesData.m_handsPresenses[0] && !m_fingersOnly) ? 1f : 0f, 0.25f);
|
||||
m_leftIK.solver.IKRotationWeight = Mathf.Lerp(m_leftIK.solver.IKRotationWeight, (p_gesturesData.m_handsPresenses[0] && !m_fingersOnly) ? 1f : 0f, 0.25f);
|
||||
m_rightIK.solver.IKPositionWeight = Mathf.Lerp(m_rightIK.solver.IKPositionWeight, (p_gesturesData.m_handsPresenses[1] && !m_fingersOnly) ? 1f : 0f, 0.25f);
|
||||
m_rightIK.solver.IKRotationWeight = Mathf.Lerp(m_rightIK.solver.IKPositionWeight, (p_gesturesData.m_handsPresenses[1] && !m_fingersOnly) ? 1f : 0f, 0.25f);
|
||||
}
|
||||
|
||||
if(p_gesturesData.m_handsPresenses[0])
|
||||
{
|
||||
|
@ -128,22 +170,30 @@ namespace ml_lme
|
|||
if(p_gesturesData.m_handsPresenses[0] && !m_leftTargetActive)
|
||||
{
|
||||
m_vrIK.solver.leftArm.target = m_leftHandTarget;
|
||||
m_vrIK.solver.leftArm.bendGoal = m_leftElbow;
|
||||
m_vrIK.solver.leftArm.bendGoalWeight = (m_trackElbows ? 1f : 0f);
|
||||
m_leftTargetActive = true;
|
||||
}
|
||||
if(!p_gesturesData.m_handsPresenses[0] && m_leftTargetActive)
|
||||
{
|
||||
m_vrIK.solver.leftArm.target = IKSystem.Instance.leftHandAnchor;
|
||||
m_vrIK.solver.leftArm.bendGoal = null;
|
||||
m_vrIK.solver.leftArm.bendGoalWeight = 0f;
|
||||
m_leftTargetActive = false;
|
||||
}
|
||||
|
||||
if(p_gesturesData.m_handsPresenses[1] && !m_rightTargetActive)
|
||||
{
|
||||
m_vrIK.solver.rightArm.target = m_rightHandTarget;
|
||||
m_vrIK.solver.rightArm.bendGoal = m_rightElbow;
|
||||
m_vrIK.solver.rightArm.bendGoalWeight = (m_trackElbows ? 1f : 0f);
|
||||
m_rightTargetActive = true;
|
||||
}
|
||||
if(!p_gesturesData.m_handsPresenses[1] && m_rightTargetActive)
|
||||
{
|
||||
m_vrIK.solver.rightArm.target = IKSystem.Instance.rightHandAnchor;
|
||||
m_vrIK.solver.rightArm.bendGoal = null;
|
||||
m_vrIK.solver.rightArm.bendGoalWeight = 0f;
|
||||
m_rightTargetActive = false;
|
||||
}
|
||||
}
|
||||
|
@ -152,8 +202,9 @@ namespace ml_lme
|
|||
|
||||
public void OnAvatarClear()
|
||||
{
|
||||
m_leapIK = null;
|
||||
m_vrIK = null;
|
||||
m_leftIK = null;
|
||||
m_rightIK = null;
|
||||
m_leftTargetActive = false;
|
||||
m_rightTargetActive = false;
|
||||
|
||||
|
@ -161,6 +212,8 @@ namespace ml_lme
|
|||
m_leftHandTarget.localRotation = Quaternion.identity;
|
||||
m_rightHandTarget.localPosition = Vector3.zero;
|
||||
m_rightHandTarget.localRotation = Quaternion.identity;
|
||||
|
||||
m_armsWeights.Set(0f, 0f);
|
||||
}
|
||||
|
||||
public void OnCalibrateAvatar()
|
||||
|
@ -176,24 +229,107 @@ namespace ml_lme
|
|||
|
||||
if(PlayerSetup.Instance._animator.isHuman)
|
||||
{
|
||||
HumanPoseHandler l_poseHandler = null;
|
||||
HumanPose l_initPose = new HumanPose();
|
||||
|
||||
// Force desktop non-VRIK avatar into T-Pose
|
||||
if(m_vrIK == null)
|
||||
{
|
||||
l_poseHandler = new HumanPoseHandler(PlayerSetup.Instance._animator.avatar, PlayerSetup.Instance._avatar.transform);
|
||||
l_poseHandler.GetHumanPose(ref l_initPose);
|
||||
|
||||
HumanPose l_tPose = new HumanPose();
|
||||
l_tPose.bodyPosition = l_initPose.bodyPosition;
|
||||
l_tPose.bodyRotation = l_initPose.bodyRotation;
|
||||
l_tPose.muscles = new float[l_initPose.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.LeftHand);
|
||||
if(l_hand != null)
|
||||
m_leftHandTarget.localRotation = ms_offsetLeft * (PlayerSetup.Instance._avatar.transform.GetMatrix().inverse * l_hand.GetMatrix()).rotation;
|
||||
m_leftHandTarget.localRotation = ((m_vrIK != null) ? ms_offsetLeft : ms_offsetLeftDesktop) * (PlayerSetup.Instance._avatar.transform.GetMatrix().inverse * l_hand.GetMatrix()).rotation;
|
||||
|
||||
l_hand = PlayerSetup.Instance._animator.GetBoneTransform(HumanBodyBones.RightHand);
|
||||
if(l_hand != null)
|
||||
m_rightHandTarget.localRotation = ms_offsetRight * (PlayerSetup.Instance._avatar.transform.GetMatrix().inverse * l_hand.GetMatrix()).rotation;
|
||||
m_rightHandTarget.localRotation = ((m_vrIK != null) ? ms_offsetRight : ms_offsetRightDesktop) * (PlayerSetup.Instance._avatar.transform.GetMatrix().inverse * l_hand.GetMatrix()).rotation;
|
||||
|
||||
if(m_vrIK == null)
|
||||
{
|
||||
m_leapIK = PlayerSetup.Instance._animator.gameObject.AddComponent<LeapIK>();
|
||||
m_leapIK.SetHands(m_leftHand, m_rightHand);
|
||||
m_leapIK.SetEnabled(m_enabled);
|
||||
m_leapIK.SetFingersOnly(m_fingersOnly);
|
||||
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_leftIK = PlayerSetup.Instance._avatar.AddComponent<ArmIK>();
|
||||
m_leftIK.solver.isLeft = true;
|
||||
m_leftIK.solver.SetChain(
|
||||
l_chest,
|
||||
PlayerSetup.Instance._animator.GetBoneTransform(HumanBodyBones.LeftShoulder),
|
||||
PlayerSetup.Instance._animator.GetBoneTransform(HumanBodyBones.LeftUpperArm),
|
||||
PlayerSetup.Instance._animator.GetBoneTransform(HumanBodyBones.LeftLowerArm),
|
||||
PlayerSetup.Instance._animator.GetBoneTransform(HumanBodyBones.LeftHand),
|
||||
PlayerSetup.Instance._animator.transform
|
||||
);
|
||||
m_leftIK.solver.arm.target = m_leftHandTarget;
|
||||
m_leftIK.solver.arm.bendGoal = m_leftElbow;
|
||||
m_leftIK.solver.arm.bendGoalWeight = (m_trackElbows ? 1f : 0f);
|
||||
m_leftIK.enabled = (m_enabled && !m_fingersOnly);
|
||||
|
||||
m_rightIK = PlayerSetup.Instance._avatar.AddComponent<ArmIK>();
|
||||
m_rightIK.solver.isLeft = false;
|
||||
m_rightIK.solver.SetChain(
|
||||
l_chest,
|
||||
PlayerSetup.Instance._animator.GetBoneTransform(HumanBodyBones.RightShoulder),
|
||||
PlayerSetup.Instance._animator.GetBoneTransform(HumanBodyBones.RightUpperArm),
|
||||
PlayerSetup.Instance._animator.GetBoneTransform(HumanBodyBones.RightLowerArm),
|
||||
PlayerSetup.Instance._animator.GetBoneTransform(HumanBodyBones.RightHand),
|
||||
PlayerSetup.Instance._animator.transform
|
||||
);
|
||||
m_rightIK.solver.arm.target = m_rightHandTarget;
|
||||
m_rightIK.solver.arm.bendGoal = m_rightElbow;
|
||||
m_rightIK.solver.arm.bendGoalWeight = (m_trackElbows ? 1f : 0f);
|
||||
m_rightIK.enabled = (m_enabled && !m_fingersOnly);
|
||||
|
||||
l_poseHandler.SetHumanPose(ref l_initPose);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_vrIK.onPreSolverUpdate.AddListener(this.OnIKPreUpdate);
|
||||
m_vrIK.onPostSolverUpdate.AddListener(this.OnIKPostUpdate);
|
||||
}
|
||||
|
||||
l_poseHandler?.Dispose();
|
||||
}
|
||||
}
|
||||
|
||||
void OnIKPreUpdate()
|
||||
{
|
||||
m_armsWeights.Set(m_vrIK.solver.leftArm.positionWeight, m_vrIK.solver.rightArm.positionWeight);
|
||||
|
||||
if(m_leftTargetActive && Mathf.Approximately(m_armsWeights.x, 0f))
|
||||
{
|
||||
m_vrIK.solver.leftArm.positionWeight = 1f;
|
||||
m_vrIK.solver.leftArm.rotationWeight = 1f;
|
||||
}
|
||||
if(m_rightTargetActive && Mathf.Approximately(m_armsWeights.y, 0f))
|
||||
{
|
||||
m_vrIK.solver.rightArm.positionWeight = 1f;
|
||||
m_vrIK.solver.rightArm.rotationWeight = 1f;
|
||||
}
|
||||
}
|
||||
void OnIKPostUpdate()
|
||||
{
|
||||
m_vrIK.solver.leftArm.positionWeight = m_armsWeights.x;
|
||||
m_vrIK.solver.leftArm.rotationWeight = m_armsWeights.x;
|
||||
|
||||
m_vrIK.solver.rightArm.positionWeight = m_armsWeights.y;
|
||||
m_vrIK.solver.rightArm.rotationWeight = m_armsWeights.y;
|
||||
}
|
||||
|
||||
void RestoreIK()
|
||||
{
|
||||
if(m_vrIK != null)
|
||||
|
@ -201,11 +337,15 @@ namespace ml_lme
|
|||
if(m_leftTargetActive)
|
||||
{
|
||||
m_vrIK.solver.leftArm.target = IKSystem.Instance.leftHandAnchor;
|
||||
m_vrIK.solver.leftArm.bendGoal = null;
|
||||
m_vrIK.solver.leftArm.bendGoalWeight = 0f;
|
||||
m_leftTargetActive = false;
|
||||
}
|
||||
if(m_rightTargetActive)
|
||||
{
|
||||
m_vrIK.solver.rightArm.target = IKSystem.Instance.rightHandAnchor;
|
||||
m_vrIK.solver.rightArm.bendGoal = null;
|
||||
m_vrIK.solver.rightArm.bendGoalWeight = 0f;
|
||||
m_rightTargetActive = false;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
using ABI_RC.Core.Player;
|
||||
using ABI_RC.Core.UI;
|
||||
using UnityEngine;
|
||||
using System.Reflection;
|
||||
using UnityEngine;
|
||||
|
||||
namespace ml_lme
|
||||
{
|
||||
|
@ -18,6 +18,7 @@ namespace ml_lme
|
|||
|
||||
GameObject m_leapTrackingRoot = null;
|
||||
GameObject[] m_leapHands = null;
|
||||
GameObject[] m_leapElbows = null;
|
||||
GameObject m_leapControllerModel = null;
|
||||
LeapTracked m_leapTracked = null;
|
||||
|
||||
|
@ -29,14 +30,15 @@ namespace ml_lme
|
|||
DependenciesHandler.ExtractDependencies();
|
||||
|
||||
Settings.Init();
|
||||
Settings.EnabledChange += this.OnSettingsEnableChange;
|
||||
Settings.DesktopOffsetChange += this.OnSettingsDesktopOffsetChange;
|
||||
Settings.FingersOnlyChange += this.OnSettingsFingersOptionChange;
|
||||
Settings.ModelVisibilityChange += this.OnSettingsModelVisibilityChange;
|
||||
Settings.TrackingModeChange += this.OnSettingsTrackingModeChange;
|
||||
Settings.RootAngleChange += this.OnSettingsRootAngleChange;
|
||||
Settings.HeadAttachChange += this.OnSettingsHeadAttachChange;
|
||||
Settings.HeadOffsetChange += this.OnSettingsHeadOffsetChange;
|
||||
Settings.EnabledChange += this.OnEnableChange;
|
||||
Settings.DesktopOffsetChange += this.OnDesktopOffsetChange;
|
||||
Settings.FingersOnlyChange += this.OnFingersOptionChange;
|
||||
Settings.ModelVisibilityChange += this.OnModelVisibilityChange;
|
||||
Settings.TrackingModeChange += this.OnTrackingModeChange;
|
||||
Settings.RootAngleChange += this.OnRootAngleChange;
|
||||
Settings.HeadAttachChange += this.OnHeadAttachChange;
|
||||
Settings.HeadOffsetChange += this.OnHeadOffsetChange;
|
||||
Settings.TrackElbowsChange += this.OnTrackElbowsChange;
|
||||
|
||||
m_leapController = new Leap.Controller();
|
||||
m_leapController.Device += this.OnLeapDeviceInitialized;
|
||||
|
@ -47,6 +49,7 @@ namespace ml_lme
|
|||
|
||||
m_gesturesData = new GestureMatcher.GesturesData();
|
||||
m_leapHands = new GameObject[GestureMatcher.GesturesData.ms_handsCount];
|
||||
m_leapElbows = new GameObject[GestureMatcher.GesturesData.ms_handsCount];
|
||||
|
||||
// Patches
|
||||
HarmonyInstance.Patch(
|
||||
|
@ -87,6 +90,11 @@ namespace ml_lme
|
|||
m_leapHands[i].transform.parent = m_leapTrackingRoot.transform;
|
||||
m_leapHands[i].transform.localPosition = Vector3.zero;
|
||||
m_leapHands[i].transform.localRotation = Quaternion.identity;
|
||||
|
||||
m_leapElbows[i] = new GameObject("LeapElbow" + i);
|
||||
m_leapElbows[i].transform.parent = m_leapTrackingRoot.transform;
|
||||
m_leapElbows[i].transform.localPosition = Vector3.zero;
|
||||
m_leapElbows[i].transform.localRotation = Quaternion.identity;
|
||||
}
|
||||
|
||||
m_leapControllerModel = AssetsHandler.GetAsset("assets/models/leapmotion/leap_motion_1_0.obj");
|
||||
|
@ -100,13 +108,14 @@ namespace ml_lme
|
|||
|
||||
// Player setup
|
||||
m_leapTracked = PlayerSetup.Instance.gameObject.AddComponent<LeapTracked>();
|
||||
m_leapTracked.SetHands(m_leapHands[0].transform, m_leapHands[1].transform);
|
||||
m_leapTracked.SetTransforms(m_leapHands[0].transform, m_leapHands[1].transform, m_leapElbows[0].transform, m_leapElbows[1].transform);
|
||||
m_leapTracked.SetTrackElbows(Settings.TrackElbows);
|
||||
|
||||
OnSettingsEnableChange(Settings.Enabled);
|
||||
OnSettingsFingersOptionChange(Settings.FingersOnly);
|
||||
OnSettingsModelVisibilityChange(Settings.ModelVisibility);
|
||||
OnSettingsTrackingModeChange(Settings.TrackingMode);
|
||||
OnSettingsHeadAttachChange(Settings.HeadAttach); // Includes offsets and parenting
|
||||
OnEnableChange(Settings.Enabled);
|
||||
OnFingersOptionChange(Settings.FingersOnly);
|
||||
OnModelVisibilityChange(Settings.ModelVisibility);
|
||||
OnTrackingModeChange(Settings.TrackingMode);
|
||||
OnHeadAttachChange(Settings.HeadAttach); // Includes offsets and parenting
|
||||
}
|
||||
|
||||
public override void OnUpdate()
|
||||
|
@ -132,6 +141,10 @@ namespace ml_lme
|
|||
ReorientateLeapToUnity(ref l_pos, ref l_rot, Settings.TrackingMode);
|
||||
m_leapHands[i].transform.localPosition = l_pos;
|
||||
m_leapHands[i].transform.localRotation = l_rot;
|
||||
|
||||
l_pos = m_gesturesData.m_elbowPositions[i];
|
||||
ReorientateLeapToUnity(ref l_pos, ref l_rot, Settings.TrackingMode);
|
||||
m_leapElbows[i].transform.localPosition = l_pos;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -143,7 +156,7 @@ namespace ml_lme
|
|||
}
|
||||
|
||||
// Settings changes
|
||||
void OnSettingsEnableChange(bool p_state)
|
||||
void OnEnableChange(bool p_state)
|
||||
{
|
||||
if(p_state)
|
||||
{
|
||||
|
@ -157,7 +170,7 @@ namespace ml_lme
|
|||
m_leapTracked.SetEnabled(p_state);
|
||||
}
|
||||
|
||||
void OnSettingsDesktopOffsetChange(Vector3 p_offset)
|
||||
void OnDesktopOffsetChange(Vector3 p_offset)
|
||||
{
|
||||
if((m_leapTrackingRoot != null) && !Settings.HeadAttach)
|
||||
{
|
||||
|
@ -168,19 +181,19 @@ namespace ml_lme
|
|||
}
|
||||
}
|
||||
|
||||
void OnSettingsFingersOptionChange(bool p_state)
|
||||
void OnFingersOptionChange(bool p_state)
|
||||
{
|
||||
if(m_leapTracked != null)
|
||||
m_leapTracked.SetFingersOnly(p_state);
|
||||
}
|
||||
|
||||
void OnSettingsModelVisibilityChange(bool p_state)
|
||||
void OnModelVisibilityChange(bool p_state)
|
||||
{
|
||||
if(m_leapControllerModel != null)
|
||||
m_leapControllerModel.SetActive(p_state);
|
||||
}
|
||||
|
||||
void OnSettingsTrackingModeChange(Settings.LeapTrackingMode p_mode)
|
||||
void OnTrackingModeChange(Settings.LeapTrackingMode p_mode)
|
||||
{
|
||||
if(Settings.Enabled)
|
||||
UpdateDeviceTrackingMode();
|
||||
|
@ -202,13 +215,13 @@ namespace ml_lme
|
|||
}
|
||||
}
|
||||
|
||||
void OnSettingsRootAngleChange(float p_angle)
|
||||
void OnRootAngleChange(float p_angle)
|
||||
{
|
||||
if(m_leapTrackingRoot != null)
|
||||
m_leapTrackingRoot.transform.localRotation = Quaternion.Euler(p_angle, 0f, 0f);
|
||||
}
|
||||
|
||||
void OnSettingsHeadAttachChange(bool p_state)
|
||||
void OnHeadAttachChange(bool p_state)
|
||||
{
|
||||
if(m_leapTrackingRoot != null)
|
||||
{
|
||||
|
@ -247,7 +260,7 @@ namespace ml_lme
|
|||
}
|
||||
}
|
||||
|
||||
void OnSettingsHeadOffsetChange(Vector3 p_offset)
|
||||
void OnHeadOffsetChange(Vector3 p_offset)
|
||||
{
|
||||
if((m_leapTrackingRoot != null) && Settings.HeadAttach)
|
||||
{
|
||||
|
@ -257,6 +270,12 @@ namespace ml_lme
|
|||
m_leapTrackingRoot.transform.localPosition = p_offset;
|
||||
}
|
||||
}
|
||||
|
||||
void OnTrackElbowsChange(bool p_state)
|
||||
{
|
||||
if(m_leapTracked != null)
|
||||
m_leapTracked.SetTrackElbows(p_state);
|
||||
}
|
||||
|
||||
// Internal utility
|
||||
void UpdateDeviceTrackingMode()
|
||||
|
@ -328,8 +347,7 @@ namespace ml_lme
|
|||
MelonLoader.MelonLogger.Error(e);
|
||||
}
|
||||
}
|
||||
|
||||
// Sneaky forced IndexIK calibration
|
||||
|
||||
static void OnCalibrateAvatar_Postfix() => ms_instance?.OnCalibrateAvatar();
|
||||
void OnCalibrateAvatar()
|
||||
{
|
||||
|
@ -338,7 +356,7 @@ namespace ml_lme
|
|||
if(m_leapTracked != null)
|
||||
m_leapTracked.OnCalibrateAvatar();
|
||||
|
||||
OnSettingsHeadAttachChange(Settings.HeadAttach);
|
||||
OnHeadAttachChange(Settings.HeadAttach);
|
||||
}
|
||||
catch(System.Exception e)
|
||||
{
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
using System.Reflection;
|
||||
|
||||
[assembly: AssemblyTitle("LeapMotionExtension")]
|
||||
[assembly: AssemblyVersion("1.2.2")]
|
||||
[assembly: AssemblyFileVersion("1.2.2")]
|
||||
[assembly: AssemblyVersion("1.2.3")]
|
||||
[assembly: AssemblyFileVersion("1.2.3")]
|
||||
|
||||
[assembly: MelonLoader.MelonInfo(typeof(ml_lme.LeapMotionExtension), "LeapMotionExtension", "1.2.2", "SDraw", "https://github.com/SDraw/ml_mods_cvr")]
|
||||
[assembly: MelonLoader.MelonInfo(typeof(ml_lme.LeapMotionExtension), "LeapMotionExtension", "1.2.3", "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)]
|
||||
|
|
|
@ -18,5 +18,6 @@ Available mod's settings in `Settings - Implementation - Leap Motion Tracking`:
|
|||
* **Attach to head:** attach hands transformation to head instead of body, disabled by default.
|
||||
* **Head offset X/Y/Z:** offset position for head attachment (`Attach to head` is **`true`**), (0, -30, 15) by default.
|
||||
* **Offset angle:** rotation around X axis, useful for neck mounts, 0 by default.
|
||||
* **Track elbows:** elbows tracking, works best in `Screentop` and `HMD` tracking modes, `true` by default.
|
||||
* **Fingers tracking only:** apply only fingers tracking, disabled by default.
|
||||
* **Model visibility:** show Leap Motion controller model, useful for tracking visualizing, disabled by default.
|
||||
|
|
|
@ -28,7 +28,8 @@ namespace ml_lme
|
|||
Head,
|
||||
HeadX,
|
||||
HeadY,
|
||||
HeadZ
|
||||
HeadZ,
|
||||
TrackElbows
|
||||
};
|
||||
|
||||
static bool ms_enabled = false;
|
||||
|
@ -39,6 +40,7 @@ namespace ml_lme
|
|||
static float ms_rootAngle = 0f;
|
||||
static bool ms_headAttach = false;
|
||||
static Vector3 ms_headOffset = new Vector3(0f, -0.3f, 0.15f);
|
||||
static bool ms_trackElbows = true;
|
||||
|
||||
static MelonLoader.MelonPreferences_Category ms_category = null;
|
||||
static List<MelonLoader.MelonPreferences_Entry> ms_entries = null;
|
||||
|
@ -51,6 +53,7 @@ namespace ml_lme
|
|||
static public event Action<float> RootAngleChange;
|
||||
static public event Action<bool> HeadAttachChange;
|
||||
static public event Action<Vector3> HeadOffsetChange;
|
||||
static public event Action<bool> TrackElbowsChange;
|
||||
|
||||
public static void Init()
|
||||
{
|
||||
|
@ -69,6 +72,7 @@ namespace ml_lme
|
|||
ms_entries.Add(ms_category.CreateEntry(ModSetting.HeadX.ToString(), 0));
|
||||
ms_entries.Add(ms_category.CreateEntry(ModSetting.HeadY.ToString(), -30));
|
||||
ms_entries.Add(ms_category.CreateEntry(ModSetting.HeadZ.ToString(), 15));
|
||||
ms_entries.Add(ms_category.CreateEntry(ModSetting.TrackElbows.ToString(), true));
|
||||
|
||||
Load();
|
||||
|
||||
|
@ -116,6 +120,7 @@ namespace ml_lme
|
|||
(int)ms_entries[(int)ModSetting.HeadY].BoxedValue,
|
||||
(int)ms_entries[(int)ModSetting.HeadZ].BoxedValue
|
||||
) * 0.01f;
|
||||
ms_trackElbows = (bool)ms_entries[(int)ModSetting.TrackElbows].BoxedValue;
|
||||
}
|
||||
|
||||
static void OnToggleUpdate(string p_name, string p_value)
|
||||
|
@ -151,6 +156,12 @@ namespace ml_lme
|
|||
HeadAttachChange?.Invoke(ms_headAttach);
|
||||
}
|
||||
break;
|
||||
|
||||
case ModSetting.TrackElbows:
|
||||
{
|
||||
ms_trackElbows = bool.Parse(p_value);
|
||||
TrackElbowsChange?.Invoke(ms_trackElbows);
|
||||
} break;
|
||||
}
|
||||
|
||||
ms_entries[(int)l_setting].BoxedValue = bool.Parse(p_value);
|
||||
|
@ -235,40 +246,37 @@ namespace ml_lme
|
|||
{
|
||||
get => ms_enabled;
|
||||
}
|
||||
|
||||
public static Vector3 DesktopOffset
|
||||
{
|
||||
get => ms_desktopOffset;
|
||||
}
|
||||
|
||||
public static bool FingersOnly
|
||||
{
|
||||
get => ms_fingersOnly;
|
||||
}
|
||||
|
||||
public static bool ModelVisibility
|
||||
{
|
||||
get => ms_modelVisibility;
|
||||
}
|
||||
|
||||
public static LeapTrackingMode TrackingMode
|
||||
{
|
||||
get => ms_trackingMode;
|
||||
}
|
||||
|
||||
public static float RootAngle
|
||||
{
|
||||
get => ms_rootAngle;
|
||||
}
|
||||
|
||||
public static bool HeadAttach
|
||||
{
|
||||
get => ms_headAttach;
|
||||
}
|
||||
|
||||
public static Vector3 HeadOffset
|
||||
{
|
||||
get => ms_headOffset;
|
||||
}
|
||||
public static bool TrackElbows
|
||||
{
|
||||
get => ms_trackElbows;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,7 +10,7 @@ namespace ml_lme
|
|||
|
||||
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);
|
||||
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 Swap<T>(ref T lhs, ref T rhs)
|
||||
|
|
|
@ -84,7 +84,6 @@
|
|||
<Compile Include="AssetsHandler.cs" />
|
||||
<Compile Include="DependenciesHandler.cs" />
|
||||
<Compile Include="GestureMatcher.cs" />
|
||||
<Compile Include="LeapIK.cs" />
|
||||
<Compile Include="LeapTracked.cs" />
|
||||
<Compile Include="Main.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
|
|
|
@ -350,6 +350,13 @@ function inp_dropdown_mod_lme(_obj, _callbackName) {
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<div class ="row-wrapper">
|
||||
<div class ="option-caption">Track elbows: </div>
|
||||
<div class ="option-input">
|
||||
<div id="TrackElbows" class ="inp_toggle no-scroll" data-current="true"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class ="row-wrapper">
|
||||
<div class ="option-caption">Fingers tracking only: </div>
|
||||
<div class ="option-input">
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue