Decompiled source of Personal Wardrobe v0.6.1

plugins/com.github.Kirshoo.PersonalWardrobe.dll

Decompiled a week 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.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using Microsoft.CodeAnalysis;
using Newtonsoft.Json;
using PersonalWardrobe.Presentation;
using PersonalWardrobe.Presentation.Cards;
using PersonalWardrobe.Utils;
using Photon.Pun;
using TMPro;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.Events;
using UnityEngine.InputSystem;
using UnityEngine.SceneManagement;
using UnityEngine.UI;
using Zorro.Core;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: IgnoresAccessChecksTo("Assembly-CSharp")]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("com.github.Kirshoo.PersonalWardrobe")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("0.6.1.0")]
[assembly: AssemblyInformationalVersion("0.6.1+63e7f96e7a8b86ebf3481de1f25cc947d603dccd")]
[assembly: AssemblyProduct("com.github.Kirshoo.PersonalWardrobe")]
[assembly: AssemblyTitle("PersonalWardrobe")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("0.6.1.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableAttribute : Attribute
	{
		public readonly byte[] NullableFlags;

		public NullableAttribute(byte P_0)
		{
			NullableFlags = new byte[1] { P_0 };
		}

		public NullableAttribute(byte[] P_0)
		{
			NullableFlags = P_0;
		}
	}
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableContextAttribute : Attribute
	{
		public readonly byte Flag;

		public NullableContextAttribute(byte P_0)
		{
			Flag = P_0;
		}
	}
	[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 BepInEx
{
	[AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = false)]
	[Conditional("CodeGeneration")]
	internal sealed class BepInAutoPluginAttribute : Attribute
	{
		public BepInAutoPluginAttribute(string? id = null, string? name = null, string? version = null)
		{
		}
	}
}
namespace BepInEx.Preloader.Core.Patching
{
	[AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = false)]
	[Conditional("CodeGeneration")]
	internal sealed class PatcherAutoPluginAttribute : Attribute
	{
		public PatcherAutoPluginAttribute(string? id = null, string? name = null, string? version = null)
		{
		}
	}
}
namespace PersonalWardrobe
{
	public class Loadout
	{
		[JsonIgnore]
		public int IdleIndex = -1;

		[JsonIgnore]
		public bool IsActive;

		[JsonProperty("name")]
		public string Name { get; set; } = string.Empty;

		[JsonProperty("skin")]
		public int SkinIndex { get; set; }

		[JsonProperty("accessory")]
		public int AccessoryIndex { get; set; }

		[JsonProperty("hat")]
		public int HatIndex { get; set; }

		[JsonProperty("outfit")]
		public int OutfitIndex { get; set; }

		[JsonProperty("eyes")]
		public int EyesIndex { get; set; }

		[JsonProperty("mouth")]
		public int MouthIndex { get; set; }

		[JsonProperty("sash")]
		public int SashIndex { get; set; }

		public static bool Equals(Loadout lhs, Loadout rhs)
		{
			return lhs.Name == rhs.Name;
		}

		public static bool Equals(Loadout lhs, string name)
		{
			return lhs.Name == name;
		}
	}
	public class Wardrobe
	{
		[JsonProperty("version")]
		public int Version = 2;

		[JsonProperty("last_active")]
		public int LastActiveIndex;

		[JsonProperty("wardrobe")]
		public List<Loadout> Loadouts = new List<Loadout>();
	}
	[BepInPlugin("com.github.Kirshoo.PersonalWardrobe", "PersonalWardrobe", "0.6.1")]
	public class Plugin : BaseUnityPlugin
	{
		public static readonly string configFolder = Path.Combine(Paths.ConfigPath, "PersonalWardrobe");

		public static readonly string loadoutsPath = Path.Combine(configFolder, "wardrobe.json");

		public static readonly string loadoutsBackupPath = Path.Combine(configFolder, "~wardrobe.json");

		internal static ConfigEntry<KeyCode> toggleMenuButton = null;

		private GameObject menuObj;

		private WardrobeMenu menu;

		internal static TMP_FontAsset? font = null;

		public const string Id = "com.github.Kirshoo.PersonalWardrobe";

		internal static ManualLogSource Log { get; private set; } = null;

		private Wardrobe Wardrobe { get; set; }

		public static string Name => "PersonalWardrobe";

		public static string Version => "0.6.1";

		private void Awake()
		{
			Log = ((BaseUnityPlugin)this).Logger;
			((MonoBehaviour)this).StartCoroutine(new FontUtil.FontLoader().LoadFontCoroutine("DarumaDropOne-Regular SDF", delegate(TMP_FontAsset font)
			{
				Plugin.font = font;
			}));
			try
			{
				WardrobeManager.Instance.EnsureWardrobe();
			}
			catch (Exception ex)
			{
				Log.LogError((object)("Wardrobe Load error: " + ex.Message));
				throw;
			}
			toggleMenuButton = ((BaseUnityPlugin)this).Config.Bind<KeyCode>("Controls", "ToggleMenu", (KeyCode)290, "Button to toggle Wardrobe UI");
			Log.LogInfo((object)("Plugin " + Name + " is loaded!"));
		}

		private void OnApplicationQuit()
		{
			WardrobeManager.SaveWardrobeToFile();
		}

		private void EnsureMenu()
		{
			if (!((Object)(object)menuObj != (Object)null))
			{
				CreateMenu();
			}
		}

		private void CreateMenu()
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Expected O, but got Unknown
			menuObj = new GameObject("Wardrobe");
			Object.DontDestroyOnLoad((Object)(object)menuObj);
			menu = menuObj.AddComponent<WardrobeMenu>();
		}

		private void Update()
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			if (Input.GetKeyDown(toggleMenuButton.Value) && WardrobeMenu.CanCreatePreview())
			{
				EnsureMenu();
				menu.ToggleOpen();
			}
		}
	}
	internal class WardrobeManager
	{
		private static WardrobeManager _instance;

		private Wardrobe wardrobe;

		public const string DefaultLoadoutName = "New Template";

		public static WardrobeManager Instance
		{
			get
			{
				if (_instance == null)
				{
					_instance = new WardrobeManager();
				}
				return _instance;
			}
		}

		public Wardrobe Wardrobe
		{
			get
			{
				EnsureWardrobe();
				return wardrobe;
			}
		}

		public WardrobeManager()
		{
			if (_instance == null)
			{
				_instance = this;
				LoadWardrobe();
			}
		}

		public void LoadWardrobe()
		{
			Directory.CreateDirectory(Plugin.configFolder);
			if (!File.Exists(Plugin.loadoutsPath))
			{
				Wardrobe wardrobe = new Wardrobe();
				File.WriteAllText(Plugin.loadoutsPath, JsonConvert.SerializeObject((object)wardrobe, (Formatting)1));
				Plugin.Log.LogInfo((object)"Created a default wardrobe file.");
			}
			string text = File.ReadAllText(Plugin.loadoutsPath);
			Wardrobe wardrobe2 = JsonConvert.DeserializeObject<Wardrobe>(text);
			if (wardrobe2 == null)
			{
				throw new FileLoadException("Deserialization returned null");
			}
			this.wardrobe = MigrateVersion(wardrobe2);
			Plugin.Log.LogInfo((object)$"Loaded wardrobe: v{this.wardrobe.Version}.");
		}

		public Wardrobe MigrateVersion(Wardrobe oldWardrobe)
		{
			if (oldWardrobe.Version < 2)
			{
				oldWardrobe.LastActiveIndex = 0;
				oldWardrobe.Version = 2;
			}
			return oldWardrobe;
		}

		public void EnsureWardrobe()
		{
			if (wardrobe == null)
			{
				LoadWardrobe();
			}
		}

		public void SaveWardrobe()
		{
			File.WriteAllText(Plugin.loadoutsBackupPath, JsonConvert.SerializeObject((object)wardrobe, (Formatting)1));
			Plugin.Log.LogInfo((object)"Wardrobe is saved.");
		}

		public void SaveLoadout(Loadout loadout)
		{
			EnsureWardrobe();
			int index = GetIndex(loadout);
			if (index == -1)
			{
				wardrobe.Loadouts.Add(loadout);
			}
			else
			{
				wardrobe.Loadouts[index] = loadout;
			}
			SaveWardrobe();
		}

		public static void SaveWardrobeToFile()
		{
			if (File.Exists(Plugin.loadoutsBackupPath))
			{
				string contents = File.ReadAllText(Plugin.loadoutsBackupPath);
				File.WriteAllText(Plugin.loadoutsPath, contents);
				File.Delete(Plugin.loadoutsBackupPath);
				Plugin.Log.LogInfo((object)"Backup removed and main file is up to date.");
			}
		}

		public Loadout GetLoadout(string name)
		{
			EnsureWardrobe();
			Loadout loadout = wardrobe.Loadouts.Find((Loadout x) => Loadout.Equals(x, name));
			if (loadout == null)
			{
				Plugin.Log.LogDebug((object)("Unable to find \"" + name + "\" loadout. Returning default."));
				return new Loadout
				{
					Name = name
				};
			}
			return loadout;
		}

		public bool IsInWardrobe(Loadout loadout)
		{
			if (wardrobe == null)
			{
				throw new InvalidOperationException("Wardrobe is not initialized.");
			}
			return wardrobe.Loadouts.Exists((Loadout other) => Loadout.Equals(other, loadout));
		}

		public int GetIndex(Loadout loadout)
		{
			if (wardrobe == null)
			{
				throw new InvalidOperationException("Wardrobe is not initialized.");
			}
			if (!IsInWardrobe(loadout))
			{
				return -1;
			}
			return wardrobe.Loadouts.FindIndex((Loadout other) => Loadout.Equals(other, loadout));
		}

		public Loadout GetLoadout(int index)
		{
			EnsureWardrobe();
			if (index < 0 || index >= wardrobe.Loadouts.Count)
			{
				Plugin.Log.LogDebug((object)"Index is out of bounds. Returning default.");
				return new Loadout
				{
					Name = string.Format("{0} #{1}", "New Template", wardrobe.Loadouts.Count)
				};
			}
			return wardrobe.Loadouts[index];
		}
	}
	internal class WardrobeMenu : MenuWindow
	{
		public GameObject uiObject;

		private Canvas canvas;

		private WardrobeManager wardrobe;

		private CardManager cardManager;

		private Loadout? currentLoadout;

		private const int LoadoutCount = 5;

		private GameObject rigObjectsRoot;

		private List<OutfitThumbnailRig> rigs = new List<OutfitThumbnailRig>();

		private List<LoadoutCard> uiCards = new List<LoadoutCard>();

		private CarouselController controller;

		public override bool openOnStart => false;

		public override bool closeOnPause => true;

		public WardrobeMenu()
		{
			wardrobe = WardrobeManager.Instance;
			int num = wardrobe.Wardrobe.LastActiveIndex;
			if (num < 0)
			{
				num = 0;
			}
			LoadLoadout(wardrobe.GetLoadout(num));
			CreateRigs();
			CreateUI();
			SubscribeToEvents();
		}

		public void CreateUI()
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Expected O, but got Unknown
			//IL_0055: Unknown result type (might be due to invalid IL or missing references)
			//IL_005b: Expected O, but got Unknown
			//IL_0084: Unknown result type (might be due to invalid IL or missing references)
			//IL_0099: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ae: 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_00c8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ce: Expected O, but got Unknown
			//IL_00fc: Unknown result type (might be due to invalid IL or missing references)
			//IL_0110: Unknown result type (might be due to invalid IL or missing references)
			//IL_011c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0128: Unknown result type (might be due to invalid IL or missing references)
			//IL_0134: Unknown result type (might be due to invalid IL or missing references)
			//IL_014c: Unknown result type (might be due to invalid IL or missing references)
			//IL_015b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0162: Expected O, but got Unknown
			//IL_018f: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ba: Unknown result type (might be due to invalid IL or missing references)
			//IL_01fb: Unknown result type (might be due to invalid IL or missing references)
			//IL_0202: Expected O, but got Unknown
			//IL_023e: Unknown result type (might be due to invalid IL or missing references)
			//IL_026c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0295: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ab: Unknown result type (might be due to invalid IL or missing references)
			uiObject = new GameObject("WardrobeMenu");
			canvas = uiObject.AddComponent<Canvas>();
			canvas.renderMode = (RenderMode)0;
			uiObject.AddComponent<CanvasScaler>();
			uiObject.AddComponent<GraphicRaycaster>();
			Object.DontDestroyOnLoad((Object)(object)uiObject);
			GameObject val = new GameObject("WardrobeBackground");
			val.transform.SetParent(((Component)canvas).transform, false);
			RectTransform val2 = val.AddComponent<RectTransform>();
			val2.anchorMin = new Vector2(0.5f, 0.5f);
			val2.anchorMax = new Vector2(0.5f, 0.5f);
			val2.pivot = new Vector2(0.5f, 0.5f);
			val2.anchoredPosition = Vector2.zero;
			GameObject val3 = new GameObject("WardrobeBackgroundDim");
			val3.transform.SetParent(val.transform, false);
			Image val4 = val3.AddComponent<Image>();
			((Graphic)val4).color = new Color(0f, 0f, 0f, 0.8f);
			RectTransform component = ((Component)val4).GetComponent<RectTransform>();
			component.anchorMin = Vector2.zero;
			component.anchorMax = Vector2.one;
			component.offsetMin = Vector2.zero;
			component.offsetMax = Vector2.zero;
			component.sizeDelta = new Vector2((float)Screen.width, (float)Screen.height);
			GameObject val5 = new GameObject("WardrobeBackgroundImage");
			val5.transform.SetParent(val.transform, false);
			Image val6 = val5.AddComponent<Image>();
			((Graphic)val6).color = ColorUtil.FromRGB(223, 218, 194);
			RectTransform component2 = ((Component)val6).GetComponent<RectTransform>();
			component2.sizeDelta = new Vector2(600f, 200f);
			component2.anchoredPosition = Vector2.zero;
			val3.transform.SetAsFirstSibling();
			val5.transform.SetAsLastSibling();
			GameObject val7 = CreateCarousel();
			val7.transform.SetParent(val.transform, false);
			GameObject val8 = new GameObject("WardrobeText");
			val8.transform.SetParent(((Component)canvas).transform, false);
			TextMeshProUGUI val9 = val8.AddComponent<TextMeshProUGUI>();
			if ((Object)(object)Plugin.font != (Object)null)
			{
				((TMP_Text)val9).font = Plugin.font;
			}
			((Graphic)val9).color = Color.white;
			((TMP_Text)val9).fontSize = 42f;
			((TMP_Text)val9).alignment = (TextAlignmentOptions)514;
			((TMP_Text)val9).text = $"In Wardrobe Menu - Press {Plugin.toggleMenuButton.Value} to exit";
			RectTransform component3 = ((Component)val9).GetComponent<RectTransform>();
			component3.sizeDelta = new Vector2(1000f, 100f);
			component3.anchoredPosition = new Vector2(0f, 300f);
		}

		private void SaveLoadout(string loadoutName)
		{
			Plugin.Log.LogDebug((object)"Overriding saved loadout with current cosmetics.");
			CharacterCustomizationData customizationData = CharacterCustomization.GetCustomizationData(PhotonNetwork.LocalPlayer);
			if (customizationData == null)
			{
				Plugin.Log.LogError((object)"Unable to retreive current cosmetics data.");
				return;
			}
			Loadout loadout = new Loadout
			{
				Name = loadoutName,
				SkinIndex = customizationData.currentSkin,
				AccessoryIndex = customizationData.currentAccessory,
				EyesIndex = customizationData.currentEyes,
				MouthIndex = customizationData.currentMouth,
				HatIndex = customizationData.currentHat,
				OutfitIndex = customizationData.currentOutfit,
				SashIndex = customizationData.currentSash
			};
			wardrobe.SaveLoadout(loadout);
		}

		private void LoadLoadout(Loadout loadout)
		{
			if (currentLoadout != null)
			{
				currentLoadout.IsActive = false;
			}
			CharacterCustomization.SetCharacterSkinColor(loadout.SkinIndex);
			CharacterCustomization.SetCharacterAccessory(loadout.AccessoryIndex);
			CharacterCustomization.SetCharacterEyes(loadout.EyesIndex);
			CharacterCustomization.SetCharacterMouth(loadout.MouthIndex);
			CharacterCustomization.SetCharacterHat(loadout.HatIndex);
			CharacterCustomization.SetCharacterOutfit(loadout.OutfitIndex);
			CharacterCustomization.SetCharacterSash(loadout.SashIndex);
			currentLoadout = loadout;
			currentLoadout.IsActive = true;
		}

		private void LoadLoadout(string loadoutName)
		{
			Plugin.Log.LogDebug((object)"Overriding current cosmetics with saved loadout.");
			Loadout loadout = wardrobe.GetLoadout(loadoutName);
			if (loadout == null)
			{
				Plugin.Log.LogError((object)("Unable to find loadout with name " + loadoutName));
			}
			else
			{
				LoadLoadout(loadout);
			}
		}

		private GameObject CreateCarousel()
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Expected O, but got Unknown
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_0047: 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_0077: Unknown result type (might be due to invalid IL or missing references)
			//IL_007d: Expected O, but got Unknown
			//IL_00b1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b8: Expected O, but got Unknown
			//IL_010b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0115: Expected O, but got Unknown
			//IL_018d: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = new GameObject("Loadouts");
			RectTransform val2 = val.AddComponent<RectTransform>();
			val2.anchorMin = new Vector2(0.5f, 0.5f);
			val2.anchorMax = new Vector2(0.5f, 0.5f);
			val2.sizeDelta = new Vector2(1000f, 500f);
			val2.anchoredPosition = new Vector2(0.5f, 0.5f);
			cardManager = val.AddComponent<CardManager>();
			GameObject val3 = new GameObject("Cards");
			val3.transform.SetParent(((Component)val2).transform, false);
			List<ICard> list = new List<ICard>();
			for (int i = 0; i < rigs.Count; i++)
			{
				GameObject val4 = new GameObject("LoadoutCard");
				val4.transform.SetParent(val3.transform, false);
				LoadoutCard card = val4.AddComponent<LoadoutCard>();
				card.SetPreviewRig(rigs[i]);
				((UnityEvent)card.Button.onClick).AddListener((UnityAction)delegate
				{
					if (card.AssignedLoadout == null)
					{
						Plugin.Log.LogWarning((object)"Pressed on a card with no loadout. Do nothing.");
					}
					else
					{
						if (!wardrobe.IsInWardrobe(card.AssignedLoadout))
						{
							Plugin.Log.LogDebug((object)"Pressed on a card with new loadout. Forcefully adding new loadout.");
							wardrobe.SaveLoadout(card.AssignedLoadout);
						}
						if (currentLoadout != null && Loadout.Equals(currentLoadout, card.AssignedLoadout.Name))
						{
							Plugin.Log.LogWarning((object)"Selected current loadout. Do nothing.");
						}
						else
						{
							SwitchLoadout(card.AssignedLoadout);
							cardManager.UpdateCardVisibility();
						}
					}
				});
				list.Add(card);
				uiCards.Add(card);
			}
			cardManager.Initialize(rigs, list);
			controller = val.AddComponent<CarouselController>();
			controller.Initialize(cardManager);
			controller.CarouselSize = 5;
			controller.ItemSpacing = LoadoutCard.CardActualSize.x + 20f;
			cardManager.SubscribeToEvents(controller);
			return val;
		}

		private void CreateRigs()
		{
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Expected O, but got Unknown
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Expected O, but got Unknown
			//IL_0076: Unknown result type (might be due to invalid IL or missing references)
			Object.Destroy((Object)(object)rigObjectsRoot);
			rigObjectsRoot = new GameObject("OutfitThumbnailRigs");
			rigs = new List<OutfitThumbnailRig>();
			for (int i = 0; i < 5; i++)
			{
				GameObject val = new GameObject("Rig");
				val.transform.SetParent(rigObjectsRoot.transform, false);
				rigs.Add(CreateThumbnailRig(val));
				val.transform.localPosition = new Vector3(20f * (float)i, -999f, 0f);
			}
		}

		private OutfitThumbnailRig CreateThumbnailRig(GameObject rigObj)
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Expected O, but got Unknown
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ac: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b3: Expected O, but got Unknown
			//IL_00dc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f3: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = new GameObject("PortraitCamera");
			val.transform.SetParent(rigObj.transform, false);
			Camera val2 = val.AddComponent<Camera>();
			val2.clearFlags = (CameraClearFlags)2;
			val2.backgroundColor = new Color(0.3255f, 0.5922f, 0.8667f, 1f);
			val2.orthographic = true;
			val2.orthographicSize = 1.2f;
			val2.nearClipPlane = 0.1f;
			val2.farClipPlane = 10f;
			((Behaviour)val2).enabled = true;
			GameObject val3 = Object.Instantiate<GameObject>(((Component)PassportManager.instance.dummy).gameObject);
			val3.transform.SetParent(rigObj.transform);
			OutfitThumbnailRig result = new OutfitThumbnailRig(val2, val3);
			GameObject val4 = new GameObject("SpotLight");
			val4.transform.SetParent(rigObj.transform, false);
			val4.transform.localPosition = new Vector3(0f, 2.5f, -2f);
			val4.transform.LookAt(val3.transform.position);
			Light val5 = val4.AddComponent<Light>();
			val5.intensity = 2f;
			val5.range = 10f;
			val5.spotAngle = 45f;
			return result;
		}

		public void SubscribeToEvents()
		{
			SceneManager.activeSceneChanged += OnSceneChanged;
		}

		private void OnSceneChanged(Scene oldScene, Scene newScene)
		{
			if (CanCreatePreview() && !((Object)(object)cardManager == (Object)null))
			{
				CreateRigs();
				for (int i = 0; i < uiCards.Count && i < rigs.Count; i++)
				{
					uiCards[i].SetPreviewRig(rigs[i]);
				}
				cardManager.UpdateRigs(rigs);
				controller.OverrideScrollPosition(0f);
			}
		}

		public static bool CanCreatePreview()
		{
			PassportManager instance = PassportManager.instance;
			object obj;
			if (instance == null)
			{
				obj = null;
			}
			else
			{
				PlayerCustomizationDummy dummy = instance.dummy;
				obj = ((dummy != null) ? ((Component)dummy).gameObject : null);
			}
			return (Object)obj != (Object)null;
		}

		public void SwitchLoadout(Loadout loadout)
		{
			wardrobe.Wardrobe.LastActiveIndex = wardrobe.GetIndex(loadout);
			if (currentLoadout != null)
			{
				SaveLoadout(currentLoadout.Name);
			}
			LoadLoadout(loadout);
			cardManager.UpdateCardVisibility();
		}

		public void Awake()
		{
			uiObject.SetActive(false);
		}

		public void ToggleOpen()
		{
			if (!((MenuWindow)this).isOpen)
			{
				((MenuWindow)this).Open();
				uiObject.SetActive(true);
			}
			else
			{
				((MenuWindow)this).Close();
			}
		}

		public override void OnClose()
		{
			uiObject.SetActive(false);
		}
	}
}
namespace PersonalWardrobe.Utils
{
	internal static class ColorUtil
	{
		public static Color FromRGB(int red, int green, int blue)
		{
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			return FromRGB(red, green, blue, 1f);
		}

