mirror of
https://github.com/hanetzer/sdraw_mods_cvr.git
synced 2025-09-05 03:19:23 +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:**
|
**Table for game build 2023r173:**
|
||||||
| Full name | Short name | Latest version | Available in [CVRMA](https://github.com/knah/CVRMelonAssistant) |
|
| 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 |
|
| [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.4 [:arrow_down:](../../releases/latest/download/ml_lme.dll)| ✔ Yes |
|
| [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.8 [:arrow_down:](../../releases/latest/download/ml_pam.dll)| ✔ Yes |
|
| [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 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 |
|
| [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 |
|
| [Vive Extended Input](/ml_vei/README.md) | ml_vei | 1.0.0 [:arrow_down:](../../releases/latest/download/ml_vei.dll)| ✔ Yes |
|
||||||
|
|
|
@ -8,7 +8,6 @@ namespace ml_amt
|
||||||
{
|
{
|
||||||
public enum ParameterType
|
public enum ParameterType
|
||||||
{
|
{
|
||||||
Upright,
|
|
||||||
GroundedRaw,
|
GroundedRaw,
|
||||||
Moving
|
Moving
|
||||||
}
|
}
|
||||||
|
@ -43,10 +42,6 @@ namespace ml_amt
|
||||||
{
|
{
|
||||||
switch(m_type)
|
switch(m_type)
|
||||||
{
|
{
|
||||||
case ParameterType.Upright:
|
|
||||||
SetFloat(p_tweaker.GetUpright());
|
|
||||||
break;
|
|
||||||
|
|
||||||
case ParameterType.GroundedRaw:
|
case ParameterType.GroundedRaw:
|
||||||
SetBoolean(p_tweaker.GetGroundedRaw());
|
SetBoolean(p_tweaker.GetGroundedRaw());
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -136,7 +136,6 @@ namespace ml_amt
|
||||||
m_avatarScale = Mathf.Abs(PlayerSetup.Instance._avatar.transform.localScale.y);
|
m_avatarScale = Mathf.Abs(PlayerSetup.Instance._avatar.transform.localScale.y);
|
||||||
|
|
||||||
// Parse animator parameters
|
// 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.GroundedRaw, PlayerSetup.Instance.animatorManager));
|
||||||
m_parameters.Add(new AvatarParameter(AvatarParameter.ParameterType.Moving, PlayerSetup.Instance.animatorManager));
|
m_parameters.Add(new AvatarParameter(AvatarParameter.ParameterType.Moving, PlayerSetup.Instance.animatorManager));
|
||||||
m_parameters.RemoveAll(p => !p.IsValid());
|
m_parameters.RemoveAll(p => !p.IsValid());
|
||||||
|
@ -246,11 +245,7 @@ namespace ml_amt
|
||||||
}
|
}
|
||||||
|
|
||||||
if(m_locomotionOverride && !l_locomotionOverride)
|
if(m_locomotionOverride && !l_locomotionOverride)
|
||||||
{
|
|
||||||
m_vrIk.solver.Reset();
|
m_vrIk.solver.Reset();
|
||||||
if((IKSystem.VrikRootController != null) && !MovementSystem.Instance.sitting)
|
|
||||||
IKSystem.VrikRootController.enabled = true;
|
|
||||||
}
|
|
||||||
m_locomotionOverride = l_locomotionOverride;
|
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.MelonGame(null, "ChilloutVR")]
|
||||||
[assembly: MelonLoader.MelonPlatform(MelonLoader.MelonPlatformAttribute.CompatiblePlatforms.WINDOWS_X64)]
|
[assembly: MelonLoader.MelonPlatform(MelonLoader.MelonPlatformAttribute.CompatiblePlatforms.WINDOWS_X64)]
|
||||||
[assembly: MelonLoader.MelonPlatformDomain(MelonLoader.MelonPlatformDomainAttribute.CompatibleDomains.MONO)]
|
[assembly: MelonLoader.MelonPlatformDomain(MelonLoader.MelonPlatformDomainAttribute.CompatibleDomains.MONO)]
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
using ABI_RC.Core.UI;
|
using ABI_RC.Core.UI;
|
||||||
using ABI_RC.Systems.MovementSystem;
|
using ABI_RC.Systems.MovementSystem;
|
||||||
using RootMotion.FinalIK;
|
using RootMotion.FinalIK;
|
||||||
|
using System.Collections.Generic;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
|
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
<Company>None</Company>
|
<Company>None</Company>
|
||||||
<Product>AvatarMotionTweaker</Product>
|
<Product>AvatarMotionTweaker</Product>
|
||||||
<PackageId>AvatarMotionTweaker</PackageId>
|
<PackageId>AvatarMotionTweaker</PackageId>
|
||||||
<Version>1.3.4</Version>
|
<Version>1.3.5</Version>
|
||||||
<Platforms>x64</Platforms>
|
<Platforms>x64</Platforms>
|
||||||
<AssemblyName>ml_amt</AssemblyName>
|
<AssemblyName>ml_amt</AssemblyName>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
|
@ -14,7 +14,7 @@ namespace ml_lme
|
||||||
static readonly Quaternion ms_offsetRight = Quaternion.Euler(0f, 270f, 0f);
|
static readonly Quaternion ms_offsetRight = Quaternion.Euler(0f, 270f, 0f);
|
||||||
|
|
||||||
VRIK m_vrIK = null;
|
VRIK m_vrIK = null;
|
||||||
Vector4 m_armsWeights = Vector2.zero;
|
Vector4 m_vrIKWeights = Vector2.zero;
|
||||||
bool m_inVR = false;
|
bool m_inVR = false;
|
||||||
Transform m_hips = null;
|
Transform m_hips = null;
|
||||||
Transform m_origLeftHand = null;
|
Transform m_origLeftHand = null;
|
||||||
|
@ -87,35 +87,8 @@ namespace ml_lme
|
||||||
|
|
||||||
if((m_vrIK != null) && !m_fingersOnly)
|
if((m_vrIK != null) && !m_fingersOnly)
|
||||||
{
|
{
|
||||||
if(l_data.m_leftHand.m_present && !m_leftTargetActive)
|
m_leftTargetActive = l_data.m_leftHand.m_present;
|
||||||
{
|
m_rightTargetActive = l_data.m_rightHand.m_present;
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -207,7 +180,7 @@ namespace ml_lme
|
||||||
m_origLeftElbow = null;
|
m_origLeftElbow = null;
|
||||||
m_origRightElbow = null;
|
m_origRightElbow = null;
|
||||||
m_hips = null;
|
m_hips = null;
|
||||||
m_armsWeights = Vector2.zero;
|
m_vrIKWeights = Vector2.zero;
|
||||||
m_leftArmIK = null;
|
m_leftArmIK = null;
|
||||||
m_rightArmIK = null;
|
m_rightArmIK = null;
|
||||||
m_leftTargetActive = false;
|
m_leftTargetActive = false;
|
||||||
|
@ -329,30 +302,42 @@ namespace ml_lme
|
||||||
// IK updates
|
// IK updates
|
||||||
void OnIKPreUpdate()
|
void OnIKPreUpdate()
|
||||||
{
|
{
|
||||||
m_armsWeights.Set(
|
m_vrIKWeights.Set(
|
||||||
m_vrIK.solver.leftArm.positionWeight,
|
m_vrIK.solver.leftArm.positionWeight,
|
||||||
m_vrIK.solver.leftArm.rotationWeight,
|
m_vrIK.solver.leftArm.rotationWeight,
|
||||||
m_vrIK.solver.rightArm.positionWeight,
|
m_vrIK.solver.rightArm.positionWeight,
|
||||||
m_vrIK.solver.rightArm.rotationWeight
|
m_vrIK.solver.rightArm.rotationWeight
|
||||||
);
|
);
|
||||||
|
|
||||||
if(m_leftTargetActive && (Mathf.Approximately(m_armsWeights.x, 0f) || Mathf.Approximately(m_armsWeights.y, 0f)))
|
if(m_leftTargetActive)
|
||||||
{
|
{
|
||||||
m_vrIK.solver.leftArm.positionWeight = 1f;
|
m_vrIK.solver.leftArm.positionWeight = 1f;
|
||||||
m_vrIK.solver.leftArm.rotationWeight = 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 && (Mathf.Approximately(m_armsWeights.z, 0f) || Mathf.Approximately(m_armsWeights.w, 0f)))
|
if(m_rightTargetActive)
|
||||||
{
|
{
|
||||||
m_vrIK.solver.rightArm.positionWeight = 1f;
|
m_vrIK.solver.rightArm.positionWeight = 1f;
|
||||||
m_vrIK.solver.rightArm.rotationWeight = 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()
|
void OnIKPostUpdate()
|
||||||
{
|
{
|
||||||
m_vrIK.solver.leftArm.positionWeight = m_armsWeights.x;
|
m_vrIK.solver.leftArm.positionWeight = m_vrIKWeights.x;
|
||||||
m_vrIK.solver.leftArm.rotationWeight = m_armsWeights.y;
|
m_vrIK.solver.leftArm.rotationWeight = m_vrIKWeights.y;
|
||||||
m_vrIK.solver.rightArm.positionWeight = m_armsWeights.z;
|
m_vrIK.solver.leftArm.target = m_origLeftHand;
|
||||||
m_vrIK.solver.rightArm.rotationWeight = m_armsWeights.w;
|
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
|
// Settings
|
||||||
|
@ -392,20 +377,8 @@ namespace ml_lme
|
||||||
{
|
{
|
||||||
if(m_vrIK != null)
|
if(m_vrIK != null)
|
||||||
{
|
{
|
||||||
if(m_leftTargetActive)
|
m_leftTargetActive = false;
|
||||||
{
|
m_rightTargetActive = false;
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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.MelonGame(null, "ChilloutVR")]
|
||||||
[assembly: MelonLoader.MelonOptionalDependencies("ml_pmc")]
|
[assembly: MelonLoader.MelonOptionalDependencies("ml_pmc")]
|
||||||
[assembly: MelonLoader.MelonPlatform(MelonLoader.MelonPlatformAttribute.CompatiblePlatforms.WINDOWS_X64)]
|
[assembly: MelonLoader.MelonPlatform(MelonLoader.MelonPlatformAttribute.CompatiblePlatforms.WINDOWS_X64)]
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
<TargetFramework>netstandard2.1</TargetFramework>
|
<TargetFramework>netstandard2.1</TargetFramework>
|
||||||
<Platforms>x64</Platforms>
|
<Platforms>x64</Platforms>
|
||||||
<PackageId>LeapMotionExtension</PackageId>
|
<PackageId>LeapMotionExtension</PackageId>
|
||||||
<Version>1.4.4</Version>
|
<Version>1.4.5</Version>
|
||||||
<Authors>SDraw</Authors>
|
<Authors>SDraw</Authors>
|
||||||
<Company>None</Company>
|
<Company>None</Company>
|
||||||
<Product>LeapMotionExtension</Product>
|
<Product>LeapMotionExtension</Product>
|
||||||
|
|
4
ml_lme/vendor/LeapSDK/README.md
vendored
4
ml_lme/vendor/LeapSDK/README.md
vendored
|
@ -98,7 +98,7 @@ cmake --build ${REPOS_BUILD_ROOT}/${BUILD_TYPE}/LeapSDK/leapc_example -j --confi
|
||||||
|
|
||||||
### MacOS
|
### MacOS
|
||||||
|
|
||||||
1. Open CMake using /Library/Application Support/Ultraleap/LeapSDK/samples as the source directory
|
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
|
2. Select a build directory (eg. ~/ultraleap-tracking-samples/build) to use
|
||||||
|
|
||||||
|
@ -107,7 +107,7 @@ cmake --build ${REPOS_BUILD_ROOT}/${BUILD_TYPE}/LeapSDK/leapc_example -j --confi
|
||||||
4. Open and build the CMake generated project files. For more help, see the CMake documentation.
|
4. Open and build the CMake generated project files. For more help, see the CMake documentation.
|
||||||
* An example script would be :
|
* An example script would be :
|
||||||
```bash
|
```bash
|
||||||
SRC_DIR='/Library/Application Support/Ultraleap/LeapSDK/samples'
|
SRC_DIR='/Applications/Ultraleap\ Hand\ Tracking\ Service.app/Contents/LeapSDK/samples'
|
||||||
BUILD_TYPE='Release'
|
BUILD_TYPE='Release'
|
||||||
REPOS_BUILD_ROOT=~/ultraleap-tracking-samples/build
|
REPOS_BUILD_ROOT=~/ultraleap-tracking-samples/build
|
||||||
REPOS_INSTALL_ROOT=~/ultraleap-tracking-samples/bin
|
REPOS_INSTALL_ROOT=~/ultraleap-tracking-samples/bin
|
||||||
|
|
2147
ml_lme/vendor/LeapSDK/ThirdPartyNotices.md
vendored
2147
ml_lme/vendor/LeapSDK/ThirdPartyNotices.md
vendored
File diff suppressed because it is too large
Load diff
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.InteractionSystem;
|
||||||
using ABI_RC.Core.Player;
|
using ABI_RC.Core.Player;
|
||||||
using RootMotion.FinalIK;
|
using RootMotion.FinalIK;
|
||||||
using System.Reflection;
|
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
|
|
||||||
namespace ml_pam
|
namespace ml_pam
|
||||||
|
@ -10,47 +9,72 @@ namespace ml_pam
|
||||||
[DisallowMultipleComponent]
|
[DisallowMultipleComponent]
|
||||||
class ArmMover : MonoBehaviour
|
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 Vector4 ms_pointVector = new Vector4(0f, 0f, 0f, 1f);
|
||||||
static readonly Quaternion ms_offsetRight = Quaternion.Euler(0f, 0f, 90f);
|
static readonly Quaternion ms_offsetLeft = Quaternion.Euler(270f, 90f, 0f);
|
||||||
static readonly Quaternion ms_offsetRightDesktop = Quaternion.Euler(0f, 270f, 0f);
|
static readonly Quaternion ms_offsetRight = Quaternion.Euler(270f, 270f, 0f);
|
||||||
static readonly Quaternion ms_palmToLeft = Quaternion.Euler(0f, 0f, -90f);
|
|
||||||
|
|
||||||
bool m_inVR = false;
|
bool m_inVR = false;
|
||||||
VRIK m_vrIK = null;
|
VRIK m_vrIK = null;
|
||||||
Vector2 m_armWeight = Vector2.zero;
|
Vector4 m_vrIKWeights = Vector4.zero;
|
||||||
Transform m_origRightHand = null;
|
Transform m_origRightHand = null;
|
||||||
|
Transform m_origLeftHand = null;
|
||||||
|
float m_armLength = 0f;
|
||||||
float m_playspaceScale = 1f;
|
float m_playspaceScale = 1f;
|
||||||
|
|
||||||
bool m_enabled = true;
|
bool m_enabled = true;
|
||||||
ArmIK m_armIK = null;
|
Transform m_rootLeft = null;
|
||||||
Transform m_target = null;
|
Transform m_rootRight = null;
|
||||||
Transform m_rotationTarget = null;
|
Transform m_leftTarget = null;
|
||||||
|
Transform m_rightTarget = null;
|
||||||
|
ArmIK m_armIKLeft = null;
|
||||||
|
ArmIK m_armIKRight = null;
|
||||||
CVRPickupObject m_pickup = null;
|
CVRPickupObject m_pickup = null;
|
||||||
Matrix4x4 m_offset = Matrix4x4.identity;
|
Matrix4x4 m_offset;
|
||||||
bool m_targetActive = false;
|
HandState m_leftHandState = HandState.Empty;
|
||||||
|
HandState m_rightHandState = HandState.Empty;
|
||||||
|
|
||||||
// Unity events
|
// Unity events
|
||||||
void Start()
|
void Start()
|
||||||
{
|
{
|
||||||
m_inVR = Utils.IsInVR();
|
m_inVR = Utils.IsInVR();
|
||||||
|
|
||||||
m_target = new GameObject("ArmPickupTarget").transform;
|
m_rootLeft = new GameObject("[ArmPickupLeft]").transform;
|
||||||
m_target.parent = PlayerSetup.Instance.GetActiveCamera().transform;
|
m_rootLeft.parent = PlayerSetup.Instance.GetActiveCamera().transform;
|
||||||
m_target.localPosition = Vector3.zero;
|
m_rootLeft.localPosition = Vector3.zero;
|
||||||
m_target.localRotation = Quaternion.identity;
|
m_rootLeft.localRotation = Quaternion.identity;
|
||||||
|
|
||||||
m_rotationTarget = new GameObject("RotationTarget").transform;
|
m_leftTarget = new GameObject("Target").transform;
|
||||||
m_rotationTarget.parent = m_target;
|
m_leftTarget.parent = m_rootLeft;
|
||||||
m_rotationTarget.localPosition = new Vector3(c_offsetLimit * Settings.GrabOffset, 0f, 0f);
|
m_leftTarget.localPosition = new Vector3(c_offsetLimit * -Settings.GrabOffset, 0f, 0f);
|
||||||
m_rotationTarget.localRotation = Quaternion.identity;
|
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;
|
m_enabled = Settings.Enabled;
|
||||||
|
|
||||||
Settings.EnabledChange += this.SetEnabled;
|
Settings.EnabledChange += this.SetEnabled;
|
||||||
Settings.GrabOffsetChange += this.SetGrabOffset;
|
Settings.GrabOffsetChange += this.SetGrabOffset;
|
||||||
|
Settings.LeadingHandChange += this.OnLeadingHandChange;
|
||||||
|
Settings.HandsExtensionChange += this.OnHandsExtensionChange;
|
||||||
}
|
}
|
||||||
|
|
||||||
void OnDestroy()
|
void OnDestroy()
|
||||||
|
@ -61,33 +85,106 @@ namespace ml_pam
|
||||||
|
|
||||||
void Update()
|
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;
|
if(Settings.HandsExtension && Input.GetKeyDown(c_leftKey))
|
||||||
m_target.position = l_result * ms_pointVector;
|
{
|
||||||
|
m_leftHandState = HandState.Extended;
|
||||||
|
m_rootLeft.localPosition = new Vector3(0f, 0f, m_armLength * m_playspaceScale);
|
||||||
|
SetArmActive(Settings.LeadHand.Left, true);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
break;
|
||||||
this.OnPickupDrop(m_pickup);
|
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()
|
void OnIKPreUpdate()
|
||||||
{
|
{
|
||||||
m_armWeight.Set(m_vrIK.solver.rightArm.positionWeight, m_vrIK.solver.rightArm.rotationWeight);
|
if(m_enabled)
|
||||||
|
|
||||||
if(m_targetActive && (Mathf.Approximately(m_armWeight.x, 0f) || Mathf.Approximately(m_armWeight.y, 0f)))
|
|
||||||
{
|
{
|
||||||
m_vrIK.solver.rightArm.positionWeight = 1f;
|
m_vrIKWeights.Set(m_vrIK.solver.leftArm.positionWeight, m_vrIK.solver.leftArm.rotationWeight, m_vrIK.solver.rightArm.positionWeight, m_vrIK.solver.rightArm.rotationWeight);
|
||||||
m_vrIK.solver.rightArm.rotationWeight = 1f;
|
|
||||||
|
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()
|
void OnIKPostUpdate()
|
||||||
{
|
{
|
||||||
m_vrIK.solver.rightArm.positionWeight = m_armWeight.x;
|
if(m_enabled)
|
||||||
m_vrIK.solver.rightArm.rotationWeight = m_armWeight.y;
|
{
|
||||||
|
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
|
// Settings
|
||||||
|
@ -95,17 +192,93 @@ namespace ml_pam
|
||||||
{
|
{
|
||||||
m_enabled = p_state;
|
m_enabled = p_state;
|
||||||
|
|
||||||
RefreshArmIK();
|
|
||||||
if(m_enabled)
|
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
|
else
|
||||||
RestoreVRIK();
|
SetArmActive(Settings.LeadHand.Both, false, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SetGrabOffset(float p_value)
|
void SetGrabOffset(float p_value)
|
||||||
{
|
{
|
||||||
if(m_rotationTarget != null)
|
if(m_leftTarget != null)
|
||||||
m_rotationTarget.localPosition = new Vector3(c_offsetLimit * m_playspaceScale * p_value, 0f, 0f);
|
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
|
// Game events
|
||||||
|
@ -113,8 +286,9 @@ namespace ml_pam
|
||||||
{
|
{
|
||||||
m_vrIK = null;
|
m_vrIK = null;
|
||||||
m_origRightHand = null;
|
m_origRightHand = null;
|
||||||
m_armIK = null;
|
m_armIKLeft = null;
|
||||||
m_targetActive = false;
|
m_armIKRight = null;
|
||||||
|
m_armLength = 0f;
|
||||||
}
|
}
|
||||||
|
|
||||||
internal void OnAvatarSetup()
|
internal void OnAvatarSetup()
|
||||||
|
@ -122,44 +296,30 @@ namespace ml_pam
|
||||||
// Recheck if user could switch to VR
|
// Recheck if user could switch to VR
|
||||||
if(m_inVR != Utils.IsInVR())
|
if(m_inVR != Utils.IsInVR())
|
||||||
{
|
{
|
||||||
m_target.parent = PlayerSetup.Instance.GetActiveCamera().transform;
|
m_rootLeft.parent = PlayerSetup.Instance.GetActiveCamera().transform;
|
||||||
m_target.localPosition = Vector3.zero;
|
m_rootLeft.localPosition = Vector3.zero;
|
||||||
m_target.localRotation = Quaternion.identity;
|
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_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;
|
m_vrIK = PlayerSetup.Instance._animator.GetComponent<VRIK>();
|
||||||
Transform l_hips = PlayerSetup.Instance._animator.GetBoneTransform(HumanBodyBones.Hips);
|
|
||||||
if(l_hips != null)
|
|
||||||
l_hipsPos = l_hips.localPosition;
|
|
||||||
|
|
||||||
HumanPose l_currentPose = new HumanPose();
|
TPoseHelper l_tpHelper = new TPoseHelper();
|
||||||
HumanPoseHandler l_poseHandler = null;
|
l_tpHelper.Assign(PlayerSetup.Instance._animator);
|
||||||
|
l_tpHelper.Apply();
|
||||||
|
|
||||||
if(!m_inVR)
|
Transform l_leftHand = PlayerSetup.Instance._animator.GetBoneTransform(HumanBodyBones.LeftHand);
|
||||||
{
|
if(l_leftHand != null)
|
||||||
l_poseHandler = new HumanPoseHandler(PlayerSetup.Instance._animator.avatar, PlayerSetup.Instance._avatar.transform);
|
m_leftTarget.localRotation = ms_offsetLeft * (PlayerSetup.Instance._avatar.transform.GetMatrix().inverse * l_leftHand.GetMatrix()).rotation;
|
||||||
l_poseHandler.GetHumanPose(ref l_currentPose);
|
Transform l_rightHand = PlayerSetup.Instance._animator.GetBoneTransform(HumanBodyBones.RightHand);
|
||||||
|
if(l_rightHand != null)
|
||||||
HumanPose l_tPose = new HumanPose
|
m_rightTarget.localRotation = ms_offsetRight * (PlayerSetup.Instance._avatar.transform.GetMatrix().inverse * l_rightHand.GetMatrix()).rotation;
|
||||||
{
|
|
||||||
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;
|
|
||||||
|
|
||||||
if(m_vrIK == null)
|
if(m_vrIK == null)
|
||||||
{
|
{
|
||||||
|
@ -169,39 +329,56 @@ namespace ml_pam
|
||||||
if(l_chest == null)
|
if(l_chest == null)
|
||||||
l_chest = PlayerSetup.Instance._animator.GetBoneTransform(HumanBodyBones.Spine);
|
l_chest = PlayerSetup.Instance._animator.GetBoneTransform(HumanBodyBones.Spine);
|
||||||
|
|
||||||
m_armIK = PlayerSetup.Instance._avatar.AddComponent<ArmIK>();
|
m_armIKLeft = PlayerSetup.Instance._avatar.AddComponent<ArmIK>();
|
||||||
m_armIK.solver.isLeft = false;
|
m_armIKLeft.solver.isLeft = true;
|
||||||
m_armIK.solver.SetChain(
|
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,
|
l_chest,
|
||||||
PlayerSetup.Instance._animator.GetBoneTransform(HumanBodyBones.RightShoulder),
|
PlayerSetup.Instance._animator.GetBoneTransform(HumanBodyBones.RightShoulder),
|
||||||
PlayerSetup.Instance._animator.GetBoneTransform(HumanBodyBones.RightUpperArm),
|
PlayerSetup.Instance._animator.GetBoneTransform(HumanBodyBones.RightUpperArm),
|
||||||
PlayerSetup.Instance._animator.GetBoneTransform(HumanBodyBones.RightLowerArm),
|
PlayerSetup.Instance._animator.GetBoneTransform(HumanBodyBones.RightLowerArm),
|
||||||
l_hand,
|
l_rightHand,
|
||||||
PlayerSetup.Instance._animator.transform
|
PlayerSetup.Instance._animator.transform
|
||||||
);
|
);
|
||||||
m_armIK.solver.arm.target = m_rotationTarget;
|
m_armIKRight.solver.arm.target = m_rightTarget;
|
||||||
m_armIK.solver.arm.positionWeight = 1f;
|
m_armIKRight.solver.arm.positionWeight = 1f;
|
||||||
m_armIK.solver.arm.rotationWeight = 1f;
|
m_armIKRight.solver.arm.rotationWeight = 1f;
|
||||||
m_armIK.solver.IKPositionWeight = 0f;
|
m_armIKRight.solver.IKPositionWeight = 0f;
|
||||||
m_armIK.solver.IKRotationWeight = 0f;
|
m_armIKRight.solver.IKRotationWeight = 0f;
|
||||||
m_armIK.enabled = m_enabled;
|
m_armIKRight.enabled = false;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
m_origLeftHand = m_vrIK.solver.leftArm.target;
|
||||||
m_origRightHand = m_vrIK.solver.rightArm.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.OnPreUpdate += this.OnIKPreUpdate;
|
||||||
m_vrIK.solver.OnPostUpdate += this.OnIKPostUpdate;
|
m_vrIK.solver.OnPostUpdate += this.OnIKPostUpdate;
|
||||||
}
|
}
|
||||||
|
|
||||||
l_poseHandler?.SetHumanPose(ref l_currentPose);
|
l_tpHelper.Restore();
|
||||||
l_poseHandler?.Dispose();
|
l_tpHelper.Unassign();
|
||||||
|
|
||||||
if(l_hips != null)
|
|
||||||
l_hips.localPosition = l_hipsPos;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if(m_enabled)
|
SetEnabled(m_enabled);
|
||||||
RestorePickup();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
internal void OnPickupGrab(CVRPickupObject p_pickup, ControllerRay p_ray, Vector3 p_hit)
|
internal void OnPickupGrab(CVRPickupObject p_pickup, ControllerRay p_ray, Vector3 p_hit)
|
||||||
|
@ -224,20 +401,23 @@ namespace ml_pam
|
||||||
else
|
else
|
||||||
m_offset = m_pickup.transform.GetMatrix().inverse * Matrix4x4.Translate(p_hit);
|
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_leftHandState = HandState.Pickup;
|
||||||
m_targetActive = true;
|
m_rightHandState = HandState.Pickup;
|
||||||
}
|
|
||||||
|
|
||||||
if(m_armIK != null)
|
|
||||||
{
|
|
||||||
m_armIK.solver.IKPositionWeight = 1f;
|
|
||||||
m_armIK.solver.IKRotationWeight = 1f;
|
|
||||||
}
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SetArmActive(Settings.LeadingHand, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -246,17 +426,22 @@ namespace ml_pam
|
||||||
if(m_pickup == p_pickup)
|
if(m_pickup == p_pickup)
|
||||||
{
|
{
|
||||||
m_pickup = null;
|
m_pickup = null;
|
||||||
|
switch(Settings.LeadingHand)
|
||||||
if(m_enabled)
|
|
||||||
{
|
{
|
||||||
RestoreVRIK();
|
case Settings.LeadHand.Left:
|
||||||
|
m_leftHandState = HandState.Empty;
|
||||||
if(m_armIK != null)
|
break;
|
||||||
|
case Settings.LeadHand.Right:
|
||||||
|
m_rightHandState = HandState.Empty;
|
||||||
|
break;
|
||||||
|
case Settings.LeadHand.Both:
|
||||||
{
|
{
|
||||||
m_armIK.solver.IKPositionWeight = 0f;
|
m_leftHandState = HandState.Empty;
|
||||||
m_armIK.solver.IKRotationWeight = 0f;
|
m_rightHandState = HandState.Empty;
|
||||||
}
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
SetArmActive(Settings.LeadingHand, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -267,33 +452,23 @@ namespace ml_pam
|
||||||
}
|
}
|
||||||
|
|
||||||
// Arbitrary
|
// 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;
|
if(((p_hand == Settings.LeadHand.Left) || (p_hand == Settings.LeadHand.Both)) && (m_armIKLeft != null))
|
||||||
m_targetActive = true;
|
{
|
||||||
|
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,4 +1,4 @@
|
||||||
[assembly: MelonLoader.MelonInfo(typeof(ml_pam.PickupArmMovement), "PickupArmMovement", "1.0.8", "SDraw", "https://github.com/SDraw/ml_mods_cvr")]
|
[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.MelonGame(null, "ChilloutVR")]
|
||||||
[assembly: MelonLoader.MelonPriority(1)]
|
[assembly: MelonLoader.MelonPriority(1)]
|
||||||
[assembly: MelonLoader.MelonPlatform(MelonLoader.MelonPlatformAttribute.CompatiblePlatforms.WINDOWS_X64)]
|
[assembly: MelonLoader.MelonPlatform(MelonLoader.MelonPlatformAttribute.CompatiblePlatforms.WINDOWS_X64)]
|
||||||
|
|
|
@ -9,4 +9,10 @@ This mod adds arm tracking upon holding pickup in desktop mode.
|
||||||
# Usage
|
# Usage
|
||||||
Available mod's settings in `Settings - Interactions - Pickup Arm Movement`:
|
Available mod's settings in `Settings - Interactions - Pickup Arm Movement`:
|
||||||
* **Enable hand movement:** enables/disables arm tracking; default value - `true`.
|
* **Enable hand movement:** enables/disables arm tracking; default value - `true`.
|
||||||
* **Grab offset:** offset from pickup grab point; defalut value - `25`.
|
* **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).
|
||||||
|
|
|
@ -9,17 +9,29 @@ namespace ml_pam
|
||||||
public enum ModSetting
|
public enum ModSetting
|
||||||
{
|
{
|
||||||
Enabled = 0,
|
Enabled = 0,
|
||||||
GrabOffset
|
GrabOffset,
|
||||||
|
LeadHand,
|
||||||
|
HandsExtension
|
||||||
|
}
|
||||||
|
public enum LeadHand
|
||||||
|
{
|
||||||
|
Left = 0,
|
||||||
|
Right,
|
||||||
|
Both
|
||||||
}
|
}
|
||||||
|
|
||||||
public static bool Enabled { get; private set; } = true;
|
public static bool Enabled { get; private set; } = true;
|
||||||
public static float GrabOffset { get; private set; } = 0.25f;
|
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 MelonLoader.MelonPreferences_Category ms_category = null;
|
||||||
static List<MelonLoader.MelonPreferences_Entry> ms_entries = null;
|
static List<MelonLoader.MelonPreferences_Entry> ms_entries = null;
|
||||||
|
|
||||||
static public event Action<bool> EnabledChange;
|
static public event Action<bool> EnabledChange;
|
||||||
static public event Action<float> GrabOffsetChange;
|
static public event Action<float> GrabOffsetChange;
|
||||||
|
static public event Action<LeadHand> LeadingHandChange;
|
||||||
|
static public event Action<bool> HandsExtensionChange;
|
||||||
|
|
||||||
internal static void Init()
|
internal static void Init()
|
||||||
{
|
{
|
||||||
|
@ -29,9 +41,14 @@ namespace ml_pam
|
||||||
{
|
{
|
||||||
ms_category.CreateEntry(ModSetting.Enabled.ToString(), Enabled),
|
ms_category.CreateEntry(ModSetting.Enabled.ToString(), Enabled),
|
||||||
ms_category.CreateEntry(ModSetting.GrabOffset.ToString(), (int)(GrabOffset * 100f)),
|
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),
|
||||||
};
|
};
|
||||||
|
|
||||||
Load();
|
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());
|
MelonLoader.MelonCoroutines.Start(WaitMainMenuUi());
|
||||||
}
|
}
|
||||||
|
@ -49,6 +66,7 @@ namespace ml_pam
|
||||||
{
|
{
|
||||||
ViewManager.Instance.gameMenuView.View.BindCall("OnToggleUpdate_" + ms_category.Identifier, new Action<string, string>(OnToggleUpdate));
|
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("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.Listener.FinishLoad += (_) =>
|
||||||
{
|
{
|
||||||
|
@ -59,12 +77,6 @@ namespace ml_pam
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
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)
|
static void OnToggleUpdate(string p_name, string p_value)
|
||||||
{
|
{
|
||||||
if(Enum.TryParse(p_name, out ModSetting l_setting))
|
if(Enum.TryParse(p_name, out ModSetting l_setting))
|
||||||
|
@ -77,6 +89,12 @@ namespace ml_pam
|
||||||
EnabledChange?.Invoke(Enabled);
|
EnabledChange?.Invoke(Enabled);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case ModSetting.HandsExtension:
|
||||||
|
{
|
||||||
|
HandsExtension = bool.Parse(p_value);
|
||||||
|
HandsExtensionChange?.Invoke(HandsExtension);
|
||||||
|
} break;
|
||||||
}
|
}
|
||||||
|
|
||||||
ms_entries[(int)l_setting].BoxedValue = bool.Parse(p_value);
|
ms_entries[(int)l_setting].BoxedValue = bool.Parse(p_value);
|
||||||
|
@ -100,5 +118,23 @@ namespace ml_pam
|
||||||
ms_entries[(int)l_setting].BoxedValue = int.Parse(p_value);
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -4,7 +4,7 @@
|
||||||
<TargetFramework>netstandard2.1</TargetFramework>
|
<TargetFramework>netstandard2.1</TargetFramework>
|
||||||
<Platforms>x64</Platforms>
|
<Platforms>x64</Platforms>
|
||||||
<PackageId>PickupArmMovement</PackageId>
|
<PackageId>PickupArmMovement</PackageId>
|
||||||
<Version>1.0.8</Version>
|
<Version>1.0.9</Version>
|
||||||
<Authors>SDraw</Authors>
|
<Authors>SDraw</Authors>
|
||||||
<Company>None</Company>
|
<Company>None</Company>
|
||||||
<Product>PickupArmMovement</Product>
|
<Product>PickupArmMovement</Product>
|
||||||
|
@ -65,6 +65,10 @@
|
||||||
<HintPath>D:\Games\Steam\steamapps\common\ChilloutVR\ChilloutVR_Data\Managed\UnityEngine.CoreModule.dll</HintPath>
|
<HintPath>D:\Games\Steam\steamapps\common\ChilloutVR\ChilloutVR_Data\Managed\UnityEngine.CoreModule.dll</HintPath>
|
||||||
<Private>false</Private>
|
<Private>false</Private>
|
||||||
</Reference>
|
</Reference>
|
||||||
|
<Reference Include="UnityEngine.InputLegacyModule">
|
||||||
|
<HintPath>D:\Games\Steam\steamapps\common\ChilloutVR\ChilloutVR_Data\Managed\UnityEngine.InputLegacyModule.dll</HintPath>
|
||||||
|
<Private>false</Private>
|
||||||
|
</Reference>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<Target Name="PostBuild" AfterTargets="PostBuildEvent">
|
<Target Name="PostBuild" AfterTargets="PostBuildEvent">
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class ="row-wrapper">
|
<div class ="row-wrapper">
|
||||||
<div class ="option-caption">Enable hand movement: </div>
|
<div class ="option-caption">Enabled: </div>
|
||||||
<div class ="option-input">
|
<div class ="option-input">
|
||||||
<div id="Enabled" class ="inp_toggle no-scroll" data-current="true"></div>
|
<div id="Enabled" class ="inp_toggle no-scroll" data-current="true"></div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -19,6 +19,20 @@
|
||||||
<div id="GrabOffset" class ="inp_slider no-scroll" data-min="0" data-max="100" data-current="25"></div>
|
<div id="GrabOffset" class ="inp_slider no-scroll" data-min="0" data-max="100" data-current="25"></div>
|
||||||
</div>
|
</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);
|
document.getElementById('settings-interaction').appendChild(l_block);
|
||||||
|
|
||||||
|
@ -29,4 +43,8 @@
|
||||||
// Sliders
|
// Sliders
|
||||||
for (let l_slider of l_block.querySelectorAll('.inp_slider'))
|
for (let l_slider of l_block.querySelectorAll('.inp_slider'))
|
||||||
modsExtension.addSetting('PAM', l_slider.id, modsExtension.createSlider(l_slider, 'OnSliderUpdate_PAM'));
|
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)
|
internal void OnAvatarScaling(float p_scaleDifference)
|
||||||
{
|
{
|
||||||
if(m_avatarReady)
|
if(m_puppetRoot != null)
|
||||||
{
|
|
||||||
m_puppetRoot.localScale = Vector3.one * p_scaleDifference;
|
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)
|
internal void OnSeatSitDown(CVRSeat p_seat)
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue