[EzCurls] Initial tests

This commit is contained in:
NotAKidoS 2023-07-10 09:58:31 -05:00
parent 686a06fab1
commit 623df261b0
7 changed files with 294 additions and 0 deletions

2
EzCurls/EzCurls.csproj Normal file
View file

@ -0,0 +1,2 @@
<?xml version="1.0" encoding="utf-8"?>
<Project Sdk="Microsoft.NET.Sdk"/>

View file

@ -0,0 +1,141 @@
using ABI_RC.Core.Savior;
using ABI_RC.Systems.IK.SubSystems;
namespace NAK.EzCurls;
internal class InputModuleCurlAdjuster : CVRInputModule
{
public static InputModuleCurlAdjuster Instance;
// Curl clamping/adjustment
public bool UseCurlSnapping = false;
public float SnappedCurlValue = 0.5f;
public float RangeStartPercent = 0.5f;
public float RangeEndPercent = 0.8f;
// Curl smoothing/averaging
public bool UseCurlSmoothing = false;
public bool DontSmoothExtremes = true;
public float CurlSimilarityThreshold = 0.5f;
public float CurlSmoothingFactor = 0.5f;
public new void Start()
{
Instance = this;
base.Start();
EzCurls.OnSettingsChanged();
}
public override void UpdateInput() => DoCurlAdjustments();
public override void UpdateImportantInput() => DoCurlAdjustments();
private void DoCurlAdjustments()
{
if (!_inputManager.individualFingerTracking)
return;
if (UseCurlSmoothing)
{
SmoothCurls(
ref _inputManager.fingerCurlLeftIndex,
ref _inputManager.fingerCurlLeftMiddle,
ref _inputManager.fingerCurlLeftRing,
ref _inputManager.fingerCurlLeftPinky
);
SmoothCurls(
ref _inputManager.fingerCurlRightIndex,
ref _inputManager.fingerCurlRightMiddle,
ref _inputManager.fingerCurlRightRing,
ref _inputManager.fingerCurlRightPinky
);
}
if (UseCurlSnapping)
{
SnapCurls(ref _inputManager.fingerCurlLeftIndex);
SnapCurls(ref _inputManager.fingerCurlLeftMiddle);
SnapCurls(ref _inputManager.fingerCurlLeftRing);
SnapCurls(ref _inputManager.fingerCurlLeftPinky);
SnapCurls(ref _inputManager.fingerCurlRightIndex);
SnapCurls(ref _inputManager.fingerCurlRightMiddle);
SnapCurls(ref _inputManager.fingerCurlRightRing);
SnapCurls(ref _inputManager.fingerCurlRightPinky);
}
}
private void SnapCurls(ref float fingerCurl)
{
if (fingerCurl >= RangeStartPercent && fingerCurl <= RangeEndPercent)
fingerCurl = SnappedCurlValue;
}
private void SmoothCurls(ref float index, ref float middle, ref float ring, ref float pinky)
{
List<float> values = new List<float> { index, middle, ring, pinky };
for (int i = 0; i < values.Count; i++)
{
for (int j = i + 1; j < values.Count; j++)
{
if (Math.Abs(values[i] - values[j]) <= CurlSimilarityThreshold)
{
// Compute new smoothed values
float smoothedValue = (values[i] + values[j]) / 2;
// Calculate smoothing factors for both values
float smoothingFactor1 = CalculateSmoothingFactor(values[i]);
float smoothingFactor2 = CalculateSmoothingFactor(values[j]);
// Adjust both values towards the smoothed value
values[i] = values[i] + smoothingFactor1 * CurlSmoothingFactor * (smoothedValue - values[i]);
values[j] = values[j] + smoothingFactor2 * CurlSmoothingFactor * (smoothedValue - values[j]);
}
}
}
index = values[0];
middle = values[1];
ring = values[2];
pinky = values[3];
}
private void SmoothCurlsNear(ref float index, ref float middle, ref float ring, ref float pinky)
{
List<float> values = new List<float> { index, middle, ring, pinky };
for (int i = 0; i < values.Count - 1; i++)
{
if (Math.Abs(values[i] - values[i + 1]) <= CurlSimilarityThreshold)
{
// Compute new smoothed value
float smoothedValue = (values[i] + values[i + 1]) / 2;
// Calculate smoothing factors for both values
float smoothingFactor1 = CalculateSmoothingFactor(values[i]);
float smoothingFactor2 = CalculateSmoothingFactor(values[i + 1]);
// Adjust both values towards the smoothed value
values[i] = values[i] + smoothingFactor1 * CurlSmoothingFactor * (smoothedValue - values[i]);
values[i + 1] = values[i + 1] + smoothingFactor2 * CurlSmoothingFactor * (smoothedValue - values[i + 1]);
}
}
index = values[0];
middle = values[1];
ring = values[2];
pinky = values[3];
}
// calculate the smoothing factor based on the curl value
private float CalculateSmoothingFactor(float curlValue)
{
if (!DontSmoothExtremes)
return 1f;
// Compute the distance from the center (0.5) and square it
float dist = curlValue - 0.5f;
return 1.0f - 4 * dist * dist;
}
}