		public static Color FromRGB(int red, int green, int blue, float alpha)
		{
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			red = Math.Clamp(red, 0, 255);
			green = Math.Clamp(green, 0, 255);
			blue = Math.Clamp(blue, 0, 255);
			return new Color((float)red / 255f, (float)green / 255f, (float)blue / 255f, alpha);
		}
	}
	internal class FontUtil
	{
		public struct FontLoader
		{
			public int MAX_LOAD_FONT_RETRIES;

			public float BACKOFF_DELAY_MILLISECONDS;

			public FontLoader()
			{
				MAX_LOAD_FONT_RETRIES = 5;
				BACKOFF_DELAY_MILLISECONDS = 0.05f;
			}

			public IEnumerator LoadFontCoroutine(string fontname, Action<TMP_FontAsset> callback)
			{
				int retries = MAX_LOAD_FONT_RETRIES;
				TMP_FontAsset font = null;
				while (retries > 0)
				{
					font = ((IEnumerable<TMP_FontAsset>)Resources.FindObjectsOfTypeAll<TMP_FontAsset>()).FirstOrDefault((Func<TMP_FontAsset, bool>)((TMP_FontAsset asset) => ((Object)asset).name == fontname));
					if ((Object)(object)font != (Object)null)
					{
						Plugin.Log.LogDebug((object)("Found " + fontname + "! Proceeding..."));
						break;
					}
					retries--;
					Plugin.Log.LogDebug((object)$"Failed to load {fontname} font, retrying after {(float)(MAX_LOAD_FONT_RETRIES - retries) * BACKOFF_DELAY_MILLISECONDS}s...");
					yield return (object)new WaitForSeconds((float)(MAX_LOAD_FONT_RETRIES - retries) * BACKOFF_DELAY_MILLISECONDS);
				}
				if ((Object)(object)font == (Object)null)
				{
					Plugin.Log.LogWarning((object)("Failed to load " + fontname + " font, fallback to built in font..."));
					font = Resources.GetBuiltinResource<TMP_FontAsset>("LiberationSans SDF");
				}
				callback?.Invoke(font);
			}
		}
	}
}
namespace PersonalWardrobe.Presentation
{
	internal class CarouselController : MonoBehaviour, IBeginDragHandler, IEventSystemHandler, IDragHandler, IEndDragHandler
	{
		public int CarouselSize = 5;

