mirror of
https://github.com/SDraw/ml_mods_cvr.git
synced 2026-06-25 07:48:25 +00:00
Archived BetterFingerTracking
This commit is contained in:
parent
aa8def3192
commit
92357d3076
16 changed files with 0 additions and 0 deletions
BIN
archived/ml_bft/.github/img_01.png
vendored
Normal file
BIN
archived/ml_bft/.github/img_01.png
vendored
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 306 KiB |
89
archived/ml_bft/AssetsHandler.cs
Normal file
89
archived/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
|
||||
{
|
||||
readonly static string ms_namespace = typeof(AssetsHandler).Namespace;
|
||||
|
||||
static readonly List<string> ms_assets = new List<string>()
|
||||
{
|
||||
"ovr_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();
|
||||
|
||||
foreach(string l_assetName in ms_assets)
|
||||
{
|
||||
try
|
||||
{
|
||||
Stream l_assetStream = l_assembly.GetManifestResourceStream(ms_namespace + ".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();
|
||||
}
|
||||
}
|
||||
}
|
||||
358
archived/ml_bft/FingerSystem.cs
Normal file
358
archived/ml_bft/FingerSystem.cs
Normal file
|
|
@ -0,0 +1,358 @@
|
|||
using ABI.CCK.Components;
|
||||
using ABI_RC.Core.Player;
|
||||
using ABI_RC.Core.Savior;
|
||||
using ABI_RC.Systems.GameEventSystem;
|
||||
using ABI_RC.Systems.IK;
|
||||
using ABI_RC.Systems.InputManagement;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace ml_bft
|
||||
{
|
||||
class FingerSystem
|
||||
{
|
||||
enum PlaneType
|
||||
{
|
||||
OXZ,
|
||||
OYX
|
||||
}
|
||||
|
||||
struct RotationOffset
|
||||
{
|
||||
public Transform m_target;
|
||||
public Transform m_source;
|
||||
public Quaternion m_offset;
|
||||
|
||||
public void Reset()
|
||||
{
|
||||
m_source = null;
|
||||
m_target = null;
|
||||
m_offset = Quaternion.identity;
|
||||
}
|
||||
}
|
||||
|
||||
static readonly HumanBodyBones[] ms_leftFingerBones =
|
||||
{
|
||||
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 HumanBodyBones[] ms_rightFingerBones =
|
||||
{
|
||||
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
|
||||
};
|
||||
static readonly (HumanBodyBones, HumanBodyBones, bool)[] ms_fingersChains =
|
||||
{
|
||||
(HumanBodyBones.LeftThumbProximal,HumanBodyBones.LeftThumbIntermediate,true), (HumanBodyBones.LeftThumbIntermediate, HumanBodyBones.LeftThumbDistal,true), (HumanBodyBones.LeftThumbDistal,HumanBodyBones.LastBone,true),
|
||||
(HumanBodyBones.LeftIndexProximal,HumanBodyBones.LeftIndexIntermediate,true), (HumanBodyBones.LeftIndexIntermediate, HumanBodyBones.LeftIndexDistal,true), (HumanBodyBones.LeftIndexDistal,HumanBodyBones.LastBone,true),
|
||||
(HumanBodyBones.LeftMiddleProximal,HumanBodyBones.LeftMiddleIntermediate,true), (HumanBodyBones.LeftMiddleIntermediate, HumanBodyBones.LeftMiddleDistal,true), (HumanBodyBones.LeftMiddleDistal,HumanBodyBones.LastBone,true),
|
||||
(HumanBodyBones.LeftRingProximal,HumanBodyBones.LeftRingIntermediate,true), (HumanBodyBones.LeftRingIntermediate, HumanBodyBones.LeftRingDistal,true), (HumanBodyBones.LeftRingDistal,HumanBodyBones.LastBone,true),
|
||||
(HumanBodyBones.LeftLittleProximal,HumanBodyBones.LeftLittleIntermediate,true), (HumanBodyBones.LeftLittleIntermediate, HumanBodyBones.LeftLittleDistal,true), (HumanBodyBones.LeftLittleDistal,HumanBodyBones.LastBone,true),
|
||||
(HumanBodyBones.RightThumbProximal,HumanBodyBones.RightThumbIntermediate,false), (HumanBodyBones.RightThumbIntermediate, HumanBodyBones.RightThumbDistal,false), (HumanBodyBones.RightThumbDistal,HumanBodyBones.LastBone,false),
|
||||
(HumanBodyBones.RightIndexProximal,HumanBodyBones.RightIndexIntermediate,false), (HumanBodyBones.RightIndexIntermediate, HumanBodyBones.RightIndexDistal,false), (HumanBodyBones.RightIndexDistal,HumanBodyBones.LastBone,false),
|
||||
(HumanBodyBones.RightMiddleProximal,HumanBodyBones.RightMiddleIntermediate,false), (HumanBodyBones.RightMiddleIntermediate, HumanBodyBones.RightMiddleDistal,false), (HumanBodyBones.RightMiddleDistal,HumanBodyBones.LastBone,false),
|
||||
(HumanBodyBones.RightRingProximal,HumanBodyBones.RightRingIntermediate,false), (HumanBodyBones.RightRingIntermediate, HumanBodyBones.RightRingDistal,false), (HumanBodyBones.RightRingDistal,HumanBodyBones.LastBone,false),
|
||||
(HumanBodyBones.RightLittleProximal,HumanBodyBones.RightLittleIntermediate,false), (HumanBodyBones.RightLittleIntermediate, HumanBodyBones.RightLittleDistal,false),(HumanBodyBones.RightLittleDistal,HumanBodyBones.LastBone,false),
|
||||
};
|
||||
|
||||
static readonly Vector3[] ms_directions =
|
||||
{
|
||||
Vector3.forward,
|
||||
Vector3.back,
|
||||
Vector3.left,
|
||||
Vector3.right,
|
||||
Vector3.up,
|
||||
Vector3.down,
|
||||
};
|
||||
|
||||
public static 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];
|
||||
|
||||
CVRGameEventSystem.Avatar.OnLocalAvatarLoad.AddListener(this.OnAvatarSetup);
|
||||
CVRGameEventSystem.Avatar.OnLocalAvatarClear.AddListener(this.OnAvatarClear);
|
||||
GameEvents.OnAvatarReuse.AddListener(this.OnAvatarReuse);
|
||||
GameEvents.OnIKSystemLateUpdate.AddListener(this.OnIKSystemLateUpdate);
|
||||
}
|
||||
internal void Cleanup()
|
||||
{
|
||||
if(Instance == this)
|
||||
Instance = null;
|
||||
|
||||
m_leftFingerOffsets.Clear();
|
||||
m_rightFingerOffsets.Clear();
|
||||
m_ready = false;
|
||||
|
||||
CVRGameEventSystem.Avatar.OnLocalAvatarLoad.RemoveListener(this.OnAvatarSetup);
|
||||
CVRGameEventSystem.Avatar.OnLocalAvatarClear.RemoveListener(this.OnAvatarClear);
|
||||
GameEvents.OnAvatarReuse.RemoveListener(this.OnAvatarReuse);
|
||||
GameEvents.OnIKSystemLateUpdate.RemoveListener(this.OnIKSystemLateUpdate);
|
||||
}
|
||||
|
||||
internal void OnAvatarSetup(CVRAvatar p_avatar)
|
||||
{
|
||||
try
|
||||
{
|
||||
Animator l_animator = PlayerSetup.Instance.Animator;
|
||||
if(l_animator.isHuman)
|
||||
{
|
||||
IKSystem.Instance.SetAvatarPose(IKSystem.AvatarPose.TPose);
|
||||
PlayerSetup.Instance.AvatarTransform.localPosition = Vector3.zero;
|
||||
PlayerSetup.Instance.AvatarTransform.localRotation = Quaternion.identity;
|
||||
|
||||
InputHandler.Instance.Rebind(PlayerSetup.Instance.transform.rotation);
|
||||
foreach(var l_tuple in ms_fingersChains)
|
||||
{
|
||||
ReorientateTowards(
|
||||
PlayerSetup.Instance.transform,
|
||||
l_animator.GetBoneTransform(l_tuple.Item1),
|
||||
(l_tuple.Item2 != HumanBodyBones.LastBone) ? l_animator.GetBoneTransform(l_tuple.Item2) : null,
|
||||
InputHandler.Instance.GetSourceForBone(l_tuple.Item1, l_tuple.Item3),
|
||||
InputHandler.Instance.GetSourceForBone(l_tuple.Item2, l_tuple.Item3),
|
||||
PlaneType.OXZ
|
||||
);
|
||||
ReorientateTowards(
|
||||
PlayerSetup.Instance.transform,
|
||||
l_animator.GetBoneTransform(l_tuple.Item1),
|
||||
(l_tuple.Item2 != HumanBodyBones.LastBone) ? l_animator.GetBoneTransform(l_tuple.Item2) : null,
|
||||
InputHandler.Instance.GetSourceForBone(l_tuple.Item1, l_tuple.Item3),
|
||||
InputHandler.Instance.GetSourceForBone(l_tuple.Item2, l_tuple.Item3),
|
||||
PlaneType.OYX
|
||||
);
|
||||
}
|
||||
|
||||
// Bind hands
|
||||
m_leftHandOffset.m_source = l_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 = l_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;
|
||||
|
||||
// Bind fingers
|
||||
foreach(HumanBodyBones p_bone in ms_leftFingerBones)
|
||||
{
|
||||
Transform l_avatarBone = l_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 = l_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));
|
||||
}
|
||||
}
|
||||
catch(System.Exception e)
|
||||
{
|
||||
MelonLoader.MelonLogger.Error(e);
|
||||
}
|
||||
}
|
||||
|
||||
internal void OnAvatarClear(CVRAvatar p_avatar)
|
||||
{
|
||||
try
|
||||
{
|
||||
m_ready = false;
|
||||
m_pose = new HumanPose();
|
||||
|
||||
m_leftHandOffset.Reset();
|
||||
m_rightHandOffset.Reset();
|
||||
|
||||
m_leftFingerOffsets.Clear();
|
||||
m_rightFingerOffsets.Clear();
|
||||
}
|
||||
catch(System.Exception e)
|
||||
{
|
||||
MelonLoader.MelonLogger.Error(e);
|
||||
}
|
||||
}
|
||||
|
||||
internal void OnAvatarReuse()
|
||||
{
|
||||
OnAvatarClear(PlayerSetup.Instance.AvatarDescriptor);
|
||||
OnAvatarSetup(PlayerSetup.Instance.AvatarDescriptor);
|
||||
}
|
||||
|
||||
internal void OnIKSystemLateUpdate(HumanPoseHandler p_handler, Transform p_hips)
|
||||
{
|
||||
if(m_ready && MetaPort.Instance.isUsingVr && (p_handler != null) && Settings.SkeletalInput)
|
||||
{
|
||||
if(CVRInputManager.Instance.IsLeftControllerTracking())
|
||||
{
|
||||
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.IsRightControllerTracking())
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
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];
|
||||
|
||||
if(Settings.MechanimFilter && (p_hips != null))
|
||||
{
|
||||
// Yoinked from IKSystem.OnPostSolverUpdateGeneral
|
||||
Vector3 l_pos = p_hips.position;
|
||||
Quaternion l_rot = p_hips.rotation;
|
||||
p_handler.SetHumanPose(ref m_pose);
|
||||
p_hips.SetPositionAndRotation(l_pos, l_rot);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void ReorientateTowards(Transform root, Transform p_source, Transform p_sourceEnd, Transform p_target, Transform p_targetEnd, PlaneType p_plane)
|
||||
{
|
||||
if((root != null) && (p_target != null) && (p_source != null))
|
||||
{
|
||||
Quaternion l_rootInv = Quaternion.Inverse(root.rotation);
|
||||
Vector3 l_targetDir = l_rootInv * (((p_targetEnd != null) ? p_targetEnd.position : GuessEnd(p_target)) - p_target.position);
|
||||
Vector3 l_sourceDir = l_rootInv * (((p_sourceEnd != null) ? p_sourceEnd.position : GuessEnd(p_source)) - p_source.position);
|
||||
switch(p_plane)
|
||||
{
|
||||
case PlaneType.OXZ:
|
||||
l_targetDir.y = 0f;
|
||||
l_sourceDir.y = 0f;
|
||||
break;
|
||||
case PlaneType.OYX:
|
||||
l_targetDir.z = 0f;
|
||||
l_sourceDir.z = 0f;
|
||||
break;
|
||||
}
|
||||
l_targetDir = Vector3.Normalize(l_targetDir);
|
||||
l_sourceDir = Vector3.Normalize(l_sourceDir);
|
||||
|
||||
Quaternion l_targetRot = Quaternion.identity;
|
||||
Quaternion l_sourceRot = Quaternion.identity;
|
||||
switch(p_plane)
|
||||
{
|
||||
case PlaneType.OXZ:
|
||||
l_targetRot = Quaternion.LookRotation(l_targetDir, Vector3.up);
|
||||
l_sourceRot = Quaternion.LookRotation(l_sourceDir, Vector3.up);
|
||||
break;
|
||||
case PlaneType.OYX:
|
||||
l_targetRot = Quaternion.LookRotation(l_targetDir, Vector3.forward);
|
||||
l_sourceRot = Quaternion.LookRotation(l_sourceDir, Vector3.forward);
|
||||
break;
|
||||
}
|
||||
|
||||
Quaternion l_diff = Quaternion.Inverse(l_targetRot) * l_sourceRot;
|
||||
if(p_plane == PlaneType.OYX)
|
||||
l_diff = Quaternion.Euler(0f, 0f, l_diff.eulerAngles.y);
|
||||
|
||||
Quaternion l_adjusted = l_diff * (l_rootInv * p_target.rotation);
|
||||
p_target.rotation = root.rotation * l_adjusted;
|
||||
}
|
||||
}
|
||||
|
||||
static Vector3 GuessEnd(Transform p_target)
|
||||
{
|
||||
Vector3 l_result = p_target.position;
|
||||
if(p_target.parent != null)
|
||||
{
|
||||
float l_dot = -1f;
|
||||
Vector3 l_axisDir = p_target.position - p_target.parent.position;
|
||||
foreach(Vector3 l_dir in ms_directions)
|
||||
{
|
||||
Vector3 l_rotDir = p_target.rotation * l_dir;
|
||||
float l_stepDot = Vector3.Dot(l_rotDir, l_axisDir);
|
||||
if(l_stepDot >= l_dot)
|
||||
{
|
||||
l_dot = l_stepDot;
|
||||
l_result = p_target.position + l_rotDir;
|
||||
}
|
||||
}
|
||||
}
|
||||
return l_result;
|
||||
}
|
||||
}
|
||||
}
|
||||
95
archived/ml_bft/GameEvents.cs
Normal file
95
archived/ml_bft/GameEvents.cs
Normal file
|
|
@ -0,0 +1,95 @@
|
|||
using ABI_RC.Core.Player;
|
||||
using ABI_RC.Systems.IK;
|
||||
using ABI_RC.Systems.InputManagement;
|
||||
using System;
|
||||
using System.Reflection;
|
||||
using UnityEngine;
|
||||
|
||||
namespace ml_bft
|
||||
{
|
||||
static class GameEvents
|
||||
{
|
||||
internal class GameEvent
|
||||
{
|
||||
event Action m_action;
|
||||
public void AddListener(Action p_listener) => m_action += p_listener;
|
||||
public void RemoveListener(Action p_listener) => m_action -= p_listener;
|
||||
public void Invoke() => m_action?.Invoke();
|
||||
}
|
||||
internal class GameEvent<T1, T2>
|
||||
{
|
||||
event Action<T1, T2> m_action;
|
||||
public void AddListener(Action<T1, T2> p_listener) => m_action += p_listener;
|
||||
public void RemoveListener(Action<T1, T2> p_listener) => m_action -= p_listener;
|
||||
public void Invoke(T1 p_objA, T2 p_objB) => m_action?.Invoke(p_objA, p_objB);
|
||||
}
|
||||
|
||||
public static readonly GameEvent OnAvatarReuse = new GameEvent();
|
||||
public static readonly GameEvent OnInputUpdate = new GameEvent();
|
||||
public static readonly GameEvent<HumanPoseHandler, Transform> OnIKSystemLateUpdate = new GameEvent<HumanPoseHandler, Transform>();
|
||||
|
||||
internal static void Init(HarmonyLib.Harmony p_instance)
|
||||
{
|
||||
try
|
||||
{
|
||||
p_instance.Patch(
|
||||
typeof(IKSystem).GetMethod(nameof(IKSystem.ReinitializeAvatar), BindingFlags.Instance | BindingFlags.Public),
|
||||
null,
|
||||
new HarmonyLib.HarmonyMethod(typeof(GameEvents).GetMethod(nameof(OnAvatarReinitialize_Postfix), BindingFlags.Static | BindingFlags.NonPublic))
|
||||
);
|
||||
|
||||
p_instance.Patch(
|
||||
typeof(CVRInputManager).GetMethod("UpdateInput", BindingFlags.Instance | BindingFlags.NonPublic),
|
||||
null,
|
||||
new HarmonyLib.HarmonyMethod(typeof(GameEvents).GetMethod(nameof(OnInputUpdate_Postfix), BindingFlags.Static | BindingFlags.NonPublic))
|
||||
);
|
||||
|
||||
p_instance.Patch(
|
||||
typeof(IKSystem).GetMethod("LateUpdate", BindingFlags.Instance | BindingFlags.NonPublic),
|
||||
null,
|
||||
new HarmonyLib.HarmonyMethod(typeof(GameEvents).GetMethod(nameof(OnIKSystemLateUpdate_Postfix), BindingFlags.Static | BindingFlags.NonPublic))
|
||||
);
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
MelonLoader.MelonLogger.Error(e);
|
||||
}
|
||||
}
|
||||
|
||||
static void OnAvatarReinitialize_Postfix()
|
||||
{
|
||||
try
|
||||
{
|
||||
OnAvatarReuse.Invoke();
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
MelonLoader.MelonLogger.Error(e);
|
||||
}
|
||||
}
|
||||
|
||||
static void OnInputUpdate_Postfix()
|
||||
{
|
||||
try
|
||||
{
|
||||
OnInputUpdate.Invoke();
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
MelonLoader.MelonLogger.Error(e);
|
||||
}
|
||||
}
|
||||
|
||||
static void OnIKSystemLateUpdate_Postfix(HumanPoseHandler ____humanPoseHandler, Transform ____hipTransform)
|
||||
{
|
||||
try
|
||||
{
|
||||
OnIKSystemLateUpdate.Invoke(____humanPoseHandler, ____hipTransform);
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
MelonLoader.MelonLogger.Error(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
286
archived/ml_bft/HandHandlerVR.cs
Normal file
286
archived/ml_bft/HandHandlerVR.cs
Normal file
|
|
@ -0,0 +1,286 @@
|
|||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using Valve.VR;
|
||||
|
||||
namespace ml_bft
|
||||
{
|
||||
class HandHandlerVR
|
||||
{
|
||||
// 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;
|
||||
|
||||
readonly bool m_left = false;
|
||||
readonly List<Transform> m_bones = null;
|
||||
readonly List<Quaternion> m_localRotations = null;
|
||||
Transform m_prefabRoot = null;
|
||||
readonly List<Renderer> m_renderers = null;
|
||||
|
||||
SteamVR_Action_Skeleton m_skeletonAction;
|
||||
|
||||
public HandHandlerVR(Transform p_root, bool p_left)
|
||||
{
|
||||
m_left = p_left;
|
||||
m_bones = new List<Transform>();
|
||||
m_localRotations = new List<Quaternion>();
|
||||
m_renderers = new List<Renderer>();
|
||||
|
||||
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_VR]";
|
||||
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
|
||||
char l_side = (m_left ? 'l' : 'r');
|
||||
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}", l_side));
|
||||
m_bones[(int)SteamVR_Skeleton_JointIndexEnum.thumbProximal] = m_prefabRoot.Find(string.Format("Root/wrist_{0}/finger_thumb_0_{0}", l_side));
|
||||
m_bones[(int)SteamVR_Skeleton_JointIndexEnum.thumbMiddle] = m_prefabRoot.Find(string.Format("Root/wrist_{0}/finger_thumb_0_{0}/finger_thumb_1_{0}", l_side));
|
||||
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}", l_side));
|
||||
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", l_side));
|
||||
|
||||
m_bones[(int)SteamVR_Skeleton_JointIndexEnum.indexMetacarpal] = m_prefabRoot.Find(string.Format("Root/wrist_{0}/finger_index_meta_{0}", l_side));
|
||||
m_bones[(int)SteamVR_Skeleton_JointIndexEnum.indexProximal] = m_prefabRoot.Find(string.Format("Root/wrist_{0}/finger_index_meta_{0}/finger_index_0_{0}", l_side));
|
||||
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}", l_side));
|
||||
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}", l_side));
|
||||
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", l_side));
|
||||
|
||||
m_bones[(int)SteamVR_Skeleton_JointIndexEnum.middleMetacarpal] = m_prefabRoot.Find(string.Format("Root/wrist_{0}/finger_middle_meta_{0}", l_side));
|
||||
m_bones[(int)SteamVR_Skeleton_JointIndexEnum.middleProximal] = m_prefabRoot.Find(string.Format("Root/wrist_{0}/finger_middle_meta_{0}/finger_middle_0_{0}", l_side));
|
||||
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}", l_side));
|
||||
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}", l_side));
|
||||
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", l_side));
|
||||
|
||||
m_bones[(int)SteamVR_Skeleton_JointIndexEnum.ringMetacarpal] = m_prefabRoot.Find(string.Format("Root/wrist_{0}/finger_ring_meta_{0}", l_side));
|
||||
m_bones[(int)SteamVR_Skeleton_JointIndexEnum.ringProximal] = m_prefabRoot.Find(string.Format("Root/wrist_{0}/finger_ring_meta_{0}/finger_ring_0_{0}", l_side));
|
||||
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}", l_side));
|
||||
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}", l_side));
|
||||
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", l_side));
|
||||
|
||||
m_bones[(int)SteamVR_Skeleton_JointIndexEnum.pinkyMetacarpal] = m_prefabRoot.Find(string.Format("Root/wrist_{0}/finger_pinky_meta_{0}", l_side));
|
||||
m_bones[(int)SteamVR_Skeleton_JointIndexEnum.pinkyProximal] = m_prefabRoot.Find(string.Format("Root/wrist_{0}/finger_pinky_meta_{0}/finger_pinky_0_{0}", l_side));
|
||||
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}", l_side));
|
||||
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}", l_side));
|
||||
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", l_side));
|
||||
|
||||
m_bones[(int)SteamVR_Skeleton_JointIndexEnum.thumbAux] = m_prefabRoot.Find(string.Format("Root/finger_thumb_{0}_aux", l_side));
|
||||
m_bones[(int)SteamVR_Skeleton_JointIndexEnum.indexAux] = m_prefabRoot.Find(string.Format("Root/finger_index_{0}_aux", l_side));
|
||||
m_bones[(int)SteamVR_Skeleton_JointIndexEnum.middleAux] = m_prefabRoot.Find(string.Format("Root/finger_middle_{0}_aux", l_side));
|
||||
m_bones[(int)SteamVR_Skeleton_JointIndexEnum.ringAux] = m_prefabRoot.Find(string.Format("Root/finger_ring_{0}_aux", l_side));
|
||||
m_bones[(int)SteamVR_Skeleton_JointIndexEnum.pinkyAux] = m_prefabRoot.Find(string.Format("Root/finger_pinky_{0}_aux", l_side));
|
||||
|
||||
// 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");
|
||||
|
||||
OnShowHandsChanged(Settings.ShowHands);
|
||||
OnMotionRangeChanged(Settings.MotionRange);
|
||||
|
||||
Settings.OnSkeletalInputChanged.AddListener(this.OnSkeletalInputChanged);
|
||||
Settings.OnShowHandsChanged.AddListener(this.OnShowHandsChanged);
|
||||
Settings.OnMotionRangeChanged.AddListener(this.OnMotionRangeChanged);
|
||||
}
|
||||
|
||||
public void Cleanup()
|
||||
{
|
||||
if(m_prefabRoot != null)
|
||||
Object.Destroy(m_prefabRoot.gameObject);
|
||||
m_prefabRoot = null;
|
||||
|
||||
m_bones.Clear();
|
||||
m_localRotations.Clear();
|
||||
m_renderers.Clear();
|
||||
|
||||
m_skeletonAction = null;
|
||||
|
||||
Settings.OnSkeletalInputChanged.RemoveListener(this.OnSkeletalInputChanged);
|
||||
Settings.OnShowHandsChanged.RemoveListener(this.OnShowHandsChanged);
|
||||
Settings.OnMotionRangeChanged.RemoveListener(this.OnMotionRangeChanged);
|
||||
}
|
||||
|
||||
public 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 Transform GetSourceForBone(HumanBodyBones p_bone)
|
||||
{
|
||||
Transform l_result = null;
|
||||
switch(p_bone)
|
||||
{
|
||||
case HumanBodyBones.LeftHand:
|
||||
l_result = (m_left ? m_bones[(int)SteamVR_Skeleton_JointIndexEnum.wrist] : null);
|
||||
break;
|
||||
case HumanBodyBones.LeftThumbProximal:
|
||||
l_result = (m_left ? m_bones[(int)SteamVR_Skeleton_JointIndexEnum.thumbProximal] : null);
|
||||
break;
|
||||
case HumanBodyBones.LeftThumbIntermediate:
|
||||
l_result = (m_left ? m_bones[(int)SteamVR_Skeleton_JointIndexEnum.thumbMiddle] : null);
|
||||
break;
|
||||
case HumanBodyBones.LeftThumbDistal:
|
||||
l_result = (m_left ? m_bones[(int)SteamVR_Skeleton_JointIndexEnum.thumbDistal] : null);
|
||||
break;
|
||||
|
||||
case HumanBodyBones.LeftIndexProximal:
|
||||
l_result = (m_left ? m_bones[(int)SteamVR_Skeleton_JointIndexEnum.indexProximal] : null);
|
||||
break;
|
||||
case HumanBodyBones.LeftIndexIntermediate:
|
||||
l_result = (m_left ? m_bones[(int)SteamVR_Skeleton_JointIndexEnum.indexMiddle] : null);
|
||||
break;
|
||||
case HumanBodyBones.LeftIndexDistal:
|
||||
l_result = (m_left ? m_bones[(int)SteamVR_Skeleton_JointIndexEnum.indexDistal] : null);
|
||||
break;
|
||||
|
||||
case HumanBodyBones.LeftMiddleProximal:
|
||||
l_result = (m_left ? m_bones[(int)SteamVR_Skeleton_JointIndexEnum.middleProximal] : null);
|
||||
break;
|
||||
case HumanBodyBones.LeftMiddleIntermediate:
|
||||
l_result = (m_left ? m_bones[(int)SteamVR_Skeleton_JointIndexEnum.middleMiddle] : null);
|
||||
break;
|
||||
case HumanBodyBones.LeftMiddleDistal:
|
||||
l_result = (m_left ? m_bones[(int)SteamVR_Skeleton_JointIndexEnum.middleDistal] : null);
|
||||
break;
|
||||
|
||||
case HumanBodyBones.LeftRingProximal:
|
||||
l_result = (m_left ? m_bones[(int)SteamVR_Skeleton_JointIndexEnum.ringProximal] : null);
|
||||
break;
|
||||
case HumanBodyBones.LeftRingIntermediate:
|
||||
l_result = (m_left ? m_bones[(int)SteamVR_Skeleton_JointIndexEnum.ringMiddle] : null);
|
||||
break;
|
||||
case HumanBodyBones.LeftRingDistal:
|
||||
l_result = (m_left ? m_bones[(int)SteamVR_Skeleton_JointIndexEnum.ringDistal] : null);
|
||||
break;
|
||||
|
||||
case HumanBodyBones.LeftLittleProximal:
|
||||
l_result = (m_left ? m_bones[(int)SteamVR_Skeleton_JointIndexEnum.pinkyProximal] : null);
|
||||
break;
|
||||
case HumanBodyBones.LeftLittleIntermediate:
|
||||
l_result = (m_left ? m_bones[(int)SteamVR_Skeleton_JointIndexEnum.pinkyMiddle] : null);
|
||||
break;
|
||||
case HumanBodyBones.LeftLittleDistal:
|
||||
l_result = (m_left ? m_bones[(int)SteamVR_Skeleton_JointIndexEnum.pinkyDistal] : null);
|
||||
break;
|
||||
|
||||
case HumanBodyBones.RightHand:
|
||||
l_result = (!m_left ? m_bones[(int)SteamVR_Skeleton_JointIndexEnum.wrist] : null);
|
||||
break;
|
||||
case HumanBodyBones.RightThumbProximal:
|
||||
l_result = (!m_left ? m_bones[(int)SteamVR_Skeleton_JointIndexEnum.thumbProximal] : null);
|
||||
break;
|
||||
case HumanBodyBones.RightThumbIntermediate:
|
||||
l_result = (!m_left ? m_bones[(int)SteamVR_Skeleton_JointIndexEnum.thumbMiddle] : null);
|
||||
break;
|
||||
case HumanBodyBones.RightThumbDistal:
|
||||
l_result = (!m_left ? m_bones[(int)SteamVR_Skeleton_JointIndexEnum.thumbDistal] : null);
|
||||
break;
|
||||
|
||||
case HumanBodyBones.RightIndexProximal:
|
||||
l_result = (!m_left ? m_bones[(int)SteamVR_Skeleton_JointIndexEnum.indexProximal] : null);
|
||||
break;
|
||||
case HumanBodyBones.RightIndexIntermediate:
|
||||
l_result = (!m_left ? m_bones[(int)SteamVR_Skeleton_JointIndexEnum.indexMiddle] : null);
|
||||
break;
|
||||
case HumanBodyBones.RightIndexDistal:
|
||||
l_result = (!m_left ? m_bones[(int)SteamVR_Skeleton_JointIndexEnum.indexDistal] : null);
|
||||
break;
|
||||
|
||||
case HumanBodyBones.RightMiddleProximal:
|
||||
l_result = (!m_left ? m_bones[(int)SteamVR_Skeleton_JointIndexEnum.middleProximal] : null);
|
||||
break;
|
||||
case HumanBodyBones.RightMiddleIntermediate:
|
||||
l_result = (!m_left ? m_bones[(int)SteamVR_Skeleton_JointIndexEnum.middleMiddle] : null);
|
||||
break;
|
||||
case HumanBodyBones.RightMiddleDistal:
|
||||
l_result = (!m_left ? m_bones[(int)SteamVR_Skeleton_JointIndexEnum.middleDistal] : null);
|
||||
break;
|
||||
|
||||
case HumanBodyBones.RightRingProximal:
|
||||
l_result = (!m_left ? m_bones[(int)SteamVR_Skeleton_JointIndexEnum.ringProximal] : null);
|
||||
break;
|
||||
case HumanBodyBones.RightRingIntermediate:
|
||||
l_result = (!m_left ? m_bones[(int)SteamVR_Skeleton_JointIndexEnum.ringMiddle] : null);
|
||||
break;
|
||||
case HumanBodyBones.RightRingDistal:
|
||||
l_result = (!m_left ? m_bones[(int)SteamVR_Skeleton_JointIndexEnum.ringDistal] : null);
|
||||
break;
|
||||
|
||||
case HumanBodyBones.RightLittleProximal:
|
||||
l_result = (!m_left ? m_bones[(int)SteamVR_Skeleton_JointIndexEnum.pinkyProximal] : null);
|
||||
break;
|
||||
case HumanBodyBones.RightLittleIntermediate:
|
||||
l_result = (!m_left ? m_bones[(int)SteamVR_Skeleton_JointIndexEnum.pinkyMiddle] : null);
|
||||
break;
|
||||
case HumanBodyBones.RightLittleDistal:
|
||||
l_result = (!m_left ? m_bones[(int)SteamVR_Skeleton_JointIndexEnum.pinkyDistal] : null);
|
||||
break;
|
||||
}
|
||||
return l_result;
|
||||
}
|
||||
|
||||
public 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, -90f) : Quaternion.Euler(0f, 90f, 90f));
|
||||
}
|
||||
|
||||
// Settings
|
||||
void OnSkeletalInputChanged(bool p_state)
|
||||
{
|
||||
OnShowHandsChanged(Settings.ShowHands);
|
||||
}
|
||||
|
||||
void OnShowHandsChanged(bool p_state)
|
||||
{
|
||||
foreach(var l_render in m_renderers)
|
||||
{
|
||||
if(l_render != null)
|
||||
l_render.enabled = (Settings.SkeletalInput && p_state);
|
||||
}
|
||||
}
|
||||
|
||||
void OnMotionRangeChanged(Settings.MotionRangeType p_mode)
|
||||
{
|
||||
switch(p_mode)
|
||||
{
|
||||
case Settings.MotionRangeType.WithController:
|
||||
m_skeletonAction?.SetRangeOfMotion(EVRSkeletalMotionRange.WithController);
|
||||
break;
|
||||
case Settings.MotionRangeType.WithoutController:
|
||||
m_skeletonAction?.SetRangeOfMotion(EVRSkeletalMotionRange.WithoutController);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
159
archived/ml_bft/InputHandler.cs
Normal file
159
archived/ml_bft/InputHandler.cs
Normal file
|
|
@ -0,0 +1,159 @@
|
|||
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;
|
||||
|
||||
HandHandlerVR m_leftHandHandler = null;
|
||||
HandHandlerVR m_rightHandHandler = null;
|
||||
|
||||
internal InputHandler()
|
||||
{
|
||||
if(Instance == null)
|
||||
Instance = this;
|
||||
|
||||
m_active = false;
|
||||
|
||||
if(MetaPort.Instance.isUsingVr)
|
||||
SetupHandlers();
|
||||
|
||||
VRModeSwitchEvents.OnCompletedVRModeSwitch.AddListener(this.OnVRModeSwitch);
|
||||
|
||||
Settings.OnSkeletalInputChanged.AddListener(this.OnSkeletalInputChanged);
|
||||
|
||||
GameEvents.OnInputUpdate.AddListener(this.OnInputUpdate);
|
||||
}
|
||||
internal void Cleanup()
|
||||
{
|
||||
if(Instance == this)
|
||||
Instance = null;
|
||||
|
||||
RemoveHandlers();
|
||||
|
||||
VRModeSwitchEvents.OnCompletedVRModeSwitch.RemoveListener(this.OnVRModeSwitch);
|
||||
|
||||
Settings.OnSkeletalInputChanged.RemoveListener(this.OnSkeletalInputChanged);
|
||||
|
||||
GameEvents.OnInputUpdate.RemoveListener(this.OnInputUpdate);
|
||||
}
|
||||
|
||||
void SetupHandlers()
|
||||
{
|
||||
if(!CheckVR.Instance.forceOpenXr)
|
||||
{
|
||||
m_leftHandHandler = new HandHandlerVR(CVRInputManager.Instance.leftHandTransform, true);
|
||||
m_rightHandHandler = new HandHandlerVR(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 OnVRModeSwitch(bool p_state)
|
||||
{
|
||||
try
|
||||
{
|
||||
if(Utils.IsInVR())
|
||||
SetupHandlers();
|
||||
else
|
||||
RemoveHandlers();
|
||||
}
|
||||
catch(System.Exception e)
|
||||
{
|
||||
MelonLoader.MelonLogger.Error(e);
|
||||
}
|
||||
}
|
||||
|
||||
// Settings
|
||||
void OnSkeletalInputChanged(bool p_value)
|
||||
{
|
||||
if(!p_value)
|
||||
CVRInputManager.Instance.individualFingerTracking = Utils.AreKnucklesInUse();
|
||||
}
|
||||
}
|
||||
}
|
||||
40
archived/ml_bft/Main.cs
Normal file
40
archived/ml_bft/Main.cs
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
using System.Collections;
|
||||
|
||||
namespace ml_bft
|
||||
{
|
||||
public class BetterFingersTracking : MelonLoader.MelonMod
|
||||
{
|
||||
InputHandler m_inputHandler = null;
|
||||
FingerSystem m_fingerSystem = null;
|
||||
|
||||
public override void OnInitializeMelon()
|
||||
{
|
||||
AssetsHandler.Load();
|
||||
GameEvents.Init(HarmonyInstance);
|
||||
}
|
||||
|
||||
public override void OnLateInitializeMelon()
|
||||
{
|
||||
Settings.Init();
|
||||
MelonLoader.MelonCoroutines.Start(WaitForInstances());
|
||||
}
|
||||
|
||||
IEnumerator WaitForInstances()
|
||||
{
|
||||
while(ABI_RC.Systems.InputManagement.CVRInputManager.Instance == null)
|
||||
yield return null;
|
||||
|
||||
m_inputHandler = new InputHandler();
|
||||
m_fingerSystem = new FingerSystem();
|
||||
}
|
||||
|
||||
public override void OnDeinitializeMelon()
|
||||
{
|
||||
m_inputHandler?.Cleanup();
|
||||
m_inputHandler = null;
|
||||
|
||||
m_fingerSystem?.Cleanup();
|
||||
m_fingerSystem = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
4
archived/ml_bft/Properties/AssemblyInfo.cs
Normal file
4
archived/ml_bft/Properties/AssemblyInfo.cs
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
[assembly: MelonLoader.MelonInfo(typeof(ml_bft.BetterFingersTracking), "BetterFingersTracking", "1.1.4", "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)]
|
||||
22
archived/ml_bft/README.md
Normal file
22
archived/ml_bft/README.md
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
# 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 `BetterFingersTracking.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
|
||||
* **Motion range:** fingers tracking motion range/mode/type; `With controller` by default
|
||||
* **Filter humanoid limits:** Limits fingers rotations to be valid for Unity's Mechanim; `true` by default
|
||||
* Note: Enabling this option ensures that visual representation of your fingers will be same for you and remote players, but it cancels out additional finger segments rotations that can be better visually in most cases.
|
||||
* **Show hands model:** shows transparent hands model (mostly as debug option); `false` by default
|
||||
* **Change fingers direction at bind:** tries to allign avatar's fingers for more accurate poses; `true` by default
|
||||
|
||||
# Notes
|
||||
* Currently supports only SteamVR environment, OpenXR support is planned.
|
||||
* Fingers tracking quality is highly dependant on avatar's hand state in Unity's T-pose, possible solutions are in search.
|
||||
* For Oculus Quest controllers (all versions) be sure that skeleton bindings are properly set up in SteamVR controllers bindings.
|
||||
<kbd></kbd>
|
||||
30
archived/ml_bft/ResourcesHandler.cs
Normal file
30
archived/ml_bft/ResourcesHandler.cs
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
using System;
|
||||
using System.IO;
|
||||
using System.Reflection;
|
||||
|
||||
namespace ml_bft
|
||||
{
|
||||
static class ResourcesHandler
|
||||
{
|
||||
readonly static string ms_namespace = typeof(ResourcesHandler).Namespace;
|
||||
|
||||
public static string GetEmbeddedResource(string p_name)
|
||||
{
|
||||
string l_result = "";
|
||||
Assembly l_assembly = Assembly.GetExecutingAssembly();
|
||||
|
||||
try
|
||||
{
|
||||
Stream l_libraryStream = l_assembly.GetManifestResourceStream(ms_namespace + ".resources." + p_name);
|
||||
StreamReader l_streadReader = new StreamReader(l_libraryStream);
|
||||
l_result = l_streadReader.ReadToEnd();
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
MelonLoader.MelonLogger.Error(e);
|
||||
}
|
||||
|
||||
return l_result;
|
||||
}
|
||||
}
|
||||
}
|
||||
158
archived/ml_bft/Settings.cs
Normal file
158
archived/ml_bft/Settings.cs
Normal file
|
|
@ -0,0 +1,158 @@
|
|||
using ABI_RC.Core.InteractionSystem;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace ml_bft
|
||||
{
|
||||
static class Settings
|
||||
{
|
||||
internal class SettingEvent<T>
|
||||
{
|
||||
event Action<T> m_action;
|
||||
public void AddListener(Action<T> p_listener) => m_action += p_listener;
|
||||
public void RemoveListener(Action<T> p_listener) => m_action -= p_listener;
|
||||
public void Invoke(T p_value) => m_action?.Invoke(p_value);
|
||||
}
|
||||
|
||||
public enum MotionRangeType
|
||||
{
|
||||
WithController = 0,
|
||||
WithoutController
|
||||
}
|
||||
enum ModSetting
|
||||
{
|
||||
SkeletalInput = 0,
|
||||
MotionRange,
|
||||
ShowHands,
|
||||
MechanimFilter
|
||||
}
|
||||
|
||||
public static bool SkeletalInput { get; private set; } = false;
|
||||
public static MotionRangeType MotionRange { get; private set; } = MotionRangeType.WithController;
|
||||
public static bool ShowHands { get; private set; } = false;
|
||||
public static bool MechanimFilter { get; private set; } = true;
|
||||
|
||||
static MelonLoader.MelonPreferences_Category ms_category = null;
|
||||
static List<MelonLoader.MelonPreferences_Entry> ms_entries = null;
|
||||
|
||||
public static readonly SettingEvent<bool> OnSkeletalInputChanged = new SettingEvent<bool>();
|
||||
public static readonly SettingEvent<MotionRangeType> OnMotionRangeChanged = new SettingEvent<MotionRangeType>();
|
||||
public static readonly SettingEvent<bool> OnShowHandsChanged = new SettingEvent<bool>();
|
||||
public static readonly SettingEvent<bool> OnMechanimFilterChanged = new SettingEvent<bool>();
|
||||
|
||||
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.MotionRange.ToString(), (int)MotionRange),
|
||||
ms_category.CreateEntry(ModSetting.ShowHands.ToString(), ShowHands),
|
||||
ms_category.CreateEntry(ModSetting.MechanimFilter.ToString(), MechanimFilter)
|
||||
};
|
||||
|
||||
SkeletalInput = (bool)ms_entries[(int)ModSetting.SkeletalInput].BoxedValue;
|
||||
MotionRange = (MotionRangeType)(int)ms_entries[(int)ModSetting.MotionRange].BoxedValue;
|
||||
ShowHands = (bool)ms_entries[(int)ModSetting.ShowHands].BoxedValue;
|
||||
MechanimFilter = (bool)ms_entries[(int)ModSetting.MechanimFilter].BoxedValue;
|
||||
|
||||
MelonLoader.MelonCoroutines.Start(WaitMainMenuUi());
|
||||
}
|
||||
|
||||
static System.Collections.IEnumerator WaitMainMenuUi()
|
||||
{
|
||||
while(ViewManager.Instance == null)
|
||||
yield return null;
|
||||
while(ViewManager.Instance.cohtmlView == null)
|
||||
yield return null;
|
||||
while(ViewManager.Instance.cohtmlView.Listener == null)
|
||||
yield return null;
|
||||
|
||||
ViewManager.Instance.cohtmlView.Listener.ReadyForBindings += () =>
|
||||
{
|
||||
ViewManager.Instance.cohtmlView.View.BindCall("OnToggleUpdate_" + ms_category.Identifier, new Action<string, string>(OnToggleUpdate));
|
||||
ViewManager.Instance.cohtmlView.View.BindCall("OnDropdownUpdate_" + ms_category.Identifier, new Action<string, string>(OnDropdownUpdate));
|
||||
};
|
||||
ViewManager.Instance.cohtmlView.Listener.FinishLoad += (_) =>
|
||||
{
|
||||
ViewManager.Instance.cohtmlView.View.ExecuteScript(ResourcesHandler.GetEmbeddedResource("mods_extension.js"));
|
||||
ViewManager.Instance.cohtmlView.View.ExecuteScript(ResourcesHandler.GetEmbeddedResource("mod_menu.js"));
|
||||
MelonLoader.MelonCoroutines.Start(UpdateMenuSettings());
|
||||
};
|
||||
}
|
||||
|
||||
static System.Collections.IEnumerator UpdateMenuSettings()
|
||||
{
|
||||
while(!ViewManager.Instance.IsReady || !ViewManager.Instance.IsViewShown)
|
||||
yield return null;
|
||||
|
||||
foreach(var l_entry in ms_entries)
|
||||
ViewManager.Instance.cohtmlView.View.TriggerEvent("updateModSetting", ms_category.Identifier, l_entry.DisplayName, l_entry.GetValueAsString());
|
||||
}
|
||||
|
||||
static void OnToggleUpdate(string p_name, string p_value)
|
||||
{
|
||||
try
|
||||
{
|
||||
if(Enum.TryParse(p_name, out ModSetting l_setting) && bool.TryParse(p_value, out bool l_value))
|
||||
{
|
||||
switch(l_setting)
|
||||
{
|
||||
case ModSetting.SkeletalInput:
|
||||
{
|
||||
SkeletalInput = l_value;
|
||||
OnSkeletalInputChanged.Invoke(SkeletalInput);
|
||||
}
|
||||
break;
|
||||
|
||||
case ModSetting.ShowHands:
|
||||
{
|
||||
ShowHands = l_value;
|
||||
OnShowHandsChanged.Invoke(ShowHands);
|
||||
}
|
||||
break;
|
||||
|
||||
case ModSetting.MechanimFilter:
|
||||
{
|
||||
MechanimFilter = l_value;
|
||||
OnMechanimFilterChanged.Invoke(MechanimFilter);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
ms_entries[(int)l_setting].BoxedValue = l_value;
|
||||
}
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
MelonLoader.MelonLogger.Error(e);
|
||||
}
|
||||
}
|
||||
|
||||
static void OnDropdownUpdate(string p_name, string p_value)
|
||||
{
|
||||
try
|
||||
{
|
||||
if(Enum.TryParse(p_name, out ModSetting l_setting) && int.TryParse(p_value, out int l_value))
|
||||
{
|
||||
switch(l_setting)
|
||||
{
|
||||
case ModSetting.MotionRange:
|
||||
{
|
||||
MotionRange = (MotionRangeType)l_value;
|
||||
OnMotionRangeChanged.Invoke(MotionRange);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
ms_entries[(int)l_setting].BoxedValue = l_value;
|
||||
}
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
MelonLoader.MelonLogger.Error(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
21
archived/ml_bft/Utils.cs
Normal file
21
archived/ml_bft/Utils.cs
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
using ABI_RC.Core.Player;
|
||||
using ABI_RC.Core.Savior;
|
||||
using ABI_RC.Core.UI;
|
||||
using ABI_RC.Systems.IK;
|
||||
using ABI_RC.Systems.InputManagement;
|
||||
using System.Reflection;
|
||||
using UnityEngine;
|
||||
|
||||
namespace ml_bft
|
||||
{
|
||||
static class Utils
|
||||
{
|
||||
static readonly FieldInfo ms_view = typeof(CohtmlControlledViewWrapper).GetField("_view", BindingFlags.Instance | BindingFlags.NonPublic);
|
||||
|
||||
public static void ExecuteScript(this CohtmlControlledViewWrapper p_instance, string p_script) => (ms_view?.GetValue(p_instance) as cohtml.Net.View)?.ExecuteScript(p_script);
|
||||
|
||||
public static bool IsInVR() => ((MetaPort.Instance != null) && MetaPort.Instance.isUsingVr);
|
||||
|
||||
public static bool AreKnucklesInUse() => ((CVRInputManager.Instance._leftController == ABI_RC.Systems.InputManagement.XR.eXRControllerType.Index) || (CVRInputManager.Instance._rightController == ABI_RC.Systems.InputManagement.XR.eXRControllerType.Index));
|
||||
}
|
||||
}
|
||||
100
archived/ml_bft/ml_bft.csproj
Normal file
100
archived/ml_bft/ml_bft.csproj
Normal file
|
|
@ -0,0 +1,100 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>netstandard2.1</TargetFramework>
|
||||
<Platforms>x64</Platforms>
|
||||
<PackageId>BetterFingersTracking</PackageId>
|
||||
<Authors>SDraw</Authors>
|
||||
<Company>SDraw</Company>
|
||||
<Product>BetterFingersTracking</Product>
|
||||
<Version>1.1.4</Version>
|
||||
<AssemblyName>BetterFingersTracking</AssemblyName>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<DebugType>embedded</DebugType>
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<EmbeddedResource Include="resources/mod_menu.js" />
|
||||
<EmbeddedResource Include="resources/ovr_fingers.asset" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<EmbeddedResource Include="../js/mods_extension.js" Link="resources/mods_extension.js" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Reference Include="0Harmony">
|
||||
<HintPath>$(CVRPath)/MelonLoader/net35/0Harmony.dll</HintPath>
|
||||
<Private>false</Private>
|
||||
<SpecificVersion>false</SpecificVersion>
|
||||
</Reference>
|
||||
<Reference Include="Assembly-CSharp">
|
||||
<HintPath>$(CVRPath)/ChilloutVR_Data/Managed/Assembly-CSharp.dll</HintPath>
|
||||
<Private>false</Private>
|
||||
<SpecificVersion>false</SpecificVersion>
|
||||
</Reference>
|
||||
<Reference Include="cohtml.Net">
|
||||
<HintPath>$(CVRPath)/ChilloutVR_Data/Managed/cohtml.Net.dll</HintPath>
|
||||
<SpecificVersion>false</SpecificVersion>
|
||||
<Private>false</Private>
|
||||
</Reference>
|
||||
<Reference Include="Cohtml.Runtime">
|
||||
<HintPath>$(CVRPath)/ChilloutVR_Data/Managed/Cohtml.Runtime.dll</HintPath>
|
||||
<SpecificVersion>false</SpecificVersion>
|
||||
<Private>false</Private>
|
||||
</Reference>
|
||||
<Reference Include="MelonLoader">
|
||||
<HintPath>$(CVRPath)/MelonLoader/net35/MelonLoader.dll</HintPath>
|
||||
<Private>false</Private>
|
||||
<SpecificVersion>false</SpecificVersion>
|
||||
</Reference>
|
||||
<Reference Include="SteamVR">
|
||||
<HintPath>$(CVRPath)/ChilloutVR_Data/Managed/SteamVR.dll</HintPath>
|
||||
<Private>false</Private>
|
||||
<SpecificVersion>false</SpecificVersion>
|
||||
</Reference>
|
||||
<Reference Include="Unity.XR.Hands">
|
||||
<HintPath>$(CVRPath)/ChilloutVR_Data/Managed/Unity.XR.Hands.dll</HintPath>
|
||||
<SpecificVersion>false</SpecificVersion>
|
||||
<Private>false</Private>
|
||||
</Reference>
|
||||
<Reference Include="Unity.XR.OpenVR">
|
||||
<HintPath>$(CVRPath)/ChilloutVR_Data/Managed/Unity.XR.OpenVR.dll</HintPath>
|
||||
<SpecificVersion>false</SpecificVersion>
|
||||
<Private>false</Private>
|
||||
</Reference>
|
||||
<Reference Include="Unity.XR.OpenXR">
|
||||
<HintPath>$(CVRPath)/ChilloutVR_Data/Managed/Unity.XR.OpenXR.dll</HintPath>
|
||||
<SpecificVersion>false</SpecificVersion>
|
||||
<Private>false</Private>
|
||||
</Reference>
|
||||
<Reference Include="UnityEngine.AnimationModule">
|
||||
<HintPath>$(CVRPath)/ChilloutVR_Data/Managed/UnityEngine.AnimationModule.dll</HintPath>
|
||||
<SpecificVersion>false</SpecificVersion>
|
||||
<Private>false</Private>
|
||||
</Reference>
|
||||
<Reference Include="UnityEngine.AssetBundleModule">
|
||||
<HintPath>$(CVRPath)/ChilloutVR_Data/Managed/UnityEngine.AssetBundleModule.dll</HintPath>
|
||||
<SpecificVersion>false</SpecificVersion>
|
||||
<Private>false</Private>
|
||||
</Reference>
|
||||
<Reference Include="UnityEngine.CoreModule">
|
||||
<HintPath>$(CVRPath)/ChilloutVR_Data/Managed/UnityEngine.CoreModule.dll</HintPath>
|
||||
<SpecificVersion>false</SpecificVersion>
|
||||
<Private>false</Private>
|
||||
</Reference>
|
||||
<Reference Include="UnityEngine.XRModule">
|
||||
<HintPath>$(CVRPath)/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)" "$(CVRPath)/Mods/"" />
|
||||
</Target>
|
||||
|
||||
</Project>
|
||||
46
archived/ml_bft/resources/mod_menu.js
Normal file
46
archived/ml_bft/resources/mod_menu.js
Normal file
|
|
@ -0,0 +1,46 @@
|
|||
{
|
||||
let l_block = document.createElement('div');
|
||||
l_block.innerHTML = `
|
||||
<div class ="settings-subcategory">
|
||||
<div class ="subcategory-name">Better Fingers 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">Motion range: </div>
|
||||
<div class ="option-input">
|
||||
<div id="MotionRange" class ="inp_dropdown no-scroll" data-options="0:With controller,1:Without controller" data-current="0"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class ="row-wrapper">
|
||||
<div class ="option-caption">Filter humanoid limits: </div>
|
||||
<div class ="option-input">
|
||||
<div id="MechanimFilter" class ="inp_toggle no-scroll" data-current="true"></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'));
|
||||
|
||||
// Dropdowns
|
||||
for (let l_dropdown of l_block.querySelectorAll('.inp_dropdown'))
|
||||
modsExtension.addSetting('BFT', l_dropdown.id, modsExtension.createDropdown(l_dropdown, 'OnDropdownUpdate_BFT'));
|
||||
}
|
||||
BIN
archived/ml_bft/resources/ovr_fingers.asset
Normal file
BIN
archived/ml_bft/resources/ovr_fingers.asset
Normal file
Binary file not shown.
BIN
archived/ml_bft/resources/oxr_fingers.asset
Normal file
BIN
archived/ml_bft/resources/oxr_fingers.asset
Normal file
Binary file not shown.
Loading…
Add table
Add a link
Reference in a new issue