Decompiled source of Custom Holsters v1.0.0

Mods/CustomHolsters.dll

Decompiled 13 hours ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Text;
using System.Text.Json;
using System.Text.Json.Serialization;
using BoneLib;
using BoneLib.BoneMenu;
using BoneLib.Notifications;
using CustomHolsters;
using CustomHolsters.Compat;
using CustomHolsters.Holsters;
using CustomHolsters.Layouts;
using CustomHolsters.Menu;
using CustomHolsters.Preview;
using HarmonyLib;
using Il2CppInterop.Runtime.InteropTypes;
using Il2CppInterop.Runtime.InteropTypes.Arrays;
using Il2CppSLZ.Marrow;
using Il2CppSLZ.Marrow.Warehouse;
using Il2CppSLZ.VRMK;
using MelonLoader;
using MelonLoader.Preferences;
using MelonLoader.Utils;
using Microsoft.CodeAnalysis;
using UnityEngine;
using UnityEngine.Rendering;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: MelonInfo(typeof(Core), "Custom Holsters", "1.0.0", "TMLMedia", null)]
[assembly: MelonGame("Stress Level Zero", "BONELAB")]
[assembly: TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName = ".NET 6.0")]
[assembly: AssemblyCompany("CustomHolsters")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("Custom Holsters")]
[assembly: AssemblyTitle("Custom Holsters")]
[assembly: AssemblyVersion("1.0.0.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace CustomHolsters
{
	public class Core : MelonMod
	{
		private object _setupRoutine;

		public static Core Instance { get; private set; }

		public static Instance Log => ((MelonBase)Instance).LoggerInstance;

		public override void OnInitializeMelon()
		{
			Instance = this;
			Settings.Init();
			LayoutManager.Init();
			Hooking.OnLevelLoaded += OnLevelLoaded;
			Hooking.OnLevelUnloaded += OnLevelUnloaded;
			Log.Msg("Custom Holsters 1.0.0 loaded. Layouts: " + LayoutManager.LayoutDir);
		}

		public override void OnLateInitializeMelon()
		{
			FusionCompat.Init();
			BuildMenuSafe();
		}

		private static void BuildMenuSafe()
		{
			try
			{
				HolsterMenu.Build();
			}
			catch (Exception ex)
			{
				Log.Error("Failed to build BoneMenu page: " + ex);
			}
		}

		private void OnLevelLoaded(LevelInfo info)
		{
			BuildMenuSafe();
			ScheduleSetup(avatarChanged: false);
		}

		private void OnLevelUnloaded()
		{
			LayoutManager.FlushPendingSave();
			AvatarPreview.Destroy();
			HolsterApplier.ClearQueue();
			HolsterRegistry.Clear(restore: false);
			AnchorResolver.Clear();
		}

		internal static void OnLocalAvatarSwitched()
		{
			if (Instance != null)
			{
				Instance.ScheduleSetup(avatarChanged: true);
			}
		}

		public void ScheduleSetup(bool avatarChanged)
		{
			if (_setupRoutine != null)
			{
				MelonCoroutines.Stop(_setupRoutine);
			}
			_setupRoutine = MelonCoroutines.Start(SetupRoutine(avatarChanged));
		}

		private IEnumerator SetupRoutine(bool avatarChanged)
		{
			HolsterApplier.Suspended = true;
			for (int i = 0; i < 3; i++)
			{
				yield return null;
			}
			float until = Time.realtimeSinceStartup + 0.35f;
			while (Time.realtimeSinceStartup < until)
			{
				yield return null;
			}
			RigManager rigManager = Player.RigManager;
			if ((Object)(object)rigManager == (Object)null)
			{
				HolsterApplier.Suspended = false;
				_setupRoutine = null;
				yield break;
			}
			try
			{
				if ((Object)(object)HolsterRegistry.Rig != (Object)(object)rigManager)
				{
					HolsterRegistry.Scan(rigManager);
				}
				else
				{
					foreach (HolsterSlot slot in HolsterRegistry.Slots)
					{
						if (slot.IsValid && slot.Overridden)
						{
							slot.RestoreVanilla();
						}
					}
					try
					{
						if ((Object)(object)rigManager.avatar != (Object)null && (Object)(object)rigManager.physicsRig != (Object)null)
						{
							rigManager.physicsRig.SetBodySlot(rigManager.avatar);
						}
					}
					catch (Exception)
					{
					}
					HolsterRegistry.RecaptureVanilla();
				}
				AnchorResolver.Calibrate(rigManager);
				string text = "";
				string title = "";
				try
				{
					text = ((ScannableReference)rigManager.AvatarCrate).Barcode.ID;
					title = (((Object)(object)((CrateReferenceT<AvatarCrate>)(object)rigManager.AvatarCrate).Crate != (Object)null) ? ((Scannable)((CrateReferenceT<AvatarCrate>)(object)rigManager.AvatarCrate).Crate).Title : text);
				}
				catch (Exception)
				{
				}
				LayoutManager.OnAvatarChanged(text, title);
				HolsterApplier.OnLayoutReplaced();
			}
			catch (Exception ex3)
			{
				Log.Error("Holster setup failed: " + ex3);
			}
			HolsterApplier.Suspended = false;
			HolsterMenu.OnRigReady();
			if (AvatarPreview.IsVisible)
			{
				AvatarPreview.Rebuild();
			}
			_setupRoutine = null;
		}

		public override void OnUpdate()
		{
			RigManager rigManager = Player.RigManager;
			if ((Object)(object)rigManager != (Object)null && (Object)(object)rigManager != (Object)(object)HolsterRegistry.Rig && _setupRoutine == null)
			{
				HolsterRegistry.Clear(restore: false);
				ScheduleSetup(avatarChanged: false);
			}
			HolsterApplier.Tick(processQueue: true);
			LayoutManager.Tick();
			HolsterMenu.Tick();
		}

		public override void OnFixedUpdate()
		{
			HolsterApplier.Tick(processQueue: false);
		}

		public override void OnLateUpdate()
		{
			HolsterApplier.Tick(processQueue: false);
			AvatarPreview.Tick();
		}

		public override void OnApplicationQuit()
		{
			LayoutManager.FlushPendingSave();
		}
	}
	[HarmonyPatch(typeof(RigManager), "SwitchAvatar")]
	internal static class SwitchAvatarPatch
	{
		[HarmonyPostfix]
		private static void Postfix(RigManager __instance)
		{
			try
			{
				if ((Object)(object)__instance != (Object)null && (Object)(object)__instance == (Object)(object)Player.RigManager)
				{
					Core.OnLocalAvatarSwitched();
				}
			}
			catch (Exception)
			{
			}
		}
	}
	public static class ModInfo
	{
		public const string Name = "Custom Holsters";

		public const string InternalName = "CustomHolsters";

		public const string Version = "1.0.0";

		public const string Author = "TMLMedia";

		public const string DataFolderName = "CustomHolsters";
	}
	public static class Settings
	{
		private static MelonPreferences_Category _category;

		public static MelonPreferences_Entry<bool> Enabled;

		public static MelonPreferences_Entry<string> DefaultLayout;

		public static MelonPreferences_Entry<bool> AutoLoadAvatarLayouts;

		public static MelonPreferences_Entry<bool> AutoSave;

		public static MelonPreferences_Entry<bool> ReseatHolsteredItems;

		public static MelonPreferences_Entry<bool> ShowLiveGizmo;

		public static MelonPreferences_Entry<bool> CopyHandRotation;

		public static MelonPreferences_Entry<float> PreviewHeight;

		public static void Init()
		{
			_category = MelonPreferences.CreateCategory("CustomHolsters", "Custom Holsters");
			Enabled = _category.CreateEntry<bool>("Enabled", true, "Enabled", "Master switch. When off, every holster returns to its vanilla BONELAB position.", false, false, (ValueValidator)null, (string)null);
			DefaultLayout = _category.CreateEntry<string>("DefaultLayout", "Default", "Default Layout", "Layout used for any avatar that has no layout bound to it.", false, false, (ValueValidator)null, (string)null);
			AutoLoadAvatarLayouts = _category.CreateEntry<bool>("AutoLoadAvatarLayouts", true, "Auto-Load Avatar Layouts", "Automatically switch to the layout bound to an avatar when you change into it.", false, false, (ValueValidator)null, (string)null);
			AutoSave = _category.CreateEntry<bool>("AutoSave", true, "Auto-Save", "Save the active layout automatically a moment after each edit.", false, false, (ValueValidator)null, (string)null);
			ReseatHolsteredItems = _category.CreateEntry<bool>("ReseatHolsteredItems", true, "Re-seat Holstered Items", "After moving a holster, re-insert whatever it holds so the item jumps to the new spot. Disabled automatically inside Fusion lobbies.", false, false, (ValueValidator)null, (string)null);
			ShowLiveGizmo = _category.CreateEntry<bool>("ShowLiveGizmo", true, "Show Live Gizmo", "Draw a small marker on the real holster you are editing.", false, false, (ValueValidator)null, (string)null);
			CopyHandRotation = _category.CreateEntry<bool>("CopyHandRotation", false, "Copy Hand Rotation", "When placing a holster at your hand, also copy the hand's rotation.", false, false, (ValueValidator)null, (string)null);
			PreviewHeight = _category.CreateEntry<float>("PreviewHeight", 0.6f, "Preview Height", "Height in meters of the 3D avatar preview figure.", false, false, (ValueValidator)null, (string)null);
		}

		public static void Save()
		{
			if (_category != null)
			{
				_category.SaveToFile(false);
			}
		}
	}
}
namespace CustomHolsters.Preview
{
	public static class AvatarPreview
	{
		private sealed class Marker
		{
			public GameObject Root;

			public Renderer Ball;

			public int ColorKey = -1;
		}

		private static readonly Color SelectedColor = new Color(1f, 0.85f, 0.1f, 1f);

		private static readonly Color MovedColor = new Color(0.1f, 0.85f, 1f, 1f);

		private static readonly Color VanillaColor = new Color(0.85f, 0.85f, 0.85f, 1f);

		private static readonly Color AmmoColor = new Color(1f, 0.5f, 0.15f, 1f);

		private static readonly Color DiscColor = new Color(0.15f, 0.17f, 0.2f, 1f);

		private static GameObject _root;

		private static Transform _turntable;

		private static Transform _model;

		private static GameObject _liveGizmo;

		private static Transform _liveGizmoTarget;

		private static readonly List<Mesh> _bakedMeshes = new List<Mesh>();

		private static readonly Dictionary<string, Marker> _markers = new Dictionary<string, Marker>();

		private static readonly Dictionary<string, Vector3> _vanillaPos = new Dictionary<string, Vector3>();

		private static readonly Dictionary<string, Quaternion> _vanillaRot = new Dictionary<string, Quaternion>();

		private static readonly int AnchorCount = Enum.GetValues(typeof(BodyAnchor)).Length;

		private static readonly Vector3[] _anchorPos = (Vector3[])(object)new Vector3[AnchorCount];

		private static readonly Quaternion[] _anchorRot = (Quaternion[])(object)new Quaternion[AnchorCount];

		private static readonly bool[] _anchorValid = new bool[AnchorCount];

		private static float _avatarHeight = 1.76f;

		private static float _modelScale = 1f;

		private static float _yaw;

		private static float _pitch;

		public static bool AutoSpin;

		public static string SelectedId;

		public static bool IsVisible => (Object)(object)_root != (Object)null;

		public static float Yaw => _yaw;

		public static void SetVisible(bool visible)
		{
			if (visible)
			{
				Rebuild();
			}
			else
			{
				Destroy();
			}
		}

		public static void Rebuild()
		{
			//IL_0064: Unknown result type (might be due to invalid IL or missing references)
			//IL_006e: Expected O, but got Unknown
			//IL_0073: Unknown result type (might be due to invalid IL or missing references)
			//IL_009c: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f9: Unknown result type (might be due to invalid IL or missing references)
			//IL_0103: Unknown result type (might be due to invalid IL or missing references)
			//IL_012e: Unknown result type (might be due to invalid IL or missing references)
			Destroy();
			RigManager rigManager = Player.RigManager;
			Avatar val = (((Object)(object)rigManager != (Object)null) ? rigManager.avatar : null);
			if ((Object)(object)val == (Object)null || !AnchorResolver.IsCalibrated)
			{
				HolsterMenuNotify("Load into a level with an avatar first.");
				return;
			}
			try
			{
				Transform transform = ((Component)val).transform;
				_avatarHeight = ((val.height > 0.1f) ? val.height : 1.76f);
				_root = new GameObject("[Custom Holsters] Preview");
				_turntable = new GameObject("Turntable").transform;
				_turntable.SetParent(_root.transform, false);
				_model = new GameObject("Model").transform;
				_model.SetParent(_turntable, false);
				BakeRenderers(transform);
				BakeAnchorsAndVanilla(transform);
				BuildDisc();
				BuildMarkers();
				_modelScale = Mathf.Clamp(Settings.PreviewHeight.Value, 0.15f, 2.5f) / _avatarHeight;
				_model.localScale = Vector3.one * _modelScale;
				_model.localPosition = new Vector3(0f, (0f - _avatarHeight) * 0.5f * _modelScale, 0f);
				Recenter();
				ApplyRotation();
				UpdateMarkers();
			}
			catch (Exception ex)
			{
				Core.Log.Error("Failed to build avatar preview: " + ex);
				Destroy();
			}
		}

		public static void Destroy()
		{
			if ((Object)(object)_root != (Object)null)
			{
				Object.Destroy((Object)(object)_root);
			}
			_root = null;
			_turntable = null;
			_model = null;
			foreach (Mesh bakedMesh in _bakedMeshes)
			{
				if ((Object)(object)bakedMesh != (Object)null)
				{
					Object.Destroy((Object)(object)bakedMesh);
				}
			}
			_bakedMeshes.Clear();
			_markers.Clear();
			_vanillaPos.Clear();
			_vanillaRot.Clear();
			DestroyLiveGizmo();
		}

		public static void Recenter()
		{
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: 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_0040: 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_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0066: Unknown result type (might be due to invalid IL or missing references)
			//IL_006c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0071: Unknown result type (might be due to invalid IL or missing references)
			//IL_0076: Unknown result type (might be due to invalid IL or missing references)
			//IL_0080: Unknown result type (might be due to invalid IL or missing references)
			//IL_0085: 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_0095: Unknown result type (might be due to invalid IL or missing references)
			//IL_0096: Unknown result type (might be due to invalid IL or missing references)
			//IL_0097: Unknown result type (might be due to invalid IL or missing references)
			//IL_009c: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_0059: Unknown result type (might be due to invalid IL or missing references)
			//IL_005e: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)_root == (Object)null))
			{
				Transform head = Player.Head;
				Vector3 val = (((Object)(object)head != (Object)null) ? head.position : Vector3.zero);
				Vector3 val2 = (((Object)(object)head != (Object)null) ? Vector3.ProjectOnPlane(head.forward, Vector3.up) : Vector3.forward);
				if (((Vector3)(ref val2)).sqrMagnitude < 0.0001f)
				{
					val2 = Vector3.forward;
				}
				((Vector3)(ref val2)).Normalize();
				Vector3 val3 = val + val2 * 0.6f + Vector3.down * 0.3f;
				_root.transform.SetPositionAndRotation(val3, Quaternion.LookRotation(-val2, Vector3.up));
			}
		}

		public static void Rotate(float degrees)
		{
			_yaw = HolsterApplier.Wrap(_yaw + degrees);
			ApplyRotation();
		}

		public static void Tilt(float degrees)
		{
			_pitch = Mathf.Clamp(_pitch + degrees, -75f, 75f);
			ApplyRotation();
		}

		public static void SetView(float yaw)
		{
			_yaw = yaw;
			_pitch = 0f;
			ApplyRotation();
		}

		public static void Tick()
		{
			if ((Object)(object)_root == (Object)null)
			{
				DestroyLiveGizmo();
				return;
			}
			if (AutoSpin)
			{
				_yaw = HolsterApplier.Wrap(_yaw + 30f * Time.deltaTime);
				ApplyRotation();
			}
			try
			{
				UpdateMarkers();
				UpdateLiveGizmo();
			}
			catch (Exception)
			{
				Destroy();
			}
		}

		private static void BakeRenderers(Transform src)
		{
			//IL_0001: 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_000b: 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_0012: 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_0052: Expected O, but got Unknown
			//IL_0087: 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)
			//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)
			//IL_009d: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_0141: Unknown result type (might be due to invalid IL or missing references)
			//IL_0144: Unknown result type (might be due to invalid IL or missing references)
			//IL_0149: Unknown result type (might be due to invalid IL or missing references)
			//IL_014a: Unknown result type (might be due to invalid IL or missing references)
			//IL_014f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0154: Unknown result type (might be due to invalid IL or missing references)
			//IL_0157: Unknown result type (might be due to invalid IL or missing references)
			//IL_015c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0163: Unknown result type (might be due to invalid IL or missing references)
			Quaternion val = Quaternion.Inverse(src.rotation);
			Vector3 position = src.position;
			foreach (SkinnedMeshRenderer componentsInChild in ((Component)src).GetComponentsInChildren<SkinnedMeshRenderer>(false))
			{
				if (!((Object)(object)componentsInChild == (Object)null) && ((Renderer)componentsInChild).enabled && !((Object)(object)componentsInChild.sharedMesh == (Object)null))
				{
					Mesh val2 = new Mesh();
					componentsInChild.BakeMesh(val2, true);
					_bakedMeshes.Add(val2);
					Transform transform = ((Component)componentsInChild).transform;
					AddStatic("Baked " + ((Object)componentsInChild).name, val2, ((Renderer)componentsInChild).sharedMaterials, val * (transform.position - position), val * transform.rotation, Vector3.one);
				}
			}
			foreach (MeshRenderer componentsInChild2 in ((Component)src).GetComponentsInChildren<MeshRenderer>(false))
			{
				if (!((Object)(object)componentsInChild2 == (Object)null) && ((Renderer)componentsInChild2).enabled)
				{
					MeshFilter component = ((Component)componentsInChild2).GetComponent<MeshFilter>();
					if (!((Object)(object)component == (Object)null) && !((Object)(object)component.sharedMesh == (Object)null))
					{
						Transform transform2 = ((Component)componentsInChild2).transform;
						AddStatic("Static " + ((Object)componentsInChild2).name, component.sharedMesh, ((Renderer)componentsInChild2).sharedMaterials, val * (transform2.position - position), val * transform2.rotation, transform2.lossyScale);
					}
				}
			}
		}

		private static void AddStatic(string name, Mesh mesh, Il2CppReferenceArray<Material> materials, Vector3 localPos, Quaternion localRot, Vector3 localScale)
		{
			//IL_0001: 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_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: 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_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: 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_0044: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = new GameObject(name);
			val.transform.SetParent(_model, false);
			val.transform.localPosition = localPos;
			val.transform.localRotation = localRot;
			val.transform.localScale = localScale;
			val.layer = 0;
			val.AddComponent<MeshFilter>().sharedMesh = mesh;
			MeshRenderer obj = val.AddComponent<MeshRenderer>();
			((Renderer)obj).sharedMaterials = materials;
			((Renderer)obj).shadowCastingMode = (ShadowCastingMode)0;
			((Renderer)obj).receiveShadows = false;
			if (materials != null && ((Il2CppArrayBase<Material>)(object)materials).Length > 0 && (Object)(object)((Il2CppArrayBase<Material>)(object)materials)[0] != (Object)null)
			{
				PreviewMaterials.SetFallbackShader(((Il2CppArrayBase<Material>)(object)materials)[0].shader);
			}
		}

		private static void BakeAnchorsAndVanilla(Transform src)
		{
			//IL_0001: 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_000b: 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_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_005c: Unknown result type (might be due to invalid IL or missing references)
			//IL_005d: Unknown result type (might be due to invalid IL or missing references)
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0060: 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_006a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0076: 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)
			//IL_0079: Unknown result type (might be due to invalid IL or missing references)
			//IL_007e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00db: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f9: Unknown result type (might be due to invalid IL or missing references)
			Quaternion val = Quaternion.Inverse(src.rotation);
			Vector3 position = src.position;
			foreach (BodyAnchor value in Enum.GetValues(typeof(BodyAnchor)))
			{
				int num = (int)value;
				_anchorValid[num] = AnchorResolver.TryGetFrame(value, out var position2, out var rotation);
				if (_anchorValid[num])
				{
					_anchorPos[num] = val * (position2 - position);
					_anchorRot[num] = val * rotation;
				}
			}
			foreach (HolsterSlot slot in HolsterRegistry.Slots)
			{
				if (slot.IsValid)
				{
					_vanillaPos[slot.Id] = val * (slot.VanillaWorldPosition - position);
					_vanillaRot[slot.Id] = val * slot.VanillaWorldRotation;
				}
			}
		}

		private static void BuildDisc()
		{
			//IL_0031: 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_0057: 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_00a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c6: Unknown result type (might be due to invalid IL or missing references)
			GameObject obj = Primitive((PrimitiveType)2, "Turntable Disc", _model);
			float num = _avatarHeight * 0.45f;
			obj.transform.localPosition = new Vector3(0f, -0.01f, 0f);
			obj.transform.localScale = new Vector3(num, 0.008f, num);
			SetColor(obj.GetComponent<Renderer>(), DiscColor);
			GameObject obj2 = Primitive((PrimitiveType)3, "Front Notch", _model);
			obj2.transform.localPosition = new Vector3(0f, 0f, num * 0.5f);
			obj2.transform.localScale = new Vector3(0.04f, 0.012f, 0.06f) * (_avatarHeight / 1.76f);
			SetColor(obj2.GetComponent<Renderer>(), SelectedColor);
		}

		private static void BuildMarkers()
		{
			//IL_004f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0059: Expected O, but got Unknown
			//IL_009d: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f9: Unknown result type (might be due to invalid IL or missing references)
			//IL_0112: Unknown result type (might be due to invalid IL or missing references)
			foreach (HolsterSlot slot in HolsterRegistry.Slots)
			{
				if (slot.IsValid && !_markers.ContainsKey(slot.Id))
				{
					Marker marker = new Marker();
					marker.Root = new GameObject("Marker " + slot.Id);
					marker.Root.transform.SetParent(_model, false);
					GameObject val = Primitive((PrimitiveType)0, "Ball", marker.Root.transform);
					marker.Ball = val.GetComponent<Renderer>();
					AddAxis(marker.Root.transform, Vector3.right, new Color(1f, 0.25f, 0.25f, 1f));
					AddAxis(marker.Root.transform, Vector3.up, new Color(0.3f, 1f, 0.3f, 1f));
					AddAxis(marker.Root.transform, Vector3.forward, new Color(0.3f, 0.5f, 1f, 1f));
					_markers[slot.Id] = marker;
				}
			}
		}

		private static void AddAxis(Transform parent, Vector3 dir, Color color)
		{
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: 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_006a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0089: Unknown result type (might be due to invalid IL or missing references)
			//IL_0094: Unknown result type (might be due to invalid IL or missing references)
			GameObject obj = Primitive((PrimitiveType)3, "Axis", parent);
			obj.transform.localPosition = dir * 0.9f;
			Vector3 localScale = default(Vector3);
			((Vector3)(ref localScale))..ctor(0.15f, 0.15f, 0.15f);
			if (dir.x != 0f)
			{
				localScale.x = 1.8f;
			}
			if (dir.y != 0f)
			{
				localScale.y = 1.8f;
			}
			if (dir.z != 0f)
			{
				localScale.z = 1.8f;
			}
			obj.transform.localScale = localScale;
			SetColor(obj.GetComponent<Renderer>(), color);
		}

		private static void ApplyRotation()
		{
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)_turntable != (Object)null)
			{
				_turntable.localRotation = Quaternion.Euler(_pitch, _yaw, 0f);
			}
		}

		private static void UpdateMarkers()
		{
			//IL_00b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00dd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00eb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fc: Unknown result type (might be due to invalid IL or missing references)
			//IL_0101: Unknown result type (might be due to invalid IL or missing references)
			//IL_0106: Unknown result type (might be due to invalid IL or missing references)
			//IL_0172: Unknown result type (might be due to invalid IL or missing references)
			//IL_0185: Unknown result type (might be due to invalid IL or missing references)
			//IL_0198: Unknown result type (might be due to invalid IL or missing references)
			//IL_019e: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01dc: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d5: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ce: Unknown result type (might be due to invalid IL or missing references)
			//IL_0222: Unknown result type (might be due to invalid IL or missing references)
			HolsterLayout current = LayoutManager.Current;
			float offsetScale = HolsterApplier.OffsetScale;
			float num = 0.035f * (_avatarHeight / 1.76f);
			foreach (HolsterSlot slot in HolsterRegistry.Slots)
			{
				if (_markers.TryGetValue(slot.Id, out var value) && !((Object)(object)value.Root == (Object)null))
				{
					HolsterPlacement holsterPlacement = ((current != null && Settings.Enabled.Value) ? current.Get(slot.Id) : null);
					bool flag = holsterPlacement != null && holsterPlacement.Moved && _anchorValid[(int)holsterPlacement.Anchor];
					Vector3 value2;
					Quaternion value3;
					if (flag)
					{
						int anchor = (int)holsterPlacement.Anchor;
						value2 = _anchorPos[anchor] + _anchorRot[anchor] * (holsterPlacement.Position.ToVector3() * offsetScale);
						value3 = _anchorRot[anchor] * Quaternion.Euler(holsterPlacement.Rotation.ToVector3());
					}
					else if (!_vanillaPos.TryGetValue(slot.Id, out value2) || !_vanillaRot.TryGetValue(slot.Id, out value3))
					{
						value.Root.SetActive(false);
						continue;
					}
					bool flag2 = slot.Id == SelectedId;
					value.Root.SetActive(true);
					value.Root.transform.localPosition = value2;
					value.Root.transform.localRotation = value3;
					value.Root.transform.localScale = Vector3.one * num * (flag2 ? 1.7f : 1f);
					Color color = (flag2 ? SelectedColor : (flag ? MovedColor : (slot.IsAmmoPouch ? AmmoColor : VanillaColor)));
					int num2 = ((!flag2) ? (flag ? 1 : (slot.IsAmmoPouch ? 2 : 3)) : 0);
					if (value.ColorKey != num2)
					{
						value.ColorKey = num2;
						SetColor(value.Ball, color);
					}
				}
			}
		}

		private static void UpdateLiveGizmo()
		{
			//IL_0071: Unknown result type (might be due to invalid IL or missing references)
			//IL_007b: Expected O, but got Unknown
			//IL_00ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bf: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ec: Unknown result type (might be due to invalid IL or missing references)
			//IL_0105: Unknown result type (might be due to invalid IL or missing references)
			//IL_0119: Unknown result type (might be due to invalid IL or missing references)
			//IL_0132: Unknown result type (might be due to invalid IL or missing references)
			//IL_0142: Unknown result type (might be due to invalid IL or missing references)
			//IL_0161: Unknown result type (might be due to invalid IL or missing references)
			//IL_0175: Unknown result type (might be due to invalid IL or missing references)
			//IL_0189: Unknown result type (might be due to invalid IL or missing references)
			//IL_0195: Unknown result type (might be due to invalid IL or missing references)
			HolsterSlot holsterSlot = (string.IsNullOrEmpty(SelectedId) ? null : HolsterRegistry.Find(SelectedId));
			if (!Settings.ShowLiveGizmo.Value || holsterSlot == null || !holsterSlot.IsValid)
			{
				DestroyLiveGizmo();
				return;
			}
			if ((Object)(object)_liveGizmo == (Object)null || (Object)(object)_liveGizmoTarget != (Object)(object)holsterSlot.Target)
			{
				DestroyLiveGizmo();
				_liveGizmoTarget = holsterSlot.Target;
				_liveGizmo = new GameObject("[Custom Holsters] Live Gizmo");
				_liveGizmo.transform.SetParent(holsterSlot.Target, false);
				SetColor(Primitive((PrimitiveType)0, "Ball", _liveGizmo.transform).GetComponent<Renderer>(), SelectedColor);
				AddAxis(_liveGizmo.transform, Vector3.right, new Color(1f, 0.25f, 0.25f, 1f));
				AddAxis(_liveGizmo.transform, Vector3.up, new Color(0.3f, 1f, 0.3f, 1f));
				AddAxis(_liveGizmo.transform, Vector3.forward, new Color(0.3f, 0.5f, 1f, 1f));
			}
			float num = Mathf.Max(holsterSlot.Target.lossyScale.x, 0.0001f);
			_liveGizmo.transform.localPosition = Vector3.zero;
			_liveGizmo.transform.localRotation = Quaternion.identity;
			_liveGizmo.transform.localScale = Vector3.one * (0.03f / num);
		}

		private static void DestroyLiveGizmo()
		{
			if ((Object)(object)_liveGizmo != (Object)null)
			{
				Object.Destroy((Object)(object)_liveGizmo);
			}
			_liveGizmo = null;
			_liveGizmoTarget = null;
		}

		private static GameObject Primitive(PrimitiveType type, string name, Transform parent)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			GameObject obj = GameObject.CreatePrimitive(type);
			((Object)obj).name = name;
			Collider component = obj.GetComponent<Collider>();
			if ((Object)(object)component != (Object)null)
			{
				Object.DestroyImmediate((Object)(object)component);
			}
			obj.transform.SetParent(parent, false);
			obj.layer = 0;
			Renderer component2 = obj.GetComponent<Renderer>();
			if ((Object)(object)component2 != (Object)null)
			{
				component2.shadowCastingMode = (ShadowCastingMode)0;
				component2.receiveShadows = false;
			}
			return obj;
		}

		private static void SetColor(Renderer renderer, Color color)
		{
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)renderer == (Object)null))
			{
				Material val = PreviewMaterials.Get(color);
				if ((Object)(object)val != (Object)null)
				{
					renderer.sharedMaterial = val;
				}
			}
		}

		private static void HolsterMenuNotify(string message)
		{
			HolsterMenu.Notify(message, warning: true);
		}
	}
	public static class PreviewMaterials
	{
		private static readonly Dictionary<int, Material> _cache = new Dictionary<int, Material>();

		private static Shader _shader;

		private static Shader _fallback;

		private static readonly string[] ShaderNames = new string[4] { "Universal Render Pipeline/Unlit", "Universal Render Pipeline/Simple Lit", "Universal Render Pipeline/Lit", "Unlit/Color" };

		public static void SetFallbackShader(Shader shader)
		{
			if ((Object)(object)shader != (Object)null && (Object)(object)_fallback == (Object)null)
			{
				_fallback = shader;
			}
		}

		public static Material Get(Color color)
		{
			//IL_0000: 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_0021: 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_006c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0072: Expected O, but got Unknown
			//IL_008d: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ca: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d0: Unknown result type (might be due to invalid IL or missing references)
			int key = ((int)(color.r * 255f) << 24) | ((int)(color.g * 255f) << 16) | ((int)(color.b * 255f) << 8) | (int)(color.a * 255f);
			if (_cache.TryGetValue(key, out var value) && (Object)(object)value != (Object)null)
			{
				return value;
			}
			Shader val = FindShader();
			if ((Object)(object)val == (Object)null)
			{
				return null;
			}
			value = new Material(val);
			((Object)value).hideFlags = (HideFlags)32;
			if (value.HasProperty("_BaseColor"))
			{
				value.SetColor("_BaseColor", color);
			}
			if (value.HasProperty("_Color"))
			{
				value.SetColor("_Color", color);
			}
			if (value.HasProperty("_EmissionColor"))
			{
				value.EnableKeyword("_EMISSION");
				value.SetColor("_EmissionColor", color * 0.6f);
			}
			_cache[key] = value;
			return value;
		}

		private static Shader FindShader()
		{
			if ((Object)(object)_shader != (Object)null)
			{
				return _shader;
			}
			string[] shaderNames = ShaderNames;
			for (int i = 0; i < shaderNames.Length; i++)
			{
				Shader val = Shader.Find(shaderNames[i]);
				if ((Object)(object)val != (Object)null)
				{
					_shader = val;
					return val;
				}
			}
			return _fallback;
		}
	}
}
namespace CustomHolsters.Menu
{
	public static class HolsterMenu
	{
		private enum StepSize
		{
			Fine,
			Normal,
			Coarse
		}