		public float ItemSpacing = 150f;

		private CardManager? manager;

		private int leftIndex;

		private float scrollPosition;

		public float ScrollThreshold = 20f;

		public float CenterScale = 1.2f;

		public float EdgeScale = 0.7f;

		public float CenterAlpha = 1f;

		public float EdgeAlpha = 0.5f;

		private bool isDragging;

		private float velocity;

		private const float drag = 0.5f;

		public float MaxAlphaDistance => ItemSpacing * 1.2f;

		public event Action<int, int> ItemsChanged;

		public void Initialize(CardManager manager)
		{
			this.manager = manager;
		}

		public bool IsIntialized()
		{
			return (Object)(object)manager != (Object)null;
		}

		private void Move(float amount)
		{
			scrollPosition += amount;
		}

		public void Update()
		{
			UpdateControls();
			UpdateScrollPosition();
			if (IsIntialized())
			{
				UpdateItemIndex();
				CenterOnClosestCard();
				UpdateCardPositions();
			}
		}

		private void UpdateControls()
		{
			//IL_004d: Unknown result type (might be due to invalid IL or missing references)
			if (Input.GetKeyDown((KeyCode)276))
			{
				Move(0f - ItemSpacing);
			}
			if (Input.GetKeyDown((KeyCode)275))
			{
				Move(ItemSpacing);
			}
			if (Mouse.current.leftButton.isPressed)
			{
				velocity = (0f - ((InputControl<Vector2>)(object)((Pointer)Mouse.current).delta).ReadValue().x) * ItemSpacing / ScrollThreshold;
			}
		}

