using System;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using HarmonyLib;
using Il2CppSLZ.Marrow;
using MelonLoader;
using Microsoft.CodeAnalysis;
using UnityEngine;
using UnityEngine.XR;
using ViveWandThumbFix;
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: MelonInfo(typeof(ThumbFixMod), "Vive Wand Thumb Fix", "1.0.1", "Codex", null)]
[assembly: MelonGame("Stress Level Zero", "BONELAB")]
[assembly: TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName = ".NET 6.0")]
[assembly: AssemblyCompany("ViveWandThumbFix")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("ViveWandThumbFix")]
[assembly: AssemblyTitle("ViveWandThumbFix")]
[assembly: AssemblyVersion("1.0.0.0")]
namespace Microsoft.CodeAnalysis
{
[CompilerGenerated]
[Embedded]
internal sealed class EmbeddedAttribute : Attribute
{
}
}
namespace System.Runtime.CompilerServices
{
[CompilerGenerated]
[Embedded]
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
internal sealed class NullableAttribute : Attribute
{
public readonly byte[] NullableFlags;
public NullableAttribute(byte P_0)
{
NullableFlags = new byte[1] { P_0 };
}
public NullableAttribute(byte[] P_0)
{
NullableFlags = P_0;
}
}
[CompilerGenerated]
[Embedded]
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)]
internal sealed class NullableContextAttribute : Attribute
{
public readonly byte Flag;
public NullableContextAttribute(byte P_0)
{
Flag = P_0;
}
}
}
namespace ViveWandThumbFix
{
public sealed class ThumbFixMod : MelonMod
{
public override void OnInitializeMelon()
{
((MelonBase)this).LoggerInstance.Msg("Active. Vive Wand thumb curl now follows the physical trackpad touch state.");
}
}
internal static class ViveTouchReader
{
private const float AxisFallbackDeadzone = 0.075f;
private static readonly InputFeatureUsage<bool> TouchpadTouchUsage = new InputFeatureUsage<bool>("TouchpadTouch");
private static readonly InputFeatureUsage<bool> TrackpadTouchUsage = new InputFeatureUsage<bool>("TrackpadTouch");
private static bool _announcedLeft;
private static bool _announcedRight;
private static bool _warnedLeft;
private static bool _warnedRight;
internal static bool IsViveWand(OpenController controller)
{
//IL_0001: Unknown result type (might be due to invalid IL or missing references)
//IL_0007: Invalid comparison between Unknown and I4
return (int)((BaseController)controller).Type == 2;
}
internal static bool TryGetTouch(OpenController controller, out bool touched)
{
//IL_0004: Unknown result type (might be due to invalid IL or missing references)
//IL_000a: Invalid comparison between Unknown and I4
//IL_000e: Unknown result type (might be due to invalid IL or missing references)
//IL_0014: Invalid comparison between Unknown and I4
//IL_0026: Unknown result type (might be due to invalid IL or missing references)
//IL_002b: Unknown result type (might be due to invalid IL or missing references)
//IL_002d: Unknown result type (might be due to invalid IL or missing references)
touched = false;
bool flag = (int)((BaseController)controller).handedness == 1;
bool flag2 = (int)((BaseController)controller).handedness == 2;
if (!flag && !flag2)
{
return false;
}
InputDevice deviceAtXRNode = InputDevices.GetDeviceAtXRNode((XRNode)(flag ? 4 : 5));
AnnounceDevice(flag, deviceAtXRNode);
if (((InputDevice)(ref deviceAtXRNode)).isValid && ((InputDevice)(ref deviceAtXRNode)).TryGetFeatureValue(CommonUsages.primary2DAxisTouch, ref touched))
{
return true;
}
if (((InputDevice)(ref deviceAtXRNode)).isValid && (((InputDevice)(ref deviceAtXRNode)).TryGetFeatureValue(TouchpadTouchUsage, ref touched) || ((InputDevice)(ref deviceAtXRNode)).TryGetFeatureValue(TrackpadTouchUsage, ref touched)))
{
return true;
}
Vector2 val = default(Vector2);
if (((InputDevice)(ref deviceAtXRNode)).isValid && ((InputDevice)(ref deviceAtXRNode)).TryGetFeatureValue(CommonUsages.primary2DAxis, ref val))
{
bool flag4 = default(bool);
bool flag3 = ((InputDevice)(ref deviceAtXRNode)).TryGetFeatureValue(CommonUsages.primary2DAxisClick, ref flag4) && flag4;
touched = flag3 || ((Vector2)(ref val)).sqrMagnitude > 0.005625f;
WarnAboutFallback(flag);
return true;
}
WarnAboutFallback(flag);
touched = false;
return true;
}
internal static void Apply(OpenController controller, bool touched)
{
float simThumbAxis = (((BaseController)controller)._processedThumb = (touched ? 1f : 0f));
((BaseController)controller)._simThumbAxis = simThumbAxis;
((BaseController)controller)._isThumbTouch = touched;
((BaseController)controller)._touchPadTouch = touched;
}
private static void AnnounceDevice(bool left, InputDevice device)
{
if (!(left ? _announcedLeft : _announcedRight))
{
if (left)
{
_announcedLeft = true;
}
else
{
_announcedRight = true;
}
MelonLogger.Msg($"Vive Wand {(left ? "left" : "right")} detected: {(((InputDevice)(ref device)).isValid ? ((InputDevice)(ref device)).name : "XR device not ready yet")}.");
}
}
private static void WarnAboutFallback(bool left)
{
if (!(left ? _warnedLeft : _warnedRight))
{
if (left)
{
_warnedLeft = true;
}
else
{
_warnedRight = true;
}
MelonLogger.Warning("No direct trackpad-touch feature for the " + (left ? "left" : "right") + " Wand; using axis/click fallback.");
}
}
}
[HarmonyPatch(typeof(OpenController), "OnUpdate")]
internal static class OpenControllerUpdatePatch
{
[HarmonyPostfix]
private static void Postfix(OpenController __instance)
{
if (ViveTouchReader.IsViveWand(__instance) && ViveTouchReader.TryGetTouch(__instance, out var touched))
{
ViveTouchReader.Apply(__instance, touched);
}
}
}
[HarmonyPatch(typeof(OpenController), "GetThumbCurlAxis")]
internal static class ThumbCurlGetterPatch
{
[HarmonyPostfix]
private static void Postfix(OpenController __instance, ref float __result)
{
if (ViveTouchReader.IsViveWand(__instance) && ViveTouchReader.TryGetTouch(__instance, out var touched))
{
__result = (touched ? 1f : 0f);
}
}
}
[HarmonyPatch(typeof(OpenController), "GetThumbTouch")]
internal static class ThumbTouchGetterPatch
{
[HarmonyPostfix]
private static void Postfix(OpenController __instance, ref bool __result)
{
if (ViveTouchReader.IsViveWand(__instance) && ViveTouchReader.TryGetTouch(__instance, out var touched))
{
__result = touched;
}
}
}
}