79
EzCurls/Main.cs Normal file
View file

@ -0,0 +1,79 @@
using ABI_RC.Core.Savior;
using MelonLoader;
using System.Reflection;
namespace NAK.EzCurls;
public class EzCurls : MelonMod
{
internal const string SettingsCategory = nameof(EzCurls);
public static readonly MelonPreferences_Category Category =
MelonPreferences.CreateCategory(SettingsCategory);
public static readonly MelonPreferences_Entry<bool> EntryUseCurlSnapping =
Category.CreateEntry("UseCurlSnapping", true,
description: "Finger curl snapping to a specified value when in the specified range.");
public static readonly MelonPreferences_Entry<float> EntrySnappedCurlValue =
Category.CreateEntry("SnappedCurlValue", 0.5f,
description: "The value to which the finger curl snaps within the range.");
public static readonly MelonPreferences_Entry<float> EntryRangeStartPercent =
Category.CreateEntry("RangeStartPercent", 0.5f,
description: "The minimum value for the SnappedCurlValue range.");
public static readonly MelonPreferences_Entry<float> EntryRangeEndPercent =
Category.CreateEntry("RangeEndPercent", 0.8f,
description: "The maximum value for the SnappedCurlValue range.");
public static readonly MelonPreferences_Entry<bool> EntryUseCurlSmoothing =
Category.CreateEntry("UseCurlSmoothing", false,
description: "Finger curl smoothing to average out similar finger positions.");
public static readonly MelonPreferences_Entry<bool> EntryDontSmoothExtremes =
Category.CreateEntry("DontSmoothExtremes", true,
description: "Should the finger curl smoothing be less effective on curls towards 0 or 1?");
public static readonly MelonPreferences_Entry<float> EntryCurlSimilarityThreshold =
Category.CreateEntry("CurlSimilarityThreshold", 0.1f,
description: "The threshold for curl similarity during curl smoothing.");
public static readonly MelonPreferences_Entry<float> EntryCurlSmoothingFactor =
Category.CreateEntry("CurlSmoothingFactor", 0.5f,
description: "The multiplier for curl smoothing.");
public override void OnInitializeMelon()
{
HarmonyInstance.Patch(
typeof(InputModuleSteamVR).GetMethod(nameof(InputModuleSteamVR.Start)),
prefix: new HarmonyLib.HarmonyMethod(typeof(EzCurls).GetMethod(nameof(OnInputModuleSteamVRStart_Prefix), BindingFlags.NonPublic | BindingFlags.Static))
);
foreach (MelonPreferences_Entry setting in Category.Entries)
setting.OnEntryValueChangedUntyped.Subscribe(OnSettingsChanged);
}
public static void OnSettingsChanged(object oldValue = null, object newValue = null)
{
if (InputModuleCurlAdjuster.Instance == null)
return;
// curl snapping
InputModuleCurlAdjuster.Instance.UseCurlSnapping = EntryUseCurlSnapping.Value;
InputModuleCurlAdjuster.Instance.SnappedCurlValue = EntrySnappedCurlValue.Value;
InputModuleCurlAdjuster.Instance.RangeStartPercent = EntryRangeStartPercent.Value;
InputModuleCurlAdjuster.Instance.RangeEndPercent = EntryRangeEndPercent.Value;
// curl smoothing
InputModuleCurlAdjuster.Instance.UseCurlSmoothing = EntryUseCurlSmoothing.Value;
InputModuleCurlAdjuster.Instance.DontSmoothExtremes = EntryDontSmoothExtremes.Value;
InputModuleCurlAdjuster.Instance.CurlSimilarityThreshold = EntryCurlSimilarityThreshold.Value;
InputModuleCurlAdjuster.Instance.CurlSmoothingFactor = EntryCurlSmoothingFactor.Value;
}
private static void OnInputModuleSteamVRStart_Prefix(ref InputModuleSteamVR __instance)
{
__instance.gameObject.AddComponent<InputModuleCurlAdjuster>();
}
}

View file