		private void UpdateItemIndex()
		{
			int num = Mathf.RoundToInt(scrollPosition / ItemSpacing);
			if (num != leftIndex)
			{
				this.ItemsChanged?.Invoke(num - leftIndex, num);
				leftIndex = num;
			}
		}

		private void UpdateScrollPosition()
		{
			scrollPosition += velocity * Time.deltaTime;
			velocity *= Mathf.Pow(isDragging ? 1f : 0.5f, Time.deltaTime);
		}

		private void CenterOnClosestCard()
		{
		}

		private void UpdateCardPositions()
		{
			//IL_010c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0118: Unknown result type (might be due to invalid IL or missing references)
			//IL_011f: Unknown result type (might be due to invalid IL or missing references)
			if (!IsIntialized())
			{
				return;
			}
			int num = manager.Cards.Count();
			float num2 = (scrollPosition - (float)leftIndex * ItemSpacing) % ItemSpacing;
			float num3 = (float)(CarouselSize - 1) * ItemSpacing * 0.5f;
			for (int i = 0; i < num; i++)
			{
				int index = (leftIndex % num + i + num) % num;
				float num4 = (float)i * ItemSpacing - num2 - num3;
				float num5 = Mathf.Clamp01(Mathf.Abs(num4) / (ItemSpacing * (float)CarouselSize / 2f));
				float num6 = Mathf.Lerp(CenterScale, EdgeScale, num5);
				float alpha = 1f;
				if (Mathf.Abs(num4) > MaxAlphaDistance)
				{
					float num7 = Mathf.InverseLerp(0.3f, 1f, num5);
					alpha = Mathf.Lerp(CenterAlpha, EdgeAlpha, num7);
				}
				ICard card = manager.Cards[index];
				card.SetPosition(new Vector3(num4, 0f, 0f));
				card.SetScale(Vector3.one * num6);
				card.SetAlpha(alpha);
			}
		}