		private static readonly Color Accent = new Color(0.35f, 0.85f, 1f, 1f);

		private static readonly Color Gold = new Color(1f, 0.85f, 0.2f, 1f);

		private static readonly Color Soft = new Color(0.8f, 0.8f, 0.85f, 1f);

		private static readonly Color Muted = new Color(0.55f, 0.55f, 0.6f, 1f);

		private static readonly Color Good = new Color(0.4f, 1f, 0.55f, 1f);

		private static readonly Color Danger = new Color(1f, 0.4f, 0.35f, 1f);

		private static readonly Color PosColor = new Color(0.55f, 0.9f, 1f, 1f);

		private static readonly Color RotColor = new Color(1f, 0.7f, 0.95f, 1f);

		private static bool _built;

		private static Page _root;

		private static Page _editor;

		private static Page _choose;

		private static Page _anchors;

		private static Page _quick;

		private static Page _preview;

		private static Page _layouts;

		private static Page _load;

		private static Page _settings;

		private static FunctionElement _status;

		private static FunctionElement _selected;

		private static FunctionElement _state;

		private static FunctionElement _anchorButton;

		private static FunctionElement _stepButton;

		private static FunctionElement _layoutLabel;

		private static FunctionElement _avatarLabel;

		private static FunctionElement _fusionLabel;

		private static FloatElement _px;

		private static FloatElement _py;

		private static FloatElement _pz;

		private static FloatElement _rx;

		private static FloatElement _ry;

		private static FloatElement _rz;

		private static FloatElement _grab;

		private static FloatElement _globalGrab;

		private static FloatElement _previewSize;

		private static BoolElement _enabled;

		private static BoolElement _scaleWithAvatar;

		private static BoolElement _previewToggle;

		private static int _selectedIndex;

		private static StepSize _step = StepSize.Normal;

		private static string _pendingName = "My Layout";

		private static float _countdownEnd = -1f;

		private static int _countdownShown;

		private static string _countdownMessage;

		private static Action _countdownAction;

		private static float _nextStatusRefresh;

		private static HolsterSlot Selected
		{
			get
			{
				int count = HolsterRegistry.Slots.Count;
				if (count == 0)
				{
					return null;
				}
				_selectedIndex = (_selectedIndex % count + count) % count;
				HolsterSlot holsterSlot = HolsterRegistry.Slots[_selectedIndex];
				if (!holsterSlot.IsValid)
				{
					return null;
				}
				return holsterSlot;
			}
		}

		public static void Build()
		{
			//IL_001f: 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_0095: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e8: Unknown result type (might be due to invalid IL or missing references)
			//IL_0103: Unknown result type (might be due to invalid IL or missing references)
			//IL_011e: Unknown result type (might be due to invalid IL or missing references)
			if (!_built && Page.Root != null)
			{
				_built = true;
				_root = Page.Root.CreatePage("Custom Holsters", Accent, 0, true);
				TrySetLogo(_root);
				_enabled = _root.CreateBool("Enabled", Good, Settings.Enabled.Value, (Action<bool>)delegate(bool v)
				{
					Settings.Enabled.Value = v;
					Settings.Save();
					HolsterApplier.MarkGrabDirty();
				});
				((Element)_enabled).ElementTooltip = "Master switch. Off returns every holster to its vanilla spot.";
				_status = _root.CreateFunction("Status: waiting for a level", Muted, (Action)delegate
				{
					RefreshStatus();
				});
				_editor = _root.CreatePage("Holster Editor", Gold, 0, true);
				_preview = _root.CreatePage("3D Avatar Preview", Accent, 0, true);
				_layouts = _root.CreatePage("Layouts", Good, 0, true);
				_settings = _root.CreatePage("Settings & Resets", Soft, 0, true);
				BuildEditor();
				BuildPreview();
				BuildLayouts();
				BuildSettings();
				LayoutManager.LayoutSwitched += delegate
				{
					RefreshAll();
					RebuildLoadList();
				};
				LayoutManager.LibraryChanged += delegate
				{
					RebuildLoadList();
					RefreshLayoutLabels();
				};
				RebuildLoadList();
				RefreshAll();
			}
		}

