mirror of
https://github.com/hanetzer/sdraw_mods_cvr.git
synced 2025-09-03 10:29:22 +00:00
Removed Upright
Leading hand option Hands extension with `Q`/`E` Joints fix Update to LeapSDK 5.16
This commit is contained in:
parent
b6a200d44c
commit
aebf6c2c4e
22 changed files with 9131 additions and 6719 deletions
|
@ -3,9 +3,9 @@ Merged set of MelonLoader mods for ChilloutVR.
|
|||
**Table for game build 2023r173:**
|
||||
| Full name | Short name | Latest version | Available in [CVRMA](https://github.com/knah/CVRMelonAssistant) |
|
||||
|:---------:|:----------:|:--------------:| :----------------------------------------------------------------|
|
||||
| [Avatar Motion Tweaker](/ml_amt/README.md) | ml_amt | 1.3.4 [:arrow_down:](../../releases/latest/download/ml_amt.dll)| ✔ Yes |
|
||||
| [Leap Motion Extension](/ml_lme/README.md)| ml_lme | 1.4.4 [:arrow_down:](../../releases/latest/download/ml_lme.dll)| ✔ Yes |
|
||||
| [Pickup Arm Movement](/ml_pam/README.md)| ml_pam | 1.0.8 [:arrow_down:](../../releases/latest/download/ml_pam.dll)| ✔ Yes |
|
||||
| [Avatar Motion Tweaker](/ml_amt/README.md) | ml_amt | 1.3.5 [:arrow_down:](../../releases/latest/download/ml_amt.dll)| ✔ Yes<br>⌛ Update review |
|
||||
| [Leap Motion Extension](/ml_lme/README.md)| ml_lme | 1.4.5 [:arrow_down:](../../releases/latest/download/ml_lme.dll)| ✔ Yes<br>⌛ Update review |
|
||||
| [Pickup Arm Movement](/ml_pam/README.md)| ml_pam | 1.0.9 [:arrow_down:](../../releases/latest/download/ml_pam.dll)| ✔ Yes<br>⌛ Update review |
|
||||
| [Player Movement Copycat](/ml_pmc/README.md)| ml_pmc | 1.0.4 [:arrow_down:](../../releases/latest/download/ml_pmc.dll)| ✔ Yes<br>⌛ Update review |
|
||||
| [Player Ragdoll Mod](/ml_prm/README.md) | ml_prm | 1.1.1 [:arrow_down:](../../releases/latest/download/ml_prm.dll)| ✔ Yes<br>⌛ Update review |
|
||||
| [Vive Extended Input](/ml_vei/README.md) | ml_vei | 1.0.0 [:arrow_down:](../../releases/latest/download/ml_vei.dll)| ✔ Yes |
|
||||
|
|
|
@ -1,85 +1,80 @@
|
|||
using ABI_RC.Core;
|
||||
using System.Text.RegularExpressions;
|
||||
using UnityEngine;
|
||||
|
||||
namespace ml_amt
|
||||
{
|
||||
class AvatarParameter
|
||||
{
|
||||
public enum ParameterType
|
||||
{
|
||||
Upright,
|
||||
GroundedRaw,
|
||||
Moving
|
||||
}
|
||||
|
||||
readonly ParameterType m_type;
|
||||
readonly string m_name;
|
||||
readonly int m_hash = 0;
|
||||
readonly bool m_sync;
|
||||
readonly AnimatorControllerParameterType m_innerType;
|
||||
readonly CVRAnimatorManager m_manager = null;
|
||||
|
||||
public AvatarParameter(ParameterType p_type, CVRAnimatorManager p_manager)
|
||||
{
|
||||
m_type = p_type;
|
||||
m_name = p_type.ToString();
|
||||
m_manager = p_manager;
|
||||
|
||||
Regex l_regex = new Regex("^#?" + m_name + '$');
|
||||
foreach(var l_param in m_manager.animator.parameters)
|
||||
{
|
||||
if(l_regex.IsMatch(l_param.name))
|
||||
{
|
||||
m_hash = l_param.nameHash;
|
||||
m_sync = (l_param.name[0] != '#');
|
||||
m_innerType = l_param.type;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void Update(MotionTweaker p_tweaker)
|
||||
{
|
||||
switch(m_type)
|
||||
{
|
||||
case ParameterType.Upright:
|
||||
SetFloat(p_tweaker.GetUpright());
|
||||
break;
|
||||
|
||||
case ParameterType.GroundedRaw:
|
||||
SetBoolean(p_tweaker.GetGroundedRaw());
|
||||
break;
|
||||
|
||||
case ParameterType.Moving:
|
||||
SetBoolean(p_tweaker.GetMoving());
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public bool IsValid() => (m_hash != 0);
|
||||
public ParameterType GetParameterType() => m_type;
|
||||
|
||||
void SetFloat(float p_value)
|
||||
{
|
||||
if(m_innerType == AnimatorControllerParameterType.Float)
|
||||
{
|
||||
if(m_sync)
|
||||
m_manager.SetAnimatorParameterFloat(m_name, p_value);
|
||||
else
|
||||
m_manager.animator.SetFloat(m_hash, p_value);
|
||||
}
|
||||
}
|
||||
|
||||
void SetBoolean(bool p_value)
|
||||
{
|
||||
if(m_innerType == AnimatorControllerParameterType.Bool)
|
||||
{
|
||||
if(m_sync)
|
||||
m_manager.SetAnimatorParameterBool(m_name, p_value);
|
||||
else
|
||||
m_manager.animator.SetBool(m_hash, p_value);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
using ABI_RC.Core;
|
||||
using System.Text.RegularExpressions;
|
||||
using UnityEngine;
|
||||
|
||||
namespace ml_amt
|
||||
{
|
||||
class AvatarParameter
|
||||
{
|
||||
public enum ParameterType
|
||||
{
|
||||
GroundedRaw,
|
||||
Moving
|
||||
}
|
||||
|
||||
readonly ParameterType m_type;
|
||||
readonly string m_name;
|
||||
readonly int m_hash = 0;
|
||||
readonly bool m_sync;
|
||||
readonly AnimatorControllerParameterType m_innerType;
|
||||
readonly CVRAnimatorManager m_manager = null;
|
||||
|
||||
public AvatarParameter(ParameterType p_type, CVRAnimatorManager p_manager)
|
||||
{
|
||||
m_type = p_type;
|
||||
m_name = p_type.ToString();
|
||||
m_manager = p_manager;
|
||||
|
||||
Regex l_regex = new Regex("^#?" + m_name + '$');
|
||||
foreach(var l_param in m_manager.animator.parameters)
|
||||
{
|
||||
if(l_regex.IsMatch(l_param.name))
|
||||
{
|
||||
m_hash = l_param.nameHash;
|
||||
m_sync = (l_param.name[0] != '#');
|
||||
m_innerType = l_param.type;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void Update(MotionTweaker p_tweaker)
|
||||
{
|
||||
switch(m_type)
|
||||
{
|
||||
case ParameterType.GroundedRaw:
|
||||
SetBoolean(p_tweaker.GetGroundedRaw());
|
||||
break;
|
||||
|
||||
case ParameterType.Moving:
|
||||
SetBoolean(p_tweaker.GetMoving());
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public bool IsValid() => (m_hash != 0);
|
||||
public ParameterType GetParameterType() => m_type;
|
||||
|
||||
void SetFloat(float p_value)
|
||||
{
|
||||
if(m_innerType == AnimatorControllerParameterType.Float)
|
||||
{
|
||||
if(m_sync)
|
||||
m_manager.SetAnimatorParameterFloat(m_name, p_value);
|
||||
else
|
||||
m_manager.animator.SetFloat(m_hash, p_value);
|
||||
}
|
||||
}
|
||||
|
||||
void SetBoolean(bool p_value)
|
||||
{
|
||||
if(m_innerType == AnimatorControllerParameterType.Bool)
|
||||
{
|
||||
if(m_sync)
|
||||
m_manager.SetAnimatorParameterBool(m_name, p_value);
|
||||
else
|
||||
m_manager.animator.SetBool(m_hash, p_value);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -136,7 +136,6 @@ namespace ml_amt
|
|||
m_avatarScale = Mathf.Abs(PlayerSetup.Instance._avatar.transform.localScale.y);
|
||||
|
||||
// Parse animator parameters
|
||||
m_parameters.Add(new AvatarParameter(AvatarParameter.ParameterType.Upright, PlayerSetup.Instance.animatorManager));
|
||||
m_parameters.Add(new AvatarParameter(AvatarParameter.ParameterType.GroundedRaw, PlayerSetup.Instance.animatorManager));
|
||||
m_parameters.Add(new AvatarParameter(AvatarParameter.ParameterType.Moving, PlayerSetup.Instance.animatorManager));
|
||||
m_parameters.RemoveAll(p => !p.IsValid());
|
||||
|
@ -246,11 +245,7 @@ namespace ml_amt
|
|||
}
|
||||
|
||||
if(m_locomotionOverride && !l_locomotionOverride)
|
||||
{
|
||||
m_vrIk.solver.Reset();
|
||||
if((IKSystem.VrikRootController != null) && !MovementSystem.Instance.sitting)
|
||||
IKSystem.VrikRootController.enabled = true;
|
||||
}
|
||||
m_locomotionOverride = l_locomotionOverride;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
[assembly: MelonLoader.MelonInfo(typeof(ml_amt.AvatarMotionTweaker), "AvatarMotionTweaker", "1.3.4", "SDraw", "https://github.com/SDraw/ml_mods_cvr")]
|
||||
[assembly: MelonLoader.MelonInfo(typeof(ml_amt.AvatarMotionTweaker), "AvatarMotionTweaker", "1.3.5", "SDraw", "https://github.com/SDraw/ml_mods_cvr")]
|
||||
[assembly: MelonLoader.MelonGame(null, "ChilloutVR")]
|
||||
[assembly: MelonLoader.MelonPlatform(MelonLoader.MelonPlatformAttribute.CompatiblePlatforms.WINDOWS_X64)]
|
||||
[assembly: MelonLoader.MelonPlatformDomain(MelonLoader.MelonPlatformDomainAttribute.CompatibleDomains.MONO)]
|
||||
|
|
|
@ -1,46 +1,47 @@
|
|||
using ABI.CCK.Components;
|
||||
using ABI_RC.Core.UI;
|
||||
using ABI_RC.Systems.MovementSystem;
|
||||
using RootMotion.FinalIK;
|
||||
using System.Reflection;
|
||||
using UnityEngine;
|
||||
|
||||
namespace ml_amt
|
||||
{
|
||||
static class Utils
|
||||
{
|
||||
static readonly FieldInfo ms_grounded = typeof(MovementSystem).GetField("_isGrounded", BindingFlags.NonPublic | BindingFlags.Instance);
|
||||
static readonly FieldInfo ms_groundedRaw = typeof(MovementSystem).GetField("_isGroundedRaw", BindingFlags.NonPublic | BindingFlags.Instance);
|
||||
static readonly FieldInfo ms_hasToes = typeof(IKSolverVR).GetField("hasToes", BindingFlags.NonPublic | BindingFlags.Instance);
|
||||
static readonly FieldInfo ms_view = typeof(CohtmlControlledViewWrapper).GetField("_view", BindingFlags.NonPublic | BindingFlags.Instance);
|
||||
|
||||
public static bool IsInVR() => ((ABI_RC.Core.Savior.CheckVR.Instance != null) && ABI_RC.Core.Savior.CheckVR.Instance.hasVrDeviceLoaded);
|
||||
|
||||
public static bool IsGrounded(this MovementSystem p_instance) => (bool)ms_grounded.GetValue(MovementSystem.Instance);
|
||||
public static bool IsGroundedRaw(this MovementSystem p_instance) => (bool)ms_groundedRaw.GetValue(MovementSystem.Instance);
|
||||
|
||||
public static bool HasToes(this IKSolverVR p_instance) => (bool)ms_hasToes.GetValue(p_instance);
|
||||
|
||||
public static bool IsWorldSafe() => ((CVRWorld.Instance != null) && CVRWorld.Instance.allowFlying);
|
||||
public static float GetWorldMovementLimit()
|
||||
{
|
||||
float l_result = 1f;
|
||||
if(CVRWorld.Instance != null)
|
||||
{
|
||||
l_result = CVRWorld.Instance.baseMovementSpeed;
|
||||
l_result *= CVRWorld.Instance.sprintMultiplier;
|
||||
l_result *= CVRWorld.Instance.inAirMovementMultiplier;
|
||||
l_result *= CVRWorld.Instance.flyMultiplier;
|
||||
}
|
||||
return l_result;
|
||||
}
|
||||
|
||||
static public void ExecuteScript(this CohtmlControlledViewWrapper p_instance, string p_script) => ((cohtml.Net.View)ms_view.GetValue(p_instance)).ExecuteScript(p_script);
|
||||
|
||||
// Engine extensions
|
||||
public static Matrix4x4 GetMatrix(this Transform p_transform, bool p_pos = true, bool p_rot = true, bool p_scl = false)
|
||||
{
|
||||
return Matrix4x4.TRS(p_pos ? p_transform.position : Vector3.zero, p_rot ? p_transform.rotation : Quaternion.identity, p_scl ? p_transform.localScale : Vector3.one);
|
||||
}
|
||||
}
|
||||
}
|
||||
using ABI.CCK.Components;
|
||||
using ABI_RC.Core.UI;
|
||||
using ABI_RC.Systems.MovementSystem;
|
||||
using RootMotion.FinalIK;
|
||||
using System.Collections.Generic;
|
||||
using System.Reflection;
|
||||
using UnityEngine;
|
||||
|
||||
namespace ml_amt
|
||||
{
|
||||
static class Utils
|
||||
{
|
||||
static readonly FieldInfo ms_grounded = typeof(MovementSystem).GetField("_isGrounded", BindingFlags.NonPublic | BindingFlags.Instance);
|
||||
static readonly FieldInfo ms_groundedRaw = typeof(MovementSystem).GetField("_isGroundedRaw", BindingFlags.NonPublic | BindingFlags.Instance);
|
||||
static readonly FieldInfo ms_hasToes = typeof(IKSolverVR).GetField("hasToes", BindingFlags.NonPublic | BindingFlags.Instance);
|
||||
static readonly FieldInfo ms_view = typeof(CohtmlControlledViewWrapper).GetField("_view", BindingFlags.NonPublic | BindingFlags.Instance);
|
||||
|
||||
public static bool IsInVR() => ((ABI_RC.Core.Savior.CheckVR.Instance != null) && ABI_RC.Core.Savior.CheckVR.Instance.hasVrDeviceLoaded);
|
||||
|
||||
public static bool IsGrounded(this MovementSystem p_instance) => (bool)ms_grounded.GetValue(MovementSystem.Instance);
|
||||
public static bool IsGroundedRaw(this MovementSystem p_instance) => (bool)ms_groundedRaw.GetValue(MovementSystem.Instance);
|
||||
|
||||
public static bool HasToes(this IKSolverVR p_instance) => (bool)ms_hasToes.GetValue(p_instance);
|
||||
|
||||
public static bool IsWorldSafe() => ((CVRWorld.Instance != null) && CVRWorld.Instance.allowFlying);
|
||||
public static float GetWorldMovementLimit()
|
||||
{
|
||||
float l_result = 1f;
|
||||
if(CVRWorld.Instance != null)
|
||||
{
|
||||
l_result = CVRWorld.Instance.baseMovementSpeed;
|
||||
l_result *= CVRWorld.Instance.sprintMultiplier;
|
||||
l_result *= CVRWorld.Instance.inAirMovementMultiplier;
|
||||
l_result *= CVRWorld.Instance.flyMultiplier;
|
||||
}
|
||||
return l_result;
|
||||
}
|
||||
|
||||
static public void ExecuteScript(this CohtmlControlledViewWrapper p_instance, string p_script) => ((cohtml.Net.View)ms_view.GetValue(p_instance)).ExecuteScript(p_script);
|
||||
|
||||
// Engine extensions
|
||||
public static Matrix4x4 GetMatrix(this Transform p_transform, bool p_pos = true, bool p_rot = true, bool p_scl = false)
|
||||
{
|
||||
return Matrix4x4.TRS(p_pos ? p_transform.position : Vector3.zero, p_rot ? p_transform.rotation : Quaternion.identity, p_scl ? p_transform.localScale : Vector3.one);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
<Company>None</Company>
|
||||
<Product>AvatarMotionTweaker</Product>
|
||||
<PackageId>AvatarMotionTweaker</PackageId>
|
||||
<Version>1.3.4</Version>
|
||||
<Version>1.3.5</Version>
|
||||
<Platforms>x64</Platforms>
|
||||
<AssemblyName>ml_amt</AssemblyName>
|
||||
</PropertyGroup>
|
||||
|
|
|
@ -1,427 +1,400 @@
|
|||
using ABI_RC.Core.Player;
|
||||
using ABI_RC.Systems.IK;
|
||||
using RootMotion.FinalIK;
|
||||
using System.Reflection;
|
||||
using UnityEngine;
|
||||
|
||||
namespace ml_lme
|
||||
{
|
||||
[DisallowMultipleComponent]
|
||||
class LeapTracked : MonoBehaviour
|
||||
{
|
||||
static readonly float[] ms_tposeMuscles = typeof(ABI_RC.Systems.IK.SubSystems.BodySystem).GetField("TPoseMuscles", BindingFlags.Static | BindingFlags.NonPublic).GetValue(null) as float[];
|
||||
static readonly Quaternion ms_offsetLeft = Quaternion.Euler(0f, 90f, 0f);
|
||||
static readonly Quaternion ms_offsetRight = Quaternion.Euler(0f, 270f, 0f);
|
||||
|
||||
VRIK m_vrIK = null;
|
||||
Vector4 m_armsWeights = Vector2.zero;
|
||||
bool m_inVR = false;
|
||||
Transform m_hips = null;
|
||||
Transform m_origLeftHand = null;
|
||||
Transform m_origRightHand = null;
|
||||
Transform m_origLeftElbow = null;
|
||||
Transform m_origRightElbow = null;
|
||||
|
||||
bool m_enabled = true;
|
||||
bool m_fingersOnly = false;
|
||||
bool m_trackElbows = true;
|
||||
|
||||
ArmIK m_leftArmIK = null;
|
||||
ArmIK m_rightArmIK = null;
|
||||
HumanPoseHandler m_poseHandler = null;
|
||||
HumanPose m_pose;
|
||||
Transform m_leftHandTarget = null;
|
||||
Transform m_rightHandTarget = null;
|
||||
bool m_leftTargetActive = false;
|
||||
bool m_rightTargetActive = false;
|
||||
|
||||
// Unity events
|
||||
void Start()
|
||||
{
|
||||
m_inVR = Utils.IsInVR();
|
||||
|
||||
m_leftHandTarget = new GameObject("RotationTarget").transform;
|
||||
m_leftHandTarget.parent = LeapTracking.Instance.GetLeftHand();
|
||||
m_leftHandTarget.localPosition = Vector3.zero;
|
||||
m_leftHandTarget.localRotation = Quaternion.identity;
|
||||
|
||||
m_rightHandTarget = new GameObject("RotationTarget").transform;
|
||||
m_rightHandTarget.parent = LeapTracking.Instance.GetRightHand();
|
||||
m_rightHandTarget.localPosition = Vector3.zero;
|
||||
m_rightHandTarget.localRotation = Quaternion.identity;
|
||||
|
||||
Settings.EnabledChange += this.OnEnabledChange;
|
||||
Settings.FingersOnlyChange += this.OnFingersOnlyChange;
|
||||
Settings.TrackElbowsChange += this.OnTrackElbowsChange;
|
||||
|
||||
OnEnabledChange(Settings.Enabled);
|
||||
OnFingersOnlyChange(Settings.FingersOnly);
|
||||
OnTrackElbowsChange(Settings.TrackElbows);
|
||||
}
|
||||
|
||||
void OnDestroy()
|
||||
{
|
||||
Settings.EnabledChange -= this.OnEnabledChange;
|
||||
Settings.FingersOnlyChange -= this.OnFingersOnlyChange;
|
||||
Settings.TrackElbowsChange -= this.OnTrackElbowsChange;
|
||||
}
|
||||
|
||||
void Update()
|
||||
{
|
||||
if(m_enabled)
|
||||
{
|
||||
LeapParser.LeapData l_data = LeapManager.Instance.GetLatestData();
|
||||
|
||||
if((m_leftArmIK != null) && (m_rightArmIK != null))
|
||||
{
|
||||
m_leftArmIK.solver.IKPositionWeight = Mathf.Lerp(m_leftArmIK.solver.IKPositionWeight, (l_data.m_leftHand.m_present && !m_fingersOnly) ? 1f : 0f, 0.25f);
|
||||
m_leftArmIK.solver.IKRotationWeight = Mathf.Lerp(m_leftArmIK.solver.IKRotationWeight, (l_data.m_leftHand.m_present && !m_fingersOnly) ? 1f : 0f, 0.25f);
|
||||
if(m_trackElbows)
|
||||
m_leftArmIK.solver.arm.bendGoalWeight = Mathf.Lerp(m_leftArmIK.solver.arm.bendGoalWeight, (l_data.m_leftHand.m_present && !m_fingersOnly) ? 1f : 0f, 0.25f);
|
||||
|
||||
m_rightArmIK.solver.IKPositionWeight = Mathf.Lerp(m_rightArmIK.solver.IKPositionWeight, (l_data.m_rightHand.m_present && !m_fingersOnly) ? 1f : 0f, 0.25f);
|
||||
m_rightArmIK.solver.IKRotationWeight = Mathf.Lerp(m_rightArmIK.solver.IKRotationWeight, (l_data.m_rightHand.m_present && !m_fingersOnly) ? 1f : 0f, 0.25f);
|
||||
if(m_trackElbows)
|
||||
m_rightArmIK.solver.arm.bendGoalWeight = Mathf.Lerp(m_rightArmIK.solver.arm.bendGoalWeight, (l_data.m_rightHand.m_present && !m_fingersOnly) ? 1f : 0f, 0.25f);
|
||||
}
|
||||
|
||||
if((m_vrIK != null) && !m_fingersOnly)
|
||||
{
|
||||
if(l_data.m_leftHand.m_present && !m_leftTargetActive)
|
||||
{
|
||||
m_vrIK.solver.leftArm.target = m_leftHandTarget;
|
||||
m_vrIK.solver.leftArm.bendGoal = LeapTracking.Instance.GetLeftElbow();
|
||||
m_vrIK.solver.leftArm.bendGoalWeight = (m_trackElbows ? 1f : 0f);
|
||||
m_leftTargetActive = true;
|
||||
}
|
||||
if(!l_data.m_leftHand.m_present && m_leftTargetActive)
|
||||
{
|
||||
m_vrIK.solver.leftArm.target = m_origLeftHand;
|
||||
m_vrIK.solver.leftArm.bendGoal = m_origLeftElbow;
|
||||
m_vrIK.solver.leftArm.bendGoalWeight = ((m_origLeftElbow != null) ? 1f : 0f);
|
||||
m_leftTargetActive = false;
|
||||
}
|
||||
|
||||
if(l_data.m_rightHand.m_present && !m_rightTargetActive)
|
||||
{
|
||||
m_vrIK.solver.rightArm.target = m_rightHandTarget;
|
||||
m_vrIK.solver.rightArm.bendGoal = LeapTracking.Instance.GetRightElbow();
|
||||
m_vrIK.solver.rightArm.bendGoalWeight = (m_trackElbows ? 1f : 0f);
|
||||
m_rightTargetActive = true;
|
||||
}
|
||||
if(!l_data.m_rightHand.m_present && m_rightTargetActive)
|
||||
{
|
||||
m_vrIK.solver.rightArm.target = m_origRightHand;
|
||||
m_vrIK.solver.rightArm.bendGoal = m_origRightElbow;
|
||||
m_vrIK.solver.rightArm.bendGoalWeight = ((m_origRightElbow != null) ? 1f : 0f);
|
||||
m_rightTargetActive = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void LateUpdate()
|
||||
{
|
||||
if(m_enabled && !m_inVR && (m_poseHandler != null))
|
||||
{
|
||||
LeapParser.LeapData l_data = LeapManager.Instance.GetLatestData();
|
||||
|
||||
Vector3 l_hipsLocalPos = m_hips.localPosition;
|
||||
Quaternion l_hipsLocalRot = m_hips.localRotation;
|
||||
|
||||
m_poseHandler.GetHumanPose(ref m_pose);
|
||||
UpdateFingers(l_data);
|
||||
m_poseHandler.SetHumanPose(ref m_pose);
|
||||
|
||||
m_hips.localPosition = l_hipsLocalPos;
|
||||
m_hips.localRotation = l_hipsLocalRot;
|
||||
}
|
||||
}
|
||||
|
||||
// Tracking update
|
||||
void UpdateFingers(LeapParser.LeapData p_data)
|
||||
{
|
||||
if(p_data.m_leftHand.m_present)
|
||||
{
|
||||
UpdatePoseMuscle(ref m_pose, (int)MuscleIndex.LeftThumb1Stretched, -0.5f - p_data.m_leftHand.m_bends[0]);
|
||||
UpdatePoseMuscle(ref m_pose, (int)MuscleIndex.LeftThumb2Stretched, 0.7f - p_data.m_leftHand.m_bends[0] * 2f);
|
||||
UpdatePoseMuscle(ref m_pose, (int)MuscleIndex.LeftThumb3Stretched, 0.7f - p_data.m_leftHand.m_bends[0] * 2f);
|
||||
UpdatePoseMuscle(ref m_pose, (int)MuscleIndex.LeftThumbSpread, -p_data.m_leftHand.m_spreads[0]);
|
||||
|
||||
UpdatePoseMuscle(ref m_pose, (int)MuscleIndex.LeftIndex1Stretched, 0.5f - p_data.m_leftHand.m_bends[1]);
|
||||
UpdatePoseMuscle(ref m_pose, (int)MuscleIndex.LeftIndex2Stretched, 0.7f - p_data.m_leftHand.m_bends[1] * 2f);
|
||||
UpdatePoseMuscle(ref m_pose, (int)MuscleIndex.LeftIndex3Stretched, 0.7f - p_data.m_leftHand.m_bends[1] * 2f);
|
||||
UpdatePoseMuscle(ref m_pose, (int)MuscleIndex.LeftIndexSpread, p_data.m_leftHand.m_spreads[1]);
|
||||
|
||||
UpdatePoseMuscle(ref m_pose, (int)MuscleIndex.LeftMiddle1Stretched, 0.5f - p_data.m_leftHand.m_bends[2]);
|
||||
UpdatePoseMuscle(ref m_pose, (int)MuscleIndex.LeftMiddle2Stretched, 0.7f - p_data.m_leftHand.m_bends[2] * 2f);
|
||||
UpdatePoseMuscle(ref m_pose, (int)MuscleIndex.LeftMiddle3Stretched, 0.7f - p_data.m_leftHand.m_bends[2] * 2f);
|
||||
UpdatePoseMuscle(ref m_pose, (int)MuscleIndex.LeftMiddleSpread, p_data.m_leftHand.m_spreads[2]);
|
||||
|
||||
UpdatePoseMuscle(ref m_pose, (int)MuscleIndex.LeftRing1Stretched, 0.5f - p_data.m_leftHand.m_bends[3]);
|
||||
UpdatePoseMuscle(ref m_pose, (int)MuscleIndex.LeftRing2Stretched, 0.7f - p_data.m_leftHand.m_bends[3] * 2f);
|
||||
UpdatePoseMuscle(ref m_pose, (int)MuscleIndex.LeftRing3Stretched, 0.7f - p_data.m_leftHand.m_bends[3] * 2f);
|
||||
UpdatePoseMuscle(ref m_pose, (int)MuscleIndex.LeftRingSpread, -p_data.m_leftHand.m_spreads[3]);
|
||||
|
||||
UpdatePoseMuscle(ref m_pose, (int)MuscleIndex.LeftLittle1Stretched, 0.5f - p_data.m_leftHand.m_bends[4]);
|
||||
UpdatePoseMuscle(ref m_pose, (int)MuscleIndex.LeftLittle2Stretched, 0.7f - p_data.m_leftHand.m_bends[4] * 2f);
|
||||
UpdatePoseMuscle(ref m_pose, (int)MuscleIndex.LeftLittle3Stretched, 0.7f - p_data.m_leftHand.m_bends[4] * 2f);
|
||||
UpdatePoseMuscle(ref m_pose, (int)MuscleIndex.LeftLittleSpread, -p_data.m_leftHand.m_spreads[4]);
|
||||
}
|
||||
|
||||
if(p_data.m_rightHand.m_present)
|
||||
{
|
||||
UpdatePoseMuscle(ref m_pose, (int)MuscleIndex.RightThumb1Stretched, -0.5f - p_data.m_rightHand.m_bends[0]);
|
||||
UpdatePoseMuscle(ref m_pose, (int)MuscleIndex.RightThumb2Stretched, 0.7f - p_data.m_rightHand.m_bends[0] * 2f);
|
||||
UpdatePoseMuscle(ref m_pose, (int)MuscleIndex.RightThumb3Stretched, 0.7f - p_data.m_rightHand.m_bends[0] * 2f);
|
||||
UpdatePoseMuscle(ref m_pose, (int)MuscleIndex.RightThumbSpread, -p_data.m_rightHand.m_spreads[0]);
|
||||
|
||||
UpdatePoseMuscle(ref m_pose, (int)MuscleIndex.RightIndex1Stretched, 0.5f - p_data.m_rightHand.m_bends[1]);
|
||||
UpdatePoseMuscle(ref m_pose, (int)MuscleIndex.RightIndex2Stretched, 0.7f - p_data.m_rightHand.m_bends[1] * 2f);
|
||||
UpdatePoseMuscle(ref m_pose, (int)MuscleIndex.RightIndex3Stretched, 0.7f - p_data.m_rightHand.m_bends[1] * 2f);
|
||||
UpdatePoseMuscle(ref m_pose, (int)MuscleIndex.RightIndexSpread, p_data.m_rightHand.m_spreads[1]);
|
||||
|
||||
UpdatePoseMuscle(ref m_pose, (int)MuscleIndex.RightMiddle1Stretched, 0.5f - p_data.m_rightHand.m_bends[2]);
|
||||
UpdatePoseMuscle(ref m_pose, (int)MuscleIndex.RightMiddle2Stretched, 0.7f - p_data.m_rightHand.m_bends[2] * 2f);
|
||||
UpdatePoseMuscle(ref m_pose, (int)MuscleIndex.RightMiddle3Stretched, 0.7f - p_data.m_rightHand.m_bends[2] * 2f);
|
||||
UpdatePoseMuscle(ref m_pose, (int)MuscleIndex.RightMiddleSpread, p_data.m_rightHand.m_spreads[2]);
|
||||
|
||||
UpdatePoseMuscle(ref m_pose, (int)MuscleIndex.RightRing1Stretched, 0.5f - p_data.m_rightHand.m_bends[3]);
|
||||
UpdatePoseMuscle(ref m_pose, (int)MuscleIndex.RightRing2Stretched, 0.7f - p_data.m_rightHand.m_bends[3] * 2f);
|
||||
UpdatePoseMuscle(ref m_pose, (int)MuscleIndex.RightRing3Stretched, 0.7f - p_data.m_rightHand.m_bends[3] * 2f);
|
||||
UpdatePoseMuscle(ref m_pose, (int)MuscleIndex.RightRingSpread, -p_data.m_rightHand.m_spreads[3]);
|
||||
|
||||
UpdatePoseMuscle(ref m_pose, (int)MuscleIndex.RightLittle1Stretched, 0.5f - p_data.m_rightHand.m_bends[4]);
|
||||
UpdatePoseMuscle(ref m_pose, (int)MuscleIndex.RightLittle2Stretched, 0.7f - p_data.m_rightHand.m_bends[4] * 2f);
|
||||
UpdatePoseMuscle(ref m_pose, (int)MuscleIndex.RightLittle3Stretched, 0.7f - p_data.m_rightHand.m_bends[4] * 2f);
|
||||
UpdatePoseMuscle(ref m_pose, (int)MuscleIndex.RightLittleSpread, -p_data.m_rightHand.m_spreads[4]);
|
||||
}
|
||||
}
|
||||
|
||||
// Game events
|
||||
internal void OnAvatarClear()
|
||||
{
|
||||
m_vrIK = null;
|
||||
m_origLeftHand = null;
|
||||
m_origRightHand = null;
|
||||
m_origLeftElbow = null;
|
||||
m_origRightElbow = null;
|
||||
m_hips = null;
|
||||
m_armsWeights = Vector2.zero;
|
||||
m_leftArmIK = null;
|
||||
m_rightArmIK = null;
|
||||
m_leftTargetActive = false;
|
||||
m_rightTargetActive = false;
|
||||
|
||||
if(!m_inVR)
|
||||
m_poseHandler?.Dispose();
|
||||
m_poseHandler = null;
|
||||
|
||||
m_leftHandTarget.localPosition = Vector3.zero;
|
||||
m_leftHandTarget.localRotation = Quaternion.identity;
|
||||
m_rightHandTarget.localPosition = Vector3.zero;
|
||||
m_rightHandTarget.localRotation = Quaternion.identity;
|
||||
}
|
||||
|
||||
internal void OnAvatarSetup()
|
||||
{
|
||||
m_inVR = Utils.IsInVR();
|
||||
m_vrIK = PlayerSetup.Instance._animator.GetComponent<VRIK>();
|
||||
|
||||
if(PlayerSetup.Instance._animator.isHuman)
|
||||
{
|
||||
Vector3 l_hipsPos = Vector3.zero;
|
||||
m_hips = PlayerSetup.Instance._animator.GetBoneTransform(HumanBodyBones.Hips);
|
||||
if(m_hips != null)
|
||||
l_hipsPos = m_hips.localPosition;
|
||||
|
||||
if(!m_inVR)
|
||||
{
|
||||
// Force desktop avatar into T-Pose
|
||||
m_poseHandler = new HumanPoseHandler(PlayerSetup.Instance._animator.avatar, PlayerSetup.Instance._avatar.transform);
|
||||
m_poseHandler.GetHumanPose(ref m_pose);
|
||||
|
||||
HumanPose l_tPose = new HumanPose
|
||||
{
|
||||
bodyPosition = m_pose.bodyPosition,
|
||||
bodyRotation = m_pose.bodyRotation,
|
||||
muscles = new float[m_pose.muscles.Length]
|
||||
};
|
||||
for(int i = 0; i < l_tPose.muscles.Length; i++)
|
||||
l_tPose.muscles[i] = ms_tposeMuscles[i];
|
||||
m_poseHandler.SetHumanPose(ref l_tPose);
|
||||
}
|
||||
|
||||
Transform l_hand = PlayerSetup.Instance._animator.GetBoneTransform(HumanBodyBones.LeftHand);
|
||||
if(l_hand != null)
|
||||
m_leftHandTarget.localRotation = ms_offsetLeft * (PlayerSetup.Instance._avatar.transform.GetMatrix().inverse * l_hand.GetMatrix()).rotation;
|
||||
|
||||
l_hand = PlayerSetup.Instance._animator.GetBoneTransform(HumanBodyBones.RightHand);
|
||||
if(l_hand != null)
|
||||
m_rightHandTarget.localRotation = ms_offsetRight * (PlayerSetup.Instance._avatar.transform.GetMatrix().inverse * l_hand.GetMatrix()).rotation;
|
||||
|
||||
if(m_vrIK == null)
|
||||
{
|
||||
Transform l_chest = PlayerSetup.Instance._animator.GetBoneTransform(HumanBodyBones.UpperChest);
|
||||
if(l_chest == null)
|
||||
l_chest = PlayerSetup.Instance._animator.GetBoneTransform(HumanBodyBones.Chest);
|
||||
if(l_chest == null)
|
||||
l_chest = PlayerSetup.Instance._animator.GetBoneTransform(HumanBodyBones.Spine);
|
||||
|
||||
m_leftArmIK = PlayerSetup.Instance._avatar.AddComponent<ArmIK>();
|
||||
m_leftArmIK.solver.isLeft = true;
|
||||
m_leftArmIK.solver.SetChain(
|
||||
l_chest,
|
||||
PlayerSetup.Instance._animator.GetBoneTransform(HumanBodyBones.LeftShoulder),
|
||||
PlayerSetup.Instance._animator.GetBoneTransform(HumanBodyBones.LeftUpperArm),
|
||||
PlayerSetup.Instance._animator.GetBoneTransform(HumanBodyBones.LeftLowerArm),
|
||||
PlayerSetup.Instance._animator.GetBoneTransform(HumanBodyBones.LeftHand),
|
||||
PlayerSetup.Instance._animator.transform
|
||||
);
|
||||
m_leftArmIK.solver.arm.target = m_leftHandTarget;
|
||||
m_leftArmIK.solver.arm.bendGoal = LeapTracking.Instance.GetLeftElbow();
|
||||
m_leftArmIK.solver.arm.bendGoalWeight = (m_trackElbows ? 1f : 0f);
|
||||
m_leftArmIK.enabled = (m_enabled && !m_fingersOnly);
|
||||
|
||||
m_rightArmIK = PlayerSetup.Instance._avatar.AddComponent<ArmIK>();
|
||||
m_rightArmIK.solver.isLeft = false;
|
||||
m_rightArmIK.solver.SetChain(
|
||||
l_chest,
|
||||
PlayerSetup.Instance._animator.GetBoneTransform(HumanBodyBones.RightShoulder),
|
||||
PlayerSetup.Instance._animator.GetBoneTransform(HumanBodyBones.RightUpperArm),
|
||||
PlayerSetup.Instance._animator.GetBoneTransform(HumanBodyBones.RightLowerArm),
|
||||
PlayerSetup.Instance._animator.GetBoneTransform(HumanBodyBones.RightHand),
|
||||
PlayerSetup.Instance._animator.transform
|
||||
);
|
||||
m_rightArmIK.solver.arm.target = m_rightHandTarget;
|
||||
m_rightArmIK.solver.arm.bendGoal = LeapTracking.Instance.GetRightElbow();
|
||||
m_rightArmIK.solver.arm.bendGoalWeight = (m_trackElbows ? 1f : 0f);
|
||||
m_rightArmIK.enabled = (m_enabled && !m_fingersOnly);
|
||||
|
||||
m_poseHandler?.SetHumanPose(ref m_pose);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_origLeftHand = m_vrIK.solver.leftArm.target;
|
||||
m_origRightHand = m_vrIK.solver.rightArm.target;
|
||||
m_origLeftElbow = m_vrIK.solver.leftArm.bendGoal;
|
||||
m_origRightElbow = m_vrIK.solver.rightArm.bendGoal;
|
||||
m_vrIK.solver.OnPreUpdate += this.OnIKPreUpdate;
|
||||
m_vrIK.solver.OnPostUpdate += this.OnIKPostUpdate;
|
||||
}
|
||||
|
||||
if(m_hips != null)
|
||||
m_hips.localPosition = l_hipsPos;
|
||||
}
|
||||
}
|
||||
|
||||
internal void OnCalibrate()
|
||||
{
|
||||
if(m_vrIK != null)
|
||||
{
|
||||
m_origLeftHand = m_vrIK.solver.leftArm.target;
|
||||
m_origRightHand = m_vrIK.solver.rightArm.target;
|
||||
m_origLeftElbow = m_vrIK.solver.leftArm.bendGoal;
|
||||
m_origRightElbow = m_vrIK.solver.rightArm.bendGoal;
|
||||
}
|
||||
}
|
||||
|
||||
// IK updates
|
||||
void OnIKPreUpdate()
|
||||
{
|
||||
m_armsWeights.Set(
|
||||
m_vrIK.solver.leftArm.positionWeight,
|
||||
m_vrIK.solver.leftArm.rotationWeight,
|
||||
m_vrIK.solver.rightArm.positionWeight,
|
||||
m_vrIK.solver.rightArm.rotationWeight
|
||||
);
|
||||
|
||||
if(m_leftTargetActive && (Mathf.Approximately(m_armsWeights.x, 0f) || Mathf.Approximately(m_armsWeights.y, 0f)))
|
||||
{
|
||||
m_vrIK.solver.leftArm.positionWeight = 1f;
|
||||
m_vrIK.solver.leftArm.rotationWeight = 1f;
|
||||
}
|
||||
if(m_rightTargetActive && (Mathf.Approximately(m_armsWeights.z, 0f) || Mathf.Approximately(m_armsWeights.w, 0f)))
|
||||
{
|
||||
m_vrIK.solver.rightArm.positionWeight = 1f;
|
||||
m_vrIK.solver.rightArm.rotationWeight = 1f;
|
||||
}
|
||||
}
|
||||
void OnIKPostUpdate()
|
||||
{
|
||||
m_vrIK.solver.leftArm.positionWeight = m_armsWeights.x;
|
||||
m_vrIK.solver.leftArm.rotationWeight = m_armsWeights.y;
|
||||
m_vrIK.solver.rightArm.positionWeight = m_armsWeights.z;
|
||||
m_vrIK.solver.rightArm.rotationWeight = m_armsWeights.w;
|
||||
}
|
||||
|
||||
// Settings
|
||||
void OnEnabledChange(bool p_state)
|
||||
{
|
||||
m_enabled = p_state;
|
||||
|
||||
RefreshArmIK();
|
||||
if(!m_enabled || m_fingersOnly)
|
||||
RestoreVRIK();
|
||||
}
|
||||
|
||||
void OnFingersOnlyChange(bool p_state)
|
||||
{
|
||||
m_fingersOnly = p_state;
|
||||
|
||||
RefreshArmIK();
|
||||
if(!m_enabled || m_fingersOnly)
|
||||
RestoreVRIK();
|
||||
}
|
||||
|
||||
void OnTrackElbowsChange(bool p_state)
|
||||
{
|
||||
m_trackElbows = p_state;
|
||||
|
||||
if((m_leftArmIK != null) && (m_rightArmIK != null))
|
||||
{
|
||||
m_leftArmIK.solver.arm.bendGoalWeight = (m_trackElbows ? 1f : 0f);
|
||||
m_rightArmIK.solver.arm.bendGoalWeight = (m_trackElbows ? 1f : 0f);
|
||||
}
|
||||
|
||||
RestoreVRIK();
|
||||
}
|
||||
|
||||
// Arbitrary
|
||||
void RestoreVRIK()
|
||||
{
|
||||
if(m_vrIK != null)
|
||||
{
|
||||
if(m_leftTargetActive)
|
||||
{
|
||||
m_vrIK.solver.leftArm.target = m_origLeftHand;
|
||||
m_vrIK.solver.leftArm.bendGoal = m_origLeftElbow;
|
||||
m_vrIK.solver.leftArm.bendGoalWeight = ((m_origLeftElbow != null) ? 1f : 0f);
|
||||
m_leftTargetActive = false;
|
||||
}
|
||||
if(m_rightTargetActive)
|
||||
{
|
||||
m_vrIK.solver.rightArm.target = m_origRightHand;
|
||||
m_vrIK.solver.rightArm.bendGoal = m_origRightElbow;
|
||||
m_vrIK.solver.rightArm.bendGoalWeight = ((m_origRightElbow != null) ? 1f : 0f);
|
||||
m_rightTargetActive = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void RefreshArmIK()
|
||||
{
|
||||
if((m_leftArmIK != null) && (m_rightArmIK != null))
|
||||
{
|
||||
m_leftArmIK.enabled = (m_enabled && !m_fingersOnly);
|
||||
m_rightArmIK.enabled = (m_enabled && !m_fingersOnly);
|
||||
}
|
||||
}
|
||||
|
||||
static void UpdatePoseMuscle(ref HumanPose p_pose, int p_index, float p_value)
|
||||
{
|
||||
if(p_pose.muscles.Length > p_index)
|
||||
p_pose.muscles[p_index] = p_value;
|
||||
}
|
||||
}
|
||||
}
|
||||
using ABI_RC.Core.Player;
|
||||
using ABI_RC.Systems.IK;
|
||||
using RootMotion.FinalIK;
|
||||
using System.Reflection;
|
||||
using UnityEngine;
|
||||
|
||||
namespace ml_lme
|
||||
{
|
||||
[DisallowMultipleComponent]
|
||||
class LeapTracked : MonoBehaviour
|
||||
{
|
||||
static readonly float[] ms_tposeMuscles = typeof(ABI_RC.Systems.IK.SubSystems.BodySystem).GetField("TPoseMuscles", BindingFlags.Static | BindingFlags.NonPublic).GetValue(null) as float[];
|
||||
static readonly Quaternion ms_offsetLeft = Quaternion.Euler(0f, 90f, 0f);
|
||||
static readonly Quaternion ms_offsetRight = Quaternion.Euler(0f, 270f, 0f);
|
||||
|
||||
VRIK m_vrIK = null;
|
||||
Vector4 m_vrIKWeights = Vector2.zero;
|
||||
bool m_inVR = false;
|
||||
Transform m_hips = null;
|
||||
Transform m_origLeftHand = null;
|
||||
Transform m_origRightHand = null;
|
||||
Transform m_origLeftElbow = null;
|
||||
Transform m_origRightElbow = null;
|
||||
|
||||
bool m_enabled = true;
|
||||
bool m_fingersOnly = false;
|
||||
bool m_trackElbows = true;
|
||||
|
||||
ArmIK m_leftArmIK = null;
|
||||
ArmIK m_rightArmIK = null;
|
||||
HumanPoseHandler m_poseHandler = null;
|
||||
HumanPose m_pose;
|
||||
Transform m_leftHandTarget = null;
|
||||
Transform m_rightHandTarget = null;
|
||||
bool m_leftTargetActive = false;
|
||||
bool m_rightTargetActive = false;
|
||||
|
||||
// Unity events
|
||||
void Start()
|
||||
{
|
||||
m_inVR = Utils.IsInVR();
|
||||
|
||||
m_leftHandTarget = new GameObject("RotationTarget").transform;
|
||||
m_leftHandTarget.parent = LeapTracking.Instance.GetLeftHand();
|
||||
m_leftHandTarget.localPosition = Vector3.zero;
|
||||
m_leftHandTarget.localRotation = Quaternion.identity;
|
||||
|
||||
m_rightHandTarget = new GameObject("RotationTarget").transform;
|
||||
m_rightHandTarget.parent = LeapTracking.Instance.GetRightHand();
|
||||
m_rightHandTarget.localPosition = Vector3.zero;
|
||||
m_rightHandTarget.localRotation = Quaternion.identity;
|
||||
|
||||
Settings.EnabledChange += this.OnEnabledChange;
|
||||
Settings.FingersOnlyChange += this.OnFingersOnlyChange;
|
||||
Settings.TrackElbowsChange += this.OnTrackElbowsChange;
|
||||
|
||||
OnEnabledChange(Settings.Enabled);
|
||||
OnFingersOnlyChange(Settings.FingersOnly);
|
||||
OnTrackElbowsChange(Settings.TrackElbows);
|
||||
}
|
||||
|
||||
void OnDestroy()
|
||||
{
|
||||
Settings.EnabledChange -= this.OnEnabledChange;
|
||||
Settings.FingersOnlyChange -= this.OnFingersOnlyChange;
|
||||
Settings.TrackElbowsChange -= this.OnTrackElbowsChange;
|
||||
}
|
||||
|
||||
void Update()
|
||||
{
|
||||
if(m_enabled)
|
||||
{
|
||||
LeapParser.LeapData l_data = LeapManager.Instance.GetLatestData();
|
||||
|
||||
if((m_leftArmIK != null) && (m_rightArmIK != null))
|
||||
{
|
||||
m_leftArmIK.solver.IKPositionWeight = Mathf.Lerp(m_leftArmIK.solver.IKPositionWeight, (l_data.m_leftHand.m_present && !m_fingersOnly) ? 1f : 0f, 0.25f);
|
||||
m_leftArmIK.solver.IKRotationWeight = Mathf.Lerp(m_leftArmIK.solver.IKRotationWeight, (l_data.m_leftHand.m_present && !m_fingersOnly) ? 1f : 0f, 0.25f);
|
||||
if(m_trackElbows)
|
||||
m_leftArmIK.solver.arm.bendGoalWeight = Mathf.Lerp(m_leftArmIK.solver.arm.bendGoalWeight, (l_data.m_leftHand.m_present && !m_fingersOnly) ? 1f : 0f, 0.25f);
|
||||
|
||||
m_rightArmIK.solver.IKPositionWeight = Mathf.Lerp(m_rightArmIK.solver.IKPositionWeight, (l_data.m_rightHand.m_present && !m_fingersOnly) ? 1f : 0f, 0.25f);
|
||||
m_rightArmIK.solver.IKRotationWeight = Mathf.Lerp(m_rightArmIK.solver.IKRotationWeight, (l_data.m_rightHand.m_present && !m_fingersOnly) ? 1f : 0f, 0.25f);
|
||||
if(m_trackElbows)
|
||||
m_rightArmIK.solver.arm.bendGoalWeight = Mathf.Lerp(m_rightArmIK.solver.arm.bendGoalWeight, (l_data.m_rightHand.m_present && !m_fingersOnly) ? 1f : 0f, 0.25f);
|
||||
}
|
||||
|
||||
if((m_vrIK != null) && !m_fingersOnly)
|
||||
{
|
||||
m_leftTargetActive = l_data.m_leftHand.m_present;
|
||||
m_rightTargetActive = l_data.m_rightHand.m_present;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void LateUpdate()
|
||||
{
|
||||
if(m_enabled && !m_inVR && (m_poseHandler != null))
|
||||
{
|
||||
LeapParser.LeapData l_data = LeapManager.Instance.GetLatestData();
|
||||
|
||||
Vector3 l_hipsLocalPos = m_hips.localPosition;
|
||||
Quaternion l_hipsLocalRot = m_hips.localRotation;
|
||||
|
||||
m_poseHandler.GetHumanPose(ref m_pose);
|
||||
UpdateFingers(l_data);
|
||||
m_poseHandler.SetHumanPose(ref m_pose);
|
||||
|
||||
m_hips.localPosition = l_hipsLocalPos;
|
||||
m_hips.localRotation = l_hipsLocalRot;
|
||||
}
|
||||
}
|
||||
|
||||
// Tracking update
|
||||
void UpdateFingers(LeapParser.LeapData p_data)
|
||||
{
|
||||
if(p_data.m_leftHand.m_present)
|
||||
{
|
||||
UpdatePoseMuscle(ref m_pose, (int)MuscleIndex.LeftThumb1Stretched, -0.5f - p_data.m_leftHand.m_bends[0]);
|
||||
UpdatePoseMuscle(ref m_pose, (int)MuscleIndex.LeftThumb2Stretched, 0.7f - p_data.m_leftHand.m_bends[0] * 2f);
|
||||
UpdatePoseMuscle(ref m_pose, (int)MuscleIndex.LeftThumb3Stretched, 0.7f - p_data.m_leftHand.m_bends[0] * 2f);
|
||||
UpdatePoseMuscle(ref m_pose, (int)MuscleIndex.LeftThumbSpread, -p_data.m_leftHand.m_spreads[0]);
|
||||
|
||||
UpdatePoseMuscle(ref m_pose, (int)MuscleIndex.LeftIndex1Stretched, 0.5f - p_data.m_leftHand.m_bends[1]);
|
||||
UpdatePoseMuscle(ref m_pose, (int)MuscleIndex.LeftIndex2Stretched, 0.7f - p_data.m_leftHand.m_bends[1] * 2f);
|
||||
UpdatePoseMuscle(ref m_pose, (int)MuscleIndex.LeftIndex3Stretched, 0.7f - p_data.m_leftHand.m_bends[1] * 2f);
|
||||
UpdatePoseMuscle(ref m_pose, (int)MuscleIndex.LeftIndexSpread, p_data.m_leftHand.m_spreads[1]);
|
||||
|
||||
UpdatePoseMuscle(ref m_pose, (int)MuscleIndex.LeftMiddle1Stretched, 0.5f - p_data.m_leftHand.m_bends[2]);
|
||||
UpdatePoseMuscle(ref m_pose, (int)MuscleIndex.LeftMiddle2Stretched, 0.7f - p_data.m_leftHand.m_bends[2] * 2f);
|
||||
UpdatePoseMuscle(ref m_pose, (int)MuscleIndex.LeftMiddle3Stretched, 0.7f - p_data.m_leftHand.m_bends[2] * 2f);
|
||||
UpdatePoseMuscle(ref m_pose, (int)MuscleIndex.LeftMiddleSpread, p_data.m_leftHand.m_spreads[2]);
|
||||
|
||||
UpdatePoseMuscle(ref m_pose, (int)MuscleIndex.LeftRing1Stretched, 0.5f - p_data.m_leftHand.m_bends[3]);
|
||||
UpdatePoseMuscle(ref m_pose, (int)MuscleIndex.LeftRing2Stretched, 0.7f - p_data.m_leftHand.m_bends[3] * 2f);
|
||||
UpdatePoseMuscle(ref m_pose, (int)MuscleIndex.LeftRing3Stretched, 0.7f - p_data.m_leftHand.m_bends[3] * 2f);
|
||||
UpdatePoseMuscle(ref m_pose, (int)MuscleIndex.LeftRingSpread, -p_data.m_leftHand.m_spreads[3]);
|
||||
|
||||
UpdatePoseMuscle(ref m_pose, (int)MuscleIndex.LeftLittle1Stretched, 0.5f - p_data.m_leftHand.m_bends[4]);
|
||||
UpdatePoseMuscle(ref m_pose, (int)MuscleIndex.LeftLittle2Stretched, 0.7f - p_data.m_leftHand.m_bends[4] * 2f);
|
||||
UpdatePoseMuscle(ref m_pose, (int)MuscleIndex.LeftLittle3Stretched, 0.7f - p_data.m_leftHand.m_bends[4] * 2f);
|
||||
UpdatePoseMuscle(ref m_pose, (int)MuscleIndex.LeftLittleSpread, -p_data.m_leftHand.m_spreads[4]);
|
||||
}
|
||||
|
||||
if(p_data.m_rightHand.m_present)
|
||||
{
|
||||
UpdatePoseMuscle(ref m_pose, (int)MuscleIndex.RightThumb1Stretched, -0.5f - p_data.m_rightHand.m_bends[0]);
|
||||
UpdatePoseMuscle(ref m_pose, (int)MuscleIndex.RightThumb2Stretched, 0.7f - p_data.m_rightHand.m_bends[0] * 2f);
|
||||
UpdatePoseMuscle(ref m_pose, (int)MuscleIndex.RightThumb3Stretched, 0.7f - p_data.m_rightHand.m_bends[0] * 2f);
|
||||
UpdatePoseMuscle(ref m_pose, (int)MuscleIndex.RightThumbSpread, -p_data.m_rightHand.m_spreads[0]);
|
||||
|
||||
UpdatePoseMuscle(ref m_pose, (int)MuscleIndex.RightIndex1Stretched, 0.5f - p_data.m_rightHand.m_bends[1]);
|
||||
UpdatePoseMuscle(ref m_pose, (int)MuscleIndex.RightIndex2Stretched, 0.7f - p_data.m_rightHand.m_bends[1] * 2f);
|
||||
UpdatePoseMuscle(ref m_pose, (int)MuscleIndex.RightIndex3Stretched, 0.7f - p_data.m_rightHand.m_bends[1] * 2f);
|
||||
UpdatePoseMuscle(ref m_pose, (int)MuscleIndex.RightIndexSpread, p_data.m_rightHand.m_spreads[1]);
|
||||
|
||||
UpdatePoseMuscle(ref m_pose, (int)MuscleIndex.RightMiddle1Stretched, 0.5f - p_data.m_rightHand.m_bends[2]);
|
||||
UpdatePoseMuscle(ref m_pose, (int)MuscleIndex.RightMiddle2Stretched, 0.7f - p_data.m_rightHand.m_bends[2] * 2f);
|
||||
UpdatePoseMuscle(ref m_pose, (int)MuscleIndex.RightMiddle3Stretched, 0.7f - p_data.m_rightHand.m_bends[2] * 2f);
|
||||
UpdatePoseMuscle(ref m_pose, (int)MuscleIndex.RightMiddleSpread, p_data.m_rightHand.m_spreads[2]);
|
||||
|
||||
UpdatePoseMuscle(ref m_pose, (int)MuscleIndex.RightRing1Stretched, 0.5f - p_data.m_rightHand.m_bends[3]);
|
||||
UpdatePoseMuscle(ref m_pose, (int)MuscleIndex.RightRing2Stretched, 0.7f - p_data.m_rightHand.m_bends[3] * 2f);
|
||||
UpdatePoseMuscle(ref m_pose, (int)MuscleIndex.RightRing3Stretched, 0.7f - p_data.m_rightHand.m_bends[3] * 2f);
|
||||
UpdatePoseMuscle(ref m_pose, (int)MuscleIndex.RightRingSpread, -p_data.m_rightHand.m_spreads[3]);
|
||||
|
||||
UpdatePoseMuscle(ref m_pose, (int)MuscleIndex.RightLittle1Stretched, 0.5f - p_data.m_rightHand.m_bends[4]);
|
||||
UpdatePoseMuscle(ref m_pose, (int)MuscleIndex.RightLittle2Stretched, 0.7f - p_data.m_rightHand.m_bends[4] * 2f);
|
||||
UpdatePoseMuscle(ref m_pose, (int)MuscleIndex.RightLittle3Stretched, 0.7f - p_data.m_rightHand.m_bends[4] * 2f);
|
||||
UpdatePoseMuscle(ref m_pose, (int)MuscleIndex.RightLittleSpread, -p_data.m_rightHand.m_spreads[4]);
|
||||
}
|
||||
}
|
||||
|
||||
// Game events
|
||||
internal void OnAvatarClear()
|
||||
{
|
||||
m_vrIK = null;
|
||||
m_origLeftHand = null;
|
||||
m_origRightHand = null;
|
||||
m_origLeftElbow = null;
|
||||
m_origRightElbow = null;
|
||||
m_hips = null;
|
||||
m_vrIKWeights = Vector2.zero;
|
||||
m_leftArmIK = null;
|
||||
m_rightArmIK = null;
|
||||
m_leftTargetActive = false;
|
||||
m_rightTargetActive = false;
|
||||
|
||||
if(!m_inVR)
|
||||
m_poseHandler?.Dispose();
|
||||
m_poseHandler = null;
|
||||
|
||||
m_leftHandTarget.localPosition = Vector3.zero;
|
||||
m_leftHandTarget.localRotation = Quaternion.identity;
|
||||
m_rightHandTarget.localPosition = Vector3.zero;
|
||||
m_rightHandTarget.localRotation = Quaternion.identity;
|
||||
}
|
||||
|
||||
internal void OnAvatarSetup()
|
||||
{
|
||||
m_inVR = Utils.IsInVR();
|
||||
m_vrIK = PlayerSetup.Instance._animator.GetComponent<VRIK>();
|
||||
|
||||
if(PlayerSetup.Instance._animator.isHuman)
|
||||
{
|
||||
Vector3 l_hipsPos = Vector3.zero;
|
||||
m_hips = PlayerSetup.Instance._animator.GetBoneTransform(HumanBodyBones.Hips);
|
||||
if(m_hips != null)
|
||||
l_hipsPos = m_hips.localPosition;
|
||||
|
||||
if(!m_inVR)
|
||||
{
|
||||
// Force desktop avatar into T-Pose
|
||||
m_poseHandler = new HumanPoseHandler(PlayerSetup.Instance._animator.avatar, PlayerSetup.Instance._avatar.transform);
|
||||
m_poseHandler.GetHumanPose(ref m_pose);
|
||||
|
||||
HumanPose l_tPose = new HumanPose
|
||||
{
|
||||
bodyPosition = m_pose.bodyPosition,
|
||||
bodyRotation = m_pose.bodyRotation,
|
||||
muscles = new float[m_pose.muscles.Length]
|
||||
};
|
||||
for(int i = 0; i < l_tPose.muscles.Length; i++)
|
||||
l_tPose.muscles[i] = ms_tposeMuscles[i];
|
||||
m_poseHandler.SetHumanPose(ref l_tPose);
|
||||
}
|
||||
|
||||
Transform l_hand = PlayerSetup.Instance._animator.GetBoneTransform(HumanBodyBones.LeftHand);
|
||||
if(l_hand != null)
|
||||
m_leftHandTarget.localRotation = ms_offsetLeft * (PlayerSetup.Instance._avatar.transform.GetMatrix().inverse * l_hand.GetMatrix()).rotation;
|
||||
|
||||
l_hand = PlayerSetup.Instance._animator.GetBoneTransform(HumanBodyBones.RightHand);
|
||||
if(l_hand != null)
|
||||
m_rightHandTarget.localRotation = ms_offsetRight * (PlayerSetup.Instance._avatar.transform.GetMatrix().inverse * l_hand.GetMatrix()).rotation;
|
||||
|
||||
if(m_vrIK == null)
|
||||
{
|
||||
Transform l_chest = PlayerSetup.Instance._animator.GetBoneTransform(HumanBodyBones.UpperChest);
|
||||
if(l_chest == null)
|
||||
l_chest = PlayerSetup.Instance._animator.GetBoneTransform(HumanBodyBones.Chest);
|
||||
if(l_chest == null)
|
||||
l_chest = PlayerSetup.Instance._animator.GetBoneTransform(HumanBodyBones.Spine);
|
||||
|
||||
m_leftArmIK = PlayerSetup.Instance._avatar.AddComponent<ArmIK>();
|
||||
m_leftArmIK.solver.isLeft = true;
|
||||
m_leftArmIK.solver.SetChain(
|
||||
l_chest,
|
||||
PlayerSetup.Instance._animator.GetBoneTransform(HumanBodyBones.LeftShoulder),
|
||||
PlayerSetup.Instance._animator.GetBoneTransform(HumanBodyBones.LeftUpperArm),
|
||||
PlayerSetup.Instance._animator.GetBoneTransform(HumanBodyBones.LeftLowerArm),
|
||||
PlayerSetup.Instance._animator.GetBoneTransform(HumanBodyBones.LeftHand),
|
||||
PlayerSetup.Instance._animator.transform
|
||||
);
|
||||
m_leftArmIK.solver.arm.target = m_leftHandTarget;
|
||||
m_leftArmIK.solver.arm.bendGoal = LeapTracking.Instance.GetLeftElbow();
|
||||
m_leftArmIK.solver.arm.bendGoalWeight = (m_trackElbows ? 1f : 0f);
|
||||
m_leftArmIK.enabled = (m_enabled && !m_fingersOnly);
|
||||
|
||||
m_rightArmIK = PlayerSetup.Instance._avatar.AddComponent<ArmIK>();
|
||||
m_rightArmIK.solver.isLeft = false;
|
||||
m_rightArmIK.solver.SetChain(
|
||||
l_chest,
|
||||
PlayerSetup.Instance._animator.GetBoneTransform(HumanBodyBones.RightShoulder),
|
||||
PlayerSetup.Instance._animator.GetBoneTransform(HumanBodyBones.RightUpperArm),
|
||||
PlayerSetup.Instance._animator.GetBoneTransform(HumanBodyBones.RightLowerArm),
|
||||
PlayerSetup.Instance._animator.GetBoneTransform(HumanBodyBones.RightHand),
|
||||
PlayerSetup.Instance._animator.transform
|
||||
);
|
||||
m_rightArmIK.solver.arm.target = m_rightHandTarget;
|
||||
m_rightArmIK.solver.arm.bendGoal = LeapTracking.Instance.GetRightElbow();
|
||||
m_rightArmIK.solver.arm.bendGoalWeight = (m_trackElbows ? 1f : 0f);
|
||||
m_rightArmIK.enabled = (m_enabled && !m_fingersOnly);
|
||||
|
||||
m_poseHandler?.SetHumanPose(ref m_pose);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_origLeftHand = m_vrIK.solver.leftArm.target;
|
||||
m_origRightHand = m_vrIK.solver.rightArm.target;
|
||||
m_origLeftElbow = m_vrIK.solver.leftArm.bendGoal;
|
||||
m_origRightElbow = m_vrIK.solver.rightArm.bendGoal;
|
||||
m_vrIK.solver.OnPreUpdate += this.OnIKPreUpdate;
|
||||
m_vrIK.solver.OnPostUpdate += this.OnIKPostUpdate;
|
||||
}
|
||||
|
||||
if(m_hips != null)
|
||||
m_hips.localPosition = l_hipsPos;
|
||||
}
|
||||
}
|
||||
|
||||
internal void OnCalibrate()
|
||||
{
|
||||
if(m_vrIK != null)
|
||||
{
|
||||
m_origLeftHand = m_vrIK.solver.leftArm.target;
|
||||
m_origRightHand = m_vrIK.solver.rightArm.target;
|
||||
m_origLeftElbow = m_vrIK.solver.leftArm.bendGoal;
|
||||
m_origRightElbow = m_vrIK.solver.rightArm.bendGoal;
|
||||
}
|
||||
}
|
||||
|
||||
// IK updates
|
||||
void OnIKPreUpdate()
|
||||
{
|
||||
m_vrIKWeights.Set(
|
||||
m_vrIK.solver.leftArm.positionWeight,
|
||||
m_vrIK.solver.leftArm.rotationWeight,
|
||||
m_vrIK.solver.rightArm.positionWeight,
|
||||
m_vrIK.solver.rightArm.rotationWeight
|
||||
);
|
||||
|
||||
if(m_leftTargetActive)
|
||||
{
|
||||
m_vrIK.solver.leftArm.positionWeight = 1f;
|
||||
m_vrIK.solver.leftArm.rotationWeight = 1f;
|
||||
m_vrIK.solver.leftArm.target = m_leftHandTarget;
|
||||
m_vrIK.solver.leftArm.bendGoal = LeapTracking.Instance.GetLeftElbow();
|
||||
m_vrIK.solver.leftArm.bendGoalWeight = (m_trackElbows ? 1f : 0f);
|
||||
}
|
||||
if(m_rightTargetActive)
|
||||
{
|
||||
m_vrIK.solver.rightArm.positionWeight = 1f;
|
||||
m_vrIK.solver.rightArm.rotationWeight = 1f;
|
||||
m_vrIK.solver.rightArm.target = m_rightHandTarget;
|
||||
m_vrIK.solver.rightArm.bendGoal = LeapTracking.Instance.GetRightElbow();
|
||||
m_vrIK.solver.rightArm.bendGoalWeight = (m_trackElbows ? 1f : 0f);
|
||||
}
|
||||
}
|
||||
void OnIKPostUpdate()
|
||||
{
|
||||
m_vrIK.solver.leftArm.positionWeight = m_vrIKWeights.x;
|
||||
m_vrIK.solver.leftArm.rotationWeight = m_vrIKWeights.y;
|
||||
m_vrIK.solver.leftArm.target = m_origLeftHand;
|
||||
m_vrIK.solver.leftArm.bendGoal = m_origLeftElbow;
|
||||
m_vrIK.solver.leftArm.bendGoalWeight = ((m_origLeftElbow != null) ? 1f : 0f);
|
||||
m_vrIK.solver.rightArm.positionWeight = m_vrIKWeights.z;
|
||||
m_vrIK.solver.rightArm.rotationWeight = m_vrIKWeights.w;
|
||||
m_vrIK.solver.rightArm.target = m_origRightHand;
|
||||
m_vrIK.solver.rightArm.bendGoal = m_origRightElbow;
|
||||
m_vrIK.solver.rightArm.bendGoalWeight = ((m_origRightElbow != null) ? 1f : 0f);
|
||||
}
|
||||
|
||||
// Settings
|
||||
void OnEnabledChange(bool p_state)
|
||||
{
|
||||
m_enabled = p_state;
|
||||
|
||||
RefreshArmIK();
|
||||
if(!m_enabled || m_fingersOnly)
|
||||
RestoreVRIK();
|
||||
}
|
||||
|
||||
void OnFingersOnlyChange(bool p_state)
|
||||
{
|
||||
m_fingersOnly = p_state;
|
||||
|
||||
RefreshArmIK();
|
||||
if(!m_enabled || m_fingersOnly)
|
||||
RestoreVRIK();
|
||||
}
|
||||
|
||||
void OnTrackElbowsChange(bool p_state)
|
||||
{
|
||||
m_trackElbows = p_state;
|
||||
|
||||
if((m_leftArmIK != null) && (m_rightArmIK != null))
|
||||
{
|
||||
m_leftArmIK.solver.arm.bendGoalWeight = (m_trackElbows ? 1f : 0f);
|
||||
m_rightArmIK.solver.arm.bendGoalWeight = (m_trackElbows ? 1f : 0f);
|
||||
}
|
||||
|
||||
RestoreVRIK();
|
||||
}
|
||||
|
||||
// Arbitrary
|
||||
void RestoreVRIK()
|
||||
{
|
||||
if(m_vrIK != null)
|
||||
{
|
||||
m_leftTargetActive = false;
|
||||
m_rightTargetActive = false;
|
||||
}
|
||||
}
|
||||
|
||||
void RefreshArmIK()
|
||||
{
|
||||
if((m_leftArmIK != null) && (m_rightArmIK != null))
|
||||
{
|
||||
m_leftArmIK.enabled = (m_enabled && !m_fingersOnly);
|
||||
m_rightArmIK.enabled = (m_enabled && !m_fingersOnly);
|
||||
}
|
||||
}
|
||||
|
||||
static void UpdatePoseMuscle(ref HumanPose p_pose, int p_index, float p_value)
|
||||
{
|
||||
if(p_pose.muscles.Length > p_index)
|
||||
p_pose.muscles[p_index] = p_value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
[assembly: MelonLoader.MelonInfo(typeof(ml_lme.LeapMotionExtension), "LeapMotionExtension", "1.4.4", "SDraw", "https://github.com/SDraw/ml_mods_cvr")]
|
||||
[assembly: MelonLoader.MelonInfo(typeof(ml_lme.LeapMotionExtension), "LeapMotionExtension", "1.4.5", "SDraw", "https://github.com/SDraw/ml_mods_cvr")]
|
||||
[assembly: MelonLoader.MelonGame(null, "ChilloutVR")]
|
||||
[assembly: MelonLoader.MelonOptionalDependencies("ml_pmc")]
|
||||
[assembly: MelonLoader.MelonPlatform(MelonLoader.MelonPlatformAttribute.CompatiblePlatforms.WINDOWS_X64)]
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
<TargetFramework>netstandard2.1</TargetFramework>
|
||||
<Platforms>x64</Platforms>
|
||||
<PackageId>LeapMotionExtension</PackageId>
|
||||
<Version>1.4.4</Version>
|
||||
<Version>1.4.5</Version>
|
||||
<Authors>SDraw</Authors>
|
||||
<Company>None</Company>
|
||||
<Product>LeapMotionExtension</Product>
|
||||
|
|
964
ml_lme/vendor/LeapSDK/LICENSE.md
vendored
964
ml_lme/vendor/LeapSDK/LICENSE.md
vendored
|
@ -1,482 +1,482 @@
|
|||
ULTRALEAP TRACKING SDK AGREEMENT
|
||||
|
||||
Updated: 22 March 2022
|
||||
|
||||
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
|
||||
Ultraleap’s 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 Ultraleap’s prior approval,
|
||||
which will not be unreasonably withheld.
|
||||
|
||||
5.3. Ultraleap may at its option mention you and your products using Ultraleap technology in
|
||||
Ultraleap’s 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 Ultraleap’s 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 Ultraleap’s other products, and
|
||||
for any other purposes set out in Ultraleap’s 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
|
||||
Ultraleap’s 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 Ultraleap’s
|
||||
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 Ultraleap’s 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 Ultraleap’s 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 Ultraleap’s 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),
|
||||
ULTRALEAP’S 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 ULTRALEAP’S 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, Stereo IR 170, Stereo IR 170 EK or Ultraleap 3Di 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.
|
||||
ULTRALEAP TRACKING SDK AGREEMENT
|
||||
|
||||
Updated: 22 March 2022
|
||||
|
||||
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
|
||||
Ultraleap’s 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 Ultraleap’s prior approval,
|
||||
which will not be unreasonably withheld.
|
||||
|
||||
5.3. Ultraleap may at its option mention you and your products using Ultraleap technology in
|
||||
Ultraleap’s 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 Ultraleap’s 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 Ultraleap’s other products, and
|
||||
for any other purposes set out in Ultraleap’s 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
|
||||
Ultraleap’s 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 Ultraleap’s
|
||||
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 Ultraleap’s 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 Ultraleap’s 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 Ultraleap’s 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),
|
||||
ULTRALEAP’S 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 ULTRALEAP’S 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, Stereo IR 170, Stereo IR 170 EK or Ultraleap 3Di 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.
|
||||
|
|
274
ml_lme/vendor/LeapSDK/README.md
vendored
274
ml_lme/vendor/LeapSDK/README.md
vendored
|
@ -1,137 +1,137 @@
|
|||
# Ultraleap SDK
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
## Package contents:
|
||||
|
||||
LeapSDK
|
||||
- include
|
||||
* API headers.
|
||||
- lib
|
||||
* dynamic API library and CMake scripts.
|
||||
- samples
|
||||
* Various samples demonstrating several different usages.
|
||||
- LICENSE.md
|
||||
* Ultraleap Tracking SDK license.
|
||||
- README.md
|
||||
* Ultraleap Tracking SDK readme.
|
||||
- ThirdPartyNotices.md
|
||||
* Ultraleap Tracking SDK third party licenses.
|
||||
|
||||
## 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+ (Windows)
|
||||
* GCC (Linux - tested on v9.4.0)
|
||||
|
||||
## Installation:
|
||||
|
||||
The LeapSDK is installed with Ultraleap Tracking.
|
||||
|
||||
## 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/LeapC.so 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/LeapC.so.
|
||||
|
||||
## Building Samples:
|
||||
|
||||
### Windows
|
||||
|
||||
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
|
||||
|
||||
4. Open and build the CMake generated project files. For more help, see the CMake documentation.
|
||||
* An example script would be :
|
||||
```powershell
|
||||
$env:BUILD_TYPE = 'Release'
|
||||
$env:REPOS_BUILD_ROOT = 'C:/build'
|
||||
$env:REPOS_INSTALL_ROOT = 'C:/Program Files'
|
||||
|
||||
cmake -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
|
||||
```
|
||||
|
||||
### x64 Linux
|
||||
|
||||
1. Open CMake using /usr/share/doc/ultraleap-hand-tracking-service/samples as the source directory
|
||||
|
||||
2. Select a build directory (eg. ~/ultraleap-tracking-samples/build) to use
|
||||
|
||||
3. Configure & Generate CMake with the generator of your choice
|
||||
|
||||
4. Open and build the CMake generated project files. For more help, see the CMake documentation.
|
||||
* An example script would be :
|
||||
```bash
|
||||
SRC_DIR=/usr/share/doc/ultraleap-hand-tracking-service/samples
|
||||
BUILD_TYPE='Release'
|
||||
REPOS_BUILD_ROOT=~/ultraleap-tracking-samples/build
|
||||
REPOS_INSTALL_ROOT=/usr/bin/ultraleap-tracking-samples
|
||||
|
||||
cmake -S ${SRC_DIR} -B ${REPOS_BUILD_ROOT}/${BUILD_TYPE}/LeapSDK/leapc_example `
|
||||
-DCMAKE_INSTALL_PREFIX="${REPOS_INSTALL_ROOT}/leapc_example" `
|
||||
-DCMAKE_BUILD_TYPE="${BUILD_TYPE}"
|
||||
|
||||
cmake --build ${REPOS_BUILD_ROOT}/${BUILD_TYPE}/LeapSDK/leapc_example -j --config ${BUILD_TYPE}
|
||||
```
|
||||
|
||||
### MacOS
|
||||
|
||||
1. Open CMake using /Library/Application Support/Ultraleap/LeapSDK/samples as the source directory
|
||||
|
||||
2. Select a build directory (eg. ~/ultraleap-tracking-samples/build) to use
|
||||
|
||||
3. Configure & Generate CMake with the generator of your choice
|
||||
|
||||
4. Open and build the CMake generated project files. For more help, see the CMake documentation.
|
||||
* An example script would be :
|
||||
```bash
|
||||
SRC_DIR='/Library/Application Support/Ultraleap/LeapSDK/samples'
|
||||
BUILD_TYPE='Release'
|
||||
REPOS_BUILD_ROOT=~/ultraleap-tracking-samples/build
|
||||
REPOS_INSTALL_ROOT=~/ultraleap-tracking-samples/bin
|
||||
|
||||
cmake -S ${SRC_DIR} -B ${REPOS_BUILD_ROOT}/${BUILD_TYPE}/LeapSDK/leapc_example `
|
||||
-DCMAKE_INSTALL_PREFIX="${REPOS_INSTALL_ROOT}/leapc_example" `
|
||||
-DCMAKE_BUILD_TYPE="${BUILD_TYPE}"
|
||||
|
||||
cmake --build ${REPOS_BUILD_ROOT}/${BUILD_TYPE}/LeapSDK/leapc_example -j --config ${BUILD_TYPE}
|
||||
```
|
||||
|
||||
## 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.
|
||||
# Ultraleap SDK
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
## Package contents:
|
||||
|
||||
LeapSDK
|
||||
- include
|
||||
* API headers.
|
||||
- lib
|
||||
* dynamic API library and CMake scripts.
|
||||
- samples
|
||||
* Various samples demonstrating several different usages.
|
||||
- LICENSE.md
|
||||
* Ultraleap Tracking SDK license.
|
||||
- README.md
|
||||
* Ultraleap Tracking SDK readme.
|
||||
- ThirdPartyNotices.md
|
||||
* Ultraleap Tracking SDK third party licenses.
|
||||
|
||||
## 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+ (Windows)
|
||||
* GCC (Linux - tested on v9.4.0)
|
||||
|
||||
## Installation:
|
||||
|
||||
The LeapSDK is installed with Ultraleap Tracking.
|
||||
|
||||
## 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/LeapC.so 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/LeapC.so.
|
||||
|
||||
## Building Samples:
|
||||
|
||||
### Windows
|
||||
|
||||
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
|
||||
|
||||
4. Open and build the CMake generated project files. For more help, see the CMake documentation.
|
||||
* An example script would be :
|
||||
```powershell
|
||||
$env:BUILD_TYPE = 'Release'
|
||||
$env:REPOS_BUILD_ROOT = 'C:/build'
|
||||
$env:REPOS_INSTALL_ROOT = 'C:/Program Files'
|
||||
|
||||
cmake -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
|
||||
```
|
||||
|
||||
### x64 Linux
|
||||
|
||||
1. Open CMake using /usr/share/doc/ultraleap-hand-tracking-service/samples as the source directory
|
||||
|
||||
2. Select a build directory (eg. ~/ultraleap-tracking-samples/build) to use
|
||||
|
||||
3. Configure & Generate CMake with the generator of your choice
|
||||
|
||||
4. Open and build the CMake generated project files. For more help, see the CMake documentation.
|
||||
* An example script would be :
|
||||
```bash
|
||||
SRC_DIR=/usr/share/doc/ultraleap-hand-tracking-service/samples
|
||||
BUILD_TYPE='Release'
|
||||
REPOS_BUILD_ROOT=~/ultraleap-tracking-samples/build
|
||||
REPOS_INSTALL_ROOT=/usr/bin/ultraleap-tracking-samples
|
||||
|
||||
cmake -S ${SRC_DIR} -B ${REPOS_BUILD_ROOT}/${BUILD_TYPE}/LeapSDK/leapc_example `
|
||||
-DCMAKE_INSTALL_PREFIX="${REPOS_INSTALL_ROOT}/leapc_example" `
|
||||
-DCMAKE_BUILD_TYPE="${BUILD_TYPE}"
|
||||
|
||||
cmake --build ${REPOS_BUILD_ROOT}/${BUILD_TYPE}/LeapSDK/leapc_example -j --config ${BUILD_TYPE}
|
||||
```
|
||||
|
||||
### MacOS
|
||||
|
||||
1. Open CMake using /Applications/Ultraleap\ Hand\ Tracking\ Service.app/Contents/LeapSDK/samples as the source directory
|
||||
|
||||
2. Select a build directory (eg. ~/ultraleap-tracking-samples/build) to use
|
||||
|
||||
3. Configure & Generate CMake with the generator of your choice
|
||||
|
||||
4. Open and build the CMake generated project files. For more help, see the CMake documentation.
|
||||
* An example script would be :
|
||||
```bash
|
||||
SRC_DIR='/Applications/Ultraleap\ Hand\ Tracking\ Service.app/Contents/LeapSDK/samples'
|
||||
BUILD_TYPE='Release'
|
||||
REPOS_BUILD_ROOT=~/ultraleap-tracking-samples/build
|
||||
REPOS_INSTALL_ROOT=~/ultraleap-tracking-samples/bin
|
||||
|
||||
cmake -S ${SRC_DIR} -B ${REPOS_BUILD_ROOT}/${BUILD_TYPE}/LeapSDK/leapc_example `
|
||||
-DCMAKE_INSTALL_PREFIX="${REPOS_INSTALL_ROOT}/leapc_example" `
|
||||
-DCMAKE_BUILD_TYPE="${BUILD_TYPE}"
|
||||
|
||||
cmake --build ${REPOS_BUILD_ROOT}/${BUILD_TYPE}/LeapSDK/leapc_example -j --config ${BUILD_TYPE}
|
||||
```
|
||||
|
||||
## 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.
|
||||
|
|
12417
ml_lme/vendor/LeapSDK/ThirdPartyNotices.md
vendored
12417
ml_lme/vendor/LeapSDK/ThirdPartyNotices.md
vendored
File diff suppressed because it is too large
Load diff
64
ml_lme/vendor/LeapSDK/lib/x64/LICENSE.protobuf
vendored
64
ml_lme/vendor/LeapSDK/lib/x64/LICENSE.protobuf
vendored
|
@ -1,32 +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.
|
||||
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.
|
||||
|
|
BIN
ml_lme/vendor/LeapSDK/lib/x64/LeapC.dll
vendored
BIN
ml_lme/vendor/LeapSDK/lib/x64/LeapC.dll
vendored
Binary file not shown.
|
@ -2,7 +2,6 @@
|
|||
using ABI_RC.Core.InteractionSystem;
|
||||
using ABI_RC.Core.Player;
|
||||
using RootMotion.FinalIK;
|
||||
using System.Reflection;
|
||||
using UnityEngine;
|
||||
|
||||
namespace ml_pam
|
||||
|
@ -10,47 +9,72 @@ namespace ml_pam
|
|||
[DisallowMultipleComponent]
|
||||
class ArmMover : MonoBehaviour
|
||||
{
|
||||
const float c_offsetLimit = 0.5f;
|
||||
enum HandState
|
||||
{
|
||||
Empty = 0,
|
||||
Pickup,
|
||||
Extended
|
||||
}
|
||||
|
||||
const float c_offsetLimit = 0.5f;
|
||||
const KeyCode c_leftKey = KeyCode.Q;
|
||||
const KeyCode c_rightKey = KeyCode.E;
|
||||
|
||||
static readonly float[] ms_tposeMuscles = typeof(ABI_RC.Systems.IK.SubSystems.BodySystem).GetField("TPoseMuscles", BindingFlags.Static | BindingFlags.NonPublic).GetValue(null) as float[];
|
||||
static readonly Vector4 ms_pointVector = new Vector4(0f, 0f, 0f, 1f);
|
||||
static readonly Quaternion ms_offsetRight = Quaternion.Euler(0f, 0f, 90f);
|
||||
static readonly Quaternion ms_offsetRightDesktop = Quaternion.Euler(0f, 270f, 0f);
|
||||
static readonly Quaternion ms_palmToLeft = Quaternion.Euler(0f, 0f, -90f);
|
||||
static readonly Quaternion ms_offsetLeft = Quaternion.Euler(270f, 90f, 0f);
|
||||
static readonly Quaternion ms_offsetRight = Quaternion.Euler(270f, 270f, 0f);
|
||||
|
||||
bool m_inVR = false;
|
||||
VRIK m_vrIK = null;
|
||||
Vector2 m_armWeight = Vector2.zero;
|
||||
Vector4 m_vrIKWeights = Vector4.zero;
|
||||
Transform m_origRightHand = null;
|
||||
Transform m_origLeftHand = null;
|
||||
float m_armLength = 0f;
|
||||
float m_playspaceScale = 1f;
|
||||
|
||||
bool m_enabled = true;
|
||||
ArmIK m_armIK = null;
|
||||
Transform m_target = null;
|
||||
Transform m_rotationTarget = null;
|
||||
Transform m_rootLeft = null;
|
||||
Transform m_rootRight = null;
|
||||
Transform m_leftTarget = null;
|
||||
Transform m_rightTarget = null;
|
||||
ArmIK m_armIKLeft = null;
|
||||
ArmIK m_armIKRight = null;
|
||||
CVRPickupObject m_pickup = null;
|
||||
Matrix4x4 m_offset = Matrix4x4.identity;
|
||||
bool m_targetActive = false;
|
||||
Matrix4x4 m_offset;
|
||||
HandState m_leftHandState = HandState.Empty;
|
||||
HandState m_rightHandState = HandState.Empty;
|
||||
|
||||
// Unity events
|
||||
void Start()
|
||||
{
|
||||
m_inVR = Utils.IsInVR();
|
||||
|
||||
m_target = new GameObject("ArmPickupTarget").transform;
|
||||
m_target.parent = PlayerSetup.Instance.GetActiveCamera().transform;
|
||||
m_target.localPosition = Vector3.zero;
|
||||
m_target.localRotation = Quaternion.identity;
|
||||
m_rootLeft = new GameObject("[ArmPickupLeft]").transform;
|
||||
m_rootLeft.parent = PlayerSetup.Instance.GetActiveCamera().transform;
|
||||
m_rootLeft.localPosition = Vector3.zero;
|
||||
m_rootLeft.localRotation = Quaternion.identity;
|
||||
|
||||
m_rotationTarget = new GameObject("RotationTarget").transform;
|
||||
m_rotationTarget.parent = m_target;
|
||||
m_rotationTarget.localPosition = new Vector3(c_offsetLimit * Settings.GrabOffset, 0f, 0f);
|
||||
m_rotationTarget.localRotation = Quaternion.identity;
|
||||
m_leftTarget = new GameObject("Target").transform;
|
||||
m_leftTarget.parent = m_rootLeft;
|
||||
m_leftTarget.localPosition = new Vector3(c_offsetLimit * -Settings.GrabOffset, 0f, 0f);
|
||||
m_leftTarget.localRotation = Quaternion.identity;
|
||||
|
||||
m_rootRight = new GameObject("[ArmPickupRight]").transform;
|
||||
m_rootRight.parent = PlayerSetup.Instance.GetActiveCamera().transform;
|
||||
m_rootRight.localPosition = Vector3.zero;
|
||||
m_rootRight.localRotation = Quaternion.identity;
|
||||
|
||||
m_rightTarget = new GameObject("Target").transform;
|
||||
m_rightTarget.parent = m_rootRight;
|
||||
m_rightTarget.localPosition = new Vector3(c_offsetLimit * Settings.GrabOffset, 0f, 0f);
|
||||
m_rightTarget.localRotation = Quaternion.identity;
|
||||
|
||||
m_enabled = Settings.Enabled;
|
||||
|
||||
Settings.EnabledChange += this.SetEnabled;
|
||||
Settings.GrabOffsetChange += this.SetGrabOffset;
|
||||
Settings.LeadingHandChange += this.OnLeadingHandChange;
|
||||
Settings.HandsExtensionChange += this.OnHandsExtensionChange;
|
||||
}
|
||||
|
||||
void OnDestroy()
|
||||
|
@ -61,33 +85,106 @@ namespace ml_pam
|
|||
|
||||
void Update()
|
||||
{
|
||||
if(m_enabled && !ReferenceEquals(m_pickup, null))
|
||||
if(!ReferenceEquals(m_pickup, null) && (m_pickup == null))
|
||||
OnPickupDrop(m_pickup);
|
||||
|
||||
switch(m_leftHandState)
|
||||
{
|
||||
if(m_pickup != null)
|
||||
case HandState.Empty:
|
||||
{
|
||||
Matrix4x4 l_result = m_pickup.transform.GetMatrix() * m_offset;
|
||||
m_target.position = l_result * ms_pointVector;
|
||||
if(Settings.HandsExtension && Input.GetKeyDown(c_leftKey))
|
||||
{
|
||||
m_leftHandState = HandState.Extended;
|
||||
m_rootLeft.localPosition = new Vector3(0f, 0f, m_armLength * m_playspaceScale);
|
||||
SetArmActive(Settings.LeadHand.Left, true);
|
||||
}
|
||||
}
|
||||
else
|
||||
this.OnPickupDrop(m_pickup);
|
||||
break;
|
||||
case HandState.Extended:
|
||||
{
|
||||
if(Input.GetKeyUp(c_leftKey))
|
||||
{
|
||||
m_leftHandState = HandState.Empty;
|
||||
SetArmActive(Settings.LeadHand.Left, false);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case HandState.Pickup:
|
||||
{
|
||||
if(m_pickup != null)
|
||||
{
|
||||
Matrix4x4 l_result = m_pickup.transform.GetMatrix() * m_offset;
|
||||
m_rootLeft.position = l_result * ms_pointVector;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
switch(m_rightHandState)
|
||||
{
|
||||
case HandState.Empty:
|
||||
{
|
||||
if(Settings.HandsExtension && Input.GetKeyDown(c_rightKey))
|
||||
{
|
||||
m_rightHandState = HandState.Extended;
|
||||
m_rootRight.localPosition = new Vector3(0f, 0f, m_armLength * m_playspaceScale);
|
||||
SetArmActive(Settings.LeadHand.Right, true);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case HandState.Extended:
|
||||
{
|
||||
if(Input.GetKeyUp(c_rightKey))
|
||||
{
|
||||
m_rightHandState = HandState.Empty;
|
||||
SetArmActive(Settings.LeadHand.Right, false);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case HandState.Pickup:
|
||||
{
|
||||
if(m_pickup != null)
|
||||
{
|
||||
Matrix4x4 l_result = m_pickup.transform.GetMatrix() * m_offset;
|
||||
m_rootRight.position = l_result * ms_pointVector;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// IK updates
|
||||
// VRIK updates
|
||||
void OnIKPreUpdate()
|
||||
{
|
||||
m_armWeight.Set(m_vrIK.solver.rightArm.positionWeight, m_vrIK.solver.rightArm.rotationWeight);
|
||||
|
||||
if(m_targetActive && (Mathf.Approximately(m_armWeight.x, 0f) || Mathf.Approximately(m_armWeight.y, 0f)))
|
||||
if(m_enabled)
|
||||
{
|
||||
m_vrIK.solver.rightArm.positionWeight = 1f;
|
||||
m_vrIK.solver.rightArm.rotationWeight = 1f;
|
||||
m_vrIKWeights.Set(m_vrIK.solver.leftArm.positionWeight, m_vrIK.solver.leftArm.rotationWeight, m_vrIK.solver.rightArm.positionWeight, m_vrIK.solver.rightArm.rotationWeight);
|
||||
|
||||
if(m_leftHandState != HandState.Empty)
|
||||
{
|
||||
m_vrIK.solver.leftArm.positionWeight = 1f;
|
||||
m_vrIK.solver.leftArm.rotationWeight = 1f;
|
||||
m_vrIK.solver.leftArm.target = m_leftTarget;
|
||||
}
|
||||
if(m_rightHandState != HandState.Empty)
|
||||
{
|
||||
m_vrIK.solver.rightArm.positionWeight = 1f;
|
||||
m_vrIK.solver.rightArm.rotationWeight = 1f;
|
||||
m_vrIK.solver.rightArm.target = m_rightTarget;
|
||||
}
|
||||
}
|
||||
}
|
||||
void OnIKPostUpdate()
|
||||
{
|
||||
m_vrIK.solver.rightArm.positionWeight = m_armWeight.x;
|
||||
m_vrIK.solver.rightArm.rotationWeight = m_armWeight.y;
|
||||
if(m_enabled)
|
||||
{
|
||||
m_vrIK.solver.leftArm.positionWeight = m_vrIKWeights.x;
|
||||
m_vrIK.solver.leftArm.rotationWeight = m_vrIKWeights.y;
|
||||
m_vrIK.solver.leftArm.target = m_origLeftHand;
|
||||
m_vrIK.solver.rightArm.positionWeight = m_vrIKWeights.z;
|
||||
m_vrIK.solver.rightArm.rotationWeight = m_vrIKWeights.w;
|
||||
m_vrIK.solver.rightArm.target = m_origRightHand;
|
||||
}
|
||||
}
|
||||
|
||||
// Settings
|
||||
|
@ -95,17 +192,93 @@ namespace ml_pam
|
|||
{
|
||||
m_enabled = p_state;
|
||||
|
||||
RefreshArmIK();
|
||||
if(m_enabled)
|
||||
RestorePickup();
|
||||
{
|
||||
if(m_leftHandState != HandState.Empty)
|
||||
SetArmActive(Settings.LeadHand.Left, true);
|
||||
if(m_rightHandState != HandState.Empty)
|
||||
SetArmActive(Settings.LeadHand.Right, true);
|
||||
|
||||
OnHandsExtensionChange(Settings.HandsExtension);
|
||||
}
|
||||
else
|
||||
RestoreVRIK();
|
||||
SetArmActive(Settings.LeadHand.Both, false, true);
|
||||
}
|
||||
|
||||
void SetGrabOffset(float p_value)
|
||||
{
|
||||
if(m_rotationTarget != null)
|
||||
m_rotationTarget.localPosition = new Vector3(c_offsetLimit * m_playspaceScale * p_value, 0f, 0f);
|
||||
if(m_leftTarget != null)
|
||||
m_leftTarget.localPosition = new Vector3(c_offsetLimit * m_playspaceScale * -p_value, 0f, 0f);
|
||||
if(m_rightTarget != null)
|
||||
m_rightTarget.localPosition = new Vector3(c_offsetLimit * m_playspaceScale * p_value, 0f, 0f);
|
||||
}
|
||||
|
||||
void OnLeadingHandChange(Settings.LeadHand p_hand)
|
||||
{
|
||||
if(m_pickup != null)
|
||||
{
|
||||
if(m_leftHandState == HandState.Pickup)
|
||||
{
|
||||
m_leftHandState = HandState.Empty;
|
||||
SetArmActive(Settings.LeadHand.Left, false);
|
||||
}
|
||||
if(m_rightHandState == HandState.Pickup)
|
||||
{
|
||||
m_rightHandState = HandState.Empty;
|
||||
SetArmActive(Settings.LeadHand.Right, false);
|
||||
}
|
||||
|
||||
switch(p_hand)
|
||||
{
|
||||
case Settings.LeadHand.Left:
|
||||
m_leftHandState = HandState.Pickup;
|
||||
break;
|
||||
case Settings.LeadHand.Right:
|
||||
m_rightHandState = HandState.Pickup;
|
||||
break;
|
||||
case Settings.LeadHand.Both:
|
||||
{
|
||||
m_leftHandState = HandState.Pickup;
|
||||
m_rightHandState = HandState.Pickup;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
SetArmActive(p_hand, true);
|
||||
}
|
||||
}
|
||||
|
||||
void OnHandsExtensionChange(bool p_state)
|
||||
{
|
||||
if(m_enabled)
|
||||
{
|
||||
if(p_state)
|
||||
{
|
||||
if((m_leftHandState == HandState.Empty) && Input.GetKey(c_leftKey))
|
||||
{
|
||||
m_leftHandState = HandState.Extended;
|
||||
SetArmActive(Settings.LeadHand.Left, true);
|
||||
}
|
||||
if((m_rightHandState == HandState.Empty) && Input.GetKey(c_rightKey))
|
||||
{
|
||||
m_rightHandState = HandState.Extended;
|
||||
SetArmActive(Settings.LeadHand.Right, true);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if(m_leftHandState == HandState.Extended)
|
||||
{
|
||||
m_leftHandState = HandState.Empty;
|
||||
SetArmActive(Settings.LeadHand.Left, false);
|
||||
}
|
||||
if(m_rightHandState == HandState.Extended)
|
||||
{
|
||||
m_rightHandState = HandState.Empty;
|
||||
SetArmActive(Settings.LeadHand.Right, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Game events
|
||||
|
@ -113,8 +286,9 @@ namespace ml_pam
|
|||
{
|
||||
m_vrIK = null;
|
||||
m_origRightHand = null;
|
||||
m_armIK = null;
|
||||
m_targetActive = false;
|
||||
m_armIKLeft = null;
|
||||
m_armIKRight = null;
|
||||
m_armLength = 0f;
|
||||
}
|
||||
|
||||
internal void OnAvatarSetup()
|
||||
|
@ -122,44 +296,30 @@ namespace ml_pam
|
|||
// Recheck if user could switch to VR
|
||||
if(m_inVR != Utils.IsInVR())
|
||||
{
|
||||
m_target.parent = PlayerSetup.Instance.GetActiveCamera().transform;
|
||||
m_target.localPosition = Vector3.zero;
|
||||
m_target.localRotation = Quaternion.identity;
|
||||
m_rootLeft.parent = PlayerSetup.Instance.GetActiveCamera().transform;
|
||||
m_rootLeft.localPosition = Vector3.zero;
|
||||
m_rootLeft.localRotation = Quaternion.identity;
|
||||
|
||||
m_rootRight.parent = PlayerSetup.Instance.GetActiveCamera().transform;
|
||||
m_rootRight.localPosition = Vector3.zero;
|
||||
m_rootRight.localRotation = Quaternion.identity;
|
||||
}
|
||||
|
||||
m_inVR = Utils.IsInVR();
|
||||
m_vrIK = PlayerSetup.Instance._animator.GetComponent<VRIK>();
|
||||
|
||||
if(PlayerSetup.Instance._animator.isHuman)
|
||||
if(!m_inVR && PlayerSetup.Instance._animator.isHuman)
|
||||
{
|
||||
Vector3 l_hipsPos = Vector3.zero;
|
||||
Transform l_hips = PlayerSetup.Instance._animator.GetBoneTransform(HumanBodyBones.Hips);
|
||||
if(l_hips != null)
|
||||
l_hipsPos = l_hips.localPosition;
|
||||
|
||||
HumanPose l_currentPose = new HumanPose();
|
||||
HumanPoseHandler l_poseHandler = null;
|
||||
m_vrIK = PlayerSetup.Instance._animator.GetComponent<VRIK>();
|
||||
|
||||
if(!m_inVR)
|
||||
{
|
||||
l_poseHandler = new HumanPoseHandler(PlayerSetup.Instance._animator.avatar, PlayerSetup.Instance._avatar.transform);
|
||||
l_poseHandler.GetHumanPose(ref l_currentPose);
|
||||
TPoseHelper l_tpHelper = new TPoseHelper();
|
||||
l_tpHelper.Assign(PlayerSetup.Instance._animator);
|
||||
l_tpHelper.Apply();
|
||||
|
||||
HumanPose l_tPose = new HumanPose
|
||||
{
|
||||
bodyPosition = l_currentPose.bodyPosition,
|
||||
bodyRotation = l_currentPose.bodyRotation,
|
||||
muscles = new float[l_currentPose.muscles.Length]
|
||||
};
|
||||
for(int i = 0; i < l_tPose.muscles.Length; i++)
|
||||
l_tPose.muscles[i] = ms_tposeMuscles[i];
|
||||
|
||||
l_poseHandler.SetHumanPose(ref l_tPose);
|
||||
}
|
||||
|
||||
Transform l_hand = PlayerSetup.Instance._animator.GetBoneTransform(HumanBodyBones.RightHand);
|
||||
if(l_hand != null)
|
||||
m_rotationTarget.localRotation = (ms_palmToLeft * (m_inVR ? ms_offsetRight : ms_offsetRightDesktop)) * (PlayerSetup.Instance._avatar.transform.GetMatrix().inverse * l_hand.GetMatrix()).rotation;
|
||||
Transform l_leftHand = PlayerSetup.Instance._animator.GetBoneTransform(HumanBodyBones.LeftHand);
|
||||
if(l_leftHand != null)
|
||||
m_leftTarget.localRotation = ms_offsetLeft * (PlayerSetup.Instance._avatar.transform.GetMatrix().inverse * l_leftHand.GetMatrix()).rotation;
|
||||
Transform l_rightHand = PlayerSetup.Instance._animator.GetBoneTransform(HumanBodyBones.RightHand);
|
||||
if(l_rightHand != null)
|
||||
m_rightTarget.localRotation = ms_offsetRight * (PlayerSetup.Instance._avatar.transform.GetMatrix().inverse * l_rightHand.GetMatrix()).rotation;
|
||||
|
||||
if(m_vrIK == null)
|
||||
{
|
||||
|
@ -169,39 +329,56 @@ namespace ml_pam
|
|||
if(l_chest == null)
|
||||
l_chest = PlayerSetup.Instance._animator.GetBoneTransform(HumanBodyBones.Spine);
|
||||
|
||||
m_armIK = PlayerSetup.Instance._avatar.AddComponent<ArmIK>();
|
||||
m_armIK.solver.isLeft = false;
|
||||
m_armIK.solver.SetChain(
|
||||
m_armIKLeft = PlayerSetup.Instance._avatar.AddComponent<ArmIK>();
|
||||
m_armIKLeft.solver.isLeft = true;
|
||||
m_armIKLeft.solver.SetChain(
|
||||
l_chest,
|
||||
PlayerSetup.Instance._animator.GetBoneTransform(HumanBodyBones.LeftShoulder),
|
||||
PlayerSetup.Instance._animator.GetBoneTransform(HumanBodyBones.LeftUpperArm),
|
||||
PlayerSetup.Instance._animator.GetBoneTransform(HumanBodyBones.LeftLowerArm),
|
||||
l_leftHand,
|
||||
PlayerSetup.Instance._animator.transform
|
||||
);
|
||||
m_armIKLeft.solver.arm.target = m_leftTarget;
|
||||
m_armIKLeft.solver.arm.positionWeight = 1f;
|
||||
m_armIKLeft.solver.arm.rotationWeight = 1f;
|
||||
m_armIKLeft.solver.IKPositionWeight = 0f;
|
||||
m_armIKLeft.solver.IKRotationWeight = 0f;
|
||||
m_armIKLeft.enabled = false;
|
||||
|
||||
m_armLength = m_armIKLeft.solver.arm.mag * 1.25f;
|
||||
|
||||
m_armIKRight = PlayerSetup.Instance._avatar.AddComponent<ArmIK>();
|
||||
m_armIKRight.solver.isLeft = false;
|
||||
m_armIKRight.solver.SetChain(
|
||||
l_chest,
|
||||
PlayerSetup.Instance._animator.GetBoneTransform(HumanBodyBones.RightShoulder),
|
||||
PlayerSetup.Instance._animator.GetBoneTransform(HumanBodyBones.RightUpperArm),
|
||||
PlayerSetup.Instance._animator.GetBoneTransform(HumanBodyBones.RightLowerArm),
|
||||
l_hand,
|
||||
l_rightHand,
|
||||
PlayerSetup.Instance._animator.transform
|
||||
);
|
||||
m_armIK.solver.arm.target = m_rotationTarget;
|
||||
m_armIK.solver.arm.positionWeight = 1f;
|
||||
m_armIK.solver.arm.rotationWeight = 1f;
|
||||
m_armIK.solver.IKPositionWeight = 0f;
|
||||
m_armIK.solver.IKRotationWeight = 0f;
|
||||
m_armIK.enabled = m_enabled;
|
||||
m_armIKRight.solver.arm.target = m_rightTarget;
|
||||
m_armIKRight.solver.arm.positionWeight = 1f;
|
||||
m_armIKRight.solver.arm.rotationWeight = 1f;
|
||||
m_armIKRight.solver.IKPositionWeight = 0f;
|
||||
m_armIKRight.solver.IKRotationWeight = 0f;
|
||||
m_armIKRight.enabled = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_origLeftHand = m_vrIK.solver.leftArm.target;
|
||||
m_origRightHand = m_vrIK.solver.rightArm.target;
|
||||
m_armLength = m_vrIK.solver.leftArm.mag * 1.25f;
|
||||
m_vrIK.solver.OnPreUpdate += this.OnIKPreUpdate;
|
||||
m_vrIK.solver.OnPostUpdate += this.OnIKPostUpdate;
|
||||
}
|
||||
|
||||
l_poseHandler?.SetHumanPose(ref l_currentPose);
|
||||
l_poseHandler?.Dispose();
|
||||
|
||||
if(l_hips != null)
|
||||
l_hips.localPosition = l_hipsPos;
|
||||
l_tpHelper.Restore();
|
||||
l_tpHelper.Unassign();
|
||||
}
|
||||
|
||||
if(m_enabled)
|
||||
RestorePickup();
|
||||
SetEnabled(m_enabled);
|
||||
}
|
||||
|
||||
internal void OnPickupGrab(CVRPickupObject p_pickup, ControllerRay p_ray, Vector3 p_hit)
|
||||
|
@ -224,20 +401,23 @@ namespace ml_pam
|
|||
else
|
||||
m_offset = m_pickup.transform.GetMatrix().inverse * Matrix4x4.Translate(p_hit);
|
||||
|
||||
if(m_enabled)
|
||||
switch(Settings.LeadingHand)
|
||||
{
|
||||
if((m_vrIK != null) && !m_targetActive)
|
||||
case Settings.LeadHand.Left:
|
||||
m_leftHandState = HandState.Pickup;
|
||||
break;
|
||||
case Settings.LeadHand.Right:
|
||||
m_rightHandState = HandState.Pickup;
|
||||
break;
|
||||
case Settings.LeadHand.Both:
|
||||
{
|
||||
m_vrIK.solver.rightArm.target = m_rotationTarget;
|
||||
m_targetActive = true;
|
||||
}
|
||||
|
||||
if(m_armIK != null)
|
||||
{
|
||||
m_armIK.solver.IKPositionWeight = 1f;
|
||||
m_armIK.solver.IKRotationWeight = 1f;
|
||||
m_leftHandState = HandState.Pickup;
|
||||
m_rightHandState = HandState.Pickup;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
SetArmActive(Settings.LeadingHand, true);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -246,17 +426,22 @@ namespace ml_pam
|
|||
if(m_pickup == p_pickup)
|
||||
{
|
||||
m_pickup = null;
|
||||
|
||||
if(m_enabled)
|
||||
switch(Settings.LeadingHand)
|
||||
{
|
||||
RestoreVRIK();
|
||||
|
||||
if(m_armIK != null)
|
||||
case Settings.LeadHand.Left:
|
||||
m_leftHandState = HandState.Empty;
|
||||
break;
|
||||
case Settings.LeadHand.Right:
|
||||
m_rightHandState = HandState.Empty;
|
||||
break;
|
||||
case Settings.LeadHand.Both:
|
||||
{
|
||||
m_armIK.solver.IKPositionWeight = 0f;
|
||||
m_armIK.solver.IKRotationWeight = 0f;
|
||||
m_leftHandState = HandState.Empty;
|
||||
m_rightHandState = HandState.Empty;
|
||||
}
|
||||
break;
|
||||
}
|
||||
SetArmActive(Settings.LeadingHand, false);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -267,33 +452,23 @@ namespace ml_pam
|
|||
}
|
||||
|
||||
// Arbitrary
|
||||
void RestorePickup()
|
||||
void SetArmActive(Settings.LeadHand p_hand, bool p_state, bool p_forced = false)
|
||||
{
|
||||
if((m_vrIK != null) && (m_pickup != null))
|
||||
if(m_enabled || p_forced)
|
||||
{
|
||||
m_vrIK.solver.rightArm.target = m_rotationTarget;
|
||||
m_targetActive = true;
|
||||
if(((p_hand == Settings.LeadHand.Left) || (p_hand == Settings.LeadHand.Both)) && (m_armIKLeft != null))
|
||||
{
|
||||
m_armIKLeft.enabled = m_enabled;
|
||||
m_armIKLeft.solver.IKPositionWeight = (p_state ? 1f : 0f);
|
||||
m_armIKLeft.solver.IKRotationWeight = (p_state ? 1f : 0f);
|
||||
}
|
||||
if(((p_hand == Settings.LeadHand.Right) || (p_hand == Settings.LeadHand.Both)) && (m_armIKRight != null))
|
||||
{
|
||||
m_armIKRight.enabled = m_enabled;
|
||||
m_armIKRight.solver.IKPositionWeight = (p_state ? 1f : 0f);
|
||||
m_armIKRight.solver.IKRotationWeight = (p_state ? 1f : 0f);
|
||||
}
|
||||
}
|
||||
if((m_armIK != null) && (m_pickup != null))
|
||||
{
|
||||
m_armIK.solver.IKPositionWeight = 1f;
|
||||
m_armIK.solver.IKRotationWeight = 1f;
|
||||
}
|
||||
}
|
||||
|
||||
void RestoreVRIK()
|
||||
{
|
||||
if((m_vrIK != null) && m_targetActive)
|
||||
{
|
||||
m_vrIK.solver.rightArm.target = m_origRightHand;
|
||||
m_targetActive = false;
|
||||
}
|
||||
}
|
||||
|
||||
void RefreshArmIK()
|
||||
{
|
||||
if(m_armIK != null)
|
||||
m_armIK.enabled = m_enabled;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
[assembly: MelonLoader.MelonInfo(typeof(ml_pam.PickupArmMovement), "PickupArmMovement", "1.0.8", "SDraw", "https://github.com/SDraw/ml_mods_cvr")]
|
||||
[assembly: MelonLoader.MelonGame(null, "ChilloutVR")]
|
||||
[assembly: MelonLoader.MelonPriority(1)]
|
||||
[assembly: MelonLoader.MelonPlatform(MelonLoader.MelonPlatformAttribute.CompatiblePlatforms.WINDOWS_X64)]
|
||||
[assembly: MelonLoader.MelonPlatformDomain(MelonLoader.MelonPlatformDomainAttribute.CompatibleDomains.MONO)]
|
||||
[assembly: MelonLoader.MelonInfo(typeof(ml_pam.PickupArmMovement), "PickupArmMovement", "1.0.9", "SDraw", "https://github.com/SDraw/ml_mods_cvr")]
|
||||
[assembly: MelonLoader.MelonGame(null, "ChilloutVR")]
|
||||
[assembly: MelonLoader.MelonPriority(1)]
|
||||
[assembly: MelonLoader.MelonPlatform(MelonLoader.MelonPlatformAttribute.CompatiblePlatforms.WINDOWS_X64)]
|
||||
[assembly: MelonLoader.MelonPlatformDomain(MelonLoader.MelonPlatformDomainAttribute.CompatibleDomains.MONO)]
|
||||
|
|
|
@ -1,12 +1,18 @@
|
|||
# Pickup Arm Movement
|
||||
This mod adds arm tracking upon holding pickup in desktop mode.
|
||||
|
||||
# Installation
|
||||
* Install [latest MelonLoader](https://github.com/LavaGang/MelonLoader)
|
||||
* Get [latest release DLL](../../../releases/latest):
|
||||
* Put `ml_pam.dll` in `Mods` folder of game
|
||||
|
||||
# Usage
|
||||
Available mod's settings in `Settings - Interactions - Pickup Arm Movement`:
|
||||
* **Enable hand movement:** enables/disables arm tracking; default value - `true`.
|
||||
* **Grab offset:** offset from pickup grab point; defalut value - `25`.
|
||||
# Pickup Arm Movement
|
||||
This mod adds arm tracking upon holding pickup in desktop mode.
|
||||
|
||||
# Installation
|
||||
* Install [latest MelonLoader](https://github.com/LavaGang/MelonLoader)
|
||||
* Get [latest release DLL](../../../releases/latest):
|
||||
* Put `ml_pam.dll` in `Mods` folder of game
|
||||
|
||||
# Usage
|
||||
Available mod's settings in `Settings - Interactions - Pickup Arm Movement`:
|
||||
* **Enable hand movement:** enables/disables arm tracking; default value - `true`.
|
||||
* **Grab offset:** offset from pickup grab point; default value - `25`.
|
||||
* **Leading hand:** hand that will be extended when gragging pickup; available values: `Left`, `Right`, `Both`; default value - `Right`.
|
||||
* **Hands extension (Q\E):** extend left and right hand if `Q` and `E` keys are pressed; default value - `true`.
|
||||
|
||||
# Notes
|
||||
* Made for desktop mode in mind.
|
||||
* Compatible with [DekstopVRIK](https://github.com/NotAKidOnSteam/NAK_CVR_Mods).
|
||||
|
|
|
@ -1,104 +1,140 @@
|
|||
using ABI_RC.Core.InteractionSystem;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace ml_pam
|
||||
{
|
||||
static class Settings
|
||||
{
|
||||
public enum ModSetting
|
||||
{
|
||||
Enabled = 0,
|
||||
GrabOffset
|
||||
}
|
||||
|
||||
public static bool Enabled { get; private set; } = true;
|
||||
public static float GrabOffset { get; private set; } = 0.25f;
|
||||
|
||||
static MelonLoader.MelonPreferences_Category ms_category = null;
|
||||
static List<MelonLoader.MelonPreferences_Entry> ms_entries = null;
|
||||
|
||||
static public event Action<bool> EnabledChange;
|
||||
static public event Action<float> GrabOffsetChange;
|
||||
|
||||
internal static void Init()
|
||||
{
|
||||
ms_category = MelonLoader.MelonPreferences.CreateCategory("PAM", null, true);
|
||||
|
||||
ms_entries = new List<MelonLoader.MelonPreferences_Entry>()
|
||||
{
|
||||
ms_category.CreateEntry(ModSetting.Enabled.ToString(), Enabled),
|
||||
ms_category.CreateEntry(ModSetting.GrabOffset.ToString(), (int)(GrabOffset * 100f)),
|
||||
};
|
||||
|
||||
Load();
|
||||
|
||||
MelonLoader.MelonCoroutines.Start(WaitMainMenuUi());
|
||||
}
|
||||
|
||||
static System.Collections.IEnumerator WaitMainMenuUi()
|
||||
{
|
||||
while(ViewManager.Instance == null)
|
||||
yield return null;
|
||||
while(ViewManager.Instance.gameMenuView == null)
|
||||
yield return null;
|
||||
while(ViewManager.Instance.gameMenuView.Listener == null)
|
||||
yield return null;
|
||||
|
||||
ViewManager.Instance.gameMenuView.Listener.ReadyForBindings += () =>
|
||||
{
|
||||
ViewManager.Instance.gameMenuView.View.BindCall("OnToggleUpdate_" + ms_category.Identifier, new Action<string, string>(OnToggleUpdate));
|
||||
ViewManager.Instance.gameMenuView.View.BindCall("OnSliderUpdate_" + ms_category.Identifier, new Action<string, string>(OnSliderUpdate));
|
||||
};
|
||||
ViewManager.Instance.gameMenuView.Listener.FinishLoad += (_) =>
|
||||
{
|
||||
ViewManager.Instance.gameMenuView.View.ExecuteScript(Scripts.GetEmbeddedScript("mods_extension.js"));
|
||||
ViewManager.Instance.gameMenuView.View.ExecuteScript(Scripts.GetEmbeddedScript("mod_menu.js"));
|
||||
foreach(var l_entry in ms_entries)
|
||||
ViewManager.Instance.gameMenuView.View.TriggerEvent("updateModSetting", ms_category.Identifier, l_entry.DisplayName, l_entry.GetValueAsString());
|
||||
};
|
||||
}
|
||||
|
||||
static void Load()
|
||||
{
|
||||
Enabled = (bool)ms_entries[(int)ModSetting.Enabled].BoxedValue;
|
||||
GrabOffset = (int)ms_entries[(int)ModSetting.GrabOffset].BoxedValue * 0.01f;
|
||||
}
|
||||
|
||||
static void OnToggleUpdate(string p_name, string p_value)
|
||||
{
|
||||
if(Enum.TryParse(p_name, out ModSetting l_setting))
|
||||
{
|
||||
switch(l_setting)
|
||||
{
|
||||
case ModSetting.Enabled:
|
||||
{
|
||||
Enabled = bool.Parse(p_value);
|
||||
EnabledChange?.Invoke(Enabled);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
ms_entries[(int)l_setting].BoxedValue = bool.Parse(p_value);
|
||||
}
|
||||
}
|
||||
|
||||
static void OnSliderUpdate(string p_name, string p_value)
|
||||
{
|
||||
if(Enum.TryParse(p_name, out ModSetting l_setting))
|
||||
{
|
||||
switch(l_setting)
|
||||
{
|
||||
case ModSetting.GrabOffset:
|
||||
{
|
||||
GrabOffset = int.Parse(p_value) * 0.01f;
|
||||
GrabOffsetChange?.Invoke(GrabOffset);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
ms_entries[(int)l_setting].BoxedValue = int.Parse(p_value);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
using ABI_RC.Core.InteractionSystem;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace ml_pam
|
||||
{
|
||||
static class Settings
|
||||
{
|
||||
public enum ModSetting
|
||||
{
|
||||
Enabled = 0,
|
||||
GrabOffset,
|
||||
LeadHand,
|
||||
HandsExtension
|
||||
}
|
||||
public enum LeadHand
|
||||
{
|
||||
Left = 0,
|
||||
Right,
|
||||
Both
|
||||
}
|
||||
|
||||
public static bool Enabled { get; private set; } = true;
|
||||
public static float GrabOffset { get; private set; } = 0.25f;
|
||||
public static LeadHand LeadingHand { get; private set; } = LeadHand.Right;
|
||||
public static bool HandsExtension { get; private set; } = true;
|
||||
|
||||
static MelonLoader.MelonPreferences_Category ms_category = null;
|
||||
static List<MelonLoader.MelonPreferences_Entry> ms_entries = null;
|
||||
|
||||
static public event Action<bool> EnabledChange;
|
||||
static public event Action<float> GrabOffsetChange;
|
||||
static public event Action<LeadHand> LeadingHandChange;
|
||||
static public event Action<bool> HandsExtensionChange;
|
||||
|
||||
internal static void Init()
|
||||
{
|
||||
ms_category = MelonLoader.MelonPreferences.CreateCategory("PAM", null, true);
|
||||
|
||||
ms_entries = new List<MelonLoader.MelonPreferences_Entry>()
|
||||
{
|
||||
ms_category.CreateEntry(ModSetting.Enabled.ToString(), Enabled),
|
||||
ms_category.CreateEntry(ModSetting.GrabOffset.ToString(), (int)(GrabOffset * 100f)),
|
||||
ms_category.CreateEntry(ModSetting.LeadHand.ToString(), (int)LeadHand.Right),
|
||||
ms_category.CreateEntry(ModSetting.HandsExtension.ToString(), HandsExtension),
|
||||
};
|
||||
|
||||
Enabled = (bool)ms_entries[(int)ModSetting.Enabled].BoxedValue;
|
||||
GrabOffset = (int)ms_entries[(int)ModSetting.GrabOffset].BoxedValue * 0.01f;
|
||||
LeadingHand = (LeadHand)(int)ms_entries[(int)ModSetting.LeadHand].BoxedValue;
|
||||
HandsExtension = (bool)ms_entries[(int)ModSetting.HandsExtension].BoxedValue;
|
||||
|
||||
MelonLoader.MelonCoroutines.Start(WaitMainMenuUi());
|
||||
}
|
||||
|
||||
static System.Collections.IEnumerator WaitMainMenuUi()
|
||||
{
|
||||
while(ViewManager.Instance == null)
|
||||
yield return null;
|
||||
while(ViewManager.Instance.gameMenuView == null)
|
||||
yield return null;
|
||||
while(ViewManager.Instance.gameMenuView.Listener == null)
|
||||
yield return null;
|
||||
|
||||
ViewManager.Instance.gameMenuView.Listener.ReadyForBindings += () =>
|
||||
{
|
||||
ViewManager.Instance.gameMenuView.View.BindCall("OnToggleUpdate_" + ms_category.Identifier, new Action<string, string>(OnToggleUpdate));
|
||||
ViewManager.Instance.gameMenuView.View.BindCall("OnSliderUpdate_" + ms_category.Identifier, new Action<string, string>(OnSliderUpdate));
|
||||
ViewManager.Instance.gameMenuView.View.BindCall("OnDropdownUpdate_" + ms_category.Identifier, new Action<string, string>(OnDropdownUpdate));
|
||||
};
|
||||
ViewManager.Instance.gameMenuView.Listener.FinishLoad += (_) =>
|
||||
{
|
||||
ViewManager.Instance.gameMenuView.View.ExecuteScript(Scripts.GetEmbeddedScript("mods_extension.js"));
|
||||
ViewManager.Instance.gameMenuView.View.ExecuteScript(Scripts.GetEmbeddedScript("mod_menu.js"));
|
||||
foreach(var l_entry in ms_entries)
|
||||
ViewManager.Instance.gameMenuView.View.TriggerEvent("updateModSetting", ms_category.Identifier, l_entry.DisplayName, l_entry.GetValueAsString());
|
||||
};
|
||||
}
|
||||
|
||||
static void OnToggleUpdate(string p_name, string p_value)
|
||||
{
|
||||
if(Enum.TryParse(p_name, out ModSetting l_setting))
|
||||
{
|
||||
switch(l_setting)
|
||||
{
|
||||
case ModSetting.Enabled:
|
||||
{
|
||||
Enabled = bool.Parse(p_value);
|
||||
EnabledChange?.Invoke(Enabled);
|
||||
}
|
||||
break;
|
||||
|
||||
case ModSetting.HandsExtension:
|
||||
{
|
||||
HandsExtension = bool.Parse(p_value);
|
||||
HandsExtensionChange?.Invoke(HandsExtension);
|
||||
} break;
|
||||
}
|
||||
|
||||
ms_entries[(int)l_setting].BoxedValue = bool.Parse(p_value);
|
||||
}
|
||||
}
|
||||
|
||||
static void OnSliderUpdate(string p_name, string p_value)
|
||||
{
|
||||
if(Enum.TryParse(p_name, out ModSetting l_setting))
|
||||
{
|
||||
switch(l_setting)
|
||||
{
|
||||
case ModSetting.GrabOffset:
|
||||
{
|
||||
GrabOffset = int.Parse(p_value) * 0.01f;
|
||||
GrabOffsetChange?.Invoke(GrabOffset);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
ms_entries[(int)l_setting].BoxedValue = int.Parse(p_value);
|
||||
}
|
||||
}
|
||||
|
||||
static void OnDropdownUpdate(string p_name, string p_value)
|
||||
{
|
||||
if(Enum.TryParse(p_name, out ModSetting l_setting))
|
||||
{
|
||||
switch(l_setting)
|
||||
{
|
||||
case ModSetting.LeadHand:
|
||||
{
|
||||
LeadingHand = (LeadHand)int.Parse(p_value);
|
||||
LeadingHandChange?.Invoke(LeadingHand);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
ms_entries[(int)l_setting].BoxedValue = int.Parse(p_value);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
63
ml_pam/TPoseHelper.cs
Normal file
63
ml_pam/TPoseHelper.cs
Normal file
|
@ -0,0 +1,63 @@
|
|||
using System.Reflection;
|
||||
using UnityEngine;
|
||||
using ABI_RC.Systems.IK.SubSystems;
|
||||
|
||||
namespace ml_pam
|
||||
{
|
||||
class TPoseHelper
|
||||
{
|
||||
static readonly float[] ms_tposeMuscles = typeof(BodySystem).GetField("TPoseMuscles", BindingFlags.Static | BindingFlags.NonPublic).GetValue(null) as float[];
|
||||
|
||||
HumanPoseHandler m_poseHandler = null;
|
||||
HumanPose m_oldPose;
|
||||
HumanPose m_newPose;
|
||||
Vector3 m_hipsLocalPos = Vector3.zero;
|
||||
Transform m_hips = null;
|
||||
|
||||
public void Assign(Animator p_animator)
|
||||
{
|
||||
if(m_poseHandler != null)
|
||||
{
|
||||
m_poseHandler = new HumanPoseHandler(p_animator.avatar, p_animator.transform);
|
||||
m_hips = p_animator.GetBoneTransform(HumanBodyBones.Hips);
|
||||
}
|
||||
}
|
||||
|
||||
public void Unassign()
|
||||
{
|
||||
m_poseHandler?.Dispose();
|
||||
m_poseHandler = null;
|
||||
m_oldPose = new HumanPose();
|
||||
m_newPose = new HumanPose();
|
||||
m_hips = null;
|
||||
m_hipsLocalPos = Vector3.zero;
|
||||
}
|
||||
|
||||
public void Apply()
|
||||
{
|
||||
if(m_hips != null)
|
||||
m_hipsLocalPos = m_hips.localPosition;
|
||||
|
||||
if(m_poseHandler != null)
|
||||
{
|
||||
m_poseHandler.GetHumanPose(ref m_oldPose);
|
||||
m_newPose.bodyPosition = m_oldPose.bodyPosition;
|
||||
m_newPose.bodyRotation = m_oldPose.bodyRotation;
|
||||
m_newPose.muscles = new float[m_oldPose.muscles.Length];
|
||||
for(int i = 0, j = m_newPose.muscles.Length; i < j; i++)
|
||||
m_newPose.muscles[i] = ms_tposeMuscles[i];
|
||||
|
||||
m_poseHandler.SetHumanPose(ref m_newPose);
|
||||
}
|
||||
}
|
||||
|
||||
public void Restore()
|
||||
{
|
||||
if(m_poseHandler != null)
|
||||
m_poseHandler.SetHumanPose(ref m_oldPose);
|
||||
|
||||
if(m_hips != null)
|
||||
m_hips.localPosition = m_hipsLocalPos;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,74 +1,78 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>netstandard2.1</TargetFramework>
|
||||
<Platforms>x64</Platforms>
|
||||
<PackageId>PickupArmMovement</PackageId>
|
||||
<Version>1.0.8</Version>
|
||||
<Authors>SDraw</Authors>
|
||||
<Company>None</Company>
|
||||
<Product>PickupArmMovement</Product>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<DebugType>none</DebugType>
|
||||
<DebugSymbols>false</DebugSymbols>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<None Remove="PickupArmMovement.json" />
|
||||
<None Remove="resources\mod_menu.js" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<EmbeddedResource Include="resources\mod_menu.js" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<EmbeddedResource Include="..\js\mods_extension.js" Link="resources\mods_extension.js" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Reference Include="0Harmony">
|
||||
<HintPath>D:\games\Steam\steamapps\common\ChilloutVR\MelonLoader\net35\0Harmony.dll</HintPath>
|
||||
<Private>false</Private>
|
||||
</Reference>
|
||||
<Reference Include="Assembly-CSharp">
|
||||
<HintPath>D:\games\Steam\steamapps\common\ChilloutVR\ChilloutVR_Data\Managed\Assembly-CSharp.dll</HintPath>
|
||||
<Private>false</Private>
|
||||
</Reference>
|
||||
<Reference Include="Assembly-CSharp-firstpass">
|
||||
<HintPath>D:\Games\Steam\steamapps\common\ChilloutVR\ChilloutVR_Data\Managed\Assembly-CSharp-firstpass.dll</HintPath>
|
||||
<Private>false</Private>
|
||||
</Reference>
|
||||
<Reference Include="cohtml.Net">
|
||||
<HintPath>D:\Games\Steam\steamapps\common\ChilloutVR\ChilloutVR_Data\Managed\cohtml.Net.dll</HintPath>
|
||||
<Private>false</Private>
|
||||
</Reference>
|
||||
<Reference Include="Cohtml.Runtime">
|
||||
<HintPath>D:\Games\Steam\steamapps\common\ChilloutVR\ChilloutVR_Data\Managed\Cohtml.Runtime.dll</HintPath>
|
||||
<Private>false</Private>
|
||||
</Reference>
|
||||
<Reference Include="MelonLoader">
|
||||
<HintPath>D:\games\Steam\steamapps\common\ChilloutVR\MelonLoader\net35\MelonLoader.dll</HintPath>
|
||||
<Private>false</Private>
|
||||
</Reference>
|
||||
<Reference Include="UnityEngine">
|
||||
<HintPath>D:\Games\Steam\steamapps\common\ChilloutVR\ChilloutVR_Data\Managed\UnityEngine.dll</HintPath>
|
||||
<Private>false</Private>
|
||||
</Reference>
|
||||
<Reference Include="UnityEngine.AnimationModule">
|
||||
<HintPath>D:\Games\Steam\steamapps\common\ChilloutVR\ChilloutVR_Data\Managed\UnityEngine.AnimationModule.dll</HintPath>
|
||||
<Private>false</Private>
|
||||
</Reference>
|
||||
<Reference Include="UnityEngine.CoreModule">
|
||||
<HintPath>D:\Games\Steam\steamapps\common\ChilloutVR\ChilloutVR_Data\Managed\UnityEngine.CoreModule.dll</HintPath>
|
||||
<Private>false</Private>
|
||||
</Reference>
|
||||
</ItemGroup>
|
||||
|
||||
<Target Name="PostBuild" AfterTargets="PostBuildEvent">
|
||||
<Exec Command="copy /y "$(TargetPath)" "D:\Games\Steam\steamapps\common\ChilloutVR\Mods\"" />
|
||||
</Target>
|
||||
|
||||
</Project>
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>netstandard2.1</TargetFramework>
|
||||
<Platforms>x64</Platforms>
|
||||
<PackageId>PickupArmMovement</PackageId>
|
||||
<Version>1.0.9</Version>
|
||||
<Authors>SDraw</Authors>
|
||||
<Company>None</Company>
|
||||
<Product>PickupArmMovement</Product>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<DebugType>none</DebugType>
|
||||
<DebugSymbols>false</DebugSymbols>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<None Remove="PickupArmMovement.json" />
|
||||
<None Remove="resources\mod_menu.js" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<EmbeddedResource Include="resources\mod_menu.js" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<EmbeddedResource Include="..\js\mods_extension.js" Link="resources\mods_extension.js" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Reference Include="0Harmony">
|
||||
<HintPath>D:\games\Steam\steamapps\common\ChilloutVR\MelonLoader\net35\0Harmony.dll</HintPath>
|
||||
<Private>false</Private>
|
||||
</Reference>
|
||||
<Reference Include="Assembly-CSharp">
|
||||
<HintPath>D:\games\Steam\steamapps\common\ChilloutVR\ChilloutVR_Data\Managed\Assembly-CSharp.dll</HintPath>
|
||||
<Private>false</Private>
|
||||
</Reference>
|
||||
<Reference Include="Assembly-CSharp-firstpass">
|
||||
<HintPath>D:\Games\Steam\steamapps\common\ChilloutVR\ChilloutVR_Data\Managed\Assembly-CSharp-firstpass.dll</HintPath>
|
||||
<Private>false</Private>
|
||||
</Reference>
|
||||
<Reference Include="cohtml.Net">
|
||||
<HintPath>D:\Games\Steam\steamapps\common\ChilloutVR\ChilloutVR_Data\Managed\cohtml.Net.dll</HintPath>
|
||||
<Private>false</Private>
|
||||
</Reference>
|
||||
<Reference Include="Cohtml.Runtime">
|
||||
<HintPath>D:\Games\Steam\steamapps\common\ChilloutVR\ChilloutVR_Data\Managed\Cohtml.Runtime.dll</HintPath>
|
||||
<Private>false</Private>
|
||||
</Reference>
|
||||
<Reference Include="MelonLoader">
|
||||
<HintPath>D:\games\Steam\steamapps\common\ChilloutVR\MelonLoader\net35\MelonLoader.dll</HintPath>
|
||||
<Private>false</Private>
|
||||
</Reference>
|
||||
<Reference Include="UnityEngine">
|
||||
<HintPath>D:\Games\Steam\steamapps\common\ChilloutVR\ChilloutVR_Data\Managed\UnityEngine.dll</HintPath>
|
||||
<Private>false</Private>
|
||||
</Reference>
|
||||
<Reference Include="UnityEngine.AnimationModule">
|
||||
<HintPath>D:\Games\Steam\steamapps\common\ChilloutVR\ChilloutVR_Data\Managed\UnityEngine.AnimationModule.dll</HintPath>
|
||||
<Private>false</Private>
|
||||
</Reference>
|
||||
<Reference Include="UnityEngine.CoreModule">
|
||||
<HintPath>D:\Games\Steam\steamapps\common\ChilloutVR\ChilloutVR_Data\Managed\UnityEngine.CoreModule.dll</HintPath>
|
||||
<Private>false</Private>
|
||||
</Reference>
|
||||
<Reference Include="UnityEngine.InputLegacyModule">
|
||||
<HintPath>D:\Games\Steam\steamapps\common\ChilloutVR\ChilloutVR_Data\Managed\UnityEngine.InputLegacyModule.dll</HintPath>
|
||||
<Private>false</Private>
|
||||
</Reference>
|
||||
</ItemGroup>
|
||||
|
||||
<Target Name="PostBuild" AfterTargets="PostBuildEvent">
|
||||
<Exec Command="copy /y "$(TargetPath)" "D:\Games\Steam\steamapps\common\ChilloutVR\Mods\"" />
|
||||
</Target>
|
||||
|
||||
</Project>
|
||||
|
|
|
@ -1,32 +1,50 @@
|
|||
{
|
||||
let l_block = document.createElement('div');
|
||||
l_block.innerHTML = `
|
||||
<div class ="settings-subcategory">
|
||||
<div class ="subcategory-name">Pickup Arm Movement</div>
|
||||
<div class ="subcategory-description"></div>
|
||||
</div>
|
||||
|
||||
<div class ="row-wrapper">
|
||||
<div class ="option-caption">Enable hand movement: </div>
|
||||
<div class ="option-input">
|
||||
<div id="Enabled" class ="inp_toggle no-scroll" data-current="true"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class ="row-wrapper">
|
||||
<div class ="option-caption">Grab offset: </div>
|
||||
<div class ="option-input">
|
||||
<div id="GrabOffset" class ="inp_slider no-scroll" data-min="0" data-max="100" data-current="25"></div>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
document.getElementById('settings-interaction').appendChild(l_block);
|
||||
|
||||
// Toggles
|
||||
for (let l_toggle of l_block.querySelectorAll('.inp_toggle'))
|
||||
modsExtension.addSetting('PAM', l_toggle.id, modsExtension.createToggle(l_toggle, 'OnToggleUpdate_PAM'));
|
||||
|
||||
// Sliders
|
||||
for (let l_slider of l_block.querySelectorAll('.inp_slider'))
|
||||
modsExtension.addSetting('PAM', l_slider.id, modsExtension.createSlider(l_slider, 'OnSliderUpdate_PAM'));
|
||||
}
|
||||
{
|
||||
let l_block = document.createElement('div');
|
||||
l_block.innerHTML = `
|
||||
<div class ="settings-subcategory">
|
||||
<div class ="subcategory-name">Pickup Arm Movement</div>
|
||||
<div class ="subcategory-description"></div>
|
||||
</div>
|
||||
|
||||
<div class ="row-wrapper">
|
||||
<div class ="option-caption">Enabled: </div>
|
||||
<div class ="option-input">
|
||||
<div id="Enabled" class ="inp_toggle no-scroll" data-current="true"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class ="row-wrapper">
|
||||
<div class ="option-caption">Grab offset: </div>
|
||||
<div class ="option-input">
|
||||
<div id="GrabOffset" class ="inp_slider no-scroll" data-min="0" data-max="100" data-current="25"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class ="row-wrapper">
|
||||
<div class ="option-caption">Leading hand: </div>
|
||||
<div class ="option-input">
|
||||
<div id="LeadHand" class ="inp_dropdown no-scroll" data-options="0:Left,1:Right,2:Both" data-current="1"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class ="row-wrapper">
|
||||
<div class ="option-caption">Hands extension (Q/E): </div>
|
||||
<div class ="option-input">
|
||||
<div id="HandsExtension" class ="inp_toggle no-scroll" data-current="true"></div>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
document.getElementById('settings-interaction').appendChild(l_block);
|
||||
|
||||
// Toggles
|
||||
for (let l_toggle of l_block.querySelectorAll('.inp_toggle'))
|
||||
modsExtension.addSetting('PAM', l_toggle.id, modsExtension.createToggle(l_toggle, 'OnToggleUpdate_PAM'));
|
||||
|
||||
// Sliders
|
||||
for (let l_slider of l_block.querySelectorAll('.inp_slider'))
|
||||
modsExtension.addSetting('PAM', l_slider.id, modsExtension.createSlider(l_slider, 'OnSliderUpdate_PAM'));
|
||||
|
||||
// Dropdowns
|
||||
for (let l_dropdown of l_block.querySelectorAll('.inp_dropdown'))
|
||||
modsExtension.addSetting('PAM', l_dropdown.id, modsExtension.createDropdown(l_dropdown, 'OnDropdownUpdate_PAM'));
|
||||
}
|
||||
|
|
|
@ -364,12 +364,11 @@ namespace ml_prm
|
|||
|
||||
internal void OnAvatarScaling(float p_scaleDifference)
|
||||
{
|
||||
if(m_avatarReady)
|
||||
{
|
||||
if(m_puppetRoot != null)
|
||||
m_puppetRoot.localScale = Vector3.one * p_scaleDifference;
|
||||
foreach(var l_pair in m_jointAnchors)
|
||||
l_pair.Item1.connectedAnchor = l_pair.Item2 * p_scaleDifference;
|
||||
}
|
||||
|
||||
foreach(var l_pair in m_jointAnchors)
|
||||
l_pair.Item1.connectedAnchor = l_pair.Item2 * p_scaleDifference;
|
||||
}
|
||||
|
||||
internal void OnSeatSitDown(CVRSeat p_seat)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue