Too many changes

This commit is contained in:
SDraw 2024-10-05 15:42:32 +03:00
parent 45557943c4
commit a22e5992d0
No known key found for this signature in database
GPG key ID: BB95B4DAB2BB8BB5
72 changed files with 1064 additions and 927 deletions

View file

@ -7,10 +7,11 @@ 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",
"oxr_fingers.asset"
"ovr_fingers.asset"
};
static readonly Dictionary<string, AssetBundle> ms_loadedAssets = new Dictionary<string, AssetBundle>();
@ -19,13 +20,12 @@ namespace ml_bft
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);
Stream l_assetStream = l_assembly.GetManifestResourceStream(ms_namespace + ".resources." + l_assetName);
if(l_assetStream != null)
{
MemoryStream l_memorySteam = new MemoryStream((int)l_assetStream.Length);

View file

@ -45,18 +45,28 @@ namespace ml_bft
HumanBodyBones.RightRingProximal, HumanBodyBones.RightRingIntermediate, HumanBodyBones.RightRingDistal,
HumanBodyBones.RightLittleProximal, HumanBodyBones.RightLittleIntermediate, HumanBodyBones.RightLittleDistal
};
static readonly (HumanBodyBones, HumanBodyBones, bool)[] ms_rotationFixChains =
static readonly (HumanBodyBones, HumanBodyBones, bool)[] ms_fingersChains =
{
(HumanBodyBones.LeftThumbProximal,HumanBodyBones.LeftThumbIntermediate,true), (HumanBodyBones.LeftThumbIntermediate, HumanBodyBones.LeftThumbDistal,true),
(HumanBodyBones.LeftIndexProximal,HumanBodyBones.LeftIndexIntermediate,true), (HumanBodyBones.LeftIndexIntermediate, HumanBodyBones.LeftIndexDistal,true),
(HumanBodyBones.LeftMiddleProximal,HumanBodyBones.LeftMiddleIntermediate,true), (HumanBodyBones.LeftMiddleIntermediate, HumanBodyBones.LeftMiddleDistal,true),
(HumanBodyBones.LeftRingProximal,HumanBodyBones.LeftRingIntermediate,true), (HumanBodyBones.LeftRingIntermediate, HumanBodyBones.LeftRingDistal,true),
(HumanBodyBones.LeftLittleProximal,HumanBodyBones.LeftLittleIntermediate,true), (HumanBodyBones.LeftLittleIntermediate, HumanBodyBones.LeftLittleDistal,true),
(HumanBodyBones.RightThumbProximal,HumanBodyBones.RightThumbIntermediate,false), (HumanBodyBones.RightThumbIntermediate, HumanBodyBones.RightThumbDistal,false),
(HumanBodyBones.RightIndexProximal,HumanBodyBones.RightIndexIntermediate,false), (HumanBodyBones.RightIndexIntermediate, HumanBodyBones.RightIndexDistal,false),
(HumanBodyBones.RightMiddleProximal,HumanBodyBones.RightMiddleIntermediate,false), (HumanBodyBones.RightMiddleIntermediate, HumanBodyBones.RightMiddleDistal,false),
(HumanBodyBones.RightRingProximal,HumanBodyBones.RightRingIntermediate,false), (HumanBodyBones.RightRingIntermediate, HumanBodyBones.RightRingDistal,false),
(HumanBodyBones.RightLittleProximal,HumanBodyBones.RightLittleIntermediate,false), (HumanBodyBones.RightLittleIntermediate, HumanBodyBones.RightLittleDistal,false)
(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;
@ -104,39 +114,39 @@ namespace ml_bft
internal void OnAvatarSetup()
{
if(PlayerSetup.Instance._animator.isHuman)
Animator l_animator = PlayerSetup.Instance._animator;
if(l_animator.isHuman)
{
Utils.SetAvatarTPose();
InputHandler.Instance.Rebind(PlayerSetup.Instance.transform.rotation);
if(Settings.FixFingers)
foreach(var l_tuple in ms_fingersChains)
{
foreach(var l_tuple in ms_rotationFixChains)
{
ReorientateTowards(
PlayerSetup.Instance._animator.GetBoneTransform(l_tuple.Item1),
PlayerSetup.Instance._animator.GetBoneTransform(l_tuple.Item2),
InputHandler.Instance.GetSourceForBone(l_tuple.Item1, l_tuple.Item3),
InputHandler.Instance.GetSourceForBone(l_tuple.Item2, l_tuple.Item3),
PlaneType.OXZ
);
ReorientateTowards(
PlayerSetup.Instance._animator.GetBoneTransform(l_tuple.Item1),
PlayerSetup.Instance._animator.GetBoneTransform(l_tuple.Item2),
InputHandler.Instance.GetSourceForBone(l_tuple.Item1, l_tuple.Item3),
InputHandler.Instance.GetSourceForBone(l_tuple.Item2, l_tuple.Item3),
PlaneType.OYX
);
}
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 = PlayerSetup.Instance._animator.GetBoneTransform(HumanBodyBones.LeftHand);
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 = PlayerSetup.Instance._animator.GetBoneTransform(HumanBodyBones.RightHand);
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;
@ -144,7 +154,7 @@ namespace ml_bft
// Bind fingers
foreach(HumanBodyBones p_bone in ms_leftFingerBones)
{
Transform l_avatarBone = PlayerSetup.Instance._animator.GetBoneTransform(p_bone);
Transform l_avatarBone = l_animator.GetBoneTransform(p_bone);
Transform l_controllerBone = InputHandler.Instance.GetSourceForBone(p_bone, true);
if((l_avatarBone != null) && (l_controllerBone != null))
{
@ -157,7 +167,7 @@ namespace ml_bft
}
foreach(HumanBodyBones p_bone in ms_rightFingerBones)
{
Transform l_avatarBone = PlayerSetup.Instance._animator.GetBoneTransform(p_bone);
Transform l_avatarBone = l_animator.GetBoneTransform(p_bone);
Transform l_controllerBone = InputHandler.Instance.GetSourceForBone(p_bone, false);
if((l_avatarBone != null) && (l_controllerBone != null))
{
@ -262,13 +272,13 @@ namespace ml_bft
}
}
void ReorientateTowards(Transform p_target, Transform p_targetEnd, Transform p_source, Transform p_sourceEnd, PlaneType p_plane)
static void ReorientateTowards(Transform root, Transform p_source, Transform p_sourceEnd, Transform p_target, Transform p_targetEnd, PlaneType p_plane)
{
if((p_target != null) && (p_targetEnd != null) && (p_source != null) && (p_sourceEnd != null))
if((root != null) && (p_target != null) && (p_source != null))
{
Quaternion l_playerInv = Quaternion.Inverse(PlayerSetup.Instance.transform.rotation);
Vector3 l_targetDir = l_playerInv * (p_targetEnd.position - p_target.position);
Vector3 l_sourceDir = l_playerInv * (p_sourceEnd.position - p_source.position);
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:
@ -301,9 +311,30 @@ namespace ml_bft
if(p_plane == PlaneType.OYX)
l_diff = Quaternion.Euler(0f, 0f, l_diff.eulerAngles.y);
Quaternion l_adjusted = l_diff * (l_playerInv * p_target.rotation);
p_target.rotation = PlayerSetup.Instance.transform.rotation * l_adjusted;
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;
}
}
}

View file

@ -90,6 +90,7 @@ namespace ml_bft
OnShowHandsChanged(Settings.ShowHands);
OnMotionRangeChanged(Settings.MotionRange);
Settings.OnSkeletalInputChanged.AddListener(this.OnSkeletalInputChanged);
Settings.OnShowHandsChanged.AddListener(this.OnShowHandsChanged);
Settings.OnMotionRangeChanged.AddListener(this.OnMotionRangeChanged);
}
@ -106,6 +107,7 @@ namespace ml_bft
m_skeletonAction = null;
Settings.OnSkeletalInputChanged.RemoveListener(this.OnSkeletalInputChanged);
Settings.OnShowHandsChanged.RemoveListener(this.OnShowHandsChanged);
Settings.OnMotionRangeChanged.RemoveListener(this.OnMotionRangeChanged);
}
@ -254,12 +256,17 @@ namespace ml_bft
}
// 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 = p_state;
l_render.enabled = (Settings.SkeletalInput && p_state);
}
}