		private static void BuildEditor()
		{
			//IL_000a: 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_0085: 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_00d4: Unknown result type (might be due to invalid IL or missing references)
			//IL_010c: 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_0199: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e0: Unknown result type (might be due to invalid IL or missing references)
			//IL_0223: Unknown result type (might be due to invalid IL or missing references)
			//IL_026f: Unknown result type (might be due to invalid IL or missing references)
			//IL_02bb: Unknown result type (might be due to invalid IL or missing references)
			//IL_0307: Unknown result type (might be due to invalid IL or missing references)
			//IL_0353: Unknown result type (might be due to invalid IL or missing references)
			//IL_039f: Unknown result type (might be due to invalid IL or missing references)
			//IL_03fa: Unknown result type (might be due to invalid IL or missing references)
			//IL_0451: Unknown result type (might be due to invalid IL or missing references)
			//IL_0483: Unknown result type (might be due to invalid IL or missing references)
			//IL_052b: Unknown result type (might be due to invalid IL or missing references)
			//IL_055f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0593: Unknown result type (might be due to invalid IL or missing references)
			//IL_04d6: Unknown result type (might be due to invalid IL or missing references)
			//IL_05c7: Unknown result type (might be due to invalid IL or missing references)
			//IL_05fb: Unknown result type (might be due to invalid IL or missing references)
			_selected = _editor.CreateFunction("Holster: (load a level)", Gold, (Action)delegate
			{
				SelectOffset(1);
			});
			((Element)_selected).ElementTooltip = "Press to cycle to the next holster.";
			_editor.CreateFunction("< Previous Holster", Soft, (Action)delegate
			{
				SelectOffset(-1);
			});
			_editor.CreateFunction("Next Holster >", Soft, (Action)delegate
			{
				SelectOffset(1);
			});
			_choose = _editor.CreatePage("Choose Holster...", Soft, 0, true);
			_state = _editor.CreateFunction("State: -", Muted, (Action)delegate
			{
			});
			_anchors = _editor.CreatePage("Attach To (body part)", Accent, 0, false);
			foreach (BodyAnchor value in Enum.GetValues(typeof(BodyAnchor)))
			{
				BodyAnchor a = value;
				_anchors.CreateFunction(BodyAnchorUtil.Pretty(a), Soft, (Action)delegate
				{
					HolsterSlot selected = Selected;
					if (selected != null)
					{
						HolsterApplier.Reanchor(selected, a);
						RefreshEditor();
						Menu.OpenPage(_editor);
					}
				});
			}
			_anchorButton = _editor.CreateFunction("Attach To: -", Accent, (Action)delegate
			{
				Menu.OpenPage(_anchors);
			});
			((Element)_anchorButton).ElementTooltip = "Choose which body part this holster follows. The holster stays where it is; only its anchor changes.";
			_stepButton = _editor.CreateFunction("", Soft, (Action)CycleStep);
			((Element)_stepButton).ElementTooltip = "How far each +/- press moves or rotates the holster.";
			_px = _editor.CreateFloat("Left / Right (cm)", PosColor, 0f, 1f, -150f, 150f, (Action<float>)delegate(float v)
			{
				SetPosition(0, v);
			});
			_py = _editor.CreateFloat("Down / Up (cm)", PosColor, 0f, 1f, -150f, 150f, (Action<float>)delegate(float v)
			{
				SetPosition(1, v);
			});
			_pz = _editor.CreateFloat("Back / Forward (cm)", PosColor, 0f, 1f, -150f, 150f, (Action<float>)delegate(float v)
			{
				SetPosition(2, v);
			});
			_rx = _editor.CreateFloat("Pitch (deg)", RotColor, 0f, 5f, -180f, 180f, (Action<float>)delegate(float v)
			{
				SetRotation(0, v);
			});
			_ry = _editor.CreateFloat("Yaw (deg)", RotColor, 0f, 5f, -180f, 180f, (Action<float>)delegate(float v)
			{
				SetRotation(1, v);
			});
			_rz = _editor.CreateFloat("Roll (deg)", RotColor, 0f, 5f, -180f, 180f, (Action<float>)delegate(float v)
			{
				SetRotation(2, v);
			});
			((Element)_px).ElementTooltip = "Offsets are relative to the chosen body part, measured for a 1.76 m avatar and scaled to yours.";
			_grab = _editor.CreateFloat("Grab Radius (x)", Good, 1f, 0.1f, 0.1f, 5f, (Action<float>)SetGrabRadius);
			((Element)_grab).ElementTooltip = "How close your hand/item must be to use this holster. 1 = vanilla.";
			_quick = _editor.CreatePage("Quick Place...", Gold, 0, true);
			foreach (string item in Presets.Groups())
			{
				Page val = _quick.CreatePage(item, Soft, 0, true);
				foreach (HolsterPreset item2 in Presets.All)
				{
					if (item2.Group != item)
					{
						continue;
					}
					HolsterPreset p = item2;
					val.CreateFunction(p.Name, Soft, (Action)delegate
					{
						HolsterSlot selected = Selected;
						if (selected != null)
						{
							Presets.Apply(selected, p);
							RefreshEditor();
							Notify(selected.DisplayName + " -> " + p.Name, warning: false);
						}
					});
				}
			}
			_editor.CreateFunction("Place At Left Hand (3s)", Accent, (Action)delegate
			{
				StartHandPlacement(left: true);
			});
			_editor.CreateFunction("Place At Right Hand (3s)", Accent, (Action)delegate
			{
				StartHandPlacement(left: false);
			});
			_editor.CreateFunction("Mirror To Opposite Side", Accent, (Action)delegate
			{
				HolsterSlot selected = Selected;
				if (selected != null)
				{
					HolsterSlot holsterSlot = Mirroring.MirrorToOpposite(selected);
					RefreshEditor();
					Notify((holsterSlot == selected) ? ("Mirrored " + selected.DisplayName + " in place") : ("Mirrored onto " + holsterSlot.DisplayName), warning: false);
				}
			});
			_editor.CreateFunction("Toggle 3D Preview", Accent, (Action)delegate
			{
				SetPreview(!AvatarPreview.IsVisible);
			});
			_editor.CreateFunction("Reset This Holster", Danger, (Action)delegate
			{
				HolsterSlot selected = Selected;
				if (selected != null)
				{
					HolsterApplier.ResetSlot(selected, resetGrabRadius: true);
					RefreshEditor();
					Notify(selected.DisplayName + " reset to vanilla", warning: false);
				}
			});
			ApplyStep();
		}

		private static void BuildPreview()
		{
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0052: 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_00ba: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ee: Unknown result type (might be due to invalid IL or missing references)
			//IL_0122: Unknown result type (might be due to invalid IL or missing references)
			//IL_0156: Unknown result type (might be due to invalid IL or missing references)
			//IL_018a: Unknown result type (might be due to invalid IL or missing references)
			//IL_01be: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f2: Unknown result type (might be due to invalid IL or missing references)
			//IL_0227: Unknown result type (might be due to invalid IL or missing references)
			//IL_025b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0298: Unknown result type (might be due to invalid IL or missing references)
			//IL_02e9: Unknown result type (might be due to invalid IL or missing references)
			//IL_0327: Unknown result type (might be due to invalid IL or missing references)
			_previewToggle = _preview.CreateBool("Show Preview", Good, false, (Action<bool>)delegate(bool v)
			{
				SetPreview(v);
			});
			((Element)_previewToggle).ElementTooltip = "Shows a small figure of your current avatar in front of you with every holster marked.";
			_preview.CreateFunction("Rotate Left 15", Soft, (Action)delegate
			{
				AvatarPreview.Rotate(-15f);
			});
			_preview.CreateFunction("Rotate Right 15", Soft, (Action)delegate
			{
				AvatarPreview.Rotate(15f);
			});
			_preview.CreateFunction("Tilt Up", Soft, (Action)delegate
			{
				AvatarPreview.Tilt(-15f);
			});
			_preview.CreateFunction("Tilt Down", Soft, (Action)delegate
			{
				AvatarPreview.Tilt(15f);
			});
			_preview.CreateFunction("View Front", Soft, (Action)delegate
			{
				AvatarPreview.SetView(0f);
			});
			_preview.CreateFunction("View Back", Soft, (Action)delegate
			{
				AvatarPreview.SetView(180f);
			});
			_preview.CreateFunction("View Left Side", Soft, (Action)delegate
			{
				AvatarPreview.SetView(90f);
			});
			_preview.CreateFunction("View Right Side", Soft, (Action)delegate
			{
				AvatarPreview.SetView(-90f);
			});
			_preview.CreateBool("Auto Spin", Soft, false, (Action<bool>)delegate(bool v)
			{
				AvatarPreview.AutoSpin = v;
			});
			_preview.CreateFunction("Recenter In Front Of Me", Accent, (Action)delegate
			{
				AvatarPreview.Recenter();
			});
			((Element)_preview.CreateFunction("Refresh Pose", Accent, (Action)delegate
			{
				if (AvatarPreview.IsVisible)
				{
					AvatarPreview.Rebuild();
				}
			})).ElementTooltip = "Re-captures your avatar's current pose for the preview figure.";
			_previewSize = _preview.CreateFloat("Preview Size (m)", Soft, Settings.PreviewHeight.Value, 0.1f, 0.2f, 1.5f, (Action<float>)delegate(float v)
			{
				Settings.PreviewHeight.Value = v;
				Settings.Save();
				if (AvatarPreview.IsVisible)
				{
					AvatarPreview.Rebuild();
				}
			});
			_preview.CreateBool("Live Gizmo On Real Holster", Soft, Settings.ShowLiveGizmo.Value, (Action<bool>)delegate(bool v)
			{
				Settings.ShowLiveGizmo.Value = v;
				Settings.Save();
			});
			((Element)_preview.CreateFunction("Legend: Yellow=Editing Cyan=Moved", Muted, (Action)delegate
			{
			})).ElementTooltip = "Yellow = holster being edited, Cyan = moved, White = vanilla, Orange = ammo pouch. Red/green/blue sticks = holster X/Y/Z.";
		}

