Source upload

This commit is contained in:
SDraw 2022-03-21 12:29:49 +00:00 committed by SDraw
parent 50162481eb
commit 51ad6da4c3
No known key found for this signature in database
GPG key ID: BB95B4DAB2BB8BB5
51 changed files with 14957 additions and 0 deletions

21
LICENSE.txt Normal file
View file

@ -0,0 +1,21 @@
MIT License
Copyright (c) 2022 SDraw
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

1
README.md Normal file
View file

@ -0,0 +1 @@
404: Not Found

View file

@ -0,0 +1,76 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Reflection;
using System.Security.Cryptography;
namespace ml_lme_cvr
{
static class DependenciesHandler
{
static readonly List<string> ms_libraries = new List<string>()
{
"LeapC.dll"
};
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 + "." + l_library);
if(!File.Exists(l_library))
{
try
{
Stream l_fileStream = File.Create(l_library);
l_libraryStream.CopyTo(l_fileStream);
l_fileStream.Flush();
l_fileStream.Close();
}
catch(Exception)
{
MelonLoader.MelonLogger.Error("Unable to extract embedded " + l_library + " library");
}
}
else
{
try
{
FileStream l_fileStream = File.Open(l_library, FileMode.Open, FileAccess.ReadWrite, FileShare.None);
SHA256 l_hasher = SHA256.Create();
byte[] l_libraryHash = l_hasher.ComputeHash(l_libraryStream);
byte[] l_fileHash = l_hasher.ComputeHash(l_fileStream);
for(int i = 0; i < l_libraryHash.Length; i++)
{
if(l_libraryHash[i] != l_fileHash[i])
{
l_fileStream.SetLength(l_libraryStream.Length);
l_fileStream.Position = 0;
l_libraryStream.Position = 0;
l_libraryStream.CopyTo(l_fileStream);
l_fileStream.Flush();
MelonLoader.MelonLogger.Msg("Updated " + l_library + " library from embedded one");
break;
}
}
l_fileStream.Close();
}
catch(Exception)
{
MelonLoader.MelonLogger.Error("Unable to compare/update " + l_library + " library, delete it from game folder manually and restart.");
}
}
l_libraryStream.Close();
}
}
}
}

View file

@ -0,0 +1,203 @@
using UnityEngine;
namespace ml_lme_cvr
{
static class GestureMatcher
{
readonly static Vector2[] ms_fingerLimits =
{
new Vector2(0f, 15f),
new Vector2(-20f, 20f),
new Vector2(-50f, 50f),
new Vector2(-7.5f, 7.5f),
new Vector2(-20f, 20f)
};
public class GesturesData
{
readonly public static int ms_handsCount = 2;
readonly public static int ms_fingersCount = 5;
public bool[] m_handsPresenses = null;
public Vector3[] m_handsPositons = null;
public Quaternion[] m_handsRotations = null;
public float[] m_leftFingersBends = null;
public float[] m_leftFingersSpreads = null;
public float[] m_rightFingersBends = null;
public float[] m_rightFingersSpreads = null;
public GesturesData()
{
m_handsPresenses = new bool[ms_handsCount];
m_handsPositons = new Vector3[ms_handsCount];
m_handsRotations = new Quaternion[ms_handsCount];
m_leftFingersBends = new float[ms_fingersCount];
m_leftFingersSpreads = new float[ms_fingersCount];
m_rightFingersBends = new float[ms_fingersCount];
m_rightFingersSpreads = new float[ms_fingersCount];
}
}
public static void GetGestures(Leap.Frame p_frame, ref GesturesData p_data)
{
// Fill as default
for(int i = 0; i < GesturesData.ms_handsCount; i++)
p_data.m_handsPresenses[i] = false;
for(int i = 0; i < GesturesData.ms_fingersCount; i++)
{
p_data.m_leftFingersBends[i] = 0f;
p_data.m_leftFingersSpreads[i] = 0f;
p_data.m_rightFingersBends[i] = 0f;
p_data.m_leftFingersSpreads[i] = 0f;
}
// Fill hands data
foreach(Leap.Hand l_hand in p_frame.Hands)
{
int l_sideID = (l_hand.IsLeft ? 0 : 1);
if(!p_data.m_handsPresenses[l_sideID])
{
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]);
switch(l_sideID)
{
case 0:
{
FillFingerBends(l_hand, ref p_data.m_leftFingersBends);
FilFingerSpreads(l_hand, ref p_data.m_leftFingersSpreads);
}
break;
case 1:
{
FillFingerBends(l_hand, ref p_data.m_rightFingersBends);
FilFingerSpreads(l_hand, ref p_data.m_rightFingersSpreads);
}
break;
}
}
}
}
static void FillHandPosition(Leap.Hand p_hand, ref Vector3 p_pos)
{
p_pos.x = p_hand.PalmPosition.x;
p_pos.y = p_hand.PalmPosition.y;
p_pos.z = p_hand.PalmPosition.z;
}
static void FillHandRotation(Leap.Hand p_hand, ref Quaternion p_rot)
{
p_rot.x = p_hand.Rotation.x;
p_rot.y = p_hand.Rotation.y;
p_rot.z = p_hand.Rotation.z;
p_rot.w = p_hand.Rotation.w;
}
static void FillFingerBends(Leap.Hand p_hand, ref float[] p_bends)
{
foreach(Leap.Finger l_finger in p_hand.Fingers)
{
Quaternion l_prevSegment = Quaternion.identity;
float l_angle = 0f;
foreach(Leap.Bone l_bone in l_finger.bones)
{
if(l_bone.Type == Leap.Bone.BoneType.TYPE_METACARPAL)
{
l_prevSegment = new Quaternion(l_bone.Rotation.x, l_bone.Rotation.y, l_bone.Rotation.z, l_bone.Rotation.w);
continue;
}
Quaternion l_curSegment = new Quaternion(l_bone.Rotation.x, l_bone.Rotation.y, l_bone.Rotation.z, l_bone.Rotation.w);
Quaternion l_diff = Quaternion.Inverse(l_prevSegment) * l_curSegment;
l_prevSegment = l_curSegment;
// Bend - local X rotation
float l_curAngle = 360f - l_diff.eulerAngles.x;
if(l_curAngle > 180f)
l_curAngle -= 360f;
l_angle += l_curAngle;
}
p_bends[(int)l_finger.Type] = Mathf.InverseLerp(0f, (l_finger.Type == Leap.Finger.FingerType.TYPE_THUMB) ? 90f : 180f, l_angle);
}
}
static void FilFingerSpreads(Leap.Hand p_hand, ref float[] p_spreads)
{
foreach(Leap.Finger l_finger in p_hand.Fingers)
{
float l_angle = 0f;
Leap.Bone l_parent = l_finger.Bone(Leap.Bone.BoneType.TYPE_METACARPAL);
Leap.Bone l_child = l_finger.Bone(Leap.Bone.BoneType.TYPE_PROXIMAL);
Quaternion l_parentRot = new Quaternion(l_parent.Rotation.x, l_parent.Rotation.y, l_parent.Rotation.z, l_parent.Rotation.w);
Quaternion l_childRot = new Quaternion(l_child.Rotation.x, l_child.Rotation.y, l_child.Rotation.z, l_child.Rotation.w);
Quaternion l_diff = Quaternion.Inverse(l_parentRot) * l_childRot;
// Spread - local Y rotation, but thumb is obnoxious
l_angle = l_diff.eulerAngles.y;
if(l_angle > 180f)
l_angle -= 360f;
// Pain
switch(l_finger.Type)
{
case Leap.Finger.FingerType.TYPE_THUMB:
{
if(p_hand.IsRight)
l_angle *= -1f;
l_angle += ms_fingerLimits[(int)Leap.Finger.FingerType.TYPE_INDEX].y * 2f;
l_angle *= 0.5f;
}
break;
case Leap.Finger.FingerType.TYPE_INDEX:
{
if(p_hand.IsLeft)
l_angle *= -1f;
l_angle += ms_fingerLimits[(int)Leap.Finger.FingerType.TYPE_INDEX].y;
l_angle *= 0.5f;
}
break;
case Leap.Finger.FingerType.TYPE_MIDDLE:
{
l_angle += (ms_fingerLimits[(int)Leap.Finger.FingerType.TYPE_MIDDLE].y * (p_hand.IsRight ? 0.125f : -0.125f));
l_angle *= (p_hand.IsLeft ? -4f : 4f);
}
break;
case Leap.Finger.FingerType.TYPE_RING:
{
if(p_hand.IsRight)
l_angle *= -1f;
l_angle += ms_fingerLimits[(int)Leap.Finger.FingerType.TYPE_RING].y;
l_angle *= 0.5f;
}
break;
case Leap.Finger.FingerType.TYPE_PINKY:
{
l_angle += (p_hand.IsRight ? ms_fingerLimits[(int)Leap.Finger.FingerType.TYPE_PINKY].x : ms_fingerLimits[(int)Leap.Finger.FingerType.TYPE_PINKY].y);
l_angle *= (p_hand.IsRight ? -0.5f : 0.5f);
}
break;
}
p_spreads[(int)l_finger.Type] = Mathf.InverseLerp(ms_fingerLimits[(int)l_finger.Type].x, ms_fingerLimits[(int)l_finger.Type].y, l_angle);
if(l_finger.Type != Leap.Finger.FingerType.TYPE_THUMB)
{
p_spreads[(int)l_finger.Type] *= 2f;
p_spreads[(int)l_finger.Type] -= 1f;
}
}
}
}
}

53
ml_lme_cvr/LeapIK.cs Normal file
View file