View file

@ -25,8 +25,7 @@ namespace ml_bft
if(MetaPort.Instance.isUsingVr)
SetupHandlers();
VRModeSwitchEvents.OnInitializeXR.AddListener(this.OnSwitchToVR);
VRModeSwitchEvents.OnDeinitializeXR.AddListener(this.OnSwitchToDesktop);
VRModeSwitchEvents.OnCompletedVRModeSwitch.AddListener(this.OnVRModeSwitch);
Settings.OnSkeletalInputChanged.AddListener(this.OnSkeletalInputChanged);
@ -39,6 +38,8 @@ namespace ml_bft
RemoveHandlers();
VRModeSwitchEvents.OnCompletedVRModeSwitch.RemoveListener(this.OnVRModeSwitch);
Settings.OnSkeletalInputChanged.RemoveListener(this.OnSkeletalInputChanged);
GameEvents.OnInputUpdate.RemoveListener(this.OnInputUpdate);
@ -133,23 +134,14 @@ namespace ml_bft
}
}
void OnSwitchToVR()
void OnVRModeSwitch(bool p_state)
{
try
{
SetupHandlers();
}
catch(System.Exception e)
{
MelonLoader.MelonLogger.Error(e);
}
}
void OnSwitchToDesktop()
{
try
{
RemoveHandlers();
if(Utils.IsInVR())
SetupHandlers();
else
RemoveHandlers();
}
catch(System.Exception e)
{

View file

@ -1,4 +1,4 @@
[assembly: MelonLoader.MelonInfo(typeof(ml_bft.BetterFingersTracking), "BetterFingersTracking", "1.0.5", "SDraw", "https://github.com/SDraw/ml_mods_cvr")]
[assembly: MelonLoader.MelonInfo(typeof(ml_bft.BetterFingersTracking), "BetterFingersTracking", "1.1.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)]

View file

@ -13,7 +13,7 @@ Available mod's settings in `Settings - Input & Key-Bindings - Better Fingers Tr
* **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
* **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.

View file

@ -6,15 +6,16 @@ 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();
string l_assemblyName = l_assembly.GetName().Name;
try
{
Stream l_libraryStream = l_assembly.GetManifestResourceStream(l_assemblyName + ".resources." + p_name);
Stream l_libraryStream = l_assembly.GetManifestResourceStream(ms_namespace + ".resources." + p_name);
StreamReader l_streadReader = new StreamReader(l_libraryStream);
l_result = l_streadReader.ReadToEnd();
}

View file

@ -32,7 +32,6 @@ namespace ml_bft
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;
public static bool FixFingers { get; private set; } = true;
static MelonLoader.MelonPreferences_Category ms_category = null;
static List<MelonLoader.MelonPreferences_Entry> ms_entries = null;
@ -41,7 +40,6 @@ namespace ml_bft
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>();
public static readonly SettingEvent<bool> OnFixFingersChanged = new SettingEvent<bool>();
internal static void Init()
{
@ -52,14 +50,12 @@ namespace ml_bft
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),
ms_category.CreateEntry(ModSetting.FixFingers.ToString(), FixFingers)
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;
FixFingers = (bool)ms_entries[(int)ModSetting.FixFingers].BoxedValue;
MelonLoader.MelonCoroutines.Start(WaitMainMenuUi());
}
@ -115,13 +111,6 @@ namespace ml_bft
OnMechanimFilterChanged.Invoke(MechanimFilter);
}
break;
case ModSetting.FixFingers:
{
FixFingers = l_value;
OnFixFingersChanged.Invoke(FixFingers);
}
break;
}
ms_entries[(int)l_setting].BoxedValue = l_value;

View file

@ -1,4 +1,5 @@
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;
@ -13,6 +14,8 @@ namespace ml_bft
public static void ExecuteScript(this CohtmlControlledViewWrapper p_instance, string p_script) => ((cohtml.Net.View)ms_view.GetValue(p_instance)).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));
public static void SetAvatarTPose()

View file

@ -7,7 +7,7 @@
<Authors>SDraw</Authors>
<Company>SDraw</Company>
<Product>BetterFingersTracking</Product>
<Version>1.0.5</Version>
<Version>1.1.0</Version>
<AssemblyName>BetterFingersTracking</AssemblyName>
</PropertyGroup>

View file

@ -19,13 +19,6 @@
<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">Change fingers direction at bind: </div>
<div class ="option-input">
<div id="FixFingers" class ="inp_toggle no-scroll" data-current="true"></div>
</div>
</div>
<div class ="row-wrapper">
<div class ="option-caption">Filter humanoid limits: </div>