		public void OverrideScrollPosition(float newPosition)
		{
			scrollPosition = newPosition;
			velocity = 0f;
			leftIndex = 0;
			this.ItemsChanged?.Invoke(0, 0);
		}

		public void OnBeginDrag(PointerEventData eventData)
		{
			isDragging = true;
		}

		public void OnDrag(PointerEventData eventData)
		{
		}

		public void OnEndDrag(PointerEventData eventData)
		{
			isDragging = false;
		}
	}
	internal class CircularBuffer<T>
	{
		private readonly T[] buffer;

		private int head;

		public T this[int index]
		{
			get
			{
				return buffer[(head + index) % buffer.Length];
			}
			set
			{
				buffer[(head + index) % buffer.Length] = value;
			}
		}

		public int Count => buffer.Length;

		public CircularBuffer(T[] buf)
		{
			buffer = buf;
			head = 0;
		}

		public void RotateLeft(int amount = 1)
		{
			head = (head + amount) % buffer.Length;
		}

		public void RotateRight(int amount = 1)
		{
			if (amount > buffer.Length)
			{
				amount %= buffer.Length;
			}
			head = (head - amount + buffer.Length) % buffer.Length;
		}
	}
	internal class OutfitThumbnailRig
	{
		private Camera camera;

		private GameObject dummy;