@ -0,0 +1,29 @@
using MelonLoader;
using NAK.EzCurls.Properties;
using System.Reflection;
[assembly: AssemblyVersion(AssemblyInfoParams.Version)]
[assembly: AssemblyFileVersion(AssemblyInfoParams.Version)]
[assembly: AssemblyInformationalVersion(AssemblyInfoParams.Version)]
[assembly: AssemblyTitle(nameof(NAK.EzCurls))]
[assembly: AssemblyCompany(AssemblyInfoParams.Author)]
[assembly: AssemblyProduct(nameof(NAK.EzCurls))]
[assembly: MelonInfo(
typeof(NAK.EzCurls.EzCurls),
nameof(NAK.EzCurls),
AssemblyInfoParams.Version,
AssemblyInfoParams.Author,
downloadLink: "https://github.com/NotAKidOnSteam/NAK_CVR_Mods/tree/main/EzCurls"
)]
[assembly: MelonGame("Alpha Blend Interactive", "ChilloutVR")]
[assembly: MelonPlatform(MelonPlatformAttribute.CompatiblePlatforms.WINDOWS_X64)]
[assembly: MelonPlatformDomain(MelonPlatformDomainAttribute.CompatibleDomains.MONO)]
namespace NAK.EzCurls.Properties;
internal static class AssemblyInfoParams
{
public const string Version = "1.0.0";
public const string Author = "NotAKidoS";
}

14
EzCurls/README.md Normal file
View file

@ -0,0 +1,14 @@
# EzCurls
A mod that should hopefully make finger curls more predictable.
---
Here is the block of text where I tell you this mod is not affiliated or endorsed by ABI.
https://documentation.abinteractive.net/official/legal/tos/#7-modding-our-games
> This mod is an independent creation and is not affiliated with, supported by or approved by Alpha Blend Interactive.
> Use of this mod is done so at the user's own risk and the creator cannot be held responsible for any issues arising from its use.
> To the best of my knowledge, I have adhered to the Modding Guidelines established by Alpha Blend Interactive.

23
EzCurls/format.json Normal file
View file

@ -0,0 +1,23 @@
{
"_id": -1,
"name": "EzCurls",
"modversion": "1.0.0",
"gameversion": "2022r170p1",
"loaderversion": "0.6.1",
"modtype": "Mod",
"author": "NotAKidoS",
"description": "A mod that should hopefully make finger curls more predictable.",
"searchtags": [
"aas",
"sync",
"naked",
"buffer"
],
"requirements": [
"UIExpansionKit"
],
"downloadlink": "https://github.com/NotAKidOnSteam/NAK_CVR_Mods/releases/download/r13/EzCurls.dll",
"sourcelink": "https://github.com/NotAKidOnSteam/NAK_CVR_Mods/tree/main/EzCurls/",
"changelog": "- Initial CVRMG release",
"embedcolor": "7d7d7d"
}

View file

@ -73,6 +73,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "FOVAdjustment", "FOVAdjustm
EndProject EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MuteSFX", "MuteSFX\MuteSFX.csproj", "{77D222FC-4AEC-4672-A87A-B860B4C39E17}" Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MuteSFX", "MuteSFX\MuteSFX.csproj", "{77D222FC-4AEC-4672-A87A-B860B4C39E17}"
EndProject EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "EzCurls", "EzCurls\EzCurls.csproj", "{7EF74A8D-0421-4B6D-809E-40F9C2DFC7F8}"
EndProject
Global Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU Debug|Any CPU = Debug|Any CPU
@ -219,6 +221,10 @@ Global
{77D222FC-4AEC-4672-A87A-B860B4C39E17}.Debug|Any CPU.Build.0 = Debug|Any CPU {77D222FC-4AEC-4672-A87A-B860B4C39E17}.Debug|Any CPU.Build.0 = Debug|Any CPU
{77D222FC-4AEC-4672-A87A-B860B4C39E17}.Release|Any CPU.ActiveCfg = Release|Any CPU {77D222FC-4AEC-4672-A87A-B860B4C39E17}.Release|Any CPU.ActiveCfg = Release|Any CPU
{77D222FC-4AEC-4672-A87A-B860B4C39E17}.Release|Any CPU.Build.0 = Release|Any CPU {77D222FC-4AEC-4672-A87A-B860B4C39E17}.Release|Any CPU.Build.0 = Release|Any CPU
{7EF74A8D-0421-4B6D-809E-40F9C2DFC7F8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{7EF74A8D-0421-4B6D-809E-40F9C2DFC7F8}.Debug|Any CPU.Build.0 = Debug|Any CPU
{7EF74A8D-0421-4B6D-809E-40F9C2DFC7F8}.Release|Any CPU.ActiveCfg = Release|Any CPU
{7EF74A8D-0421-4B6D-809E-40F9C2DFC7F8}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection EndGlobalSection
GlobalSection(SolutionProperties) = preSolution GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE HideSolutionNode = FALSE