		private static void BuildLayouts()
		{
			//IL_000a: 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_007a: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f0: Unknown result type (might be due to invalid IL or missing references)
			//IL_0124: Unknown result type (might be due to invalid IL or missing references)
			//IL_0158: Unknown result type (might be due to invalid IL or missing references)
			//IL_0173: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e4: Unknown result type (might be due to invalid IL or missing references)
			//IL_0218: Unknown result type (might be due to invalid IL or missing references)
			//IL_0256: Unknown result type (might be due to invalid IL or missing references)
			//IL_0294: Unknown result type (might be due to invalid IL or missing references)
			//IL_02c8: Unknown result type (might be due to invalid IL or missing references)
			_layoutLabel = _layouts.CreateFunction("Active: -", Gold, (Action)delegate
			{
			});
			_avatarLabel = _layouts.CreateFunction("Avatar: -", Muted, (Action)delegate
			{
			});
			((Element)_layouts.CreateString("Layout Name", Soft, _pendingName, (Action<string>)delegate(string v)
			{
				_pendingName = v;
			})).ElementTooltip = "Name used by Save As New and New Vanilla Layout.";
			_layouts.CreateFunction("Save", Good, (Action)delegate
			{
				LayoutManager.Save();
				Notify("Saved '" + LayoutManager.Current.Name + "'", warning: false);
			});
			_layouts.CreateFunction("Save As New (uses name)", Good, (Action)delegate
			{
				string text = LayoutManager.SaveAs(_pendingName);
				Notify("Saved as '" + text + "'", warning: false);
			});
			_layouts.CreateFunction("New Vanilla Layout (uses name)", Soft, (Action)delegate
			{
				string text = LayoutManager.CreateNew(_pendingName);
				Notify("Created '" + text + "'", warning: false);
			});
			_load = _layouts.CreatePage("Load Layout...", Accent, 0, true);
			_layouts.CreateFunction("Use As Default Layout", Soft, (Action)delegate
			{
				LayoutManager.SetCurrentAsDefault();
				RefreshLayoutLabels();
				Notify("'" + LayoutManager.Current.Name + "' is now the default", warning: false);
			});
			((Element)_layouts.CreateFunction("Bind Layout To This Avatar", Accent, (Action)delegate
			{
				if (string.IsNullOrEmpty(LayoutManager.CurrentAvatarBarcode))
				{
					Notify("No avatar detected yet", warning: true);
				}
				else
				{
					LayoutManager.BindCurrentAvatar();
					Notify("This avatar now uses '" + LayoutManager.Current.Name + "'", warning: false);
				}
			})).ElementTooltip = "Whenever you switch into this avatar, this layout loads automatically.";
			_layouts.CreateFunction("Unbind This Avatar", Soft, (Action)delegate
			{
				LayoutManager.UnbindCurrentAvatar();
				Notify("Avatar unbound (uses the default layout)", warning: false);
			});
			_layouts.CreateBool("Auto-Load Avatar Layouts", Soft, Settings.AutoLoadAvatarLayouts.Value, (Action<bool>)delegate(bool v)
			{
				Settings.AutoLoadAvatarLayouts.Value = v;
				Settings.Save();
			});
			_layouts.CreateBool("Auto-Save Edits", Soft, Settings.AutoSave.Value, (Action<bool>)delegate(bool v)
			{
				Settings.AutoSave.Value = v;
				Settings.Save();
			});
			_layouts.CreateFunction("Delete This Layout", Danger, (Action)delegate
			{
				string current = LayoutManager.Current.Name;
				Menu.DisplayDialog("Delete layout?", "Delete '" + current + "'? This can't be undone.", (Texture2D)null, (Action)delegate
				{
					LayoutManager.DeleteCurrent();
					Notify("Deleted '" + current + "'", warning: false);
				}, (Action)null);
			});
			_layouts.CreateFunction("Open Layouts Folder (desktop)", Muted, (Action)delegate
			{
				try
				{
					Application.OpenURL("file:///" + LayoutManager.LayoutDir.Replace('\\', '/'));
				}
				catch (Exception)
				{
					Notify(LayoutManager.LayoutDir, warning: false);
				}
			});
		}

		private static void BuildSettings()
		{
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0052: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f4: Unknown result type (might be due to invalid IL or missing references)
			//IL_0132: Unknown result type (might be due to invalid IL or missing references)
			//IL_0166: Unknown result type (might be due to invalid IL or missing references)
			//IL_019a: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ce: Unknown result type (might be due to invalid IL or missing references)
			//IL_0202: Unknown result type (might be due to invalid IL or missing references)
			//IL_0236: Unknown result type (might be due to invalid IL or missing references)
			//IL_026a: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_02db: Unknown result type (might be due to invalid IL or missing references)
			//IL_0322: Unknown result type (might be due to invalid IL or missing references)
			_scaleWithAvatar = _settings.CreateBool("Scale Offsets With Avatar", Soft, true, (Action<bool>)delegate(bool v)
			{
				LayoutManager.Current.ScaleWithAvatar = v;
				HolsterApplier.NotifyAllEdited();
				RefreshEditor();
			});
			((Element)_scaleWithAvatar).ElementTooltip = "On: one layout fits tall and short avatars. Off: offsets are exact meters. Saved per layout.";
			_globalGrab = _settings.CreateFloat("Global Grab Radius (x)", Good, 1f, 0.1f, 0.1f, 5f, (Action<float>)delegate(float v)
			{
				LayoutManager.Current.GlobalGrabRadius = v;
				HolsterApplier.MarkGrabDirty();
				LayoutManager.MarkEdited();
			});
			((Element)_globalGrab).ElementTooltip = "Multiplies every holster's grab radius. Saved per layout.";
			((Element)_settings.CreateBool("Re-seat Holstered Items", Soft, Settings.ReseatHolsteredItems.Value, (Action<bool>)delegate(bool v)
			{
				Settings.ReseatHolsteredItems.Value = v;
				Settings.Save();
			})).ElementTooltip = "After moving a holster, snap the item it holds to the new spot. Skipped in Fusion lobbies.";
			_settings.CreateBool("Hand Placement Copies Rotation", Soft, Settings.CopyHandRotation.Value, (Action<bool>)delegate(bool v)
			{
				Settings.CopyHandRotation.Value = v;
				Settings.Save();
			});
			_settings.CreateFunction("Copy Left Side -> Right", Accent, (Action)delegate
			{
				int num = Mirroring.CopySide(-1);
				RefreshEditor();
				Notify("Mirrored " + num + " holster(s) to the right", warning: false);
			});
			_settings.CreateFunction("Copy Right Side -> Left", Accent, (Action)delegate
			{
				int num = Mirroring.CopySide(1);
				RefreshEditor();
				Notify("Mirrored " + num + " holster(s) to the left", warning: false);
			});
			_settings.CreateFunction("Flip Whole Layout (L <-> R)", Accent, (Action)delegate
			{
				Mirroring.FlipWholeLayout();
				RefreshEditor();
				Notify("Layout flipped", warning: false);
			});
			_settings.CreateFunction("Reset All Positions", Danger, (Action)delegate
			{
				Confirm("Reset all positions?", "Every holster goes back to its vanilla spot (grab radius kept).", delegate
				{
					foreach (HolsterSlot slot in HolsterRegistry.Slots)
					{
						HolsterApplier.ResetSlot(slot, resetGrabRadius: false);
					}
					RefreshEditor();
					Notify("All holsters reset", warning: false);
				});
			});
			_settings.CreateFunction("Reset All Grab Radii", Danger, (Action)delegate
			{
				LayoutManager.Current.GlobalGrabRadius = 1f;
				foreach (HolsterPlacement value in LayoutManager.Current.Holsters.Values)
				{
					if (value != null)
					{
						value.GrabRadius = 1f;
					}
				}
				HolsterApplier.NotifyAllEdited();
				RefreshAll();
				Notify("Grab radii reset", warning: false);
			});
			_settings.CreateFunction("Reset Layout To Vanilla", Danger, (Action)delegate
			{
				Confirm("Reset whole layout?", "Clears every position and grab radius in '" + LayoutManager.Current.Name + "'.", delegate
				{
					LayoutManager.Current.Holsters.Clear();
					LayoutManager.Current.GlobalGrabRadius = 1f;
					HolsterApplier.NotifyAllEdited();
					RefreshAll();
					Notify("Layout reset to vanilla", warning: false);
				});
			});
			((Element)_settings.CreateFunction("Recalibrate (stand straight, 3s)", Soft, (Action)delegate
			{
				StartCountdown("Stand straight, arms relaxed", delegate
				{
					if (Core.Instance != null)
					{
						Core.Instance.ScheduleSetup(avatarChanged: false);
					}
					Notify("Recalibrated", warning: false);
				});
			})).ElementTooltip = "Re-measures your avatar's body parts. Use if limb holsters look twisted.";
			_settings.CreateFunction("Rescan Holsters", Soft, (Action)delegate
			{
				HolsterRegistry.Clear(restore: true);
				if (Core.Instance != null)
				{
					Core.Instance.ScheduleSetup(avatarChanged: false);
				}
			});
			_fusionLabel = _settings.CreateFunction("Fusion: -", Muted, (Action)delegate
			{
				RefreshStatus();
			});
			((Element)_fusionLabel).ElementTooltip = "Holster placement is local. Others see your holstered items at default spots.";
			_settings.CreateFunction("Custom Holsters v1.0.0", Muted, (Action)delegate
			{
			});
		}

		private static void SelectOffset(int delta)
		{
			_selectedIndex += delta;
			RefreshEditor();
		}

		private static void Select(HolsterSlot slot)
		{
			int num = HolsterRegistry.Slots.IndexOf(slot);
			if (num >= 0)
			{
				_selectedIndex = num;
			}
			RefreshEditor();
		}

		private static void SetPosition(int axis, float cm)
		{
			HolsterSlot selected = Selected;
			if (selected != null)
			{
				HolsterPlacement holsterPlacement = HolsterApplier.BeginEdit(selected);
				float num = cm / 100f;
				switch (axis)
				{
				case 0:
					holsterPlacement.Position.x = num;
					break;
				case 1:
					holsterPlacement.Position.y = num;
					break;
				default:
					holsterPlacement.Position.z = num;
					break;
				}
				HolsterApplier.NotifyEdited(selected);
				RefreshStateLabel(selected);
			}
		}

		private static void SetRotation(int axis, float degrees)
		{
			HolsterSlot selected = Selected;
			if (selected != null)
			{
				HolsterPlacement holsterPlacement = HolsterApplier.BeginEdit(selected);
				switch (axis)
				{
				case 0:
					holsterPlacement.Rotation.x = degrees;
					break;
				case 1:
					holsterPlacement.Rotation.y = degrees;
					break;
				default:
					holsterPlacement.Rotation.z = degrees;
					break;
				}
				HolsterApplier.NotifyEdited(selected);
				RefreshStateLabel(selected);
			}
		}

		private static void SetGrabRadius(float value)
		{
			HolsterSlot selected = Selected;
			if (selected != null)
			{
				LayoutManager.Current.GetOrCreate(selected.Id).GrabRadius = value;
				HolsterApplier.MarkGrabDirty();
				LayoutManager.MarkEdited();
			}
		}

		private static void CycleStep()
		{
			_step = (StepSize)((int)(_step + 1) % 3);
			ApplyStep();
		}

		private static void ApplyStep()
		{
			float incrementValue = ((_step == StepSize.Fine) ? 0.5f : ((_step == StepSize.Normal) ? 1f : 5f));
			float incrementValue2 = ((_step == StepSize.Fine) ? 1f : ((_step == StepSize.Normal) ? 5f : 15f));
			_px.IncrementValue = incrementValue;
			_py.IncrementValue = incrementValue;
			_pz.IncrementValue = incrementValue;
			_rx.IncrementValue = incrementValue2;
			_ry.IncrementValue = incrementValue2;
			_rz.IncrementValue = incrementValue2;
			((Element)_stepButton).ElementName = "Step: " + _step.ToString() + " (" + incrementValue + " cm / " + incrementValue2 + " deg)";
		}

		private static void StartHandPlacement(bool left)
		{
			HolsterSlot selected = Selected;
			if (selected == null)
			{
				return;
			}
			string id = selected.Id;
			StartCountdown("Hold your " + (left ? "left" : "right") + " hand where " + selected.DisplayName + " should go", delegate
			{
				//IL_0058: 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)
				Hand val = (left ? Player.LeftHand : Player.RightHand);
				HolsterSlot holsterSlot = HolsterRegistry.Find(id);
				if (!((Object)(object)val == (Object)null) && holsterSlot != null)
				{
					Transform transform = ((Component)val).transform;
					Quaternion? worldRot = null;
					if (Settings.CopyHandRotation.Value)
					{
						worldRot = transform.rotation;
					}
					HolsterApplier.PlaceAt(holsterSlot, transform.position, worldRot);
					RefreshEditor();
					Notify(holsterSlot.DisplayName + " placed", warning: false);
				}
			});
		}

		private static void StartCountdown(string message, Action action)
		{
			_countdownMessage = message;
			_countdownAction = action;
			_countdownEnd = Time.realtimeSinceStartup + 3f;
			_countdownShown = 4;
		}

		private static void Confirm(string title, string message, Action action)
		{
			Menu.DisplayDialog(title, message, (Texture2D)null, action, (Action)null);
		}

		private static void SetPreview(bool visible)
		{
			AvatarPreview.SetVisible(visible);
			if (_previewToggle != null)
			{
				_previewToggle.Value = AvatarPreview.IsVisible;
			}
			RefreshEditor();
		}

		public static void OnRigReady()
		{
			//IL_006c: 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)
			if (!_built)
			{
				return;
			}
			_choose.RemoveAll();
			foreach (HolsterSlot slot in HolsterRegistry.Slots)
			{
				HolsterSlot s = slot;
				_choose.CreateFunction(s.DisplayName, (Color)(s.IsAmmoPouch ? new Color(1f, 0.6f, 0.3f, 1f) : Soft), (Action)delegate
				{
					Select(s);
					Menu.OpenPage(_editor);
				});
			}
			RefreshAll();
		}

		private static void RefreshAll()
		{
			if (_built)
			{
				RefreshEditor();
				RefreshLayoutLabels();
				RefreshStatus();
				if (_scaleWithAvatar != null && LayoutManager.Current != null)
				{
					_scaleWithAvatar.Value = LayoutManager.Current.ScaleWithAvatar;
				}
				if (_globalGrab != null && LayoutManager.Current != null)
				{
					_globalGrab.Value = LayoutManager.Current.GlobalGrabRadius;
				}
			}
		}

		private static void RefreshEditor()
		{
			//IL_00ef: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f5: Unknown result type (might be due to invalid IL or missing references)
			if (!_built)
			{
				return;
			}
			HolsterSlot selected = Selected;
			AvatarPreview.SelectedId = selected?.Id;
			if (selected == null || LayoutManager.Current == null || !AnchorResolver.IsCalibrated)
			{
				((Element)_selected).ElementName = "Holster: (load a level)";
				((Element)_state).ElementName = "State: -";
				((Element)_anchorButton).ElementName = "Attach To: -";
				return;
			}
			((Element)_selected).ElementName = "Holster: " + selected.DisplayName + "  (" + (_selectedIndex + 1) + "/" + HolsterRegistry.Slots.Count + ")";
			HolsterPlacement holsterPlacement = LayoutManager.Current.Get(selected.Id);
			HolsterPlacement holsterPlacement2 = holsterPlacement;
			if (holsterPlacement == null || !holsterPlacement.Moved)
			{
				holsterPlacement2 = new HolsterPlacement();
				HolsterApplier.CaptureFromWorld(holsterPlacement2, HolsterApplier.DefaultAnchorFor(selected), selected.VanillaWorldPosition, selected.VanillaWorldRotation);
				holsterPlacement2.GrabRadius = holsterPlacement?.GrabRadius ?? 1f;
			}
			((Element)_anchorButton).ElementName = "Attach To: " + BodyAnchorUtil.Pretty(holsterPlacement2.Anchor) + " >";
			_px.Value = Round(holsterPlacement2.Position.x * 100f);
			_py.Value = Round(holsterPlacement2.Position.y * 100f);
			_pz.Value = Round(holsterPlacement2.Position.z * 100f);
			_rx.Value = Round(holsterPlacement2.Rotation.x);
			_ry.Value = Round(holsterPlacement2.Rotation.y);
			_rz.Value = Round(holsterPlacement2.Rotation.z);
			_grab.Value = holsterPlacement2.GrabRadius;
			RefreshStateLabel(selected);
		}

		private static void RefreshStateLabel(HolsterSlot slot)
		{
			//IL_005f: 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)
			HolsterPlacement holsterPlacement = LayoutManager.Current.Get(slot.Id);
			bool flag = holsterPlacement?.Moved ?? false;
			((Element)_state).ElementName = (flag ? ("State: Custom" + (slot.HasItem ? " (holding item)" : "")) : "State: Vanilla position");
			((Element)_state).ElementColor = (flag ? Accent : Muted);
			if (flag)
			{
				((Element)_anchorButton).ElementName = "Attach To: " + BodyAnchorUtil.Pretty(holsterPlacement.Anchor) + " >";
			}
		}

		private static void RefreshLayoutLabels()
		{
			if (_built && LayoutManager.Current != null)
			{
				string name = LayoutManager.Current.Name;
				bool flag = string.Equals(name, Settings.DefaultLayout.Value, StringComparison.OrdinalIgnoreCase);
				((Element)_layoutLabel).ElementName = "Active: " + name + (flag ? " (default)" : "");
				string currentAvatarBarcode = LayoutManager.CurrentAvatarBarcode;
				if (string.IsNullOrEmpty(currentAvatarBarcode))
				{
					((Element)_avatarLabel).ElementName = "Avatar: -";
					return;
				}
				string binding = LayoutManager.GetBinding(currentAvatarBarcode);
				string s = (string.IsNullOrEmpty(LayoutManager.CurrentAvatarTitle) ? currentAvatarBarcode : LayoutManager.CurrentAvatarTitle);
				((Element)_avatarLabel).ElementName = "Avatar: " + Trim(s, 22) + ((binding != null) ? (" -> " + binding) : " (unbound)");
			}
		}

		private static void RebuildLoadList()
		{
			//IL_006a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0063: Unknown result type (might be due to invalid IL or missing references)
			if (!_built)
			{
				return;
			}
			_load.RemoveAll();
			foreach (string item in LayoutManager.ListLayouts())
			{
				string n = item;
				bool flag = LayoutManager.Current != null && string.Equals(n, LayoutManager.Current.Name, StringComparison.OrdinalIgnoreCase);
				_load.CreateFunction(n, flag ? Gold : Soft, (Action)delegate
				{
					if (LayoutManager.Load(n))
					{
						Notify("Loaded '" + n + "'", warning: false);
						RebuildLoadList();
					}
					else
					{
						Notify("Couldn't load '" + n + "'", warning: true);
					}
				});
			}
		}

		private static void RefreshStatus()
		{
			if (!_built)
			{
				return;
			}
			if (HolsterRegistry.Ready)
			{
				int num = 0;
				foreach (HolsterSlot slot in HolsterRegistry.Slots)
				{
					HolsterPlacement holsterPlacement = LayoutManager.Current.Get(slot.Id);
					if (holsterPlacement != null && holsterPlacement.Moved)
					{
						num++;
					}
				}
				((Element)_status).ElementName = "Status: " + num + "/" + HolsterRegistry.Slots.Count + " moved | " + Trim(LayoutManager.Current.Name, 16);
			}
			else
			{
				((Element)_status).ElementName = "Status: waiting for a level";
			}
			((Element)_fusionLabel).ElementName = FusionCompat.Status;
		}

		public static void Tick()
		{
			if (!_built)
			{
				return;
			}
			float realtimeSinceStartup = Time.realtimeSinceStartup;
			if (_countdownEnd > 0f)
			{
				int num = Mathf.CeilToInt(_countdownEnd - realtimeSinceStartup);
				if (num < _countdownShown && num > 0)
				{
					_countdownShown = num;
					Notify(_countdownMessage + "... " + num, warning: false, 0.9f);
				}
				if (realtimeSinceStartup >= _countdownEnd)
				{
					_countdownEnd = -1f;
					Action countdownAction = _countdownAction;
					_countdownAction = null;
					try
					{
						countdownAction?.Invoke();
					}
					catch (Exception ex)
					{
						Core.Log.Error("Countdown action failed: " + ex);
					}
				}
			}
			if (realtimeSinceStartup >= _nextStatusRefresh)
			{
				_nextStatusRefresh = realtimeSinceStartup + 1.5f;
				RefreshStatus();
				if (_previewToggle.Value != AvatarPreview.IsVisible)
				{
					_previewToggle.Value = AvatarPreview.IsVisible;
				}
			}
		}

		public static void Notify(string message, bool warning, float seconds = 2.5f)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: 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_0015: Unknown result type (might be due to invalid IL or missing references)
			//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_0021: 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_002e: 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_0041: Expected O, but got Unknown
			try
			{
				Notifier.Send(new Notification
				{
					Title = NotificationText.op_Implicit("Custom Holsters"),
					Message = NotificationText.op_Implicit(message),
					Type = (NotificationType)(warning ? 1 : 0),
					PopupLength = seconds,
					ShowTitleOnPopup = true
				});
			}
			catch (Exception)
			{
				Core.Log.Msg(message);
			}
		}

		private static float Round(float v)
		{
			return Mathf.Round(v * 10f) / 10f;
		}

		private static string Trim(string s, int max)
		{
			if (string.IsNullOrEmpty(s) || s.Length <= max)
			{
				return s;
			}
			return s.Substring(0, max - 1) + "~";
		}

		private static void TrySetLogo(Page page)
		{
			//IL_008d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0093: Expected O, but got Unknown
			try
			{
				Assembly assembly = typeof(HolsterMenu).Assembly;
				string text = null;
				string[] manifestResourceNames = assembly.GetManifestResourceNames();
				foreach (string text2 in manifestResourceNames)
				{
					if (text2.EndsWith("icon.png", StringComparison.OrdinalIgnoreCase))
					{
						text = text2;
					}
				}
				if (text == null)
				{
					return;
				}
				byte[] array;
				using (Stream stream = assembly.GetManifestResourceStream(text))
				{
					using MemoryStream memoryStream = new MemoryStream();
					stream.CopyTo(memoryStream);
					array = memoryStream.ToArray();
				}
				Texture2D val = new Texture2D(2, 2);
				if (ImageConversion.LoadImage(val, Il2CppStructArray<byte>.op_Implicit(array)))
				{
					((Object)val).hideFlags = (HideFlags)32;
					((Object)val).name = "CustomHolsters_Icon";
					page.Logo = val;
				}
			}
			catch (Exception ex)
			{
				Core.Log.Warning("Couldn't load menu icon: " + ex.Message);
			}
		}
	}
}
namespace CustomHolsters.Layouts
{
	[Serializable]
	public class Vec3
	{
		public float x;

		public float y;

		public float z;

		public Vec3()
		{
		}

		public Vec3(float x, float y, float z)
		{
			this.x = x;
			this.y = y;
			this.z = z;
		}

		public Vec3(Vector3 v)
		{
			//IL_0007: 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_001f: Unknown result type (might be due to invalid IL or missing references)
			x = v.x;
			y = v.y;
			z = v.z;
		}

		public Vector3 ToVector3()
		{
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			return new Vector3(x, y, z);
		}

		public Vec3 Clone()
		{
			return new Vec3(x, y, z);
		}
	}
	[Serializable]
	public class HolsterPlacement
	{
		public bool Moved;

		public BodyAnchor Anchor;

		public Vec3 Position = new Vec3();

		public Vec3 Rotation = new Vec3();

		public float GrabRadius = 1f;

		public bool IsDefault
		{
			get
			{
				if (!Moved)
				{
					return Mathf.Approximately(GrabRadius, 1f);
				}
				return false;
			}
		}

		public HolsterPlacement Clone()
		{
			return new HolsterPlacement
			{
				Moved = Moved,
				Anchor = Anchor,
				Position = Position.Clone(),
				Rotation = Rotation.Clone(),
				GrabRadius = GrabRadius
			};
		}
	}
	[Serializable]
	public class HolsterLayout
	{
		public const int CurrentFormat = 1;

		public int FormatVersion = 1;

		public string Name = "Default";

		public string ModVersion = "1.0.0";

		public bool ScaleWithAvatar = true;

		public float GlobalGrabRadius = 1f;

		public Dictionary<string, HolsterPlacement> Holsters = new Dictionary<string, HolsterPlacement>();

		public HolsterPlacement Get(string id)
		{
			if (!Holsters.TryGetValue(id, out var value))
			{
				return null;
			}
			return value;
		}

		public HolsterPlacement GetOrCreate(string id)
		{
			if (!Holsters.TryGetValue(id, out var value) || value == null)
			{
				value = new HolsterPlacement();
				Holsters[id] = value;
			}
			return value;
		}

		public HolsterLayout Clone(string newName)
		{
			HolsterLayout holsterLayout = new HolsterLayout
			{
				Name = newName,
				ScaleWithAvatar = ScaleWithAvatar,
				GlobalGrabRadius = GlobalGrabRadius
			};
			foreach (KeyValuePair<string, HolsterPlacement> holster in Holsters)
			{
				if (holster.Value != null)
				{
					holsterLayout.Holsters[holster.Key] = holster.Value.Clone();
				}
			}
			return holsterLayout;
		}

		public void Prune()
		{
			List<string> list = new List<string>();
			foreach (KeyValuePair<string, HolsterPlacement> holster in Holsters)
			{
				if (holster.Value == null || holster.Value.IsDefault)
				{
					list.Add(holster.Key);
				}
			}
			foreach (string item in list)
			{
				Holsters.Remove(item);
			}
		}