		private PlayerCustomizationDummy customizations;

		private Animator dummyAnimator;

		private const int MAX_IDLES = 8;

		public RenderTexture Texture { get; private set; }

		public event Action<Loadout>? OnLoadoutChange;

		public OutfitThumbnailRig(Camera camera, GameObject dummy)
		{
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Expected O, but got Unknown
			//IL_0073: 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_009d: 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)
			this.camera = camera;
			Texture = new RenderTexture(150, 250, 16);
			camera.targetTexture = Texture;
			this.dummy = dummy;
			customizations = this.dummy.GetComponent<PlayerCustomizationDummy>();
			dummyAnimator = this.dummy.GetComponentInChildren<Animator>();
			((Component)this.camera).transform.localPosition = new Vector3(0f, 1.1f, -3f);
			((Component)this.camera).transform.localRotation = Quaternion.identity;
			this.dummy.transform.localPosition = Vector3.zero;
			this.dummy.transform.localRotation = Quaternion.Euler(0f, 180f, 0f);
		}

		public void LookIntoNothing()
		{
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			((Component)camera).transform.localPosition = new Vector3(0f, -20f, -3f);
			((Component)camera).transform.localRotation = Quaternion.identity;
		}

		public void LookAtDummy()
		{
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			((Component)camera).transform.localPosition = new Vector3(0f, 1.1f, -3f);
			((Component)camera).transform.localRotation = Quaternion.identity;
		}

