mirror of
https://github.com/hanetzer/sdraw_mods_cvr.git
synced 2025-09-03 10:29:22 +00:00
New mod: Better Fingers Tracking
Default muscles values to zero Embedding of debug symbols
This commit is contained in:
parent
d6e52feb27
commit
2aaac8f7bd
27 changed files with 1457 additions and 36 deletions
|
@ -5,6 +5,7 @@ Merged set of MelonLoader mods for ChilloutVR.
|
||||||
|:---------:|:----------:|:--------------:| :----------------------------------------------------------------|
|
|:---------:|:----------:|:--------------:| :----------------------------------------------------------------|
|
||||||
| [Avatar Motion Tweaker](/ml_amt/README.md) | ml_amt | 1.3.7 [:arrow_down:](../../releases/latest/download/ml_amt.dll)| ✔ Yes |
|
| [Avatar Motion Tweaker](/ml_amt/README.md) | ml_amt | 1.3.7 [:arrow_down:](../../releases/latest/download/ml_amt.dll)| ✔ Yes |
|
||||||
| [Avatar Synced Look](/ml_asl/README.md) | ml_asl | 1.0.1 [:arrow_down:](../../releases/latest/download/ml_asl.dll)| ✔ Yes |
|
| [Avatar Synced Look](/ml_asl/README.md) | ml_asl | 1.0.1 [:arrow_down:](../../releases/latest/download/ml_asl.dll)| ✔ Yes |
|
||||||
|
| [Better Fingers Tracking](/ml_bft/README.md) | ml_bft | 1.0.0 [:arrow_down:](../../releases/latest/download/ml_bft.dll)| On review |
|
||||||
| [Desktop Head Tracking](/ml_dht/README.md) | ml_dht | 1.2.1 [:arrow_down:](../../releases/latest/download/ml_dht.dll) | ✔ Yes |
|
| [Desktop Head Tracking](/ml_dht/README.md) | ml_dht | 1.2.1 [:arrow_down:](../../releases/latest/download/ml_dht.dll) | ✔ Yes |
|
||||||
| [Leap Motion Extension](/ml_lme/README.md)| ml_lme | 1.4.6 [:arrow_down:](../../releases/latest/download/ml_lme.dll)| ✔ Yes |
|
| [Leap Motion Extension](/ml_lme/README.md)| ml_lme | 1.4.6 [:arrow_down:](../../releases/latest/download/ml_lme.dll)| ✔ Yes |
|
||||||
| [Pickup Arm Movement](/ml_pam/README.md)| ml_pam | 1.1.0 [:arrow_down:](../../releases/latest/download/ml_pam.dll)| ✔ Yes |
|
| [Pickup Arm Movement](/ml_pam/README.md)| ml_pam | 1.1.0 [:arrow_down:](../../releases/latest/download/ml_pam.dll)| ✔ Yes |
|
||||||
|
|
|
@ -14,8 +14,8 @@
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||||
<PlatformTarget>x64</PlatformTarget>
|
<PlatformTarget>x64</PlatformTarget>
|
||||||
<WarningLevel>4</WarningLevel>
|
<WarningLevel>4</WarningLevel>
|
||||||
<DebugType>none</DebugType>
|
<DebugType>embedded</DebugType>
|
||||||
<DebugSymbols>false</DebugSymbols>
|
<DebugSymbols>true</DebugSymbols>
|
||||||
<AllowUnsafeBlocks>false</AllowUnsafeBlocks>
|
<AllowUnsafeBlocks>false</AllowUnsafeBlocks>
|
||||||
<DefineConstants>TRACE</DefineConstants>
|
<DefineConstants>TRACE</DefineConstants>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
|
@ -10,6 +10,11 @@
|
||||||
<Version>1.0.1</Version>
|
<Version>1.0.1</Version>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||||
|
<DebugType>embedded</DebugType>
|
||||||
|
<DebugSymbols>true</DebugSymbols>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<None Remove="resources\mod_menu.js" />
|
<None Remove="resources\mod_menu.js" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
89
ml_bft/AssetsHandler.cs
Normal file
89
ml_bft/AssetsHandler.cs
Normal file
|
@ -0,0 +1,89 @@
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
using System.Reflection;
|
||||||
|
using UnityEngine;
|
||||||
|
|
||||||
|
namespace ml_bft
|
||||||
|
{
|
||||||
|
static class AssetsHandler
|
||||||
|
{
|
||||||
|
static readonly List<string> ms_assets = new List<string>()
|
||||||
|
{
|
||||||
|
"ovr_fingers.asset",
|
||||||
|
"oxr_fingers.asset"
|
||||||
|
};
|
||||||
|
|
||||||
|
static readonly Dictionary<string, AssetBundle> ms_loadedAssets = new Dictionary<string, AssetBundle>();
|
||||||
|
static readonly Dictionary<string, GameObject> ms_loadedObjects = new Dictionary<string, GameObject>();
|
||||||
|
|
||||||
|
public static void Load()
|
||||||
|
{
|
||||||
|
Assembly l_assembly = Assembly.GetExecutingAssembly();
|
||||||
|
string l_assemblyName = l_assembly.GetName().Name;
|
||||||
|
|
||||||
|
foreach(string l_assetName in ms_assets)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
Stream l_assetStream = l_assembly.GetManifestResourceStream(l_assemblyName + ".resources." + l_assetName);
|
||||||
|
if(l_assetStream != null)
|
||||||
|
{
|
||||||
|
MemoryStream l_memorySteam = new MemoryStream((int)l_assetStream.Length);
|
||||||
|
l_assetStream.CopyTo(l_memorySteam);
|
||||||
|
AssetBundle l_assetBundle = AssetBundle.LoadFromMemory(l_memorySteam.ToArray(), 0);
|
||||||
|
if(l_assetBundle != null)
|
||||||
|
{
|
||||||
|
l_assetBundle.hideFlags |= HideFlags.DontUnloadUnusedAsset;
|
||||||
|
ms_loadedAssets.Add(l_assetName, l_assetBundle);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
MelonLoader.MelonLogger.Warning("Unable to load bundled '" + l_assetName + "' asset");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
MelonLoader.MelonLogger.Warning("Unable to get bundled '" + l_assetName + "' asset stream");
|
||||||
|
}
|
||||||
|
catch(System.Exception e)
|
||||||
|
{
|
||||||
|
MelonLoader.MelonLogger.Warning("Unable to load bundled '" + l_assetName + "' asset, reason: " + e.Message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static GameObject GetAsset(string p_name)
|
||||||
|
{
|
||||||
|
GameObject l_result = null;
|
||||||
|
if(ms_loadedObjects.ContainsKey(p_name))
|
||||||
|
{
|
||||||
|
l_result = Object.Instantiate(ms_loadedObjects[p_name]);
|
||||||
|
l_result.SetActive(true);
|
||||||
|
l_result.hideFlags |= HideFlags.DontUnloadUnusedAsset;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
foreach(var l_pair in ms_loadedAssets)
|
||||||
|
{
|
||||||
|
if(l_pair.Value.Contains(p_name))
|
||||||
|
{
|
||||||
|
GameObject l_bundledObject = (GameObject)l_pair.Value.LoadAsset(p_name, typeof(GameObject));
|
||||||
|
if(l_bundledObject != null)
|
||||||
|
{
|
||||||
|
ms_loadedObjects.Add(p_name, l_bundledObject);
|
||||||
|
l_result = Object.Instantiate(l_bundledObject);
|
||||||
|
l_result.SetActive(true);
|
||||||
|
l_result.hideFlags |= HideFlags.DontUnloadUnusedAsset;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return l_result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void Unload()
|
||||||
|
{
|
||||||
|
foreach(var l_pair in ms_loadedAssets)
|
||||||
|
Object.Destroy(l_pair.Value);
|
||||||
|
ms_loadedAssets.Clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
199
ml_bft/FingerSystem.cs
Normal file
199
ml_bft/FingerSystem.cs
Normal file
|
@ -0,0 +1,199 @@
|
||||||
|
using ABI_RC.Core.Player;
|
||||||
|
using ABI_RC.Core.Savior;
|
||||||
|
using ABI_RC.Systems.IK;
|
||||||
|
using ABI_RC.Systems.InputManagement;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using UnityEngine;
|
||||||
|
|
||||||
|
namespace ml_bft
|
||||||
|
{
|
||||||
|
class FingerSystem
|
||||||
|
{
|
||||||
|
struct RotationOffset
|
||||||
|
{
|
||||||
|
public Transform m_target;
|
||||||
|
public Transform m_source;
|
||||||
|
public Quaternion m_offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
static readonly List<HumanBodyBones> ms_leftFingerBones = new List<HumanBodyBones>()
|
||||||
|
{
|
||||||
|
HumanBodyBones.LeftThumbProximal, HumanBodyBones.LeftThumbIntermediate, HumanBodyBones.LeftThumbDistal,
|
||||||
|
HumanBodyBones.LeftIndexProximal, HumanBodyBones.LeftIndexIntermediate, HumanBodyBones.LeftIndexDistal,
|
||||||
|
HumanBodyBones.LeftMiddleProximal, HumanBodyBones.LeftMiddleIntermediate, HumanBodyBones.LeftMiddleDistal,
|
||||||
|
HumanBodyBones.LeftRingProximal, HumanBodyBones.LeftRingIntermediate, HumanBodyBones.LeftRingDistal,
|
||||||
|
HumanBodyBones.LeftLittleProximal, HumanBodyBones.LeftLittleIntermediate, HumanBodyBones.LeftLittleDistal
|
||||||
|
};
|
||||||
|
static readonly List<HumanBodyBones> ms_rightFingerBones = new List<HumanBodyBones>()
|
||||||
|
{
|
||||||
|
HumanBodyBones.RightThumbProximal, HumanBodyBones.RightThumbIntermediate, HumanBodyBones.RightThumbDistal,
|
||||||
|
HumanBodyBones.RightIndexProximal, HumanBodyBones.RightIndexIntermediate, HumanBodyBones.RightIndexDistal,
|
||||||
|
HumanBodyBones.RightMiddleProximal, HumanBodyBones.RightMiddleIntermediate, HumanBodyBones.RightMiddleDistal,
|
||||||
|
HumanBodyBones.RightRingProximal, HumanBodyBones.RightRingIntermediate, HumanBodyBones.RightRingDistal,
|
||||||
|
HumanBodyBones.RightLittleProximal, HumanBodyBones.RightLittleIntermediate, HumanBodyBones.RightLittleDistal
|
||||||
|
};
|
||||||
|
|
||||||
|
public static FingerSystem Instance { get; private set; } = null;
|
||||||
|
|
||||||
|
RotationOffset m_leftHandOffset; // From avatar hand to controller wrist
|
||||||
|
RotationOffset m_rightHandOffset;
|
||||||
|
readonly List<RotationOffset> m_leftFingerOffsets = null; // From controller finger bone to avatar finger bone
|
||||||
|
readonly List<RotationOffset> m_rightFingerOffsets = null;
|
||||||
|
|
||||||
|
public readonly float[] m_lastValues;
|
||||||
|
|
||||||
|
bool m_ready = false;
|
||||||
|
HumanPose m_pose;
|
||||||
|
|
||||||
|
internal FingerSystem()
|
||||||
|
{
|
||||||
|
if(Instance == null)
|
||||||
|
Instance = this;
|
||||||
|
|
||||||
|
m_leftFingerOffsets = new List<RotationOffset>();
|
||||||
|
m_rightFingerOffsets = new List<RotationOffset>();
|
||||||
|
|
||||||
|
m_pose = new HumanPose();
|
||||||
|
m_lastValues = new float[40];
|
||||||
|
}
|
||||||
|
internal void Cleanup()
|
||||||
|
{
|
||||||
|
if(Instance == this)
|
||||||
|
Instance = null;
|
||||||
|
|
||||||
|
m_leftFingerOffsets.Clear();
|
||||||
|
m_rightFingerOffsets.Clear();
|
||||||
|
m_ready = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal void OnAvatarSetup()
|
||||||
|
{
|
||||||
|
if(PlayerSetup.Instance._animator.isHuman)
|
||||||
|
{
|
||||||
|
IKSystem.Instance.SetAvatarPose(IKSystem.AvatarPose.TPose);
|
||||||
|
PlayerSetup.Instance._avatar.transform.localPosition = Vector3.zero;
|
||||||
|
PlayerSetup.Instance._avatar.transform.localRotation = Quaternion.identity;
|
||||||
|
InputHandler.Instance?.Rebind(PlayerSetup.Instance.transform.rotation);
|
||||||
|
|
||||||
|
m_leftHandOffset.m_source = PlayerSetup.Instance._animator.GetBoneTransform(HumanBodyBones.LeftHand);
|
||||||
|
m_leftHandOffset.m_target = InputHandler.Instance?.GetSourceForBone(HumanBodyBones.LeftHand, true);
|
||||||
|
if((m_leftHandOffset.m_source != null) && (m_leftHandOffset.m_target != null))
|
||||||
|
m_leftHandOffset.m_offset = Quaternion.Inverse(m_leftHandOffset.m_source.rotation) * m_leftHandOffset.m_target.rotation;
|
||||||
|
|
||||||
|
m_rightHandOffset.m_source = PlayerSetup.Instance._animator.GetBoneTransform(HumanBodyBones.RightHand);
|
||||||
|
m_rightHandOffset.m_target = InputHandler.Instance?.GetSourceForBone(HumanBodyBones.RightHand, false);
|
||||||
|
if((m_rightHandOffset.m_source != null) && (m_rightHandOffset.m_target != null))
|
||||||
|
m_rightHandOffset.m_offset = Quaternion.Inverse(m_rightHandOffset.m_source.rotation) * m_rightHandOffset.m_target.rotation;
|
||||||
|
|
||||||
|
foreach(HumanBodyBones p_bone in ms_leftFingerBones)
|
||||||
|
{
|
||||||
|
Transform l_avatarBone = PlayerSetup.Instance._animator.GetBoneTransform(p_bone);
|
||||||
|
Transform l_controllerBone = InputHandler.Instance?.GetSourceForBone(p_bone, true);
|
||||||
|
if((l_avatarBone != null) && (l_controllerBone != null))
|
||||||
|
{
|
||||||
|
RotationOffset l_offset = new RotationOffset();
|
||||||
|
l_offset.m_source = l_controllerBone;
|
||||||
|
l_offset.m_target = l_avatarBone;
|
||||||
|
l_offset.m_offset = Quaternion.Inverse(l_controllerBone.rotation) * l_avatarBone.rotation;
|
||||||
|
m_leftFingerOffsets.Add(l_offset);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach(HumanBodyBones p_bone in ms_rightFingerBones)
|
||||||
|
{
|
||||||
|
Transform l_avatarBone = PlayerSetup.Instance._animator.GetBoneTransform(p_bone);
|
||||||
|
Transform l_controllerBone = InputHandler.Instance?.GetSourceForBone(p_bone, false);
|
||||||
|
if((l_avatarBone != null) && (l_controllerBone != null))
|
||||||
|
{
|
||||||
|
RotationOffset l_offset = new RotationOffset();
|
||||||
|
l_offset.m_source = l_controllerBone;
|
||||||
|
l_offset.m_target = l_avatarBone;
|
||||||
|
l_offset.m_offset = Quaternion.Inverse(l_controllerBone.rotation) * l_avatarBone.rotation;
|
||||||
|
m_rightFingerOffsets.Add(l_offset);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
m_ready = ((m_leftFingerOffsets.Count > 0) || (m_rightFingerOffsets.Count > 0));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal void OnAvatarClear()
|
||||||
|
{
|
||||||
|
m_ready = false;
|
||||||
|
m_pose = new HumanPose();
|
||||||
|
m_leftFingerOffsets.Clear();
|
||||||
|
m_rightFingerOffsets.Clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
internal void OnReinitializeAvatar()
|
||||||
|
{
|
||||||
|
OnAvatarClear();
|
||||||
|
OnAvatarSetup();
|
||||||
|
}
|
||||||
|
|
||||||
|
internal void OnIKSystemLateUpdate(HumanPoseHandler p_handler)
|
||||||
|
{
|
||||||
|
if(m_ready && MetaPort.Instance.isUsingVr && (p_handler != null) && Settings.SkeletalInput)
|
||||||
|
{
|
||||||
|
// Virtually allign controllers wrist bone to avatar hands with offset and apply global rotation to avatar finger bones with individial offset
|
||||||
|
// This is done to apply rotation changes from controller bones to avatar finger bones as in local space
|
||||||
|
if(CVRInputManager.Instance._leftController != ABI_RC.Systems.InputManagement.XR.eXRControllerType.None)
|
||||||
|
{
|
||||||
|
Quaternion l_turnBack = (m_leftHandOffset.m_source.rotation * m_leftHandOffset.m_offset) * Quaternion.Inverse(m_leftHandOffset.m_target.rotation);
|
||||||
|
foreach(var l_offset in m_leftFingerOffsets)
|
||||||
|
l_offset.m_target.rotation = l_turnBack * (l_offset.m_source.rotation * l_offset.m_offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(CVRInputManager.Instance._rightController != ABI_RC.Systems.InputManagement.XR.eXRControllerType.None)
|
||||||
|
{
|
||||||
|
Quaternion l_turnBack = (m_rightHandOffset.m_source.rotation * m_rightHandOffset.m_offset) * Quaternion.Inverse(m_rightHandOffset.m_target.rotation);
|
||||||
|
foreach(var l_offset in m_rightFingerOffsets)
|
||||||
|
l_offset.m_target.rotation = l_turnBack * (l_offset.m_source.rotation * l_offset.m_offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
// No matter if hands are tracked, fill muscles values
|
||||||
|
p_handler.GetHumanPose(ref m_pose);
|
||||||
|
m_lastValues[0] = m_pose.muscles[(int)MuscleIndex.LeftThumb1Stretched];
|
||||||
|
m_lastValues[1] = m_pose.muscles[(int)MuscleIndex.LeftThumb2Stretched];
|
||||||
|
m_lastValues[2] = m_pose.muscles[(int)MuscleIndex.LeftThumb3Stretched];
|
||||||
|
m_lastValues[3] = m_pose.muscles[(int)MuscleIndex.LeftThumbSpread];
|
||||||
|
m_lastValues[4] = m_pose.muscles[(int)MuscleIndex.LeftIndex1Stretched];
|
||||||
|
m_lastValues[5] = m_pose.muscles[(int)MuscleIndex.LeftIndex2Stretched];
|
||||||
|
m_lastValues[6] = m_pose.muscles[(int)MuscleIndex.LeftIndex3Stretched];
|
||||||
|
m_lastValues[7] = m_pose.muscles[(int)MuscleIndex.LeftIndexSpread];
|
||||||
|
m_lastValues[8] = m_pose.muscles[(int)MuscleIndex.LeftMiddle1Stretched];
|
||||||
|
m_lastValues[9] = m_pose.muscles[(int)MuscleIndex.LeftMiddle2Stretched];
|
||||||
|
m_lastValues[10] = m_pose.muscles[(int)MuscleIndex.LeftMiddle3Stretched];
|
||||||
|
m_lastValues[11] = m_pose.muscles[(int)MuscleIndex.LeftMiddleSpread];
|
||||||
|
m_lastValues[12] = m_pose.muscles[(int)MuscleIndex.LeftRing1Stretched];
|
||||||
|
m_lastValues[13] = m_pose.muscles[(int)MuscleIndex.LeftRing2Stretched];
|
||||||
|
m_lastValues[14] = m_pose.muscles[(int)MuscleIndex.LeftRing3Stretched];
|
||||||
|
m_lastValues[15] = m_pose.muscles[(int)MuscleIndex.LeftRingSpread];
|
||||||
|
m_lastValues[16] = m_pose.muscles[(int)MuscleIndex.LeftLittle1Stretched];
|
||||||
|
m_lastValues[17] = m_pose.muscles[(int)MuscleIndex.LeftLittle2Stretched];
|
||||||
|
m_lastValues[18] = m_pose.muscles[(int)MuscleIndex.LeftLittle3Stretched];
|
||||||
|
m_lastValues[19] = m_pose.muscles[(int)MuscleIndex.LeftLittleSpread];
|
||||||
|
m_lastValues[20] = m_pose.muscles[(int)MuscleIndex.RightThumb1Stretched];
|
||||||
|
m_lastValues[21] = m_pose.muscles[(int)MuscleIndex.RightThumb2Stretched];
|
||||||
|
m_lastValues[22] = m_pose.muscles[(int)MuscleIndex.RightThumb3Stretched];
|
||||||
|
m_lastValues[23] = m_pose.muscles[(int)MuscleIndex.RightThumbSpread];
|
||||||
|
m_lastValues[24] = m_pose.muscles[(int)MuscleIndex.RightIndex1Stretched];
|
||||||
|
m_lastValues[25] = m_pose.muscles[(int)MuscleIndex.RightIndex2Stretched];
|
||||||
|
m_lastValues[26] = m_pose.muscles[(int)MuscleIndex.RightIndex3Stretched];
|
||||||
|
m_lastValues[27] = m_pose.muscles[(int)MuscleIndex.RightIndexSpread];
|
||||||
|
m_lastValues[28] = m_pose.muscles[(int)MuscleIndex.RightMiddle1Stretched];
|
||||||
|
m_lastValues[29] = m_pose.muscles[(int)MuscleIndex.RightMiddle2Stretched];
|
||||||
|
m_lastValues[30] = m_pose.muscles[(int)MuscleIndex.RightMiddle3Stretched];
|
||||||
|
m_lastValues[31] = m_pose.muscles[(int)MuscleIndex.RightMiddleSpread];
|
||||||
|
m_lastValues[32] = m_pose.muscles[(int)MuscleIndex.RightRing1Stretched];
|
||||||
|
m_lastValues[33] = m_pose.muscles[(int)MuscleIndex.RightRing2Stretched];
|
||||||
|
m_lastValues[34] = m_pose.muscles[(int)MuscleIndex.RightRing3Stretched];
|
||||||
|
m_lastValues[35] = m_pose.muscles[(int)MuscleIndex.RightRingSpread];
|
||||||
|
m_lastValues[36] = m_pose.muscles[(int)MuscleIndex.RightLittle1Stretched];
|
||||||
|
m_lastValues[37] = m_pose.muscles[(int)MuscleIndex.RightLittle2Stretched];
|
||||||
|
m_lastValues[38] = m_pose.muscles[(int)MuscleIndex.RightLittle3Stretched];
|
||||||
|
m_lastValues[39] = m_pose.muscles[(int)MuscleIndex.RightLittleSpread];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
59
ml_bft/HandHandler.cs
Normal file
59
ml_bft/HandHandler.cs
Normal file
|
@ -0,0 +1,59 @@
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using UnityEngine;
|
||||||
|
|
||||||
|
namespace ml_bft
|
||||||
|
{
|
||||||
|
class HandHandler
|
||||||
|
{
|
||||||
|
protected bool m_left = false;
|
||||||
|
protected List<Transform> m_bones = null;
|
||||||
|
protected List<Quaternion> m_localRotations = null;
|
||||||
|
protected Transform m_prefabRoot = null;
|
||||||
|
protected List<Renderer> m_renderers = null;
|
||||||
|
|
||||||
|
protected HandHandler(bool p_left)
|
||||||
|
{
|
||||||
|
m_left = p_left;
|
||||||
|
m_bones = new List<Transform>();
|
||||||
|
m_localRotations = new List<Quaternion>();
|
||||||
|
m_renderers = new List<Renderer>();
|
||||||
|
|
||||||
|
Settings.ShowHandsChange += this.OnShowHandsChange;
|
||||||
|
}
|
||||||
|
|
||||||
|
public virtual void Cleanup()
|
||||||
|
{
|
||||||
|
if(m_prefabRoot != null)
|
||||||
|
Object.Destroy(m_prefabRoot.gameObject);
|
||||||
|
m_prefabRoot = null;
|
||||||
|
|
||||||
|
m_bones.Clear();
|
||||||
|
m_localRotations.Clear();
|
||||||
|
m_renderers.Clear();
|
||||||
|
|
||||||
|
Settings.ShowHandsChange -= this.OnShowHandsChange;
|
||||||
|
}
|
||||||
|
|
||||||
|
public virtual void Update()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public virtual Transform GetSourceForBone(HumanBodyBones p_bone)
|
||||||
|
{
|
||||||
|
return default;
|
||||||
|
}
|
||||||
|
|
||||||
|
public virtual void Rebind(Quaternion p_base)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void OnShowHandsChange(bool p_state)
|
||||||
|
{
|
||||||
|
foreach(var l_render in m_renderers)
|
||||||
|
{
|
||||||
|
if(l_render != null)
|
||||||
|
l_render.enabled = p_state;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
238
ml_bft/HandHandlerOVR.cs
Normal file
238
ml_bft/HandHandlerOVR.cs
Normal file
|
@ -0,0 +1,238 @@
|
||||||
|
using UnityEngine;
|
||||||
|
using Valve.VR;
|
||||||
|
|
||||||
|
namespace ml_bft
|
||||||
|
{
|
||||||
|
class HandHandlerOVR : HandHandler
|
||||||
|
{
|
||||||
|
// 31 bones in each hand, get index at Valve.VR.SteamVR_Skeleton_JointIndexes or SteamVR_Skeleton_JointIndexEnum
|
||||||
|
const int c_fingerBonesCount = (int)SteamVR_Skeleton_JointIndexEnum.pinkyAux + 1;
|
||||||
|
|
||||||
|
SteamVR_Action_Skeleton m_skeletonAction;
|
||||||
|
|
||||||
|
public HandHandlerOVR(Transform p_root, bool p_left) : base(p_left)
|
||||||
|
{
|
||||||
|
for(int i = 0; i < c_fingerBonesCount; i++)
|
||||||
|
{
|
||||||
|
m_bones.Add(null);
|
||||||
|
m_localRotations.Add(Quaternion.identity);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fill finger transforms
|
||||||
|
m_prefabRoot = AssetsHandler.GetAsset(string.Format("assets/steamvr/models/[openvr] {0}.prefab", m_left ? "left" : "right")).transform;
|
||||||
|
m_prefabRoot.name = "[FingersTracking_OVR]";
|
||||||
|
m_prefabRoot.parent = p_root;
|
||||||
|
m_prefabRoot.localPosition = Vector3.zero;
|
||||||
|
m_prefabRoot.localRotation = Quaternion.identity;
|
||||||
|
|
||||||
|
m_prefabRoot.GetComponentsInChildren(true, m_renderers);
|
||||||
|
|
||||||
|
// Ah yes, the stupid code
|
||||||
|
m_bones[(int)SteamVR_Skeleton_JointIndexEnum.root] = m_prefabRoot.Find("Root");
|
||||||
|
m_bones[(int)SteamVR_Skeleton_JointIndexEnum.wrist] = m_prefabRoot.Find(string.Format("Root/wrist_{0}", m_left ? 'l' : 'r'));
|
||||||
|
m_bones[(int)SteamVR_Skeleton_JointIndexEnum.thumbProximal] = m_prefabRoot.Find(string.Format("Root/wrist_{0}/finger_thumb_0_{0}", m_left ? 'l' : 'r'));
|
||||||
|
m_bones[(int)SteamVR_Skeleton_JointIndexEnum.thumbMiddle] = m_prefabRoot.Find(string.Format("Root/wrist_{0}/finger_thumb_0_{0}/finger_thumb_1_{0}", m_left ? 'l' : 'r'));
|
||||||
|
m_bones[(int)SteamVR_Skeleton_JointIndexEnum.thumbDistal] = m_prefabRoot.Find(string.Format("Root/wrist_{0}/finger_thumb_0_{0}/finger_thumb_1_{0}/finger_thumb_2_{0}", m_left ? 'l' : 'r'));
|
||||||
|
m_bones[(int)SteamVR_Skeleton_JointIndexEnum.thumbTip] = m_prefabRoot.Find(string.Format("Root/wrist_{0}/finger_thumb_0_{0}/finger_thumb_1_{0}/finger_thumb_2_{0}/finger_thumb_{0}_end", m_left ? 'l' : 'r'));
|
||||||
|
|
||||||
|
m_bones[(int)SteamVR_Skeleton_JointIndexEnum.indexMetacarpal] = m_prefabRoot.Find(string.Format("Root/wrist_{0}/finger_index_meta_{0}", m_left ? 'l' : 'r'));
|
||||||
|
m_bones[(int)SteamVR_Skeleton_JointIndexEnum.indexProximal] = m_prefabRoot.Find(string.Format("Root/wrist_{0}/finger_index_meta_{0}/finger_index_0_{0}", m_left ? 'l' : 'r'));
|
||||||
|
m_bones[(int)SteamVR_Skeleton_JointIndexEnum.indexMiddle] = m_prefabRoot.Find(string.Format("Root/wrist_{0}/finger_index_meta_{0}/finger_index_0_{0}/finger_index_1_{0}", m_left ? 'l' : 'r'));
|
||||||
|
m_bones[(int)SteamVR_Skeleton_JointIndexEnum.indexDistal] = m_prefabRoot.Find(string.Format("Root/wrist_{0}/finger_index_meta_{0}/finger_index_0_{0}/finger_index_1_{0}/finger_index_2_{0}", m_left ? 'l' : 'r'));
|
||||||
|
m_bones[(int)SteamVR_Skeleton_JointIndexEnum.indexTip] = m_prefabRoot.Find(string.Format("Root/wrist_{0}/finger_index_meta_{0}/finger_index_0_{0}/finger_index_1_{0}/finger_index_2_{0}/finger_index_{0}_end", m_left ? 'l' : 'r'));
|
||||||
|
|
||||||
|
m_bones[(int)SteamVR_Skeleton_JointIndexEnum.middleMetacarpal] = m_prefabRoot.Find(string.Format("Root/wrist_{0}/finger_middle_meta_{0}", m_left ? 'l' : 'r'));
|
||||||
|
m_bones[(int)SteamVR_Skeleton_JointIndexEnum.middleProximal] = m_prefabRoot.Find(string.Format("Root/wrist_{0}/finger_middle_meta_{0}/finger_middle_0_{0}", m_left ? 'l' : 'r'));
|
||||||
|
m_bones[(int)SteamVR_Skeleton_JointIndexEnum.middleMiddle] = m_prefabRoot.Find(string.Format("Root/wrist_{0}/finger_middle_meta_{0}/finger_middle_0_{0}/finger_middle_1_{0}", m_left ? 'l' : 'r'));
|
||||||
|
m_bones[(int)SteamVR_Skeleton_JointIndexEnum.middleDistal] = m_prefabRoot.Find(string.Format("Root/wrist_{0}/finger_middle_meta_{0}/finger_middle_0_{0}/finger_middle_1_{0}/finger_middle_2_{0}", m_left ? 'l' : 'r'));
|
||||||
|
m_bones[(int)SteamVR_Skeleton_JointIndexEnum.middleTip] = m_prefabRoot.Find(string.Format("Root/wrist_{0}/finger_middle_meta_{0}/finger_middle_0_{0}/finger_middle_1_{0}/finger_middle_2_{0}/finger_middle_{0}_end", m_left ? 'l' : 'r'));
|
||||||
|
|
||||||
|
m_bones[(int)SteamVR_Skeleton_JointIndexEnum.ringMetacarpal] = m_prefabRoot.Find(string.Format("Root/wrist_{0}/finger_ring_meta_{0}", m_left ? 'l' : 'r'));
|
||||||
|
m_bones[(int)SteamVR_Skeleton_JointIndexEnum.ringProximal] = m_prefabRoot.Find(string.Format("Root/wrist_{0}/finger_ring_meta_{0}/finger_ring_0_{0}", m_left ? 'l' : 'r'));
|
||||||
|
m_bones[(int)SteamVR_Skeleton_JointIndexEnum.ringMiddle] = m_prefabRoot.Find(string.Format("Root/wrist_{0}/finger_ring_meta_{0}/finger_ring_0_{0}/finger_ring_1_{0}", m_left ? 'l' : 'r'));
|
||||||
|
m_bones[(int)SteamVR_Skeleton_JointIndexEnum.ringDistal] = m_prefabRoot.Find(string.Format("Root/wrist_{0}/finger_ring_meta_{0}/finger_ring_0_{0}/finger_ring_1_{0}/finger_ring_2_{0}", m_left ? 'l' : 'r'));
|
||||||
|
m_bones[(int)SteamVR_Skeleton_JointIndexEnum.ringTip] = m_prefabRoot.Find(string.Format("Root/wrist_{0}/finger_ring_meta_{0}/finger_ring_0_{0}/finger_ring_1_{0}/finger_ring_2_{0}/finger_ring_{0}_end", m_left ? 'l' : 'r'));
|
||||||
|
|
||||||
|
m_bones[(int)SteamVR_Skeleton_JointIndexEnum.pinkyMetacarpal] = m_prefabRoot.Find(string.Format("Root/wrist_{0}/finger_pinky_meta_{0}", m_left ? 'l' : 'r'));
|
||||||
|
m_bones[(int)SteamVR_Skeleton_JointIndexEnum.pinkyProximal] = m_prefabRoot.Find(string.Format("Root/wrist_{0}/finger_pinky_meta_{0}/finger_pinky_0_{0}", m_left ? 'l' : 'r'));
|
||||||
|
m_bones[(int)SteamVR_Skeleton_JointIndexEnum.pinkyMiddle] = m_prefabRoot.Find(string.Format("Root/wrist_{0}/finger_pinky_meta_{0}/finger_pinky_0_{0}/finger_pinky_1_{0}", m_left ? 'l' : 'r'));
|
||||||
|
m_bones[(int)SteamVR_Skeleton_JointIndexEnum.pinkyDistal] = m_prefabRoot.Find(string.Format("Root/wrist_{0}/finger_pinky_meta_{0}/finger_pinky_0_{0}/finger_pinky_1_{0}/finger_pinky_2_{0}", m_left ? 'l' : 'r'));
|
||||||
|
m_bones[(int)SteamVR_Skeleton_JointIndexEnum.pinkyTip] = m_prefabRoot.Find(string.Format("Root/wrist_{0}/finger_pinky_meta_{0}/finger_pinky_0_{0}/finger_pinky_1_{0}/finger_pinky_2_{0}/finger_pinky_{0}_end", m_left ? 'l' : 'r'));
|
||||||
|
|
||||||
|
m_bones[(int)SteamVR_Skeleton_JointIndexEnum.thumbAux] = m_prefabRoot.Find(string.Format("Root/finger_thumb_{0}_aux", m_left ? 'l' : 'r'));
|
||||||
|
m_bones[(int)SteamVR_Skeleton_JointIndexEnum.indexAux] = m_prefabRoot.Find(string.Format("Root/finger_index_{0}_aux", m_left ? 'l' : 'r'));
|
||||||
|
m_bones[(int)SteamVR_Skeleton_JointIndexEnum.middleAux] = m_prefabRoot.Find(string.Format("Root/finger_middle_{0}_aux", m_left ? 'l' : 'r'));
|
||||||
|
m_bones[(int)SteamVR_Skeleton_JointIndexEnum.ringAux] = m_prefabRoot.Find(string.Format("Root/finger_ring_{0}_aux", m_left ? 'l' : 'r'));
|
||||||
|
m_bones[(int)SteamVR_Skeleton_JointIndexEnum.pinkyAux] = m_prefabRoot.Find(string.Format("Root/finger_pinky_{0}_aux", m_left ? 'l' : 'r'));
|
||||||
|
|
||||||
|
// Remember local rotations
|
||||||
|
for(int i = 0; i < c_fingerBonesCount; i++)
|
||||||
|
{
|
||||||
|
if(m_bones[i] != null)
|
||||||
|
m_localRotations[i] = m_bones[i].localRotation;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_skeletonAction = SteamVR_Input.GetAction<SteamVR_Action_Skeleton>(p_left ? "SkeletonLeftHand" : "SkeletonRightHand");
|
||||||
|
|
||||||
|
base.OnShowHandsChange(Settings.ShowHands);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Cleanup()
|
||||||
|
{
|
||||||
|
base.Cleanup();
|
||||||
|
|
||||||
|
m_skeletonAction = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Update()
|
||||||
|
{
|
||||||
|
if(m_skeletonAction != null)
|
||||||
|
{
|
||||||
|
var l_rotations = m_skeletonAction.GetBoneRotations();
|
||||||
|
var l_positions = m_skeletonAction.GetBonePositions();
|
||||||
|
for(int i = 0; i < c_fingerBonesCount; i++)
|
||||||
|
{
|
||||||
|
if(m_bones[i] != null)
|
||||||
|
{
|
||||||
|
m_bones[i].localRotation = l_rotations[i];
|
||||||
|
m_bones[i].localPosition = l_positions[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override Transform GetSourceForBone(HumanBodyBones p_bone)
|
||||||
|
{
|
||||||
|
Transform l_result = null;
|
||||||
|
if(m_left)
|
||||||
|
{
|
||||||
|
switch(p_bone)
|
||||||
|
{
|
||||||
|
case HumanBodyBones.LeftHand:
|
||||||
|
l_result = m_bones[(int)SteamVR_Skeleton_JointIndexEnum.wrist];
|
||||||
|
break;
|
||||||
|
case HumanBodyBones.LeftThumbProximal:
|
||||||
|
l_result = m_bones[(int)SteamVR_Skeleton_JointIndexEnum.thumbProximal];
|
||||||
|
break;
|
||||||
|
case HumanBodyBones.LeftThumbIntermediate:
|
||||||
|
l_result = m_bones[(int)SteamVR_Skeleton_JointIndexEnum.thumbMiddle];
|
||||||
|
break;
|
||||||
|
case HumanBodyBones.LeftThumbDistal:
|
||||||
|
l_result = m_bones[(int)SteamVR_Skeleton_JointIndexEnum.thumbDistal];
|
||||||
|
break;
|
||||||
|
|
||||||
|
case HumanBodyBones.LeftIndexProximal:
|
||||||
|
l_result = m_bones[(int)SteamVR_Skeleton_JointIndexEnum.indexProximal];
|
||||||
|
break;
|
||||||
|
case HumanBodyBones.LeftIndexIntermediate:
|
||||||
|
l_result = m_bones[(int)SteamVR_Skeleton_JointIndexEnum.indexMiddle];
|
||||||
|
break;
|
||||||
|
case HumanBodyBones.LeftIndexDistal:
|
||||||
|
l_result = m_bones[(int)SteamVR_Skeleton_JointIndexEnum.indexDistal];
|
||||||
|
break;
|
||||||
|
|
||||||
|
case HumanBodyBones.LeftMiddleProximal:
|
||||||
|
l_result = m_bones[(int)SteamVR_Skeleton_JointIndexEnum.middleProximal];
|
||||||
|
break;
|
||||||
|
case HumanBodyBones.LeftMiddleIntermediate:
|
||||||
|
l_result = m_bones[(int)SteamVR_Skeleton_JointIndexEnum.middleMiddle];
|
||||||
|
break;
|
||||||
|
case HumanBodyBones.LeftMiddleDistal:
|
||||||
|
l_result = m_bones[(int)SteamVR_Skeleton_JointIndexEnum.middleDistal];
|
||||||
|
break;
|
||||||
|
|
||||||
|
case HumanBodyBones.LeftRingProximal:
|
||||||
|
l_result = m_bones[(int)SteamVR_Skeleton_JointIndexEnum.ringProximal];
|
||||||
|
break;
|
||||||
|
case HumanBodyBones.LeftRingIntermediate:
|
||||||
|
l_result = m_bones[(int)SteamVR_Skeleton_JointIndexEnum.ringMiddle];
|
||||||
|
break;
|
||||||
|
case HumanBodyBones.LeftRingDistal:
|
||||||
|
l_result = m_bones[(int)SteamVR_Skeleton_JointIndexEnum.ringDistal];
|
||||||
|
break;
|
||||||
|
|
||||||
|
case HumanBodyBones.LeftLittleProximal:
|
||||||
|
l_result = m_bones[(int)SteamVR_Skeleton_JointIndexEnum.pinkyProximal];
|
||||||
|
break;
|
||||||
|
case HumanBodyBones.LeftLittleIntermediate:
|
||||||
|
l_result = m_bones[(int)SteamVR_Skeleton_JointIndexEnum.pinkyMiddle];
|
||||||
|
break;
|
||||||
|
case HumanBodyBones.LeftLittleDistal:
|
||||||
|
l_result = m_bones[(int)SteamVR_Skeleton_JointIndexEnum.pinkyDistal];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
switch(p_bone)
|
||||||
|
{
|
||||||
|
case HumanBodyBones.RightHand:
|
||||||
|
l_result = m_bones[(int)SteamVR_Skeleton_JointIndexEnum.wrist];
|
||||||
|
break;
|
||||||
|
case HumanBodyBones.RightThumbProximal:
|
||||||
|
l_result = m_bones[(int)SteamVR_Skeleton_JointIndexEnum.thumbProximal];
|
||||||
|
break;
|
||||||
|
case HumanBodyBones.RightThumbIntermediate:
|
||||||
|
l_result = m_bones[(int)SteamVR_Skeleton_JointIndexEnum.thumbMiddle];
|
||||||
|
break;
|
||||||
|
case HumanBodyBones.RightThumbDistal:
|
||||||
|
l_result = m_bones[(int)SteamVR_Skeleton_JointIndexEnum.thumbDistal];
|
||||||
|
break;
|
||||||
|
|
||||||
|
case HumanBodyBones.RightIndexProximal:
|
||||||
|
l_result = m_bones[(int)SteamVR_Skeleton_JointIndexEnum.indexProximal];
|
||||||
|
break;
|
||||||
|
case HumanBodyBones.RightIndexIntermediate:
|
||||||
|
l_result = m_bones[(int)SteamVR_Skeleton_JointIndexEnum.indexMiddle];
|
||||||
|
break;
|
||||||
|
case HumanBodyBones.RightIndexDistal:
|
||||||
|
l_result = m_bones[(int)SteamVR_Skeleton_JointIndexEnum.indexDistal];
|
||||||
|
break;
|
||||||
|
|
||||||
|
case HumanBodyBones.RightMiddleProximal:
|
||||||
|
l_result = m_bones[(int)SteamVR_Skeleton_JointIndexEnum.middleProximal];
|
||||||
|
break;
|
||||||
|
case HumanBodyBones.RightMiddleIntermediate:
|
||||||
|
l_result = m_bones[(int)SteamVR_Skeleton_JointIndexEnum.middleMiddle];
|
||||||
|
break;
|
||||||
|
case HumanBodyBones.RightMiddleDistal:
|
||||||
|
l_result = m_bones[(int)SteamVR_Skeleton_JointIndexEnum.middleDistal];
|
||||||
|
break;
|
||||||
|
|
||||||
|
case HumanBodyBones.RightRingProximal:
|
||||||
|
l_result = m_bones[(int)SteamVR_Skeleton_JointIndexEnum.ringProximal];
|
||||||
|
break;
|
||||||
|
case HumanBodyBones.RightRingIntermediate:
|
||||||
|
l_result = m_bones[(int)SteamVR_Skeleton_JointIndexEnum.ringMiddle];
|
||||||
|
break;
|
||||||
|
case HumanBodyBones.RightRingDistal:
|
||||||
|
l_result = m_bones[(int)SteamVR_Skeleton_JointIndexEnum.ringDistal];
|
||||||
|
break;
|
||||||
|
|
||||||
|
case HumanBodyBones.RightLittleProximal:
|
||||||
|
l_result = m_bones[(int)SteamVR_Skeleton_JointIndexEnum.pinkyProximal];
|
||||||
|
break;
|
||||||
|
case HumanBodyBones.RightLittleIntermediate:
|
||||||
|
l_result = m_bones[(int)SteamVR_Skeleton_JointIndexEnum.pinkyMiddle];
|
||||||
|
break;
|
||||||
|
case HumanBodyBones.RightLittleDistal:
|
||||||
|
l_result = m_bones[(int)SteamVR_Skeleton_JointIndexEnum.pinkyDistal];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return l_result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Rebind(Quaternion p_base)
|
||||||
|
{
|
||||||
|
for(int i = 0; i < c_fingerBonesCount; i++)
|
||||||
|
{
|
||||||
|
if(m_bones[i] != null)
|
||||||
|
m_bones[i].localRotation = m_localRotations[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
if(m_bones[(int)SteamVR_Skeleton_JointIndexEnum.root] != null)
|
||||||
|
m_bones[(int)SteamVR_Skeleton_JointIndexEnum.root].rotation = p_base * (m_left ? Quaternion.Euler(0f, -90f, 0f) : Quaternion.Euler(0f, 90f, 0f));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
225
ml_bft/HandHandlerXR.cs
Normal file
225
ml_bft/HandHandlerXR.cs
Normal file
|
@ -0,0 +1,225 @@
|
||||||
|
using UnityEngine;
|
||||||
|
using UnityEngine.XR.OpenXR;
|
||||||
|
using UnityEngine.XR.Hands;
|
||||||
|
|
||||||
|
namespace ml_bft
|
||||||
|
{
|
||||||
|
class HandHandlerXR : HandHandler
|
||||||
|
{
|
||||||
|
// 26 bones, get in XRHandJointID enum
|
||||||
|
const int c_fingerBonesCount = (int)XRHandJointID.EndMarker - 1;
|
||||||
|
|
||||||
|
public HandHandlerXR(Transform p_root, bool p_left) : base(p_left)
|
||||||
|
{
|
||||||
|
for(int i = 0; i < c_fingerBonesCount; i++)
|
||||||
|
{
|
||||||
|
m_bones.Add(null);
|
||||||
|
m_localRotations.Add(Quaternion.identity);
|
||||||
|
}
|
||||||
|
|
||||||
|
m_prefabRoot = AssetsHandler.GetAsset(string.Format("Assets/OpenXR/Models/{0}Hand_IK.prefab", m_left ? "Left" : "Right")).transform;
|
||||||
|
m_prefabRoot.name = "[FingersTracking_XR]";
|
||||||
|
m_prefabRoot.parent = p_root;
|
||||||
|
m_prefabRoot.localPosition = Vector3.zero;
|
||||||
|
m_prefabRoot.localRotation = Quaternion.identity;
|
||||||
|
|
||||||
|
m_prefabRoot.GetComponentsInChildren(true, m_renderers);
|
||||||
|
|
||||||
|
// Ah yes, the stupid code
|
||||||
|
m_bones[(int)XRHandJointID.Wrist - 1] = m_prefabRoot.Find(string.Format("{0}_Wrist", m_left ? 'L' : 'R'));
|
||||||
|
m_bones[(int)XRHandJointID.Palm - 1] = m_prefabRoot.Find(string.Format("{0}_Wrist/{0}_Palm", m_left ? 'L' : 'R'));
|
||||||
|
|
||||||
|
m_bones[(int)XRHandJointID.ThumbMetacarpal - 1] = m_prefabRoot.Find(string.Format("{0}_Wrist/{0}_ThumbMetacarpal", m_left ? 'L' : 'R'));
|
||||||
|
m_bones[(int)XRHandJointID.ThumbProximal - 1] = m_prefabRoot.Find(string.Format("{0}_Wrist/{0}_ThumbMetacarpal/{0}_Wrist/{0}_ThumbProximal", m_left ? 'L' : 'R'));
|
||||||
|
m_bones[(int)XRHandJointID.ThumbDistal - 1] = m_prefabRoot.Find(string.Format("{0}_Wrist/{0}_ThumbMetacarpal/{0}_Wrist/{0}_ThumbProximal/{0}_ThumbDistal", m_left ? 'L' : 'R'));
|
||||||
|
m_bones[(int)XRHandJointID.ThumbTip - 1] = m_prefabRoot.Find(string.Format("{0}_Wrist/{0}_ThumbMetacarpal/{0}_Wrist/{0}_ThumbProximal/{0}_ThumbDistal/{0}_ThumbTip", m_left ? 'L' : 'R'));
|
||||||
|
m_bones[(int)XRHandJointID.IndexMetacarpal - 1] = m_prefabRoot.Find(string.Format("{0}_Wrist/{0}_IndexMetacarpal", m_left ? 'L' : 'R'));
|
||||||
|
m_bones[(int)XRHandJointID.IndexProximal - 1] = m_prefabRoot.Find(string.Format("{0}_Wrist/{0}_IndexMetacarpal/{0}_IndexProximal", m_left ? 'L' : 'R'));
|
||||||
|
m_bones[(int)XRHandJointID.IndexIntermediate - 1] = m_prefabRoot.Find(string.Format("{0}_Wrist/{0}_IndexMetacarpal/{0}_IndexProximal/{0}_IndexIntermediate", m_left ? 'L' : 'R'));
|
||||||
|
m_bones[(int)XRHandJointID.IndexDistal - 1] = m_prefabRoot.Find(string.Format("{0}_Wrist/{0}_IndexMetacarpal/{0}_IndexProximal/{0}_IndexIntermediate/{0}_IndexDistal", m_left ? 'L' : 'R'));
|
||||||
|
m_bones[(int)XRHandJointID.IndexTip - 1] = m_prefabRoot.Find(string.Format("{0}_Wrist/{0}_IndexMetacarpal/{0}_IndexProximal/{0}_IndexIntermediate/{0}_IndexDistal/{0}_IndexTip", m_left ? 'L' : 'R'));
|
||||||
|
|
||||||
|
m_bones[(int)XRHandJointID.MiddleMetacarpal - 1] = m_prefabRoot.Find(string.Format("{0}_Wrist/{0}_MiddleMetacarpal", m_left ? 'L' : 'R'));
|
||||||
|
m_bones[(int)XRHandJointID.MiddleProximal - 1] = m_prefabRoot.Find(string.Format("{0}_Wrist/{0}_MiddleMetacarpal/{0}_MiddleProximal", m_left ? 'L' : 'R'));
|
||||||
|
m_bones[(int)XRHandJointID.MiddleIntermediate - 1] = m_prefabRoot.Find(string.Format("{0}_Wrist/{0}_MiddleMetacarpal/{0}_MiddleProximal/{0}_MiddleIntermediate", m_left ? 'L' : 'R'));
|
||||||
|
m_bones[(int)XRHandJointID.MiddleDistal - 1] = m_prefabRoot.Find(string.Format("{0}_Wrist/{0}_MiddleMetacarpal/{0}_MiddleProximal/{0}_MiddleIntermediate/{0}_MiddleDistal", m_left ? 'L' : 'R'));
|
||||||
|
m_bones[(int)XRHandJointID.MiddleTip - 1] = m_prefabRoot.Find(string.Format("{0}_Wrist/{0}_MiddleMetacarpal/{0}_MiddleProximal/{0}_MiddleIntermediate/{0}_MiddleDistal/{0}_MiddleTip", m_left ? 'L' : 'R'));
|
||||||
|
|
||||||
|
m_bones[(int)XRHandJointID.RingMetacarpal - 1] = m_prefabRoot.Find(string.Format("{0}_Wrist/{0}_RingMetacarpal", m_left ? 'L' : 'R'));
|
||||||
|
m_bones[(int)XRHandJointID.RingProximal - 1] = m_prefabRoot.Find(string.Format("{0}_Wrist/{0}_RingMetacarpal/{0}_RingProximal", m_left ? 'L' : 'R'));
|
||||||
|
m_bones[(int)XRHandJointID.RingIntermediate - 1] = m_prefabRoot.Find(string.Format("{0}_Wrist/{0}_RingMetacarpal/{0}_RingProximal/{0}_RingIntermediate", m_left ? 'L' : 'R'));
|
||||||
|
m_bones[(int)XRHandJointID.RingDistal - 1] = m_prefabRoot.Find(string.Format("{0}_Wrist/{0}_RingMetacarpal/{0}_RingProximal/{0}_RingIntermediate/{0}_RingDistal", m_left ? 'L' : 'R'));
|
||||||
|
m_bones[(int)XRHandJointID.RingTip - 1] = m_prefabRoot.Find(string.Format("{0}_Wrist/{0}_RingMetacarpal/{0}_RingProximal/{0}_RingIntermediate/{0}_RingDistal/{0}_RingTip", m_left ? 'L' : 'R'));
|
||||||
|
|
||||||
|
m_bones[(int)XRHandJointID.LittleMetacarpal - 1] = m_prefabRoot.Find(string.Format("{0}_Wrist/{0}_LittleMetacarpal", m_left ? 'L' : 'R'));
|
||||||
|
m_bones[(int)XRHandJointID.LittleProximal - 1] = m_prefabRoot.Find(string.Format("{0}_Wrist/{0}_LittleMetacarpal/{0}_LittleProximal", m_left ? 'L' : 'R'));
|
||||||
|
m_bones[(int)XRHandJointID.LittleIntermediate - 1] = m_prefabRoot.Find(string.Format("{0}_Wrist/{0}_LittleMetacarpal/{0}_LittleProximal/{0}_LittleIntermediate", m_left ? 'L' : 'R'));
|
||||||
|
m_bones[(int)XRHandJointID.LittleDistal - 1] = m_prefabRoot.Find(string.Format("{0}_Wrist/{0}_LittleMetacarpal/{0}_LittleProximal/{0}_LittleIntermediate/{0}_LittleDistal", m_left ? 'L' : 'R'));
|
||||||
|
m_bones[(int)XRHandJointID.LittleTip - 1] = m_prefabRoot.Find(string.Format("{0}_Wrist/{0}_LittleMetacarpal/{0}_LittleProximal/{0}_LittleIntermediate/{0}_LittleDistal/{0}_LittleTip", m_left ? 'L' : 'R'));
|
||||||
|
|
||||||
|
for(int i = 0; i < c_fingerBonesCount; i++)
|
||||||
|
{
|
||||||
|
if(m_bones[i] != null)
|
||||||
|
m_localRotations[i] = m_bones[i].localRotation;
|
||||||
|
}
|
||||||
|
|
||||||
|
base.OnShowHandsChange(Settings.ShowHands);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override Transform GetSourceForBone(HumanBodyBones p_bone)
|
||||||
|
{
|
||||||
|
Transform l_result = null;
|
||||||
|
if(m_left)
|
||||||
|
{
|
||||||
|
switch(p_bone)
|
||||||
|
{
|
||||||
|
case HumanBodyBones.LeftHand:
|
||||||
|
l_result = m_bones[(int)XRHandJointID.Wrist - 1];
|
||||||
|
break;
|
||||||
|
case HumanBodyBones.LeftThumbProximal:
|
||||||
|
l_result = m_bones[(int)XRHandJointID.ThumbMetacarpal - 1];
|
||||||
|
break;
|
||||||
|
case HumanBodyBones.LeftThumbIntermediate:
|
||||||
|
l_result = m_bones[(int)XRHandJointID.ThumbProximal - 1];
|
||||||
|
break;
|
||||||
|
case HumanBodyBones.LeftThumbDistal:
|
||||||
|
l_result = m_bones[(int)XRHandJointID.ThumbDistal - 1];
|
||||||
|
break;
|
||||||
|
|
||||||
|
case HumanBodyBones.LeftIndexProximal:
|
||||||
|
l_result = m_bones[(int)XRHandJointID.IndexProximal - 1];
|
||||||
|
break;
|
||||||
|
case HumanBodyBones.LeftIndexIntermediate:
|
||||||
|
l_result = m_bones[(int)XRHandJointID.IndexIntermediate - 1];
|
||||||
|
break;
|
||||||
|
case HumanBodyBones.LeftIndexDistal:
|
||||||
|
l_result = m_bones[(int)XRHandJointID.IndexDistal - 1];
|
||||||
|
break;
|
||||||
|
|
||||||
|
case HumanBodyBones.LeftMiddleProximal:
|
||||||
|
l_result = m_bones[(int)XRHandJointID.MiddleProximal - 1];
|
||||||
|
break;
|
||||||
|
case HumanBodyBones.LeftMiddleIntermediate:
|
||||||
|
l_result = m_bones[(int)XRHandJointID.MiddleIntermediate - 1];
|
||||||
|
break;
|
||||||
|
case HumanBodyBones.LeftMiddleDistal:
|
||||||
|
l_result = m_bones[(int)XRHandJointID.MiddleDistal - 1];
|
||||||
|
break;
|
||||||
|
|
||||||
|
case HumanBodyBones.LeftRingProximal:
|
||||||
|
l_result = m_bones[(int)XRHandJointID.RingProximal - 1];
|
||||||
|
break;
|
||||||
|
case HumanBodyBones.LeftRingIntermediate:
|
||||||
|
l_result = m_bones[(int)XRHandJointID.RingIntermediate - 1];
|
||||||
|
break;
|
||||||
|
case HumanBodyBones.LeftRingDistal:
|
||||||
|
l_result = m_bones[(int)XRHandJointID.RingDistal - 1];
|
||||||
|
break;
|
||||||
|
|
||||||
|
case HumanBodyBones.LeftLittleProximal:
|
||||||
|
l_result = m_bones[(int)XRHandJointID.LittleProximal - 1];
|
||||||
|
break;
|
||||||
|
case HumanBodyBones.LeftLittleIntermediate:
|
||||||
|
l_result = m_bones[(int)XRHandJointID.LittleIntermediate - 1];
|
||||||
|
break;
|
||||||
|
case HumanBodyBones.LeftLittleDistal:
|
||||||
|
l_result = m_bones[(int)XRHandJointID.LittleDistal - 1];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
switch(p_bone)
|
||||||
|
{
|
||||||
|
case HumanBodyBones.RightHand:
|
||||||
|
l_result = m_bones[(int)XRHandJointID.Wrist - 1];
|
||||||
|
break;
|
||||||
|
case HumanBodyBones.RightThumbProximal:
|
||||||
|
l_result = m_bones[(int)XRHandJointID.ThumbMetacarpal - 1];
|
||||||
|
break;
|
||||||
|
case HumanBodyBones.RightThumbIntermediate:
|
||||||
|
l_result = m_bones[(int)XRHandJointID.ThumbProximal - 1];
|
||||||
|
break;
|
||||||
|
case HumanBodyBones.RightThumbDistal:
|
||||||
|
l_result = m_bones[(int)XRHandJointID.ThumbDistal - 1];
|
||||||
|
break;
|
||||||
|
|
||||||
|
case HumanBodyBones.RightIndexProximal:
|
||||||
|
l_result = m_bones[(int)XRHandJointID.IndexProximal - 1];
|
||||||
|
break;
|
||||||
|
case HumanBodyBones.RightIndexIntermediate:
|
||||||
|
l_result = m_bones[(int)XRHandJointID.IndexIntermediate - 1];
|
||||||
|
break;
|
||||||
|
case HumanBodyBones.RightIndexDistal:
|
||||||
|
l_result = m_bones[(int)XRHandJointID.IndexDistal - 1];
|
||||||
|
break;
|
||||||
|
|
||||||
|
case HumanBodyBones.RightMiddleProximal:
|
||||||
|
l_result = m_bones[(int)XRHandJointID.MiddleProximal - 1];
|
||||||
|
break;
|
||||||
|
case HumanBodyBones.RightMiddleIntermediate:
|
||||||
|
l_result = m_bones[(int)XRHandJointID.MiddleIntermediate - 1];
|
||||||
|
break;
|
||||||
|
case HumanBodyBones.RightMiddleDistal:
|
||||||
|
l_result = m_bones[(int)XRHandJointID.MiddleDistal - 1];
|
||||||
|
break;
|
||||||
|
|
||||||
|
case HumanBodyBones.RightRingProximal:
|
||||||
|
l_result = m_bones[(int)XRHandJointID.RingProximal - 1];
|
||||||
|
break;
|
||||||
|
case HumanBodyBones.RightRingIntermediate:
|
||||||
|
l_result = m_bones[(int)XRHandJointID.RingIntermediate - 1];
|
||||||
|
break;
|
||||||
|
case HumanBodyBones.RightRingDistal:
|
||||||
|
l_result = m_bones[(int)XRHandJointID.RingDistal - 1];
|
||||||
|
break;
|
||||||
|
|
||||||
|
case HumanBodyBones.RightLittleProximal:
|
||||||
|
l_result = m_bones[(int)XRHandJointID.LittleProximal - 1];
|
||||||
|
break;
|
||||||
|
case HumanBodyBones.RightLittleIntermediate:
|
||||||
|
l_result = m_bones[(int)XRHandJointID.LittleIntermediate - 1];
|
||||||
|
break;
|
||||||
|
case HumanBodyBones.RightLittleDistal:
|
||||||
|
l_result = m_bones[(int)XRHandJointID.LittleDistal - 1];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return l_result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Update()
|
||||||
|
{
|
||||||
|
var l_tracking = OpenXRSettings.Instance.GetFeature<HandTrackingFeature>();
|
||||||
|
if(l_tracking != null)
|
||||||
|
{
|
||||||
|
// Bones from API are in playspace, not local in comparison with OpenVR
|
||||||
|
l_tracking.GetHandJoints(m_left ? HandTrackingFeature.Hand_Index.L : HandTrackingFeature.Hand_Index.R, out var l_positions, out var l_rotations, out var l_radius);
|
||||||
|
if(l_positions.Length >= c_fingerBonesCount)
|
||||||
|
{
|
||||||
|
// This stuff rotates debug hands in a weird way, but it doesn't matter because of funny math in new FingerSystem
|
||||||
|
Quaternion l_rot = m_prefabRoot.rotation;
|
||||||
|
m_prefabRoot.rotation = Quaternion.identity;
|
||||||
|
for(int i = 0; i < c_fingerBonesCount; i++)
|
||||||
|
{
|
||||||
|
if(m_bones[i] != null)
|
||||||
|
m_bones[i].rotation = l_rotations[i];
|
||||||
|
}
|
||||||
|
m_prefabRoot.rotation = l_rot;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Rebind(Quaternion p_base)
|
||||||
|
{
|
||||||
|
for(int i = 0; i < c_fingerBonesCount; i++)
|
||||||
|
{
|
||||||
|
if(m_bones[i] != null)
|
||||||
|
m_bones[i].localRotation = m_localRotations[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
if(m_bones[(int)XRHandJointID.Wrist - 1] != null)
|
||||||
|
m_bones[(int)XRHandJointID.Wrist - 1].rotation = p_base * (m_left ? Quaternion.Euler(0f, -90f, 0f) : Quaternion.Euler(0f, 90f, 0f));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
161
ml_bft/InputHandler.cs
Normal file
161
ml_bft/InputHandler.cs
Normal file
|
@ -0,0 +1,161 @@
|
||||||
|
using ABI_RC.Core.Savior;
|
||||||
|
using ABI_RC.Systems.InputManagement;
|
||||||
|
using ABI_RC.Systems.VRModeSwitch;
|
||||||
|
using UnityEngine;
|
||||||
|
|
||||||
|
namespace ml_bft
|
||||||
|
{
|
||||||
|
// Not an actual module, but can be used as one
|
||||||
|
class InputHandler
|
||||||
|
{
|
||||||
|
public static InputHandler Instance { get; private set; } = null;
|
||||||
|
|
||||||
|
bool m_active = false;
|
||||||
|
|
||||||
|
HandHandler m_leftHandHandler = null;
|
||||||
|
HandHandler m_rightHandHandler = null;
|
||||||
|
|
||||||
|
internal InputHandler()
|
||||||
|
{
|
||||||
|
if(Instance == null)
|
||||||
|
Instance = this;
|
||||||
|
|
||||||
|
m_active = false;
|
||||||
|
|
||||||
|
if(MetaPort.Instance.isUsingVr)
|
||||||
|
SetupHandlers();
|
||||||
|
|
||||||
|
VRModeSwitchEvents.OnInitializeXR.AddListener(this.OnSwitchToVR);
|
||||||
|
VRModeSwitchEvents.OnDeinitializeXR.AddListener(this.OnSwitchToDesktop);
|
||||||
|
|
||||||
|
Settings.SkeletalInputChange += this.OnSkeletalInputChange;
|
||||||
|
}
|
||||||
|
internal void Cleanup()
|
||||||
|
{
|
||||||
|
if(Instance == this)
|
||||||
|
Instance = null;
|
||||||
|
|
||||||
|
RemoveHandlers();
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetupHandlers()
|
||||||
|
{
|
||||||
|
if(!CheckVR.Instance.forceOpenXr)
|
||||||
|
{
|
||||||
|
m_leftHandHandler = new HandHandlerOVR(CVRInputManager.Instance.leftHandTransform, true);
|
||||||
|
m_rightHandHandler = new HandHandlerOVR(CVRInputManager.Instance.rightHandTransform, false);
|
||||||
|
m_active = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void RemoveHandlers()
|
||||||
|
{
|
||||||
|
m_leftHandHandler?.Cleanup();
|
||||||
|
m_leftHandHandler = null;
|
||||||
|
m_rightHandHandler?.Cleanup();
|
||||||
|
m_rightHandHandler = null;
|
||||||
|
m_active = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Rebind(Quaternion p_base)
|
||||||
|
{
|
||||||
|
if(m_active)
|
||||||
|
{
|
||||||
|
m_leftHandHandler?.Rebind(p_base);
|
||||||
|
m_rightHandHandler?.Rebind(p_base);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Transform GetSourceForBone(HumanBodyBones p_bone, bool p_left)
|
||||||
|
{
|
||||||
|
Transform l_result;
|
||||||
|
if(p_left)
|
||||||
|
l_result = m_leftHandHandler?.GetSourceForBone(p_bone);
|
||||||
|
else
|
||||||
|
l_result = m_rightHandHandler?.GetSourceForBone(p_bone);
|
||||||
|
return l_result;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Game events
|
||||||
|
internal void OnInputUpdate()
|
||||||
|
{
|
||||||
|
if(m_active && Settings.SkeletalInput)
|
||||||
|
{
|
||||||
|
m_leftHandHandler?.Update();
|
||||||
|
m_rightHandHandler?.Update();
|
||||||
|
|
||||||
|
CVRInputManager.Instance.individualFingerTracking = true;
|
||||||
|
CVRInputManager.Instance.finger1StretchedLeftThumb = FingerSystem.Instance.m_lastValues[0];
|
||||||
|
CVRInputManager.Instance.finger2StretchedLeftThumb = FingerSystem.Instance.m_lastValues[1];
|
||||||
|
CVRInputManager.Instance.finger3StretchedLeftThumb = FingerSystem.Instance.m_lastValues[2];
|
||||||
|
CVRInputManager.Instance.fingerSpreadLeftThumb = FingerSystem.Instance.m_lastValues[3];
|
||||||
|
CVRInputManager.Instance.finger1StretchedLeftIndex = FingerSystem.Instance.m_lastValues[4];
|
||||||
|
CVRInputManager.Instance.finger2StretchedLeftIndex = FingerSystem.Instance.m_lastValues[5];
|
||||||
|
CVRInputManager.Instance.finger3StretchedLeftIndex = FingerSystem.Instance.m_lastValues[6];
|
||||||
|
CVRInputManager.Instance.fingerSpreadLeftIndex = FingerSystem.Instance.m_lastValues[7];
|
||||||
|
CVRInputManager.Instance.finger1StretchedLeftMiddle = FingerSystem.Instance.m_lastValues[8];
|
||||||
|
CVRInputManager.Instance.finger2StretchedLeftMiddle = FingerSystem.Instance.m_lastValues[9];
|
||||||
|
CVRInputManager.Instance.finger3StretchedLeftMiddle = FingerSystem.Instance.m_lastValues[10];
|
||||||
|
CVRInputManager.Instance.fingerSpreadLeftMiddle = FingerSystem.Instance.m_lastValues[11];
|
||||||
|
CVRInputManager.Instance.finger1StretchedLeftRing = FingerSystem.Instance.m_lastValues[12];
|
||||||
|
CVRInputManager.Instance.finger2StretchedLeftRing = FingerSystem.Instance.m_lastValues[13];
|
||||||
|
CVRInputManager.Instance.finger3StretchedLeftRing = FingerSystem.Instance.m_lastValues[14];
|
||||||
|
CVRInputManager.Instance.fingerSpreadLeftRing = FingerSystem.Instance.m_lastValues[15];
|
||||||
|
CVRInputManager.Instance.finger1StretchedLeftPinky = FingerSystem.Instance.m_lastValues[16];
|
||||||
|
CVRInputManager.Instance.finger2StretchedLeftPinky = FingerSystem.Instance.m_lastValues[17];
|
||||||
|
CVRInputManager.Instance.finger3StretchedLeftPinky = FingerSystem.Instance.m_lastValues[18];
|
||||||
|
CVRInputManager.Instance.fingerSpreadLeftPinky = FingerSystem.Instance.m_lastValues[19];
|
||||||
|
CVRInputManager.Instance.finger1StretchedRightThumb = FingerSystem.Instance.m_lastValues[20];
|
||||||
|
CVRInputManager.Instance.finger2StretchedRightThumb = FingerSystem.Instance.m_lastValues[21];
|
||||||
|
CVRInputManager.Instance.finger3StretchedRightThumb = FingerSystem.Instance.m_lastValues[22];
|
||||||
|
CVRInputManager.Instance.fingerSpreadRightThumb = FingerSystem.Instance.m_lastValues[23];
|
||||||
|
CVRInputManager.Instance.finger1StretchedRightIndex = FingerSystem.Instance.m_lastValues[24];
|
||||||
|
CVRInputManager.Instance.finger2StretchedRightIndex = FingerSystem.Instance.m_lastValues[25];
|
||||||
|
CVRInputManager.Instance.finger3StretchedRightIndex = FingerSystem.Instance.m_lastValues[26];
|
||||||
|
CVRInputManager.Instance.fingerSpreadRightIndex = FingerSystem.Instance.m_lastValues[27];
|
||||||
|
CVRInputManager.Instance.finger1StretchedRightMiddle = FingerSystem.Instance.m_lastValues[28];
|
||||||
|
CVRInputManager.Instance.finger2StretchedRightMiddle = FingerSystem.Instance.m_lastValues[29];
|
||||||
|
CVRInputManager.Instance.finger3StretchedRightMiddle = FingerSystem.Instance.m_lastValues[30];
|
||||||
|
CVRInputManager.Instance.fingerSpreadRightMiddle = FingerSystem.Instance.m_lastValues[31];
|
||||||
|
CVRInputManager.Instance.finger1StretchedRightRing = FingerSystem.Instance.m_lastValues[32];
|
||||||
|
CVRInputManager.Instance.finger2StretchedRightRing = FingerSystem.Instance.m_lastValues[33];
|
||||||
|
CVRInputManager.Instance.finger3StretchedRightRing = FingerSystem.Instance.m_lastValues[34];
|
||||||
|
CVRInputManager.Instance.fingerSpreadRightRing = FingerSystem.Instance.m_lastValues[35];
|
||||||
|
CVRInputManager.Instance.finger1StretchedRightPinky = FingerSystem.Instance.m_lastValues[36];
|
||||||
|
CVRInputManager.Instance.finger2StretchedRightPinky = FingerSystem.Instance.m_lastValues[37];
|
||||||
|
CVRInputManager.Instance.finger3StretchedRightPinky = FingerSystem.Instance.m_lastValues[38];
|
||||||
|
CVRInputManager.Instance.fingerSpreadRightPinky = FingerSystem.Instance.m_lastValues[39];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void OnSwitchToVR()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
SetupHandlers();
|
||||||
|
}
|
||||||
|
catch(System.Exception e)
|
||||||
|
{
|
||||||
|
MelonLoader.MelonLogger.Error(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void OnSwitchToDesktop()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
RemoveHandlers();
|
||||||
|
}
|
||||||
|
catch(System.Exception e)
|
||||||
|
{
|
||||||
|
MelonLoader.MelonLogger.Error(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Settings
|
||||||
|
void OnSkeletalInputChange(bool p_value)
|
||||||
|
{
|
||||||
|
if(!p_value)
|
||||||
|
CVRInputManager.Instance.individualFingerTracking = Utils.AreKnucklesInUse();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
141
ml_bft/Main.cs
Normal file
141
ml_bft/Main.cs
Normal file
|
@ -0,0 +1,141 @@
|
||||||
|
using ABI_RC.Core.Player;
|
||||||
|
using ABI_RC.Systems.IK;
|
||||||
|
using ABI_RC.Systems.InputManagement;
|
||||||
|
using System;
|
||||||
|
using System.Collections;
|
||||||
|
using System.Reflection;
|
||||||
|
using UnityEngine;
|
||||||
|
|
||||||
|
namespace ml_bft
|
||||||
|
{
|
||||||
|
public class BetterFingersTracking : MelonLoader.MelonMod
|
||||||
|
{
|
||||||
|
static BetterFingersTracking ms_instance = null;
|
||||||
|
|
||||||
|
InputHandler m_inputHandler = null;
|
||||||
|
FingerSystem m_fingerSystem = null;
|
||||||
|
|
||||||
|
public override void OnInitializeMelon()
|
||||||
|
{
|
||||||
|
if(ms_instance == null)
|
||||||
|
ms_instance = this;
|
||||||
|
|
||||||
|
Settings.Init();
|
||||||
|
AssetsHandler.Load();
|
||||||
|
|
||||||
|
// Needed patches: avatar initialization and reinitialization on vr switch, after input update, after late iksystem update
|
||||||
|
HarmonyInstance.Patch(
|
||||||
|
typeof(PlayerSetup).GetMethod(nameof(PlayerSetup.SetupAvatar)),
|
||||||
|
null,
|
||||||
|
new HarmonyLib.HarmonyMethod(typeof(BetterFingersTracking).GetMethod(nameof(OnSetupAvatar_Postfix), BindingFlags.Static | BindingFlags.NonPublic))
|
||||||
|
);
|
||||||
|
HarmonyInstance.Patch(
|
||||||
|
typeof(PlayerSetup).GetMethod(nameof(PlayerSetup.ClearAvatar)),
|
||||||
|
null,
|
||||||
|
new HarmonyLib.HarmonyMethod(typeof(BetterFingersTracking).GetMethod(nameof(OnAvatarClear_Postfix), BindingFlags.Static | BindingFlags.NonPublic))
|
||||||
|
);
|
||||||
|
HarmonyInstance.Patch(
|
||||||
|
typeof(IKSystem).GetMethod(nameof(IKSystem.ReinitializeAvatar), BindingFlags.Instance | BindingFlags.Public),
|
||||||
|
null,
|
||||||
|
new HarmonyLib.HarmonyMethod(typeof(BetterFingersTracking).GetMethod(nameof(OnReinitializeAvatar_Postfix), BindingFlags.Static | BindingFlags.NonPublic))
|
||||||
|
);
|
||||||
|
HarmonyInstance.Patch(
|
||||||
|
typeof(CVRInputManager).GetMethod("UpdateInput", BindingFlags.NonPublic | BindingFlags.Instance),
|
||||||
|
null,
|
||||||
|
new HarmonyLib.HarmonyMethod(typeof(BetterFingersTracking).GetMethod(nameof(OnInputUpdate_Postfix), BindingFlags.NonPublic | BindingFlags.Static))
|
||||||
|
);
|
||||||
|
HarmonyInstance.Patch(
|
||||||
|
typeof(IKSystem).GetMethod("LateUpdate", BindingFlags.NonPublic | BindingFlags.Instance),
|
||||||
|
null,
|
||||||
|
new HarmonyLib.HarmonyMethod(typeof(BetterFingersTracking).GetMethod(nameof(OnIKSystemLateUpdate_Postfix), BindingFlags.NonPublic | BindingFlags.Static))
|
||||||
|
);
|
||||||
|
|
||||||
|
MelonLoader.MelonCoroutines.Start(WaitForInstances());
|
||||||
|
}
|
||||||
|
IEnumerator WaitForInstances()
|
||||||
|
{
|
||||||
|
while(CVRInputManager.Instance == null)
|
||||||
|
yield return null;
|
||||||
|
|
||||||
|
m_inputHandler = new InputHandler();
|
||||||
|
m_fingerSystem = new FingerSystem();
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void OnDeinitializeMelon()
|
||||||
|
{
|
||||||
|
if(ms_instance == this)
|
||||||
|
ms_instance = null;
|
||||||
|
|
||||||
|
m_inputHandler?.Cleanup();
|
||||||
|
m_inputHandler = null;
|
||||||
|
|
||||||
|
m_fingerSystem?.Cleanup();
|
||||||
|
m_fingerSystem = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void OnSetupAvatar_Postfix() => ms_instance?.OnSetupAvatar();
|
||||||
|
void OnSetupAvatar()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
m_fingerSystem?.OnAvatarSetup();
|
||||||
|
}
|
||||||
|
catch(Exception e)
|
||||||
|
{
|
||||||
|
MelonLoader.MelonLogger.Error(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void OnAvatarClear_Postfix() => ms_instance?.OnAvatarClear();
|
||||||
|
void OnAvatarClear()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
m_fingerSystem?.OnAvatarClear();
|
||||||
|
}
|
||||||
|
catch(Exception e)
|
||||||
|
{
|
||||||
|
MelonLoader.MelonLogger.Error(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void OnReinitializeAvatar_Postfix() => ms_instance?.OnAvatarReinitialize();
|
||||||
|
void OnAvatarReinitialize()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
m_fingerSystem?.OnReinitializeAvatar();
|
||||||
|
}
|
||||||
|
catch(Exception e)
|
||||||
|
{
|
||||||
|
MelonLoader.MelonLogger.Error(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void OnInputUpdate_Postfix() => ms_instance?.OnInputUpdate();
|
||||||
|
void OnInputUpdate()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
m_inputHandler?.OnInputUpdate();
|
||||||
|
}
|
||||||
|
catch(Exception e)
|
||||||
|
{
|
||||||
|
MelonLoader.MelonLogger.Error(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void OnIKSystemLateUpdate_Postfix(HumanPoseHandler ____humanPoseHandler) => ms_instance?.OnIKSystemLateUpdate(____humanPoseHandler);
|
||||||
|
void OnIKSystemLateUpdate(HumanPoseHandler p_handler)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
m_fingerSystem?.OnIKSystemLateUpdate(p_handler);
|
||||||
|
}
|
||||||
|
catch(Exception e)
|
||||||
|
{
|
||||||
|
MelonLoader.MelonLogger.Error(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
4
ml_bft/Properties/AssemblyInfo.cs
Normal file
4
ml_bft/Properties/AssemblyInfo.cs
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
[assembly: MelonLoader.MelonInfo(typeof(ml_bft.BetterFingersTracking), "BetterFingersTracking", "1.0.0", "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)]
|
16
ml_bft/README.md
Normal file
16
ml_bft/README.md
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
# Better Fingers Tracking
|
||||||
|
Mod that overhauls behaviour of fingers tracking.
|
||||||
|
|
||||||
|
# Installation
|
||||||
|
* Install [latest MelonLoader](https://github.com/LavaGang/MelonLoader)
|
||||||
|
* Get [latest release DLL](../../../releases/latest):
|
||||||
|
* Put `ml_bft.dll` in `Mods` folder of game
|
||||||
|
|
||||||
|
# Usage
|
||||||
|
Available mod's settings in `Settings - Input & Key-Bindings - Better Fingers Tracking`:
|
||||||
|
* **Force SteamVR skeletal input:** forced usage of SteamVR skeletal input (works as long as controllers' driver supplies skeletal pose throught OpenVR interfaces); `false` by default
|
||||||
|
* **Show hands model:** shows transparent hands model (mostly as debug option); `false` by default
|
||||||
|
|
||||||
|
# Notes
|
||||||
|
* Currently supports only SteamVR environment, OpenXR support is planned.
|
||||||
|
* Fingers tracking quaity is highly dependant on avatar's hand state in Unity's T-pose, possible solutions are in search.
|
26
ml_bft/ResourcesHandler.cs
Normal file
26
ml_bft/ResourcesHandler.cs
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
using System;
|
||||||
|
using System.IO;
|
||||||
|
using System.Reflection;
|
||||||
|
|
||||||
|
namespace ml_bft
|
||||||
|
{
|
||||||
|
static class ResourcesHandler
|
||||||
|
{
|
||||||
|
public static string GetEmbeddedResource(string p_name)
|
||||||
|
{
|
||||||
|
string l_result = "";
|
||||||
|
Assembly l_assembly = Assembly.GetExecutingAssembly();
|
||||||
|
string l_assemblyName = l_assembly.GetName().Name;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
Stream l_libraryStream = l_assembly.GetManifestResourceStream(l_assemblyName + ".resources." + p_name);
|
||||||
|
StreamReader l_streadReader = new StreamReader(l_libraryStream);
|
||||||
|
l_result = l_streadReader.ReadToEnd();
|
||||||
|
}
|
||||||
|
catch(Exception) { }
|
||||||
|
|
||||||
|
return l_result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
87
ml_bft/Settings.cs
Normal file
87
ml_bft/Settings.cs
Normal file
|
@ -0,0 +1,87 @@
|
||||||
|
using ABI_RC.Core.InteractionSystem;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace ml_bft
|
||||||
|
{
|
||||||
|
static class Settings
|
||||||
|
{
|
||||||
|
enum ModSetting
|
||||||
|
{
|
||||||
|
SkeletalInput = 0,
|
||||||
|
ShowHands
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool SkeletalInput { get; private set; } = false;
|
||||||
|
public static bool ShowHands { get; private set; } = false;
|
||||||
|
|
||||||
|
static MelonLoader.MelonPreferences_Category ms_category = null;
|
||||||
|
static List<MelonLoader.MelonPreferences_Entry> ms_entries = null;
|
||||||
|
|
||||||
|
static public event Action<bool> SkeletalInputChange;
|
||||||
|
static public event Action<bool> ShowHandsChange;
|
||||||
|
|
||||||
|
internal static void Init()
|
||||||
|
{
|
||||||
|
ms_category = MelonLoader.MelonPreferences.CreateCategory("BFT", null, true);
|
||||||
|
|
||||||
|
ms_entries = new List<MelonLoader.MelonPreferences_Entry>()
|
||||||
|
{
|
||||||
|
ms_category.CreateEntry(ModSetting.SkeletalInput.ToString(), SkeletalInput),
|
||||||
|
ms_category.CreateEntry(ModSetting.ShowHands.ToString(), ShowHands)
|
||||||
|
};
|
||||||
|
|
||||||
|
SkeletalInput = (bool)ms_entries[(int)ModSetting.SkeletalInput].BoxedValue;
|
||||||
|
ShowHands = (bool)ms_entries[(int)ModSetting.ShowHands].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.Listener.FinishLoad += (_) =>
|
||||||
|
{
|
||||||
|
ViewManager.Instance.gameMenuView.View.ExecuteScript(ResourcesHandler.GetEmbeddedResource("mods_extension.js"));
|
||||||
|
ViewManager.Instance.gameMenuView.View.ExecuteScript(ResourcesHandler.GetEmbeddedResource("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.SkeletalInput:
|
||||||
|
{
|
||||||
|
SkeletalInput = bool.Parse(p_value);
|
||||||
|
SkeletalInputChange?.Invoke(SkeletalInput);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ModSetting.ShowHands:
|
||||||
|
{
|
||||||
|
ShowHands = bool.Parse(p_value);
|
||||||
|
ShowHandsChange?.Invoke(ShowHands);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
ms_entries[(int)l_setting].BoxedValue = bool.Parse(p_value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
15
ml_bft/Utils.cs
Normal file
15
ml_bft/Utils.cs
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
using ABI_RC.Core.UI;
|
||||||
|
using ABI_RC.Systems.InputManagement;
|
||||||
|
using System.Reflection;
|
||||||
|
|
||||||
|
namespace ml_bft
|
||||||
|
{
|
||||||
|
static class Utils
|
||||||
|
{
|
||||||
|
static readonly FieldInfo ms_view = typeof(CohtmlControlledViewWrapper).GetField("_view", BindingFlags.NonPublic | BindingFlags.Instance);
|
||||||
|
|
||||||
|
static public void ExecuteScript(this CohtmlControlledViewWrapper p_instance, string p_script) => ((cohtml.Net.View)ms_view.GetValue(p_instance)).ExecuteScript(p_script);
|
||||||
|
|
||||||
|
public static bool AreKnucklesInUse() => ((CVRInputManager.Instance._leftController == ABI_RC.Systems.InputManagement.XR.eXRControllerType.Index) || (CVRInputManager.Instance._rightController == ABI_RC.Systems.InputManagement.XR.eXRControllerType.Index));
|
||||||
|
}
|
||||||
|
}
|
102
ml_bft/ml_bft.csproj
Normal file
102
ml_bft/ml_bft.csproj
Normal file
|
@ -0,0 +1,102 @@
|
||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<TargetFramework>netstandard2.1</TargetFramework>
|
||||||
|
<Platforms>x64</Platforms>
|
||||||
|
<PackageId>BetterFingersTracking</PackageId>
|
||||||
|
<Authors>SDraw</Authors>
|
||||||
|
<Company>None</Company>
|
||||||
|
<Product>BetterFingersTracking</Product>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||||
|
<DebugType>embedded</DebugType>
|
||||||
|
<DebugSymbols>true</DebugSymbols>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<None Remove="resources\mod_menu.js" />
|
||||||
|
<None Remove="resources\ovr_fingers.asset" />
|
||||||
|
<None Remove="resources\ovr_fingers_left.asset" />
|
||||||
|
<None Remove="resources\ovr_fingers_right.asset" />
|
||||||
|
<None Remove="resources\oxr_fingers.asset" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<EmbeddedResource Include="resources\mod_menu.js" />
|
||||||
|
<EmbeddedResource Include="resources\ovr_fingers.asset" />
|
||||||
|
<EmbeddedResource Include="resources\oxr_fingers.asset" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<None 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>
|
||||||
|
<SpecificVersion>false</SpecificVersion>
|
||||||
|
</Reference>
|
||||||
|
<Reference Include="Assembly-CSharp">
|
||||||
|
<HintPath>D:\games\Steam\steamapps\common\ChilloutVR\ChilloutVR_Data\Managed\Assembly-CSharp.dll</HintPath>
|
||||||
|
<Private>false</Private>
|
||||||
|
<SpecificVersion>false</SpecificVersion>
|
||||||
|
</Reference>
|
||||||
|
<Reference Include="cohtml.Net">
|
||||||
|
<HintPath>D:\Games\Steam\steamapps\common\ChilloutVR\ChilloutVR_Data\Managed\cohtml.Net.dll</HintPath>
|
||||||
|
<SpecificVersion>false</SpecificVersion>
|
||||||
|
<Private>false</Private>
|
||||||
|
</Reference>
|
||||||
|
<Reference Include="Cohtml.Runtime">
|
||||||
|
<HintPath>D:\Games\Steam\steamapps\common\ChilloutVR\ChilloutVR_Data\Managed\Cohtml.Runtime.dll</HintPath>
|
||||||
|
<SpecificVersion>false</SpecificVersion>
|
||||||
|
<Private>false</Private>
|
||||||
|
</Reference>
|
||||||
|
<Reference Include="MelonLoader">
|
||||||
|
<HintPath>D:\games\Steam\steamapps\common\ChilloutVR\MelonLoader\net35\MelonLoader.dll</HintPath>
|
||||||
|
<Private>false</Private>
|
||||||
|
<SpecificVersion>false</SpecificVersion>
|
||||||
|
</Reference>
|
||||||
|
<Reference Include="SteamVR">
|
||||||
|
<HintPath>D:\games\Steam\steamapps\common\ChilloutVR\ChilloutVR_Data\Managed\SteamVR.dll</HintPath>
|
||||||
|
<Private>false</Private>
|
||||||
|
<SpecificVersion>false</SpecificVersion>
|
||||||
|
</Reference>
|
||||||
|
<Reference Include="Unity.XR.Hands">
|
||||||
|
<HintPath>D:\Games\Steam\steamapps\common\ChilloutVR\ChilloutVR_Data\Managed\Unity.XR.Hands.dll</HintPath>
|
||||||
|
<SpecificVersion>false</SpecificVersion>
|
||||||
|
<Private>false</Private>
|
||||||
|
</Reference>
|
||||||
|
<Reference Include="Unity.XR.OpenXR">
|
||||||
|
<HintPath>D:\Games\Steam\steamapps\common\ChilloutVR\ChilloutVR_Data\Managed\Unity.XR.OpenXR.dll</HintPath>
|
||||||
|
<SpecificVersion>false</SpecificVersion>
|
||||||
|
<Private>false</Private>
|
||||||
|
</Reference>
|
||||||
|
<Reference Include="UnityEngine.AnimationModule">
|
||||||
|
<HintPath>D:\games\Steam\steamapps\common\ChilloutVR\ChilloutVR_Data\Managed\UnityEngine.AnimationModule.dll</HintPath>
|
||||||
|
<SpecificVersion>false</SpecificVersion>
|
||||||
|
<Private>false</Private>
|
||||||
|
</Reference>
|
||||||
|
<Reference Include="UnityEngine.AssetBundleModule">
|
||||||
|
<HintPath>D:\Games\Steam\steamapps\common\ChilloutVR\ChilloutVR_Data\Managed\UnityEngine.AssetBundleModule.dll</HintPath>
|
||||||
|
<SpecificVersion>false</SpecificVersion>
|
||||||
|
<Private>false</Private>
|
||||||
|
</Reference>
|
||||||
|
<Reference Include="UnityEngine.CoreModule">
|
||||||
|
<HintPath>D:\games\Steam\steamapps\common\ChilloutVR\ChilloutVR_Data\Managed\UnityEngine.CoreModule.dll</HintPath>
|
||||||
|
<SpecificVersion>false</SpecificVersion>
|
||||||
|
<Private>false</Private>
|
||||||
|
</Reference>
|
||||||
|
<Reference Include="UnityEngine.XRModule">
|
||||||
|
<HintPath>D:\Games\Steam\steamapps\common\ChilloutVR\ChilloutVR_Data\Managed\UnityEngine.XRModule.dll</HintPath>
|
||||||
|
<SpecificVersion>false</SpecificVersion>
|
||||||
|
<Private>false</Private>
|
||||||
|
</Reference>
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<Target Name="PostBuild" AfterTargets="PostBuildEvent">
|
||||||
|
<Exec Command="copy /y "$(TargetPath)" "D:\Games\Steam\steamapps\common\ChilloutVR\Mods\"" />
|
||||||
|
</Target>
|
||||||
|
|
||||||
|
</Project>
|
28
ml_bft/resources/mod_menu.js
Normal file
28
ml_bft/resources/mod_menu.js
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
{
|
||||||
|
let l_block = document.createElement('div');
|
||||||
|
l_block.innerHTML = `
|
||||||
|
<div class ="settings-subcategory">
|
||||||
|
<div class ="subcategory-name">Better Finger Tracking</div>
|
||||||
|
<div class ="subcategory-description"></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class ="row-wrapper">
|
||||||
|
<div class ="option-caption">Force SteamVR skeletal input: </div>
|
||||||
|
<div class ="option-input">
|
||||||
|
<div id="SkeletalInput" class ="inp_toggle no-scroll" data-current="false"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class ="row-wrapper">
|
||||||
|
<div class ="option-caption">Show hands model: </div>
|
||||||
|
<div class ="option-input">
|
||||||
|
<div id="ShowHands" class ="inp_toggle no-scroll" data-current="false"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
|
document.getElementById('settings-input').appendChild(l_block);
|
||||||
|
|
||||||
|
// Toggles
|
||||||
|
for (let l_toggle of l_block.querySelectorAll('.inp_toggle'))
|
||||||
|
modsExtension.addSetting('BFT', l_toggle.id, modsExtension.createToggle(l_toggle, 'OnToggleUpdate_BFT'));
|
||||||
|
}
|
BIN
ml_bft/resources/ovr_fingers.asset
Normal file
BIN
ml_bft/resources/ovr_fingers.asset
Normal file
Binary file not shown.
BIN
ml_bft/resources/oxr_fingers.asset
Normal file
BIN
ml_bft/resources/oxr_fingers.asset
Normal file
Binary file not shown.
|
@ -12,8 +12,8 @@
|
||||||
|
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||||
<PlatformTarget>x64</PlatformTarget>
|
<PlatformTarget>x64</PlatformTarget>
|
||||||
<DebugType>none</DebugType>
|
<DebugType>embedded</DebugType>
|
||||||
<DebugSymbols>false</DebugSymbols>
|
<DebugSymbols>true</DebugSymbols>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|
|
@ -538,29 +538,29 @@ namespace ml_lme
|
||||||
{
|
{
|
||||||
if(p_left)
|
if(p_left)
|
||||||
{
|
{
|
||||||
base._inputManager.finger1StretchedLeftThumb = -0.5f;
|
base._inputManager.finger1StretchedLeftThumb = 0f;
|
||||||
base._inputManager.finger2StretchedLeftThumb = 0.7f;
|
base._inputManager.finger2StretchedLeftThumb = 0f;
|
||||||
base._inputManager.finger3StretchedLeftThumb = 0.7f;
|
base._inputManager.finger3StretchedLeftThumb = 0f;
|
||||||
base._inputManager.fingerSpreadLeftThumb = 0f;
|
base._inputManager.fingerSpreadLeftThumb = 0f;
|
||||||
|
|
||||||
base._inputManager.finger1StretchedLeftIndex = 0.5f;
|
base._inputManager.finger1StretchedLeftIndex = 0f;
|
||||||
base._inputManager.finger2StretchedLeftIndex = 0.7f;
|
base._inputManager.finger2StretchedLeftIndex =0f;
|
||||||
base._inputManager.finger3StretchedLeftIndex = 0.7f;
|
base._inputManager.finger3StretchedLeftIndex = 0f;
|
||||||
base._inputManager.fingerSpreadLeftIndex = 0f;
|
base._inputManager.fingerSpreadLeftIndex = 0f;
|
||||||
|
|
||||||
base._inputManager.finger1StretchedLeftMiddle = 0.5f;
|
base._inputManager.finger1StretchedLeftMiddle = 0f;
|
||||||
base._inputManager.finger2StretchedLeftMiddle = 0.7f;
|
base._inputManager.finger2StretchedLeftMiddle = 0f;
|
||||||
base._inputManager.finger3StretchedLeftMiddle = 0.7f;
|
base._inputManager.finger3StretchedLeftMiddle = 0f;
|
||||||
base._inputManager.fingerSpreadLeftMiddle = 0f;
|
base._inputManager.fingerSpreadLeftMiddle = 0f;
|
||||||
|
|
||||||
base._inputManager.finger1StretchedLeftRing = 0.5f;
|
base._inputManager.finger1StretchedLeftRing = 0f;
|
||||||
base._inputManager.finger2StretchedLeftRing = 0.7f;
|
base._inputManager.finger2StretchedLeftRing = 0f;
|
||||||
base._inputManager.finger3StretchedLeftRing = 0.7f;
|
base._inputManager.finger3StretchedLeftRing = 0f;
|
||||||
base._inputManager.fingerSpreadLeftRing = 0f;
|
base._inputManager.fingerSpreadLeftRing = 0f;
|
||||||
|
|
||||||
base._inputManager.finger1StretchedLeftPinky = 0.5f;
|
base._inputManager.finger1StretchedLeftPinky = 0f;
|
||||||
base._inputManager.finger2StretchedLeftPinky = 0.7f;
|
base._inputManager.finger2StretchedLeftPinky = 0f;
|
||||||
base._inputManager.finger3StretchedLeftPinky = 0.7f;
|
base._inputManager.finger3StretchedLeftPinky = 0f;
|
||||||
base._inputManager.fingerSpreadLeftPinky = 0f;
|
base._inputManager.fingerSpreadLeftPinky = 0f;
|
||||||
|
|
||||||
base._inputManager.fingerFullCurlNormalizedLeftThumb = 0f;
|
base._inputManager.fingerFullCurlNormalizedLeftThumb = 0f;
|
||||||
|
@ -571,29 +571,29 @@ namespace ml_lme
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
base._inputManager.finger1StretchedRightThumb = -0.5f;
|
base._inputManager.finger1StretchedRightThumb = 0f;
|
||||||
base._inputManager.finger2StretchedRightThumb = 0.7f;
|
base._inputManager.finger2StretchedRightThumb = 0f;
|
||||||
base._inputManager.finger3StretchedRightThumb = 0.7f;
|
base._inputManager.finger3StretchedRightThumb = 0f;
|
||||||
base._inputManager.fingerSpreadRightThumb = 0f;
|
base._inputManager.fingerSpreadRightThumb = 0f;
|
||||||
|
|
||||||
base._inputManager.finger1StretchedRightIndex = 0.5f;
|
base._inputManager.finger1StretchedRightIndex = 0f;
|
||||||
base._inputManager.finger2StretchedRightIndex = 0.7f;
|
base._inputManager.finger2StretchedRightIndex = 0f;
|
||||||
base._inputManager.finger3StretchedRightIndex = 0.7f;
|
base._inputManager.finger3StretchedRightIndex = 0f;
|
||||||
base._inputManager.fingerSpreadRightIndex = 0f;
|
base._inputManager.fingerSpreadRightIndex = 0f;
|
||||||
|
|
||||||
base._inputManager.finger1StretchedRightMiddle = 0.5f;
|
base._inputManager.finger1StretchedRightMiddle = 0f;
|
||||||
base._inputManager.finger2StretchedRightMiddle = 0.7f;
|
base._inputManager.finger2StretchedRightMiddle = 0f;
|
||||||
base._inputManager.finger3StretchedRightMiddle = 0.7f;
|
base._inputManager.finger3StretchedRightMiddle = 0f;
|
||||||
base._inputManager.fingerSpreadRightMiddle = 0f;
|
base._inputManager.fingerSpreadRightMiddle = 0f;
|
||||||
|
|
||||||
base._inputManager.finger1StretchedRightRing = 0.5f;
|
base._inputManager.finger1StretchedRightRing = 0f;
|
||||||
base._inputManager.finger2StretchedRightRing = 0.7f;
|
base._inputManager.finger2StretchedRightRing = 0f;
|
||||||
base._inputManager.finger3StretchedRightRing = 0.7f;
|
base._inputManager.finger3StretchedRightRing = 0f;
|
||||||
base._inputManager.fingerSpreadRightRing = 0f;
|
base._inputManager.fingerSpreadRightRing = 0f;
|
||||||
|
|
||||||
base._inputManager.finger1StretchedRightPinky = 0.5f;
|
base._inputManager.finger1StretchedRightPinky = 0f;
|
||||||
base._inputManager.finger2StretchedRightPinky = 0.7f;
|
base._inputManager.finger2StretchedRightPinky = 0f;
|
||||||
base._inputManager.finger3StretchedRightPinky = 0.7f;
|
base._inputManager.finger3StretchedRightPinky = 0f;
|
||||||
base._inputManager.fingerSpreadRightPinky = 0f;
|
base._inputManager.fingerSpreadRightPinky = 0f;
|
||||||
|
|
||||||
base._inputManager.fingerFullCurlNormalizedRightThumb = 0f;
|
base._inputManager.fingerFullCurlNormalizedRightThumb = 0f;
|
||||||
|
|
|
@ -24,6 +24,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ml_pin", "ml_pin\ml_pin.csp
|
||||||
EndProject
|
EndProject
|
||||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ml_dht", "ml_dht\ml_dht.csproj", "{31987392-989C-40C1-A48B-7F6099816EBE}"
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ml_dht", "ml_dht\ml_dht.csproj", "{31987392-989C-40C1-A48B-7F6099816EBE}"
|
||||||
EndProject
|
EndProject
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ml_bft", "ml_bft\ml_bft.csproj", "{331C995D-9648-44AD-8B02-D5F3A89FDC1F}"
|
||||||
|
EndProject
|
||||||
Global
|
Global
|
||||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
Debug|x64 = Debug|x64
|
Debug|x64 = Debug|x64
|
||||||
|
@ -60,6 +62,9 @@ Global
|
||||||
{31987392-989C-40C1-A48B-7F6099816EBE}.Debug|x64.Build.0 = Debug|x64
|
{31987392-989C-40C1-A48B-7F6099816EBE}.Debug|x64.Build.0 = Debug|x64
|
||||||
{31987392-989C-40C1-A48B-7F6099816EBE}.Release|x64.ActiveCfg = Release|x64
|
{31987392-989C-40C1-A48B-7F6099816EBE}.Release|x64.ActiveCfg = Release|x64
|
||||||
{31987392-989C-40C1-A48B-7F6099816EBE}.Release|x64.Build.0 = Release|x64
|
{31987392-989C-40C1-A48B-7F6099816EBE}.Release|x64.Build.0 = Release|x64
|
||||||
|
{331C995D-9648-44AD-8B02-D5F3A89FDC1F}.Debug|x64.ActiveCfg = Debug|x64
|
||||||
|
{331C995D-9648-44AD-8B02-D5F3A89FDC1F}.Release|x64.ActiveCfg = Release|x64
|
||||||
|
{331C995D-9648-44AD-8B02-D5F3A89FDC1F}.Release|x64.Build.0 = Release|x64
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
GlobalSection(SolutionProperties) = preSolution
|
GlobalSection(SolutionProperties) = preSolution
|
||||||
HideSolutionNode = FALSE
|
HideSolutionNode = FALSE
|
||||||
|
|
|
@ -11,8 +11,8 @@
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||||
<DebugType>none</DebugType>
|
<DebugType>embedded</DebugType>
|
||||||
<DebugSymbols>false</DebugSymbols>
|
<DebugSymbols>true</DebugSymbols>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|
|
@ -10,6 +10,11 @@
|
||||||
<Version>1.0.2</Version>
|
<Version>1.0.2</Version>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||||
|
<DebugType>embedded</DebugType>
|
||||||
|
<DebugSymbols>true</DebugSymbols>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<None Remove="resources\Chime.wav" />
|
<None Remove="resources\Chime.wav" />
|
||||||
<None Remove="resources\DoorClose.wav" />
|
<None Remove="resources\DoorClose.wav" />
|
||||||
|
|
|
@ -10,6 +10,11 @@
|
||||||
<Version>1.0.5</Version>
|
<Version>1.0.5</Version>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||||
|
<DebugType>embedded</DebugType>
|
||||||
|
<DebugSymbols>true</DebugSymbols>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
<Target Name="PostBuild" AfterTargets="PostBuildEvent">
|
<Target Name="PostBuild" AfterTargets="PostBuildEvent">
|
||||||
<Exec Command="copy /y "$(TargetPath)" "D:\Games\Steam\steamapps\common\ChilloutVR\Mods\"" />
|
<Exec Command="copy /y "$(TargetPath)" "D:\Games\Steam\steamapps\common\ChilloutVR\Mods\"" />
|
||||||
</Target>
|
</Target>
|
||||||
|
|
|
@ -10,6 +10,11 @@
|
||||||
<Product>PlayerRagdollMod</Product>
|
<Product>PlayerRagdollMod</Product>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||||
|
<DebugType>embedded</DebugType>
|
||||||
|
<DebugSymbols>true</DebugSymbols>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<None Remove="PlayerRagdollMod.json" />
|
<None Remove="PlayerRagdollMod.json" />
|
||||||
<None Remove="resources\person.png" />
|
<None Remove="resources\person.png" />
|
||||||
|
|
|
@ -10,6 +10,11 @@
|
||||||
<Product>ViveExtendedInput</Product>
|
<Product>ViveExtendedInput</Product>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||||
|
<DebugType>embedded</DebugType>
|
||||||
|
<DebugSymbols>true</DebugSymbols>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<None Remove="PlayerRagdollMod.json" />
|
<None Remove="PlayerRagdollMod.json" />
|
||||||
<None Remove="resources\mod_menu.js" />
|
<None Remove="resources\mod_menu.js" />
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue