Too many changes

This commit is contained in:
SDraw 2024-10-05 15:42:32 +03:00
parent 45557943c4
commit a22e5992d0
No known key found for this signature in database
GPG key ID: BB95B4DAB2BB8BB5
72 changed files with 1064 additions and 927 deletions

View file

@ -7,6 +7,8 @@ namespace ml_lme
{
static class AssetsHandler
{
readonly static string ms_namespace = typeof(AssetsHandler).Namespace;
static readonly List<string> ms_assets = new List<string>()
{
"leapmotion_controller.asset",
@ -19,13 +21,12 @@ namespace ml_lme
public static void Load()
{
Assembly l_assembly = Assembly.GetExecutingAssembly();
string l_assemblyName = l_assembly.GetName().Name;
foreach(string l_assetName in ms_assets)
{
try
{
Stream l_assetStream = l_assembly.GetManifestResourceStream(l_assemblyName + ".resources." + l_assetName);
Stream l_assetStream = l_assembly.GetManifestResourceStream(ms_namespace + ".resources." + l_assetName);
if(l_assetStream != null)
{
MemoryStream l_memorySteam = new MemoryStream((int)l_assetStream.Length);

View file

@ -8,6 +8,8 @@ namespace ml_lme
{
static class DependenciesHandler
{
readonly static string ms_namespace = typeof(DependenciesHandler).Namespace;
static readonly List<string> ms_libraries = new List<string>()
{
"LeapC.dll"
@ -16,11 +18,10 @@ namespace ml_lme
public static void ExtractDependencies()
{
Assembly l_assembly = Assembly.GetExecutingAssembly();
string l_assemblyName = l_assembly.GetName().Name;
foreach(string l_library in ms_libraries)
{
Stream l_libraryStream = l_assembly.GetManifestResourceStream(l_assemblyName + ".resources." + l_library);
Stream l_libraryStream = l_assembly.GetManifestResourceStream(ms_namespace + ".resources." + l_library);
if(!File.Exists(l_library))
{

View file

@ -123,107 +123,89 @@ namespace ml_lme
}
public Transform GetRoot() => m_root;
public Transform GetBone(HumanBodyBones p_bone)
public Transform GetLinkedBone(HumanBodyBones p_bone)
{
Transform l_result = null;
switch(p_bone)
{
case HumanBodyBones.LeftHand:
l_result = (m_left ? m_wrist : null);
break;
case HumanBodyBones.LeftThumbProximal:
l_result = (m_left ? m_fingersBones[(int)FingerBone.ThumbProximal] : null);
break;
case HumanBodyBones.LeftThumbIntermediate:
l_result = (m_left ? m_fingersBones[(int)FingerBone.ThumbIntermediate] : null);
break;
case HumanBodyBones.LeftThumbDistal:
l_result = (m_left ? m_fingersBones[(int)FingerBone.ThumbDistal] : null);
break;
case HumanBodyBones.LeftIndexProximal:
l_result = (m_left ? m_fingersBones[(int)FingerBone.IndexProximal] : null);
break;
case HumanBodyBones.LeftIndexIntermediate:
l_result = (m_left ? m_fingersBones[(int)FingerBone.IndexIntermediate] : null);
break;
case HumanBodyBones.LeftIndexDistal:
l_result = (m_left ? m_fingersBones[(int)FingerBone.IndexDistal] : null);
break;
case HumanBodyBones.LeftMiddleProximal:
l_result = (m_left ? m_fingersBones[(int)FingerBone.MiddleProximal] : null);
break;
case HumanBodyBones.LeftMiddleIntermediate:
l_result = (m_left ? m_fingersBones[(int)FingerBone.MiddleIntermediate] : null);
break;
case HumanBodyBones.LeftMiddleDistal:
l_result = (m_left ? m_fingersBones[(int)FingerBone.MiddleDistal] : null);
break;
case HumanBodyBones.LeftRingProximal:
l_result = (m_left ? m_fingersBones[(int)FingerBone.RingProximal] : null);
break;
case HumanBodyBones.LeftRingIntermediate:
l_result = (m_left ? m_fingersBones[(int)FingerBone.RingIntermediate] : null);
break;
case HumanBodyBones.LeftRingDistal:
l_result = (m_left ? m_fingersBones[(int)FingerBone.RingDistal] : null);
break;
case HumanBodyBones.LeftLittleProximal:
l_result = (m_left ? m_fingersBones[(int)FingerBone.PinkyProximal] : null);
break;
case HumanBodyBones.LeftLittleIntermediate:
l_result = (m_left ? m_fingersBones[(int)FingerBone.PinkyIntermediate] : null);
break;
case HumanBodyBones.LeftLittleDistal:
l_result = (m_left ? m_fingersBones[(int)FingerBone.PinkyDistal] : null);
case HumanBodyBones.RightHand:
l_result = m_wrist;
break;
case HumanBodyBones.RightHand:
l_result = (!m_left ? m_wrist : null);
break;
case HumanBodyBones.LeftThumbProximal:
case HumanBodyBones.RightThumbProximal:
l_result = (!m_left ? m_fingersBones[(int)FingerBone.ThumbProximal] : null);
l_result = m_fingersBones[(int)FingerBone.ThumbProximal];
break;
case HumanBodyBones.LeftThumbIntermediate:
case HumanBodyBones.RightThumbIntermediate:
l_result = (!m_left ? m_fingersBones[(int)FingerBone.ThumbIntermediate] : null);
l_result = m_fingersBones[(int)FingerBone.ThumbIntermediate];
break;
case HumanBodyBones.LeftThumbDistal:
case HumanBodyBones.RightThumbDistal:
l_result = (!m_left ? m_fingersBones[(int)FingerBone.ThumbDistal] : null);
l_result = m_fingersBones[(int)FingerBone.ThumbDistal];
break;
case HumanBodyBones.LeftIndexProximal:
case HumanBodyBones.RightIndexProximal:
l_result = (!m_left ? m_fingersBones[(int)FingerBone.IndexProximal] : null);
l_result = m_fingersBones[(int)FingerBone.IndexProximal];
break;
case HumanBodyBones.LeftIndexIntermediate:
case HumanBodyBones.RightIndexIntermediate:
l_result = (!m_left ? m_fingersBones[(int)FingerBone.IndexIntermediate] : null);
l_result = m_fingersBones[(int)FingerBone.IndexIntermediate];
break;
case HumanBodyBones.LeftIndexDistal:
case HumanBodyBones.RightIndexDistal:
l_result = (!m_left ? m_fingersBones[(int)FingerBone.IndexDistal] : null);
l_result = m_fingersBones[(int)FingerBone.IndexDistal];
break;
case HumanBodyBones.LeftMiddleProximal:
case HumanBodyBones.RightMiddleProximal:
l_result = (!m_left ? m_fingersBones[(int)FingerBone.MiddleProximal] : null);
l_result = m_fingersBones[(int)FingerBone.MiddleProximal];
break;
case HumanBodyBones.LeftMiddleIntermediate:
case HumanBodyBones.RightMiddleIntermediate:
l_result = (!m_left ? m_fingersBones[(int)FingerBone.MiddleIntermediate] : null);
l_result = m_fingersBones[(int)FingerBone.MiddleIntermediate];
break;
case HumanBodyBones.LeftMiddleDistal:
case HumanBodyBones.RightMiddleDistal:
l_result = (!m_left ? m_fingersBones[(int)FingerBone.MiddleDistal] : null);
l_result = m_fingersBones[(int)FingerBone.MiddleDistal];
break;
case HumanBodyBones.LeftRingProximal:
case HumanBodyBones.RightRingProximal:
l_result = (!m_left ? m_fingersBones[(int)FingerBone.RingProximal] : null);
l_result = m_fingersBones[(int)FingerBone.RingProximal];
break;
case HumanBodyBones.LeftRingIntermediate:
case HumanBodyBones.RightRingIntermediate:
l_result = (!m_left ? m_fingersBones[(int)FingerBone.RingIntermediate] : null);
l_result = m_fingersBones[(int)FingerBone.RingIntermediate];
break;
case HumanBodyBones.LeftRingDistal:
case HumanBodyBones.RightRingDistal:
l_result = (!m_left ? m_fingersBones[(int)FingerBone.RingDistal] : null);
l_result = m_fingersBones[(int)FingerBone.RingDistal];
break;
case HumanBodyBones.LeftLittleProximal:
case HumanBodyBones.RightLittleProximal:
l_result = (!m_left ? m_fingersBones[(int)FingerBone.PinkyProximal] : null);
l_result = m_fingersBones[(int)FingerBone.PinkyProximal];
break;
case HumanBodyBones.LeftLittleIntermediate:
case HumanBodyBones.RightLittleIntermediate:
l_result = (!m_left ? m_fingersBones[(int)FingerBone.PinkyIntermediate] : null);
l_result = m_fingersBones[(int)FingerBone.PinkyIntermediate];
break;
case HumanBodyBones.LeftLittleDistal:
case HumanBodyBones.RightLittleDistal:
l_result = (!m_left ? m_fingersBones[(int)FingerBone.PinkyDistal] : null);
l_result = m_fingersBones[(int)FingerBone.PinkyDistal];
break;
}
return l_result;
@ -234,5 +216,7 @@ namespace ml_lme
if(m_mesh != null)
m_mesh.SetActive(p_state);
}
public bool IsLeft() => m_left;
}
}

View file

@ -89,8 +89,7 @@ namespace ml_lme
MelonLoader.MelonCoroutines.Start(WaitForSettings());
MelonLoader.MelonCoroutines.Start(WaitForMaterial());
VRModeSwitchEvents.OnInitializeXR.AddListener(OnModeSwitch);
VRModeSwitchEvents.OnDeinitializeXR.AddListener(OnModeSwitch);
VRModeSwitchEvents.OnCompletedVRModeSwitch.AddListener(OnVRModeSwitch);
Settings.OnEnabledChanged.AddListener(this.OnEnableChanged);
Settings.OnInteractionChanged.AddListener(this.OnInteractionChanged);
@ -153,8 +152,7 @@ namespace ml_lme
m_lineRight = null;
MetaPort.Instance.settings.settingBoolChanged.RemoveListener(this.OnGameSettingBoolChange);
VRModeSwitchEvents.OnInitializeXR.RemoveListener(OnModeSwitch);
VRModeSwitchEvents.OnDeinitializeXR.RemoveListener(OnModeSwitch);
VRModeSwitchEvents.OnCompletedVRModeSwitch.RemoveListener(OnVRModeSwitch);
Settings.OnEnabledChanged.RemoveListener(this.OnEnableChanged);
Settings.OnInteractionChanged.RemoveListener(this.OnInteractionChanged);
@ -291,7 +289,7 @@ namespace ml_lme
m_handVisibleRight = false;
}
if(!ModSupporter.SkipFingersOverride() && (!m_inVR || !Utils.AreKnucklesInUse()))
if(!m_inVR || !Utils.AreKnucklesInUse())
SetGameFingersTracking(m_handVisibleRight || m_handVisibleLeft);
base.UpdateInput();
@ -384,7 +382,7 @@ namespace ml_lme
ResetGestures(false);
}
// Reset to default, FreedomFingers can go brrr, player should press funny controller button two times
// Reset to default
SetGameFingersTracking(m_inVR && Utils.AreKnucklesInUse() && !CVRInputManager._moduleXR.GestureToggleValue);
}
@ -450,23 +448,30 @@ namespace ml_lme
}
}
void OnModeSwitch()
void OnVRModeSwitch(bool p_state)
{
m_inVR = Utils.IsInVR();
base._inputManager.SetModuleAsLast(this);
if(m_handRayLeft != null)
try
{
m_handRayLeft.isDesktopRay = !m_inVR;
m_handRayLeft.SetVRActive(m_inVR);
}
if(m_handRayRight != null)
{
m_handRayRight.isDesktopRay = !m_inVR;
m_handRayRight.SetVRActive(m_inVR);
}
m_inVR = Utils.IsInVR();
base._inputManager.SetModuleAsLast(this);
OnEnableChanged(Settings.Enabled);
if(m_handRayLeft != null)
{
m_handRayLeft.isDesktopRay = !m_inVR;
m_handRayLeft.SetVRActive(m_inVR);
}
if(m_handRayRight != null)
{
m_handRayRight.isDesktopRay = !m_inVR;
m_handRayRight.SetVRActive(m_inVR);
}
OnEnableChanged(Settings.Enabled);
}
catch(System.Exception e)
{
MelonLoader.MelonLogger.Error(e);
}
}
// Arbitrary

View file

@ -19,9 +19,9 @@ namespace ml_lme
void Awake()
{
if((Instance != null) && (Instance != this))
if(Instance != null)
{
Object.DestroyImmediate(this);
DestroyImmediate(this);
return;
}
@ -44,8 +44,7 @@ namespace ml_lme
Settings.OnEnabledChanged.AddListener(this.OnEnableChanged);
Settings.OnTrackingModeChanged.AddListener(this.OnTrackingModeChanged);
m_leapTracking = new GameObject("[LeapTrackingRoot]").AddComponent<LeapTracking>();
m_leapTracking.transform.parent = this.transform;
m_leapTracking = this.gameObject.AddComponent<LeapTracking>();
OnEnableChanged(Settings.Enabled);
OnTrackingModeChanged(Settings.TrackingMode);
@ -102,7 +101,7 @@ namespace ml_lme
m_leapInput = new LeapInput();
CVRInputManager.Instance.AddInputModule(m_leapInput);
m_leapTracked = PlayerSetup.Instance.gameObject.AddComponent<LeapTracked>();
m_leapTracked = this.gameObject.AddComponent<LeapTracked>();
}
void Update()

View file

@ -77,18 +77,28 @@ namespace ml_lme
(HumanBodyBones.RightLittleIntermediate, false),
(HumanBodyBones.RightLittleDistal, false),
};
static readonly (HumanBodyBones, HumanBodyBones, bool)[] ms_rotationFixChains =
static readonly (HumanBodyBones, HumanBodyBones, bool)[] ms_fingersChains =
{
(HumanBodyBones.LeftThumbProximal,HumanBodyBones.LeftThumbIntermediate,true), (HumanBodyBones.LeftThumbIntermediate, HumanBodyBones.LeftThumbDistal,true),
(HumanBodyBones.LeftIndexProximal,HumanBodyBones.LeftIndexIntermediate,true), (HumanBodyBones.LeftIndexIntermediate, HumanBodyBones.LeftIndexDistal,true),
(HumanBodyBones.LeftMiddleProximal,HumanBodyBones.LeftMiddleIntermediate,true), (HumanBodyBones.LeftMiddleIntermediate, HumanBodyBones.LeftMiddleDistal,true),
(HumanBodyBones.LeftRingProximal,HumanBodyBones.LeftRingIntermediate,true), (HumanBodyBones.LeftRingIntermediate, HumanBodyBones.LeftRingDistal,true),
(HumanBodyBones.LeftLittleProximal,HumanBodyBones.LeftLittleIntermediate,true), (HumanBodyBones.LeftLittleIntermediate, HumanBodyBones.LeftLittleDistal,true),
(HumanBodyBones.RightThumbProximal,HumanBodyBones.RightThumbIntermediate,false), (HumanBodyBones.RightThumbIntermediate, HumanBodyBones.RightThumbDistal,false),
(HumanBodyBones.RightIndexProximal,HumanBodyBones.RightIndexIntermediate,false), (HumanBodyBones.RightIndexIntermediate, HumanBodyBones.RightIndexDistal,false),
(HumanBodyBones.RightMiddleProximal,HumanBodyBones.RightMiddleIntermediate,false), (HumanBodyBones.RightMiddleIntermediate, HumanBodyBones.RightMiddleDistal,false),
(HumanBodyBones.RightRingProximal,HumanBodyBones.RightRingIntermediate,false), (HumanBodyBones.RightRingIntermediate, HumanBodyBones.RightRingDistal,false),
(HumanBodyBones.RightLittleProximal,HumanBodyBones.RightLittleIntermediate,false), (HumanBodyBones.RightLittleIntermediate, HumanBodyBones.RightLittleDistal,false)
(HumanBodyBones.LeftThumbProximal,HumanBodyBones.LeftThumbIntermediate,true), (HumanBodyBones.LeftThumbIntermediate, HumanBodyBones.LeftThumbDistal,true), (HumanBodyBones.LeftThumbDistal,HumanBodyBones.LastBone,true),
(HumanBodyBones.LeftIndexProximal,HumanBodyBones.LeftIndexIntermediate,true), (HumanBodyBones.LeftIndexIntermediate, HumanBodyBones.LeftIndexDistal,true), (HumanBodyBones.LeftIndexDistal,HumanBodyBones.LastBone,true),
(HumanBodyBones.LeftMiddleProximal,HumanBodyBones.LeftMiddleIntermediate,true), (HumanBodyBones.LeftMiddleIntermediate, HumanBodyBones.LeftMiddleDistal,true), (HumanBodyBones.LeftMiddleDistal,HumanBodyBones.LastBone,true),
(HumanBodyBones.LeftRingProximal,HumanBodyBones.LeftRingIntermediate,true), (HumanBodyBones.LeftRingIntermediate, HumanBodyBones.LeftRingDistal,true), (HumanBodyBones.LeftRingDistal,HumanBodyBones.LastBone,true),
(HumanBodyBones.LeftLittleProximal,HumanBodyBones.LeftLittleIntermediate,true), (HumanBodyBones.LeftLittleIntermediate, HumanBodyBones.LeftLittleDistal,true), (HumanBodyBones.LeftLittleDistal,HumanBodyBones.LastBone,true),
(HumanBodyBones.RightThumbProximal,HumanBodyBones.RightThumbIntermediate,false), (HumanBodyBones.RightThumbIntermediate, HumanBodyBones.RightThumbDistal,false), (HumanBodyBones.RightThumbDistal,HumanBodyBones.LastBone,false),
(HumanBodyBones.RightIndexProximal,HumanBodyBones.RightIndexIntermediate,false), (HumanBodyBones.RightIndexIntermediate, HumanBodyBones.RightIndexDistal,false), (HumanBodyBones.RightIndexDistal,HumanBodyBones.LastBone,false),
(HumanBodyBones.RightMiddleProximal,HumanBodyBones.RightMiddleIntermediate,false), (HumanBodyBones.RightMiddleIntermediate, HumanBodyBones.RightMiddleDistal,false), (HumanBodyBones.RightMiddleDistal,HumanBodyBones.LastBone,false),
(HumanBodyBones.RightRingProximal,HumanBodyBones.RightRingIntermediate,false), (HumanBodyBones.RightRingIntermediate, HumanBodyBones.RightRingDistal,false), (HumanBodyBones.RightRingDistal,HumanBodyBones.LastBone,false),
(HumanBodyBones.RightLittleProximal,HumanBodyBones.RightLittleIntermediate,false), (HumanBodyBones.RightLittleIntermediate, HumanBodyBones.RightLittleDistal,false),(HumanBodyBones.RightLittleDistal,HumanBodyBones.LastBone,false),
};
static readonly Vector3[] ms_directions =
{
Vector3.forward,
Vector3.back,
Vector3.left,
Vector3.right,
Vector3.up,
Vector3.down,
};
public static readonly float[] ms_lastLeftFingerBones = new float[20];
@ -97,10 +107,6 @@ namespace ml_lme
VRIK m_vrIK = null;
Transform m_hips = null;
bool m_enabled = true;
bool m_fingersOnly = false;
bool m_trackElbows = true;
IKInfo m_vrIKInfo;
ArmIK m_leftArmIK = null;
ArmIK m_rightArmIK = null;
@ -135,12 +141,11 @@ namespace ml_lme
m_rightHandTarget.localPosition = Vector3.zero;
m_rightHandTarget.localRotation = Quaternion.identity;
OnEnabledChanged(Settings.Enabled);
OnFingersOnlyChanged(Settings.FingersOnly);
OnEnabledOrFingersOnlyChanged(Settings.Enabled || Settings.FingersOnly);
OnTrackElbowsChanged(Settings.TrackElbows);
Settings.OnEnabledChanged.AddListener(this.OnEnabledChanged);
Settings.OnFingersOnlyChanged.AddListener(this.OnFingersOnlyChanged);
Settings.OnEnabledChanged.AddListener(this.OnEnabledOrFingersOnlyChanged);
Settings.OnFingersOnlyChanged.AddListener(this.OnEnabledOrFingersOnlyChanged);
Settings.OnTrackElbowsChanged.AddListener(this.OnTrackElbowsChanged);
GameEvents.OnAvatarClear.AddListener(this.OnAvatarClear);
@ -165,8 +170,8 @@ namespace ml_lme
m_vrIK = null;
Settings.OnEnabledChanged.RemoveListener(this.OnEnabledChanged);
Settings.OnFingersOnlyChanged.RemoveListener(this.OnFingersOnlyChanged);
Settings.OnEnabledChanged.RemoveListener(this.OnEnabledOrFingersOnlyChanged);
Settings.OnFingersOnlyChanged.RemoveListener(this.OnEnabledOrFingersOnlyChanged);
Settings.OnTrackElbowsChanged.RemoveListener(this.OnTrackElbowsChanged);
GameEvents.OnAvatarClear.RemoveListener(this.OnAvatarClear);
@ -176,24 +181,24 @@ namespace ml_lme
void Update()
{
if(m_enabled)
if(Settings.Enabled)
{
LeapParser.LeapData l_data = LeapManager.Instance.GetLatestData();
if((m_leftArmIK != null) && (m_rightArmIK != null))
{
m_leftArmIK.solver.IKPositionWeight = Mathf.Lerp(m_leftArmIK.solver.IKPositionWeight, (l_data.m_leftHand.m_present && !m_fingersOnly) ? 1f : 0f, 0.25f);
m_leftArmIK.solver.IKRotationWeight = Mathf.Lerp(m_leftArmIK.solver.IKRotationWeight, (l_data.m_leftHand.m_present && !m_fingersOnly) ? 1f : 0f, 0.25f);
if(m_trackElbows)
m_leftArmIK.solver.arm.bendGoalWeight = Mathf.Lerp(m_leftArmIK.solver.arm.bendGoalWeight, (l_data.m_leftHand.m_present && !m_fingersOnly) ? 1f : 0f, 0.25f);
m_leftArmIK.solver.IKPositionWeight = Mathf.Lerp(m_leftArmIK.solver.IKPositionWeight, (l_data.m_leftHand.m_present && !Settings.FingersOnly) ? 1f : 0f, 0.25f);
m_leftArmIK.solver.IKRotationWeight = Mathf.Lerp(m_leftArmIK.solver.IKRotationWeight, (l_data.m_leftHand.m_present && !Settings.FingersOnly) ? 1f : 0f, 0.25f);
if(Settings.TrackElbows)
m_leftArmIK.solver.arm.bendGoalWeight = Mathf.Lerp(m_leftArmIK.solver.arm.bendGoalWeight, (l_data.m_leftHand.m_present && !Settings.FingersOnly) ? 1f : 0f, 0.25f);
m_rightArmIK.solver.IKPositionWeight = Mathf.Lerp(m_rightArmIK.solver.IKPositionWeight, (l_data.m_rightHand.m_present && !m_fingersOnly) ? 1f : 0f, 0.25f);
m_rightArmIK.solver.IKRotationWeight = Mathf.Lerp(m_rightArmIK.solver.IKRotationWeight, (l_data.m_rightHand.m_present && !m_fingersOnly) ? 1f : 0f, 0.25f);
if(m_trackElbows)
m_rightArmIK.solver.arm.bendGoalWeight = Mathf.Lerp(m_rightArmIK.solver.arm.bendGoalWeight, (l_data.m_rightHand.m_present && !m_fingersOnly) ? 1f : 0f, 0.25f);
m_rightArmIK.solver.IKPositionWeight = Mathf.Lerp(m_rightArmIK.solver.IKPositionWeight, (l_data.m_rightHand.m_present && !Settings.FingersOnly) ? 1f : 0f, 0.25f);
m_rightArmIK.solver.IKRotationWeight = Mathf.Lerp(m_rightArmIK.solver.IKRotationWeight, (l_data.m_rightHand.m_present && !Settings.FingersOnly) ? 1f : 0f, 0.25f);
if(Settings.TrackElbows)
m_rightArmIK.solver.arm.bendGoalWeight = Mathf.Lerp(m_rightArmIK.solver.arm.bendGoalWeight, (l_data.m_rightHand.m_present && !Settings.FingersOnly) ? 1f : 0f, 0.25f);
}
if((m_vrIK != null) && !m_fingersOnly)
if((m_vrIK != null) && !Settings.FingersOnly)
{
m_leftTargetActive = l_data.m_leftHand.m_present;
m_rightTargetActive = l_data.m_rightHand.m_present;
@ -203,7 +208,7 @@ namespace ml_lme
void LateUpdate()
{
if(m_enabled && (m_poseHandler != null))
if(Settings.Enabled && (m_poseHandler != null))
{
LeapParser.LeapData l_data = LeapManager.Instance.GetLatestData();
if(l_data.m_leftHand.m_present)
@ -276,24 +281,25 @@ namespace ml_lme
void OnAvatarSetup()
{
if(PlayerSetup.Instance._animator.isHuman)
Animator l_animator = PlayerSetup.Instance._animator;
if(l_animator.isHuman)
{
Utils.SetAvatarTPose();
m_poseHandler = new HumanPoseHandler(PlayerSetup.Instance._animator.avatar, PlayerSetup.Instance._animator.transform);
m_poseHandler = new HumanPoseHandler(l_animator.avatar, l_animator.transform);
m_poseHandler.GetHumanPose(ref m_pose);
m_hips = PlayerSetup.Instance._animator.GetBoneTransform(HumanBodyBones.Hips);
m_hips = l_animator.GetBoneTransform(HumanBodyBones.Hips);
m_leftHandOffset.m_source = PlayerSetup.Instance._animator.GetBoneTransform(HumanBodyBones.LeftHand);
m_leftHandTarget.localRotation = ms_offsetLeft * (Quaternion.Inverse(PlayerSetup.Instance._avatar.transform.rotation) * m_leftHandOffset.m_source.rotation);
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 = PlayerSetup.Instance._animator.GetBoneTransform(HumanBodyBones.RightHand);
m_rightHandTarget.localRotation = ms_offsetRight * (Quaternion.Inverse(PlayerSetup.Instance._avatar.transform.rotation) * m_rightHandOffset.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 = PlayerSetup.Instance._animator.GetComponent<VRIK>();
m_vrIK = l_animator.GetComponent<VRIK>();
if(m_vrIK != null)
{
m_vrIK.onPreSolverUpdate.AddListener(this.OnIKPreSolverUpdate);
@ -339,7 +345,7 @@ namespace ml_lme
m_vrIK.solver.leftArm.positionWeight = 1f;
m_vrIK.solver.leftArm.rotationWeight = 1f;
m_vrIK.solver.leftArm.bendGoal = LeapTracking.Instance.GetLeftElbow();
m_vrIK.solver.leftArm.bendGoalWeight = (m_trackElbows ? 1f : 0f);
m_vrIK.solver.leftArm.bendGoalWeight = (Settings.TrackElbows ? 1f : 0f);
}
if(m_rightTargetActive)
{
@ -353,7 +359,7 @@ namespace ml_lme
m_vrIK.solver.rightArm.positionWeight = 1f;
m_vrIK.solver.rightArm.rotationWeight = 1f;
m_vrIK.solver.rightArm.bendGoal = LeapTracking.Instance.GetRightElbow();
m_vrIK.solver.rightArm.bendGoalWeight = (m_trackElbows ? 1f : 0f);
m_vrIK.solver.rightArm.bendGoalWeight = (Settings.TrackElbows ? 1f : 0f);
}
}
void OnIKPostSolverUpdate()
@ -377,30 +383,18 @@ namespace ml_lme
}
// Settings
void OnEnabledChanged(bool p_state)
void OnEnabledOrFingersOnlyChanged(bool p_state)
{
m_enabled = p_state;
RefreshArmIK();
ResetTargetsStates();
}
void OnFingersOnlyChanged(bool p_state)
{
m_fingersOnly = p_state;
RefreshArmIK();
ResetTargetsStates();
}
void OnTrackElbowsChanged(bool p_state)
{
m_trackElbows = p_state;
if((m_leftArmIK != null) && (m_rightArmIK != null))
{
m_leftArmIK.solver.arm.bendGoalWeight = (m_trackElbows ? 1f : 0f);
m_rightArmIK.solver.arm.bendGoalWeight = (m_trackElbows ? 1f : 0f);
m_leftArmIK.solver.arm.bendGoalWeight = (p_state ? 1f : 0f);
m_rightArmIK.solver.arm.bendGoalWeight = (p_state ? 1f : 0f);
}
ResetTargetsStates();
@ -415,41 +409,42 @@ namespace ml_lme
void SetupArmIK()
{
Transform l_chest = PlayerSetup.Instance._animator.GetBoneTransform(HumanBodyBones.UpperChest);
Animator l_animator = PlayerSetup.Instance._animator;
Transform l_chest = l_animator.GetBoneTransform(HumanBodyBones.UpperChest);
if(l_chest == null)
l_chest = PlayerSetup.Instance._animator.GetBoneTransform(HumanBodyBones.Chest);
l_chest = l_animator.GetBoneTransform(HumanBodyBones.Chest);
if(l_chest == null)
l_chest = PlayerSetup.Instance._animator.GetBoneTransform(HumanBodyBones.Spine);
l_chest = l_animator.GetBoneTransform(HumanBodyBones.Spine);
m_leftArmIK = PlayerSetup.Instance._avatar.AddComponent<ArmIK>();
m_leftArmIK = l_animator.gameObject.AddComponent<ArmIK>();
m_leftArmIK.solver.isLeft = true;
m_leftArmIK.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
l_animator.GetBoneTransform(HumanBodyBones.LeftShoulder),
l_animator.GetBoneTransform(HumanBodyBones.LeftUpperArm),
l_animator.GetBoneTransform(HumanBodyBones.LeftLowerArm),
l_animator.GetBoneTransform(HumanBodyBones.LeftHand),
l_animator.transform
);
m_leftArmIK.solver.arm.target = m_leftHandTarget;
m_leftArmIK.solver.arm.bendGoal = LeapTracking.Instance.GetLeftElbow();
m_leftArmIK.solver.arm.bendGoalWeight = (m_trackElbows ? 1f : 0f);
m_leftArmIK.enabled = (m_enabled && !m_fingersOnly);
m_leftArmIK.solver.arm.bendGoalWeight = (Settings.TrackElbows ? 1f : 0f);
m_leftArmIK.enabled = (Settings.Enabled && !Settings.FingersOnly);
m_rightArmIK = PlayerSetup.Instance._avatar.AddComponent<ArmIK>();
m_rightArmIK = l_animator.gameObject.AddComponent<ArmIK>();
m_rightArmIK.solver.isLeft = false;
m_rightArmIK.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
l_animator.GetBoneTransform(HumanBodyBones.RightShoulder),
l_animator.GetBoneTransform(HumanBodyBones.RightUpperArm),
l_animator.GetBoneTransform(HumanBodyBones.RightLowerArm),
l_animator.GetBoneTransform(HumanBodyBones.RightHand),
l_animator.transform
);
m_rightArmIK.solver.arm.target = m_rightHandTarget;
m_rightArmIK.solver.arm.bendGoal = LeapTracking.Instance.GetRightElbow();
m_rightArmIK.solver.arm.bendGoalWeight = (m_trackElbows ? 1f : 0f);
m_rightArmIK.enabled = (m_enabled && !m_fingersOnly);
m_rightArmIK.solver.arm.bendGoalWeight = (Settings.TrackElbows ? 1f : 0f);
m_rightArmIK.enabled = (Settings.Enabled && !Settings.FingersOnly);
}
void RemoveArmIK()
@ -467,8 +462,8 @@ namespace ml_lme
{
if((m_leftArmIK != null) && (m_rightArmIK != null))
{
m_leftArmIK.enabled = (m_enabled && !m_fingersOnly);
m_rightArmIK.enabled = (m_enabled && !m_fingersOnly);
m_leftArmIK.enabled = (Settings.Enabled && !Settings.FingersOnly);
m_rightArmIK.enabled = (Settings.Enabled && !Settings.FingersOnly);
}
}
@ -476,42 +471,48 @@ namespace ml_lme
{
LeapTracking.Instance.Rebind(PlayerSetup.Instance.transform.rotation);
// Align rotations of leap fingers to avatar fingers
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
foreach(var l_tuple in ms_rotationFixChains)
foreach(var l_tuple in ms_fingersChains)
{
ReorientateTowards(
PlayerSetup.Instance._animator.GetBoneTransform(l_tuple.Item1),
PlayerSetup.Instance._animator.GetBoneTransform(l_tuple.Item2),
l_tuple.Item3 ? LeapTracking.Instance.GetLeftHand().GetBone(l_tuple.Item1) : LeapTracking.Instance.GetRightHand().GetBone(l_tuple.Item1),
l_tuple.Item3 ? LeapTracking.Instance.GetLeftHand().GetBone(l_tuple.Item2) : LeapTracking.Instance.GetRightHand().GetBone(l_tuple.Item2),
PlayerSetup.Instance.transform,
l_animator.GetBoneTransform(l_tuple.Item1),
(l_tuple.Item2 != HumanBodyBones.LastBone) ? l_animator.GetBoneTransform(l_tuple.Item2) : null,
l_tuple.Item3 ? l_leapLeft.GetLinkedBone(l_tuple.Item1) : l_leapRight.GetLinkedBone(l_tuple.Item1),
l_tuple.Item3 ? l_leapLeft.GetLinkedBone(l_tuple.Item2) : l_leapRight.GetLinkedBone(l_tuple.Item2),
PlaneType.OXZ
);
ReorientateTowards(
PlayerSetup.Instance._animator.GetBoneTransform(l_tuple.Item1),
PlayerSetup.Instance._animator.GetBoneTransform(l_tuple.Item2),
l_tuple.Item3 ? LeapTracking.Instance.GetLeftHand().GetBone(l_tuple.Item1) : LeapTracking.Instance.GetRightHand().GetBone(l_tuple.Item1),
l_tuple.Item3 ? LeapTracking.Instance.GetLeftHand().GetBone(l_tuple.Item2) : LeapTracking.Instance.GetRightHand().GetBone(l_tuple.Item2),
PlayerSetup.Instance.transform,
l_animator.GetBoneTransform(l_tuple.Item1),
(l_tuple.Item2 != HumanBodyBones.LastBone) ? l_animator.GetBoneTransform(l_tuple.Item2) : null,
l_tuple.Item3 ? l_leapLeft.GetLinkedBone(l_tuple.Item1) : l_leapRight.GetLinkedBone(l_tuple.Item1),
l_tuple.Item3 ? l_leapLeft.GetLinkedBone(l_tuple.Item2) : l_leapRight.GetLinkedBone(l_tuple.Item2),
PlaneType.OYX
);
}
// Bind
m_leftHandOffset.m_target = LeapTracking.Instance.GetLeftHand().GetBone(HumanBodyBones.LeftHand);
m_leftHandOffset.m_target = l_leapLeft.GetLinkedBone(HumanBodyBones.LeftHand);
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_target = LeapTracking.Instance.GetRightHand().GetBone(HumanBodyBones.RightHand);
m_rightHandOffset.m_target = l_leapRight.GetLinkedBone(HumanBodyBones.RightHand);
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;
foreach(var l_link in ms_fingers)
{
Transform l_transform = PlayerSetup.Instance._animator.GetBoneTransform(l_link.Item1);
Transform l_transform = l_animator.GetBoneTransform(l_link.Item1);
if(l_transform != null)
{
RotationOffset l_offset = new RotationOffset();
l_offset.m_target = l_transform;
l_offset.m_source = (l_link.Item2 ? LeapTracking.Instance.GetLeftHand().GetBone(l_link.Item1) : LeapTracking.Instance.GetRightHand().GetBone(l_link.Item1));
l_offset.m_source = (l_link.Item2 ? l_leapLeft.GetLinkedBone(l_link.Item1) : l_leapRight.GetLinkedBone(l_link.Item1));
l_offset.m_offset = Quaternion.Inverse(l_offset.m_source.rotation) * l_offset.m_target.rotation;
if(l_link.Item2)
@ -522,13 +523,13 @@ namespace ml_lme
}
}
void ReorientateTowards(Transform p_target, Transform p_targetEnd, Transform p_source, Transform p_sourceEnd, PlaneType p_plane)
static void ReorientateTowards(Transform root, Transform p_source, Transform p_sourceEnd, Transform p_target, Transform p_targetEnd, PlaneType p_plane)
{
if((p_target != null) && (p_targetEnd != null) && (p_source != null) && (p_sourceEnd != null))
if((root != null) && (p_target != null) && (p_source != null))
{
Quaternion l_playerInv = Quaternion.Inverse(PlayerSetup.Instance.transform.rotation);
Vector3 l_targetDir = l_playerInv * (p_targetEnd.position - p_target.position);
Vector3 l_sourceDir = l_playerInv * (p_sourceEnd.position - p_source.position);
Quaternion l_rootInv = Quaternion.Inverse(root.rotation);
Vector3 l_targetDir = l_rootInv * (((p_targetEnd != null) ? p_targetEnd.position : GuessEnd(p_target)) - p_target.position);
Vector3 l_sourceDir = l_rootInv * (((p_sourceEnd != null) ? p_sourceEnd.position : GuessEnd(p_source)) - p_source.position);
switch(p_plane)
{
case PlaneType.OXZ:
@ -561,9 +562,30 @@ namespace ml_lme
if(p_plane == PlaneType.OYX)
l_diff = Quaternion.Euler(0f, 0f, l_diff.eulerAngles.y);
Quaternion l_adjusted = l_diff * (l_playerInv * p_target.rotation);
p_target.rotation = PlayerSetup.Instance.transform.rotation * l_adjusted;
Quaternion l_adjusted = l_diff * (l_rootInv * p_target.rotation);
p_target.rotation = root.rotation * l_adjusted;
}
}
static Vector3 GuessEnd(Transform p_target)
{
Vector3 l_result = p_target.position;
if(p_target.parent != null)
{
float l_dot = -1f;
Vector3 l_axisDir = p_target.position - p_target.parent.position;
foreach(Vector3 l_dir in ms_directions)
{
Vector3 l_rotDir = p_target.rotation * l_dir;
float l_stepDot = Vector3.Dot(l_rotDir, l_axisDir);
if(l_stepDot >= l_dot)
{
l_dot = l_stepDot;
l_result = p_target.position + l_rotDir;
}
}
}
return l_result;
}
}
}

View file

@ -1,6 +1,4 @@
using ABI_RC.Core.Player;
using ABI_RC.Systems.VRModeSwitch;
using System.Collections;
using UnityEngine;
namespace ml_lme
@ -13,8 +11,8 @@ namespace ml_lme
static readonly Quaternion ms_hmdRotation = new Quaternion(0f, 0.7071068f, 0.7071068f, 0f);
static readonly Quaternion ms_screentopRotation = new Quaternion(0f, 0f, -1f, 0f);
bool m_inVR = false;
Transform m_root = null;
Transform m_offsetPoint = null;
GameObject m_leapHands = null;
LeapHand m_leapHandLeft = null;
LeapHand m_leapHandRight = null;
@ -22,26 +20,33 @@ namespace ml_lme
Transform m_leapElbowRight = null;
GameObject m_leapControllerModel = null;
float m_scaleRelation = 1f;
void Start()
{
if((Instance != null) && (Instance != this))
if(Instance != null)
{
Object.DestroyImmediate(this);
return;
}
Instance = this;
m_inVR = Utils.IsInVR();
m_root = new GameObject("Root").transform;
m_root.parent = this.transform;
m_root.localPosition = Vector3.zero;
m_root.localRotation = Quaternion.identity;
m_offsetPoint = new GameObject("OffsetPoint").transform;
m_offsetPoint.parent = m_root;
m_offsetPoint.localPosition = Vector3.zero;
m_offsetPoint.localRotation = Quaternion.identity;
m_leapElbowLeft = new GameObject("LeapElbowLeft").transform;
m_leapElbowLeft.parent = this.transform;
m_leapElbowLeft.parent = m_offsetPoint;
m_leapElbowLeft.localPosition = Vector3.zero;
m_leapElbowLeft.localRotation = Quaternion.identity;
m_leapElbowRight = new GameObject("LeapElbowRight").transform;
m_leapElbowRight.parent = this.transform;
m_leapElbowRight.parent = m_offsetPoint;
m_leapElbowRight.localPosition = Vector3.zero;
m_leapElbowRight.localRotation = Quaternion.identity;
@ -49,7 +54,7 @@ namespace ml_lme
if(m_leapControllerModel != null)
{
m_leapControllerModel.name = "LeapModel";
m_leapControllerModel.transform.parent = this.transform;
m_leapControllerModel.transform.parent = m_offsetPoint;
m_leapControllerModel.transform.localPosition = Vector3.zero;
m_leapControllerModel.transform.localRotation = Quaternion.identity;
}
@ -58,7 +63,7 @@ namespace ml_lme
if(m_leapHands != null)
{
m_leapHands.name = "LeapHands";
m_leapHands.transform.parent = this.transform;
m_leapHands.transform.parent = m_offsetPoint;
m_leapHands.transform.localPosition = Vector3.zero;
m_leapHands.transform.localRotation = Quaternion.identity;
@ -69,34 +74,21 @@ namespace ml_lme
OnModelVisibilityChanged(Settings.ModelVisibility);
OnVisualHandsChanged(Settings.VisualHands);
OnTrackingModeChanged(Settings.TrackingMode);
OnHeadAttachChanged(Settings.HeadAttach);
OnRootAngleChanged(Settings.RootAngle);
MelonLoader.MelonCoroutines.Start(WaitForLocalPlayer());
VRModeSwitchEvents.OnInitializeXR.AddListener(this.OnAvatarSetup);
VRModeSwitchEvents.OnDeinitializeXR.AddListener(this.OnAvatarSetup);
Settings.OnDesktopOffsetChanged.AddListener(this.OnDesktopOffsetChanged);
Settings.OnEnabledChanged.AddListener(this.OnEnabledChanged);
Settings.OnModelVisibilityChanged.AddListener(this.OnModelVisibilityChanged);
Settings.OnVisualHandsChanged.AddListener(this.OnVisualHandsChanged);
Settings.OnTrackingModeChanged.AddListener(this.OnTrackingModeChanged);
Settings.OnRootAngleChanged.AddListener(this.OnRootAngleChanged);
Settings.OnHeadAttachChanged.AddListener(this.OnHeadAttachChanged);
Settings.OnHeadOffsetChanged.AddListener(this.OnHeadOffsetChanged);
Settings.OnDesktopOffsetChanged.AddListener(this.OnDesktopOffsetChanged);
Settings.OnRootAngleChanged.AddListener(this.OnRootAngleChanged);
GameEvents.OnAvatarClear.AddListener(this.OnAvatarClear);
GameEvents.OnAvatarSetup.AddListener(this.OnAvatarSetup);
GameEvents.OnPlayspaceScale.AddListener(this.OnPlayspaceScale);
}
IEnumerator WaitForLocalPlayer()
{
while(PlayerSetup.Instance == null)
yield return null;
OnHeadAttachChanged(Settings.HeadAttach);
}
void OnDestroy()
{
if(Instance == this)
@ -120,19 +112,23 @@ namespace ml_lme
Object.Destroy(m_leapControllerModel);
m_leapControllerModel = null;
VRModeSwitchEvents.OnInitializeXR.RemoveListener(this.OnAvatarSetup);
VRModeSwitchEvents.OnDeinitializeXR.RemoveListener(this.OnAvatarSetup);
if(m_offsetPoint != null)
Destroy(m_offsetPoint.gameObject);
m_offsetPoint = null;
Settings.OnDesktopOffsetChanged.RemoveListener(this.OnDesktopOffsetChanged);
if(m_root != null)
Destroy(m_root.gameObject);
m_root = null;
Settings.OnEnabledChanged.RemoveListener(this.OnEnabledChanged);
Settings.OnModelVisibilityChanged.RemoveListener(this.OnModelVisibilityChanged);
Settings.OnVisualHandsChanged.RemoveListener(this.OnVisualHandsChanged);
Settings.OnTrackingModeChanged.RemoveListener(this.OnTrackingModeChanged);
Settings.OnRootAngleChanged.RemoveListener(this.OnRootAngleChanged);
Settings.OnHeadAttachChanged.RemoveListener(this.OnHeadAttachChanged);
Settings.OnHeadOffsetChanged.RemoveListener(this.OnHeadOffsetChanged);
Settings.OnDesktopOffsetChanged.RemoveListener(this.OnDesktopOffsetChanged);
Settings.OnRootAngleChanged.RemoveListener(this.OnRootAngleChanged);
GameEvents.OnAvatarClear.RemoveListener(this.OnAvatarClear);
GameEvents.OnAvatarSetup.RemoveListener(this.OnAvatarSetup);
GameEvents.OnPlayspaceScale.RemoveListener(this.OnPlayspaceScale);
}
@ -140,6 +136,10 @@ namespace ml_lme
{
if(Settings.Enabled)
{
Transform l_camera = PlayerSetup.Instance.GetActiveCamera().transform;
m_root.position = l_camera.position;
m_root.rotation = (Settings.HeadAttach ? l_camera.rotation : PlayerSetup.Instance.GetPlayerRotation());
LeapParser.LeapData l_data = LeapManager.Instance.GetLatestData();
if(l_data.m_leftHand.m_present)
@ -185,21 +185,22 @@ namespace ml_lme
}
// Settings
void OnDesktopOffsetChanged(Vector3 p_offset)
void OnEnabledChanged(bool p_state)
{
if(!Settings.HeadAttach)
this.transform.localPosition = p_offset * (!m_inVR ? m_scaleRelation : 1f);
OnModelVisibilityChanged(Settings.ModelVisibility);
OnVisualHandsChanged(Settings.VisualHands);
}
void OnModelVisibilityChanged(bool p_state)
{
m_leapControllerModel.SetActive(p_state);
if(m_leapControllerModel != null)
m_leapControllerModel.SetActive(Settings.Enabled && p_state);
}
void OnVisualHandsChanged(bool p_state)
{
m_leapHandLeft?.SetMeshActive(p_state);
m_leapHandRight?.SetMeshActive(p_state);
m_leapHandLeft?.SetMeshActive(Settings.Enabled && p_state);
m_leapHandRight?.SetMeshActive(Settings.Enabled && p_state);
}
void OnTrackingModeChanged(Settings.LeapTrackingMode p_mode)
@ -218,51 +219,42 @@ namespace ml_lme
}
}
void OnRootAngleChanged(Vector3 p_angle)
{
this.transform.localRotation = Quaternion.Euler(p_angle);
}
void OnHeadAttachChanged(bool p_state)
{
if(!m_inVR)
{
this.transform.parent = (p_state ? PlayerSetup.Instance.desktopCamera.transform : PlayerSetup.Instance.desktopCameraRig.transform);
this.transform.localPosition = (p_state ? Settings.HeadOffset : Settings.DesktopOffset) * m_scaleRelation;
}
else
{
this.transform.parent = (p_state ? PlayerSetup.Instance.vrCamera.transform : PlayerSetup.Instance.vrCameraRig.transform);
this.transform.localPosition = (p_state ? Settings.HeadOffset : Settings.DesktopOffset);
}
this.transform.localScale = Vector3.one * (!m_inVR ? m_scaleRelation : 1f);
this.transform.localRotation = Quaternion.Euler(Settings.RootAngle);
if(m_offsetPoint != null)
m_offsetPoint.localPosition = (p_state ? Settings.HeadOffset : Settings.DesktopOffset);
}
void OnHeadOffsetChanged(Vector3 p_offset)
{
if(Settings.HeadAttach)
this.transform.localPosition = p_offset * (!m_inVR ? m_scaleRelation : 1f);
if(Settings.HeadAttach && (m_offsetPoint != null))
m_offsetPoint.localPosition = p_offset;
}
void OnDesktopOffsetChanged(Vector3 p_offset)
{
if(!Settings.HeadAttach && (m_offsetPoint != null))
m_offsetPoint.localPosition = p_offset;
}
void OnRootAngleChanged(Vector3 p_angle)
{
if(m_offsetPoint != null)
m_offsetPoint.localRotation = Quaternion.Euler(p_angle);
}
// Game events
void OnAvatarClear()
{
m_scaleRelation = 1f;
OnHeadAttachChanged(Settings.HeadAttach);
}
void OnAvatarSetup()
{
m_inVR = Utils.IsInVR();
OnHeadAttachChanged(Settings.HeadAttach);
}
void OnPlayspaceScale(float p_relation)
{
m_scaleRelation = p_relation;
OnHeadAttachChanged(Settings.HeadAttach);
try
{
if(m_root != null)
m_root.localScale = Vector3.one * p_relation;
}
catch(System.Exception e)
{
MelonLoader.MelonLogger.Error(e);
}
}
// Utils

View file

@ -14,7 +14,6 @@ namespace ml_lme
Settings.Init();
AssetsHandler.Load();
GameEvents.Init(HarmonyInstance);
ModSupporter.Init();
MelonLoader.MelonCoroutines.Start(WaitForRootLogic());
}
@ -31,7 +30,7 @@ namespace ml_lme
while(ABI_RC.Core.RootLogic.Instance == null)
yield return null;
m_leapManager = new GameObject("LeapMotionManager").AddComponent<LeapManager>();
m_leapManager = new GameObject("[LeapMotionExtension]").AddComponent<LeapManager>();
}
}
}

View file

@ -1,33 +0,0 @@
using System.Collections;
using System.Linq;
namespace ml_lme
{
static class ModSupporter
{
static bool ms_copycatMod = false;
public static void Init()
{
if(MelonLoader.MelonMod.RegisteredMelons.FirstOrDefault(m => m.Info.Name == "PlayerMovementCopycat") != null)
MelonLoader.MelonCoroutines.Start(WaitForCopycatInstance());
}
// PlayerMovementCopycat support
static IEnumerator WaitForCopycatInstance()
{
while(ml_pmc.PoseCopycat.Instance == null)
yield return null;
ms_copycatMod = true;
}
static bool IsCopycating() => (ml_pmc.PoseCopycat.Instance.IsActive() && ml_pmc.PoseCopycat.Instance.IsFingerTrackingActive());
public static bool SkipFingersOverride()
{
bool l_result = false;
l_result |= (ms_copycatMod && IsCopycating());
return l_result;
}
}
}

View file

@ -1,4 +1,4 @@
[assembly: MelonLoader.MelonInfo(typeof(ml_lme.LeapMotionExtension), "LeapMotionExtension", "1.5.2", "SDraw", "https://github.com/SDraw/ml_mods_cvr")]
[assembly: MelonLoader.MelonInfo(typeof(ml_lme.LeapMotionExtension), "LeapMotionExtension", "1.6.0", "SDraw", "https://github.com/SDraw/ml_mods_cvr")]
[assembly: MelonLoader.MelonGame(null, "ChilloutVR")]
[assembly: MelonLoader.MelonOptionalDependencies("ml_pmc")]
[assembly: MelonLoader.MelonPlatform(MelonLoader.MelonPlatformAttribute.CompatiblePlatforms.WINDOWS_X64)]

View file

@ -1,13 +1,13 @@
# Leap Motion Extension
This mod allows you to use your Leap Motion controller for hands and fingers tracking.
[![](.github/img_01.png)](https://youtu.be/nak1C8uibgc)
![](.github/img_01.png)
# Installation
* Install [latest Ultraleap Gemini tracking software](https://developer.leapmotion.com/tracking-software-download)
* Install [latest MelonLoader](https://github.com/LavaGang/MelonLoader)
* Get [latest release DLL](../../../releases/latest):
* Put `ml_lme.dll` in `Mods` folder of game
* Put `LeapMotionExtension.dll` in `Mods` folder of game
# Usage
## Settings
@ -26,4 +26,4 @@ Available mod's settings in `Settings - Implementation - Leap Motion Tracking`:
* **Interact gesture threadhold:** activation limit for interaction based on hand gesture; 80 by default.
* **Grip gesture threadhold:** activation limit for grip based on hand gesture; 40 by default.
* **Filter humanoid limits:** Limits fingers rotations to be valid for Unity's Mechanim; `true` by default
* Note: Enabling this option ensures that visual representation of your fingers will be same for you and remote players, but it cancels out additional finger segments rotations that can be better visually in most cases.
* Note: Enabling this option ensures that visual representation of your fingers will be same for you and remote players, but it cancels out additional finger segments rotations that can be better visually in some cases.

View file

@ -6,15 +6,16 @@ namespace ml_lme
{
static class ResourcesHandler
{
readonly static string ms_namespace = typeof(ResourcesHandler).Namespace;
public static string GetEmbeddedResource(string p_name)
{
string l_result = "";
Assembly l_assembly = Assembly.GetExecutingAssembly();
string l_assemblyName = l_assembly.GetName().Name;
try
{
Stream l_libraryStream = l_assembly.GetManifestResourceStream(l_assemblyName + ".resources." + p_name);
Stream l_libraryStream = l_assembly.GetManifestResourceStream(ms_namespace + ".resources." + p_name);
StreamReader l_streadReader = new StreamReader(l_libraryStream);
l_result = l_streadReader.ReadToEnd();
}

View file

@ -31,9 +31,9 @@ namespace ml_lme
if(CohtmlHud.Instance != null)
{
if(p_immediate)
CohtmlHud.Instance.ViewDropTextImmediate(p_title, p_message, p_small);
CohtmlHud.Instance.ViewDropTextImmediate(p_title, p_message, p_small, "", false);
else
CohtmlHud.Instance.ViewDropText(p_title, p_message, p_small);
CohtmlHud.Instance.ViewDropText(p_title, p_message, p_small, "", false);
}
}

View file

@ -4,10 +4,11 @@
<TargetFramework>netstandard2.1</TargetFramework>
<Platforms>x64</Platforms>
<PackageId>LeapMotionExtension</PackageId>
<Version>1.5.2</Version>
<Version>1.6.0</Version>
<Authors>SDraw</Authors>
<Company>None</Company>
<Company>SDraw</Company>
<Product>LeapMotionExtension</Product>
<AssemblyName>LeapMotionExtension</AssemblyName>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
@ -68,11 +69,6 @@
<Private>false</Private>
<SpecificVersion>false</SpecificVersion>
</Reference>
<Reference Include="ml_pmc">
<HintPath>D:\games\Steam\steamapps\common\ChilloutVR\Mods\ml_pmc.dll</HintPath>
<Private>false</Private>
<SpecificVersion>false</SpecificVersion>
</Reference>
<Reference Include="UnityEngine">
<HintPath>D:\games\Steam\steamapps\common\ChilloutVR\ChilloutVR_Data\Managed\UnityEngine.dll</HintPath>
<Private>false</Private>