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 Loadouts = new List(); } [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 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("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(); } 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(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 rigs = new List(); private List uiCards = new List(); 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.renderMode = (RenderMode)0; uiObject.AddComponent(); uiObject.AddComponent(); Object.DontDestroyOnLoad((Object)(object)uiObject); GameObject val = new GameObject("WardrobeBackground"); val.transform.SetParent(((Component)canvas).transform, false); RectTransform val2 = val.AddComponent(); 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(); ((Graphic)val4).color = new Color(0f, 0f, 0f, 0.8f); RectTransform component = ((Component)val4).GetComponent(); 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(); ((Graphic)val6).color = ColorUtil.FromRGB(223, 218, 194); RectTransform component2 = ((Component)val6).GetComponent(); 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(); 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(); 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(); 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(); GameObject val3 = new GameObject("Cards"); val3.transform.SetParent(((Component)val2).transform, false); List list = new List(); for (int i = 0; i < rigs.Count; i++) { GameObject val4 = new GameObject("LoadoutCard"); val4.transform.SetParent(val3.transform, false); LoadoutCard card = val4.AddComponent(); 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(); 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(); 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(); 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(((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(); 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 callback) { int retries = MAX_LOAD_FONT_RETRIES; TMP_FontAsset font = null; while (retries > 0) { font = ((IEnumerable)Resources.FindObjectsOfTypeAll()).FirstOrDefault((Func)((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("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 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)(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 { 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? 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(); dummyAnimator = this.dummy.GetComponentInChildren(); ((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.Instance.fits[loadout.OutfitIndex].overrideHat) { playerHat = Singleton.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.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.Instance.mouths[index].texture; refs.mouthRenderer.material.SetTexture(CharacterCustomization.MainTex, texture); } private void SetAccessory(CustomizationRefs refs, int index) { CustomizationOption val = Singleton.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 materials = new List { 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 rigs; private List cards; public CarouselController? controller; private int savedPosition; public IReadOnlyList Cards => cards; public void Initialize(List rigs, List cards) { this.rigs = new CircularBuffer(rigs.ToArray()); this.cards = cards; UpdateCardVisibility(); } public void UpdateRigs(List rigs) { this.rigs = new CircularBuffer(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(); ((TMP_Text)component).text = _loadout?.Name ?? ""; SetActive(_loadout?.IsActive ?? false); UpdateBackgroundColor(); } } public void Awake() { CanvasGroup = ((Component)this).gameObject.AddComponent(); Button = ((Component)this).gameObject.AddComponent