@ -0,0 +1,53 @@
using UnityEngine;
namespace ml_lme_cvr
{
[RequireComponent(typeof(Animator))]
[DisallowMultipleComponent]
public class LeapIK : MonoBehaviour
{
bool m_enabled = true;
bool m_fingersOnly = false;
Animator m_animator = null;
Transform m_leftHand = null;
Transform m_rightHand = null;
void Start()
{
m_animator = this.GetComponent<Animator>();
}
void OnAnimatorIK()
{
if(m_enabled && !m_fingersOnly && (m_animator != null))
{
if(m_leftHand != null)
{
m_animator.SetIKPositionWeight(AvatarIKGoal.LeftHand, 1f);
m_animator.SetIKRotationWeight(AvatarIKGoal.LeftHand, 1f);
m_animator.SetIKPosition(AvatarIKGoal.LeftHand, m_leftHand.position);
m_animator.SetIKRotation(AvatarIKGoal.LeftHand, m_leftHand.rotation);
}
if(m_rightHand != null)
{
m_animator.SetIKPositionWeight(AvatarIKGoal.RightHand, 1f);
m_animator.SetIKRotationWeight(AvatarIKGoal.RightHand, 1f);
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;
}
}
}

141
ml_lme_cvr/LeapTracked.cs Normal file
View file

@ -0,0 +1,141 @@
using UnityEngine;
namespace ml_lme_cvr
{
[RequireComponent(typeof(ABI_RC.Core.Player.IndexIK))]
[DisallowMultipleComponent]
class LeapTracked : MonoBehaviour
{
bool m_enabled = true;
bool m_fingersOnly = false;
bool m_calibrated = false;
Animator m_animator = null;
ABI_RC.Core.Player.IndexIK m_indexIK = null;
LeapIK m_leapIK = null;
Transform m_leftHand = null;
Transform m_rightHand = null;
void Start()
{
m_indexIK = this.GetComponent<ABI_RC.Core.Player.IndexIK>();
if((m_indexIK != null) && (m_animator != null))
{
m_indexIK.avatarAnimator = m_animator;
m_indexIK.Recalibrate();
m_indexIK.activeControl = m_enabled;
ABI_RC.Core.Savior.CVRInputManager.Instance.individualFingerTracking = m_enabled;
m_calibrated = true;
}
}
public void SetEnabled(bool p_state)
{
m_enabled = p_state;
if(m_enabled)
{
if((m_animator != null) && (m_indexIK != null))
{
m_indexIK.activeControl = true;
if(!m_calibrated)
{
m_indexIK.avatarAnimator = m_animator;
m_indexIK.Recalibrate();
m_calibrated = true;
}
ABI_RC.Core.Savior.CVRInputManager.Instance.individualFingerTracking = true;
}
}
else
{
if((m_indexIK != null) && m_calibrated)
{
m_indexIK.activeControl = false;
ABI_RC.Core.Savior.CVRInputManager.Instance.individualFingerTracking = false;
}
}
if(m_leapIK != null)
m_leapIK.SetEnabled(m_enabled);
}
public void SetAnimator(Animator p_animator)
{
m_animator = p_animator;
m_leapIK = m_animator.gameObject.AddComponent<LeapIK>();
m_leapIK.SetEnabled(m_enabled);
m_leapIK.SetFingersOnly(m_fingersOnly);
m_leapIK.SetHands(m_leftHand, m_rightHand);
}
public void SetFingersOnly(bool p_state)
{
m_fingersOnly = p_state;
if(m_leapIK != null)
m_leapIK.SetFingersOnly(m_fingersOnly);
}
public void SetHands(Transform p_left, Transform p_right)
{
m_leftHand = p_left;
m_rightHand = p_right;
if(m_leapIK != null)
m_leapIK.SetHands(p_left, p_right);
}
public void Reset()
{
m_calibrated = false;
m_animator = null;
m_leapIK = null;
}
public void UpdateTracking(GestureMatcher.GesturesData p_gesturesData)
{
if(m_enabled && (m_indexIK != null))
{
if(p_gesturesData.m_handsPresenses[0])
{
m_indexIK.leftThumbCurl = p_gesturesData.m_leftFingersBends[0];
m_indexIK.leftIndexCurl = p_gesturesData.m_leftFingersBends[1];
m_indexIK.leftMiddleCurl = p_gesturesData.m_leftFingersBends[2];
m_indexIK.leftRingCurl = p_gesturesData.m_leftFingersBends[3];
m_indexIK.leftPinkyCurl = p_gesturesData.m_leftFingersBends[4];
if(ABI_RC.Core.Savior.CVRInputManager.Instance != null)
{
ABI_RC.Core.Savior.CVRInputManager.Instance.fingerCurlLeftThumb = p_gesturesData.m_leftFingersBends[0];
ABI_RC.Core.Savior.CVRInputManager.Instance.fingerCurlLeftIndex = p_gesturesData.m_leftFingersBends[1];
ABI_RC.Core.Savior.CVRInputManager.Instance.fingerCurlLeftMiddle = p_gesturesData.m_leftFingersBends[2];
ABI_RC.Core.Savior.CVRInputManager.Instance.fingerCurlLeftRing = p_gesturesData.m_leftFingersBends[3];
ABI_RC.Core.Savior.CVRInputManager.Instance.fingerCurlLeftPinky = p_gesturesData.m_leftFingersBends[4];
}
}
if(p_gesturesData.m_handsPresenses[1])
{
m_indexIK.rightThumbCurl = p_gesturesData.m_rightFingersBends[0];
m_indexIK.rightIndexCurl = p_gesturesData.m_rightFingersBends[1];
m_indexIK.rightMiddleCurl = p_gesturesData.m_rightFingersBends[2];
m_indexIK.rightRingCurl = p_gesturesData.m_rightFingersBends[3];
m_indexIK.rightPinkyCurl = p_gesturesData.m_rightFingersBends[4];
if(ABI_RC.Core.Savior.CVRInputManager.Instance != null)
{
ABI_RC.Core.Savior.CVRInputManager.Instance.fingerCurlRightThumb = p_gesturesData.m_rightFingersBends[0];
ABI_RC.Core.Savior.CVRInputManager.Instance.fingerCurlRightIndex = p_gesturesData.m_rightFingersBends[1];
ABI_RC.Core.Savior.CVRInputManager.Instance.fingerCurlRightMiddle = p_gesturesData.m_rightFingersBends[2];
ABI_RC.Core.Savior.CVRInputManager.Instance.fingerCurlRightRing = p_gesturesData.m_rightFingersBends[3];
ABI_RC.Core.Savior.CVRInputManager.Instance.fingerCurlRightPinky = p_gesturesData.m_rightFingersBends[4];
}
}
}
}
}
}

177
ml_lme_cvr/Main.cs Normal file
View file

@ -0,0 +1,177 @@
using UnityEngine;
namespace ml_lme_cvr
{
public class LeapMotionExtension : MelonLoader.MelonMod
{
static readonly Quaternion ms_hmdRotationFix = new Quaternion(0f, 0.7071068f, 0.7071068f, 0f);
static LeapMotionExtension ms_instance = null;
Leap.Controller m_leapController = null;
GestureMatcher.GesturesData m_gesturesData = null;
GameObject m_leapTrackingRoot = null;
GameObject[] m_leapHands = null;
LeapTracked m_leapTracked = null;
Transform m_vrRig = null;
Transform m_desktopRig = null;
public override void OnApplicationStart()
{
ms_instance = this;
DependenciesHandler.ExtractDependencies();
Settings.Init(HarmonyInstance);
Settings.EnabledChange += this.OnSettingsEnableChange;
Settings.DesktopOffsetChange += this.OnSettingsDesktopOffsetChange;
Settings.FingersOnlyChange += this.OnSettingsFingersOptionChange;
m_leapController = new Leap.Controller();
m_gesturesData = new GestureMatcher.GesturesData();
m_leapHands = new GameObject[GestureMatcher.GesturesData.ms_handsCount];
// Patches
HarmonyInstance.Patch(
typeof(ABI_RC.Core.Player.PlayerSetup).GetMethod(nameof(ABI_RC.Core.Player.PlayerSetup.SetupAvatar)),
null,
new HarmonyLib.HarmonyMethod(typeof(LeapMotionExtension).GetMethod(nameof(OnAvatarSetup), System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.NonPublic))
);
MelonLoader.MelonCoroutines.Start(CreateTrackingObjects());
}
System.Collections.IEnumerator CreateTrackingObjects()
{
while(ABI_RC.Core.Player.PlayerSetup.Instance == null)
yield return null;
while(m_vrRig == null)
{
m_vrRig = ABI_RC.Core.Player.PlayerSetup.Instance.transform.Find("[CameraRigVR]");
yield return null;
}
while(m_desktopRig == null)
{
m_desktopRig = ABI_RC.Core.Player.PlayerSetup.Instance.transform.Find("[CameraRigDesktop]");
yield return null;
}
m_leapTrackingRoot = new GameObject("[LeapRoot]");
m_leapTrackingRoot.transform.parent = m_desktopRig;
m_leapTrackingRoot.transform.localPosition = new Vector3(0f, -0.45637f, 0.35f);
m_leapTrackingRoot.transform.localRotation = Quaternion.identity;
for(int i = 0; i < GestureMatcher.GesturesData.ms_handsCount; i++)
{
m_leapHands[i] = new GameObject("LeapHand" + i);
m_leapHands[i].transform.parent = m_leapTrackingRoot.transform;
m_leapHands[i].transform.localPosition = Vector3.zero;
m_leapHands[i].transform.localRotation = Quaternion.identity;
}
Settings.Reload();
}
public override void OnUpdate()
{
if(Settings.Enabled && (m_leapController != null))
{
Leap.Frame l_frame = m_leapController.Frame();
if(l_frame != null)
{
GestureMatcher.GetGestures(l_frame, ref m_gesturesData);
for(int i = 0; i < GestureMatcher.GesturesData.ms_handsCount; i++)
{
if(m_gesturesData.m_handsPresenses[i] && (m_leapHands[i] != null))
{
Vector3 l_pos = m_gesturesData.m_handsPositons[i];
Quaternion l_rot = m_gesturesData.m_handsRotations[i];
ReorientateLeapToUnity(ref l_pos, ref l_rot, false);
m_leapHands[i].transform.localPosition = l_pos;
m_leapHands[i].transform.localRotation = l_rot;
}
}
if(m_leapTracked != null)
m_leapTracked.UpdateTracking(m_gesturesData);
}
}
}
void OnSettingsEnableChange()
{
if(Settings.Enabled)
{
m_leapController.StartConnection();
m_leapController.SetAndClearPolicy(Leap.Controller.PolicyFlag.POLICY_DEFAULT, Leap.Controller.PolicyFlag.POLICY_OPTIMIZE_SCREENTOP | Leap.Controller.PolicyFlag.POLICY_OPTIMIZE_HMD);
}
else
m_leapController.StopConnection();
if(m_leapTracked != null)
m_leapTracked.SetEnabled(Settings.Enabled);
}
void OnSettingsDesktopOffsetChange()
{
if((m_leapTrackingRoot != null) && (m_vrRig != null))
{
m_leapTrackingRoot.transform.localPosition = new Vector3(Settings.DesktopOffsetX, Settings.DesktopOffsetY, Settings.DesktopOffsetZ) * m_vrRig.transform.localScale.x;
m_leapTrackingRoot.transform.localScale = m_vrRig.transform.localScale;
}
}
void OnSettingsFingersOptionChange()
{
if(m_leapTracked != null)
m_leapTracked.SetFingersOnly(Settings.FingersOnly);
}
static void OnAvatarSetup(ref ABI_RC.Core.Player.PlayerSetup __instance)
{
if(__instance != null && __instance == ABI_RC.Core.Player.PlayerSetup.Instance)
{
ms_instance?.OnLocalPlayerAvatarSetup(__instance._animator, __instance.GetComponent<ABI_RC.Core.Player.IndexIK>());
}
}
void OnLocalPlayerAvatarSetup(Animator p_animator, ABI_RC.Core.Player.IndexIK p_indexIK)
{
if(m_leapTracked != null)
Object.DestroyImmediate(m_leapTracked);
m_leapTracked = p_indexIK.gameObject.AddComponent<LeapTracked>();
m_leapTracked.SetEnabled(Settings.Enabled);
m_leapTracked.SetAnimator(p_animator);
m_leapTracked.SetHands(m_leapHands[0].transform, m_leapHands[1].transform);
m_leapTracked.SetFingersOnly(Settings.FingersOnly);
if((m_leapTrackingRoot != null) && (m_vrRig != null))
{
m_leapTrackingRoot.transform.localPosition = new Vector3(Settings.DesktopOffsetX, Settings.DesktopOffsetY, Settings.DesktopOffsetZ) * m_vrRig.transform.localScale.x;
m_leapTrackingRoot.transform.localScale = m_vrRig.transform.localScale;
}
}
static void ReorientateLeapToUnity(ref Vector3 p_pos, ref Quaternion p_rot, bool p_hmd)
{
p_pos *= 0.001f;
p_pos.z *= -1f;
p_rot.x *= -1f;
p_rot.y *= -1f;
if(p_hmd)
{
p_pos.x *= -1f;
Utils.Swap(ref p_pos.y, ref p_pos.z);
p_rot = (ms_hmdRotationFix * p_rot);
}
}
}
}

View file

@ -0,0 +1,10 @@
using System.Reflection;
[assembly: AssemblyTitle("LeapMotionExtension")]
[assembly: AssemblyVersion("1.0.0")]
[assembly: AssemblyFileVersion("1.0.0")]
[assembly: MelonLoader.MelonInfo(typeof(ml_lme_cvr.LeapMotionExtension), "LeapMotionExtension", "1.0.0", "SDraw", "https://github.com/SDraw")]
[assembly: MelonLoader.MelonGame(null, "ChilloutVR")]
[assembly: MelonLoader.MelonPlatform(MelonLoader.MelonPlatformAttribute.CompatiblePlatforms.WINDOWS_X64)]
[assembly: MelonLoader.MelonPlatformDomain(MelonLoader.MelonPlatformDomainAttribute.CompatibleDomains.MONO)]

117
ml_lme_cvr/Settings.cs Normal file
View file

@ -0,0 +1,117 @@
namespace ml_lme_cvr
{
static class Settings
{
public static readonly string[] ms_defaultSettings =
{
"InteractionLeapMotionTracking",
"InteractionLeapMotionTrackingDesktopX",
"InteractionLeapMotionTrackingDesktopY",
"InteractionLeapMotionTrackingDesktopZ",
"InteractionLeapMotionTrackingFingersOnly"
};
static bool ms_enabled = false;
static float ms_desktopOffsetX = 0f;
static float ms_desktopOffsetY = -0.45f;
static float ms_desktopOffsetZ = 0.3f;
static bool ms_fingersOnly = false;
static bool ms_initialized = false;
static public event System.Action EnabledChange;
static public event System.Action DesktopOffsetChange;
static public event System.Action FingersOnlyChange;
public static void Init(HarmonyLib.Harmony p_instance)
{
p_instance.Patch(
typeof(ABI_RC.Core.Savior.CVRSettings).GetMethod(nameof(ABI_RC.Core.Savior.CVRSettings.LoadSerializedSettings)),
new HarmonyLib.HarmonyMethod(typeof(Settings).GetMethod(nameof(BeforeSettingsLoad), System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.NonPublic)),
null
);
}
static void BeforeSettingsLoad(ref ABI_RC.Core.Savior.CVRSettings __instance)
{
if(!ms_initialized && __instance != null)
{
var l_settings = HarmonyLib.Traverse.Create(__instance)?.Field("_settings")?.GetValue<System.Collections.Generic.List<ABI_RC.Core.Savior.CVRSettingsValue>>();
if(l_settings != null)
{
l_settings.Add(new ABI_RC.Core.Savior.CVRSettingsBool(ms_defaultSettings[0], false));
l_settings.Add(new ABI_RC.Core.Savior.CVRSettingsInt(ms_defaultSettings[1], 0));
l_settings.Add(new ABI_RC.Core.Savior.CVRSettingsInt(ms_defaultSettings[2], -45));
l_settings.Add(new ABI_RC.Core.Savior.CVRSettingsInt(ms_defaultSettings[3], 30));
l_settings.Add(new ABI_RC.Core.Savior.CVRSettingsBool(ms_defaultSettings[4], false));
}
// Changes events
__instance.settingBoolChanged.AddListener((name, value) =>
{
if(name == ms_defaultSettings[0])
{
Settings.Reload();
EnabledChange?.Invoke();
}
});
__instance.settingIntChanged.AddListener((name, value) =>
{
for(int i=1; i <= 3; i++)
{
if(name == ms_defaultSettings[i])
{
Settings.Reload();
DesktopOffsetChange?.Invoke();
break;
}
}
});
__instance.settingBoolChanged.AddListener((name, value) =>
{
if(name == ms_defaultSettings[4])
{
Settings.Reload();
FingersOnlyChange?.Invoke();
}
});
ms_initialized = true;
}
}
static public void Reload()
{
ms_enabled = ABI_RC.Core.Savior.MetaPort.Instance.settings.GetSettingsBool(ms_defaultSettings[0]);
ms_desktopOffsetX = ABI_RC.Core.Savior.MetaPort.Instance.settings.GetSettingInt(ms_defaultSettings[1]) * 0.01f;
ms_desktopOffsetY = ABI_RC.Core.Savior.MetaPort.Instance.settings.GetSettingInt(ms_defaultSettings[2]) * 0.01f;
ms_desktopOffsetZ = ABI_RC.Core.Savior.MetaPort.Instance.settings.GetSettingInt(ms_defaultSettings[3]) * 0.01f;
ms_fingersOnly = ABI_RC.Core.Savior.MetaPort.Instance.settings.GetSettingsBool(ms_defaultSettings[4]);
}
public static bool Enabled
{
get => ms_enabled;
}
public static float DesktopOffsetX
{
get => ms_desktopOffsetX;
}
public static float DesktopOffsetY
{
get => ms_desktopOffsetY;
}
public static float DesktopOffsetZ
{
get => ms_desktopOffsetZ;
}
public static bool FingersOnly
{
get => ms_fingersOnly;
}
}
}

12
ml_lme_cvr/Utils.cs Normal file
View file

@ -0,0 +1,12 @@
namespace ml_lme_cvr
{
static class Utils
{
public static void Swap<T>(ref T lhs, ref T rhs)
{
T temp = lhs;
lhs = rhs;
rhs = temp;
}
}
}

View file

@ -0,0 +1,119 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{83CC74B7-F444-40E1-BD06-67CEC995A919}</ProjectGuid>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>ml_lme_cvr</RootNamespace>
<AssemblyName>ml_lme_cvr</AssemblyName>
<TargetFrameworkVersion>v4.7.2</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<Deterministic>true</Deterministic>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'">
<DebugSymbols>true</DebugSymbols>
<OutputPath>bin\x64\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<DebugType>full</DebugType>
<PlatformTarget>x64</PlatformTarget>
<ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x64'">
<OutputPath>bin\x64\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<Optimize>true</Optimize>
<DebugType>pdbonly</DebugType>
<PlatformTarget>x64</PlatformTarget>
<ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
</PropertyGroup>
<ItemGroup>
<Reference Include="Assembly-CSharp">
<HintPath>C:\Games\Steam\steamapps\common\ChilloutVR\ChilloutVR_Data\Managed\Assembly-CSharp.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="Assembly-CSharp-firstpass">
<HintPath>C:\Games\Steam\steamapps\common\ChilloutVR\ChilloutVR_Data\Managed\Assembly-CSharp-firstpass.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="MelonLoader">
<HintPath>C:\Games\Steam\steamapps\common\ChilloutVR\MelonLoader\MelonLoader.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Data" />
<Reference Include="System.Net.Http" />
<Reference Include="System.Xml" />
<Reference Include="UnityEngine">
<HintPath>C:\Games\Steam\steamapps\common\ChilloutVR\ChilloutVR_Data\Managed\UnityEngine.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="UnityEngine.AnimationModule">
<HintPath>C:\Games\Steam\steamapps\common\ChilloutVR\ChilloutVR_Data\Managed\UnityEngine.AnimationModule.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="UnityEngine.CoreModule">
<HintPath>C:\Games\Steam\steamapps\common\ChilloutVR\ChilloutVR_Data\Managed\UnityEngine.CoreModule.dll</HintPath>
<Private>False</Private>
</Reference>
</ItemGroup>
<ItemGroup>
<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" />
<Compile Include="Settings.cs" />
<Compile Include="Utils.cs" />
<Compile Include="vendor\LeapCSharp\Arm.cs" />
<Compile Include="vendor\LeapCSharp\Bone.cs" />
<Compile Include="vendor\LeapCSharp\CircularObjectBuffer.cs" />
<Compile Include="vendor\LeapCSharp\Config.cs" />
<Compile Include="vendor\LeapCSharp\Connection.cs" />
<Compile Include="vendor\LeapCSharp\Controller.cs" />
<Compile Include="vendor\LeapCSharp\CopyFromLeapCExtensions.cs" />
<Compile Include="vendor\LeapCSharp\CopyFromOtherExtensions.cs" />
<Compile Include="vendor\LeapCSharp\CSharpExtensions.cs" />
<Compile Include="vendor\LeapCSharp\Device.cs" />
<Compile Include="vendor\LeapCSharp\DeviceList.cs" />
<Compile Include="vendor\LeapCSharp\DistortionData.cs" />
<Compile Include="vendor\LeapCSharp\Events.cs" />
<Compile Include="vendor\LeapCSharp\FailedDevice.cs" />
<Compile Include="vendor\LeapCSharp\FailedDeviceList.cs" />
<Compile Include="vendor\LeapCSharp\Finger.cs" />
<Compile Include="vendor\LeapCSharp\Frame.cs" />
<Compile Include="vendor\LeapCSharp\Hand.cs" />
<Compile Include="vendor\LeapCSharp\IController.cs" />
<Compile Include="vendor\LeapCSharp\Image.cs" />
<Compile Include="vendor\LeapCSharp\ImageData.cs" />
<Compile Include="vendor\LeapCSharp\LeapC.cs" />
<Compile Include="vendor\LeapCSharp\LeapQuaternion.cs" />
<Compile Include="vendor\LeapCSharp\LeapTransform.cs" />
<Compile Include="vendor\LeapCSharp\Logger.cs" />
<Compile Include="vendor\LeapCSharp\Matrix.cs" />
<Compile Include="vendor\LeapCSharp\MemoryManager.cs" />
<Compile Include="vendor\LeapCSharp\MessageSeverity.cs" />
<Compile Include="vendor\LeapCSharp\PointMapping.cs" />
<Compile Include="vendor\LeapCSharp\StructMarshal.cs" />
<Compile Include="vendor\LeapCSharp\TransformExtensions.cs" />
<Compile Include="vendor\LeapCSharp\Vector.cs" />
</ItemGroup>
<ItemGroup>
<EmbeddedResource Include="vendor\LeapSDK\lib\x64\LeapC.dll">
<Link>LeapC.dll</Link>
</EmbeddedResource>
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<PropertyGroup>
<PostBuildEvent>copy /y "$(TargetPath)" "C:\Games\Steam\steamapps\common\ChilloutVR\Mods\</PostBuildEvent>
</PropertyGroup>
</Project>

View file

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<ReferencePath>C:\Games\Steam\steamapps\common\ChilloutVR\MelonLoader\;C:\Games\Steam\steamapps\common\ChilloutVR\ChilloutVR_Data\Managed\</ReferencePath>
</PropertyGroup>
</Project>

101
ml_lme_cvr/vendor/LeapCSharp/Arm.cs vendored Normal file
View file

@ -0,0 +1,101 @@
/******************************************************************************
* Copyright (C) Ultraleap, Inc. 2011-2021. *
* *
* Use subject to the terms of the Apache License 2.0 available at *
* http://www.apache.org/licenses/LICENSE-2.0, or another agreement *
* between Ultraleap and you, your company or other organization. *
******************************************************************************/
namespace Leap
{
using System;
/// <summary>
/// The Arm class represents the forearm.
/// </summary>
[Serializable]
public class Arm : Bone, IEquatable<Arm>
{
/// <summary>
/// Constructs a default Arm object.
/// Get valid Arm objects from a Hand object.
///
/// @since 2.0.3
/// </summary>
public Arm() : base() { }
/// <summary>
/// Constructs a new Arm object.
/// @since 3.0
/// </summary>
public Arm(Vector elbow,
Vector wrist,
Vector center,
Vector direction,
float length,
float width,
LeapQuaternion rotation)
: base(elbow,
wrist,
center,
direction,
length,
width,
BoneType.TYPE_METACARPAL, //ignored for arms
rotation)
{ }
/// <summary>
/// Compare Arm object equality.
/// Two Arm objects are equal if and only if both Arm objects represent the
/// exact same physical arm in the same frame and both Arm objects are valid.
/// @since 2.0.3
/// </summary>
public bool Equals(Arm other)
{
return Equals(other as Bone);
}
/// <summary>
/// A string containing a brief, human readable description of the Arm object.
/// @since 2.0.3
/// </summary>
public override string ToString()
{
return "Arm";
}
/// <summary>
/// The position of the elbow.
/// If not in view, the elbow position is estimated based on typical human
/// anatomical proportions.
///
/// @since 2.0.3
/// </summary>
public Vector ElbowPosition
{
get
{
return base.PrevJoint;
}
}
/// <summary>
/// The position of the wrist.
///
/// Note that the wrist position is not collocated with the end of any bone in
/// the hand. There is a gap of a few centimeters since the carpal bones are
/// not included in the skeleton model.
///
/// @since 2.0.3
/// </summary>
public Vector WristPosition
{
get
{
return base.NextJoint;
}
}
}
}

183
ml_lme_cvr/vendor/LeapCSharp/Bone.cs vendored Normal file
View file

@ -0,0 +1,183 @@
/******************************************************************************
* Copyright (C) Ultraleap, Inc. 2011-2021. *
* *
* Use subject to the terms of the Apache License 2.0 available at *
* http://www.apache.org/licenses/LICENSE-2.0, or another agreement *
* between Ultraleap and you, your company or other organization. *
******************************************************************************/
namespace Leap
{
using System;
/// <summary>
/// The Bone class represents a tracked bone.
///
/// All fingers contain 4 bones that make up the anatomy of the finger.
/// Get valid Bone objects from a Finger object.
///
/// Bones are ordered from base to tip, indexed from 0 to 3. Additionally, the
/// bone's Type enum may be used to index a specific bone anatomically.
///
/// The thumb does not have a base metacarpal bone and therefore contains a valid,
/// zero length bone at that location.
/// @since 2.0
/// </summary>
[Serializable]
public class Bone : IEquatable<Bone>
{
/// <summary>
/// Constructs a default invalid Bone object.
///
/// @since 2.0
/// </summary>
public Bone()
{
Type = BoneType.TYPE_INVALID;
}
/// <summary>
/// Constructs a new Bone object.
/// @since 3.0
/// </summary>
public Bone(Vector prevJoint,
Vector nextJoint,
Vector center,
Vector direction,
float length,
float width,
Bone.BoneType type,
LeapQuaternion rotation)
{
PrevJoint = prevJoint;
NextJoint = nextJoint;
Center = center;
Direction = direction;
Rotation = rotation;
Length = length;
Width = width;
Type = type;
}
/// <summary>
/// Compare Bone object equality.
///
/// Two Bone objects are equal if and only if both Bone objects represent the
/// exact same physical bone in the same frame and both Bone objects are valid.
/// @since 2.0
/// </summary>
public bool Equals(Bone other)
{
return Center == other.Center && Direction == other.Direction && Length == other.Length;
}
/// <summary>
/// A string containing a brief, human readable description of the Bone object.
/// @since 2.0
/// </summary>
public override string ToString()
{
return Enum.GetName(typeof(BoneType), this.Type) + " bone";
}
/// <summary>
/// The base of the bone, closest to the wrist.
/// In anatomical terms, this is the proximal end of the bone.
/// @since 2.0
/// </summary>
public Vector PrevJoint;
/// <summary>
/// The end of the bone, closest to the finger tip.
/// In anatomical terms, this is the distal end of the bone.
/// @since 2.0
/// </summary>
public Vector NextJoint;
/// <summary>
/// The midpoint of the bone.
/// @since 2.0
/// </summary>
public Vector Center;
/// <summary>
/// The normalized direction of the bone from base to tip.
/// @since 2.0
/// </summary>
public Vector Direction;
/// <summary>
/// The estimated length of the bone.
/// @since 2.0
/// </summary>
public float Length;
/// <summary>
/// The average width of the flesh around the bone.
/// @since 2.0
/// </summary>
public float Width;
/// <summary>
/// The type of this bone.
/// @since 2.0
/// </summary>
public BoneType Type;
/// <summary>
/// The orientation of this Bone as a Quaternion.
/// @since 2.0
/// </summary>
public LeapQuaternion Rotation;
/// <summary>
/// The orthonormal basis vectors for this Bone as a Matrix.
/// The orientation of this Bone as a Quaternion.
///
/// Basis vectors specify the orientation of a bone.
///
/// **xBasis** Perpendicular to the longitudinal axis of the
/// bone; exits the sides of the finger.
///
/// **yBasis or up vector** Perpendicular to the longitudinal
/// axis of the bone; exits the top and bottom of the finger. More positive
/// in the upward direction.
///
/// **zBasis** Aligned with the longitudinal axis of the bone.
/// More positive toward the base of the finger.
///
/// The bases provided for the right hand use the right-hand rule; those for
/// the left hand use the left-hand rule. Thus, the positive direction of the
/// x-basis is to the right for the right hand and to the left for the left
/// hand. You can change from right-hand to left-hand rule by multiplying the
/// z basis vector by -1.
///
/// You can use the basis vectors for such purposes as measuring complex
/// finger poses and skeletal animation.
///
/// Note that converting the basis vectors directly into a quaternion
/// representation is not mathematically valid. If you use quaternions,
/// create them from the derived rotation matrix not directly from the bases.
///
/// @since 2.0
/// </summary>
public LeapTransform Basis { get { return new LeapTransform(PrevJoint, Rotation); } }
/// <summary>
/// Enumerates the type of bones.
///
/// Members of this enumeration are returned by Bone.Type() to identify a
/// Bone object.
/// @since 2.0
/// </summary>
public enum BoneType
{
TYPE_INVALID = -1,
TYPE_METACARPAL = 0,
TYPE_PROXIMAL = 1,
TYPE_INTERMEDIATE = 2,
TYPE_DISTAL = 3
}
}
}

View file

@ -0,0 +1,106 @@
/******************************************************************************
* Copyright (C) Ultraleap, Inc. 2011-2021. *
* *
* Use subject to the terms of the Apache License 2.0 available at *
* http://www.apache.org/licenses/LICENSE-2.0, or another agreement *
* between Ultraleap and you, your company or other organization. *
******************************************************************************/
using System;
namespace Leap
{
/// <summary>
/// Various C# extensions used by the Leap C# classes.
///
/// @since 3.0
/// </summary>
public static class CSharpExtensions
{
/// <summary>
/// Compares whether two floating point numbers are within an epsilon value of each other.
/// @since 3.0
/// </summary>
public static bool NearlyEquals(this float a, float b, float epsilon = Constants.EPSILON)
{
float absA = Math.Abs(a);
float absB = Math.Abs(b);
float diff = Math.Abs(a - b);
if (a == b)
{ // shortcut, handles infinities
return true;
}
else if (a == 0 || b == 0 || diff < float.MinValue)
{
// a or b is zero or both are extremely close to it
// relative error is less meaningful here
return diff < (epsilon * float.MinValue);
}
else
{ // use relative error
return diff / (absA + absB) < epsilon;
}
}
/// <summary>
/// Reports whether this object has the specified method.
/// @since 3.0
/// </summary>
public static bool HasMethod(this object objectToCheck, string methodName)
{
var type = objectToCheck.GetType();
return type.GetMethod(methodName) != null;
}
/// <summary>
/// Returns the ordinal index of this enumeration item.
/// @since 3.0
/// </summary>
public static int indexOf(this Enum enumItem)
{
return Array.IndexOf(Enum.GetValues(enumItem.GetType()), enumItem);
}
/// <summary>
/// Gets the item at the ordinal position in this enumeration.
/// @since 3.0
/// </summary>
public static T itemFor<T>(this int ordinal)
{
T[] values = (T[])Enum.GetValues(typeof(T));
return values[ordinal];
}
/// <summary>
/// Convenience function to consolidate event dispatching boilerplate code.
/// @since 3.0
/// </summary>
public static void Dispatch<T>(this EventHandler<T> handler,
object sender, T eventArgs) where T : EventArgs
{
if (handler != null) handler(sender, eventArgs);
}
/// <summary>
/// Convenience function to consolidate event dispatching boilerplate code.
/// Events are dispatched on the message queue of a threads' synchronization
/// context, if possible.
/// @since 3.0
/// </summary>
public static void DispatchOnContext<T>(this EventHandler<T> handler, object sender,
System.Threading.SynchronizationContext context,
T eventArgs) where T : EventArgs
{
if (handler != null)
{
if (context != null)
{
System.Threading.SendOrPostCallback evt = (spc_args) => { handler(sender, spc_args as T); };
context.Post(evt, eventArgs);
}
else
handler(sender, eventArgs);
}
}
}
}

View file

@ -0,0 +1,110 @@
/******************************************************************************
* Copyright (C) Ultraleap, Inc. 2011-2021. *
* *
* Use subject to the terms of the Apache License 2.0 available at *
* http://www.apache.org/licenses/LICENSE-2.0, or another agreement *
* between Ultraleap and you, your company or other organization. *
******************************************************************************/
namespace LeapInternal
{
//TODO add test for thread safety
/**
* A Limited capacity, circular LIFO buffer that wraps around
* when full. Supports indexing to get older items. Array-backed.
* *
* Unlike many collections, objects are never removed, just overwritten when
* the buffer cycles back to their array location.
*
* Object types used must have default parameterless constructor. It should be obvious that
* such default objects are invalid. I.e. for Leap API objects, the IsValid property should be false.
*/
public class CircularObjectBuffer<T> where T : new()
{
private T[] array;
private int current = 0;
private object locker = new object();
public int Count { get; private set; }
public int Capacity { get; private set; }
public bool IsEmpty { get; private set; }
public CircularObjectBuffer(int capacity)
{
Capacity = capacity;
array = new T[this.Capacity];
current = 0;
Count = 0;
IsEmpty = true;
}
/** Put an item at the head of the list. Once full, this will overwrite the oldest item. */
public virtual void Put(ref T item)
{
lock (locker)
{
if (!IsEmpty)
{
current++;
if (current >= Capacity)
{
current = 0;
}
}
if (Count < Capacity)
Count++;
lock (array)
{
array[current] = item;
}
IsEmpty = false;
}
}
/** Get the item indexed backward from the head of the list */
public void Get(out T t, int index = 0)
{
lock (locker)
{
if (IsEmpty || (index > Count - 1) || index < 0)
{
t = new T(); //default(T);
}
else
{
int effectiveIndex = current - index;
if (effectiveIndex < 0)
{
effectiveIndex += Capacity;
}
t = array[effectiveIndex];
}
}
}
/** Increase */
public void Resize(int newCapacity)
{
lock (locker)
{
if (newCapacity <= Capacity)
{
return;
}
T[] newArray = new T[newCapacity];
int j = 0;
for (int i = Count - 1; i >= 0; i--)
{
T t;
Get(out t, i);
newArray[j++] = t;
}
this.array = newArray;
this.Capacity = newCapacity;
}
}
}
}

195
ml_lme_cvr/vendor/LeapCSharp/Config.cs vendored Normal file
View file

@ -0,0 +1,195 @@
/******************************************************************************
* Copyright (C) Ultraleap, Inc. 2011-2021. *
* *
* Use subject to the terms of the Apache License 2.0 available at *
* http://www.apache.org/licenses/LICENSE-2.0, or another agreement *
* between Ultraleap and you, your company or other organization. *
******************************************************************************/
namespace Leap
{
using LeapInternal;
using System;
using System.Collections.Generic;
/// <summary>
/// The Config class provides access to Leap Motion system configuration information.
///
/// @since 1.0
/// </summary>
public class Config
{
private Connection _connection;
private Dictionary<UInt32, object> _transactions = new Dictionary<UInt32, object>();
/// <summary>
/// Creates a new Config object for setting runtime configuration settings.
///
/// Note that the Controller.Config provides a properly initialized Config object already.
/// @since 3.0
/// </summary>
public Config(Connection.Key connectionKey)
{
_connection = Connection.GetConnection(connectionKey);
_connection.LeapConfigChange += handleConfigChange;
_connection.LeapConfigResponse += handleConfigResponse;
}
public Config(int connectionId) : this(new Connection.Key(connectionId)) { }
private void handleConfigChange(object sender, ConfigChangeEventArgs eventArgs)
{
object actionDelegate;
if (_transactions.TryGetValue(eventArgs.RequestId, out actionDelegate))
{
Action<bool> changeAction = actionDelegate as Action<bool>;
changeAction(eventArgs.Succeeded);
_transactions.Remove(eventArgs.RequestId);
}
}
private void handleConfigResponse(object sender, SetConfigResponseEventArgs eventArgs)
{
object actionDelegate = new object();
if (_transactions.TryGetValue(eventArgs.RequestId, out actionDelegate))
{
switch (eventArgs.DataType)
{
case ValueType.TYPE_BOOLEAN:
Action<bool> boolAction = actionDelegate as Action<bool>;
boolAction((int)eventArgs.Value != 0);
break;
case ValueType.TYPE_FLOAT:
Action<float> floatAction = actionDelegate as Action<float>;
floatAction((float)eventArgs.Value);
break;
case ValueType.TYPE_INT32:
Action<Int32> intAction = actionDelegate as Action<Int32>;
intAction((Int32)eventArgs.Value);
break;
case ValueType.TYPE_STRING:
Action<string> stringAction = actionDelegate as Action<string>;
stringAction((string)eventArgs.Value);
break;
default:
break;
}
_transactions.Remove(eventArgs.RequestId);
}
}
/// <summary>
/// Requests a configuration value.
///
/// You must provide an action to take when the Leap service returns the config value.
/// The Action delegate must take a parameter matching the config value type. The current
/// value of the setting is passed to this delegate.
///
/// @since 3.0
/// </summary>
public bool Get<T>(string key, Action<T> onResult)
{
uint requestId = _connection.GetConfigValue(key);
if (requestId > 0)
{
_transactions.Add(requestId, onResult);
return true;
}
return false;
}
/// <summary>
/// Sets a configuration value.
///
/// You must provide an action to take when the Leap service sets the config value.
/// The Action delegate must take a boolean parameter. The service calls this delegate
/// with the value true if the setting was changed successfully and false, otherwise.
///
/// @since 3.0
/// </summary>
public bool Set<T>(string key, T value, Action<bool> onResult) where T : IConvertible
{
uint requestId = _connection.SetConfigValue<T>(key, value);
if (requestId > 0)
{
_transactions.Add(requestId, onResult);
return true;
}
return false;
}
[Obsolete("Use the generic Set<T> method instead.")]
public ValueType Type(string key)
{
return ValueType.TYPE_UNKNOWN;
}
[Obsolete("Use the generic Get<T> method instead.")]
public bool GetBool(string key)
{
return false;
}
[Obsolete("Use the generic Set<T> method instead.")]
public bool SetBool(string key, bool value)
{
return false;
}
[Obsolete("Use the generic Get<T> method instead.")]
public bool GetInt32(string key)
{
return false;
}
[Obsolete("Use the generic Set<T> method instead.")]
public bool SetInt32(string key, int value)
{
return false;
}
[Obsolete("Use the generic Get<T> method instead.")]
public bool GetFloat(string key)
{
return false;
}
[Obsolete("Use the generic Set<T> method instead.")]
public bool SetFloat(string key, float value)
{
return false;
}
[Obsolete("Use the generic Get<T> method instead.")]
public bool GetString(string key)
{
return false;
}
[Obsolete("Use the generic Set<T> method instead.")]
public bool SetString(string key, string value)
{
return false;
}
[Obsolete]
public bool Save()
{
return false;
}
/// <summary>
/// Enumerates the possible data types for configuration values.
/// @since 1.0
/// </summary>
public enum ValueType
{
TYPE_UNKNOWN = 0,
TYPE_BOOLEAN = 1,
TYPE_INT32 = 2,
TYPE_FLOAT = 6,
TYPE_STRING = 8,
}
}
}

1119
ml_lme_cvr/vendor/LeapCSharp/Connection.cs vendored Normal file

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,894 @@
/******************************************************************************
* Copyright (C) Ultraleap, Inc. 2011-2021. *
* *
* Use subject to the terms of the Apache License 2.0 available at *
* http://www.apache.org/licenses/LICENSE-2.0, or another agreement *
* between Ultraleap and you, your company or other organization. *
******************************************************************************/
namespace Leap
{
using LeapInternal;
using System;
using System.Threading;
using UnityEngine;
/// <summary>
/// The Controller class is your main interface to the Leap Motion Controller.
///
/// Create an instance of this Controller class to access frames of tracking
/// data and configuration information.Frame data can be polled at any time
/// using the Controller.Frame() function.Call frame() or frame(0) to get the
/// most recent frame.Set the history parameter to a positive integer to access
/// previous frames.A controller stores up to 60 frames in its frame history.
///
///
/// Polling is an appropriate strategy for applications which already have an
/// intrinsic update loop, such as a game. You can also subscribe to the FrameReady
/// event to get tracking frames through an event delegate.
///
/// If the current thread implements a SynchronizationContext that contains a message
/// loop, events are posted to that threads message loop. Otherwise, events are called
/// on an independent thread and applications must perform any needed synchronization
/// or marshalling of data between threads. Note that Unity3D does not create an
/// appropriate SynchronizationContext object. Typically, event handlers cannot access
/// any Unity objects.
///
/// @since 1.0
/// </summary>
public class Controller :
IController
{
Connection _connection;
bool _disposed = false;
bool _supportsMultipleDevices = true;
string _serverNamespace = "Leap Service";
Config _config;
/// <summary>
/// The SynchronizationContext used for dispatching events.
///
/// By default the synchronization context of the thread creating the controller
/// instance is used. You can change the context if desired.
/// </summary>
public SynchronizationContext EventContext
{
get
{
return _connection.EventContext;
}
set
{
_connection.EventContext = value;
}
}
/// <summary>
/// Dispatched when the connection is initialized (but not necessarily connected).
///
/// Can be dispatched more than once, if connection is restarted.
/// @since 3.0
/// </summary>
public event EventHandler<LeapEventArgs> Init
{
add
{
if (_hasInitialized)
value(this, new LeapEventArgs(LeapEvent.EVENT_INIT));
_init += value;
}
remove { _init -= value; }
}
private bool _hasInitialized = false;
private EventHandler<LeapEventArgs> _init;
/// <summary>
/// Dispatched when the connection to the service is established.
/// @since 3.0
/// </summary>
public event EventHandler<ConnectionEventArgs> Connect
{
add
{
_connection.LeapConnection += value;
}
remove
{
_connection.LeapConnection -= value;
}
}
private EventHandler<ConnectionEventArgs> _connect;
/// <summary>
/// Dispatched if the connection to the service is lost.
/// @since 3.0
/// </summary>
public event EventHandler<ConnectionLostEventArgs> Disconnect
{
add
{
_connection.LeapConnectionLost += value;
}
remove
{
_connection.LeapConnectionLost -= value;
}
}
/// <summary>
/// Dispatched when a tracking frame is ready.
/// @since 3.0
/// </summary>
public event EventHandler<FrameEventArgs> FrameReady
{
add
{
_connection.LeapFrame += value;
}
remove
{
_connection.LeapFrame -= value;
}
}
/// <summary>
/// Dispatched when an internal tracking frame is ready.
/// @since 3.0
/// </summary>
public event EventHandler<InternalFrameEventArgs> InternalFrameReady
{
add
{
_connection.LeapInternalFrame += value;
}
remove
{
_connection.LeapInternalFrame -= value;
}
}
/// <summary>
/// Dispatched when a Leap Motion device is connected.
/// @since 3.0
/// </summary>
public event EventHandler<DeviceEventArgs> Device
{
add
{
_connection.LeapDevice += value;
}
remove
{
_connection.LeapDevice -= value;
}
}
/// <summary>
/// Dispatched when a Leap Motion device is disconnected.
/// @since 3.0
/// </summary>
public event EventHandler<DeviceEventArgs> DeviceLost
{
add
{
_connection.LeapDeviceLost += value;
}
remove
{
_connection.LeapDeviceLost -= value;
}
}
/// <summary>
/// Dispatched when a Leap device fails to initialize.
/// @since 3.0
/// </summary>
public event EventHandler<DeviceFailureEventArgs> DeviceFailure
{
add
{
_connection.LeapDeviceFailure += value;
}
remove
{
_connection.LeapDeviceFailure -= value;
}
}
/// <summary>
/// Dispatched when the system generates a loggable event.
/// @since 3.0
/// </summary>
public event EventHandler<LogEventArgs> LogMessage
{
add
{
_connection.LeapLogEvent += value;
}
remove
{
_connection.LeapLogEvent -= value;
}
}
/// <summary>
/// Dispatched when a policy changes.
/// @since 3.0
/// </summary>
public event EventHandler<PolicyEventArgs> PolicyChange
{
add
{
_connection.LeapPolicyChange += value;
}
remove
{
_connection.LeapPolicyChange -= value;
}
}
/// <summary>
/// Dispatched when a configuration setting changes.
/// @since 3.0
/// </summary>
public event EventHandler<ConfigChangeEventArgs> ConfigChange
{
add
{
_connection.LeapConfigChange += value;
}
remove
{
_connection.LeapConfigChange -= value;
}
}
/// <summary>
/// Dispatched when the image distortion map changes.
/// The distortion map can change when the Leap device switches orientation,
/// or a new device becomes active.
/// @since 3.0
/// </summary>
public event EventHandler<DistortionEventArgs> DistortionChange
{
add
{
_connection.LeapDistortionChange += value;
}
remove
{
_connection.LeapDistortionChange -= value;
}
}
/// <summary>
/// Dispatched when the service drops a tracking frame.
/// </summary>
public event EventHandler<DroppedFrameEventArgs> DroppedFrame
{
add
{
_connection.LeapDroppedFrame += value;
}
remove
{
_connection.LeapDroppedFrame -= value;
}
}
/// <summary>
/// Dispatched when an unrequested image is ready.
/// @since 4.0
/// </summary>
public event EventHandler<ImageEventArgs> ImageReady
{
add
{
_connection.LeapImage += value;
}
remove
{
_connection.LeapImage -= value;
}
}
/// <summary>
/// Dispatched whenever a thread wants to start profiling for a custom thread.
/// The event is always dispatched from the thread itself.
///
/// The event data will contain the name of the thread, as well as an array of
/// all possible profiling blocks that could be entered on that thread.
///
/// @since 4.0
/// </summary>
public event Action<BeginProfilingForThreadArgs> BeginProfilingForThread
{
add
{
_connection.LeapBeginProfilingForThread += value;
}
remove
{
_connection.LeapBeginProfilingForThread -= value;
}
}
/// <summary>
/// Dispatched whenever a thread is finished profiling. The event is always
/// dispatched from the thread itself.
///
/// @since 4.0
/// </summary>
public event Action<EndProfilingForThreadArgs> EndProfilingForThread
{
add
{
_connection.LeapEndProfilingForThread += value;
}
remove
{
_connection.LeapEndProfilingForThread -= value;
}
}
/// <summary>
/// Dispatched whenever a thread enters a profiling block. The event is always
/// dispatched from the thread itself.
///
/// The event data will contain the name of the profiling block.
///
/// @since 4.0
/// </summary>
public event Action<BeginProfilingBlockArgs> BeginProfilingBlock
{
add
{
_connection.LeapBeginProfilingBlock += value;
}
remove
{
_connection.LeapBeginProfilingBlock -= value;
}
}
/// <summary>
/// Dispatched whenever a thread ends a profiling block. The event is always
/// dispatched from the thread itself.
///
/// The event data will contain the name of the profiling block.
///
/// @since 4.0
/// </summary>
public event Action<EndProfilingBlockArgs> EndProfilingBlock
{
add
{
_connection.LeapEndProfilingBlock += value;
}
remove
{
_connection.LeapEndProfilingBlock -= value;
}
}
/// <summary>
/// Dispatched when point mapping change events are generated by the service.
/// @since 4.0
/// </summary>
public event EventHandler<PointMappingChangeEventArgs> PointMappingChange
{
add
{
_connection.LeapPointMappingChange += value;
}
remove
{
_connection.LeapPointMappingChange -= value;
}
}
/// <summary>
/// Dispatched when a new HeadPose is available.
/// </summary>
public event EventHandler<HeadPoseEventArgs> HeadPoseChange
{
add
{
_connection.LeapHeadPoseChange += value;
}
remove
{
_connection.LeapHeadPoseChange -= value;
}
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
// Protected implementation of Dispose pattern.
protected virtual void Dispose(bool disposing)
{
if (_disposed)
{
return;
}
_connection.Dispose();
_disposed = true;
}
/// <summary>
/// Constructs a Controller object.
///
/// The default constructor uses a connection key of 0.
///
/// @since 1.0
/// </summary>
public Controller() : this(0, null, true) { }
/// <summary>
/// Constructs a Controller object using the specified connection key.
///
/// All controller instances using the same key will use the same connection
/// to the service. In general, an application should not use more than one connection
/// for all its controllers. Each connection keeps its own cache of frames and images.
///
/// @param connectionKey An identifier specifying the connection to use. If a
/// connection with the specified key already exists, that connection is used.
/// Otherwise, a new connection is created.
/// @since 3.0
/// </summary>
public Controller(int connectionKey, string serverNamespace = "Leap Service", bool supportsMultipleDevices = true)
{
_connection = Connection.GetConnection(new Connection.Key(connectionKey, serverNamespace));
_connection.EventContext = SynchronizationContext.Current;
_connection.LeapInit += OnInit;
_connection.LeapConnection += OnConnect;
_connection.LeapConnectionLost += OnDisconnect;
_supportsMultipleDevices = supportsMultipleDevices;
_serverNamespace = serverNamespace;
_connection.Start(serverNamespace, supportsMultipleDevices);
}
/// <summary>
/// Starts the connection.
///
/// A connection starts automatically when created, but you can
/// use this function to restart the connection after stopping it.
///
/// @since 3.0
/// </summary>
public void StartConnection()
{
_connection.Start(_serverNamespace, _supportsMultipleDevices);
}
/// <summary>
/// Stops the connection.
///
/// No more frames or other events are received from a stopped connection. You can
/// restart with StartConnection().
///
/// @since 3.0
/// </summary>
public void StopConnection()
{
_connection.Stop();
}
/// <summary>
/// Reports whether your application has a connection to the Leap Motion
/// daemon/service. Can be true even if the Leap Motion hardware is not available.
/// @since 1.2
/// </summary>
public bool IsServiceConnected
{
get
{
return _connection.IsServiceConnected;
}
}
/// <summary>
/// Requests setting a policy.
///
/// A request to change a policy is subject to user approval and a policy
/// can be changed by the user at any time (using the Leap Motion settings dialog).
/// The desired policy flags must be set every time an application runs.
///
/// Policy changes are completed asynchronously and, because they are subject
/// to user approval or system compatibility checks, may not complete successfully. Call
/// Controller.IsPolicySet() after a suitable interval to test whether
/// the change was accepted.
/// @since 2.1.6
/// </summary>
public void SetAndClearPolicy(PolicyFlag set, PolicyFlag clear, string deviceSerial = "")
{
_connection.SetAndClearPolicy(set, clear);
}
public void SetPolicy(PolicyFlag policy)
{
_connection.SetPolicy(policy);
}
/// <summary>
/// Requests clearing a policy.
///
/// Policy changes are completed asynchronously and, because they are subject
/// to user approval or system compatibility checks, may not complete successfully. Call
/// Controller.IsPolicySet() after a suitable interval to test whether
/// the change was accepted.
/// @since 2.1.6
/// </summary>
public void ClearPolicy(PolicyFlag policy)
{
_connection.ClearPolicy(policy);
}
/// <summary>
/// Gets the active setting for a specific policy.
///
/// Keep in mind that setting a policy flag is asynchronous, so changes are
/// not effective immediately after calling setPolicyFlag(). In addition, a
/// policy request can be declined by the user. You should always set the
/// policy flags required by your application at startup and check that the
/// policy change request was successful after an appropriate interval.
///
/// If the controller object is not connected to the Leap Motion software, then the default
/// state for the selected policy is returned.
///
/// @since 2.1.6
/// </summary>
public bool IsPolicySet(PolicyFlag policy)
{
return _connection.IsPolicySet(policy);
}
/// <summary>
/// In most cases you should get Frame objects using the LeapProvider.CurrentFrame
/// property. The data in Frame objects taken directly from a Leap.Controller instance
/// is still in the Leap Motion frame of reference and will not match the hands
/// displayed in a Unity scene.
///
/// Returns a frame of tracking data from the Leap Motion software. Use the optional
/// history parameter to specify which frame to retrieve. Call frame() or
/// frame(0) to access the most recent frame; call frame(1) to access the
/// previous frame, and so on. If you use a history value greater than the
/// number of stored frames, then the controller returns an empty frame.
///
/// @param history The age of the frame to return, counting backwards from
/// the most recent frame (0) into the past and up to the maximum age (59).
/// @returns The specified frame; or, if no history parameter is specified,
/// the newest frame. If a frame is not available at the specified history
/// position, an invalid Frame is returned.
/// @since 1.0
/// </summary>
public Frame Frame(int history = 0)
{
Frame frame = new Frame();
Frame(frame, history);
return frame;
}
/// <summary>
/// Identical to Frame(history) but instead of constructing a new frame and returning
/// it, the user provides a frame object to be filled with data instead.
/// </summary>
public void Frame(Frame toFill, int history = 0)
{
LEAP_TRACKING_EVENT trackingEvent;
_connection.Frames.Get(out trackingEvent, history);
toFill.CopyFrom(ref trackingEvent);
}
/// <summary>
/// Returns the timestamp of a recent tracking frame. Use the
/// optional history parameter to specify how many frames in the past
/// to retrieve the timestamp. Leave the history parameter as
/// it's default value to return the timestamp of the most recent
/// tracked frame.
/// </summary>
public long FrameTimestamp(int history = 0)
{
LEAP_TRACKING_EVENT trackingEvent;
_connection.Frames.Get(out trackingEvent, history);
return trackingEvent.info.timestamp;
}
/// <summary>
/// Returns the frame object with all hands transformed by the specified
/// transform matrix.
/// </summary>
public Frame GetTransformedFrame(LeapTransform trs, int history = 0)
{
return new Frame().CopyFrom(Frame(history)).Transform(trs);
}
/// <summary>
/// Returns the Frame at the specified time, interpolating the data between existing frames, if necessary.
/// </summary>
public Frame GetInterpolatedFrame(Int64 time)
{
return _connection.GetInterpolatedFrame(time);
}
/// <summary>
/// Fills the Frame with data taken at the specified time, interpolating the data between existing frames, if necessary.
/// </summary>
public void GetInterpolatedFrame(Frame toFill, Int64 time)
{
_connection.GetInterpolatedFrame(toFill, time);
}
/// <summary>
/// Returns the Head pose at the specified time, interpolating the data between existing frames, if necessary.
/// </summary>
public LEAP_HEAD_POSE_EVENT GetInterpolatedHeadPose(Int64 time)
{
return _connection.GetInterpolatedHeadPose(time);
}
public void GetInterpolatedHeadPose(ref LEAP_HEAD_POSE_EVENT toFill, Int64 time)
{
_connection.GetInterpolatedHeadPose(ref toFill, time);
}
/// <summary>
/// Subscribes to the events coming from an individual device
///
/// If this is not called, only the primary device will be subscribed.
/// Will automatically unsubscribe the primary device if this is called
/// on a secondary device, but not a primary one.
///
/// @since 4.1
/// </summary>
public void SubscribeToDeviceEvents(Device device)
{
_connection.SubscribeToDeviceEvents(device);
}
/// <summary>
/// Unsubscribes from the events coming from an individual device
///
/// This can be called safely, even if the device has not been subscribed.
///
/// @since 4.1
/// </summary>
public void UnsubscribeFromDeviceEvents(Device device)
{
_connection.UnsubscribeFromDeviceEvents(device);
}
/// <summary>
/// Subscribes to the events coming from all devices
///
/// @since 4.1
/// </summary>
public void SubscribeToAllDevices()
{
for (int i = 1; i < Devices.Count; i++)
{
_connection.SubscribeToDeviceEvents(Devices[i]);
}
}
/// <summary>
/// Unsubscribes from the events coming from all devices
///
/// @since 4.1
/// </summary>
public void UnsubscribeFromAllDevices()
{
for (int i = 1; i < Devices.Count; i++)
{
_connection.UnsubscribeFromDeviceEvents(Devices[i]);
}
}
public void TelemetryProfiling(ref LEAP_TELEMETRY_DATA telemetryData)
{
_connection.TelemetryProfiling(ref telemetryData);
}
public UInt64 TelemetryGetNow()
{
return LeapC.TelemetryGetNow();
}
public void GetPointMapping(ref PointMapping pointMapping)
{
_connection.GetPointMapping(ref pointMapping);
}
/// <summary>
/// This is a special variant of GetInterpolatedFrameFromTime, for use with special
/// features that only require the position and orientation of the palm positions, and do
/// not care about pose data or any other data.
///
/// You must specify the id of the hand that you wish to get a transform for. If you specify
/// an id that is not present in the interpolated frame, the output transform will be the
/// identity transform.
/// </summary>
public void GetInterpolatedLeftRightTransform(Int64 time,
Int64 sourceTime,
int leftId,
int rightId,
out LeapTransform leftTransform,
out LeapTransform rightTransform)
{
_connection.GetInterpolatedLeftRightTransform(time, sourceTime, leftId, rightId, out leftTransform, out rightTransform);
}
public void GetInterpolatedFrameFromTime(Frame toFill, Int64 time, Int64 sourceTime)
{
_connection.GetInterpolatedFrameFromTime(toFill, time, sourceTime);
}
/// <summary>
/// Returns a timestamp value as close as possible to the current time.
/// Values are in microseconds, as with all the other timestamp values.
///
/// @since 2.2.7
/// </summary>
public long Now()
{
return LeapC.GetNow();
}
/// <summary>
/// Reports whether this Controller is connected to the Leap Motion service and
/// the Leap Motion hardware is plugged in.
///
/// When you first create a Controller object, isConnected() returns false.
/// After the controller finishes initializing and connects to the Leap Motion
/// software and if the Leap Motion hardware is plugged in, isConnected() returns true.
///
/// You can either handle the onConnect event using a Listener instance or
/// poll the isConnected() function if you need to wait for your
/// application to be connected to the Leap Motion software before performing some other
/// operation.
///
/// @since 1.0
/// </summary>
public bool IsConnected
{
get
{
return IsServiceConnected && Devices.Count > 0;
}
}
/// <summary>
/// Returns a Config object, which you can use to query the Leap Motion system for
/// configuration information.
///
/// @since 1.0
/// </summary>
public Config Config
{
get
{
if (_config == null)
_config = new Config(this._connection.ConnectionKey);
return _config;
}
}
/// <summary>
/// The list of currently attached and recognized Leap Motion controller devices.
///
/// The Device objects in the list describe information such as the range and
/// tracking volume.
///
/// Currently, the Leap Motion Controller only allows a single active device at a time,
/// however there may be multiple devices physically attached and listed here. Any active
/// device(s) are guaranteed to be listed first, however order is not determined beyond that.
///
/// @since 1.0
/// </summary>
public DeviceList Devices
{
get
{
return _connection.Devices;
}
}
/// <summary>
/// A list of any Leap Motion hardware devices that are physically connected to
/// the client computer, but are not functioning correctly. The list contains
/// FailedDevice objects containing the pnpID and the reason for failure. No
/// other device information is available.
///
/// @since 3.0
/// </summary>
public FailedDeviceList FailedDevices()
{
return _connection.FailedDevices;
}
/// <summary>
/// The supported controller policies.
///
/// The supported policy flags are:
///
/// **POLICY_BACKGROUND_FRAMES** -- requests that your application receives frames
/// when it is not the foreground application for user input.
///
/// The background frames policy determines whether an application
/// receives frames of tracking data while in the background. By
/// default, the Leap Motion software only sends tracking data to the foreground application.
/// Only applications that need this ability should request the background
/// frames policy. The "Allow Background Apps" checkbox must be enabled in the
/// Leap Motion Control Panel or this policy will be denied.
///
/// **POLICY_OPTIMIZE_HMD** -- request that the tracking be optimized for head-mounted
/// tracking.
///
/// The optimize HMD policy improves tracking in situations where the Leap
/// Motion hardware is attached to a head-mounted display. This policy is
/// not granted for devices that cannot be mounted to an HMD, such as
/// Leap Motion controllers embedded in a laptop or keyboard.
///
/// Some policies can be denied if the user has disabled the feature on
/// their Leap Motion control panel.
///
/// @since 1.0
/// </summary>
public enum PolicyFlag
{
/// <summary>
/// The default policy.
/// </summary>
POLICY_DEFAULT = 0,
/// <summary>
/// Receive background frames.
/// </summary>
POLICY_BACKGROUND_FRAMES = (1 << 0),
/// <summary>
/// Allow streaming images.
/// </summary>
POLICY_IMAGES = (1 << 1),
/// <summary>
/// Optimize the tracking for head-mounted device.
/// </summary>
POLICY_OPTIMIZE_HMD = (1 << 2),
/// <summary>
/// Allow pausing and unpausing of the Leap Motion service.
/// </summary>
POLICY_ALLOW_PAUSE_RESUME = (1 << 3),
/// <summary>
/// Allow streaming map point
/// </summary>
POLICY_MAP_POINTS = (1 << 7),
/// <summary>
/// Optimize the tracking for screen-top device.
/// @since 5.0.0
/// </summary>
POLICY_OPTIMIZE_SCREENTOP = (1 << 8),
}
protected virtual void OnInit(object sender, LeapEventArgs eventArgs)
{
_hasInitialized = true;
}
protected virtual void OnConnect(object sender, ConnectionEventArgs eventArgs)
{
}
protected virtual void OnDisconnect(object sender, ConnectionLostEventArgs eventArgs)
{
_hasInitialized = false;
}
}
}

View file

@ -0,0 +1,142 @@
/******************************************************************************
* Copyright (C) Ultraleap, Inc. 2011-2021. *
* *
* Use subject to the terms of the Apache License 2.0 available at *
* http://www.apache.org/licenses/LICENSE-2.0, or another agreement *
* between Ultraleap and you, your company or other organization. *
******************************************************************************/
namespace LeapInternal
{
using Leap;
public static class CopyFromLeapCExtensions
{
/**
* Copies the data from an internal tracking message into a frame.
*
* @param trackingMsg The internal tracking message with the data to be copied into this frame.
*/
public static Frame CopyFrom(this Frame frame, ref LEAP_TRACKING_EVENT trackingMsg)
{
frame.Id = (long)trackingMsg.info.frame_id;
frame.Timestamp = (long)trackingMsg.info.timestamp;
frame.CurrentFramesPerSecond = trackingMsg.framerate;
frame.ResizeHandList((int)trackingMsg.nHands);
for (int i = frame.Hands.Count; i-- != 0;)
{
LEAP_HAND hand;
StructMarshal<LEAP_HAND>.ArrayElementToStruct(trackingMsg.pHands, i, out hand);
frame.Hands[i].CopyFrom(ref hand, frame.Id);
}
return frame;
}
/**
* Copies the data from an internal hand definition into a hand.
*
* @param leapHand The internal hand definition to be copied into this hand.
* @param frameId The frame id of the frame this hand belongs to.
*/
public static Hand CopyFrom(this Hand hand, ref LEAP_HAND leapHand, long frameId)
{
hand.FrameId = frameId;
hand.Id = (int)leapHand.id;
hand.Arm.CopyFrom(leapHand.arm, Bone.BoneType.TYPE_INVALID);
hand.Confidence = leapHand.confidence;
hand.GrabStrength = leapHand.grab_strength;
hand.GrabAngle = leapHand.grab_angle;
hand.PinchStrength = leapHand.pinch_strength;
hand.PinchDistance = leapHand.pinch_distance;
hand.PalmWidth = leapHand.palm.width;
hand.IsLeft = leapHand.type == eLeapHandType.eLeapHandType_Left;
hand.TimeVisible = (float)(leapHand.visible_time * 1e-6);
hand.PalmPosition = leapHand.palm.position.ToLeapVector();
hand.StabilizedPalmPosition = leapHand.palm.stabilized_position.ToLeapVector();
hand.PalmVelocity = leapHand.palm.velocity.ToLeapVector();
hand.PalmNormal = leapHand.palm.normal.ToLeapVector();
hand.Rotation = leapHand.palm.orientation.ToLeapQuaternion();
hand.Direction = leapHand.palm.direction.ToLeapVector();
hand.WristPosition = hand.Arm.NextJoint;
hand.Fingers[0].CopyFrom(leapHand.thumb, Leap.Finger.FingerType.TYPE_THUMB, hand.Id, hand.TimeVisible);
hand.Fingers[1].CopyFrom(leapHand.index, Leap.Finger.FingerType.TYPE_INDEX, hand.Id, hand.TimeVisible);
hand.Fingers[2].CopyFrom(leapHand.middle, Leap.Finger.FingerType.TYPE_MIDDLE, hand.Id, hand.TimeVisible);
hand.Fingers[3].CopyFrom(leapHand.ring, Leap.Finger.FingerType.TYPE_RING, hand.Id, hand.TimeVisible);
hand.Fingers[4].CopyFrom(leapHand.pinky, Leap.Finger.FingerType.TYPE_PINKY, hand.Id, hand.TimeVisible);
return hand;
}
/**
* Copies the data from an internal finger definition into a finger.
*
* @param leapBone The internal finger definition to be copied into this finger.
* @param type The finger type of this finger.
* @param frameId The frame id of the frame this finger belongs to.
* @param handId The hand id of the hand this finger belongs to.
* @param timeVisible The time in seconds that this finger has been visible.
*/
public static Finger CopyFrom(this Finger finger, LEAP_DIGIT leapBone, Finger.FingerType type, int handId, float timeVisible)
{
finger.Id = (handId * 10) + leapBone.finger_id;
finger.HandId = handId;
finger.TimeVisible = timeVisible;
Bone metacarpal = finger.bones[0];
Bone proximal = finger.bones[1];
Bone intermediate = finger.bones[2];
Bone distal = finger.bones[3];
metacarpal.CopyFrom(leapBone.metacarpal, Leap.Bone.BoneType.TYPE_METACARPAL);
proximal.CopyFrom(leapBone.proximal, Leap.Bone.BoneType.TYPE_PROXIMAL);
intermediate.CopyFrom(leapBone.intermediate, Leap.Bone.BoneType.TYPE_INTERMEDIATE);
distal.CopyFrom(leapBone.distal, Leap.Bone.BoneType.TYPE_DISTAL);
finger.TipPosition = distal.NextJoint;
finger.Direction = intermediate.Direction;
finger.Width = intermediate.Width;
finger.Length = (leapBone.finger_id == 0 ? 0.0f : 0.5f * proximal.Length) + intermediate.Length + 0.77f * distal.Length; //The values 0.5 for proximal and 0.77 for distal are used in platform code for this calculation
finger.IsExtended = leapBone.is_extended != 0;
finger.Type = type;
return finger;
}
/**
* Copies the data from an internal bone definition into a bone.
*
* @param leapBone The internal bone definition to be copied into this bone.
* @param type The bone type of this bone.
*/
public static Bone CopyFrom(this Bone bone, LEAP_BONE leapBone, Bone.BoneType type)
{
bone.Type = type;
bone.PrevJoint = leapBone.prev_joint.ToLeapVector();
bone.NextJoint = leapBone.next_joint.ToLeapVector();
bone.Direction = (bone.NextJoint - bone.PrevJoint);
bone.Length = bone.Direction.Magnitude;
if (bone.Length < float.Epsilon)
{
bone.Direction = Vector.Zero;
}
else
{
bone.Direction /= bone.Length;
}
bone.Center = (bone.PrevJoint + bone.NextJoint) / 2.0f;
bone.Rotation = leapBone.rotation.ToLeapQuaternion();
bone.Width = leapBone.width;
return bone;
}
}
}

View file

@ -0,0 +1,120 @@
/******************************************************************************
* Copyright (C) Ultraleap, Inc. 2011-2021. *
* *
* Use subject to the terms of the Apache License 2.0 available at *
* http://www.apache.org/licenses/LICENSE-2.0, or another agreement *
* between Ultraleap and you, your company or other organization. *
******************************************************************************/
namespace Leap
{
public static class CopyFromOtherExtensions
{
/**
* Copies the data from a source frame into a frame. After the operation is
* complete, the frame will be identical to the source frame.
*
* @param source The source frame that is copied into a frame.
*/
public static Frame CopyFrom(this Frame frame, Frame source)
{
frame.Id = source.Id;
frame.Timestamp = source.Timestamp;
frame.CurrentFramesPerSecond = source.CurrentFramesPerSecond;
frame.DeviceID = source.DeviceID;
frame.ResizeHandList(source.Hands.Count);
for (int i = frame.Hands.Count; i-- != 0;)
{
frame.Hands[i].CopyFrom(source.Hands[i]);
}
return frame;
}
/*
* Copies the data from a source hand into a hand. After the operation is
* complete, the hand will be identical to the source hand.
*
* @param source The source hand that is copied into a hand.
*/
public static Hand CopyFrom(this Hand hand, Hand source)
{
hand.Id = source.Id;
hand.Confidence = source.Confidence;
hand.GrabStrength = source.GrabStrength;
hand.GrabAngle = source.GrabAngle;
hand.Rotation = source.Rotation;
hand.PinchStrength = source.PinchStrength;
hand.PinchDistance = source.PinchDistance;
hand.PalmWidth = source.PalmWidth;
hand.IsLeft = source.IsLeft;
hand.TimeVisible = source.TimeVisible;
hand.PalmPosition = source.PalmPosition;
hand.StabilizedPalmPosition = source.StabilizedPalmPosition;
hand.PalmVelocity = source.PalmVelocity;
hand.PalmNormal = source.PalmNormal;
hand.Direction = source.Direction;
hand.WristPosition = source.WristPosition;
hand.Arm.CopyFrom(source.Arm);
for (int i = 5; i-- != 0;)
{
hand.Fingers[i].CopyFrom(source.Fingers[i]);
}
return hand;
}
/**
* Copies the data from a source finger into a finger. After the operation is
* complete, the finger will be identical to the source finger.
*
* @param source The source finger that is copied into a finger.
*/
public static Finger CopyFrom(this Finger finger, Finger source)
{
for (int i = 4; i-- != 0;)
{
finger.bones[i].CopyFrom(source.bones[i]);
}
finger.Id = source.Id;
finger.HandId = source.HandId;
finger.TimeVisible = source.TimeVisible;
finger.TipPosition = source.TipPosition;
finger.Direction = source.Direction;
finger.Width = source.Width;
finger.Length = source.Length;
finger.IsExtended = source.IsExtended;
finger.Type = source.Type;
return finger;
}
/**
* Copies the data from a source bone into a bone. After the operation is
* complete, the bone will be identical to the source bone.
*
* @param source The source bone that is copied into a bone.
*/
public static Bone CopyFrom(this Bone bone, Bone source)
{
bone.PrevJoint = source.PrevJoint;
bone.NextJoint = source.NextJoint;
bone.Direction = source.Direction;
bone.Center = source.Center;
bone.Length = source.Length;
bone.Width = source.Width;
bone.Rotation = source.Rotation;
bone.Type = source.Type;
return bone;
}
}
}

316
ml_lme_cvr/vendor/LeapCSharp/Device.cs vendored Normal file
View file

@ -0,0 +1,316 @@
/******************************************************************************
* Copyright (C) Ultraleap, Inc. 2011-2021. *
* *
* Use subject to the terms of the Apache License 2.0 available at *
* http://www.apache.org/licenses/LICENSE-2.0, or another agreement *
* between Ultraleap and you, your company or other organization. *
******************************************************************************/
namespace Leap
{
using LeapInternal;
using System;
/// <summary>
/// The Device class represents a physically connected device.
///
/// The Device class contains information related to a particular connected
/// device such as device id, field of view relative to the device,
/// and the position and orientation of the device in relative coordinates.
///
/// The position and orientation describe the alignment of the device relative to the user.
/// The alignment relative to the user is only descriptive. Aligning devices to users
/// provides consistency in the parameters that describe user interactions.
///
/// Note that Device objects can be invalid, which means that they do not contain
/// valid device information and do not correspond to a physical device.
/// @since 1.0
/// </summary>
public class Device :
IEquatable<Device>
{
/// <summary>
/// Constructs a default Device object.
///
/// Get valid Device objects from a DeviceList object obtained using the
/// Controller.Devices() method.
///
/// @since 1.0
/// </summary>
public Device() { }
public Device(IntPtr deviceHandle,
IntPtr internalHandle,
float horizontalViewAngle,
float verticalViewAngle,
float range,
float baseline,
DeviceType type,
bool isStreaming,
uint status,
string serialNumber)
{
Handle = deviceHandle;
InternalHandle = internalHandle;
HorizontalViewAngle = horizontalViewAngle;
VerticalViewAngle = verticalViewAngle;
Range = range;
Baseline = baseline;
Type = type;
IsStreaming = isStreaming;
SerialNumber = serialNumber;
UpdateStatus((eLeapDeviceStatus)status);
}
/// <summary>
/// For internal use only.
/// </summary>
public void Update(
float horizontalViewAngle,
float verticalViewAngle,
float range,
float baseline,
uint status,
string serialNumber)
{
HorizontalViewAngle = horizontalViewAngle;
VerticalViewAngle = verticalViewAngle;
Range = range;
Baseline = baseline;
SerialNumber = serialNumber;
UpdateStatus((eLeapDeviceStatus)status);
}
/// <summary>
/// For internal use only.
/// </summary>
public void Update(Device updatedDevice)
{
HorizontalViewAngle = updatedDevice.HorizontalViewAngle;
VerticalViewAngle = updatedDevice.VerticalViewAngle;
Range = updatedDevice.Range;
Baseline = updatedDevice.Baseline;
IsStreaming = updatedDevice.IsStreaming;
SerialNumber = updatedDevice.SerialNumber;
}
/// <summary>
/// Updates the status fields by parsing the uint given by the event
/// </summary>
internal void UpdateStatus(eLeapDeviceStatus status)
{
if ((status & eLeapDeviceStatus.eLeapDeviceStatus_Streaming) == eLeapDeviceStatus.eLeapDeviceStatus_Streaming)
IsStreaming = true;
else
IsStreaming = false;
if ((status & eLeapDeviceStatus.eLeapDeviceStatus_Smudged) == eLeapDeviceStatus.eLeapDeviceStatus_Smudged)
IsSmudged = true;
else
IsSmudged = false;
if ((status & eLeapDeviceStatus.eLeapDeviceStatus_Robust) == eLeapDeviceStatus.eLeapDeviceStatus_Robust)
IsLightingBad = true;
else
IsLightingBad = false;
if ((status & eLeapDeviceStatus.eLeapDeviceStatus_LowResource) == eLeapDeviceStatus.eLeapDeviceStatus_LowResource)
IsLowResource = true;
else
IsLowResource = false;
}
/// <summary>
/// For internal use only.
/// </summary>
public IntPtr Handle { get; private set; }
private IntPtr InternalHandle;
public bool SetPaused(bool pause)
{
eLeapRS result = LeapC.LeapSetPause(Handle, pause);
return result == eLeapRS.eLeapRS_Success;
}
/// <summary>
/// Compare Device object equality.
///
/// Two Device objects are equal if and only if both Device objects represent the
/// exact same Device and both Devices are valid.
///
/// @since 1.0
/// </summary>
public bool Equals(Device other)
{
return SerialNumber == other.SerialNumber;
}
/// <summary>
/// A string containing a brief, human readable description of the Device object.
/// @since 1.0
/// </summary>
public override string ToString()
{
return "Device serial# " + this.SerialNumber;
}
/// <summary>
/// The angle in radians of view along the x axis of this device.
///
/// The Leap Motion controller scans a region in the shape of an inverted pyramid
/// centered at the device's center and extending upwards. The horizontalViewAngle
/// reports the view angle along the long dimension of the device.
///
/// @since 1.0
/// </summary>
public float HorizontalViewAngle { get; private set; }
/// <summary>
/// The angle in radians of view along the z axis of this device.
///
/// The Leap Motion controller scans a region in the shape of an inverted pyramid
/// centered at the device's center and extending upwards. The verticalViewAngle
/// reports the view angle along the short dimension of the device.
///
/// @since 1.0
/// </summary>
public float VerticalViewAngle { get; private set; }
/// <summary>
/// The maximum reliable tracking range from the center of this device.
///
/// The range reports the maximum recommended distance from the device center
/// for which tracking is expected to be reliable. This distance is not a hard limit.
/// Tracking may be still be functional above this distance or begin to degrade slightly
/// before this distance depending on calibration and extreme environmental conditions.
///
/// @since 1.0
/// </summary>
public float Range { get; private set; }
/// <summary>
/// The distance in mm between the center points of the stereo sensors.
///
/// The baseline value, together with the maximum resolution, influence the
/// maximum range.
///
/// @since 2.2.5
/// </summary>
public float Baseline { get; private set; }
/// <summary>
/// Reports whether this device is streaming data to your application.
///
/// Currently only one controller can provide data at a time.
/// @since 1.2
/// </summary>
public bool IsStreaming { get; internal set; }
/// <summary>
/// The device type.
///
/// Use the device type value in the (rare) circumstances that you
/// have an application feature which relies on a particular type of device.
/// Current types of device include the original Leap Motion peripheral,
/// keyboard-embedded controllers, and laptop-embedded controllers.
///
/// @since 1.2
/// </summary>
public DeviceType Type { get; private set; }
/// <summary>
/// An alphanumeric serial number unique to each device.
///
/// Consumer device serial numbers consist of 2 letters followed by 11 digits.
///
/// When using multiple devices, the serial number provides an unambiguous
/// identifier for each device.
/// @since 2.2.2
/// </summary>
public string SerialNumber { get; private set; }
/// <summary>
/// Returns the internal status field of the current device
/// </summary>
protected uint GetDeviceStatus()
{
eLeapRS result;
LEAP_DEVICE_INFO deviceInfo = new LEAP_DEVICE_INFO();
deviceInfo.serial = IntPtr.Zero;
deviceInfo.size = (uint)System.Runtime.InteropServices.Marshal.SizeOf(deviceInfo);
result = LeapC.GetDeviceInfo(InternalHandle, ref deviceInfo);
if (result != eLeapRS.eLeapRS_Success)
return 0;
uint status = deviceInfo.status;
System.Runtime.InteropServices.Marshal.FreeCoTaskMem(deviceInfo.serial);
return status;
}
/// <summary>
/// The software has detected a possible smudge on the translucent cover
/// over the Leap Motion cameras.
/// @since 3.0
/// </summary>
public bool IsSmudged { get; internal set; }
/// <summary>
/// The software has entered low-resource mode
/// @since 3.0
/// </summary>
public bool IsLowResource { get; internal set; }
/// <summary>
/// The software has detected excessive IR illumination, which may interfere
/// with tracking. If robust mode is enabled, the system will enter robust mode when
/// isLightingBad() is true.
/// @since 3.0
/// </summary>
public bool IsLightingBad { get; internal set; }
/// <summary>
/// The available types of Leap Motion controllers.
/// </summary>
public enum DeviceType
{
TYPE_INVALID = -1,
/// <summary>
/// A standalone USB peripheral. The original Leap Motion controller device.
/// @since 1.2
/// </summary>
TYPE_PERIPHERAL = (int)eLeapDeviceType.eLeapDeviceType_Peripheral,
/// <summary>
/// Internal research product codename "Dragonfly".
/// </summary>
TYPE_DRAGONFLY = (int)eLeapDeviceType.eLeapDeviceType_Dragonfly,
/// <summary>
/// Internal research product codename "Nightcrawler".
/// </summary>
TYPE_NIGHTCRAWLER = (int)eLeapDeviceType.eLeapDeviceType_Nightcrawler,
/// <summary>
/// Research product codename "Rigel".
/// </summary>
TYPE_RIGEL = (int)eLeapDeviceType.eLeapDevicePID_Rigel,
/// <summary>
/// The Ultraleap Stereo IR 170 (SIR170) hand tracking module.
/// </summary>
TYPE_SIR170 = (int)eLeapDeviceType.eLeapDevicePID_SIR170,
/// <summary>
/// The Ultraleap 3Di hand tracking camera.
/// </summary>
TYPE_3DI = (int)eLeapDeviceType.eLeapDevicePID_3Di,
[Obsolete]
TYPE_LAPTOP,
[Obsolete]
TYPE_KEYBOARD
}
}
}

View file

@ -0,0 +1,94 @@
/******************************************************************************
* Copyright (C) Ultraleap, Inc. 2011-2021. *
* *
* Use subject to the terms of the Apache License 2.0 available at *
* http://www.apache.org/licenses/LICENSE-2.0, or another agreement *
* between Ultraleap and you, your company or other organization. *
******************************************************************************/
namespace Leap
{
using System;
using System.Collections.Generic;
/// <summary>
/// The DeviceList class represents a list of Device objects.
///
/// Get a DeviceList object by calling Controller.Devices().
/// @since 1.0
/// </summary>
public class DeviceList :
List<Device>
{
/// <summary>
/// Constructs an empty list of devices.
/// @since 1.0
/// </summary>
public DeviceList() { }
/// <summary>
/// For internal use only.
/// </summary>
public Device FindDeviceByHandle(IntPtr deviceHandle)
{
for (int d = 0; d < this.Count; d++)
{
if (this[d].Handle == deviceHandle)
return this[d];
}
return null;
}
/// <summary>
/// The device that is currently streaming tracking data.
/// If no streaming devices are found, returns null
/// </summary>
public Device ActiveDevice
{
get
{
if (Count == 1)
{
return this[0];
}
for (int d = 0; d < Count; d++)
{
this[d].UpdateStatus(LeapInternal.eLeapDeviceStatus.eLeapDeviceStatus_Streaming);
if (this[d].IsStreaming)
{
return this[d];
}
}
return null;
}
}
/// <summary>
/// For internal use only.
/// </summary>
public void AddOrUpdate(Device device)
{
Device existingDevice = FindDeviceByHandle(device.Handle);
if (existingDevice != null)
{
existingDevice.Update(device);
}
else
{
Add(device);
}
}
/// <summary>
/// Reports whether the list is empty.
/// @since 1.0
/// </summary>
public bool IsEmpty
{
get { return Count == 0; }
}
}
}

View file

@ -0,0 +1,93 @@
/******************************************************************************
* Copyright (C) Ultraleap, Inc. 2011-2021. *
* *
* Use subject to the terms of the Apache License 2.0 available at *
* http://www.apache.org/licenses/LICENSE-2.0, or another agreement *
* between Ultraleap and you, your company or other organization. *
******************************************************************************/
using System;
namespace Leap
{
/// <summary>
/// The DistortionData class contains the distortion map for correcting the
/// lens distortion of an image.
///
/// The distortion data is an array containing a 64x64 grid of floating point pairs.
/// The distortion map for both sides of an image pair are stacked in
/// the Data array -- the left map first, followed by the right map.
///
/// @since 3.0
/// </summary>
public class DistortionData
{
/// <summary>
/// Constructs an uninitialized distortion object.
/// @since 3.0
/// </summary>
public DistortionData() { }
/// <summary>
/// @since 3.0
/// </summary>
public DistortionData(UInt64 version, float width, float height, float[] data)
{
Version = version;
Width = width;
Height = height;
Data = data;
}
/// <summary>
/// An identifier assigned to the distortion map.
///
/// When the distortion map changes -- either because the devices flips the images
/// to automatically orient the hands or because a different device is plugged in,
/// the version number of the distortion data changes.
///
/// Note that the version always increases. If the images change orientation and then
/// return to their original orientation, a new version number is assigned. Thus
/// the version number can be used to detect when the data has changed, but not
/// to uniquely identify the data.
/// @since 3.0
/// </summary>
public UInt64 Version { get; set; }
/// <summary>
/// The width of the distortion map.
///
/// Currently always 64. Note that there are two floating point values for every point in the map.
/// @since 3.0
/// </summary>
public float Width { get; set; }
/// <summary>
/// The height of the distortion map.
///
/// Currently always 64.
/// @since 3.0
/// </summary>
public float Height { get; set; }
/// <summary>
/// The distortion data.
///
/// @since 3.0
/// </summary>
public float[] Data { get; set; }
/// <summary>
/// Reports whether the distortion data is internally consistent.
/// @since 3.0
/// </summary>
public bool IsValid
{
get
{
if (Data != null &&
Width == LeapInternal.LeapC.DistortionSize &&
Height == LeapInternal.LeapC.DistortionSize &&
Data.Length == Width * Height * 2)
return true;
return false;
}
}
}
}

323
ml_lme_cvr/vendor/LeapCSharp/Events.cs vendored Normal file
View file

@ -0,0 +1,323 @@
/******************************************************************************
* Copyright (C) Ultraleap, Inc. 2011-2021. *
* *
* Use subject to the terms of the Apache License 2.0 available at *
* http://www.apache.org/licenses/LICENSE-2.0, or another agreement *
* between Ultraleap and you, your company or other organization. *
******************************************************************************/
namespace Leap
{
using LeapInternal;
using System;
/// <summary>
/// An enumeration defining the types of Leap Motion events.
/// @since 3.0
/// </summary>
public enum LeapEvent
{
EVENT_CONNECTION, //!< A connection event has occurred
EVENT_CONNECTION_LOST, //!< The connection with the service has been lost
EVENT_DEVICE, //!< A device event has occurred
EVENT_DEVICE_FAILURE, //!< A device failure event has occurred
EVENT_DEVICE_LOST, //!< Event asserted when the underlying device object has been lost
EVENT_POLICY_CHANGE, //!< A change in policy occurred
EVENT_CONFIG_RESPONSE, //!< Response to a Config value request
EVENT_CONFIG_CHANGE, //!< Success response to a Config value change
EVENT_FRAME, //!< A tracking frame has been received
EVENT_INTERNAL_FRAME, //!< An internal tracking frame has been received
EVENT_IMAGE_COMPLETE, //!< A requested image is available
EVENT_IMAGE_REQUEST_FAILED, //!< A requested image could not be provided
EVENT_DISTORTION_CHANGE, //!< The distortion matrix used for image correction has changed
EVENT_LOG_EVENT, //!< A diagnostic event has occurred
EVENT_INIT,
EVENT_DROPPED_FRAME,
EVENT_IMAGE, //!< An unrequested image is available
EVENT_POINT_MAPPING_CHANGE,
EVENT_HEAD_POSE
};
/// <summary>
/// A generic object with no arguments beyond the event type.
/// @since 3.0
/// </summary>
public class LeapEventArgs : EventArgs
{
public LeapEventArgs(LeapEvent type)
{
this.type = type;
}
public LeapEvent type { get; set; }
}
/// <summary>
/// Dispatched when a tracking frame is ready.
///
/// Provides the Frame object as an argument.
/// @since 3.0
/// </summary>
public class FrameEventArgs : LeapEventArgs
{
public FrameEventArgs(Frame frame) : base(LeapEvent.EVENT_FRAME)
{
this.frame = frame;
}
public Frame frame { get; set; }
}
public class InternalFrameEventArgs : LeapEventArgs
{
public InternalFrameEventArgs(ref LEAP_TRACKING_EVENT frame) : base(LeapEvent.EVENT_INTERNAL_FRAME)
{
this.frame = frame;
}
public LEAP_TRACKING_EVENT frame { get; set; }
}
/// <summary>
/// Dispatched when loggable events are generated by the service and the
/// service connection code.
///
/// Provides the severity rating, log text, and timestamp as arguments.
/// @since 3.0
/// </summary>
public class LogEventArgs : LeapEventArgs
{
public LogEventArgs(MessageSeverity severity, Int64 timestamp, string message) : base(LeapEvent.EVENT_LOG_EVENT)
{
this.severity = severity;
this.message = message;
this.timestamp = timestamp;
}
public MessageSeverity severity { get; set; }
public Int64 timestamp { get; set; }
public string message { get; set; }
}
/// <summary>
/// Dispatched when a policy change is complete.
///
/// Provides the current and previous policies as arguments.
///
/// @since 3.0
/// </summary>
public class PolicyEventArgs : LeapEventArgs
{
public PolicyEventArgs(UInt64 currentPolicies, UInt64 oldPolicies) : base(LeapEvent.EVENT_POLICY_CHANGE)
{
this.currentPolicies = currentPolicies;
this.oldPolicies = oldPolicies;
}
public UInt64 currentPolicies { get; set; }
public UInt64 oldPolicies { get; set; }
}
/// <summary>
/// Dispatched when the image distortion map changes.
///
/// Provides the new distortion map as an argument.
/// @since 3.0
/// </summary>
public class DistortionEventArgs : LeapEventArgs
{
public DistortionEventArgs(DistortionData distortion, Image.CameraType camera) : base(LeapEvent.EVENT_DISTORTION_CHANGE)
{
this.distortion = distortion;
this.camera = camera;
}
public DistortionData distortion { get; protected set; }
public Image.CameraType camera { get; protected set; }
}
/// <summary>
/// Dispatched when a configuration change is completed.
///
/// Provides the configuration key, whether the change was successful, and the id of the original change request.
/// @since 3.0
/// </summary>
public class ConfigChangeEventArgs : LeapEventArgs
{
public ConfigChangeEventArgs(string config_key, bool succeeded, uint requestId) : base(LeapEvent.EVENT_CONFIG_CHANGE)
{
this.ConfigKey = config_key;
this.Succeeded = succeeded;
this.RequestId = requestId;
}
public string ConfigKey { get; set; }
public bool Succeeded { get; set; }
public uint RequestId { get; set; }
}
/// <summary>
/// Dispatched when a configuration change is completed.
///
/// Provides the configuration key, whether the change was successful, and the id of the original change request.
/// @since 3.0
/// </summary>
public class SetConfigResponseEventArgs : LeapEventArgs
{
public SetConfigResponseEventArgs(string config_key, Config.ValueType dataType, object value, uint requestId) : base(LeapEvent.EVENT_CONFIG_RESPONSE)
{
this.ConfigKey = config_key;
this.DataType = dataType;
this.Value = value;
this.RequestId = requestId;
}
public string ConfigKey { get; set; }
public Config.ValueType DataType { get; set; }
public object Value { get; set; }
public uint RequestId { get; set; }
}
/// <summary>
/// Dispatched when the connection is established.
/// @since 3.0
/// </summary>
public class ConnectionEventArgs : LeapEventArgs
{
public ConnectionEventArgs() : base(LeapEvent.EVENT_CONNECTION) { }
}
/// <summary>
/// Dispatched when the connection is lost.
/// @since 3.0
/// </summary>
public class ConnectionLostEventArgs : LeapEventArgs
{
public ConnectionLostEventArgs() : base(LeapEvent.EVENT_CONNECTION_LOST) { }
}
/// <summary>
/// Dispatched when a device is plugged in.
///
/// Provides the device as an argument.
/// @since 3.0
/// </summary>
public class DeviceEventArgs : LeapEventArgs
{
public DeviceEventArgs(Device device) : base(LeapEvent.EVENT_DEVICE)
{
this.Device = device;
}
public Device Device { get; set; }
}
/// <summary>
/// Dispatched when a device is plugged in, but fails to initialize or when
/// a working device fails in use.
///
/// Provides the failure reason and, if available, the serial number.
/// @since 3.0
/// </summary>
public class DeviceFailureEventArgs : LeapEventArgs
{
public DeviceFailureEventArgs(uint code, string message, string serial) : base(LeapEvent.EVENT_DEVICE_FAILURE)
{
ErrorCode = code;
ErrorMessage = message;
DeviceSerialNumber = serial;
}
public uint ErrorCode { get; set; }
public string ErrorMessage { get; set; }
public string DeviceSerialNumber { get; set; }
}
public class DroppedFrameEventArgs : LeapEventArgs
{
public DroppedFrameEventArgs(Int64 frame_id, eLeapDroppedFrameType type) : base(LeapEvent.EVENT_DROPPED_FRAME)
{
frameID = frame_id;
reason = type;
}
public Int64 frameID { get; set; }
public eLeapDroppedFrameType reason { get; set; }
}
/// <summary>
/// Dispatched when an unrequested Image is ready.
///
/// Provides the Image object as an argument.
/// @since 4.0
/// </summary>
public class ImageEventArgs : LeapEventArgs
{
public ImageEventArgs(Image image) : base(LeapEvent.EVENT_IMAGE)
{
this.image = image;
}
public Image image { get; set; }
}
/// <summary>
/// Dispatched when point mapping change events are generated by the service.
///
/// @since 4.0
/// </summary>
public class PointMappingChangeEventArgs : LeapEventArgs
{
public PointMappingChangeEventArgs(Int64 frame_id, Int64 timestamp, UInt32 nPoints) : base(LeapEvent.EVENT_POINT_MAPPING_CHANGE)
{
this.frameID = frame_id;
this.timestamp = timestamp;
this.nPoints = nPoints;
}
public Int64 frameID { get; set; }
public Int64 timestamp { get; set; }
public UInt32 nPoints { get; set; }
}
public class HeadPoseEventArgs : LeapEventArgs
{
public HeadPoseEventArgs(LEAP_VECTOR head_position, LEAP_QUATERNION head_orientation) : base(LeapEvent.EVENT_POINT_MAPPING_CHANGE)
{
this.headPosition = head_position;
this.headOrientation = head_orientation;
}
public LEAP_VECTOR headPosition { get; set; }
public LEAP_QUATERNION headOrientation { get; set; }
}
public struct BeginProfilingForThreadArgs
{
public string threadName;
public string[] blockNames;
public BeginProfilingForThreadArgs(string threadName, params string[] blockNames)
{
this.threadName = threadName;
this.blockNames = blockNames;
}
}
public struct EndProfilingForThreadArgs { }
public struct BeginProfilingBlockArgs
{
public string blockName;
public BeginProfilingBlockArgs(string blockName)
{
this.blockName = blockName;
}
}
public struct EndProfilingBlockArgs
{
public string blockName;
public EndProfilingBlockArgs(string blockName)
{
this.blockName = blockName;
}
}
}

View file

@ -0,0 +1,88 @@
/******************************************************************************
* Copyright (C) Ultraleap, Inc. 2011-2021. *
* *
* Use subject to the terms of the Apache License 2.0 available at *
* http://www.apache.org/licenses/LICENSE-2.0, or another agreement *
* between Ultraleap and you, your company or other organization. *
******************************************************************************/
namespace Leap
{
using System;
/// <summary>
/// The FailedDevice class provides information about Leap Motion hardware that
/// has been physically connected to the client computer, but is not operating
/// correctly.
///
/// Failed devices do not provide any tracking data and do not show up in the
/// Controller.Devices() list.
///
/// Get the list of failed devices using Controller.FailedDevices().
///
/// @since 3.0
/// </summary>
public class FailedDevice :
IEquatable<FailedDevice>
{
public FailedDevice()
{
Failure = FailureType.FAIL_UNKNOWN;
PnpId = "0";
}
/// <summary>
/// Test FailedDevice equality.
/// True if the devices are the same.
/// @since 3.0
/// </summary>
public bool Equals(FailedDevice other)
{
return PnpId == other.PnpId;
}
/// <summary>
/// The device plug-and-play id string.
/// @since 3.0
/// </summary>
public string PnpId { get; private set; }
/// <summary>
/// The reason for device failure.
/// The failure reasons are defined as members of the FailureType enumeration.
///
/// @since 3.0
/// </summary>
public FailureType Failure { get; private set; }
/// <summary>
/// The errors that can cause a device to fail to properly connect to the service.
///
/// @since 3.0
/// </summary>
public enum FailureType
{
/// <summary>
/// The cause of the error is unknown.
/// </summary>
FAIL_UNKNOWN,
/// <summary>
/// The device has a bad calibration record.
/// </summary>
FAIL_CALIBRATION,
/// <summary>
/// The device firmware is corrupt or failed to update.
/// </summary>
FAIL_FIRMWARE,
/// <summary>
/// The device is unresponsive.
/// </summary>
FAIL_TRANSPORT,
/// <summary>
/// The service cannot establish the required USB control interfaces.
/// </summary>
FAIL_CONTROl
}
}
}

View file

@ -0,0 +1,47 @@
/******************************************************************************
* Copyright (C) Ultraleap, Inc. 2011-2021. *
* *
* Use subject to the terms of the Apache License 2.0 available at *
* http://www.apache.org/licenses/LICENSE-2.0, or another agreement *
* between Ultraleap and you, your company or other organization. *
******************************************************************************/
namespace Leap
{
using System.Collections.Generic;
/// <summary>
/// The list of FailedDevice objects contains an entry for every failed Leap Motion
/// hardware device connected to the client computer. FailedDevice objects report
/// the device pnpID string and reason for failure.
///
/// Get the list of FailedDevice objects from Controller.FailedDevices().
///
/// @since 3.0
/// </summary>
public class FailedDeviceList : List<FailedDevice>
{
/// <summary>
/// Constructs an empty list.
/// </summary>
public FailedDeviceList() { }
/// <summary>
/// Appends the contents of another FailedDeviceList to this one.
/// </summary>
public FailedDeviceList Append(FailedDeviceList other)
{
AddRange(other);
return this;
}
/// <summary>
/// Reports whether the list is empty.
/// </summary>
public bool IsEmpty
{
get { return Count == 0; }
}
}
}

183
ml_lme_cvr/vendor/LeapCSharp/Finger.cs vendored Normal file
View file

@ -0,0 +1,183 @@
/******************************************************************************
* Copyright (C) Ultraleap, Inc. 2011-2021. *
* *
* Use subject to the terms of the Apache License 2.0 available at *
* http://www.apache.org/licenses/LICENSE-2.0, or another agreement *
* between Ultraleap and you, your company or other organization. *
******************************************************************************/
namespace Leap
{
using System;
/// <summary>
/// The Finger class represents a tracked finger.
///
/// Fingers are objects that the Leap Motion software has classified as a finger.
/// Get valid Finger objects from a Frame or a Hand object.
/// @since 1.0
/// </summary>
[Serializable]
public class Finger
{
public Bone[] bones = new Bone[4];
/// <summary>
/// Constructs a finger.
///
/// An uninitialized finger is considered invalid.
/// Get valid Finger objects from a Hand object.
///
/// @since 3.0
/// </summary>
public Finger()
{
bones[0] = new Bone();
bones[1] = new Bone();
bones[2] = new Bone();
bones[3] = new Bone();
}
/// <summary>
/// Constructs a finger.
///
/// Generally, you should not create your own finger objects. Such objects will not
/// have valid tracking data. Get valid finger objects from a hand in a frame
/// received from the service.
/// @since 3.0
/// </summary>
public Finger(long frameId,
int handId,
int fingerId,
float timeVisible,
Vector tipPosition,
Vector direction,
float width,
float length,
bool isExtended,
FingerType type,
Bone metacarpal,
Bone proximal,
Bone intermediate,
Bone distal)
{
Type = type;
bones[0] = metacarpal;
bones[1] = proximal;
bones[2] = intermediate;
bones[3] = distal;
Id = (handId * 10) + fingerId;
HandId = handId;
TipPosition = tipPosition;
Direction = direction;
Width = width;
Length = length;
IsExtended = isExtended;
TimeVisible = timeVisible;
}
/// <summary>
/// The bone at a given bone index on this finger.
/// @since 2.0
/// </summary>
public Bone Bone(Bone.BoneType boneIx)
{
return bones[(int)boneIx];
}
/// <summary>
/// A string containing a brief, human readable description of the Finger object.
/// @since 1.0
/// </summary>
public override string ToString()
{
return Enum.GetName(typeof(FingerType), Type) + " id:" + Id;
}
/// <summary>
/// The type of this finger.
/// @since 2.0
/// </summary>
public Finger.FingerType Type;
/// <summary>
/// A unique ID assigned to this Finger object, whose value remains the
/// same across consecutive frames while the tracked hand remains visible.
/// If tracking of the hand is lost, the Leap Motion software may assign a
/// new ID when it detects the hand in a future frame.
///
/// Use the ID value to find this Finger object in future frames.
///
/// IDs should be from 1 to 100 (inclusive). If more than 100 objects are tracked
/// an IDs of -1 will be used until an ID in the defined range is available.
///
/// @since 1.0
/// </summary>
public int Id;
/// <summary>
/// The Hand associated with a finger.
/// @since 1.0
/// </summary>
public int HandId;
/// <summary>
/// The tip position of this Finger.
/// @since 1.0
/// </summary>
public Vector TipPosition;
/// <summary>
/// The direction in which this finger or tool is pointing. The direction is expressed
/// as a unit vector pointing in the same direction as the tip.
/// @since 1.0
/// </summary>
public Vector Direction;
/// <summary>
/// The estimated width of the finger.
/// @since 1.0
/// </summary>
public float Width;
/// <summary>
/// The estimated length of the finger.
/// @since 1.0
/// </summary>
public float Length;
/// <summary>
/// Whether or not this Finger is in an extended posture.
///
/// A finger is considered extended if it is extended straight from the hand as if
/// pointing. A finger is not extended when it is bent down and curled towards the
/// palm.
///
/// @since 2.0
/// </summary>
public bool IsExtended;
/// <summary>
/// The duration of time this Finger has been visible to the Leap Motion Controller.
/// @since 1.0
/// </summary>
public float TimeVisible;
/// <summary>
/// Enumerates the names of the fingers.
///
/// Members of this enumeration are returned by Finger.Type() to identify a
/// Finger object.
/// @since 2.0
/// </summary>
public enum FingerType
{
TYPE_THUMB = 0,
TYPE_INDEX = 1,
TYPE_MIDDLE = 2,
TYPE_RING = 3,
TYPE_PINKY = 4,
TYPE_UNKNOWN = -1
}
}
}

221
ml_lme_cvr/vendor/LeapCSharp/Frame.cs vendored Normal file
View file

@ -0,0 +1,221 @@
/******************************************************************************
* Copyright (C) Ultraleap, Inc. 2011-2021. *
* *
* Use subject to the terms of the Apache License 2.0 available at *
* http://www.apache.org/licenses/LICENSE-2.0, or another agreement *
* between Ultraleap and you, your company or other organization. *
******************************************************************************/
namespace Leap
{
using System;
using System.Collections.Generic;
/// <summary>
/// The Frame class represents a set of hand and finger tracking data detected
/// in a single frame.
///
/// The Leap Motion software detects hands, fingers and tools within the tracking area, reporting
/// their positions, orientations, gestures, and motions in frames at the Leap Motion frame rate.
///
/// Access Frame objects through an instance of the Controller class.
/// @since 1.0
/// </summary>
[Serializable]
public class Frame : IEquatable<Frame>
{
[ThreadStatic]
private static Queue<Hand> _handPool;
/// <summary>
/// Constructs a Frame object.
///
/// Frame instances created with this constructor are invalid.
/// Get valid Frame objects by calling the Controller.Frame() function.
///
/// The only time you should use this constructor is before deserializing
/// serialized frame data, or if you are going to be passing this Frame
/// to a method that fills it with valid data.
///
/// @since 1.0
/// </summary>
public Frame(UInt32 DeviceID = 1)
{
Hands = new List<Hand>();
this.DeviceID = DeviceID;
}
/// <summary>
/// Constructs a new Frame.
/// @since 3.0
/// </summary>
public Frame(long id, long timestamp, float fps, List<Hand> hands)
{
Id = id;
Timestamp = timestamp;
CurrentFramesPerSecond = fps;
Hands = hands;
DeviceID = 1;
}
/// <summary>
/// The Device ID that this frame was seen from.
///
/// 1-Indexed; Non-Deterministic order
///
/// Only valid when `supportsMultipleDevices` is true on the LeapProvider.
///
/// @since 4.1
/// </summary>
public UInt32 DeviceID;
[Obsolete]
public int SerializeLength
{
get
{
throw new NotImplementedException();
}
}
[Obsolete]
public byte[] Serialize
{
get
{
throw new NotImplementedException();
}
}
[Obsolete]
public void Deserialize(byte[] arg)
{
throw new NotImplementedException();
}
/// <summary>
/// The Hand object with the specified ID in this frame, or null if none
/// exists.
///
/// Use the Frame.Hand() function to retrieve the Hand object from
/// this frame using an ID value obtained from a previous frame.
/// This function always returns a Hand object, but if no hand
/// with the specified ID is present, an invalid Hand object is returned.
///
/// Note that ID values persist across frames, but only until tracking of a
/// particular object is lost. If tracking of a hand is lost and subsequently
/// regained, the new Hand object representing that physical hand may have
/// a different ID than that representing the physical hand in an earlier frame.
/// @since 1.0 </summary>
public Hand Hand(int id)
{
for (int i = Hands.Count; i-- != 0;)
{
if (Hands[i].Id == id)
{
return Hands[i];
}
}
return null;
}
/// <summary>
/// Compare Frame object equality.
///
/// Two Frame objects are equal if and only if both Frame objects represent
/// the exact same frame of tracking data and both Frame objects are valid.
/// @since 1.0
/// </summary>
public bool Equals(Frame other)
{
return Id == other.Id && Timestamp == other.Timestamp;
}
/// <summary>
/// A string containing a brief, human readable description of the Frame object.
/// @since 1.0
/// </summary>
public override string ToString()
{
return "Frame id: " + this.Id + " timestamp: " + this.Timestamp;
}
/// <summary>
/// A unique ID for this Frame.
///
/// Consecutive frames processed by the Leap Motion software have consecutive
/// increasing values. You can use the frame ID to avoid processing the same
/// Frame object twice, as well as to make sure that your application processes
/// every frame.
///
/// @since 1.0
/// </summary>
public long Id;
/// <summary>
/// The frame capture time in microseconds elapsed since an arbitrary point in
/// time in the past.
///
/// You can use Controller.Now() to calculate the age of the frame.
///
/// @since 1.0
/// </summary>
public long Timestamp;
/// <summary>
/// The instantaneous framerate.
///
/// The rate at which the Leap Motion software is providing frames of data
/// (in frames per second). The framerate can fluctuate depending on available computing
/// resources, activity within the device field of view, software tracking settings,
/// and other factors.
///
/// @since 1.0
/// </summary>
public float CurrentFramesPerSecond;
/// <summary>
/// The list of Hand objects detected in this frame, given in arbitrary order.
/// The list can be empty if no hands are detected.
///
/// @since 1.0
/// </summary>
public List<Hand> Hands;
/// <summary>
/// Resizes the Hand list to have a specific size. If the size is decreased,
/// the removed hands are placed into the hand pool. If the size is increased, the
/// new spaces are filled with hands taken from the hand pool. If the pool is
/// empty, new hands are constructed instead.
/// </summary>
public void ResizeHandList(int count)
{
if (_handPool == null)
{
_handPool = new Queue<Hand>();
}
while (Hands.Count < count)
{
Hand newHand;
if (_handPool.Count > 0)
{
newHand = _handPool.Dequeue();
}
else
{
newHand = new Hand();
}
Hands.Add(newHand);
}
while (Hands.Count > count)
{
Hand lastHand = Hands[Hands.Count - 1];
Hands.RemoveAt(Hands.Count - 1);
_handPool.Enqueue(lastHand);
}
}
}
}

322
ml_lme_cvr/vendor/LeapCSharp/Hand.cs vendored Normal file
View file

@ -0,0 +1,322 @@
/******************************************************************************
* Copyright (C) Ultraleap, Inc. 2011-2021. *
* *
* Use subject to the terms of the Apache License 2.0 available at *
* http://www.apache.org/licenses/LICENSE-2.0, or another agreement *
* between Ultraleap and you, your company or other organization. *
******************************************************************************/
namespace Leap
{
using System;
using System.Collections.Generic;
/// <summary>
/// The Hand class reports the physical characteristics of a detected hand.
///
/// Hand tracking data includes a palm position and velocity; vectors for
/// the palm normal and direction to the fingers; and lists of the attached fingers.
///
/// Note that Hand objects can be invalid, which means that they do not contain
/// valid tracking data and do not correspond to a physical entity. Invalid Hand
/// objects can be the result of using the default constructor, or modifying the
/// hand data in an incorrect way.
/// @since 1.0
/// </summary>
[Serializable]
public class Hand : IEquatable<Hand>
{
/// <summary>
/// Constructs a Hand object.
///
/// An uninitialized hand is considered invalid.
/// Get valid Hand objects from a Frame object.
///
/// @since 1.0
/// </summary>
public Hand()
{
Arm = new Arm();
Fingers = new List<Finger>(5);
Fingers.Add(new Finger());
Fingers.Add(new Finger());
Fingers.Add(new Finger());
Fingers.Add(new Finger());
Fingers.Add(new Finger());
}
/// <summary>
/// Constructs a hand.
///
/// Generally, you should not create your own Hand objects. Such objects will not
/// have valid tracking data. Get valid Hand objects from a frame
/// received from the service.
/// @since 3.0
/// </summary>
public Hand(long frameID,
int id,
float confidence,
float grabStrength,
float grabAngle,
float pinchStrength,
float pinchDistance,
float palmWidth,
bool isLeft,
float timeVisible,
Arm arm,
List<Finger> fingers,
Vector palmPosition,
Vector stabilizedPalmPosition,
Vector palmVelocity,
Vector palmNormal,
LeapQuaternion palmOrientation,
Vector direction,
Vector wristPosition)
{
FrameId = frameID;
Id = id;
Confidence = confidence;
GrabStrength = grabStrength;
GrabAngle = grabAngle;
PinchStrength = pinchStrength;
PinchDistance = pinchDistance;
PalmWidth = palmWidth;
IsLeft = isLeft;
TimeVisible = timeVisible;
Arm = arm;
Fingers = fingers;
PalmPosition = palmPosition;
StabilizedPalmPosition = stabilizedPalmPosition;
PalmVelocity = palmVelocity;
PalmNormal = palmNormal;
Rotation = palmOrientation;
Direction = direction;
WristPosition = wristPosition;
}
/// <summary>
/// The Finger object with the specified ID attached to this hand.
///
/// Use the Hand.Finger() function to retrieve a Finger object attached to
/// this hand using an ID value obtained from a previous frame.
///
/// Note that ID values persist across frames, but only until tracking of a
/// particular object is lost. If tracking of a hand is lost and subsequently
/// regained, the new Finger object representing that finger may have a
/// different ID than that representing the finger in an earlier frame.
///
/// @since 1.0
/// </summary>
public Finger Finger(int id)
{
for (int i = Fingers.Count; i-- != 0;)
{
if (Fingers[i].Id == id)
{
return Fingers[i];
}
}
return null;
}
/// <summary>
/// Compare Hand object equality.
///
/// Two Hand objects are equal if and only if both Hand objects represent the
/// exact same physical hand in the same frame and both Hand objects are valid.
/// </summary>
public bool Equals(Hand other)
{
return Id == other.Id && FrameId == other.FrameId;
}
/// <summary>
/// A string containing a brief, human readable description of the Hand object.
/// @since 1.0
/// </summary>
public override string ToString()
{
return string.Format(
"Hand {0} {1}.",
this.Id,
this.IsLeft ? "left" : "right"
);
}
public long FrameId;
/// <summary>
/// A unique ID assigned to this Hand object, whose value remains the same
/// across consecutive frames while the tracked hand remains visible. If
/// tracking is lost (for example, when a hand is occluded by another hand
/// or when it is withdrawn from or reaches the edge of the Leap Motion Controller field of view),
/// the Leap Motion software may assign a new ID when it detects the hand in a future frame.
///
/// Use the ID value with the Frame.Hand() function to find this Hand object
/// in future frames.
///
/// @since 1.0
/// </summary>
public int Id;
/// <summary>
/// The list of Finger objects detected in this frame that are attached to
/// this hand, given in order from thumb to pinky. The list cannot be empty.
/// @since 1.0
/// </summary>
public List<Finger> Fingers;
/// <summary>
/// The center position of the palm.
/// @since 1.0
/// </summary>
public Vector PalmPosition;
/// <summary>
/// The rate of change of the palm position.
/// @since 1.0
/// </summary>
public Vector PalmVelocity;
/// <summary>
/// The normal vector to the palm. If your hand is flat, this vector will
/// point downward, or "out" of the front surface of your palm.
///
/// The direction is expressed as a unit vector pointing in the same
/// direction as the palm normal (that is, a vector orthogonal to the palm).
///
/// You can use the palm normal vector to compute the roll angle of the palm with
/// respect to the horizontal plane.
/// @since 1.0
/// </summary>
public Vector PalmNormal;
/// <summary>
/// The direction from the palm position toward the fingers.
///
/// The direction is expressed as a unit vector pointing in the same
/// direction as the directed line from the palm position to the fingers.
///
/// You can use the palm direction vector to compute the pitch and yaw angles of the palm with
/// respect to the horizontal plane.
/// @since 1.0
/// </summary>
public Vector Direction;
/// <summary>
/// The transform of the hand.
///
/// Note, in version prior to 3.1, the Basis was a Matrix object.
/// @since 3.1
/// </summary>
public LeapTransform Basis { get { return new LeapTransform(PalmPosition, Rotation); } }
/// <summary>
/// The rotation of the hand as a quaternion.
///
/// @since 3.1
/// </summary>
public LeapQuaternion Rotation;
/// <summary>
/// The strength of a grab hand pose.
///
/// The strength is zero for an open hand, and blends to one when a grabbing hand
/// pose is recognized.
/// @since 2.0
/// </summary>
public float GrabStrength;
/// <summary>
/// The angle between the fingers and the hand of a grab hand pose.
///
/// The angle is computed by looking at the angle between the direction of the
/// 4 fingers and the direction of the hand. Thumb is not considered when
/// computing the angle.
/// The angle is 0 radian for an open hand, and reaches pi radians when the pose
/// is a tight fist.
///
/// @since 3.0
/// </summary>
public float GrabAngle;
/// <summary>
/// The holding strength of a pinch hand pose.
///
/// The strength is zero for an open hand, and blends to one when a pinching
/// hand pose is recognized. Pinching can be done between the thumb
/// and any other finger of the same hand.
/// @since 2.0
/// </summary>
public float PinchStrength;
/// <summary>
/// The distance between the thumb and index finger of a pinch hand pose.
///
/// The distance is computed by looking at the shortest distance between
/// the last 2 phalanges of the thumb and those of the index finger.
/// This pinch measurement only takes thumb and index finger into account.
/// @since 3.0
/// </summary>
public float PinchDistance;
/// <summary>
/// The estimated width of the palm when the hand is in a flat position.
/// @since 2.0
/// </summary>
public float PalmWidth;
/// <summary>
/// The stabilized palm position of this Hand.
///
/// Smoothing and stabilization is performed in order to make
/// this value more suitable for interaction with 2D content. The stabilized
/// position lags behind the palm position by a variable amount, depending
/// primarily on the speed of movement.
/// @since 1.0
/// </summary>
public Vector StabilizedPalmPosition;
/// <summary>
/// The position of the wrist of this hand.
/// @since 2.0.3
/// </summary>
public Vector WristPosition;
/// <summary>
/// The duration of time this Hand has been visible to the Leap Motion Controller.
/// @since 1.0
/// </summary>
public float TimeVisible;
/// <summary>
/// How confident we are with a given hand pose.
/// The confidence level ranges between 0.0 and 1.0 inclusive.
///
/// @since 2.0
/// </summary>
public float Confidence;
/// <summary>
/// Identifies whether this Hand is a left hand.
/// @since 2.0
/// </summary>
public bool IsLeft;
/// <summary>
/// Identifies whether this Hand is a right hand.
/// @since 2.0
/// </summary>
public bool IsRight { get { return !IsLeft; } }
/// <summary>
/// The arm to which this hand is attached.
///
/// If the arm is not completely in view, Arm attributes are estimated based on
/// the attributes of entities that are in view combined with typical human anatomy.
/// @since 2.0.3
/// </summary>
public Arm Arm;
}
}

View file

@ -0,0 +1,46 @@
/******************************************************************************
* Copyright (C) Ultraleap, Inc. 2011-2021. *
* *
* Use subject to the terms of the Apache License 2.0 available at *
* http://www.apache.org/licenses/LICENSE-2.0, or another agreement *
* between Ultraleap and you, your company or other organization. *
******************************************************************************/
using System;
namespace Leap
{
public interface IController :
IDisposable
{
Frame Frame(int history = 0);
Frame GetTransformedFrame(LeapTransform trs, int history = 0);
Frame GetInterpolatedFrame(Int64 time);
void SetPolicy(Controller.PolicyFlag policy);
void ClearPolicy(Controller.PolicyFlag policy);
bool IsPolicySet(Controller.PolicyFlag policy);
long Now();
bool IsConnected { get; }
Config Config { get; }
DeviceList Devices { get; }
event EventHandler<ConnectionEventArgs> Connect;
event EventHandler<ConnectionLostEventArgs> Disconnect;
event EventHandler<FrameEventArgs> FrameReady;
event EventHandler<DeviceEventArgs> Device;
event EventHandler<DeviceEventArgs> DeviceLost;
event EventHandler<DeviceFailureEventArgs> DeviceFailure;
event EventHandler<LogEventArgs> LogMessage;
//new
event EventHandler<PolicyEventArgs> PolicyChange;
event EventHandler<ConfigChangeEventArgs> ConfigChange;
event EventHandler<DistortionEventArgs> DistortionChange;
event EventHandler<ImageEventArgs> ImageReady;
event EventHandler<PointMappingChangeEventArgs> PointMappingChange;
event EventHandler<HeadPoseEventArgs> HeadPoseChange;
}
}

456
ml_lme_cvr/vendor/LeapCSharp/Image.cs vendored Normal file
View file

@ -0,0 +1,456 @@
/******************************************************************************
* Copyright (C) Ultraleap, Inc. 2011-2021. *
* *
* Use subject to the terms of the Apache License 2.0 available at *
* http://www.apache.org/licenses/LICENSE-2.0, or another agreement *
* between Ultraleap and you, your company or other organization. *
******************************************************************************/
namespace Leap
{
using LeapInternal;
using System;
/// <summary>
/// The Image class represents a stereo image pair from the Leap Motion device.
///
/// In addition to image data, the Image object provides a distortion map for correcting
/// lens distortion.
/// @since 2.1.0
/// </summary>
public class Image
{
private ImageData leftImage;
private ImageData rightImage;
private Int64 frameId = 0;
private Int64 timestamp = 0;
private UInt32 deviceId = 0;
public Image(Int64 frameId, Int64 timestamp, ImageData leftImage, ImageData rightImage, UInt32 deviceId = 1)
{
if (leftImage == null || rightImage == null)
{
throw new ArgumentNullException("images");
}
if (leftImage.type != rightImage.type ||
leftImage.format != rightImage.format ||
leftImage.width != rightImage.width ||
leftImage.height != rightImage.height ||
leftImage.bpp != rightImage.bpp ||
leftImage.DistortionSize != rightImage.DistortionSize)
{
throw new ArgumentException("image mismatch");
}
this.frameId = frameId;
this.timestamp = timestamp;
this.leftImage = leftImage;
this.rightImage = rightImage;
this.deviceId = deviceId;
}
private ImageData imageData(CameraType camera)
{
return camera == CameraType.LEFT ? leftImage : rightImage;
}
/// <summary>
/// The buffer containing the image data.
///
/// The image data is a set of 8-bit intensity values. The buffer is
/// image.Width * image.Height * image.BytesPerPixel bytes long.
///
/// Use the ByteOffset method to find the beginning offset
/// of the data for the specified camera.
///
/// @since 4.0
/// </summary>
public byte[] Data(CameraType camera)
{
if (camera != CameraType.LEFT && camera != CameraType.RIGHT)
return null;
return imageData(camera).AsByteArray;
}
/// <summary>
/// Returns a convenience device ID based on which attached device sent this
/// image.
/// @since 4.5.0
/// </summary>
public UInt32 DeviceID
{
get
{
return deviceId;
}
}
public enum CalibrationType
{
INFRARED = 0,
VISIBLE = 1
};
/// <summary>
/// The offset, in number of bytes, from the beginning of the Data()
/// buffer to the first byte of the image data for the specified camera.
///
/// @since 4.0
/// </summary>
public UInt32 ByteOffset(CameraType camera)
{
if (camera != CameraType.LEFT && camera != CameraType.RIGHT)
return 0;
return imageData(camera).byteOffset;
}
/// <summary>
/// The number of bytes in the Data() buffer corresponding to each
/// image. Use the ByteOffset() function to find the starting byte
/// offset for each image.
///
/// @since 4.0
/// </summary>
public UInt32 NumBytes
{
get
{
return leftImage.width * leftImage.height * leftImage.bpp;
}
}
/// <summary>
/// The distortion calibration map for this image.
///
/// The calibration map is a 64x64 grid of points. Each point is defined by
/// a pair of 32-bit floating point values. Each point in the map
/// represents a ray projected into the camera. The value of
/// a grid point defines the pixel in the image data containing the brightness
/// value produced by the light entering along the corresponding ray. By
/// interpolating between grid data points, you can find the brightness value
/// for any projected ray. Grid values that fall outside the range [0..1] do
/// not correspond to a value in the image data and those points should be ignored.
///
/// The calibration map can be used to render an undistorted image as well as to
/// find the true angle from the camera to a feature in the raw image. The
/// distortion map itself is designed to be used with GLSL shader programs.
/// In other contexts, it may be more convenient to use the Image Rectify()
/// and Warp() functions.
///
/// Distortion is caused by the lens geometry as well as imperfections in the
/// lens and sensor window. The calibration map is created by the calibration
/// process run for each device at the factory (and which can be rerun by the
/// user).
///
/// @since 2.1.0
/// </summary>
public float[] Distortion(CameraType camera)
{
if (camera != CameraType.LEFT && camera != CameraType.RIGHT)
return null;
return imageData(camera).DistortionData.Data;
}
/// <summary>
/// Provides the corrected camera ray intercepting the specified point on the image.
///
/// Given a point on the image, PixelToRectilinear() corrects for camera distortion
/// and returns the true direction from the camera to the source of that image point
/// within the Leap Motion field of view.
///
/// This direction vector has an x and y component [x, y, 1], with the third element
/// always one. Note that this vector uses the 2D camera coordinate system
/// where the x-axis parallels the longer (typically horizontal) dimension and
/// the y-axis parallels the shorter (vertical) dimension. The camera coordinate
/// system does not correlate to the 3D Leap Motion coordinate system.
///
/// **Note:** This function should be called immediately after an image is obtained. Incorrect
/// results will be returned if the image orientation has changed or a different device is plugged
/// in between the time the image was received and the time this function is called.
///
/// Note, this function was formerly named Rectify().
/// @since 2.1.0
/// </summary>
public Vector PixelToRectilinear(CameraType camera, Vector pixel)
{
return Connection.GetConnection().PixelToRectilinear(camera, pixel);
}
/// <summary>
/// Provides the point in the image corresponding to a ray projecting
/// from the camera.
///
/// Given a ray projected from the camera in the specified direction, RectilinearToPixel()
/// corrects for camera distortion and returns the corresponding pixel
/// coordinates in the image.
///
/// The ray direction is specified in relationship to the camera. The first
/// vector element corresponds to the "horizontal" view angle; the second
/// corresponds to the "vertical" view angle.
///
/// The RectilinearToPixel() function returns pixel coordinates outside of the image bounds
/// if you project a ray toward a point for which there is no recorded data.
///
/// RectilinearToPixel() is typically not fast enough for realtime distortion correction.
/// For better performance, use a shader program executed on a GPU.
///
/// **Note:** This function should be called immediately after an image is obtained. Incorrect
/// results will be returned if the image orientation has changed or a different device is plugged
/// in between the time the image was received and the time this function is called.
///
/// Note, this function was formerly named Warp().
/// @since 2.1.0
/// </summary>
public Vector RectilinearToPixel(CameraType camera, Vector ray)
{
return Connection.GetConnection().RectilinearToPixel(camera, ray);
}
/// <summary>
/// Compare Image object equality.
///
/// Two Image objects are equal if and only if both Image objects represent the
/// exact same Image and both Images are valid.
/// @since 2.1.0
/// </summary>
public bool Equals(Image other)
{
return
this.frameId == other.frameId &&
this.Type == other.Type &&
this.Timestamp == other.Timestamp;
}
/// <summary>
/// A string containing a brief, human readable description of the Image object.
/// @since 2.1.0
/// </summary>
public override string ToString()
{
return "Image sequence" + this.frameId + ", format: " + this.Format + ", type: " + this.Type;
}
/// <summary>
/// The image sequence ID.
/// @since 2.2.1
/// </summary>
public Int64 SequenceId
{
get
{
return frameId;
}
}
/// <summary>
/// The image width.
/// @since 2.1.0
/// </summary>
public int Width
{
get
{
return (int)leftImage.width;
}
}
/// <summary>
/// The image height.
/// @since 2.1.0
/// </summary>
public int Height
{
get
{
return (int)leftImage.height;
}
}
/// <summary>
/// The number of bytes per pixel.
///
/// Use this value along with Image.Width() and Image.Height()
/// to calculate the size of the data buffer.
///
/// @since 2.2.0
/// </summary>
public int BytesPerPixel
{
get
{
return (int)leftImage.bpp;
}
}
/// <summary>
/// The image format.
/// @since 2.2.0
/// </summary>
public FormatType Format
{
get
{
switch (leftImage.format)
{
case eLeapImageFormat.eLeapImageType_IR:
return FormatType.INFRARED;
case eLeapImageFormat.eLeapImageType_RGBIr_Bayer:
return FormatType.IBRG;
default:
return FormatType.INFRARED;
}
}
}
public ImageType Type
{
get
{
switch (leftImage.type)
{
case eLeapImageType.eLeapImageType_Default:
return ImageType.DEFAULT;
case eLeapImageType.eLeapImageType_Raw:
return ImageType.RAW;
default:
return ImageType.DEFAULT;
}
}
}
/// <summary>
/// The stride of the distortion map.
///
/// Since each point on the 64x64 element distortion map has two values in the
/// buffer, the stride is 2 times the size of the grid. (Stride is currently fixed
/// at 2 * 64 = 128).
///
/// @since 2.1.0
/// </summary>
public int DistortionWidth
{
get
{
return leftImage.DistortionSize * 2;
}
}
/// <summary>
/// The distortion map height.
/// Currently fixed at 64.
///
/// @since 2.1.0
/// </summary>
public int DistortionHeight
{
get
{
return leftImage.DistortionSize;
}
}
/// <summary>
/// The horizontal ray offset for a particular camera.
///
/// Used to convert between normalized coordinates in the range [0..1] and the
/// ray slope range [-4..4].
///
/// @since 4.0
/// </summary>
public float RayOffsetX(CameraType camera)
{
if (camera != CameraType.LEFT && camera != CameraType.RIGHT)
return 0;
return imageData(camera).RayOffsetX;
}
/// <summary>
/// The vertical ray offset for a particular camera.
///
/// Used to convert between normalized coordinates in the range [0..1] and the
/// ray slope range [-4..4].
///
/// @since 2.1.0
/// </summary>
public float RayOffsetY(CameraType camera)
{
if (camera != CameraType.LEFT && camera != CameraType.RIGHT)
return 0;
return imageData(camera).RayOffsetY;
}
/// <summary>
/// The horizontal ray scale factor for a particular camera.
///
/// Used to convert between normalized coordinates in the range [0..1] and the
/// ray slope range [-4..4].
///
/// @since 2.1.0
/// </summary>
public float RayScaleX(CameraType camera)
{
if (camera != CameraType.LEFT && camera != CameraType.RIGHT)
return 0;
return imageData(camera).RayScaleX;
}
/// <summary>
/// The vertical ray scale factor for a particular camera.
///
/// Used to convert between normalized coordinates in the range [0..1] and the
/// ray slope range [-4..4].
///
/// @since 2.1.0
/// </summary>
public float RayScaleY(CameraType camera)
{
if (camera != CameraType.LEFT && camera != CameraType.RIGHT)
return 0;
return imageData(camera).RayScaleY;
}
/// <summary>
/// Returns a timestamp indicating when this frame began being captured on the device.
/// @since 2.2.7
/// </summary>
public Int64 Timestamp
{
get
{
return timestamp;
}
}
/// <summary>
/// Enumerates the possible image formats.
///
/// The Image.Format() function returns an item from the FormatType enumeration.
/// @since 2.2.0
/// </summary>
public enum FormatType
{
INFRARED = 0,
IBRG = 1
}
public enum ImageType
{
DEFAULT,
RAW
}
public enum CameraType
{
LEFT = 0,
RIGHT = 1
};
}
}

View file

@ -0,0 +1,47 @@
/******************************************************************************
* Copyright (C) Ultraleap, Inc. 2011-2021. *
* *
* Use subject to the terms of the Apache License 2.0 available at *
* http://www.apache.org/licenses/LICENSE-2.0, or another agreement *
* between Ultraleap and you, your company or other organization. *
******************************************************************************/
namespace LeapInternal
{
using Leap;
using System;
public class ImageData
{
private LEAP_IMAGE_PROPERTIES _properties;
private object _object;
public Image.CameraType camera { get; protected set; }
public eLeapImageType type { get { return _properties.type; } }
public eLeapImageFormat format { get { return _properties.format; } }
public UInt32 bpp { get { return _properties.bpp; } }
public UInt32 width { get { return _properties.width; } }
public UInt32 height { get { return _properties.height; } }
public float RayScaleX { get { return _properties.x_scale; } }
public float RayScaleY { get { return _properties.y_scale; } }
public float RayOffsetX { get { return _properties.x_offset; } }
public float RayOffsetY { get { return _properties.y_offset; } }
public byte[] AsByteArray { get { return _object as byte[]; } }
public float[] AsFloatArray { get { return _object as float[]; } }
public UInt32 byteOffset { get; protected set; }
public int DistortionSize { get { return LeapC.DistortionSize; } }
public UInt64 DistortionMatrixKey { get; protected set; }
public DistortionData DistortionData { get; protected set; }
public ImageData(Image.CameraType camera, LEAP_IMAGE image, DistortionData distortionData)
{
this.camera = camera;
this._properties = image.properties;
this.DistortionMatrixKey = image.matrix_version;
this.DistortionData = distortionData;
this._object = MemoryManager.GetPinnedObject(image.data);
this.byteOffset = image.offset;
}
}
}

1195
ml_lme_cvr/vendor/LeapCSharp/LeapC.cs vendored Normal file

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,171 @@
/******************************************************************************
* Copyright (C) Ultraleap, Inc. 2011-2021. *
* *
* Use subject to the terms of the Apache License 2.0 available at *
* http://www.apache.org/licenses/LICENSE-2.0, or another agreement *
* between Ultraleap and you, your company or other organization. *
******************************************************************************/
namespace Leap
{
using System;
/// <summary>
/// The LeapQuaternion struct represents a rotation in three-dimensional space.
/// @since 3.1.2
/// </summary>
[Serializable]
public struct LeapQuaternion :
IEquatable<LeapQuaternion>
{
/// <summary>
/// Creates a new LeapQuaternion with the specified component values.
/// @since 3.1.2
/// </summary>
public LeapQuaternion(float x, float y, float z, float w) :
this()
{
this.x = x;
this.y = y;
this.z = z;
this.w = w;
}
/// <summary>
/// Copies the specified LeapQuaternion.
/// @since 3.1.2
/// </summary>
public LeapQuaternion(LeapQuaternion quaternion) :
this()
{
x = quaternion.x;
y = quaternion.y;
z = quaternion.z;
w = quaternion.w;
}
/// <summary>
/// Copies the specified LEAP_QUATERNION.
/// @since 3.1.2
/// </summary>
public LeapQuaternion(LeapInternal.LEAP_QUATERNION quaternion) :
this()
{
x = quaternion.x;
y = quaternion.y;
z = quaternion.z;
w = quaternion.w;
}
/// <summary>
/// Returns a string containing this quaternion in a human readable format: (x, y, z).
/// @since 3.1.2
/// </summary>
public override string ToString()
{
return "(" + x + ", " + y + ", " + z + ", " + w + ")";
}
/// <summary>
/// Compare LeapQuaternion equality component-wise.
/// @since 3.1.2
/// </summary>
public bool Equals(LeapQuaternion v)
{
return x.NearlyEquals(v.x) && y.NearlyEquals(v.y) && z.NearlyEquals(v.z) && w.NearlyEquals(v.w);
}
public override bool Equals(Object obj)
{
return obj is LeapQuaternion && Equals((LeapQuaternion)obj);
}
/// <summary>
/// Returns true if all of the quaternion's components are finite. If any
/// component is NaN or infinite, then this returns false.
/// @since 3.1.2
/// </summary>
public bool IsValid()
{
return !(float.IsNaN(x) || float.IsInfinity(x) ||
float.IsNaN(y) || float.IsInfinity(y) ||
float.IsNaN(z) || float.IsInfinity(z) ||
float.IsNaN(w) || float.IsInfinity(w));
}
public float x;
public float y;
public float z;
public float w;
/// <summary>
/// The magnitude, or length, of this quaternion.
/// @since 3.1.2
/// </summary>
public float Magnitude
{
get { return (float)Math.Sqrt(x * x + y * y + z * z + w * w); }
}
/// <summary>
/// The square of the magnitude, or length, of this quaternion.
/// @since 3.1.2
/// </summary>
public float MagnitudeSquared
{
get { return x * x + y * y + z * z + w * w; }
}
/// <summary>
/// A normalized copy of this quaternion.
/// @since 3.1.2
/// </summary>
public LeapQuaternion Normalized
{
get
{
float denom = MagnitudeSquared;
if (denom <= Constants.EPSILON)
{
return Identity;
}
denom = 1.0f / (float)Math.Sqrt(denom);
return new LeapQuaternion(x * denom, y * denom, z * denom, w * denom);
}
}
/// <summary>
/// Concatenates the rotation described by this quaternion with the one provided
/// and returns the result.
/// @since 3.1.2
/// </summary>
public LeapQuaternion Multiply(LeapQuaternion rhs)
{
return new LeapQuaternion(
w * rhs.x + x * rhs.w + y * rhs.z - z * rhs.y,
w * rhs.y + y * rhs.w + z * rhs.x - x * rhs.z,
w * rhs.z + z * rhs.w + x * rhs.y - y * rhs.x,
w * rhs.w - x * rhs.x - y * rhs.y - z * rhs.z);
}
/// <summary>
/// The identity quaternion.
/// @since 3.1.2
/// </summary>
public static readonly LeapQuaternion Identity = new LeapQuaternion(0, 0, 0, 1);
public override int GetHashCode()
{
unchecked // Overflow is fine, just wrap
{
int hash = 17;
hash = hash * 23 + x.GetHashCode();
hash = hash * 23 + y.GetHashCode();
hash = hash * 23 + z.GetHashCode();
hash = hash * 23 + w.GetHashCode();
return hash;
}
}
}
}

View file

@ -0,0 +1,277 @@
/******************************************************************************
* Copyright (C) Ultraleap, Inc. 2011-2021. *
* *
* Use subject to the terms of the Apache License 2.0 available at *
* http://www.apache.org/licenses/LICENSE-2.0, or another agreement *
* between Ultraleap and you, your company or other organization. *
******************************************************************************/
namespace Leap
{
using System;
/// <summary>
/// The LeapTransform class represents a transform in three dimensional space.
///
/// Note that the LeapTransform class replaces the Leap.Matrix class.
/// @since 3.1.2
/// </summary>
public struct LeapTransform
{
/// <summary>
/// Constructs a new transform from the specified translation and rotation.
/// @since 3.1.2
/// </summary>
public LeapTransform(Vector translation, LeapQuaternion rotation) :
this(translation, rotation, Vector.Ones)
{
}
/// <summary>
/// Constructs a new transform from the specified translation, rotation and scale.
/// @since 3.1.2
/// </summary>
public LeapTransform(Vector translation, LeapQuaternion rotation, Vector scale) :
this()
{
_scale = scale;
// these are non-trival setters.
this.translation = translation;
this.rotation = rotation; // Calls validateBasis
}
/// <summary>
/// Transforms the specified position vector, applying translation, rotation and scale.
/// @since 3.1.2
/// </summary>
public Vector TransformPoint(Vector point)
{
return _xBasisScaled * point.x + _yBasisScaled * point.y + _zBasisScaled * point.z + translation;
}
/// <summary>
/// Transforms the specified direction vector, applying rotation only.
/// @since 3.1.2
/// </summary>
public Vector TransformDirection(Vector direction)
{
return _xBasis * direction.x + _yBasis * direction.y + _zBasis * direction.z;
}
/// <summary>
/// Transforms the specified velocity vector, applying rotation and scale.
/// @since 3.1.2
/// </summary>
public Vector TransformVelocity(Vector velocity)
{
return _xBasisScaled * velocity.x + _yBasisScaled * velocity.y + _zBasisScaled * velocity.z;
}
/// <summary>
/// Transforms the specified quaternion.
/// Multiplies the quaternion representing the rotational part of this transform by the specified
/// quaternion.
///
/// **Important:** Modifying the basis vectors of this transform directly leaves the underlying quaternion in
/// an indeterminate state. Neither this function nor the LeapTransform.rotation quaternion can be used after
/// the basis vectors are set.
///
/// @since 3.1.2
/// </summary>
public LeapQuaternion TransformQuaternion(LeapQuaternion rhs)
{
if (_quaternionDirty)
throw new InvalidOperationException("Calling TransformQuaternion after Basis vectors have been modified.");
if (_flip)
{
// Mirror the axis of rotation across the flip axis.
rhs.x *= _flipAxes.x;
rhs.y *= _flipAxes.y;
rhs.z *= _flipAxes.z;
}
LeapQuaternion t = _quaternion.Multiply(rhs);
return t;
}
/// <summary>
/// Mirrors this transform's rotation and scale across the x-axis. Translation is not affected.
/// @since 3.1.2
/// </summary>
public void MirrorX()
{
_xBasis = -_xBasis;
_xBasisScaled = -_xBasisScaled;
_flip = true;
_flipAxes.y = -_flipAxes.y;
_flipAxes.z = -_flipAxes.z;
}
/// <summary>
/// Mirrors this transform's rotation and scale across the z-axis. Translation is not affected.
/// @since 3.1.2
/// </summary>
public void MirrorZ()
{
_zBasis = -_zBasis;
_zBasisScaled = -_zBasisScaled;
_flip = true;
_flipAxes.x = -_flipAxes.x;
_flipAxes.y = -_flipAxes.y;
}
/// <summary>
/// The x-basis of the transform.
///
/// **Important:** Modifying the basis vectors of this transform directly leaves the underlying quaternion in
/// an indeterminate state. Neither the TransformQuaternion() function nor the LeapTransform.rotation quaternion
/// can be used after the basis vectors are set.
///
/// @since 3.1.2
/// </summary>
public Vector xBasis
{
get { return _xBasis; }
set
{
_xBasis = value;
_xBasisScaled = value * scale.x;
_quaternionDirty = true;
}
}
/// <summary>
/// The y-basis of the transform.
///
/// **Important:** Modifying the basis vectors of this transform directly leaves the underlying quaternion in
/// an indeterminate state. Neither the TransformQuaternion() function nor the LeapTransform.rotation quaternion
/// can be used after the basis vectors are set.
///
/// @since 3.1.2
/// </summary>
public Vector yBasis
{
get { return _yBasis; }
set
{
_yBasis = value;
_yBasisScaled = value * scale.y;
_quaternionDirty = true;
}
}
/// <summary>
/// The z-basis of the transform.
///
/// **Important:** Modifying the basis vectors of this transform directly leaves the underlying quaternion in
/// an indeterminate state. Neither the TransformQuaternion() function nor the LeapTransform.rotation quaternion
/// can be used after the basis vectors are set.
///
/// @since 3.1.2
/// </summary>
public Vector zBasis
{
get { return _zBasis; }
set
{
_zBasis = value;
_zBasisScaled = value * scale.z;
_quaternionDirty = true;
}
}
/// <summary>
/// The translation component of the transform.
/// @since 3.1.2
/// </summary>
public Vector translation
{
get { return _translation; }
set
{
_translation = value;
}
}
/// <summary>
/// The scale factors of the transform.
/// Scale is kept separate from translation.
/// @since 3.1.2
/// </summary>
public Vector scale
{
get { return _scale; }
set
{
_scale = value;
_xBasisScaled = _xBasis * scale.x;
_yBasisScaled = _yBasis * scale.y;
_zBasisScaled = _zBasis * scale.z;
}
}
/// <summary>
/// The rotational component of the transform.
///
/// **Important:** Modifying the basis vectors of this transform directly leaves the underlying quaternion in
/// an indeterminate state. This rotation quaternion cannot be accessed after
/// the basis vectors are modified directly.
///
/// @since 3.1.2
/// </summary>
public LeapQuaternion rotation
{
get
{
if (_quaternionDirty)
throw new InvalidOperationException("Requesting rotation after Basis vectors have been modified.");
return _quaternion;
}
set
{
_quaternion = value;
float d = value.MagnitudeSquared;
float s = 2.0f / d;
float xs = value.x * s, ys = value.y * s, zs = value.z * s;
float wx = value.w * xs, wy = value.w * ys, wz = value.w * zs;
float xx = value.x * xs, xy = value.x * ys, xz = value.x * zs;
float yy = value.y * ys, yz = value.y * zs, zz = value.z * zs;
_xBasis = new Vector(1.0f - (yy + zz), xy + wz, xz - wy);
_yBasis = new Vector(xy - wz, 1.0f - (xx + zz), yz + wx);
_zBasis = new Vector(xz + wy, yz - wx, 1.0f - (xx + yy));
_xBasisScaled = _xBasis * scale.x;
_yBasisScaled = _yBasis * scale.y;
_zBasisScaled = _zBasis * scale.z;
_quaternionDirty = false;
_flip = false;
_flipAxes = new Vector(1.0f, 1.0f, 1.0f);
}
}
/// <summary>
/// The identity transform.
/// @since 3.1.2
/// </summary>
public static readonly LeapTransform Identity = new LeapTransform(Vector.Zero, LeapQuaternion.Identity, Vector.Ones);
private Vector _translation;
private Vector _scale;
private LeapQuaternion _quaternion;
private bool _quaternionDirty;
private bool _flip;
private Vector _flipAxes;
private Vector _xBasis;
private Vector _yBasis;
private Vector _zBasis;
private Vector _xBasisScaled;
private Vector _yBasisScaled;
private Vector _zBasisScaled;
}
}

55
ml_lme_cvr/vendor/LeapCSharp/Logger.cs vendored Normal file
View file

@ -0,0 +1,55 @@
/******************************************************************************
* Copyright (C) Ultraleap, Inc. 2011-2021. *
* *
* Use subject to the terms of the Apache License 2.0 available at *
* http://www.apache.org/licenses/LICENSE-2.0, or another agreement *
* between Ultraleap and you, your company or other organization. *
******************************************************************************/
using System;
using System.Reflection;
namespace LeapInternal
{
public static class Logger
{
/// <summary>
/// Logs message to the a Console.
/// </summary>
public static void Log(object message)
{
UnityEngine.Debug.Log(message);
}
public static void LogStruct(object thisObject, string title = "")
{
try
{
if (!thisObject.GetType().IsValueType)
{
Log(title + " ---- Trying to log non-struct with struct logger");
return;
}
Log(title + " ---- " + thisObject.GetType().ToString());
FieldInfo[] fieldInfos;
fieldInfos = thisObject.GetType().GetFields(
BindingFlags.Public | BindingFlags.NonPublic // Get public and non-public
| BindingFlags.Static | BindingFlags.Instance // Get instance + static
| BindingFlags.FlattenHierarchy); // Search up the hierarchy
// write member names
foreach (FieldInfo fieldInfo in fieldInfos)
{
object obj = fieldInfo.GetValue(thisObject);
string value = obj == null ? "null" : obj.ToString();
Log(" -------- Name: " + fieldInfo.Name + ", Value = " + value);
}
}
catch (Exception exception)
{
Log(exception.Message);
}
}
}
}

362
ml_lme_cvr/vendor/LeapCSharp/Matrix.cs vendored Normal file
View file

@ -0,0 +1,362 @@
/******************************************************************************
* Copyright (C) Ultraleap, Inc. 2011-2021. *
* *
* Use subject to the terms of the Apache License 2.0 available at *
* http://www.apache.org/licenses/LICENSE-2.0, or another agreement *
* between Ultraleap and you, your company or other organization. *
******************************************************************************/
namespace Leap
{
using System;
/// <summary>
/// The Matrix struct represents a transformation matrix.
///
/// To use this struct to transform a Vector, construct a matrix containing the
/// desired transformation and then use the Matrix::transformPoint() or
/// Matrix.TransformDirection() functions to apply the transform.
///
/// Transforms can be combined by multiplying two or more transform matrices using
/// the * operator.
/// @since 1.0
/// </summary>
public struct Matrix
{
/// <summary>
/// Multiply two matrices.
/// </summary>
public static Matrix operator *(Matrix m1, Matrix m2)
{
return m1._operator_mul(m2);
}
/// <summary>
/// Copy this matrix to the specified array of 9 float values in row-major order.
/// </summary>
public float[] ToArray3x3(float[] output)
{
output[0] = xBasis.x;
output[1] = xBasis.y;
output[2] = xBasis.z;
output[3] = yBasis.x;
output[4] = yBasis.y;
output[5] = yBasis.z;
output[6] = zBasis.x;
output[7] = zBasis.y;
output[8] = zBasis.z;
return output;
}
/// <summary>
/// Copy this matrix to the specified array containing 9 double values in row-major order.
/// </summary>
public double[] ToArray3x3(double[] output)
{
output[0] = xBasis.x;
output[1] = xBasis.y;
output[2] = xBasis.z;
output[3] = yBasis.x;
output[4] = yBasis.y;
output[5] = yBasis.z;
output[6] = zBasis.x;
output[7] = zBasis.y;
output[8] = zBasis.z;
return output;
}
/// <summary>
/// Convert this matrix to an array containing 9 float values in row-major order.
/// </summary>
public float[] ToArray3x3()
{
return ToArray3x3(new float[9]);
}
/// <summary>
/// Copy this matrix to the specified array of 16 float values in row-major order.
/// </summary>
public float[] ToArray4x4(float[] output)
{
output[0] = xBasis.x;
output[1] = xBasis.y;
output[2] = xBasis.z;
output[3] = 0.0f;
output[4] = yBasis.x;
output[5] = yBasis.y;
output[6] = yBasis.z;
output[7] = 0.0f;
output[8] = zBasis.x;
output[9] = zBasis.y;
output[10] = zBasis.z;
output[11] = 0.0f;
output[12] = origin.x;
output[13] = origin.y;
output[14] = origin.z;
output[15] = 1.0f;
return output;
}
/// <summary>
/// Copy this matrix to the specified array of 16 double values in row-major order.
/// </summary>
public double[] ToArray4x4(double[] output)
{
output[0] = xBasis.x;
output[1] = xBasis.y;
output[2] = xBasis.z;
output[3] = 0.0f;
output[4] = yBasis.x;
output[5] = yBasis.y;
output[6] = yBasis.z;
output[7] = 0.0f;
output[8] = zBasis.x;
output[9] = zBasis.y;
output[10] = zBasis.z;
output[11] = 0.0f;
output[12] = origin.x;
output[13] = origin.y;
output[14] = origin.z;
output[15] = 1.0f;
return output;
}
/// <summary>
/// Convert this matrix to an array containing 16 float values in row-major order.
/// </summary>
public float[] ToArray4x4()
{
return ToArray4x4(new float[16]);
}
/// <summary>
/// Constructs a copy of the specified Matrix object.
/// @since 1.0
/// </summary>
public Matrix(Matrix other) :
this()
{
xBasis = other.xBasis;
yBasis = other.yBasis;
zBasis = other.zBasis;
origin = other.origin;
}
/// <summary>
/// Constructs a transformation matrix from the specified basis vectors.
/// @since 1.0
/// </summary>
public Matrix(Vector xBasis, Vector yBasis, Vector zBasis) :
this()
{
this.xBasis = xBasis;
this.yBasis = yBasis;
this.zBasis = zBasis;
this.origin = Vector.Zero;
}
/// <summary>
/// Constructs a transformation matrix from the specified basis and translation vectors.
/// @since 1.0
/// </summary>
public Matrix(Vector xBasis, Vector yBasis, Vector zBasis, Vector origin) :
this()
{
this.xBasis = xBasis;
this.yBasis = yBasis;
this.zBasis = zBasis;
this.origin = origin;
}
/// <summary>
/// Constructs a transformation matrix specifying a rotation around the specified vector.
/// @since 1.0
/// </summary>
public Matrix(Vector axis, float angleRadians) :
this()
{
xBasis = Vector.XAxis;
yBasis = Vector.YAxis;
zBasis = Vector.ZAxis;
origin = Vector.Zero;
SetRotation(axis, angleRadians);
}
/// <summary>
/// Constructs a transformation matrix specifying a rotation around the specified vector
/// and a translation by the specified vector.
/// @since 1.0
/// </summary>
public Matrix(Vector axis, float angleRadians, Vector translation) :
this()
{
xBasis = Vector.XAxis;
yBasis = Vector.YAxis;
zBasis = Vector.ZAxis;
origin = translation;
this.SetRotation(axis, angleRadians);
}
public Matrix(float m00,
float m01,
float m02,
float m10,
float m11,
float m12,
float m20,
float m21,
float m22) :
this()
{
xBasis = new Vector(m00, m01, m02);
yBasis = new Vector(m10, m11, m12);
zBasis = new Vector(m20, m21, m22);
origin = Vector.Zero;
}
public Matrix(float m00,
float m01,
float m02,
float m10,
float m11,
float m12,
float m20,
float m21,
float m22,
float m30,
float m31,
float m32) :
this()
{
xBasis = new Vector(m00, m01, m02);
yBasis = new Vector(m10, m11, m12);
zBasis = new Vector(m20, m21, m22);
origin = new Vector(m30, m31, m32);
}
/// <summary>
/// Sets this transformation matrix to represent a rotation around the specified vector.
///
/// This function erases any previous rotation and scale transforms applied
/// to this matrix, but does not affect translation.
///
/// @since 1.0
/// </summary>
public void SetRotation(Vector axis, float angleRadians)
{
Vector n = axis.Normalized;
float s = (float)Math.Sin(angleRadians);
float c = (float)Math.Cos(angleRadians);
float C = (1 - c);
xBasis = new Vector(n[0] * n[0] * C + c, n[0] * n[1] * C - n[2] * s, n[0] * n[2] * C + n[1] * s);
yBasis = new Vector(n[1] * n[0] * C + n[2] * s, n[1] * n[1] * C + c, n[1] * n[2] * C - n[0] * s);
zBasis = new Vector(n[2] * n[0] * C - n[1] * s, n[2] * n[1] * C + n[0] * s, n[2] * n[2] * C + c);
}
/// <summary>
/// Transforms a vector with this matrix by transforming its rotation,
/// scale, and translation.
///
/// Translation is applied after rotation and scale.
///
/// @since 1.0
/// </summary>
public Vector TransformPoint(Vector point)
{
return xBasis * point.x + yBasis * point.y + zBasis * point.z + origin;
}
/// <summary>
/// Transforms a vector with this matrix by transforming its rotation and
/// scale only.
/// @since 1.0
/// </summary>
public Vector TransformDirection(Vector direction)
{
return xBasis * direction.x + yBasis * direction.y + zBasis * direction.z;
}
/// <summary>
/// Performs a matrix inverse if the matrix consists entirely of rigid
/// transformations (translations and rotations). If the matrix is not rigid,
/// this operation will not represent an inverse.
///
/// Note that all matrices that are directly returned by the API are rigid.
///
/// @since 1.0
/// </summary>
public Matrix RigidInverse()
{
Matrix rotInverse = new Matrix(new Vector(xBasis[0], yBasis[0], zBasis[0]),
new Vector(xBasis[1], yBasis[1], zBasis[1]),
new Vector(xBasis[2], yBasis[2], zBasis[2]));
rotInverse.origin = rotInverse.TransformDirection(-origin);
return rotInverse;
}
/// <summary>
/// Multiply transform matrices.
/// Combines two transformations into a single equivalent transformation.
/// @since 1.0
/// </summary>
private Matrix _operator_mul(Matrix other)
{
return new Matrix(TransformDirection(other.xBasis),
TransformDirection(other.yBasis),
TransformDirection(other.zBasis),
TransformPoint(other.origin));
}
/// <summary>
/// Compare Matrix equality component-wise.
/// @since 1.0
/// </summary>
public bool Equals(Matrix other)
{
return xBasis == other.xBasis &&
yBasis == other.yBasis &&
zBasis == other.zBasis &&
origin == other.origin;
}
/// <summary>
/// Write the matrix to a string in a human readable format.
/// </summary>
public override string ToString()
{
return string.Format("xBasis: {0} yBasis: {1} zBasis: {2} origin: {3}", xBasis, yBasis, zBasis, origin);
}
/// <summary>
/// The basis vector for the x-axis.
/// @since 1.0
/// </summary>
public Vector xBasis { get; set; }
/// <summary>
/// The basis vector for the y-axis.
/// @since 1.0
/// </summary>
public Vector yBasis { get; set; }
/// <summary>
/// The basis vector for the z-axis.
/// @since 1.0
/// </summary>
public Vector zBasis { get; set; }
/// <summary>
/// The translation factors for all three axes.
/// @since 1.0
/// </summary>
public Vector origin { get; set; }
/// <summary>
/// Returns the identity matrix specifying no translation, rotation, and scale.
/// @since 1.0
/// </summary>
public static readonly Matrix Identity = new Matrix(Vector.XAxis, Vector.YAxis, Vector.ZAxis, Vector.Zero);
}
}

View file

@ -0,0 +1,190 @@
/******************************************************************************
* Copyright (C) Ultraleap, Inc. 2011-2021. *
* *
* Use subject to the terms of the Apache License 2.0 available at *
* http://www.apache.org/licenses/LICENSE-2.0, or another agreement *
* between Ultraleap and you, your company or other organization. *
******************************************************************************/
using AOT;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Runtime.InteropServices;
namespace LeapInternal
{
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate IntPtr Allocate(UInt32 size, eLeapAllocatorType typeHint, IntPtr state);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate void Deallocate(IntPtr buffer, IntPtr state);
public static class MemoryManager
{
/// <summary>
/// Specifies whether or not a pooling strategy should be used for the
/// internal MemoryManager. If enabled, memory will be periodically
/// recycled to be used again instead of being deallocated.
///
/// An object may be reclaimed from the pool at any time on the
/// worker thread. If you are running into issues where an object
/// you are working with is being overwritten, consider making a copy,
/// or turning up the MinPoolSize.
/// </summary>
public static bool EnablePooling = true;
/// <summary>
/// Specifies how many objects of a specific type need to be in the pool
/// before they will start to be recycled. Turning this number up can
/// help prevent issues where objects you are working with are being
/// overwritten with new objects. Turning this number down can reduce
/// the total memory footprint used by the memory manager.
/// </summary>
public static uint MinPoolSize = 64;
private static ConcurrentDictionary<IntPtr, ActiveMemoryInfo> _activeMemory =
new ConcurrentDictionary<IntPtr, ActiveMemoryInfo>();
private static ConcurrentDictionary<PoolKey, Queue<object>> _pooledMemory =
new ConcurrentDictionary<PoolKey, Queue<object>>();
[MonoPInvokeCallback(typeof(Allocate))]
public static IntPtr Pin(UInt32 size, eLeapAllocatorType typeHint, IntPtr state)
{
try
{
//Construct a key to identify the desired allocation
PoolKey key = new PoolKey()
{
type = typeHint,
size = size
};
//Attempt to find the pool that holds this type of allocation
Queue<object> pool;
if (!_pooledMemory.TryGetValue(key, out pool))
{
//Construct a new pool if none exists yet
pool = new Queue<object>();
_pooledMemory[key] = pool;
}
//Attempt to get an object from the pool
object memory;
if (EnablePooling && pool.Count > MinPoolSize)
{
memory = pool.Dequeue();
}
else
{
//If the pool is empty, we need to construct a new object
switch (typeHint)
{
default:
case eLeapAllocatorType.eLeapAllocatorType_Uint8:
memory = new byte[size];
break;
case eLeapAllocatorType.eLeapAllocatorType_Float:
memory = new float[(size + sizeof(float) - 1) / sizeof(float)];
break;
}
}
//Pin the object so its address will not change
GCHandle handle = GCHandle.Alloc(memory, GCHandleType.Pinned);
IntPtr ptr = handle.AddrOfPinnedObject();
//Put the information about the newly pinned allocation into the
//active memory map so it can be retrieved and freed layer.
_activeMemory.TryAdd(ptr, new ActiveMemoryInfo()
{
handle = handle,
key = key
});
return ptr;
}
catch (Exception e)
{
UnityEngine.Debug.LogException(e);
}
return IntPtr.Zero;
}
[MonoPInvokeCallback(typeof(Deallocate))]
public static void Unpin(IntPtr ptr, IntPtr state)
{
try
{
//Grab the info for the given pointer
ActiveMemoryInfo info = _activeMemory[ptr];
//First we return the object back to its pool
if (EnablePooling)
{
_pooledMemory[info.key].Enqueue(info.handle.Target);
}
//Then we remove the pointer from the active memory map
ActiveMemoryInfo value;
_activeMemory.TryRemove(ptr, out value);
//Finally we unpin the memory
info.handle.Free();
}
catch (Exception e)
{
UnityEngine.Debug.LogException(e);
}
}
public static object GetPinnedObject(IntPtr ptr)
{
try
{
return _activeMemory[ptr].handle.Target;
}
catch (Exception) { }
return null;
}
private struct PoolKey : IEquatable<PoolKey>
{
public eLeapAllocatorType type;
public UInt32 size;
public override int GetHashCode()
{
return (int)type | (int)size << 4;
}
public bool Equals(PoolKey other)
{
return type == other.type &&
size == other.size;
}
public override bool Equals(object obj)
{
if (obj is PoolKey)
{
return Equals((PoolKey)obj);
}
else
{
return false;
}
}
}
private struct ActiveMemoryInfo
{
public GCHandle handle;
public PoolKey key;
}
}
}

View file

@ -0,0 +1,24 @@
/******************************************************************************
* Copyright (C) Ultraleap, Inc. 2011-2021. *
* *
* Use subject to the terms of the Apache License 2.0 available at *
* http://www.apache.org/licenses/LICENSE-2.0, or another agreement *
* between Ultraleap and you, your company or other organization. *
******************************************************************************/
namespace Leap
{
/// <summary>
/// Reports whether the message is for
/// a severe failure, a recoverable warning, or a status change.
/// @since 3.0
/// </summary>
public enum MessageSeverity
{
MESSAGE_UNKNOWN = 0,
MESSAGE_CRITICAL = 1,
MESSAGE_WARNING = 2,
/** A verbose, informational message */
MESSAGE_INFORMATION = 3
}
}

View file

@ -0,0 +1,19 @@
/******************************************************************************
* Copyright (C) Ultraleap, Inc. 2011-2021. *
* *
* Use subject to the terms of the Apache License 2.0 available at *
* http://www.apache.org/licenses/LICENSE-2.0, or another agreement *
* between Ultraleap and you, your company or other organization. *
******************************************************************************/
namespace Leap
{
public struct PointMapping
{
public long frameId;
public long timestamp;
public Vector[] points;
public uint[] ids;
}
}

View file

@ -0,0 +1,92 @@
/******************************************************************************
* Copyright (C) Ultraleap, Inc. 2011-2021. *
* *
* Use subject to the terms of the Apache License 2.0 available at *
* http://www.apache.org/licenses/LICENSE-2.0, or another agreement *
* between Ultraleap and you, your company or other organization. *
******************************************************************************/
using System;
using System.Runtime.InteropServices;
namespace LeapInternal
{
/**
* A helper class to marshal between unmanaged memory and structs without creating garbage.
*/
public static class StructMarshal<T> where T : struct
{
#if !ENABLE_IL2CPP
[StructLayout(LayoutKind.Sequential)]
private class StructContainer
{
public T value;
}
[ThreadStatic]
private static StructContainer _container;
#endif
private static int _sizeofT;
static StructMarshal()
{
_sizeofT = Marshal.SizeOf(typeof(T));
}
/**
* Returns the size in bytes of the struct of type T. This call is equivalent to
* Marshal.Sizeof(typeof(T)) but caches the result for ease of access.
*/
public static int Size
{
get
{
return _sizeofT;
}
}
/**
* Converts an IntPtr to a struct of type T.
*/
public static void PtrToStruct(IntPtr ptr, out T t)
{
#if ENABLE_IL2CPP
#if UNITY_2018_1_OR_NEWER
unsafe {
Unity.Collections.LowLevel.Unsafe.UnsafeUtility.CopyPtrToStructure((void*)ptr, out t);
}
#else
#error UnityModules Only supports IL2CPP on versions of Unity 2018.1 or greater.
#endif
#else
if (_container == null)
{
_container = new StructContainer();
}
try
{
Marshal.PtrToStructure(ptr, _container);
t = _container.value;
}
catch (Exception e)
{
UnityEngine.Debug.LogException(e);
t = default(T);
}
#endif
}
/**
* Converts a single element in an array pointed to by ptr to a struct
* of type T. This method does not and cannot do any bounds checking!
* This method does not create any garbage.
*/
public static void ArrayElementToStruct(IntPtr ptr, int arrayIndex, out T t)
{
PtrToStruct(new IntPtr(ptr.ToInt64() + _sizeofT * arrayIndex), out t);
}
}
}

View file

@ -0,0 +1,176 @@
/******************************************************************************
* Copyright (C) Ultraleap, Inc. 2011-2021. *
* *
* Use subject to the terms of the Apache License 2.0 available at *
* http://www.apache.org/licenses/LICENSE-2.0, or another agreement *
* between Ultraleap and you, your company or other organization. *
******************************************************************************/
namespace Leap
{
using System;
public static class TransformExtensions
{
/**
* Does an in-place rigid transformation of a Frame.
*
* @param transform A LeapTransform containing the desired translation, rotation, and scale
* to be applied to the Frame.
*/
public static Frame Transform(this Frame frame, LeapTransform transform)
{
for (int i = frame.Hands.Count; i-- != 0;)
{
frame.Hands[i].Transform(transform);
}
return frame;
}
/**
* Returns a new frame that is a copy of a frame, with an additional rigid
* transformation applied to it.
*
* @param transform The transformation to be applied to the copied frame.
*/
public static Frame TransformedCopy(this Frame frame, LeapTransform transform)
{
return new Frame().CopyFrom(frame).Transform(transform);
}
/**
* Does an in-place rigid transformation of a Hand.
*
* @param transform A LeapTransform containing the desired translation, rotation, and scale
* to be applied to the Hand.
*/
public static Hand Transform(this Hand hand, LeapTransform transform)
{
hand.PalmPosition = transform.TransformPoint(hand.PalmPosition);
hand.StabilizedPalmPosition = transform.TransformPoint(hand.StabilizedPalmPosition);
hand.PalmVelocity = transform.TransformVelocity(hand.PalmVelocity);
hand.PalmNormal = transform.TransformDirection(hand.PalmNormal);
hand.Direction = transform.TransformDirection(hand.Direction);
hand.WristPosition = transform.TransformPoint(hand.WristPosition);
hand.PalmWidth *= Math.Abs(transform.scale.x);
hand.Rotation = transform.TransformQuaternion(hand.Rotation);
hand.Arm.Transform(transform);
for (int i = 5; i-- != 0;)
{
hand.Fingers[i].Transform(transform);
}
return hand;
}
/**
* Returns a new hand that is a copy of a hand, with an additional rigid
* transformation applied to it.
*
* @param transform The transformation to be applied to the copied hand.
*/
public static Hand TransformedCopy(this Hand hand, LeapTransform transform)
{
return new Hand().CopyFrom(hand).Transform(transform);
}
/**
* Does an in-place rigid transformation of a Finger.
*
* @param transform A LeapTransform containing the desired translation, rotation, and scale
* to be applied to the Finger.
*/
public static Finger Transform(this Finger finger, LeapTransform transform)
{
Bone nextBone = finger.bones[3];
nextBone.NextJoint = transform.TransformPoint(nextBone.NextJoint);
finger.TipPosition = nextBone.NextJoint;
for (int i = 3; i-- != 0;)
{
Bone bone = finger.bones[i];
bone.NextJoint = nextBone.PrevJoint = transform.TransformPoint(bone.NextJoint);
nextBone.TransformGivenJoints(transform);
nextBone = bone;
}
nextBone.PrevJoint = transform.TransformPoint(nextBone.PrevJoint);
nextBone.TransformGivenJoints(transform);
finger.Direction = finger.bones[2].Direction;
finger.Width *= Math.Abs(transform.scale.x);
finger.Length *= Math.Abs(transform.scale.z);
return finger;
}
/**
* Returns a new finger that is a copy of a finger, with an additional rigid
* transformation applied to it.
*
* @param transform The transformation to be applied to the copied finger.
*/
public static Finger TransformedCopy(this Finger finger, LeapTransform transform)
{
return new Finger().CopyFrom(finger).Transform(transform);
}
/**
* Does an in-place rigid transformation of a Bone.
*
* @param transform A LeapTransform containing the desired translation, rotation, and scale
- * to be applied to the bone.
*/
public static Bone Transform(this Bone bone, LeapTransform transform)
{
bone.PrevJoint = transform.TransformPoint(bone.PrevJoint);
bone.NextJoint = transform.TransformPoint(bone.NextJoint);
bone.TransformGivenJoints(transform);
return bone;
}
/**
* Does an in-place rigid transformation of a Bone, assuming the joints have already been transformed.
*
* @param transform A LeapTransform containing the desired translation, rotation, and scale
- * to be applied to the bone.
*/
internal static void TransformGivenJoints(this Bone bone, LeapTransform transform)
{
bone.Length *= Math.Abs(transform.scale.z);
bone.Center = (bone.PrevJoint + bone.NextJoint) / 2.0f;
if (bone.Length < float.Epsilon)
{
bone.Direction = Vector.Zero;
}
else
{
bone.Direction = (bone.NextJoint - bone.PrevJoint) / bone.Length;
}
bone.Width *= Math.Abs(transform.scale.x);
bone.Rotation = transform.TransformQuaternion(bone.Rotation);
}
/**
* Returns a new bone that is a copy of a bone, with an additional rigid
* transformation applied to it.
*
* @param transform The transformation to be applied to the copied bone.
*/
public static Bone TransformedCopy(this Bone bone, LeapTransform transform)
{
return new Bone().CopyFrom(bone).Transform(transform);
}
}
}

425
ml_lme_cvr/vendor/LeapCSharp/Vector.cs vendored Normal file
View file

@ -0,0 +1,425 @@
/******************************************************************************
* Copyright (C) Ultraleap, Inc. 2011-2021. *
* *
* Use subject to the terms of the Apache License 2.0 available at *
* http://www.apache.org/licenses/LICENSE-2.0, or another agreement *
* between Ultraleap and you, your company or other organization. *
******************************************************************************/
namespace Leap
{
using System;
/// <summary>
/// Constants used in Leap Motion math functions.
/// </summary>
public static class Constants
{
public const float PI = 3.1415926536f;
public const float DEG_TO_RAD = 0.0174532925f;
public const float RAD_TO_DEG = 57.295779513f;
public const float EPSILON = 1.192092896e-07f;
}
/// <summary>
/// The Vector struct represents a three-component mathematical vector or point
/// such as a direction or position in three-dimensional space.
///
/// The Leap Motion software employs a right-handed Cartesian coordinate system.
/// Values given are in units of real-world millimeters. The origin is centered
/// at the center of the Leap Motion Controller. The x- and z-axes lie in the horizontal
/// plane, with the x-axis running parallel to the long edge of the device.
/// The y-axis is vertical, with positive values increasing upwards (in contrast
/// to the downward orientation of most computer graphics coordinate systems).
/// The z-axis has positive values increasing away from the computer screen.
/// @since 1.0
/// </summary>
[Serializable]
public struct Vector : IEquatable<Vector>
{
public static Vector operator +(Vector v1, Vector v2)
{
return new Vector(v1.x + v2.x, v1.y + v2.y, v1.z + v2.z);
}
public static Vector operator -(Vector v1, Vector v2)
{
return new Vector(v1.x - v2.x, v1.y - v2.y, v1.z - v2.z);
}
public static Vector operator *(Vector v1, float scalar)
{
return new Vector(v1.x * scalar, v1.y * scalar, v1.z * scalar);
}
public static Vector operator *(float scalar, Vector v1)
{
return new Vector(v1.x * scalar, v1.y * scalar, v1.z * scalar);
}
public static Vector operator /(Vector v1, float scalar)
{
return new Vector(v1.x / scalar, v1.y / scalar, v1.z / scalar);
}
public static Vector operator -(Vector v1)
{
return new Vector(-v1.x, -v1.y, -v1.z);
}
public static bool operator ==(Vector v1, Vector v2)
{
return v1.Equals(v2);
}
public static bool operator !=(Vector v1, Vector v2)
{
return !v1.Equals(v2);
}
public float[] ToFloatArray()
{
return new float[] { x, y, z };
}
/// <summary>
/// Creates a new Vector with the specified component values.
/// @since 1.0
/// </summary>
public Vector(float x, float y, float z) :
this()
{
this.x = x;
this.y = y;
this.z = z;
}
/// <summary>
/// Copies the specified Vector.
/// @since 1.0
/// </summary>
public Vector(Vector vector) :
this()
{
x = vector.x;
y = vector.y;
z = vector.z;
}
/// <summary>
/// The distance between the point represented by this Vector
/// object and a point represented by the specified Vector object.
///
/// @since 1.0
/// </summary>
public float DistanceTo(Vector other)
{
return (float)Math.Sqrt((x - other.x) * (x - other.x) +
(y - other.y) * (y - other.y) +
(z - other.z) * (z - other.z));
}
/// <summary>
/// The angle between this vector and the specified vector in radians.
///
/// The angle is measured in the plane formed by the two vectors. The
/// angle returned is always the smaller of the two conjugate angles.
/// Thus A.angleTo(B) == B.angleTo(A) and is always a positive
/// value less than or equal to pi radians (180 degrees).
///
/// If either vector has zero length, then this function returns zero.
/// @since 1.0
/// </summary>
public float AngleTo(Vector other)
{
float denom = MagnitudeSquared * other.MagnitudeSquared;
if (denom <= Constants.EPSILON)
{
return 0.0f;
}
float val = Dot(other) / (float)Math.Sqrt(denom);
if (val >= 1.0f)
{
return 0.0f;
}
else if (val <= -1.0f)
{
return Constants.PI;
}
return (float)Math.Acos(val);
}
/// <summary>
/// The dot product of this vector with another vector.
///
/// The dot product is the magnitude of the projection of this vector
/// onto the specified vector.
/// @since 1.0
/// </summary>
public float Dot(Vector other)
{
return (x * other.x) + (y * other.y) + (z * other.z);
}
/// <summary>
/// The cross product of this vector and the specified vector.
///
/// The cross product is a vector orthogonal to both original vectors.
/// It has a magnitude equal to the area of a parallelogram having the
/// two vectors as sides. The direction of the returned vector is
/// determined by the right-hand rule. Thus A.cross(B) == -B.cross(A).
///
/// @since 1.0
/// </summary>
public Vector Cross(Vector other)
{
return new Vector((y * other.z) - (z * other.y),
(z * other.x) - (x * other.z),
(x * other.y) - (y * other.x));
}
/// <summary>
/// Returns a string containing this vector in a human readable format: (x, y, z).
/// @since 1.0
/// </summary>
public override string ToString()
{
return "(" + x + ", " + y + ", " + z + ")";
}
/// <summary>
/// Compare Vector equality component-wise.
/// @since 1.0
/// </summary>
public bool Equals(Vector v)
{
return x.NearlyEquals(v.x) && y.NearlyEquals(v.y) && z.NearlyEquals(v.z);
}
public override bool Equals(Object obj)
{
return obj is Vector && Equals((Vector)obj);
}
/// <summary>
/// Returns true if all of the vector's components are finite. If any
/// component is NaN or infinite, then this returns false.
/// @since 1.0
/// </summary>
public bool IsValid()
{
return !(float.IsNaN(x) || float.IsInfinity(x) ||
float.IsNaN(y) || float.IsInfinity(y) ||
float.IsNaN(z) || float.IsInfinity(z));
}
/// <summary>
/// Index vector components numerically.
/// Index 0 is x, index 1 is y, and index 2 is z.
/// @since 1.0
/// </summary>
public float this[uint index]
{
get
{
if (index == 0)
return x;
if (index == 1)
return y;
if (index == 2)
return z;
throw new IndexOutOfRangeException();
}
set
{
if (index == 0)
x = value;
if (index == 1)
y = value;
if (index == 2)
z = value;
throw new IndexOutOfRangeException();
}
}
public float x;
public float y;
public float z;
/// <summary>
/// The magnitude, or length, of this vector.
///
/// The magnitude is the L2 norm, or Euclidean distance between the origin and
/// the point represented by the (x, y, z) components of this Vector object.
/// @since 1.0
/// </summary>
public float Magnitude
{
get { return (float)Math.Sqrt(x * x + y * y + z * z); }
}
/// <summary>
/// The square of the magnitude, or length, of this vector.
/// @since 1.0
/// </summary>
public float MagnitudeSquared
{
get { return x * x + y * y + z * z; }
}
/// <summary>
/// The pitch angle in radians.
///
/// Pitch is the angle between the negative z-axis and the projection of
/// the vector onto the y-z plane. In other words, pitch represents rotation
/// around the x-axis.
/// If the vector points upward, the returned angle is between 0 and pi radians
/// (180 degrees); if it points downward, the angle is between 0 and -pi radians.
///
/// @since 1.0
/// </summary>
public float Pitch
{
get { return (float)Math.Atan2(y, -z); }
}
/// <summary>
/// The roll angle in radians.
///
/// Roll is the angle between the y-axis and the projection of
/// the vector onto the x-y plane. In other words, roll represents rotation
/// around the z-axis. If the vector points to the left of the y-axis,
/// then the returned angle is between 0 and pi radians (180 degrees);
/// if it points to the right, the angle is between 0 and -pi radians.
///
/// Use this function to get roll angle of the plane to which this vector is a
/// normal. For example, if this vector represents the normal to the palm,
/// then this function returns the tilt or roll of the palm plane compared
/// to the horizontal (x-z) plane.
///
/// @since 1.0
/// </summary>
public float Roll
{
get { return (float)Math.Atan2(x, -y); }
}
/// <summary>
/// The yaw angle in radians.
///
/// Yaw is the angle between the negative z-axis and the projection of
/// the vector onto the x-z plane. In other words, yaw represents rotation
/// around the y-axis. If the vector points to the right of the negative z-axis,
/// then the returned angle is between 0 and pi radians (180 degrees);
/// if it points to the left, the angle is between 0 and -pi radians.
///
/// @since 1.0
/// </summary>
public float Yaw
{
get { return (float)Math.Atan2(x, -z); }
}
/// <summary>
/// A normalized copy of this vector.
///
/// A normalized vector has the same direction as the original vector,
/// but with a length of one.
///
/// @since 1.0
/// </summary>
public Vector Normalized
{
get
{
float denom = MagnitudeSquared;
if (denom <= Constants.EPSILON)
{
return Zero;
}
denom = 1.0f / (float)Math.Sqrt(denom);
return new Vector(x * denom, y * denom, z * denom);
}
}
/// <summary>
/// The zero vector: (0, 0, 0)
/// </summary>
public static readonly Vector Zero = new Vector(0, 0, 0);
/// <summary>
/// The ones vector: (1, 1, 1)
/// </summary>
public static readonly Vector Ones = new Vector(1, 1, 1);
/// <summary>
/// The x-axis unit vector: (1, 0, 0)
/// </summary>
public static readonly Vector XAxis = new Vector(1, 0, 0);
/// <summary>
/// The y-axis unit vector: (0, 1, 0)
/// </summary>
public static readonly Vector YAxis = new Vector(0, 1, 0);
/// <summary>
/// The z-axis unit vector: (0, 0, 1)
/// </summary>
public static readonly Vector ZAxis = new Vector(0, 0, 1);
/// <summary>
/// The unit vector pointing forward along the negative z-axis: (0, 0, -1)
/// </summary>
public static readonly Vector Forward = new Vector(0, 0, -1);
/// <summary>
/// The unit vector pointing backward along the positive z-axis: (0, 0, 1)
/// </summary>
public static readonly Vector Backward = new Vector(0, 0, 1);
/// <summary>
/// The unit vector pointing left along the negative x-axis: (-1, 0, 0)
/// </summary>
public static readonly Vector Left = new Vector(-1, 0, 0);
/// <summary>
/// The unit vector pointing right along the positive x-axis: (1, 0, 0)
/// </summary>
public static readonly Vector Right = new Vector(1, 0, 0);
/// <summary>
/// The unit vector pointing up along the positive y-axis: (0, 1, 0)
/// </summary>
public static readonly Vector Up = new Vector(0, 1, 0);
/// <summary>
/// The unit vector pointing down along the negative y-axis: (0, -1, 0)
/// </summary>
public static readonly Vector Down = new Vector(0, -1, 0);
public static Vector Lerp(Vector a, Vector b, float t)
{
return new Vector(
a.x + t * (b.x - a.x),
a.y + t * (b.y - a.y),
a.z + t * (b.z - a.z)
);
}
public override int GetHashCode()
{
unchecked // Overflow is fine, just wrap
{
int hash = 17;
hash = hash * 23 + x.GetHashCode();
hash = hash * 23 + y.GetHashCode();
hash = hash * 23 + z.GetHashCode();
return hash;
}
}
}
}

388
ml_lme_cvr/vendor/LeapSDK/LICENSE.md vendored Normal file
View file

@ -0,0 +1,388 @@
ULTRALEAP TRACKING SDK AGREEMENT
Updated: 26 October 2021
Permitted uses
This SDK Agreement (“Agreement”) covers use of the Ultraleap hand tracking SDK (the “SDK”) by
individuals and businesses for the following purposes:
1. Your personal, non-commercial use (for the avoidance of doubt, excluding use for the design or
manufacture of a commercial or distributable product (e.g in design studios)); or
2. Commercial use for the development and sale consumer facing games, made available for sale to
be purchased by consumers for personal use either at retail or through app stores (excluding,
without limitation, location-based entertainment and arcade applications); or
3. Demonstration of your application to internal and external stakeholders and customers where
there is no transaction, no sale of tickets specifically for the application, or any other form of
compensation for you or your organisation,
but in all cases excluding applications relating to the following: (a) the production of or trade in tobacco,
alcoholic beverages, and related products, (b) the production or trade in weapons of any kind or any
military applications, (c) casinos, gambling and equivalent enterprises, (d) human cloning, human
embryos, or stem cells, or (e) nuclear energy.
Any other uses, or applications using third party hardware are “Specialised Applications” and will require
a separate license agreement. Please contact Ultraleap info@ultraleap.com for more information.
In each case, the SDK may only be used with Ultraleap Hardware and Ultraleap Software.
1. Parties
1.1. This Agreement is made between the individual or entity (“you” or the “Developer”) that accepts
it and Ultraleap Limited (“Ultraleap”). You accept this Agreement by (a) accepting it on download
of the SDK, or (b) if you use or access the SDK or any part of the SDK. Your entry into this
Agreement also binds your authorized users, and your company or organisation.
1.2. If you do not agree to the terms of this Agreement you must not use the SDK.
1.3. Capitalized terms bear the meanings given in the “Definitions” section of this Agreement.
1.4. This Agreement incorporates the terms of the Ultraleap Hand Tracking End User License
Agreement (“EULA”), which is available at https://developer.leapmotion.com/end-user-license-
agreement or from Ultraleap on request. In the event of a conflict between these terms and the
EULA, these terms will prevail.
2. License
Development License
2.1. Conditional on your compliance with the terms and conditions of this Agreement, Ultraleap
hereby grants you a limited, non-exclusive, personal, revocable, non-sublicensable, and non-
transferable license to:
2.1.1. install and use a reasonable number of copies of the SDK on computers owned or
controlled by you for the purpose of developing and testing applications that (a) are not
Specialised Applications and (b) are intended for use solely in connection with Ultraleap
Hardware and Ultraleap Software (each being an “Ultraleap Enabled Application”); and
2.1.2. modify and incorporate into your Ultraleap Enabled Application any sample code
provided in the SDK.
Distribution License
2.2. Conditional on your compliance with the terms and conditions of this Agreement, Ultraleap
hereby grants you a limited, non-exclusive, personal, revocable, non-transferrable license of
Ultraleaps intellectual property rights to the extent necessary to:
2.2.1. copy and distribute (or have copied and distributed) the Ultraleap Redistributables,
solely as compiled with, incorporated into, or packaged with, your Ultraleap Enabled
Application; and
2.2.2. to make (but not have made), use, sell, offer for sale, and import your Ultraleap Enabled
Application.
3. Restrictions
3.1. The license granted to you in section 2.1 and section 2.2 is subject to the following restrictions,
as well as others listed in this Agreement:
3.1.1. Except as expressly permitted in section 2.1, (a) you may not publish, distribute, or copy
the SDK, and (b) you may not modify or create derivative works of the SDK;
3.1.2. Except as expressly permitted in section 2.2, you may not, and may not allow any third
party, directly or indirectly, to publish, post, or otherwise make available, the Ultraleap
Redistributables;
3.1.3. You may not, and may not enable others to, distributed the Non-Redistributable
Materials;
3.1.4. You may use the SDK solely in connection with Ultraleap Hardware and/or Ultraleap
Software;
3.1.5. You may not use the SDK to create, or aid in the creation, directly or indirectly, of any
software or hardware which provides hand tracking functionality or which is otherwise
substantially similar to the features or functionality of Ultraleap products;
3.1.6. You may not, and may not enable others to, directly or indirectly, reverse engineer,
decompile, disassemble, or otherwise attempt to reconstruct, identify, or discover any
source code, underlying ideas, techniques, or algorithms in the Ultraleap Software, the
Ultraleap Hardware, or any software which forms part of the SDK, nor attempt to
circumvent any related security measures (except as and only to the extent any
foregoing restriction is prohibited by applicable law notwithstanding the foregoing
restriction, or to the extent as may be permitted by licensing terms governing the use of
any open source software components or sample code contained within the SDK;
3.1.7. You may not remove, obscure, or alter any proprietary rights or confidentiality notices
within the SDK or any software, documentation, or other materials in it or supplied with
it;
3.1.8. You must not allow the Ultraleap Software or SDK to fall under the terms of any license
which would obligate you or Ultraleap to make available or publish any part of the
Ultraleap Software or SDK.
3.1.9. You may not create Ultraleap Enabled Applications or other software that prevent or
degrade the interaction of applications developed by others with the Ultraleap Software;
3.1.10. You may not represent functionality provided by any Ultraleap hardware or software as
your technology or the technology of any third party. For example (without limitation)
you may not describe any application, technology, or feature developed or distributed
by you that incorporates Ultraleap technology as your gesture or touchless control
technology without providing attribution to Ultraleap; and
3.1.11. You may not allow your Ultraleap Enabled Application to be used for a High Risk Use.
4. Updates
4.1. The terms of this Agreement will apply to any Updates which Ultraleap (in its sole discretion)
makes available to you. You agree that Updates may require you to change or update your
Ultraleap Enabled Application, and may affect your ability to use, access, or interact with the
Ultraleap Software, the Ultraleap Hardware, and/or the SDK. You are solely responsible for
turning off any auto-update functionality of the Ultraleap Software.
5. Trademarks and Marketing
5.1. Conditioned upon compliance with the terms and conditions of this Agreement, Ultraleap grants
you a limited, non-exclusive, personal, license to reproduce and use Ultraleap trademarks solely
to (a) mark the Ultraleap Enabled Application, (b) produce and make available related collateral,
and (c) to promote and market your Ultraleap Enabled Application, in each case solely in
accordance with the Ultraleap trademark guidelines that Ultraleap may provide to you from time
to time.
5.2. For so long as Ultraleap technology is included with the Ultraleap Enabled Application, you must
identify on the packaging of the Ultraleap Enabled Application, the loading screen and start-up
messages for the Ultraleap Enabled Application, and list on your website and marketing collateral
(in each case, where applicable), as prominently as other listed features and functionality, that
Ultraleap technology is included with the Ultraleap Enabled Application, in accordance with the
Ultraleap trademark guidelines that Ultraleap may provide to you from time to time. All
references to Ultraleap or Ultraleap Technology will be subject to Ultraleaps prior approval,
which will not be unreasonably withheld.
5.3. Ultraleap may at its option mention you and your products using Ultraleap technology in
Ultraleaps press releases, press briefings, social media accounts, and/or website, and may use
your trademarks for such purpose. You grant to Ultraleap and its affiliates a non-exclusive,
worldwide and royalty-free limited license to use, reproduce, display, perform, publish and
distribute screenshots, elements, assets, photographic, graphic or video reproductions or
fragments of your Ultraleap Enabled Application in any medium or media, solely for purposes of
promotion of your Ultraleap Enabled Application or of Ultraleap and its technology and business.
The rights set out in this section 5.3 will survive termination of this Agreement in respect of
materials already in existence as at the date of termination.
6. EULA and Other Licenses
6.1. Example code made publicly available by Ultraleap on its developer web site may be provided
subject to the Apache 2.0 license, this Agreement, or other licenses, as specified in the notice or
readme files distributed with the example or in related documentation. The SDK may otherwise
include software or other materials that are provided under a separate license agreement, and
that separate license will govern the use of such software or other materials in the event of a
conflict with this Agreement. Any such separate license agreement may be indicated in the
license, notice, or readme files distributed with the applicable software or other materials or in
related documentation.
6.2. You must either require end users of your Ultraleap Enabled Application to affirmatively agree to
the Ultraleap EULA, or require its End Users to affirmatively agree to your own end user license
agreement that protects Ultraleap at least as much as the Ultraleap EULA.
7. High Risk Uses and Waiver
7.1. Notwithstanding anything in this Agreement, you are not licensed to, and you agree not to, use,
copy, sell, offer for sale, or distribute the SDK, Ultraleap Hardware, Ultraleap Software or
Ultraleap Redistributables (whether compiled with, incorporated into, or packaged with your
Ultraleap Enabled Application or otherwise), for or in connection with uses where failure or fault
of the Ultraleap Hardware, Ultraleap Software, Ultraleap Redistributables or your Ultraleap
Enabled Application could lead to death or serious bodily injury of any person, or to severe
physical or environmental damage (“High Risk Use”). Any such use is strictly prohibited.
7.2. You acknowledge the SDK may allow you to develop Ultraleap Enabled Applications that enable
the control of motorized or mechanical equipment, or other systems, machines or devices. If you
elect to use the SDK in such a way, you must take steps to design and test your Ultraleap Enabled
Applications to ensure that your Ultraleap Enabled Applications do not present risks of personal
injury or death, property damage, or other losses. The Ultraleap Hardware, the Ultraleap
Software, the Ultraleap Redistributables and other software in the SDK may not always function
as intended. You must design your Ultraleap Enabled Applications so that any failure of Ultraleap
Technology and/or such other software as Ultraleap may make available from time to time does
not cause personal injury or death, property damage, or other losses. If you choose to use the
SDK, (i) you assume all risk that use of the Ultraleap Technology and/or such other software by
you or by any others causes any harm or loss, including to the end users of your Ultraleap
Enabled Applications or to third parties, (ii) you hereby waive, on behalf of yourself and your
Authorized Users, all claims against Ultraleap and its affiliates related to such use, harm or loss
(including, but not limited to, any claim that Ultraleap Technology or such other software is
defective), and (iii) you agree to hold Ultraleap and its affiliates harmless from such claims.
8. Confidentiality and Data Protection
8.1. Beta Software etc. Obligations. You acknowledge and agree that Ultraleap may share alpha or
beta software or hardware with you that it identifies as non-public. If so, you agree not to
disclose such software or hardware to others without the prior written consent of Ultraleap
until the time, if any, it is made public by Ultraleap, and to use such software or hardware only
as expressly permitted by Ultraleap. Without limitation to the foregoing, the distribution license
set out in section 2.2 shall not apply to any alpha or beta software which may be shared with
you.
8.2. Your Information. Ultraleap may collect personal information provided by you or your
Authorized Users to Ultraleap or any group company of Ultraleap in connection with the SDK,
and may collect other information from you or your Authorized Users, including technical, non-
personally identifiable and/or aggregated information such as usage statistics, hardware
configuration, problem / fault data, IP addresses, version number of the SDK, information about
which tools and/or services in the SDK are being used and how they are being used, and any
other information described in Ultraleaps privacy policy, currently available at
https://www.ultraleap.com/privacy-policy/. Ultraleap may use the information collected to
facilitate the provision of Updates and other services to you, to verify compliance with, and
enforce, the terms of this Agreement, to improve the SDK and Ultraleaps other products, and
for any other purposes set out in Ultraleaps privacy policy (these uses, collectively, are
“Permitted Uses”). The information collected may be transferred to, stored, and processed in a
destination outside the European Economic Area, including (without limitation) by our staff in
the USA, China, Japan, and Hong Kong. By submitting information about you and/or your
Authorized Users to Ultraleap through your access and use of the SDK, you consent to
Ultraleaps collection and use of the information for the Permitted Uses and represent that you
have obtained all consents and permits necessary under applicable law to disclose your
Authorized Users information to Ultraleap for the Permitted Uses. You further agree that
Ultraleap may provide any information collected under this Section 8.2, including your or your
Authorized Users user name, IP address or other identifying information to law enforcement
authorities or as required by applicable law or regulation.
9. Ownership and Feedback
9.1. As between you and Ultraleap, Ultraleap owns all right, title, and interest, including all
intellectual property rights, in and to the SDK, the Ultraleap Software, Ultraleap Hardware, the
Ultraleap Redistributables, and all documentation associated with the foregoing, other than any
third party software or materials incorporated into the SDK. You agree not to contest Ultraleaps
ownership of any of the foregoing.
9.2. Subject to Section 9.1, Ultraleap agrees that it obtains no right, title, or interest from you (or
your licensors) under this Agreement in or to your Ultraleap Enabled Applications, including any
intellectual property rights which subsist in those Ultraleap Enabled Applications.
9.3. Feedback. You may (but are not required to) provide feedback, comments, and suggestions
(collectively “Feedback”) to Ultraleap. You hereby grant to Ultraleap a non-exclusive, perpetual,
irrevocable, paid-up, transferrable, sub-licensable, worldwide license under all intellectual
property rights covering such Feedback to use, disclose, and exploit all such Feedback for any
purpose.
10. Your Obligations and Warranties
In addition to your other obligations under this Agreement, you warrant and agree that:
10.1. you are at least 18 years of age and have the right and authority to enter into this Agreement on
your own behalf and that of your Authorized Users. If you are entering into this Agreement on
behalf of your company or organization, you warrant that you have the right and authority to
legally bind your company or organization and its Authorized Users;
10.2. you will use the SDK only in accordance with all accompanying documentation, and in the
manner expressly permitted by this Agreement; and
10.3. your use of the SDK, and the marketing, sales and distribution of your Ultraleap Enabled
Application, will be in compliance with all applicable laws and regulations and all UK, U.S. and
local or foreign export and re-export restrictions applicable to the technology and
documentation provided under this Agreement (including privacy and data security laws and
regulations), and you will not develop any Ultraleap Enabled Application which would commit or
facilitate the commission of a crime, or other tortious, unlawful, or illegal act.
11. Agreement and Development Program
11.1. We reserve the right to change this Agreement, the SDK or the Ultraleap development and
licensing program at any time in our discretion. Ultraleap may require that you either accept
and agree to the new terms of this Agreement, or, if you do not agree to the new terms, cease
or terminate your use of the SDK. Your continued use of the SDK after changes to this
Agreement take effect will constitute your acceptance of the changes. If you do not agree to a
change, you must stop using the SDK and terminate this Agreement. Any termination of this
Agreement by you under this Section 11 (and only this Section 11) will not affect your right,
subject to your continued compliance with your obligations under this Agreement, to continue
to distribute versions of your Ultraleap Enabled Application created and first distributed before
termination, and will not affect the right of your End Users to continue using such versions of
your Ultraleap Enabled Application, both of which rights will survive termination.
12. Term and Termination
12.1. Term. This Agreement will continue to apply until terminated by either you or Ultraleap as set
out below.
12.2. Termination by You. If you want to terminate this Agreement, you may terminate it by
uninstalling and destroying all copies of the SDK that are in the possession, custody or control of
you, your Authorized Users and your organization.
12.3. Termination by Ultraleap. Ultraleap may at any time, terminate this Agreement with you for
any reason or for no reason in Ultraleaps sole discretion, including as a result of non-
compliance by you with the restrictions in in this Agreement, or for other reasons.
12.4. Effect of Termination. Upon termination of this Agreement, all rights granted to you under this
Agreement will immediately terminate and you must immediately cease all use and destroy all
copies of the SDK in your and your Authorized Users possession, custody or control, and, except
as specifically set out in Section 11, cease your distribution of Ultraleap Enabled Applications.
Sections 3, 8.1, 8.2, 9, 12.4, 14-16, and 17, will survive termination of this Agreement.
Termination of this Agreement will not affect the right of your End Users who have downloaded
your Ultraleap Enabled Application prior to termination to continue using it.
13. Indemnification.
13.1. You agree to indemnify, hold harmless and, at Ultraleaps option, defend Ultraleap and its
affiliates and their respective officers, directors, employees, agents, and representatives
harmless from any and all judgments, awards, settlements, liabilities, damages, costs, penalties,
fines and other expenses (including court costs and reasonable attorneys fees) incurred by
them arising out of or relating to any third party claim (a) with respect to your Ultraleap Enabled
Application, including products liability, privacy, or intellectual property infringement claims, or
(b) based upon your negligence or wilful misconduct or any breach or alleged breach of your
representations, warranties, and covenants under this Agreement. In no event may you enter
into any settlement or like agreement with a third party that affects Ultraleaps rights or binds
Ultraleap or its affiliates in any way, without the prior written consent of Ultraleap.
14. Warranty Disclaimer.
14.1. THE SDK, THE ULTRALEAP SOFTWARE AND THE ULTRALEAP REDISTRIBUTABLES ARE PROVIDED
"AS IS" WITHOUT WARRANTY OF ANY KIND. ULTRALEAP, ON BEHALF OF ITSELF AND ITS
SUPPLIERS, HEREBY DISCLAIMS ALL REPRESENTATIONS, PROMISES, OR WARRANTIES, WHETHER
EXPRESS, IMPLIED, STATUTORY, OR OTHERWISE, WITH RESPECT TO THE SDK, THE ULTRALEAP
SOFTWARE AND THE ULTRALEAP REDISTRIBUTABLES, INCLUDING THEIR CONDITION,
AVAILABILITY, OR THE EXISTENCE OF ANY LATENT DEFECTS, AND ULTRALEAP SPECIFICALLY
DISCLAIMS ALL IMPLIED WARRANTIES OF MERCHANTABILITY, TITLE, NONINFRINGEMENT,
SUITABILITY, AND FITNESS FOR ANY PURPOSE. ULTRALEAP DOES NOT WARRANT THAT THE SDK,
THE ULTRALEAP SOFTWARE OR THE ULTALEAP REDISTRIBUTABLES WILL BE ERROR-FREE OR
THAT THEY WILL WORK WITHOUT INTERRUPTION.
15. Limitation of Liability.
15.1. ULTRALEAP SHALL NOT IN ANY CIRCUMSTANCES WHATEVER BE LIABLE TO YOU, WHETHER IN
CONTRACT, TORT (INCLUDING NEGLIGENCE), BREACH OF STATUTORY DUTY, OR OTHERWISE,
ARISING UNDER OR IN CONNECTION WITH THE AGREEMENT FOR:
15.1.1. LOSS OF PROFITS, SALES, BUSINESS, OR REVENUE;
15.1.2. BUSINESS INTERRUPTION;
15.1.3. LOSS OF ANTICIPATED SAVINGS;
15.1.4. LOSS OR CORRUPTION OF DATA OR INFORMATION;
15.1.5. LOSS OF BUSINESS OPPORTUNITY, GOODWILL OR REPUTATION; OR
15.1.6. ANY INDIRECT OR CONSEQUENTIAL LOSS OR DAMAGE.
15.2. OTHER THAN THE LOSSES SET OUT ABOVE (FOR WHICH ULTRALEAP IS NOT LIABLE),
ULTRALEAPS MAXIMUM AGGREGATE LIABILITY UNDER OR IN CONNECTION WITH THE
AGREEMENT WHETHER IN CONTRACT, TORT (INCLUDING NEGLIGENCE), BREACH OF STATUTORY
DUTY, OR OTHERWISE, SHALL IN ALL CIRCUMSTANCES BE LIMITED TO $1,000 (ONE THOUSAND
US DOLLARS). THIS MAXIMUM CAP DOES NOT APPLY TO DEATH OR PERSONAL INJURY
RESULTING FROM ULTRALEAP'S NEGLIGENCE; FRAUD OR FRAUDULENT MISREPRESENTATION;
OR ANY OTHER LIABILITY THAT CANNOT BE EXCLUDED OR LIMITED BY APPLICABLE LAW.
15.3. THE AGREEMENT SETS OUT THE FULL EXTENT OF ULTRALEAPS OBLIGATIONS AND LIABILITIES IN
RESPECT OF THE SUPPLY OF THE ULTRALEAP DEVICES, DELIVERABLES AND SOFTWARE. EXCEPT
AS EXPRESSLY STATED IN THE AGREEMENT, THERE ARE NO CONDITIONS, WARRANTIES,
REPRESENTATIONS OR OTHER TERMS, EXPRESS OR IMPLIED, THAT ARE BINDING ON
ULTRALEAP. ANY CONDITION, WARRANTY, REPRESENTATION OR OTHER TERM CONCERNING
THE SUPPLY OF THE ULTRALEAP HARDWARE, ULTRALEAP SOFTWARE, THE SDK, THE ULTRALEAP
REDISTRIBUTABLES, OR ANY OTHER ULTRALEAP TECHNOLOGY WHICH MIGHT OTHERWISE BE
IMPLIED INTO, OR INCORPORATED IN THE AGREEMENT WHETHER BY STATUTE, COMMON LAW
OR OTHERWISE, INCLUDING ANY WARRANTY OR CONDITION OF MERCHANTABILITY OR FITNESS
FOR A PARTICULAR PURPOSE, IS EXCLUDED TO THE FULLEST EXTENT PERMITTED BY LAW. THESE
LIMITATIONS WILL APPLY NOTWITHSTANDING ANY FAILURE OF ESSENTIAL PURPOSE OF ANY
LIMITED REMEDY. THE PARTIES AGREE THAT THE FOREGOING LIMITATIONS REPRESENT A
REASONABLE ALLOCATION OF RISK UNDER THIS AGREEMENT.
16. Miscellaneous.
16.1. Assignment. You may not assign this Agreement without the prior written consent of Ultraleap.
Any assignment without such consent is void and of no effect. Ultraleap may assign this
Agreement without your consent in connection with (a) a merger or consolidation of Ultraleap,
(b) a sale or assignment of substantially all its assets, or (c) any other transaction which results
in another entity or person owning substantially all of the assets of Ultraleap, or (d) to any of its
affiliates. In the event of a permitted assignment, this Agreement will inure to the benefit of and
be binding upon the parties and their respective successors and permitted assigns.
16.2. Waiver; Severability. The failure of the other party to enforce any rights under this Agreement
will not be deemed a waiver of any rights. The rights and remedies of the parties in this
Agreement are not exclusive and are in addition to any other rights and remedies provided by
law. If any provision of this Agreement is held by a court of competent jurisdiction to be
contrary to law, the remaining provisions of this Agreement will remain in full force and effect.
16.3. Reservation. All licenses not expressly granted in this Agreement are reserved and no other
licenses, immunity or rights, express or implied, are granted by Ultraleap, by implication,
estoppel, or otherwise. The software in the SDK is licensed, not sold.
16.4. Export Restrictions. The Ultraleap Software is subject to United States and UK export laws and
regulations. You must comply with all domestic and international export laws and regulations
that apply to the Ultraleap Software. These laws include restrictions on destinations, end users,
and end use.
16.5. Governing Law and Jurisdiction. This Agreement will be exclusively governed by and construed
under the laws of the England and Wales, without reference to or application of rules governing
choice of laws. All disputes arising out of or related to this Agreement will be subject to the
exclusive jurisdiction of courts of England and you hereby consent to such jurisdiction. However,
Ultraleap may apply to any court or tribunal worldwide, including but not limited to those
having jurisdiction over you or your Authorized Users, to seek injunctive relief.
16.6. Relationship of the Parties. This Agreement does not create any agency, partnership, or joint
venture relationship between Ultraleap and you. This Agreement is for the sole benefit of
Ultraleap and you (and indemnified parties), and no other persons will have any right or remedy
under this Agreement.
16.7. Notices. The address for notice to Ultraleap under this Agreement is:
Ultraleap Limited
The West Wing
Glass Wharf
Bristol, BS2 0EL
United Kingdom
Ultraleap may provide you notice under this Agreement by email or other electronic
communication or by posting communications to its development community on the Ultraleap
developer portal. You consent to receive such notices in any of the foregoing manners and
agree that any such notices by Ultraleap will satisfy any legal communication requirements.
16.8. Entire Agreement. This Agreement is the entire understanding of the parties with respect to its
subject matter and supersedes any previous or contemporaneous communications, whether
oral or written with respect to such subject matter.
17. Definitions
Whenever capitalized in this Agreement:
“Authorized Users” means your employees and contractors, members of your organization or, if you
are an educational institution, your faculty, staff and registered students, who (a) have a
demonstrable need to know or use the SDK in order to develop and test Ultraleap Enabled
Applications on your behalf and (b) each have written and binding agreements with you to protect
against the unauthorized use and disclosure of the SDK consistent with the terms and conditions of
this Agreement. Authorized Users do not include End Users.
“End User” means your end user customer(s) or licensee(s).
“Non-Redistributable Materials” means the Ultraleap Software, and any other code, files or
materials that are not specifically designated in the SDK as made available for incorporation into
Ultraleap Enabled Applications or that are specifically designated in the SDK as not subject to
distribution.
“SDK” means, collectively, the Ultraleap Redistributables, tools, APIs, sample code, software,
documentation, other materials and any updates to the foregoing that may be provided or made
available to you by Ultraleap in connection with this Agreement, via the Ultraleap developer portal or
otherwise for use in connection with the Ultraleap development program to develop Ultraleap
Enabled Applications.
“Specialized Application” means an Ultraleap Enabled Application which does not fall within the
permitted uses set out in this Agreement.
“Ultraleap” “we” or “us” means Ultraleap Limited, a company registered in England with company
number 08781720, with a principal place of business at The West Wing, Glass Wharf, Bristol, BS2 0EL,
United Kingdom.
“Ultraleap Hardware” means the Leap Motion Controller or Stereo IR 170, each being a device that
detects and reads movements within a 3-D interaction space to precisely interact with and control
software on a computing device, or an Ultraleap-authorized embedded optical module.
“Ultraleap Redistributables” means any .lib code, .dll files, .so files, sample code, or other materials
we specifically designate in the SDK as made available for incorporation into or distribution with
Ultraleap Enabled Applications.
“Ultraleap Software” means the Ultraleap core services application and related applications that
interact with Ultraleap Hardware and an operating system to make motion control functionality
available to Ultraleap Enabled Applications, and includes any Updates thereto.
“Updates” means updates, upgrades, modifications, enhancements, revisions, new releases or new
versions to the SDK that Ultraleap may make available to you in connection with this Agreement.
Other capitalized terms used in this Agreement have the meaning given them elsewhere in this
Agreement.
18. Supplemental Terms Applicable to the Use of Image API
18.1. Purpose. You and/or your Ultraleap Enabled Application may access the Image API and use
image data available through the Image API only for the purpose of developing and testing
Ultraleap Enabled Applications, and only for use with Ultraleap Hardware. You may not use the
Image API to develop or aid development of competing motion tracking hardware or software.
Any use of the Image API is subject to the terms of the Agreement.
18.2. Data Protection.
18.2.1. If you or your Ultraleap Enabled Application collects, uploads, stores, transmits, or
shares images, videos, or other personal information available through the Image API,
either through or in connection with your Ultraleap Enabled Application, you must
expressly provide users with your privacy policy and adhere to it.
18.2.2. You must obtain specific, opt-in consent from the user for any use that is beyond the
limited and express purpose of your Ultraleap Enabled Application.
18.2.3. You and your Ultraleap Enabled Application must use and store information collected
form users securely and only for as long as it is required.
18.2.4. You agree that you will protect the privacy and legal rights of users, and will comply with
all applicable criminal, civil, and statutory privacy and data protection laws and
regulations.

92
ml_lme_cvr/vendor/LeapSDK/README.md vendored Normal file
View file

@ -0,0 +1,92 @@
# Ultraleap SDK
--------------------------------------------------------------------------------
## Package contents:
LeapSDK
- docs
* API reference documentation & guidelines.
- include
* API headers.
- lib
* dynamic API library and CMake scripts.
- samples
* Various samples demonstrating several different usages.
- LICENSE.md
* Ultraleap Tracking SDK license.
- Uninstall.exe
* Program to uninstall the LeapSDK application.
## Requirements:
1. Running requires
* Ultraleap Tracking Software https://developer.leapmotion.com/get-started/
2. Building Samples requires
* CMake 3.16.3+ (https://cmake.org/)
* Microsoft Visual Studio 15+
## Installation:
1. Execute the LeapSDK installer.
2. Choose a suitable destination location on your computer.
3. Read and accept the Ultraleap Tracking SDK Agreement to use the Ultraleap SDK.
## Usage:
1. For CMake projects
* Ensure LeapSDK is in a directory considered as a prefix by find_package.
(https://cmake.org/cmake/help/v3.16/command/find_package.html)
* Or : directly set LeapSDK_DIR to <install_dir>/LeapSDK/lib/cmake/LeapSDK
* Or : Pass the LeapSDK's path to find_package with the PATHS option.
* call find_package(LeapSDK 5 [PATHS ...]).
* call target_link_libraries(<your project> PUBLIC|PRIVATE LeapSDK::LeapC).
* Ensure LeapC.dll is in your dynamic library search path.
* A popular option is to add a post-build step that copies it to your project's output directory.
2. For non-CMake projects
* Use a C/C++ compiler such as MSVC, Clang or GCC.
* Add LeapSDK/include to the compiler include search paths.
* Either add a linker reference to LeapC.lib or dynamically load LeapC.dll.
## Building Samples:
1. Open CMake using LeapSDK/samples as the source directory
2. Select a build directory (often LeapSDK/samples/build) to use
3. Configure & Generate CMake with the generator of your choice
* An example script would be :
```powershell
$env:BUILD_TYPE = 'Release'
$env:REPOS_BUILD_ROOT = 'C:/build'
$env:REPOS_INSTALL_ROOT = 'C:/Program Files'
cmake -j -S "C:/Program Files/Ultraleap/LeapSDK/samples" -B $env:REPOS_BUILD_ROOT/$env:BUILD_TYPE/LeapSDK/leapc_example `
-DCMAKE_INSTALL_PREFIX="$env:REPOS_INSTALL_ROOT/leapc_example" `
-DCMAKE_BUILD_TYPE="$env:BUILD_TYPE"
cmake --build $env:REPOS_BUILD_ROOT/$env:BUILD_TYPE/LeapSDK/leapc_example -j --config $env:BUILD_TYPE
```
4. Open and build the CMake generated project files. For more help, see the CMake documentation.
## Resources:
1. Ultraleap For Developers Site (https://developer.leapmotion.com)
provides examples, community forums, Ultraleap news, and documentation
to help you to learn how to develop applications using the Ultraleap Tracking
SDK.
2. C# and Unity bindings (https://github.com/leapmotion/UnityModules)
3. C++ bindings matching the old API (https://github.com/leapmotion/LeapCxx)
--------------------------------------------------------------------------------
Copyright © 2012-2020 Ultraleap Ltd. All rights reserved.
Use subject to the terms of the Ultraleap Tracking SDK Agreement `LICENSE.md` next to this `README.md` file.

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,32 @@
Copyright 2008 Google Inc. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following disclaimer
in the documentation and/or other materials provided with the
distribution.
* Neither the name of Google Inc. nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Code generated by the Protocol Buffer compiler is owned by the owner
of the input file used when generating it. This code is not
standalone and requires a support library to be linked with it. This
support library is itself covered by the above license.

Binary file not shown.

Binary file not shown.

25
ml_mods_cvr.sln Normal file
View file

@ -0,0 +1,25 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 15
VisualStudioVersion = 15.0.28307.1738
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ml_lme_cvr", "ml_lme_cvr\ml_lme_cvr.csproj", "{83CC74B7-F444-40E1-BD06-67CEC995A919}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|x64 = Debug|x64
Release|x64 = Release|x64
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{83CC74B7-F444-40E1-BD06-67CEC995A919}.Debug|x64.ActiveCfg = Debug|x64
{83CC74B7-F444-40E1-BD06-67CEC995A919}.Debug|x64.Build.0 = Debug|x64
{83CC74B7-F444-40E1-BD06-67CEC995A919}.Release|x64.ActiveCfg = Release|x64
{83CC74B7-F444-40E1-BD06-67CEC995A919}.Release|x64.Build.0 = Release|x64
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {C7C6398E-220C-40C3-AE95-5690C9B2B3C3}
EndGlobalSection
EndGlobal