		public void ApplyLoadout(Loadout loadout)
		{
			if (!((Object)(object)customizations == (Object)null))
			{
				LookAtDummy();
				customizations.SetPlayerColor(loadout.SkinIndex);
				int playerHat = loadout.HatIndex;
				if (Singleton<Customization>.Instance.fits[loadout.OutfitIndex].overrideHat)
				{
					playerHat = Singleton<Customization>.Instance.fits[loadout.OutfitIndex].overrideHatIndex;
				}
				customizations.SetPlayerHat(playerHat);
				customizations.SetPlayerCostume(loadout.OutfitIndex);
				SetAccessory(customizations.refs, loadout.AccessoryIndex);
				SetEyes(customizations.refs, loadout.EyesIndex);
				SetMouth(customizations.refs, loadout.MouthIndex);
				SetSash(customizations.refs, loadout.SashIndex);
				if (loadout.IdleIndex == -1)
				{
					loadout.IdleIndex = SetRandomIdle();
				}
				else
				{
					SetIdle(loadout.IdleIndex);
				}
				this.OnLoadoutChange?.Invoke(loadout);
			}
		}

		public void Destroy()
		{
			Object.Destroy((Object)(object)dummy);
			Object.Destroy((Object)(object)Texture);
		}

		private void SetEyes(CustomizationRefs refs, int index)
		{
			Texture texture = Singleton<Customization>.Instance.eyes[index].texture;
			Renderer[] eyeRenderers = refs.EyeRenderers;
			for (int i = 0; i < eyeRenderers.Length; i++)
			{
				eyeRenderers[i].material.SetTexture(CharacterCustomization.MainTex, texture);
			}
		}

		private void SetMouth(CustomizationRefs refs, int index)
		{
			Texture texture = Singleton<Customization>.Instance.mouths[index].texture;
			refs.mouthRenderer.material.SetTexture(CharacterCustomization.MainTex, texture);
		}

		private void SetAccessory(CustomizationRefs refs, int index)
		{
			CustomizationOption val = Singleton<Customization>.Instance.accessories[index];
			Texture texture = val.texture;
			refs.accessoryRenderer.material.SetTexture(CharacterCustomization.MainTex, texture);
			refs.accessoryRenderer.material.renderQueue = (val.drawUnderEye ? 3007 : 3009);
			refs.accessoryEnabled = !val.isThirdEye;
			refs.thirdEye.gameObject.SetActive(val.isThirdEye);
		}

		private void SetSash(CustomizationRefs refs, int index)
		{
			List<Material> materials = new List<Material>
			{
				refs.sashRenderer.materials[0],
				refs.sashAscentMaterials[index]
			};
			refs.sashRenderer.SetMaterials(materials);
		}

		private void SetIdle(int index)
		{
			dummyAnimator.SetFloat(CharacterCustomization.Idle, (float)index);
		}

		public int SetRandomIdle()
		{
			int num = Random.Range(0, 8);
			SetIdle(num);
			return num;
		}
	}
}
namespace PersonalWardrobe.Presentation.Cards
{
	internal class CardManager : MonoBehaviour
	{
		private CircularBuffer<OutfitThumbnailRig> rigs;

		private List<ICard> cards;

		public CarouselController? controller;

		private int savedPosition;

		public IReadOnlyList<ICard> Cards => cards;

		public void Initialize(List<OutfitThumbnailRig> rigs, List<ICard> cards)
		{
			this.rigs = new CircularBuffer<OutfitThumbnailRig>(rigs.ToArray());
			this.cards = cards;
			UpdateCardVisibility();
		}

		public void UpdateRigs(List<OutfitThumbnailRig> rigs)
		{
			this.rigs = new CircularBuffer<OutfitThumbnailRig>(rigs.ToArray());
		}

		public void SetSavedOffset(int newOffset)
		{
			savedPosition = newOffset;
		}

		public void SubscribeToEvents(CarouselController controller)
		{
			this.controller = controller;
			controller.ItemsChanged += UpdateCardVisibility;
		}

		public void UpdateCardVisibility(int delta = 0, int position = int.MaxValue)
		{
			if (cards == null || rigs == null)
			{
				return;
			}
			if (delta < 0)
			{
				rigs.RotateRight(Mathf.Abs(delta));
			}
			else if (delta > 0)
			{
				rigs.RotateLeft(Mathf.Abs(delta));
			}
			if (position == int.MaxValue)
			{
				position = savedPosition;
			}
			int num = WardrobeManager.Instance.Wardrobe.Loadouts.Count + 1;
			for (int i = 0; i < rigs.Count && i < cards.Count; i++)
			{
				int num2 = (position % num + i + num) % num;
				Loadout loadout = WardrobeManager.Instance.GetLoadout(num2);
				rigs[i].ApplyLoadout(loadout);
				if (num2 >= WardrobeManager.Instance.Wardrobe.Loadouts.Count)
				{
					rigs[i].LookIntoNothing();
				}
			}
			savedPosition = position;
		}
	}
	internal interface ICard
	{
		void SetPosition(Vector3 position);

		void SetRotation(Quaternion rotation);

		void SetScale(Vector3 scale);

		void SetAlpha(float alpha);
	}
	internal class LoadoutCard : MonoBehaviour, ICard
	{
		public static readonly Vector2 PreviewSize = new Vector2(150f, 250f);

		public const float BorderSize = 10f;

		public bool IsActive;

		private GameObject BackgroundObject;

		private GameObject PreviewObject;

		private GameObject LabelObject;

		private RawImage previewImage;

		private OutfitThumbnailRig? currentRig;

		private Loadout? _loadout;

		public static Vector2 CardActualSize => PreviewSize + 2f * new Vector2(10f, 10f);

		public CanvasGroup CanvasGroup { get; private set; }

		public Button Button { get; private set; }