		public void Sanitize()
		{
			if (Holsters == null)
			{
				Holsters = new Dictionary<string, HolsterPlacement>();
			}
			if (float.IsNaN(GlobalGrabRadius) || GlobalGrabRadius <= 0f)
			{
				GlobalGrabRadius = 1f;
			}
			GlobalGrabRadius = Mathf.Clamp(GlobalGrabRadius, 0.1f, 5f);
			foreach (HolsterPlacement value in Holsters.Values)
			{
				if (value != null)
				{
					if (value.Position == null)
					{
						value.Position = new Vec3();
					}
					if (value.Rotation == null)
					{
						value.Rotation = new Vec3();
					}
					if (float.IsNaN(value.GrabRadius) || value.GrabRadius <= 0f)
					{
						value.GrabRadius = 1f;
					}
					value.GrabRadius = Mathf.Clamp(value.GrabRadius, 0.1f, 5f);
					if (!Enum.IsDefined(typeof(BodyAnchor), value.Anchor))
					{
						value.Anchor = BodyAnchor.Hips;
					}
				}
			}
		}
	}
	public static class LayoutManager
	{
		private static readonly JsonSerializerOptions JsonOptions = CreateJsonOptions();

		private static Dictionary<string, string> _bindings = new Dictionary<string, string>();

		private static float _saveAt = -1f;

		public static string RootDir { get; private set; }

		public static string LayoutDir { get; private set; }

		public static string BindingsPath { get; private set; }

		public static HolsterLayout Current { get; private set; }

		public static string CurrentAvatarBarcode { get; private set; } = "";

		public static string CurrentAvatarTitle { get; private set; } = "";

		public static bool HasPendingSave => _saveAt > 0f;

		public static int BindingCount => _bindings.Count;

		public static event Action LayoutSwitched;

		public static event Action LibraryChanged;

		private static JsonSerializerOptions CreateJsonOptions()
		{
			return new JsonSerializerOptions
			{
				IncludeFields = true,
				WriteIndented = true,
				ReadCommentHandling = JsonCommentHandling.Skip,
				AllowTrailingCommas = true,
				Converters = { (JsonConverter)new JsonStringEnumConverter() }
			};
		}

		public static void Init()
		{
			RootDir = Path.Combine(MelonEnvironment.UserDataDirectory, "CustomHolsters");
			LayoutDir = Path.Combine(RootDir, "Layouts");
			BindingsPath = Path.Combine(RootDir, "AvatarBindings.json");
			Directory.CreateDirectory(LayoutDir);
			LoadBindings();
			string text = Settings.DefaultLayout.Value;
			if (string.IsNullOrWhiteSpace(text))
			{
				text = "Default";
			}
			if (!Load(text, announce: false))
			{
				Current = new HolsterLayout
				{
					Name = SanitizeName(text)
				};
				Save();
			}
		}

		public static List<string> ListLayouts()
		{
			if (!Directory.Exists(LayoutDir))
			{
				return new List<string>();
			}
			return Directory.GetFiles(LayoutDir, "*.json").Select(Path.GetFileNameWithoutExtension).OrderBy<string, string>((string n) => n, StringComparer.OrdinalIgnoreCase)
				.ToList();
		}

		public static bool Exists(string name)
		{
			return File.Exists(PathFor(name));
		}

		public static bool Load(string name, bool announce = true)
		{
			FlushPendingSave();
			string path = PathFor(name);
			if (!File.Exists(path))
			{
				return false;
			}
			try
			{
				HolsterLayout holsterLayout = JsonSerializer.Deserialize<HolsterLayout>(File.ReadAllText(path), JsonOptions);
				if (holsterLayout == null)
				{
					return false;
				}
				holsterLayout.Name = Path.GetFileNameWithoutExtension(path);
				holsterLayout.Sanitize();
				Current = holsterLayout;
				if (announce)
				{
					Core.Log.Msg("Loaded layout '" + holsterLayout.Name + "'");
				}
				HolsterApplier.OnLayoutReplaced();
				if (LayoutManager.LayoutSwitched != null)
				{
					LayoutManager.LayoutSwitched();
				}
				return true;
			}
			catch (Exception ex)
			{
				Core.Log.Error("Failed to load layout '" + name + "': " + ex.Message);
				return false;
			}
		}

		public static void Save()
		{
			_saveAt = -1f;
			if (Current == null)
			{
				return;
			}
			try
			{
				Current.Name = SanitizeName(Current.Name);
				Current.ModVersion = "1.0.0";
				Current.FormatVersion = 1;
				Current.Prune();
				Directory.CreateDirectory(LayoutDir);
				string text = PathFor(Current.Name);
				string text2 = text + ".tmp";
				File.WriteAllText(text2, JsonSerializer.Serialize(Current, JsonOptions));
				if (File.Exists(text))
				{
					File.Delete(text);
				}
				File.Move(text2, text);
				if (LayoutManager.LibraryChanged != null)
				{
					LayoutManager.LibraryChanged();
				}
			}
			catch (Exception ex)
			{
				Core.Log.Error("Failed to save layout: " + ex.Message);
			}
		}

		public static string SaveAs(string name)
		{
			FlushPendingSave();
			name = UniqueName(SanitizeName(name));
			Current = Current.Clone(name);
			Save();
			if (LayoutManager.LayoutSwitched != null)
			{
				LayoutManager.LayoutSwitched();
			}
			return name;
		}

		public static string CreateNew(string name)
		{
			FlushPendingSave();
			name = UniqueName(SanitizeName(name));
			Current = new HolsterLayout
			{
				Name = name
			};
			Save();
			HolsterApplier.OnLayoutReplaced();
			if (LayoutManager.LayoutSwitched != null)
			{
				LayoutManager.LayoutSwitched();
			}
			return name;
		}

		public static void DeleteCurrent()
		{
			_saveAt = -1f;
			string name = Current.Name;
			try
			{
				if (File.Exists(PathFor(name)))
				{
					File.Delete(PathFor(name));
				}
			}
			catch (Exception ex)
			{
				Core.Log.Error("Failed to delete layout: " + ex.Message);
				return;
			}
			foreach (string item in (from kv in _bindings
				where kv.Value == name
				select kv.Key).ToList())
			{
				_bindings.Remove(item);
			}
			SaveBindings();
			string value = Settings.DefaultLayout.Value;
			if (value == name || !Load(value))
			{
				List<string> list = ListLayouts();
				if (list.Count == 0 || !Load(list[0]))
				{
					CreateNew("Default");
				}
				Settings.DefaultLayout.Value = Current.Name;
				Settings.Save();
			}
			if (LayoutManager.LibraryChanged != null)
			{
				LayoutManager.LibraryChanged();
			}
		}

		public static void SetCurrentAsDefault()
		{
			Settings.DefaultLayout.Value = Current.Name;
			Settings.Save();
		}

		public static void MarkEdited()
		{
			if (Settings.AutoSave.Value)
			{
				_saveAt = Time.realtimeSinceStartup + 1.5f;
			}
		}

		public static void Tick()
		{
			if (_saveAt > 0f && Time.realtimeSinceStartup >= _saveAt)
			{
				Save();
			}
		}

		public static void FlushPendingSave()
		{
			if (_saveAt > 0f)
			{
				Save();
			}
		}

		public static string GetBinding(string barcode)
		{
			if (!string.IsNullOrEmpty(barcode) && _bindings.TryGetValue(barcode, out var value))
			{
				return value;
			}
			return null;
		}

		public static void BindCurrentAvatar()
		{
			if (!string.IsNullOrEmpty(CurrentAvatarBarcode))
			{
				FlushPendingSave();
				if (!Exists(Current.Name))
				{
					Save();
				}
				_bindings[CurrentAvatarBarcode] = Current.Name;
				SaveBindings();
				if (LayoutManager.LibraryChanged != null)
				{
					LayoutManager.LibraryChanged();
				}
			}
		}

		public static void UnbindCurrentAvatar()
		{
			if (!string.IsNullOrEmpty(CurrentAvatarBarcode))
			{
				_bindings.Remove(CurrentAvatarBarcode);
				SaveBindings();
				if (LayoutManager.LibraryChanged != null)
				{
					LayoutManager.LibraryChanged();
				}
			}
		}

		public static void OnAvatarChanged(string barcode, string title)
		{
			CurrentAvatarBarcode = barcode ?? "";
			CurrentAvatarTitle = title ?? "";
			if (Settings.AutoLoadAvatarLayouts.Value)
			{
				string text = GetBinding(CurrentAvatarBarcode) ?? Settings.DefaultLayout.Value;
				if (!string.IsNullOrEmpty(text) && Current != null && !string.Equals(text, Current.Name, StringComparison.OrdinalIgnoreCase) && Exists(text))
				{
					Load(text);
				}
			}
		}

		private static void LoadBindings()
		{
			_bindings = new Dictionary<string, string>();
			try
			{
				if (File.Exists(BindingsPath))
				{
					Dictionary<string, string> dictionary = JsonSerializer.Deserialize<Dictionary<string, string>>(File.ReadAllText(BindingsPath), JsonOptions);
					if (dictionary != null)
					{
						_bindings = dictionary;
					}
				}
			}
			catch (Exception ex)
			{
				Core.Log.Error("Failed to read avatar bindings: " + ex.Message);
			}
		}

		private static void SaveBindings()
		{
			try
			{
				Directory.CreateDirectory(RootDir);
				File.WriteAllText(BindingsPath, JsonSerializer.Serialize(_bindings, JsonOptions));
			}
			catch (Exception ex)
			{
				Core.Log.Error("Failed to save avatar bindings: " + ex.Message);
			}
		}

		private static string PathFor(string name)
		{
			return Path.Combine(LayoutDir, SanitizeName(name) + ".json");
		}

		public static string SanitizeName(string name)
		{
			if (string.IsNullOrWhiteSpace(name))
			{
				return "Layout";
			}
			char[] invalidFileNameChars = Path.GetInvalidFileNameChars();
			StringBuilder stringBuilder = new StringBuilder();
			string text = name.Trim();
			foreach (char c in text)
			{
				stringBuilder.Append((Array.IndexOf(invalidFileNameChars, c) >= 0) ? '_' : c);
			}
			string text2 = stringBuilder.ToString().Trim('.', ' ');
			if (text2.Length > 48)
			{
				text2 = text2.Substring(0, 48);
			}
			if (text2.Length != 0)
			{
				return text2;
			}
			return "Layout";
		}

		public static string UniqueName(string name)
		{
			if (!Exists(name))
			{
				return name;
			}
			for (int i = 2; i < 1000; i++)
			{
				string text = name + " " + i;
				if (!Exists(text))
				{
					return text;
				}
			}
			return name + " " + DateTime.Now.Ticks;
		}
	}
	public static class Mirroring
	{
		public static HolsterPlacement Mirror(HolsterPlacement src)
		{
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_004f: 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_0057: Unknown result type (might be due to invalid IL or missing references)
			//IL_005d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0064: Unknown result type (might be due to invalid IL or missing references)
			//IL_006b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0079: Unknown result type (might be due to invalid IL or missing references)
			//IL_007e: Unknown result type (might be due to invalid IL or missing references)
			HolsterPlacement holsterPlacement = src.Clone();
			holsterPlacement.Anchor = BodyAnchorUtil.Mirror(src.Anchor);
			holsterPlacement.Position = new Vec3(0f - src.Position.x, src.Position.y, src.Position.z);
			Quaternion val = Quaternion.Euler(src.Rotation.ToVector3());
			Quaternion val2 = default(Quaternion);
			((Quaternion)(ref val2))..ctor(val.x, 0f - val.y, 0f - val.z, val.w);
			holsterPlacement.Rotation = new Vec3(HolsterApplier.NormalizeEuler(((Quaternion)(ref val2)).eulerAngles));
			return holsterPlacement;
		}

		public static HolsterSlot MirrorToOpposite(HolsterSlot slot)
		{
			HolsterLayout current = LayoutManager.Current;
			HolsterSlot holsterSlot = HolsterRegistry.FindMirrorPartner(slot);
			HolsterPlacement holsterPlacement = current.Get(slot.Id);
			if (holsterSlot == null)
			{
				HolsterPlacement src = HolsterApplier.BeginEdit(slot);
				current.Holsters[slot.Id] = Mirror(src);
				HolsterApplier.NotifyEdited(slot);
				return slot;
			}
			if (holsterPlacement == null || !holsterPlacement.Moved)
			{
				HolsterPlacement orCreate = current.GetOrCreate(holsterSlot.Id);
				orCreate.Moved = false;
				orCreate.GrabRadius = holsterPlacement?.GrabRadius ?? 1f;
			}
			else
			{
				current.Holsters[holsterSlot.Id] = Mirror(holsterPlacement);
			}
			HolsterApplier.NotifyEdited(holsterSlot);
			return holsterSlot;
		}

