using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.Globalization;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using FistVR;
using HarmonyLib;
using UnityEngine;
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyCompany("quaternion")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyDescription("Configurable H3VR quickbelt slots attached below each hand.")]
[assembly: AssemblyFileVersion("0.4.2.0")]
[assembly: AssemblyInformationalVersion("0.4.2")]
[assembly: AssemblyProduct("quaternion.hqb")]
[assembly: AssemblyTitle("Hand Quickbelts")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("0.4.2.0")]
[module: UnverifiableCode]
namespace BepInEx
{
[AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = false)]
[Conditional("CodeGeneration")]
internal sealed class BepInAutoPluginAttribute : Attribute
{
public BepInAutoPluginAttribute(string id = null, string name = null, string version = null)
{
}
}
}
namespace BepInEx.Preloader.Core.Patching
{
[AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = false)]
[Conditional("CodeGeneration")]
internal sealed class PatcherAutoPluginAttribute : Attribute
{
public PatcherAutoPluginAttribute(string id = null, string name = null, string version = null)
{
}
}
}
namespace HandQuickbelts
{
internal sealed class HandQuickbeltController
{
private const float MillimetersToMeters = 0.001f;
private readonly List<FVRQuickBeltSlot> _slots = new List<FVRQuickBeltSlot>();
private readonly List<FVRQuickBeltSlot> _leftSlots = new List<FVRQuickBeltSlot>();
private readonly List<FVRQuickBeltSlot> _rightSlots = new List<FVRQuickBeltSlot>();
private FVRPlayerBody _body;
private GameObject _leftRoot;
private GameObject _rightRoot;
private HandQuickbeltAdjustmentHandle _leftHandle;
private HandQuickbeltAdjustmentHandle _rightHandle;
private bool _rebuildRequested;
private bool _layoutRequested;
private bool _templateWarningLogged;
private float _nextTemplateLookupTime;
internal void Tick()
{
FVRPlayerBody currentPlayerBody = GM.CurrentPlayerBody;
if (!SceneAllowsQuickbelts(currentPlayerBody))
{
DisableForScene();
}
else if ((Object)(object)_body != (Object)(object)currentPlayerBody || (Object)(object)_leftRoot == (Object)null || (Object)(object)_rightRoot == (Object)null)
{
Rebuild(currentPlayerBody, dropContents: false);
}
else if (_rebuildRequested)
{
_rebuildRequested = false;
_layoutRequested = false;
Rebuild(currentPlayerBody, dropContents: true);
}
else if (_layoutRequested)
{
_layoutRequested = false;
ApplyLayout();
}
}
internal void RebuildAfterQuickbeltChange(FVRPlayerBody body)
{
if (!SceneAllowsQuickbelts(body))
{
DisableForScene();
}
else
{
Rebuild(body, dropContents: false);
}
}
internal void RequestRebuild()
{
_rebuildRequested = true;
}
internal void RequestLayout()
{
_layoutRequested = true;
}
internal void Dispose()
{
RemoveSlots(dropContents: true);
_body = null;
}
private void Rebuild(FVRPlayerBody body, bool dropContents)
{
if (!SceneAllowsQuickbelts(body) || Time.unscaledTime < _nextTemplateLookupTime)
{
return;
}
FVRQuickBeltSlot val = FindTemplate(body);
if ((Object)(object)val == (Object)null)
{
_nextTemplateLookupTime = Time.unscaledTime + 1f;
if (!_templateWarningLogged)
{
_templateWarningLogged = true;
Plugin.Logger.LogWarning((object)"Native spherical quickbelt slots are not ready; retrying once per second.");
}
return;
}
_nextTemplateLookupTime = 0f;
_templateWarningLogged = false;
RemoveSlots(dropContents);
_body = body;
_leftRoot = CreateHandRoot("HQB_LeftHand", body.LeftHand);
_rightRoot = CreateHandRoot("HQB_RightHand", body.RightHand);
_leftHandle = CreateAdjustmentHandle(_leftRoot.transform, isLeftHand: true);
_rightHandle = CreateAdjustmentHandle(_rightRoot.transform, isLeftHand: false);
CreateHandSlots(_leftRoot.transform, _leftSlots, val, Plugin.LeftLargeSlots.Value, Plugin.LeftMediumSlots.Value, Plugin.LeftSmallSlots.Value);
CreateHandSlots(_rightRoot.transform, _rightSlots, val, Plugin.RightLargeSlots.Value, Plugin.RightMediumSlots.Value, Plugin.RightSmallSlots.Value);
ApplyLayout();
Plugin.Logger.LogInfo((object)$"Created {_slots.Count} hand quickbelt slots.");
}
private static bool SceneAllowsQuickbelts(FVRPlayerBody body)
{
if ((Object)(object)body != (Object)null && (Object)(object)body.LeftHand != (Object)null && (Object)(object)body.RightHand != (Object)null && (Object)(object)GM.CurrentSceneSettings != (Object)null)
{
return GM.CurrentSceneSettings.AreQuickbeltSlotsEnabled;
}
return false;
}
private void DisableForScene()
{
if (_slots.Count > 0 || (Object)(object)_leftRoot != (Object)null || (Object)(object)_rightRoot != (Object)null)
{
RemoveSlots(dropContents: true);
Plugin.Logger.LogInfo((object)"Removed hand quickbelt slots because the current scene disables quickbelts.");
}
_body = null;
_rebuildRequested = false;
_layoutRequested = false;
_nextTemplateLookupTime = 0f;
_templateWarningLogged = false;
}
private static GameObject CreateHandRoot(string name, Transform hand)
{
//IL_0029: Unknown result type (might be due to invalid IL or missing references)
//IL_002e: Unknown result type (might be due to invalid IL or missing references)
//IL_003c: Expected O, but got Unknown
FVRViveHand component = ((Component)hand).GetComponent<FVRViveHand>();
Transform val = (((Object)(object)component != (Object)null && (Object)(object)component.PalmTransform != (Object)null) ? component.PalmTransform : hand);
GameObject val2 = new GameObject(name);
val2.transform.SetParent(val, false);
return val2;
}
private static HandQuickbeltAdjustmentHandle CreateAdjustmentHandle(Transform root, bool isLeftHand)
{
//IL_003e: Unknown result type (might be due to invalid IL or missing references)
//IL_004e: Unknown result type (might be due to invalid IL or missing references)
//IL_0058: Unknown result type (might be due to invalid IL or missing references)
//IL_009d: Unknown result type (might be due to invalid IL or missing references)
//IL_00a4: Expected O, but got Unknown
//IL_00d8: Unknown result type (might be due to invalid IL or missing references)
//IL_00bd: Unknown result type (might be due to invalid IL or missing references)
GameObject val = GameObject.CreatePrimitive((PrimitiveType)0);
((Object)val).name = (isLeftHand ? "HQB_LeftAnchorHandle" : "HQB_RightAnchorHandle");
val.transform.SetParent(root, false);
val.transform.localPosition = new Vector3(0f, 0.055f, 0f);
val.transform.localScale = Vector3.one * 0.035f;
int num = LayerMask.NameToLayer("Interactable");
if (num >= 0)
{
val.layer = num;
}
Renderer component = val.GetComponent<Renderer>();
Shader val2 = Shader.Find("Unlit/Color");
if ((Object)(object)component != (Object)null && (Object)(object)val2 != (Object)null)
{
Material val3 = new Material(val2);
val3.color = (isLeftHand ? new Color(1f, 0.72f, 0.12f, 1f) : new Color(0.35f, 0.9f, 1f, 1f));
component.material = val3;
}
Rigidbody obj = val.AddComponent<Rigidbody>();
obj.isKinematic = true;
obj.useGravity = false;
HandQuickbeltAdjustmentHandle handQuickbeltAdjustmentHandle = val.AddComponent<HandQuickbeltAdjustmentHandle>();
handQuickbeltAdjustmentHandle.Configure(root, isLeftHand);
val.SetActive(false);
return handQuickbeltAdjustmentHandle;
}
private void CreateHandSlots(Transform root, List<FVRQuickBeltSlot> handSlots, FVRQuickBeltSlot template, int large, int medium, int small)
{
FVRPhysicalObjectSize[] array = (FVRPhysicalObjectSize[])(object)new FVRPhysicalObjectSize[3]
{
(FVRPhysicalObjectSize)2,
(FVRPhysicalObjectSize)1,
default(FVRPhysicalObjectSize)
};
int[] array2 = new int[3] { large, medium, small };
int num = 0;
for (int i = 0; i < array.Length; i++)
{
int num2 = 0;
while (num2 < array2[i])
{
FVRQuickBeltSlot val = CreateSlot(root, template, array[i], num);
if ((Object)(object)val != (Object)null)
{
handSlots.Add(val);
}
num2++;
num++;
}
}
}
private FVRQuickBeltSlot CreateSlot(Transform root, FVRQuickBeltSlot template, FVRPhysicalObjectSize size, int index)
{
//IL_0019: Unknown result type (might be due to invalid IL or missing references)
//IL_0045: Unknown result type (might be due to invalid IL or missing references)
//IL_0055: Unknown result type (might be due to invalid IL or missing references)
//IL_0065: Unknown result type (might be due to invalid IL or missing references)
//IL_00b1: Unknown result type (might be due to invalid IL or missing references)
//IL_00b2: Unknown result type (might be due to invalid IL or missing references)
//IL_00b9: Unknown result type (might be due to invalid IL or missing references)
//IL_00c0: Unknown result type (might be due to invalid IL or missing references)
GameObject val = Object.Instantiate<GameObject>(((Component)template).gameObject);
val.SetActive(false);
((Object)val).name = $"HQB_{size}_{index + 1:00}";
val.transform.SetParent(root, false);
val.transform.localPosition = Vector3.zero;
val.transform.localRotation = Quaternion.identity;
val.transform.localScale = Vector3.one;
FVRQuickBeltSlot component = val.GetComponent<FVRQuickBeltSlot>();
if ((Object)(object)component == (Object)null || !BuildLocalGeometry(component, template))
{
Plugin.Logger.LogError((object)$"Could not create {((Object)val).name} from template {((Object)template).name}.");
Object.Destroy((Object)(object)val);
return null;
}
component.SizeLimit = size;
component.Shape = (QuickbeltSlotShape)0;
component.Type = (QuickbeltSlotType)0;
component.IsPlayer = true;
component.IsSelectable = true;
component.CurObject = null;
component.HeldObject = null;
component.IsKeepingTrackWithHead = false;
component.IsHovered = false;
val.AddComponent<HandQuickbeltSlotMarker>();
val.AddComponent<HandQuickbeltMiniaturizer>();
val.SetActive(true);
_body.QBSlots_Internal.Add(component);
_slots.Add(component);
return component;
}
private static bool BuildLocalGeometry(FVRQuickBeltSlot slot, FVRQuickBeltSlot template)
{
//IL_0075: Unknown result type (might be due to invalid IL or missing references)
//IL_007b: Expected O, but got Unknown
//IL_00bc: Unknown result type (might be due to invalid IL or missing references)
//IL_00cc: Unknown result type (might be due to invalid IL or missing references)
//IL_014c: Unknown result type (might be due to invalid IL or missing references)
//IL_015d: Unknown result type (might be due to invalid IL or missing references)
//IL_0174: Unknown result type (might be due to invalid IL or missing references)
//IL_017b: Expected O, but got Unknown
//IL_0212: Unknown result type (might be due to invalid IL or missing references)
if ((Object)(object)template == (Object)null || (Object)(object)template.HoverGeo == (Object)null)
{
return false;
}
Renderer[] componentsInChildren = ((Component)slot).GetComponentsInChildren<Renderer>(true);
for (int i = 0; i < componentsInChildren.Length; i++)
{
componentsInChildren[i].enabled = false;
}
for (int num = ((Component)slot).transform.childCount - 1; num >= 0; num--)
{
Object.Destroy((Object)(object)((Component)((Component)slot).transform.GetChild(num)).gameObject);
}
GameObject val = new GameObject("HQB_QuickbeltRoot");
val.transform.SetParent(((Component)slot).transform, false);
GameObject val2 = Object.Instantiate<GameObject>(template.HoverGeo);
((Object)val2).name = "HQB_HoverGeo";
val2.transform.SetParent(val.transform, false);
val2.transform.localPosition = Vector3.zero;
val2.transform.localRotation = Quaternion.identity;
Transform root = (((Object)(object)template.QuickbeltRoot != (Object)null) ? template.QuickbeltRoot : template.HoverGeo.transform.parent);
Transform val3 = FindBaseSphere(template, root);
GameObject val4 = Object.Instantiate<GameObject>(((Object)(object)val3 != (Object)null) ? ((Component)val3).gameObject : template.HoverGeo);
((Object)val4).name = "HQB_BaseSphere";
val4.transform.SetParent(val.transform, false);
val4.transform.localPosition = Vector3.zero;
val4.transform.localRotation = Quaternion.identity;
val4.SetActive(true);
GameObject val5 = new GameObject("HQB_PoseOverride");
val5.transform.SetParent(val.transform, false);
Renderer val6 = FindRenderer(val2.transform);
Renderer val7 = FindRenderer(val4.transform);
if ((Object)(object)val6 == (Object)null || (Object)(object)val7 == (Object)null)
{
Object.Destroy((Object)(object)val);
return false;
}
slot.QuickbeltRoot = val.transform;
slot.HoverGeo = val2;
slot.PoseOverride = val5.transform;
slot.RectBounds = val4.transform;
slot.m_hoverGeoRend = val6;
val6.enabled = true;
val7.enabled = true;
val2.SetActive(false);
slot.SetBaseRotation(Quaternion.identity);
ApplyGeometryScale(slot);
if ((Object)(object)val3 == (Object)null)
{
Plugin.Logger.LogWarning((object)$"{((Object)slot).name} uses a hover-material clone as its fallback base sphere.");
}
return true;
}
private static Transform FindBaseSphere(FVRQuickBeltSlot template, Transform root)
{
if ((Object)(object)template == (Object)null || (Object)(object)template.HoverGeo == (Object)null || (Object)(object)root == (Object)null)
{
return null;
}
Renderer val = FindRenderer(template.HoverGeo.transform);
MeshFilter val2 = (((Object)(object)val != (Object)null) ? ((Component)val).GetComponent<MeshFilter>() : null);
Renderer val3 = null;
Renderer[] componentsInChildren = ((Component)root).GetComponentsInChildren<Renderer>(true);
foreach (Renderer val4 in componentsInChildren)
{
if (!((Object)(object)val4 == (Object)null) && !((Object)(object)val4 == (Object)(object)val) && !((Component)val4).transform.IsChildOf(template.HoverGeo.transform))
{
if ((Object)(object)val3 == (Object)null)
{
val3 = val4;
}
MeshFilter component = ((Component)val4).GetComponent<MeshFilter>();
if ((Object)(object)val2 != (Object)null && (Object)(object)component != (Object)null && (Object)(object)component.sharedMesh == (Object)(object)val2.sharedMesh)
{
return ((Component)val4).transform;
}
}
}
if (!((Object)(object)val3 != (Object)null))
{
return null;
}
return ((Component)val3).transform;
}
private static Renderer FindRenderer(Transform root)
{
if ((Object)(object)root == (Object)null)
{
return null;
}
Renderer component = ((Component)root).GetComponent<Renderer>();
if (!((Object)(object)component != (Object)null))
{
return ((Component)root).GetComponentInChildren<Renderer>(true);
}
return component;
}
private void ApplyLayout()
{
//IL_002d: Unknown result type (might be due to invalid IL or missing references)
//IL_0032: Unknown result type (might be due to invalid IL or missing references)
//IL_004c: Unknown result type (might be due to invalid IL or missing references)
//IL_0051: Unknown result type (might be due to invalid IL or missing references)
//IL_0056: Unknown result type (might be due to invalid IL or missing references)
//IL_0070: Unknown result type (might be due to invalid IL or missing references)
//IL_008a: Unknown result type (might be due to invalid IL or missing references)
//IL_008f: Unknown result type (might be due to invalid IL or missing references)
if (!((Object)(object)_leftRoot == (Object)null) && !((Object)(object)_rightRoot == (Object)null))
{
_leftRoot.transform.localPosition = Plugin.MirrorPosition(Plugin.AnchorPosition.Value);
_leftRoot.transform.localRotation = Plugin.MirrorRotation(Quaternion.Euler(Plugin.AnchorRotation.Value));
_rightRoot.transform.localPosition = Plugin.AnchorPosition.Value;
_rightRoot.transform.localRotation = Quaternion.Euler(Plugin.AnchorRotation.Value);
ArrangeSlots(_leftSlots);
ArrangeSlots(_rightSlots);
SetHandleVisible(_leftHandle);
SetHandleVisible(_rightHandle);
}
}
private static void ArrangeSlots(List<FVRQuickBeltSlot> slots)
{
//IL_00a3: Unknown result type (might be due to invalid IL or missing references)
//IL_00aa: Unknown result type (might be due to invalid IL or missing references)
//IL_00b1: Unknown result type (might be due to invalid IL or missing references)
//IL_00b8: Unknown result type (might be due to invalid IL or missing references)
//IL_00bd: Unknown result type (might be due to invalid IL or missing references)
//IL_00c2: Unknown result type (might be due to invalid IL or missing references)
//IL_0098: Unknown result type (might be due to invalid IL or missing references)
int num = Mathf.Max(1, Plugin.GridColumns.Value);
float num2 = (float)Plugin.SlotSpacingMillimeters.Value * 0.001f;
for (int i = 0; i < slots.Count; i++)
{
FVRQuickBeltSlot val = slots[i];
if (!((Object)(object)val == (Object)null))
{
int num3 = i / num;
int num4 = i % num;
int num5 = Mathf.Min(num, slots.Count - num3 * num);
float num6 = ((float)num4 - (float)(num5 - 1) * 0.5f) * num2;
float num7 = (float)(-num3) * num2;
Transform parent = ((Component)val).transform.parent;
((Component)val).transform.localPosition = (Vector3)(((Object)(object)parent != (Object)null) ? parent.InverseTransformVector(parent.right * num6 + parent.forward * num7) : new Vector3(num6, 0f, num7));
ApplyGeometryScale(val);
}
}
}
private static void SetHandleVisible(HandQuickbeltAdjustmentHandle handle)
{
if (!((Object)(object)handle == (Object)null))
{
bool value = Plugin.ShowAdjustmentHandles.Value;
if (!value && ((FVRInteractiveObject)handle).IsHeld)
{
((FVRInteractiveObject)handle).ForceBreakInteraction();
}
if (((Component)handle).gameObject.activeSelf != value)
{
((Component)handle).gameObject.SetActive(value);
}
}
}
private static void ApplyGeometryScale(FVRQuickBeltSlot slot)
{
//IL_006d: Unknown result type (might be due to invalid IL or missing references)
//IL_0088: Unknown result type (might be due to invalid IL or missing references)
//IL_00a3: Unknown result type (might be due to invalid IL or missing references)
float diameter = Mathf.Max(0.001f, Mathf.Abs((float)Plugin.SlotDiameterMillimeters.Value * 0.001f));
if ((Object)(object)slot.HoverGeo != (Object)null)
{
SetWorldDiameter(slot.HoverGeo.transform, diameter);
}
if ((Object)(object)slot.RectBounds != (Object)null && (Object)(object)slot.HoverGeo != (Object)null)
{
slot.RectBounds.position = slot.HoverGeo.transform.position;
slot.RectBounds.rotation = slot.HoverGeo.transform.rotation;
slot.RectBounds.localScale = slot.HoverGeo.transform.localScale;
}
}
private static void SetWorldDiameter(Transform sphere, float diameter)
{
//IL_001b: Unknown result type (might be due to invalid IL or missing references)
//IL_000e: Unknown result type (might be due to invalid IL or missing references)
//IL_0020: Unknown result type (might be due to invalid IL or missing references)
//IL_0028: Unknown result type (might be due to invalid IL or missing references)
//IL_003f: Unknown result type (might be due to invalid IL or missing references)
//IL_0056: Unknown result type (might be due to invalid IL or missing references)
//IL_0067: Unknown result type (might be due to invalid IL or missing references)
Vector3 val = (((Object)(object)sphere.parent != (Object)null) ? sphere.parent.lossyScale : Vector3.one);
sphere.localScale = new Vector3(diameter / Mathf.Max(0.0001f, Mathf.Abs(val.x)), diameter / Mathf.Max(0.0001f, Mathf.Abs(val.y)), diameter / Mathf.Max(0.0001f, Mathf.Abs(val.z)));
}
private FVRQuickBeltSlot FindTemplate(FVRPlayerBody body)
{
if ((Object)(object)body != (Object)null && body.QBSlots_Internal != null)
{
for (int i = 0; i < body.QBSlots_Internal.Count; i++)
{
FVRQuickBeltSlot val = body.QBSlots_Internal[i];
if (IsUsableTemplate(val) && (Object)(object)((Component)val).GetComponent<HandQuickbeltSlotMarker>() == (Object)null)
{
return val;
}
}
}
if ((Object)(object)ManagerSingleton<GM>.Instance == (Object)null || ManagerSingleton<GM>.Instance.QuickbeltConfigurations == null)
{
return null;
}
FVRQuickBeltSlot val2 = null;
GameObject[] quickbeltConfigurations = ManagerSingleton<GM>.Instance.QuickbeltConfigurations;
foreach (GameObject val3 in quickbeltConfigurations)
{
if ((Object)(object)val3 == (Object)null)
{
continue;
}
FVRQuickBeltSlot[] componentsInChildren = val3.GetComponentsInChildren<FVRQuickBeltSlot>(true);
foreach (FVRQuickBeltSlot val4 in componentsInChildren)
{
if (IsUsableTemplate(val4))
{
if ((Object)(object)val2 == (Object)null)
{
val2 = val4;
}
if (((Object)val4).name == "QuickBeltSlot_Harness")
{
return val4;
}
}
}
}
return val2;
}
private static bool IsUsableTemplate(FVRQuickBeltSlot slot)
{
//IL_000a: Unknown result type (might be due to invalid IL or missing references)
if ((Object)(object)slot == (Object)null || (int)slot.Shape != 0 || (Object)(object)slot.HoverGeo == (Object)null)
{
return false;
}
Transform root = (((Object)(object)slot.QuickbeltRoot != (Object)null) ? slot.QuickbeltRoot : slot.HoverGeo.transform.parent);
return (Object)(object)FindBaseSphere(slot, root) != (Object)null;
}
private void RemoveSlots(bool dropContents)
{
for (int num = _slots.Count - 1; num >= 0; num--)
{
FVRQuickBeltSlot val = _slots[num];
if (!((Object)(object)val == (Object)null))
{
val.IsSelectable = false;
HandQuickbeltMiniaturizer component = ((Component)val).GetComponent<HandQuickbeltMiniaturizer>();
if ((Object)(object)component != (Object)null)
{
component.Restore();
}
if (dropContents && (Object)(object)val.CurObject != (Object)null)
{
val.CurObject.ClearQuickbeltState();
}
if ((Object)(object)_body != (Object)null && _body.QBSlots_Internal != null)
{
_body.QBSlots_Internal.Remove(val);
}
Object.Destroy((Object)(object)((Component)val).gameObject);
}
}
_slots.Clear();
_leftSlots.Clear();
_rightSlots.Clear();
_leftHandle = null;
_rightHandle = null;
DestroyRoot(ref _leftRoot);
DestroyRoot(ref _rightRoot);
}
private static void DestroyRoot(ref GameObject root)
{
if ((Object)(object)root != (Object)null)
{
Object.Destroy((Object)(object)root);
root = null;
}
}
}
internal sealed class HandQuickbeltSlotMarker : MonoBehaviour
{
}
internal sealed class HandQuickbeltAdjustmentHandle : FVRInteractiveObject
{
private Transform _anchor;
private bool _isLeftHand;
private Vector3 _positionOffset;
private Quaternion _rotationOffset;
internal void Configure(Transform anchor, bool isLeftHand)
{
//IL_0010: Unknown result type (might be due to invalid IL or missing references)
_anchor = anchor;
_isLeftHand = isLeftHand;
base.ControlType = (FVRInteractionControlType)0;
base.PoseOverride = ((Component)this).transform;
base.EndInteractionIfDistant = false;
}
public override bool IsDistantGrabbable()
{
return false;
}
public override void BeginInteraction(FVRViveHand hand)
{
//IL_0016: Unknown result type (might be due to invalid IL or missing references)
//IL_001b: Unknown result type (might be due to invalid IL or missing references)
//IL_0020: Unknown result type (might be due to invalid IL or missing references)
//IL_0022: Unknown result type (might be due to invalid IL or missing references)
//IL_0029: Unknown result type (might be due to invalid IL or missing references)
//IL_002f: Unknown result type (might be due to invalid IL or missing references)
//IL_0034: Unknown result type (might be due to invalid IL or missing references)
//IL_0039: Unknown result type (might be due to invalid IL or missing references)
//IL_003e: Unknown result type (might be due to invalid IL or missing references)
//IL_0044: Unknown result type (might be due to invalid IL or missing references)
//IL_004b: Unknown result type (might be due to invalid IL or missing references)
//IL_0050: Unknown result type (might be due to invalid IL or missing references)
//IL_0055: Unknown result type (might be due to invalid IL or missing references)
((FVRInteractiveObject)this).BeginInteraction(hand);
if ((Object)(object)_anchor != (Object)null)
{
Quaternion val = Quaternion.Inverse(((FVRInteractiveObject)this).m_handRot);
_positionOffset = val * (_anchor.position - ((FVRInteractiveObject)this).m_handPos);
_rotationOffset = val * _anchor.rotation;
}
}
public override void UpdateInteraction(FVRViveHand hand)
{
//IL_001c: Unknown result type (might be due to invalid IL or missing references)
//IL_0022: Unknown result type (might be due to invalid IL or missing references)
//IL_0028: 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)
//IL_0032: Unknown result type (might be due to invalid IL or missing references)
//IL_0043: Unknown result type (might be due to invalid IL or missing references)
//IL_0049: Unknown result type (might be due to invalid IL or missing references)
//IL_004e: Unknown result type (might be due to invalid IL or missing references)
((FVRInteractiveObject)this).UpdateInteraction(hand);
if ((Object)(object)_anchor != (Object)null)
{
_anchor.position = ((FVRInteractiveObject)this).m_handPos + ((FVRInteractiveObject)this).m_handRot * _positionOffset;
_anchor.rotation = ((FVRInteractiveObject)this).m_handRot * _rotationOffset;
}
}
public override void EndInteraction(FVRViveHand hand)
{
//IL_002c: Unknown result type (might be due to invalid IL or missing references)
//IL_0037: Unknown result type (might be due to invalid IL or missing references)
if ((Object)(object)_anchor != (Object)null && (Object)(object)Plugin.Instance != (Object)null)
{
Plugin.Instance.SaveAnchorPose(_isLeftHand, _anchor.localPosition, _anchor.localRotation);
}
((FVRInteractiveObject)this).EndInteraction(hand);
}
}
internal sealed class HandQuickbeltMiniaturizer : MonoBehaviour
{
private readonly HashSet<GameObject> _knownPhysicalObjects = new HashSet<GameObject>();
private FVRQuickBeltSlot _slot;
private FVRPhysicalObject _item;
private Vector3 _originalScale;
private Vector3 _storedScale;
private float _scaleFactor = 1f;
private float _targetSize;
private int _knownTransformCount;
private void Awake()
{
_slot = ((Component)this).GetComponent<FVRQuickBeltSlot>();
}
private void Update()
{
FVRPhysicalObject val = (FVRPhysicalObject)((Plugin.MiniaturizeStoredObjects.Value && (Object)(object)_slot != (Object)null) ? /*isinst with value type is only supported in some contexts*/: null);
if ((Object)(object)val != (Object)(object)_item)
{
Restore();
if ((Object)(object)val != (Object)null)
{
Track(val);
}
}
if (!((Object)(object)_item == (Object)null))
{
float num = TargetSizeMeters();
if (!Mathf.Approximately(num, _targetSize))
{
RestoreScale();
Fit(num);
}
if (((FVRInteractiveObject)_item).IsHeld)
{
RestoreScale();
return;
}
RefitAfterHierarchyChange();
ApplyScale();
}
}
private void OnDestroy()
{
Restore();
}
internal void Restore()
{
//IL_000e: Unknown result type (might be due to invalid IL or missing references)
//IL_0013: Unknown result type (might be due to invalid IL or missing references)
RestoreScale();
_item = null;
_storedScale = Vector3.zero;
_scaleFactor = 1f;
_targetSize = 0f;
_knownTransformCount = 0;
_knownPhysicalObjects.Clear();
}
internal void RestoreBeforeRemoval(FVRPhysicalObject physicalObject)
{
if ((Object)(object)_item == (Object)(object)physicalObject)
{
Restore();
}
}
private void Track(FVRPhysicalObject physicalObject)
{
//IL_000e: Unknown result type (might be due to invalid IL or missing references)
//IL_0013: Unknown result type (might be due to invalid IL or missing references)
_item = physicalObject;
_originalScale = ((Component)physicalObject).transform.localScale;
RecordHierarchy();
Fit(TargetSizeMeters());
}
private void Fit(float targetSize)
{
//IL_0014: Unknown result type (might be due to invalid IL or missing references)
//IL_0019: Unknown result type (might be due to invalid IL or missing references)
//IL_0035: Unknown result type (might be due to invalid IL or missing references)
//IL_003a: Unknown result type (might be due to invalid IL or missing references)
//IL_003b: Unknown result type (might be due to invalid IL or missing references)
//IL_0041: Unknown result type (might be due to invalid IL or missing references)
//IL_0047: Unknown result type (might be due to invalid IL or missing references)
//IL_0067: Unknown result type (might be due to invalid IL or missing references)
//IL_0072: Unknown result type (might be due to invalid IL or missing references)
//IL_0077: Unknown result type (might be due to invalid IL or missing references)
_targetSize = targetSize;
_scaleFactor = 1f;
_storedScale = _originalScale;
if (TryGetColliderBounds(((Component)_item).gameObject, out var bounds))
{
Vector3 size = ((Bounds)(ref bounds)).size;
float num = Mathf.Max(size.x, Mathf.Max(size.y, size.z));
if (num > targetSize)
{
_scaleFactor = targetSize / num;
_storedScale = _originalScale * _scaleFactor;
}
}
}
private void RefitAfterHierarchyChange()
{
//IL_0063: Unknown result type (might be due to invalid IL or missing references)
//IL_006e: Unknown result type (might be due to invalid IL or missing references)
if (((Component)_item).GetComponentsInChildren<Transform>(true).Length == _knownTransformCount)
{
return;
}
RestoreScale();
FVRPhysicalObject[] componentsInChildren = ((Component)_item).GetComponentsInChildren<FVRPhysicalObject>(true);
foreach (FVRPhysicalObject val in componentsInChildren)
{
if ((Object)(object)val != (Object)null && (Object)(object)val != (Object)(object)_item && !_knownPhysicalObjects.Contains(((Component)val).gameObject))
{
Transform transform = ((Component)val).transform;
transform.localScale *= _scaleFactor;
}
}
RecordHierarchy();
Fit(_targetSize);
}
private void RecordHierarchy()
{
_knownPhysicalObjects.Clear();
_knownTransformCount = ((Component)_item).GetComponentsInChildren<Transform>(true).Length;
FVRPhysicalObject[] componentsInChildren = ((Component)_item).GetComponentsInChildren<FVRPhysicalObject>(true);
for (int i = 0; i < componentsInChildren.Length; i++)
{
if ((Object)(object)componentsInChildren[i] != (Object)null)
{
_knownPhysicalObjects.Add(((Component)componentsInChildren[i]).gameObject);
}
}
}
private void RestoreScale()
{
//IL_001a: Unknown result type (might be due to invalid IL or missing references)
if ((Object)(object)_item != (Object)null)
{
((Component)_item).transform.localScale = _originalScale;
}
}
private void ApplyScale()
{
//IL_0027: Unknown result type (might be due to invalid IL or missing references)
if ((Object)(object)_item != (Object)null && !((FVRInteractiveObject)_item).IsHeld)
{
((Component)_item).transform.localScale = _storedScale;
}
}
private static float TargetSizeMeters()
{
float num = (float)Mathf.Abs(Plugin.SlotDiameterMillimeters.Value) * 0.001f;
return Mathf.Max(0.001f, num * (float)Plugin.StoredSizePercent.Value * 0.01f);
}
private static bool TryGetColliderBounds(GameObject root, out Bounds bounds)
{
//IL_0001: Unknown result type (might be due to invalid IL or missing references)
//IL_0054: Unknown result type (might be due to invalid IL or missing references)
//IL_0044: Unknown result type (might be due to invalid IL or missing references)
//IL_0049: Unknown result type (might be due to invalid IL or missing references)
bounds = default(Bounds);
bool flag = false;
Collider[] componentsInChildren = root.GetComponentsInChildren<Collider>(true);
foreach (Collider val in componentsInChildren)
{
if (!((Object)(object)val == (Object)null) && val.enabled && ((Component)val).gameObject.activeInHierarchy && !val.isTrigger)
{
if (!flag)
{
bounds = val.bounds;
flag = true;
}
else
{
((Bounds)(ref bounds)).Encapsulate(val.bounds);
}
}
}
return flag;
}
}
[HarmonyPatch(typeof(FVRPlayerBody), "ConfigureQuickbelt")]
internal static class ConfigureQuickbeltPatch
{
[HarmonyPostfix]
private static void Postfix(FVRPlayerBody __instance)
{
if ((Object)(object)Plugin.Instance != (Object)null)
{
Plugin.Instance.RebuildAfterQuickbeltChange(__instance);
}
}
}
[HarmonyPatch(typeof(FVRViveHand), "TestQuickBeltDistances")]
internal static class HandQuickbeltInteractionPatch
{
[HarmonyPostfix]
private static void Postfix(FVRViveHand __instance)
{
//IL_0085: Unknown result type (might be due to invalid IL or missing references)
//IL_0090: Unknown result type (might be due to invalid IL or missing references)
//IL_0095: Unknown result type (might be due to invalid IL or missing references)
//IL_009a: Unknown result type (might be due to invalid IL or missing references)
if ((Object)(object)__instance == (Object)null || (Object)(object)GM.CurrentPlayerBody == (Object)null || GM.CurrentPlayerBody.QBSlots_Internal == null)
{
return;
}
FVRInteractiveObject currentInteractable = __instance.CurrentInteractable;
FVRPhysicalObject val = (FVRPhysicalObject)(object)((currentInteractable is FVRPhysicalObject) ? currentInteractable : null);
if ((Object)(object)val == (Object)null || (Object)(object)val.QuickbeltSlot != (Object)null)
{
return;
}
FVRQuickBeltSlot val2 = null;
float num = float.MaxValue;
for (int i = 0; i < GM.CurrentPlayerBody.QBSlots_Internal.Count; i++)
{
FVRQuickBeltSlot val3 = GM.CurrentPlayerBody.QBSlots_Internal[i];
if (CanStore(val3, val) && IntersectsSlot(val3, val))
{
Vector3 val4 = val3.HoverGeo.transform.position - ((Component)val).transform.position;
float sqrMagnitude = ((Vector3)(ref val4)).sqrMagnitude;
if (sqrMagnitude < num)
{
val2 = val3;
num = sqrMagnitude;
}
}
}
if ((Object)(object)val2 != (Object)null)
{
__instance.CurrentHoveredQuickbeltSlot = val2;
__instance.CurrentHoveredQuickbeltSlotDirty = val2;
}
else if (IsHandQuickbelt(__instance.CurrentHoveredQuickbeltSlot))
{
__instance.CurrentHoveredQuickbeltSlot = null;
__instance.CurrentHoveredQuickbeltSlotDirty = null;
}
}
private static bool CanStore(FVRQuickBeltSlot slot, FVRPhysicalObject physicalObject)
{
//IL_002d: Unknown result type (might be due to invalid IL or missing references)
//IL_0033: Unknown result type (might be due to invalid IL or missing references)
//IL_003b: Unknown result type (might be due to invalid IL or missing references)
//IL_0041: Unknown result type (might be due to invalid IL or missing references)
if (IsHandQuickbelt(slot) && slot.IsSelectable && (Object)(object)slot.CurObject == (Object)null && (Object)(object)slot.HeldObject == (Object)null && slot.SizeLimit >= physicalObject.Size)
{
return slot.Type == physicalObject.QBSlotType;
}
return false;
}
private static bool IsHandQuickbelt(FVRQuickBeltSlot slot)
{
if ((Object)(object)slot != (Object)null)
{
return (Object)(object)((Component)slot).GetComponent<HandQuickbeltSlotMarker>() != (Object)null;
}
return false;
}
private static bool IntersectsSlot(FVRQuickBeltSlot slot, FVRPhysicalObject physicalObject)
{
//IL_001b: Unknown result type (might be due to invalid IL or missing references)
//IL_0020: Unknown result type (might be due to invalid IL or missing references)
//IL_002c: Unknown result type (might be due to invalid IL or missing references)
//IL_0031: Unknown result type (might be due to invalid IL or missing references)
//IL_0037: Unknown result type (might be due to invalid IL or missing references)
//IL_0042: Unknown result type (might be due to invalid IL or missing references)
//IL_004d: Unknown result type (might be due to invalid IL or missing references)
//IL_00fd: Unknown result type (might be due to invalid IL or missing references)
//IL_0102: Unknown result type (might be due to invalid IL or missing references)
//IL_0107: Unknown result type (might be due to invalid IL or missing references)
//IL_00ab: Unknown result type (might be due to invalid IL or missing references)
//IL_00b0: Unknown result type (might be due to invalid IL or missing references)
//IL_00b4: Unknown result type (might be due to invalid IL or missing references)
if ((Object)(object)slot.HoverGeo == (Object)null)
{
return false;
}
Vector3 position = slot.HoverGeo.transform.position;
Vector3 lossyScale = slot.HoverGeo.transform.lossyScale;
float num = 0.5f * Mathf.Min(Mathf.Abs(lossyScale.x), Mathf.Min(Mathf.Abs(lossyScale.y), Mathf.Abs(lossyScale.z)));
float num2 = num * num;
Collider[] componentsInChildren = ((Component)physicalObject).GetComponentsInChildren<Collider>(true);
bool flag = false;
foreach (Collider val in componentsInChildren)
{
if (!((Object)(object)val == (Object)null) && val.enabled && ((Component)val).gameObject.activeInHierarchy && !val.isTrigger)
{
flag = true;
Bounds bounds = val.bounds;
if (((Bounds)(ref bounds)).SqrDistance(position) <= num2)
{
return true;
}
}
}
if (flag)
{
return false;
}
Transform val2 = (((Object)(object)((FVRInteractiveObject)physicalObject).PoseOverride != (Object)null) ? ((FVRInteractiveObject)physicalObject).PoseOverride : ((Component)physicalObject).transform);
Vector3 val3 = slot.HoverGeo.transform.InverseTransformPoint(val2.position);
return ((Vector3)(ref val3)).magnitude < 0.5f;
}
}
[HarmonyPatch]
internal static class StoredObjectScalePatch
{
[HarmonyPatch(typeof(FVRPhysicalObject), "SetParentage")]
[HarmonyPrefix]
private static void BeforeSetParentage(FVRPhysicalObject __instance)
{
RestoreBeforeRemoval(__instance);
}
[HarmonyPatch(typeof(FVRPhysicalObject), "SetQuickBeltSlot")]
[HarmonyPrefix]
private static void BeforeClearQuickbelt(FVRPhysicalObject __instance, FVRQuickBeltSlot slot)
{
if ((Object)(object)slot == (Object)null)
{
RestoreBeforeRemoval(__instance);
}
}
private static void RestoreBeforeRemoval(FVRPhysicalObject physicalObject)
{
if (!((Object)(object)physicalObject == (Object)null) && !((Object)(object)physicalObject.QuickbeltSlot == (Object)null))
{
HandQuickbeltMiniaturizer component = ((Component)physicalObject.QuickbeltSlot).GetComponent<HandQuickbeltMiniaturizer>();
if ((Object)(object)component != (Object)null)
{
component.RestoreBeforeRemoval(physicalObject);
}
}
}
}
[BepInProcess("h3vr.exe")]
[BepInPlugin("quaternion.hqb", "Hand Quickbelts", "0.4.2")]
public class Plugin : BaseUnityPlugin
{
internal static readonly Vector3 DefaultAnchorPosition = new Vector3(-1.4656025f, 0.07558223f, -0.8075327f);
internal static readonly Vector3 DefaultAnchorRotation = new Vector3(-6.0018616f, 36.728462f, 174.04753f);
private HandQuickbeltController _controller;
private Harmony _harmony;
private bool _resetting;
public const string Id = "quaternion.hqb";
internal static Plugin Instance { get; private set; }
internal static ManualLogSource Logger { get; private set; }
internal static ConfigEntry<int> LeftLargeSlots { get; private set; }
internal static ConfigEntry<int> LeftMediumSlots { get; private set; }
internal static ConfigEntry<int> LeftSmallSlots { get; private set; }
internal static ConfigEntry<int> RightLargeSlots { get; private set; }
internal static ConfigEntry<int> RightMediumSlots { get; private set; }
internal static ConfigEntry<int> RightSmallSlots { get; private set; }
internal static ConfigEntry<int> GridColumns { get; private set; }
internal static ConfigEntry<int> SlotSpacingMillimeters { get; private set; }
internal static ConfigEntry<int> SlotDiameterMillimeters { get; private set; }
internal static ConfigEntry<Vector3> AnchorPosition { get; private set; }
internal static ConfigEntry<Vector3> AnchorRotation { get; private set; }
internal static ConfigEntry<bool> ShowAdjustmentHandles { get; private set; }
internal static ConfigEntry<bool> ResetAllSettings { get; private set; }
internal static ConfigEntry<bool> MiniaturizeStoredObjects { get; private set; }
internal static ConfigEntry<int> StoredSizePercent { get; private set; }
public static string Name => "Hand Quickbelts";
public static string Version => "0.4.2";
private void Awake()
{
//IL_0033: Unknown result type (might be due to invalid IL or missing references)
//IL_003d: Expected O, but got Unknown
Instance = this;
Logger = ((BaseUnityPlugin)this).Logger;
RegisterVectorConverter();
BindConfig();
_controller = new HandQuickbeltController();
SubscribeToConfigChanges();
_harmony = new Harmony("quaternion.hqb");
_harmony.PatchAll();
Logger.LogMessage((object)$"{Name} {Version} loaded.");
}
private void Update()
{
if (_controller != null)
{
_controller.Tick();
}
}
private void OnDestroy()
{
if (_controller != null)
{
_controller.Dispose();
_controller = null;
}
if (_harmony != null)
{
_harmony.UnpatchSelf();
_harmony = null;
}
Instance = null;
}
private void BindConfig()
{
//IL_00f6: Unknown result type (might be due to invalid IL or missing references)
//IL_011a: Unknown result type (might be due to invalid IL or missing references)
//IL_01b6: Unknown result type (might be due to invalid IL or missing references)
//IL_01c0: Expected O, but got Unknown
LeftLargeSlots = BindSlotCount("Left Large Slots", 1, "Large quickbelt slots attached below the left hand.");
LeftMediumSlots = BindSlotCount("Left Medium Slots", 0, "Medium quickbelt slots attached below the left hand.");
LeftSmallSlots = BindSlotCount("Left Small Slots", 0, "Small quickbelt slots attached below the left hand.");
RightLargeSlots = BindSlotCount("Right Large Slots", 1, "Large quickbelt slots attached below the right hand.");
RightMediumSlots = BindSlotCount("Right Medium Slots", 0, "Medium quickbelt slots attached below the right hand.");
RightSmallSlots = BindSlotCount("Right Small Slots", 0, "Small quickbelt slots attached below the right hand.");
GridColumns = ((BaseUnityPlugin)this).Config.Bind<int>("Slots", "Grid Columns", 2, "Slots per row before the grid wraps toward the elbow.");
SlotSpacingMillimeters = ((BaseUnityPlugin)this).Config.Bind<int>("Slots", "Slot Spacing (mm)", 120, "World-space center-to-center spacing on both grid axes.");
SlotDiameterMillimeters = ((BaseUnityPlugin)this).Config.Bind<int>("Slots", "Slot Diameter (mm)", 100, "World-space diameter of each native sphere visual and interaction volume.");
AnchorPosition = ((BaseUnityPlugin)this).Config.Bind<Vector3>("Placement", "Anchor Position (meters)", DefaultAnchorPosition, "Shared palm-local position. The left hand uses its mirrored pose.");
AnchorRotation = ((BaseUnityPlugin)this).Config.Bind<Vector3>("Placement", "Anchor Rotation (degrees)", DefaultAnchorRotation, "Shared palm-local Euler rotation. The left hand uses its mirrored pose.");
ShowAdjustmentHandles = ((BaseUnityPlugin)this).Config.Bind<bool>("Placement", "Show Adjustment Handles", false, "Show grabbable handles for moving and rotating the shared anchor pose.");
ResetAllSettings = ((BaseUnityPlugin)this).Config.Bind<bool>("Placement", "Reset All Settings", false, "Restore every Hand Quickbelts setting to its default, then turn this toggle off.");
MiniaturizeStoredObjects = ((BaseUnityPlugin)this).Config.Bind<bool>("Stored Objects", "Miniaturize Stored Objects", true, "Reduce stored items to fit and restore their original scale before removal.");
StoredSizePercent = ((BaseUnityPlugin)this).Config.Bind<int>("Stored Objects", "Stored Size (% of Slot Diameter)", 80, new ConfigDescription("Maximum stored-object size as a percentage of the slot diameter. Objects are reduced to fit but never enlarged.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 1000), new object[0]));
}
private ConfigEntry<int> BindSlotCount(string name, int defaultValue, string description)
{
//IL_0026: Unknown result type (might be due to invalid IL or missing references)
//IL_0030: Expected O, but got Unknown
return ((BaseUnityPlugin)this).Config.Bind<int>("Slots", name, defaultValue, new ConfigDescription(description + " Changing a slot count drops items stored in hand slots.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 10), new object[0]));
}
private void SubscribeToConfigChanges()
{
ConfigEntry<int>[] array = new ConfigEntry<int>[6] { LeftLargeSlots, LeftMediumSlots, LeftSmallSlots, RightLargeSlots, RightMediumSlots, RightSmallSlots };
for (int i = 0; i < array.Length; i++)
{
array[i].SettingChanged += OnSlotCountChanged;
}
GridColumns.SettingChanged += OnLayoutChanged;
SlotSpacingMillimeters.SettingChanged += OnLayoutChanged;
SlotDiameterMillimeters.SettingChanged += OnLayoutChanged;
AnchorPosition.SettingChanged += OnLayoutChanged;
AnchorRotation.SettingChanged += OnLayoutChanged;
ShowAdjustmentHandles.SettingChanged += OnLayoutChanged;
ResetAllSettings.SettingChanged += OnResetAllSettingsChanged;
}
private void OnSlotCountChanged(object sender, EventArgs eventArgs)
{
if (_controller != null)
{
_controller.RequestRebuild();
}
}
private void OnLayoutChanged(object sender, EventArgs eventArgs)
{
if (_controller != null)
{
_controller.RequestLayout();
}
}
private void OnResetAllSettingsChanged(object sender, EventArgs eventArgs)
{
//IL_0086: Unknown result type (might be due to invalid IL or missing references)
//IL_0095: Unknown result type (might be due to invalid IL or missing references)
if (!_resetting && ResetAllSettings.Value)
{
_resetting = true;
LeftLargeSlots.Value = 1;
LeftMediumSlots.Value = 0;
LeftSmallSlots.Value = 0;
RightLargeSlots.Value = 1;
RightMediumSlots.Value = 0;
RightSmallSlots.Value = 0;
GridColumns.Value = 2;
SlotSpacingMillimeters.Value = 120;
SlotDiameterMillimeters.Value = 100;
AnchorPosition.Value = DefaultAnchorPosition;
AnchorRotation.Value = DefaultAnchorRotation;
ShowAdjustmentHandles.Value = false;
MiniaturizeStoredObjects.Value = true;
StoredSizePercent.Value = 80;
ResetAllSettings.Value = false;
((BaseUnityPlugin)this).Config.Save();
_resetting = false;
if (_controller != null)
{
_controller.RequestRebuild();
}
Logger.LogInfo((object)"Reset all settings to defaults.");
}
}
internal void RebuildAfterQuickbeltChange(FVRPlayerBody body)
{
if (_controller != null)
{
_controller.RebuildAfterQuickbeltChange(body);
}
}
internal void SaveAnchorPose(bool isLeftHand, Vector3 position, Quaternion rotation)
{
//IL_0006: Unknown result type (might be due to invalid IL or missing references)
//IL_0007: Unknown result type (might be due to invalid IL or missing references)
//IL_0003: Unknown result type (might be due to invalid IL or missing references)
//IL_000c: Unknown result type (might be due to invalid IL or missing references)
//IL_0013: Unknown result type (might be due to invalid IL or missing references)
//IL_0014: Unknown result type (might be due to invalid IL or missing references)
//IL_0010: Unknown result type (might be due to invalid IL or missing references)
//IL_0019: Unknown result type (might be due to invalid IL or missing references)
//IL_001c: Unknown result type (might be due to invalid IL or missing references)
//IL_0021: Unknown result type (might be due to invalid IL or missing references)
//IL_0027: Unknown result type (might be due to invalid IL or missing references)
//IL_0032: Unknown result type (might be due to invalid IL or missing references)
//IL_003d: Unknown result type (might be due to invalid IL or missing references)
//IL_0048: Unknown result type (might be due to invalid IL or missing references)
//IL_0053: Unknown result type (might be due to invalid IL or missing references)
//IL_0086: Unknown result type (might be due to invalid IL or missing references)
//IL_0095: Unknown result type (might be due to invalid IL or missing references)
Vector3 value = (isLeftHand ? MirrorPosition(position) : position);
Quaternion val = (isLeftHand ? MirrorRotation(rotation) : rotation);
Vector3 eulerAngles = ((Quaternion)(ref val)).eulerAngles;
AnchorPosition.Value = value;
AnchorRotation.Value = new Vector3(NormalizeAngle(eulerAngles.x), NormalizeAngle(eulerAngles.y), NormalizeAngle(eulerAngles.z));
((BaseUnityPlugin)this).Config.Save();
Logger.LogInfo((object)string.Format("Saved shared anchor from the {0} handle: position {1}, rotation {2}.", isLeftHand ? "left" : "right", AnchorPosition.Value, AnchorRotation.Value));
}
internal static Vector3 MirrorPosition(Vector3 position)
{
//IL_0000: Unknown result type (might be due to invalid IL or missing references)
//IL_0007: Unknown result type (might be due to invalid IL or missing references)
//IL_000d: Unknown result type (might be due to invalid IL or missing references)
//IL_0013: Unknown result type (might be due to invalid IL or missing references)
return new Vector3(0f - position.x, position.y, position.z);
}
internal static Quaternion MirrorRotation(Quaternion rotation)
{
//IL_0000: Unknown result type (might be due to invalid IL or missing references)
//IL_0006: Unknown result type (might be due to invalid IL or missing references)
//IL_000d: Unknown result type (might be due to invalid IL or missing references)
//IL_0014: Unknown result type (might be due to invalid IL or missing references)
//IL_001a: Unknown result type (might be due to invalid IL or missing references)
return new Quaternion(rotation.x, 0f - rotation.y, 0f - rotation.z, rotation.w);
}
private static float NormalizeAngle(float angle)
{
if (!(angle > 180f))
{
return angle;
}
return angle - 360f;
}
private static void RegisterVectorConverter()
{
if (!TypeDescriptor.GetConverter(typeof(Vector3)).CanConvertFrom(typeof(string)))
{
TypeDescriptor.AddAttributes(typeof(Vector3), new TypeConverterAttribute(typeof(Vector3ConfigTypeConverter)));
}
}
}
public sealed class Vector3ConfigTypeConverter : TypeConverter
{
public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
{
if ((object)sourceType != typeof(string))
{
return base.CanConvertFrom(context, sourceType);
}
return true;
}
public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType)
{
if ((object)destinationType != typeof(string))
{
return base.CanConvertTo(context, destinationType);
}
return true;
}
public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value)
{
//IL_0087: Unknown result type (might be due to invalid IL or missing references)
if (!(value is string text))
{
return base.ConvertFrom(context, culture, value);
}
string[] array = text.Trim().Trim('(', ')').Split(new char[1] { ',' });
if (array.Length != 3)
{
throw new FormatException("Expected a vector in x, y, z format.");
}
return (object)new Vector3(float.Parse(array[0], NumberStyles.Float, CultureInfo.InvariantCulture), float.Parse(array[1], NumberStyles.Float, CultureInfo.InvariantCulture), float.Parse(array[2], NumberStyles.Float, CultureInfo.InvariantCulture));
}
public override object ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value, Type destinationType)
{
//IL_0017: Unknown result type (might be due to invalid IL or missing references)
//IL_001c: Unknown result type (might be due to invalid IL or missing references)
//IL_002f: Unknown result type (might be due to invalid IL or missing references)
//IL_003d: Unknown result type (might be due to invalid IL or missing references)
//IL_004b: Unknown result type (might be due to invalid IL or missing references)
if ((object)destinationType == typeof(string) && value is Vector3 val)
{
return string.Format(CultureInfo.InvariantCulture, "{0:0.######}, {1:0.######}, {2:0.######}", new object[3] { val.x, val.y, val.z });
}
return base.ConvertTo(context, culture, value, destinationType);
}
}
}