		public Loadout? AssignedLoadout
		{
			get
			{
				return _loadout;
			}
			set
			{
				_loadout = value;
				TextMeshProUGUI component = LabelObject.GetComponent<TextMeshProUGUI>();
				((TMP_Text)component).text = _loadout?.Name ?? "";
				SetActive(_loadout?.IsActive ?? false);
				UpdateBackgroundColor();
			}
		}

		public void Awake()
		{
			CanvasGroup = ((Component)this).gameObject.AddComponent<CanvasGroup>();
			Button = ((Component)this).gameObject.AddComponent<Button>();
			CreateLabel();
			CreateBackground();
			CreatePreview();
		}

		private void CreateBackground()
		{
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: Expected O, but got Unknown
			//IL_0056: 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)
			if (!((Object)(object)BackgroundObject != (Object)null))
			{
				BackgroundObject = new GameObject("Background", new Type[1] { typeof(Image) });
				BackgroundObject.transform.SetParent(((Component)this).transform, false);
				Image component = BackgroundObject.GetComponent<Image>();
				((Graphic)component).color = Color.white;
				((Graphic)component).rectTransform.sizeDelta = CardActualSize;
				BackgroundObject.transform.SetAsFirstSibling();
			}
		}

		private void CreatePreview()
		{
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: Expected O, but got Unknown
			//IL_006d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0082: 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_00a2: 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)
			if (!((Object)(object)PreviewObject != (Object)null))
			{
				PreviewObject = new GameObject("Preview", new Type[2]
				{
					typeof(RawImage),
					typeof(RectTransform)
				});
				PreviewObject.transform.SetParent(((Component)this).transform, false);
				RectTransform component = PreviewObject.GetComponent<RectTransform>();
				component.anchorMin = new Vector2(0.5f, 0.5f);
				component.anchorMax = new Vector2(0.5f, 0.5f);
				component.pivot = new Vector2(0.5f, 0.5f);
				component.sizeDelta = PreviewSize;
				component.anchoredPosition = Vector2.zero;
				previewImage = PreviewObject.GetComponent<RawImage>();
				((Graphic)previewImage).raycastTarget = false;
				((Component)this).gameObject.AddComponent<Button>();
			}
		}

		private void CreateLabel()
		{
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: Expected O, but got Unknown
			//IL_0089: 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)
			//IL_00db: 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_00fb: Unknown result type (might be due to invalid IL or missing references)
			//IL_0115: Unknown result type (might be due to invalid IL or missing references)
			//IL_012b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0130: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)LabelObject != (Object)null))
			{
				LabelObject = new GameObject("Label", new Type[2]
				{
					typeof(RectTransform),
					typeof(TextMeshProUGUI)
				});
				LabelObject.transform.SetParent(((Component)this).transform, false);
				TextMeshProUGUI component = LabelObject.GetComponent<TextMeshProUGUI>();
				((TMP_Text)component).overflowMode = (TextOverflowModes)0;
				((TMP_Text)component).textWrappingMode = (TextWrappingModes)1;
				if ((Object)(object)Plugin.font != (Object)null)
				{
					((TMP_Text)component).font = Plugin.font;
				}
				((Graphic)component).color = Color.white;
				((TMP_Text)component).fontWeight = (FontWeight)700;
				((TMP_Text)component).fontSize = 28f;
				((TMP_Text)component).alignment = (TextAlignmentOptions)514;
				RectTransform component2 = ((Component)component).GetComponent<RectTransform>();
				component2.anchorMin = new Vector2(0.5f, 0.5f);
				component2.anchorMax = new Vector2(0.5f, 0.5f);
				component2.pivot = new Vector2(0.5f, 0.5f);
				component2.anchoredPosition = Vector2.zero;
				((Transform)component2).localPosition = -1f * new Vector3(0f, 0.5f * (CardActualSize.y + 50f), 0f);
			}
		}

		public void SetPreviewRig(OutfitThumbnailRig rig)
		{
			if ((Object)(object)previewImage == (Object)null)
			{
				Plugin.Log.LogWarning((object)"Setting preview rig before preview image is created. Create preview first.");
				return;
			}
			if (currentRig != null)
			{
				currentRig.OnLoadoutChange -= RigLoadoutChanged;
			}
			currentRig = rig;
			previewImage.texture = (Texture)(object)rig.Texture;
			currentRig.OnLoadoutChange += RigLoadoutChanged;
		}

		public void RigLoadoutChanged(Loadout loadout)
		{
			AssignedLoadout = loadout;
		}

		public void UpdateBackgroundColor()
		{
			//IL_0028: 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)
			Image component = BackgroundObject.GetComponent<Image>();
			((Graphic)component).color = (IsActive ? ColorUtil.FromRGB(120, 255, 160) : Color.white);
		}

		public void SetActive(bool active)
		{
			IsActive = active;
		}

		public void SetPosition(Vector3 position)
		{
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			((Component)this).gameObject.transform.localPosition = position;
		}

		public void SetRotation(Quaternion rotation)
		{
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			((Component)this).gameObject.transform.localRotation = rotation;
		}

		public void SetScale(Vector3 scale)
		{
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			((Component)this).gameObject.transform.localScale = scale;
		}

		public void SetAlpha(float alpha)
		{
			CanvasGroup.alpha = alpha;
		}
	}
}
namespace System.Runtime.CompilerServices
{
	[AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)]
	internal sealed class IgnoresAccessChecksToAttribute : Attribute
	{
		public IgnoresAccessChecksToAttribute(string assemblyName)
		{
		}
	}
}