		public static int CopySide(int fromSide)
		{
			int num = 0;
			foreach (HolsterSlot slot in HolsterRegistry.Slots)
			{
				if (HolsterRegistry.SideOf(slot.Id) == fromSide && HolsterRegistry.FindMirrorPartner(slot) != null)
				{
					MirrorToOpposite(slot);
					num++;
				}
			}
			return num;
		}

		public static void FlipWholeLayout()
		{
			HolsterLayout current = LayoutManager.Current;
			HolsterLayout holsterLayout = current.Clone(current.Name);
			foreach (HolsterSlot slot in HolsterRegistry.Slots)
			{
				HolsterSlot holsterSlot = HolsterRegistry.FindMirrorPartner(slot);
				string id = ((holsterSlot != null) ? holsterSlot.Id : slot.Id);
				HolsterPlacement holsterPlacement = holsterLayout.Get(id);
				if (holsterPlacement == null || !holsterPlacement.Moved)
				{
					HolsterPlacement holsterPlacement2 = current.Get(slot.Id);
					if (holsterPlacement2 != null)
					{
						holsterPlacement2.Moved = false;
						holsterPlacement2.GrabRadius = holsterPlacement?.GrabRadius ?? 1f;
					}
				}
				else
				{
					current.Holsters[slot.Id] = Mirror(holsterPlacement);
				}
			}
			HolsterApplier.NotifyAllEdited();
		}
	}
	public sealed class HolsterPreset
	{
		public string Name;

		public string Group;

		public BodyAnchor Anchor;

		public Vector3 Position;

		public string OrientationFrom;

		public int Side;

		public HolsterPreset(string group, string name, BodyAnchor anchor, float x, float y, float z, string orientationFrom = null, int side = 0)
		{
			//IL_0022: 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)
			Group = group;
			Name = name;
			Anchor = anchor;
			Position = new Vector3(x, y, z);
			OrientationFrom = orientationFrom;
			Side = side;
		}
	}
	public static class Presets
	{
		public static readonly List<HolsterPreset> All = new List<HolsterPreset>
		{
			new HolsterPreset("Hips", "Left Hip", BodyAnchor.Hips, -0.17f, -0.02f, 0f, "Side", -1),
			new HolsterPreset("Hips", "Right Hip", BodyAnchor.Hips, 0.17f, -0.02f, 0f, "Side", 1),
			new HolsterPreset("Hips", "Left Front Hip", BodyAnchor.Hips, -0.12f, -0.02f, 0.1f, "Side", -1),
			new HolsterPreset("Hips", "Right Front Hip", BodyAnchor.Hips, 0.12f, -0.02f, 0.1f, "Side", 1),
			new HolsterPreset("Hips", "Front Belt", BodyAnchor.Hips, 0f, 0.04f, 0.15f),
			new HolsterPreset("Hips", "Lower Back", BodyAnchor.Hips, 0f, 0.06f, -0.15f, "Back"),
			new HolsterPreset("Chest", "Chest Center", BodyAnchor.Chest, 0f, 0.02f, 0.15f),
			new HolsterPreset("Chest", "Chest Left", BodyAnchor.Chest, -0.09f, 0.02f, 0.14f),
			new HolsterPreset("Chest", "Chest Right", BodyAnchor.Chest, 0.09f, 0.02f, 0.14f),
			new HolsterPreset("Shoulders & Back", "Left Shoulder", BodyAnchor.UpperChest, -0.18f, 0.1f, 0f, "Back", -1),
			new HolsterPreset("Shoulders & Back", "Right Shoulder", BodyAnchor.UpperChest, 0.18f, 0.1f, 0f, "Back", 1),
			new HolsterPreset("Shoulders & Back", "Back Left", BodyAnchor.UpperChest, -0.12f, 0.04f, -0.15f, "Back", -1),
			new HolsterPreset("Shoulders & Back", "Back Right", BodyAnchor.UpperChest, 0.12f, 0.04f, -0.15f, "Back", 1),
			new HolsterPreset("Shoulders & Back", "Back Center", BodyAnchor.UpperChest, 0f, 0.02f, -0.16f, "Back"),
			new HolsterPreset("Legs", "Left Thigh (Outer)", BodyAnchor.LeftThigh, -0.09f, -0.18f, 0f, "Side", -1),
			new HolsterPreset("Legs", "Right Thigh (Outer)", BodyAnchor.RightThigh, 0.09f, -0.18f, 0f, "Side", 1),
			new HolsterPreset("Legs", "Left Thigh (Front)", BodyAnchor.LeftThigh, -0.01f, -0.18f, 0.08f, "Side", -1),
			new HolsterPreset("Legs", "Right Thigh (Front)", BodyAnchor.RightThigh, 0.01f, -0.18f, 0.08f, "Side", 1),
			new HolsterPreset("Legs", "Left Shin", BodyAnchor.LeftShin, -0.06f, -0.2f, 0f, "Side", -1),
			new HolsterPreset("Legs", "Right Shin", BodyAnchor.RightShin, 0.06f, -0.2f, 0f, "Side", 1),
			new HolsterPreset("Arms", "Left Forearm", BodyAnchor.LeftForearm, 0f, -0.12f, 0.05f),
			new HolsterPreset("Arms", "Right Forearm", BodyAnchor.RightForearm, 0f, -0.12f, 0.05f),
			new HolsterPreset("Arms", "Left Upper Arm", BodyAnchor.LeftUpperArm, -0.06f, -0.12f, 0f),
			new HolsterPreset("Arms", "Right Upper Arm", BodyAnchor.RightUpperArm, 0.06f, -0.12f, 0f),
			new HolsterPreset("Head & Face", "Top Of Head", BodyAnchor.Head, 0f, 0.2f, 0f),
			new HolsterPreset("Head & Face", "Left Side Of Head", BodyAnchor.Head, -0.14f, 0.06f, 0f),
			new HolsterPreset("Head & Face", "Right Side Of Head", BodyAnchor.Head, 0.14f, 0.06f, 0f),
			new HolsterPreset("Head & Face", "In Front Of Face", BodyAnchor.HeadView, 0f, -0.03f, 0.25f),
			new HolsterPreset("Head & Face", "Behind Head", BodyAnchor.Head, 0f, 0.05f, -0.25f, "Back"),
			new HolsterPreset("Floating", "Floating In Front", BodyAnchor.Chest, 0f, 0.05f, 0.45f),
			new HolsterPreset("Floating", "Floating Left", BodyAnchor.Chest, -0.45f, 0.05f, 0.15f),
			new HolsterPreset("Floating", "Floating Right", BodyAnchor.Chest, 0.45f, 0.05f, 0.15f),
			new HolsterPreset("Floating", "Floating Overhead", BodyAnchor.Head, 0f, 0.45f, 0f)
		};

		public static IEnumerable<string> Groups()
		{
			List<string> seen = new List<string>();
			foreach (HolsterPreset item in All)
			{
				if (!seen.Contains(item.Group))
				{
					seen.Add(item.Group);
					yield return item.Group;
				}
			}
		}

		public static void Apply(HolsterSlot slot, HolsterPreset preset)
		{
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: 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_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_005c: Unknown result type (might be due to invalid IL or missing references)
			//IL_006d: Unknown result type (might be due to invalid IL or missing references)
			//IL_006f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0074: Unknown result type (might be due to invalid IL or missing references)
			//IL_0075: Unknown result type (might be due to invalid IL or missing references)
			//IL_007a: Unknown result type (might be due to invalid IL or missing references)
			//IL_007e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0083: Unknown result type (might be due to invalid IL or missing references)
			HolsterApplier.GetCurrentWorldPose(slot, out var _, out var rotation);
			Quaternion val = rotation;
			HolsterSlot holsterSlot = FindReference(preset.OrientationFrom, preset.Side);
			if (holsterSlot != null)
			{
				val = holsterSlot.VanillaWorldRotation;
			}
			HolsterPlacement orCreate = LayoutManager.Current.GetOrCreate(slot.Id);
			if (AnchorResolver.TryGetFrame(preset.Anchor, out var _, out var rotation2))
			{
				orCreate.Anchor = preset.Anchor;
				orCreate.Position = new Vec3(preset.Position);
				Quaternion val2 = Quaternion.Inverse(rotation2) * val;
				orCreate.Rotation = new Vec3(HolsterApplier.NormalizeEuler(((Quaternion)(ref val2)).eulerAngles));
				orCreate.Moved = true;
				HolsterApplier.NotifyEdited(slot);
			}
		}

		private static HolsterSlot FindReference(string kind, int side)
		{
			if (string.IsNullOrEmpty(kind))
			{
				return null;
			}
			HolsterSlot holsterSlot = null;
			foreach (HolsterSlot slot in HolsterRegistry.Slots)
			{
				if (!slot.IsAmmoPouch && slot.Id.IndexOf(kind, StringComparison.OrdinalIgnoreCase) >= 0)
				{
					if (HolsterRegistry.SideOf(slot.Id) == side)
					{
						return slot;
					}
					if (holsterSlot == null)
					{
						holsterSlot = slot;
					}
				}
			}
			if (side != 0)
			{
				return null;
			}
			return holsterSlot;
		}
	}
}
namespace CustomHolsters.Holsters
{
	public static class AnchorResolver
	{
		private sealed class Binding
		{
			public Transform Bone;

			public Transform LimbEnd;

			public Quaternion Correction;

			public bool UseRawRotation;
		}

		public const float ReferenceHeight = 1.76f;

		private static readonly Binding[] _bindings = new Binding[Enum.GetValues(typeof(BodyAnchor)).Length];

		private static Transform _root;

		private static float _scale = 1f;

		private static bool _humanoid;

		public static bool IsCalibrated { get; private set; }

		public static bool IsHumanoid => _humanoid;

		public static Transform Root => _root;

		public static float AvatarScale => _scale;

		public static void Clear()
		{
			for (int i = 0; i < _bindings.Length; i++)
			{
				_bindings[i] = null;
			}
			_root = null;
			_scale = 1f;
			_humanoid = false;
			IsCalibrated = false;
		}

		public static void Calibrate(RigManager rig)
		{
			//IL_0226: Unknown result type (might be due to invalid IL or missing references)
			//IL_022b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0231: Unknown result type (might be due to invalid IL or missing references)
			//IL_023c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0247: Unknown result type (might be due to invalid IL or missing references)
			//IL_0252: Unknown result type (might be due to invalid IL or missing references)
			//IL_025d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0268: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_02de: Unknown result type (might be due to invalid IL or missing references)
			//IL_030f: Unknown result type (might be due to invalid IL or missing references)
			//IL_032c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0349: Unknown result type (might be due to invalid IL or missing references)
			//IL_0366: Unknown result type (might be due to invalid IL or missing references)
			//IL_0383: Unknown result type (might be due to invalid IL or missing references)
			//IL_039e: Unknown result type (might be due to invalid IL or missing references)
			//IL_03b9: Unknown result type (might be due to invalid IL or missing references)
			//IL_03d4: Unknown result type (might be due to invalid IL or missing references)
			//IL_03ef: Unknown result type (might be due to invalid IL or missing references)
			//IL_0414: Unknown result type (might be due to invalid IL or missing references)
			//IL_0439: Unknown result type (might be due to invalid IL or missing references)
			//IL_045d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0462: Unknown result type (might be due to invalid IL or missing references)
			//IL_0467: Unknown result type (might be due to invalid IL or missing references)
			//IL_0469: Unknown result type (might be due to invalid IL or missing references)
			//IL_046e: Unknown result type (might be due to invalid IL or missing references)
			Clear();
			if ((Object)(object)rig == (Object)null)
			{
				return;
			}
			Avatar avatar = rig.avatar;
			PhysicsRig physicsRig = rig.physicsRig;
			_root = (((Object)(object)avatar != (Object)null) ? ((Component)avatar).