Decompiled source of QuickSpraySelector v1.0.2

plugins/QuickSpraySelector/QuickSpraySelector.dll

Decompiled 8 hours ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Reflection.Emit;
using System.Runtime.CompilerServices;
using BepInEx;
using BepInEx.Configuration;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using Reptile;
using Rewired;
using TMPro;
using UnityEngine;
using UnityEngine.Audio;
using UnityEngine.Rendering.PostProcessing;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyVersion("0.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 QuickPickGraffiti
{
	[BepInPlugin("codex.quickpickgraffiti", "QuickSpraySelector", "1.0.0")]
	public class Plugin : BaseUnityPlugin
	{
		private static Harmony harmony;

		private static GraffitiGame activeGame;

		private static List<GraffitiArt> choices;

		private static Texture[] previews;

		private static GUIContent[] artNames;

		private static WheelSelection wheel;

		private static readonly WheelAimInput aimInput = new WheelAimInput();

		private static Vector2 lastMousePosition;

		private static bool mouseCaptured;

		private static CursorLockMode savedCursorLock;

		private static bool savedCursorVisible;

		private static bool pickerOpen;

		private static bool selectionResolved;

		private static bool aborted;

		private static int rememberedIndex = -1;

		private static string sizeCategory;

		private static LastGraffitiStore memory;

		private static readonly Dictionary<ControllerMap, bool> pickerMaps = new Dictionary<ControllerMap, bool>();

		private static readonly int[] pickerActions = new int[5] { 2, 3, 45, 47, 0 };

		private static float inputReadyTime;

		private static float openedAt;

		private static float visualPointerAngle;

		private static readonly float[] iconScales = new float[12];

		private bool hintsWarmed;

		private bool rendererWarmed;

		private float nextWarmAttempt;

		private GameButtonHints hints;

		private PaintVisuals paintVisuals;

		private static BackgroundBlur backgroundBlur;

		private static SelectorCameraMotion selectorCamera;

		private Texture2D ringTexture;

		private Texture2D pointerTexture;

		private static GameObject hiddenCircle;

		private static bool circleWasActive;

		private GUIStyle titleStyle;

		private GUIStyle detailStyle;

		private GUIStyle sizeStyle;

		private static Dictionary<GraffitiSize, ConfigEntry<string>> lastGraffitiTitles;

		private SelectionAudio selectionAudio;

		private ConfigEntry<bool> nativeBlurEnabled;

		private ConfigEntry<KernelSize> nativeBlurQuality;

		private static readonly ControllerType[] pickerControllerTypes = (ControllerType[])(object)new ControllerType[3]
		{
			default(ControllerType),
			(ControllerType)1,
			(ControllerType)2
		};

		private void Awake()
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Expected O, but got Unknown
			//IL_00d9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00de: 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)
			harmony = new Harmony("codex.quickpickgraffiti.patch");
			ringTexture = WheelStyle.CreateSelectionGlow(512);
			pointerTexture = WheelStyle.CreatePointer();
			harmony.PatchAll();
			((BaseUnityPlugin)this).Logger.LogInfo((object)"QuickSpraySelector 1.0.0 loaded: native game depth-of-field blur.");
			backgroundBlur = new BackgroundBlur(delegate(string message)
			{
				((BaseUnityPlugin)this).Logger.LogWarning((object)message);
			});
			selectorCamera = new SelectorCameraMotion(delegate(string message)
			{
				((BaseUnityPlugin)this).Logger.LogWarning((object)message);
			});
			nativeBlurEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("Graphics", "NativeBlurEnabled", true, "Enable background blur while the wheel is open. Turn off for the lowest GPU cost.");
			nativeBlurQuality = ((BaseUnityPlugin)this).Config.Bind<KernelSize>("Graphics", "NativeBlurQuality", (KernelSize)1, "Small has the lowest blur cost. Medium is the recommended default; Large and VeryLarge use more GPU work.");
			lastGraffitiTitles = new Dictionary<GraffitiSize, ConfigEntry<string>>();
			foreach (GraffitiSize value in Enum.GetValues(typeof(GraffitiSize)))
			{
				lastGraffitiTitles[value] = ((BaseUnityPlugin)this).Config.Bind<string>("LastGraffiti", ((object)value/*cast due to .constrained prefix*/).ToString(), "", "Last successfully painted art of this size");
			}
			memory = new LastGraffitiStore((string value) => lastGraffitiTitles[(GraffitiSize)Enum.Parse(typeof(GraffitiSize), value)].Value, delegate(string value, string title)
			{
				//IL_0015: Unknown result type (might be due to invalid IL or missing references)
				lastGraffitiTitles[(GraffitiSize)Enum.Parse(typeof(GraffitiSize), value)].Value = title;
				((BaseUnityPlugin)this).Config.Save();
			});
			selectionAudio = new SelectionAudio(((Component)this).transform, delegate(string message)
			{
				((BaseUnityPlugin)this).Logger.LogWarning((object)message);
			});
		}

		private static IGamepadTemplate GetGamepad()
		{
			Core instance = Core.Instance;
			if ((Object)(object)instance == (Object)null || instance.GameInput == null || !instance.GameInput.IsRewiredInitialized)
			{
				return null;
			}
			Player firstRewiredPlayer = instance.GameInput.FirstRewiredPlayer;
			if (firstRewiredPlayer == null)
			{
				return null;
			}
			foreach (Joystick joystick in firstRewiredPlayer.controllers.Joysticks)
			{
				IGamepadTemplate template = ((Controller)joystick).GetTemplate<IGamepadTemplate>();
				if (template != null)
				{
					return template;
				}
			}
			return null;
		}

		private void Update()
		{
			//IL_0099: Unknown result type (might be due to invalid IL or missing references)
			//IL_009f: Invalid comparison between Unknown and I4
			//IL_010f: 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)
			//IL_01b1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01cd: Unknown result type (might be due to invalid IL or missing references)
			//IL_01cf: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01db: Unknown result type (might be due to invalid IL or missing references)
			//IL_01dd: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e7: Unknown result type (might be due to invalid IL or missing references)
			//IL_0204: Unknown result type (might be due to invalid IL or missing references)
			//IL_021e: 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_0228: Unknown result type (might be due to invalid IL or missing references)
			//IL_01fd: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ff: Unknown result type (might be due to invalid IL or missing references)
			//IL_0266: Unknown result type (might be due to invalid IL or missing references)
			//IL_025f: Unknown result type (might be due to invalid IL or missing references)
			//IL_026b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0272: Unknown result type (might be due to invalid IL or missing references)
			//IL_0279: Unknown result type (might be due to invalid IL or missing references)
			//IL_0280: Unknown result type (might be due to invalid IL or missing references)
			//IL_0287: Unknown result type (might be due to invalid IL or missing references)
			//IL_028e: 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)
			WarmResources();
			if (pickerOpen)
			{
				SelectorPaintCloud.Tick(Time.deltaTime);
			}
			if (!pickerOpen || wheel == null)
			{
				if (hints != null)
				{
					hints.Hide();
				}
				return;
			}
			Core instance = Core.Instance;
			if ((Object)(object)instance == (Object)null || instance.GameInput == null || !instance.GameInput.IsRewiredInitialized)
			{
				return;
			}
			GameInput gameInput = instance.GameInput;
			if (instance.BaseModule.IsInGamePaused || !Application.isFocused)
			{
				RestoreMouseCursor();
				return;
			}
			CaptureMouseCursor();
			EnablePickerMaps(gameInput);
			if (Time.unscaledTime < inputReadyTime)
			{
				return;
			}
			bool num = (int)gameInput.GetCurrentControllerType(0) != 2;
			Player firstRewiredPlayer = gameInput.FirstRewiredPlayer;
			IGamepadTemplate gamepad = GetGamepad();
			bool flag = (num && firstRewiredPlayer != null && firstRewiredPlayer.GetNegativeButtonDown(0)) || (gamepad != null && gamepad.dPad.left.justPressed);
			bool flag2 = (num && firstRewiredPlayer != null && firstRewiredPlayer.GetButtonDown(0)) || (gamepad != null && gamepad.dPad.right.justPressed);
			bool flag3 = gameInput.GetButtonNew(45, 0) || Input.mouseScrollDelta.y > 0f;
			bool flag4 = gameInput.GetButtonNew(47, 0) || Input.mouseScrollDelta.y < 0f;
			bool flag5 = flag || flag2 || flag3 || flag4;
			int selectedIndex = wheel.SelectedIndex;
			if (flag3)
			{
				wheel.ChangePage(-1);
			}
			else if (flag4)
			{
				wheel.ChangePage(1);
			}
			else if (flag)
			{
				wheel.Step(-1);
			}
			else if (flag2)
			{
				wheel.Step(1);
			}
			Vector2 val = ((gamepad == null) ? Vector2.zero : gamepad.leftStick.value);
			Vector2 val2 = ((gamepad == null) ? Vector2.zero : gamepad.rightStick.value);
			Vector2 val3 = Vector2.op_Implicit(Input.mousePosition);
			Vector2 val4 = val3 - lastMousePosition;
			bool flag6 = ((Vector2)(ref val4)).sqrMagnitude > 0.5f;
			if (flag6)
			{
				lastMousePosition = val3;
			}
			Vector2 val5 = val3 - new Vector2((float)Screen.width * 0.5f, (float)Screen.height * 0.54f);
			float num2 = Mathf.Min((float)Screen.height * 0.4f, (float)Screen.width * 0.3f);
			val5 = ((((Vector2)(ref val5)).sqrMagnitude < num2 * num2 * 0.0324f) ? Vector2.zero : ((Vector2)(ref val5)).normalized);
			if (aimInput.Update(val.x, val.y, val2.x, val2.y, val5.x, val5.y, flag6, flag5, out var x, out var y) || flag5 || !aimInput.MouseActive || flag6)
			{
				wheel.UpdateStick(x, y, flag5);
			}
			Cursor.visible = false;
			if (wheel.SelectedIndex != selectedIndex)
			{
				PlaySelectionSound(instance.AudioManager);
			}
			if (gameInput.GetButtonNew(2, 0) || Input.GetMouseButtonDown(0))
			{
				selectionResolved = true;
				pickerOpen = false;
			}
			else if (gameInput.GetButtonNew(3, 0) || Input.GetMouseButtonDown(1))
			{
				if (rememberedIndex >= 0)
				{
					wheel.SelectIndex(rememberedIndex);
				}
				else
				{
					aborted = true;
				}
				selectionResolved = true;
				pickerOpen = false;
			}
			if (pickerOpen && (Object)(object)instance.UIManager != (Object)null)
			{
				if (hints == null)
				{
					hints = new GameButtonHints(instance.UIManager);
				}
				hints.Refresh(gameInput, rememberedIndex >= 0);
			}
			else if (hints != null)
			{
				hints.Hide();
			}
			if (!pickerOpen && backgroundBlur != null)
			{
				backgroundBlur.UpdateActive(active: false);
			}
			if (!pickerOpen)
			{
				RestoreMouseCursor();
			}
		}

		private void PlaySelectionSound(AudioManager manager)
		{
			if (selectionAudio != null)
			{
				selectionAudio.Play(manager);
			}
		}

		private void WarmResources()
		{
			if ((hintsWarmed && paintVisuals != null) || Time.unscaledTime < nextWarmAttempt)
			{
				return;
			}
			Core instance = Core.Instance;
			if ((Object)(object)instance == (Object)null || (Object)(object)instance.UIManager == (Object)null || instance.GameInput == null || !instance.GameInput.IsRewiredInitialized)
			{
				return;
			}
			try
			{
				if (paintVisuals == null)
				{
					paintVisuals = new PaintVisuals();
				}
				else if (hints == null)
				{
					hints = new GameButtonHints(instance.UIManager);
				}
				else if (!hintsWarmed && !pickerOpen)
				{
					hints.Warmup(instance.GameInput);
					hintsWarmed = true;
				}
			}
			catch (Exception ex)
			{
				nextWarmAttempt = Time.unscaledTime + 5f;
				((BaseUnityPlugin)this).Logger.LogWarning((object)("Picker warmup will retry when UI is ready: " + ex.Message));
			}
		}

		private void LateUpdate()
		{
			//IL_00be: Unknown result type (might be due to invalid IL or missing references)
			Core instance = Core.Instance;
			bool flag = pickerOpen && wheel != null && (Object)(object)activeGame != (Object)null && (Object)(object)instance != (Object)null && (Object)(object)instance.BaseModule != (Object)null && !instance.BaseModule.IsInGamePaused;
			float age = Mathf.Max(0f, Time.unscaledTime - openedAt);
			float selectedAngle = (flag ? ((float)(wheel.SelectedIndex - wheel.PageStart) * (360f / (float)wheel.VisibleCount)) : 0f);
			if (selectorCamera != null)
			{
				selectorCamera.UpdateActive(flag, activeGame, age, selectedAngle);
			}
			if (backgroundBlur != null)
			{
				backgroundBlur.SetQuality(nativeBlurQuality.Value);
				backgroundBlur.UpdateActive(flag && nativeBlurEnabled.Value, PresentationTiming.BlurWeight(age));
			}
			if (pickerOpen && wheel != null)
			{
				float unscaledDeltaTime = Time.unscaledDeltaTime;
				visualPointerAngle = WheelMotion.SmoothAngle(visualPointerAngle, wheel.PointerAngle, unscaledDeltaTime);
				float num = 1f - Mathf.Exp((0f - unscaledDeltaTime) / 0.045f);
				float num2 = 360f / (float)wheel.VisibleCount;
				for (int i = 0; i < wheel.VisibleCount; i++)
				{
					bool selected = wheel.PageStart + i == wheel.SelectedIndex;
					float num3 = WheelMotion.TargetScale((float)i * num2, visualPointerAngle, selected);
					iconScales[i] = Mathf.Lerp(iconScales[i], num3, num);
				}
			}
		}

		private void OnGUI()
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Invalid comparison between Unknown and I4
			//IL_005c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0062: Invalid comparison between Unknown and I4
			//IL_0087: Unknown result type (might be due to invalid IL or missing references)
			//IL_008c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0093: 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_00a6: Expected O, but got Unknown
			//IL_00ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00be: Expected O, but got Unknown
			//IL_00c5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cf: Expected O, but got Unknown
			//IL_01f8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01fd: Unknown result type (might be due to invalid IL or missing references)
			//IL_01fe: Unknown result type (might be due to invalid IL or missing references)
			//IL_020a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0212: Unknown result type (might be due to invalid IL or missing references)
			//IL_0246: Unknown result type (might be due to invalid IL or missing references)
			//IL_0258: 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_0277: Unknown result type (might be due to invalid IL or missing references)
			//IL_027d: Unknown result type (might be due to invalid IL or missing references)
			//IL_028a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0291: Unknown result type (might be due to invalid IL or missing references)
			//IL_029f: 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_02d5: Unknown result type (might be due to invalid IL or missing references)
			//IL_02e3: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ff: Unknown result type (might be due to invalid IL or missing references)
			//IL_0330: Unknown result type (might be due to invalid IL or missing references)
			//IL_0336: Unknown result type (might be due to invalid IL or missing references)
			//IL_033c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0346: Unknown result type (might be due to invalid IL or missing references)
			//IL_034b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0350: Unknown result type (might be due to invalid IL or missing references)
			//IL_035d: Unknown result type (might be due to invalid IL or missing references)
			//IL_036d: Unknown result type (might be due to invalid IL or missing references)
			//IL_03d3: Unknown result type (might be due to invalid IL or missing references)
			//IL_03d8: Unknown result type (might be due to invalid IL or missing references)
			//IL_03fc: Unknown result type (might be due to invalid IL or missing references)
			//IL_0505: Unknown result type (might be due to invalid IL or missing references)
			//IL_0513: Unknown result type (might be due to invalid IL or missing references)
			//IL_0426: Unknown result type (might be due to invalid IL or missing references)
			//IL_0413: Unknown result type (might be due to invalid IL or missing references)
			//IL_0565: Unknown result type (might be due to invalid IL or missing references)
			//IL_0573: Unknown result type (might be due to invalid IL or missing references)
			//IL_058f: Unknown result type (might be due to invalid IL or missing references)
			//IL_05b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_05be: Unknown result type (might be due to invalid IL or missing references)
			//IL_05da: Unknown result type (might be due to invalid IL or missing references)
			//IL_054c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0468: Unknown result type (might be due to invalid IL or missing references)
			//IL_04e2: Unknown result type (might be due to invalid IL or missing references)
			//IL_04bf: Unknown result type (might be due to invalid IL or missing references)
			//IL_04d8: Unknown result type (might be due to invalid IL or missing references)
			//IL_0699: Unknown result type (might be due to invalid IL or missing references)
			//IL_069e: Unknown result type (might be due to invalid IL or missing references)
			//IL_06a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_06a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_06a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_06ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_06b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_06b8: Unknown result type (might be due to invalid IL or missing references)
			//IL_06c3: Unknown result type (might be due to invalid IL or missing references)
			//IL_06d2: Unknown result type (might be due to invalid IL or missing references)
			//IL_06f7: Unknown result type (might be due to invalid IL or missing references)
			//IL_0707: Unknown result type (might be due to invalid IL or missing references)
			//IL_071b: Unknown result type (might be due to invalid IL or missing references)
			//IL_072b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0732: Unknown result type (might be due to invalid IL or missing references)
			if ((int)Event.current.type == 7 && !rendererWarmed && paintVisuals != null)
			{
				paintVisuals.Prepare(Mathf.Min((float)Screen.height * 0.4f, (float)Screen.width * 0.3f) * 2f, 1f);
				rendererWarmed = true;
			}
			if ((int)Event.current.type != 7)
			{
				return;
			}
			if (titleStyle == null && (paintVisuals != null || pickerOpen))
			{
				detailStyle = new GUIStyle(GUI.skin.label)
				{
					alignment = (TextAnchor)4,
					wordWrap = true,
					richText = false
				};
				titleStyle = new GUIStyle(detailStyle)
				{
					fontStyle = (FontStyle)1
				};
				sizeStyle = new GUIStyle(titleStyle);
			}
			if (!pickerOpen || wheel == null)
			{
				return;
			}
			if (backgroundBlur != null)
			{
				backgroundBlur.Draw(Time.unscaledTime - openedAt);
			}
			float num = Mathf.Min((float)Screen.height * 0.4f, (float)Screen.width * 0.3f);
			Vector2 val = default(Vector2);
			((Vector2)(ref val))..ctor((float)Screen.width * 0.5f, (float)Screen.height * 0.46f);
			float num2 = 360f / (float)wheel.VisibleCount;
			detailStyle.fontSize = Mathf.Max(13, Mathf.RoundToInt(num * 0.04f));
			titleStyle.fontSize = Mathf.Max(17, Mathf.RoundToInt(num * 0.054f));
			sizeStyle.fontSize = Mathf.RoundToInt((float)titleStyle.fontSize * 1.7f);
			if (hints != null && (Object)(object)hints.GuiFont != (Object)null)
			{
				GUIStyle obj = titleStyle;
				GUIStyle obj2 = detailStyle;
				Font val2 = (sizeStyle.font = hints.GuiFont);
				Font font = (obj2.font = val2);
				obj.font = font;
			}
			Color color = GUI.color;
			GUI.color = Color.white;
			Rect val4 = default(Rect);
			((Rect)(ref val4))..ctor(val.x - num, val.y - num, num * 2f, num * 2f);
			if (paintVisuals == null)
			{
				paintVisuals = new PaintVisuals();
			}
			paintVisuals.Draw(val4, Time.unscaledTime - openedAt);
			Matrix4x4 matrix = GUI.matrix;
			GUIUtility.RotateAroundPivot((float)(wheel.SelectedIndex - wheel.PageStart) * num2, val);
			GUI.DrawTexture(val4, (Texture)(object)ringTexture);
			GUI.matrix = matrix;
			DrawTitleTab(new Rect(val.x - num * 0.91f, val.y - num * 0.93f, num * 0.83f, num * 0.1f), "GRAFFITI SELECT", -17f, detailStyle);
			DrawTitleTab(new Rect(val.x + num * 0.56f, val.y - num * 0.78f, num * 0.29f, num * 0.16f), sizeCategory, 17f, sizeStyle);
			Rect val6 = default(Rect);
			Rect val7 = default(Rect);
			for (int i = 0; i < wheel.VisibleCount; i++)
			{
				int num3 = wheel.PageStart + i;
				Vector2 val5 = val + Direction((float)i * num2) * num * 0.73f;
				float num4 = num * 0.26f;
				((Rect)(ref val6))..ctor(val5.x - num4 * 0.5f, val5.y - num4 * 0.5f, num4, num4);
				bool flag = num3 == wheel.SelectedIndex;
				((Rect)(ref val7))..ctor(((Rect)(ref val6)).x + 7f, ((Rect)(ref val6)).y + 7f, num4 - 14f, num4 * 0.73f);
				float num5 = iconScales[i];
				Vector2 center = ((Rect)(ref val7)).center;
				((Rect)(ref val7)).width = ((Rect)(ref val7)).width * num5;
				((Rect)(ref val7)).height = ((Rect)(ref val7)).height * num5;
				((Rect)(ref val7)).center = center;
				if ((Object)(object)previews[num3] != (Object)null)
				{
					GUI.DrawTexture(val7, previews[num3], (ScaleMode)2, true);
				}
				else
				{
					GUI.Label(val7, "Preview unavailable", detailStyle);
				}
				DrawName(new Rect(((Rect)(ref val6)).x - num4 * 0.12f, ((Rect)(ref val6)).y + num4 * 0.76f, num4 * 1.24f, num4 * 0.42f), artNames[num3], detailStyle, flag);
				if (flag)
				{
					Fill(new Rect(((Rect)(ref val6)).x + num4 * 0.19f, ((Rect)(ref val6)).y + num4 * 1.13f, num4 * 0.62f, Mathf.Max(3f, num * 0.008f)), new Color(0.56f, 0.9f, 0.28f, 1f));
				}
				GUI.color = Color.white;
			}
			Rect val8 = default(Rect);
			((Rect)(ref val8))..ctor(val.x - num * 0.38f, val.y - num * 0.3f, num * 0.76f, num * 0.53f);
			if ((Object)(object)previews[wheel.SelectedIndex] != (Object)null)
			{
				GUI.DrawTexture(val8, previews[wheel.SelectedIndex], (ScaleMode)2, true);
			}
			DrawName(new Rect(val.x - num * 0.4f, val.y + num * 0.24f, num * 0.8f, num * 0.13f), artNames[wheel.SelectedIndex], titleStyle, selected: false);
			GUI.Label(new Rect(val.x - num * 0.4f, val.y + num * 0.37f, num * 0.8f, num * 0.06f), wheel.SelectedIndex + 1 + " / " + choices.Count + "   •   " + (wheel.PageStart / 12 + 1) + " / " + (choices.Count + 12 - 1) / 12 + ((wheel.SelectedIndex == rememberedIndex) ? "   •   LAST USED" : ""), detailStyle);
			Vector2 val9 = Direction(visualPointerAngle);
			Vector2 val10 = val + val9 * num * 0.515f;
			float num6 = num * 0.17f;
			GUI.color = Color.white;
			GUIUtility.RotateAroundPivot(visualPointerAngle, val10);
			float num7 = num6 * (float)((Texture)pointerTexture).height / (float)((Texture)pointerTexture).width;
			GUI.DrawTexture(new Rect(val10.x - num6 * 0.5f, val10.y - num7 * 0.5f, num6, num7), (Texture)(object)pointerTexture);
			GUI.matrix = matrix;
			GUI.color = color;
			SelectorPaintCloud.DrawForegroundDots();
		}

		private static void DrawTitleTab(Rect rect, string text, float angle, GUIStyle style)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: 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_0027: 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)
			Matrix4x4 matrix = GUI.matrix;
			GUIUtility.RotateAroundPivot(angle, ((Rect)(ref rect)).center);
			Fill(rect, new Color(0.025f, 0.03f, 0.023f, 1f));
			GUI.Label(rect, text, style);
			GUI.matrix = matrix;
		}

		private static void DrawName(Rect rect, GUIContent content, GUIStyle style, bool selected)
		{
			//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_0061: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e5: 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_00ef: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fe: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a5: Unknown result type (might be due to invalid IL or missing references)
			Color color = GUI.color;
			int fontSize = style.fontSize;
			while (style.fontSize > Mathf.Max(11, fontSize * 2 / 3) && style.CalcHeight(content, ((Rect)(ref rect)).width) > ((Rect)(ref rect)).height)
			{
				int fontSize2 = style.fontSize;
				style.fontSize = fontSize2 - 1;
			}
			float num = Mathf.Max(1f, (float)Screen.height / 720f);
			GUI.color = Color.black;
			for (int i = -1; i <= 1; i++)
			{
				for (int j = -1; j <= 1; j++)
				{
					if (i != 0 || j != 0)
					{
						GUI.Label(new Rect(((Rect)(ref rect)).x + (float)i * num, ((Rect)(ref rect)).y + (float)j * num, ((Rect)(ref rect)).width, ((Rect)(ref rect)).height), content, style);
					}
				}
			}
			GUI.color = (Color)(selected ? new Color(0.72f, 1f, 0.42f, 1f) : Color.white);
			GUI.Label(rect, content, style);
			style.fontSize = fontSize;
			GUI.color = color;
		}

		private static void EnablePickerMaps(GameInput input)
		{
			//IL_000d: 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)
			ControllerType[] array = pickerControllerTypes;
			foreach (ControllerType val in array)
			{
				int[] array2 = pickerActions;
				foreach (int num in array2)
				{
					ActionElementMap currentControllerActionElementMap = input.RewiredMappingHandler.GetCurrentControllerActionElementMap(num, val, 0);
					ControllerMap val2 = ((currentControllerActionElementMap == null) ? null : currentControllerActionElementMap.controllerMap);
					if (val2 != null)
					{
						if (!pickerMaps.ContainsKey(val2))
						{
							pickerMaps.Add(val2, val2.enabled);
						}
						val2.enabled = true;
					}
				}
			}
		}

		internal static void RestorePickerMaps()
		{
			NativeSprayPose.ResetFor(activeGame);
			RestoreMouseCursor();
			if (selectorCamera != null)
			{
				selectorCamera.Restore();
			}
			if (backgroundBlur != null)
			{
				backgroundBlur.UpdateActive(active: false);
			}
			RestoreNativeCircle();
			foreach (KeyValuePair<ControllerMap, bool> pickerMap in pickerMaps)
			{
				pickerMap.Key.enabled = pickerMap.Value;
			}
			pickerMaps.Clear();
		}

		private static void CaptureMouseCursor()
		{
			//IL_0008: 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_002e: 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_0038: Unknown result type (might be due to invalid IL or missing references)
			if (!mouseCaptured)
			{
				savedCursorLock = Cursor.lockState;
				savedCursorVisible = Cursor.visible;
				mouseCaptured = true;
				Cursor.lockState = (CursorLockMode)2;
				Cursor.visible = false;
				lastMousePosition = Vector2.op_Implicit(Input.mousePosition);
			}
		}

		private static void RestoreMouseCursor()
		{
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			if (mouseCaptured)
			{
				Cursor.lockState = savedCursorLock;
				Cursor.visible = savedCursorVisible;
				mouseCaptured = false;
			}
		}

		private static void HideNativeCircle(GraffitiGame game)
		{
			RestoreNativeCircle();
			hiddenCircle = Traverse.Create((object)game).Field("backgroundCircle").GetValue<GameObject>();
			if (!((Object)(object)hiddenCircle == (Object)null))
			{
				circleWasActive = hiddenCircle.activeSelf;
				hiddenCircle.SetActive(false);
			}
		}

		private static void RestoreNativeCircle()
		{
			if ((Object)(object)hiddenCircle != (Object)null)
			{
				hiddenCircle.SetActive(circleWasActive);
			}
			hiddenCircle = null;
		}

		private static Vector2 Direction(float clockwiseDegrees)
		{
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			float num = clockwiseDegrees * ((float)Math.PI / 180f);
			return new Vector2(Mathf.Sin(num), 0f - Mathf.Cos(num));
		}

		private static void Fill(Rect rect, Color color)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			GUI.color = color;
			GUI.DrawTexture(rect, (Texture)(object)Texture2D.whiteTexture);
			GUI.color = Color.white;
		}

		private static void DrawLine(Vector2 from, Vector2 to, float width, Color color)
		{
			//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_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_000c: 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_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: 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_003c: 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_0061: Unknown result type (might be due to invalid IL or missing references)
			Matrix4x4 matrix = GUI.matrix;
			Color color2 = GUI.color;
			Vector2 val = to - from;
			GUIUtility.RotateAroundPivot(Mathf.Atan2(val.y, val.x) * 57.29578f, from);
			GUI.color = color;
			GUI.DrawTexture(new Rect(from.x, from.y - width * 0.5f, ((Vector2)(ref val)).magnitude, width), (Texture)(object)Texture2D.whiteTexture);
			GUI.matrix = matrix;
			GUI.color = color2;
		}

		internal unsafe static void BeginSelection(GraffitiGame game, List<GraffitiArt> available, GraffitiSize size)
		{
			//IL_0125: Unknown result type (might be due to invalid IL or missing references)
			//IL_012b: Expected O, but got Unknown
			if (activeGame == game)
			{
				return;
			}
			activeGame = game;
			openedAt = Time.unscaledTime;
			inputReadyTime = Time.unscaledTime + 0.15f;
			choices = available;
			pickerOpen = choices != null && choices.Count > 0;
			selectionResolved = !pickerOpen;
			aborted = false;
			rememberedIndex = -1;
			sizeCategory = ((object)(*(GraffitiSize*)(&size))/*cast due to .constrained prefix*/).ToString();
			wheel = (pickerOpen ? new WheelSelection(choices.Count) : null);
			previews = (Texture[])(object)(pickerOpen ? new Texture[choices.Count] : null);
			artNames = (GUIContent[])(object)(pickerOpen ? new GUIContent[choices.Count] : null);
			if (pickerOpen && selectorCamera != null)
			{
				selectorCamera.BeginSession();
			}
			if (pickerOpen)
			{
				HideNativeCircle(game);
			}
			if (pickerOpen)
			{
				for (int i = 0; i < choices.Count; i++)
				{
					GraffitiArt val = choices[i];
					artNames[i] = new GUIContent((val == null) ? "" : val.title);
					if (val != null)
					{
						Texture val2 = (((Object)(object)val.unlockable == (Object)null) ? null : val.unlockable.GraffitiTexture);
						previews[i] = (((Object)(object)val2 != (Object)null) ? val2 : (((Object)(object)val.graffitiMaterial == (Object)null) ? null : val.graffitiMaterial.mainTexture));
					}
				}
			}
			if (pickerOpen && memory != null)
			{
				rememberedIndex = memory.FindAvailable(sizeCategory, choices.ConvertAll((GraffitiArt art) => art?.title));
				if (rememberedIndex >= 0)
				{
					wheel.SelectIndex(rememberedIndex);
				}
			}
			if (pickerOpen)
			{
				aimInput.Reset();
				CaptureMouseCursor();
				NativeSprayPose.Begin(game, Traverse.Create((object)game).Field("characterPuppet").GetValue<CharacterVisual>());
				visualPointerAngle = wheel.PointerAngle;
				for (int num = 0; num < iconScales.Length; num++)
				{
					iconScales[num] = ((num == wheel.SelectedIndex - wheel.PageStart) ? 1.8f : 1f);
				}
			}
		}

		internal static bool IsSelectionResolved(GraffitiGame game)
		{
			if (activeGame == game)
			{
				return selectionResolved;
			}
			return false;
		}

		internal static bool HasSelectionFor(GraffitiGame game)
		{
			return activeGame == game;
		}

		internal static GraffitiArt TakeSelection(GraffitiGame game)
		{
			if (activeGame != game || !selectionResolved || wheel == null || aborted)
			{
				return null;
			}
			return choices[wheel.SelectedIndex];
		}

		internal static GraffitiArt TakeActiveSelection()
		{
			if (!((Object)(object)activeGame == (Object)null))
			{
				return TakeSelection(activeGame);
			}
			return null;
		}

		internal static void FinishSelection(GraffitiGame game)
		{
			if (activeGame == game)
			{
				RestorePickerMaps();
				activeGame = null;
				choices = null;
				previews = null;
				artNames = null;
				wheel = null;
				pickerOpen = false;
				selectionResolved = false;
				aborted = false;
				rememberedIndex = -1;
			}
		}

		internal static bool SelectionWasAborted(GraffitiGame game)
		{
			if (activeGame == game)
			{
				return aborted;
			}
			return false;
		}

		internal static void RememberPainted(GraffitiArt art)
		{
			if (art != null && memory != null)
			{
				memory.RecordPainted(((object)Unsafe.As<GraffitiSize, GraffitiSize>(ref art.graffitiSize)/*cast due to .constrained prefix*/).ToString(), art.title);
			}
		}

		private void OnDestroy()
		{
			RestorePickerMaps();
			NativeSprayPose.Reset();
			harmony.UnpatchSelf();
			if (hints != null)
			{
				hints.Dispose();
			}
			if (paintVisuals != null)
			{
				paintVisuals.Dispose();
			}
			if (backgroundBlur != null)
			{
				backgroundBlur.Dispose();
				backgroundBlur = null;
			}
			if (selectorCamera != null)
			{
				selectorCamera.Dispose();
				selectorCamera = null;
			}
			if (selectionAudio != null)
			{
				selectionAudio.Dispose();
				selectionAudio = null;
			}
			if ((Object)(object)ringTexture != (Object)null)
			{
				Object.Destroy((Object)(object)ringTexture);
			}
			if ((Object)(object)pointerTexture != (Object)null)
			{
				Object.Destroy((Object)(object)pointerTexture);
			}
			activeGame = null;
			choices = null;
			previews = null;
			artNames = null;
			wheel = null;
			pickerOpen = false;
		}
	}
	internal sealed class BackgroundBlur : IDisposable
	{
		private static readonly FieldInfo resourceField = AccessTools.Field(typeof(PostProcessLayer), "m_Resources");

		private readonly Action<string> log;

		private readonly List<PostProcessLayer> ownedLayers = new List<PostProcessLayer>();

		private Camera[] cameras = (Camera[])(object)new Camera[8];

		private PostProcessResources resources;

		private GameObject root;

		private PostProcessProfile profile;

		private PostProcessVolume volume;

		private DepthOfField effect;

		private Camera camera;

		private PostProcessLayer layer;

		private bool originalEnabled;

		private bool bound;

		private bool disposed;

		private bool failed;

		private bool warned;

		private bool logged;

		private LayerMask originalMask;

		private DepthTextureMode originalDepth;

		private float nextResourceAttempt;

		private KernelSize requestedQuality = (KernelSize)1;

		internal BackgroundBlur(Action<string> logger)
		{
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			log = logger;
		}

		internal void SetQuality(KernelSize quality)
		{
			//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_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			if (requestedQuality != quality)
			{
				requestedQuality = quality;
				if ((Object)(object)effect != (Object)null)
				{
					((ParameterOverride<KernelSize>)(object)effect.kernelSize).Override(quality);
				}
			}
		}

		private static bool Usable(PostProcessResources candidate)
		{
			if ((Object)(object)candidate != (Object)null && candidate.shaders != null && (Object)(object)candidate.shaders.depthOfField != (Object)null)
			{
				return candidate.shaders.depthOfField.isSupported;
			}
			return false;
		}

		private void FindResources()
		{
			if (Usable(resources) || Time.unscaledTime < nextResourceAttempt)
			{
				return;
			}
			nextResourceAttempt = Time.unscaledTime + 2f;
			PostProcessResources[] array = Resources.FindObjectsOfTypeAll<PostProcessResources>();
			foreach (PostProcessResources candidate in array)
			{
				if (Usable(candidate))
				{
					resources = candidate;
					return;
				}
			}
			PostProcessLayer[] array2 = Resources.FindObjectsOfTypeAll<PostProcessLayer>();
			foreach (PostProcessLayer obj in array2)
			{
				PostProcessResources candidate2 = (PostProcessResources)((resourceField == null) ? null : /*isinst with value type is only supported in some contexts*/);
				if (Usable(candidate2))
				{
					resources = candidate2;
					break;
				}
			}
		}

		internal void Prepare()
		{
			//IL_00f3: 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_0108: Unknown result type (might be due to invalid IL or missing references)
			//IL_0115: Expected O, but got Unknown
			if (disposed || failed)
			{
				return;
			}
			try
			{
				FindResources();
				if (!((Object)(object)root != (Object)null) || !((Object)(object)volume != (Object)null) || !((Object)(object)profile != (Object)null) || !((Object)(object)effect != (Object)null))
				{
					Detach();
					ReleaseVolume();
					profile = ScriptableObject.CreateInstance<PostProcessProfile>();
					((Object)profile).hideFlags = (HideFlags)61;
					effect = profile.AddSettings<DepthOfField>();
					((Object)effect).hideFlags = (HideFlags)61;
					((ParameterOverride<bool>)(object)((PostProcessEffectSettings)effect).enabled).Override(true);
					((ParameterOverride<float>)(object)effect.focusDistance).Override(0.15f);
					((ParameterOverride<float>)(object)effect.focalLength).Override(100f);
					((ParameterOverride<float>)(object)effect.aperture).Override(1f);
					((ParameterOverride<KernelSize>)(object)effect.kernelSize).Override(requestedQuality);
					root = new GameObject("SpraySelectorNativeBlur")
					{
						hideFlags = (HideFlags)61
					};
					Object.DontDestroyOnLoad((Object)(object)root);
					root.SetActive(false);
					volume = root.AddComponent<PostProcessVolume>();
					volume.sharedProfile = profile;
					volume.isGlobal = true;
					volume.priority = 100000f;
					volume.weight = 0f;
				}
			}
			catch (Exception ex)
			{
				Fail("Native blur preparation failed: " + ex.Message);
			}
		}

		internal void UpdateActive(bool active, float strength = 1f)
		{
			//IL_00b1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b7: Invalid comparison between Unknown and I4
			//IL_00d9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00de: 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_026f: Unknown result type (might be due to invalid IL or missing references)
			//IL_02dd: Unknown result type (might be due to invalid IL or missing references)
			//IL_02e2: Unknown result type (might be due to invalid IL or missing references)
			//IL_0309: Unknown result type (might be due to invalid IL or missing references)
			//IL_030e: Unknown result type (might be due to invalid IL or missing references)
			strength = Mathf.Clamp01(strength);
			if (!active || strength <= 0f || disposed || failed)
			{
				Detach();
				return;
			}
			Prepare();
			if (failed || (Object)(object)volume == (Object)null)
			{
				return;
			}
			volume.weight = strength;
			try
			{
				int allCamerasCount = Camera.allCamerasCount;
				if (cameras.Length < allCamerasCount)
				{
					cameras = (Camera[])(object)new Camera[Mathf.NextPowerOfTwo(allCamerasCount)];
				}
				allCamerasCount = Camera.GetAllCameras(cameras);
				Camera val = null;
				for (int i = 0; i < allCamerasCount; i++)
				{
					Camera val2 = cameras[i];
					if (!((Object)(object)val2 == (Object)null) && ((Behaviour)val2).isActiveAndEnabled && (int)val2.cameraType == 1 && !((Object)(object)val2.targetTexture != (Object)null) && val2.targetDisplay == 0)
					{
						Rect rect = val2.rect;
						if (!(Mathf.Abs(((Rect)(ref rect)).x) > 0.001f) && !(Mathf.Abs(((Rect)(ref rect)).y) > 0.001f) && !(Mathf.Abs(((Rect)(ref rect)).width - 1f) > 0.001f) && !(Mathf.Abs(((Rect)(ref rect)).height - 1f) > 0.001f) && ((Object)(object)val == (Object)null || val2.depth >= val.depth))
						{
							val = val2;
						}
					}
				}
				if (bound && (Object)(object)val == (Object)(object)camera && (Object)(object)layer != (Object)null)
				{
					return;
				}
				Detach();
				ownedLayers.RemoveAll((PostProcessLayer owned) => (Object)(object)owned == (Object)null);
				if ((Object)(object)val == (Object)null)
				{
					Warn("Native blur: no active fullscreen camera found.");
					return;
				}
				PostProcessLayer val3 = ((Component)val).GetComponent<PostProcessLayer>();
				PostProcessResources val4 = (PostProcessResources)(((Object)(object)val3 == (Object)null || resourceField == null) ? null : /*isinst with value type is only supported in some contexts*/);
				if (!Usable(val4))
				{
					val4 = resources;
				}
				if (!Usable(val4))
				{
					Warn("Native blur: waiting for the game's post-processing resources.");
					return;
				}
				if ((Object)(object)val3 != (Object)null && !Usable((PostProcessResources)/*isinst with value type is only supported in some contexts*/))
				{
					Warn("Native blur: existing camera effects do not have usable resources.");
					return;
				}
				camera = val;
				originalDepth = camera.depthTextureMode;
				if ((Object)(object)val3 == (Object)null)
				{
					val3 = ((Component)camera).gameObject.AddComponent<PostProcessLayer>();
					ownedLayers.Add(val3);
					((Behaviour)val3).enabled = false;
					val3.Init(val4);
				}
				layer = val3;
				originalEnabled = !ownedLayers.Contains(layer) && ((Behaviour)layer).enabled;
				originalMask = layer.volumeLayer;
				bound = true;
				int value = ((LayerMask)(ref originalMask)).value;
				int num = 0;
				if (value == 0)
				{
					layer.volumeLayer = LayerMask.op_Implicit(1);
				}
				else
				{
					for (; num < 31 && (value & (1 << num)) == 0; num++)
					{
					}
				}
				root.layer = num;
				root.SetActive(true);
				((Behaviour)layer).enabled = true;
				if (!logged && log != null)
				{
					logged = true;
					log("Native depth-of-field blur enabled on camera " + ((Object)camera).name + ".");
				}
			}
			catch (Exception ex)
			{
				Fail("Native blur activation failed: " + ex.Message);
			}
		}

		internal void Draw(float age)
		{
		}

		private void Detach()
		{
			//IL_0067: Unknown result type (might be due to invalid IL or missing references)
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)root != (Object)null)
			{
				root.SetActive(false);
			}
			if (bound && (Object)(object)layer != (Object)null)
			{
				layer.volumeLayer = originalMask;
				((Behaviour)layer).enabled = originalEnabled;
			}
			if ((Object)(object)camera != (Object)null)
			{
				camera.depthTextureMode = originalDepth;
			}
			bound = false;
			layer = null;
			camera = null;
		}

		private void ReleaseVolume()
		{
			if ((Object)(object)volume != (Object)null)
			{
				volume.sharedProfile = null;
			}
			if ((Object)(object)profile != (Object)null)
			{
				profile.settings.Clear();
			}
			if ((Object)(object)effect != (Object)null)
			{
				Object.Destroy((Object)(object)effect);
			}
			if ((Object)(object)profile != (Object)null)
			{
				Object.Destroy((Object)(object)profile);
			}
			if ((Object)(object)root != (Object)null)
			{
				Object.Destroy((Object)(object)root);
			}
			effect = null;
			profile = null;
			volume = null;
			root = null;
		}

		private void Warn(string message)
		{
			if (!warned)
			{
				warned = true;
				if (log != null)
				{
					log(message);
				}
			}
		}

		private void Fail(string message)
		{
			failed = true;
			Detach();
			Warn(message);
		}

		public void Dispose()
		{
			if (disposed)
			{
				return;
			}
			disposed = true;
			Detach();
			foreach (PostProcessLayer ownedLayer in ownedLayers)
			{
				if ((Object)(object)ownedLayer != (Object)null)
				{
					((Behaviour)ownedLayer).enabled = false;
					Object.Destroy((Object)(object)ownedLayer);
				}
			}
			ownedLayers.Clear();
			ReleaseVolume();
			resources = null;
		}
	}
	internal sealed class SelectorCameraMotion : IDisposable
	{
		private static readonly FieldInfo cameraField = AccessTools.Field(typeof(GraffitiGame), "graffitiCameraTf");

		private static readonly FieldInfo puppetField = AccessTools.Field(typeof(GraffitiGame), "characterPuppet");

		private static readonly FieldInfo playerField = AccessTools.Field(typeof(GraffitiGame), "player");

		private readonly Action<string> log;

		private GraffitiGame owner;

		private Transform camera;

		private Vector3 originalPosition;

		private Vector3 pivot;

		private Quaternion originalRotation;

		private bool bound;

		private bool failed;

		private float orbitDirection = 1f;

		private readonly CameraMotionState attachment = new CameraMotionState();

		private float noiseSeed;

		internal SelectorCameraMotion(Action<string> logger)
		{
			log = logger;
		}

		internal void BeginSession()
		{
			Restore();
			orbitDirection = ((Random.value < 0.5f) ? (-1f) : 1f);
			noiseSeed = Random.Range(10f, 1000f);
		}

		private void AttachTo(float clockwiseDegrees)
		{
			if (!failed)
			{
				float num = clockwiseDegrees * ((float)Math.PI / 180f);
				attachment.SetTarget(Mathf.Sin(num), Mathf.Cos(num));
			}
		}

		internal void UpdateActive(bool active, GraffitiGame game, float age, float selectedAngle)
		{
			//IL_018a: Unknown result type (might be due to invalid IL or missing references)
			//IL_018f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0194: 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)
			//IL_0197: Unknown result type (might be due to invalid IL or missing references)
			//IL_019c: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_01cd: Unknown result type (might be due to invalid IL or missing references)
			//IL_01cf: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d4: 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_01da: Unknown result type (might be due to invalid IL or missing references)
			//IL_0200: Unknown result type (might be due to invalid IL or missing references)
			//IL_0207: Unknown result type (might be due to invalid IL or missing references)
			//IL_020c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0211: Unknown result type (might be due to invalid IL or missing references)
			//IL_0213: Unknown result type (might be due to invalid IL or missing references)
			//IL_0216: Unknown result type (might be due to invalid IL or missing references)
			//IL_021b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0220: Unknown result type (might be due to invalid IL or missing references)
			//IL_0229: Unknown result type (might be due to invalid IL or missing references)
			//IL_022e: 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_0237: 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_0241: Unknown result type (might be due to invalid IL or missing references)
			//IL_0246: 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_0258: Unknown result type (might be due to invalid IL or missing references)
			//IL_025a: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e6: 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_00f3: Unknown result type (might be due to invalid IL or missing references)
			//IL_0100: 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_010a: Unknown result type (might be due to invalid IL or missing references)
			//IL_010f: Unknown result type (might be due to invalid IL or missing references)
			if (!active || (Object)(object)game == (Object)null || failed)
			{
				Restore();
				return;
			}
			try
			{
				if ((Object)(object)owner != (Object)(object)game || (Object)(object)camera == (Object)null || !bound)
				{
					Restore();
					Transform val = (Transform)((cameraField == null) ? null : /*isinst with value type is only supported in some contexts*/);
					Component val2 = (Component)((puppetField == null) ? null : /*isinst with value type is only supported in some contexts*/);
					if ((Object)(object)val2 == (Object)null && playerField != null)
					{
						object? value = playerField.GetValue(game);
						val2 = (Component)((value is Component) ? value : null);
					}
					if ((Object)(object)val == (Object)null || (Object)(object)val2 == (Object)null)
					{
						return;
					}
					owner = game;
					camera = val;
					originalPosition = val.position;
					originalRotation = val.rotation;
					pivot = val2.transform.position + Vector3.up;
					bound = true;
				}
				AttachTo(selectedAngle);
				attachment.Step(Time.unscaledDeltaTime);
				float num = Mathf.Max(0f, age);
				float num2 = orbitDirection * num * ((float)Math.PI / 9f);
				float num3 = Mathf.SmoothStep(0f, 1f, Mathf.Clamp01(num / 0.8f));
				Quaternion val3 = Quaternion.AngleAxis(3.2f * Mathf.Sin(num2) * num3 + 9f * attachment.X, Vector3.up);
				Vector3 val4 = val3 * originalRotation * Vector3.right;
				Quaternion val5 = Quaternion.AngleAxis(1.7f * Mathf.Cos(num2) * num3 + 4f * attachment.Y, val4) * val3;
				float num4 = Mathf.SmoothStep(0f, 1f, Mathf.Clamp01(num / 0.4f));
				Quaternion val6 = Quaternion.Euler(SampleHandheld(num, noiseSeed) * num4);
				Quaternion val7 = val5 * originalRotation;
				camera.position = pivot + val5 * (originalPosition - pivot);
				camera.rotation = val7 * val6;
			}
			catch (Exception ex)
			{
				Restore();
				failed = true;
				if (log != null)
				{
					log("Selector camera motion disabled: " + ex.Message);
				}
			}
		}

		private static Vector3 SampleHandheld(float time, float seed)
		{
			//IL_00aa: Unknown result type (might be due to invalid IL or missing references)
			float num = 0.1f * Noise(time * 0.63f, seed) + 0.025f * Noise(time * 1.8f, seed + 17f) + 0.012f * Mathf.Sin(time * 1.1f);
			float num2 = 0.11f * Noise(time * 0.52f, seed + 37f) + 0.025f * Noise(time * 1.6f, seed + 53f);
			float num3 = 0.06f * Noise(time * 0.74f, seed + 71f) + 0.015f * Noise(time * 1.9f, seed + 97f);
			return new Vector3(num, num2, num3);
		}

		private static float Noise(float time, float seed)
		{
			return 2f * Mathf.Clamp01(Mathf.PerlinNoise(time, seed)) - 1f;
		}

		internal void Restore()
		{
			//IL_001d: 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)
			if (bound && (Object)(object)camera != (Object)null)
			{
				camera.position = originalPosition;
				camera.rotation = originalRotation;
			}
			bound = false;
			owner = null;
			camera = null;
			attachment.Reset();
		}

		public void Dispose()
		{
			Restore();
		}
	}
	internal static class PresentationTiming
	{
		internal static float BlurWeight(float age)
		{
			if (float.IsNaN(age) || age <= 10f)
			{
				return 0f;
			}
			if (age >= 15f)
			{
				return 1f;
			}
			if (age <= 14f)
			{
				return (age - 10f) / 4.5f;
			}
			float num = 15f - age;
			return 1f - num * num / 9f;
		}
	}
	internal sealed class CameraMotionState
	{
		private double x;

		private double y;

		private double vx;

		private double vy;

		private double targetX;

		private double targetY;

		internal float X => (float)x;

		internal float Y => (float)y;

		internal void Reset()
		{
			x = (y = (vx = (vy = 0.0)));
			targetX = (targetY = 0.0);
		}

		internal void SetTarget(float screenX, float screenY)
		{
			if (!float.IsNaN(screenX) && !float.IsInfinity(screenX) && !float.IsNaN(screenY) && !float.IsInfinity(screenY))
			{
				double num = screenX;
				if (num < -1.0)
				{
					num = -1.0;
				}
				else if (num > 1.0)
				{
					num = 1.0;
				}
				double num2 = screenY;
				if (num2 < -1.0)
				{
					num2 = -1.0;
				}
				else if (num2 > 1.0)
				{
					num2 = 1.0;
				}
				targetX = 0.0 - num;
				targetY = num2;
			}
		}

		internal void Step(float dt)
		{
			if (!(dt <= 0f) && !float.IsNaN(dt) && !float.IsInfinity(dt))
			{
				double num = x - targetX;
				double num2 = (vx + 12.0 * num) * (double)dt;
				double num3 = Math.Exp(-12.0 * (double)dt);
				x = targetX + (num + num2) * num3;
				vx = (vx - 12.0 * num2) * num3;
				double num4 = y - targetY;
				double num5 = (vy + 12.0 * num4) * (double)dt;
				double num6 = Math.Exp(-12.0 * (double)dt);
				y = targetY + (num4 + num5) * num6;
				vy = (vy - 12.0 * num5) * num6;
				if (Math.Abs(num) < 1E-06 && Math.Abs(vx) < 1E-06)
				{
					x = targetX;
					vx = 0.0;
				}
				if (Math.Abs(num4) < 1E-06 && Math.Abs(vy) < 1E-06)
				{
					y = targetY;
					vy = 0.0;
				}
			}
		}
	}
	internal static class Patches
	{
		[HarmonyPatch(typeof(GraffitiGame), "SetState")]
		private static class StatePatch
		{
			private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions)
			{
				MethodInfo find = AccessTools.Method(typeof(GraffitiArtInfo), "FindBySequence", (Type[])null, (Type[])null);
				MethodInfo resolve = AccessTools.Method(typeof(Patches), "ResolveArt", (Type[])null, (Type[])null);
				bool replaced = false;
				foreach (CodeInstruction instruction in instructions)
				{
					if (CodeInstructionExtensions.Calls(instruction, find))
					{
						instruction.opcode = OpCodes.Call;
						instruction.operand = resolve;
						replaced = true;
					}
					yield return instruction;
				}
				if (!replaced)
				{
					throw new InvalidOperationException("Native graffiti pattern lookup was not found.");
				}
			}

			private static void Postfix(GraffitiGame __instance, GraffitiGameState setState)
			{
				//IL_0000: Unknown result type (might be due to invalid IL or missing references)
				//IL_0002: Invalid comparison between Unknown and I4
				//IL_0026: Unknown result type (might be due to invalid IL or missing references)
				//IL_0028: Invalid comparison between Unknown and I4
				if ((int)setState == 2 && Plugin.IsSelectionResolved(__instance))
				{
					Plugin.RememberPainted(Traverse.Create((object)__instance).Field("grafArt").GetValue<GraffitiArt>());
				}
				if ((int)setState == 3)
				{
					Plugin.FinishSelection(__instance);
				}
			}
		}

		[HarmonyPatch(typeof(GraffitiGame), "SetStateVisual")]
		private static class VisualStatePatch
		{
			private static void Prefix(GraffitiGame __instance, GraffitiGameState __0)
			{
				//IL_0000: Unknown result type (might be due to invalid IL or missing references)
				if ((int)__0 != 0)
				{
					NativeSprayPose.ResetFor(__instance);
				}
			}
		}

		[HarmonyPatch(typeof(GraffitiGame), "Update")]
		private static class UpdatePatch
		{
			private static bool Prefix(GraffitiGame __instance)
			{
				//IL_002b: Unknown result type (might be due to invalid IL or missing references)
				//IL_0046: Unknown result type (might be due to invalid IL or missing references)
				//IL_0068: 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)
				Traverse val = Traverse.Create((object)__instance);
				if (val.Field("baseModule").GetValue<BaseModule>().IsInGamePaused)
				{
					return true;
				}
				if ((int)val.Field("state").GetValue<GraffitiGameState>() != 0)
				{
					return true;
				}
				GraffitiSpot value = val.Field("gSpot").GetValue<GraffitiSpot>();
				if ((int)value.size == 0)
				{
					return true;
				}
				if (!Plugin.HasSelectionFor(__instance))
				{
					List<GraffitiArt> available = AvailableArt(val.Field("unlockedGraffiti").GetValue<List<GraffitiArt>>(), value.size);
					Plugin.BeginSelection(__instance, available, value.size);
				}
				if (!Plugin.IsSelectionResolved(__instance))
				{
					return false;
				}
				Plugin.RestorePickerMaps();
				if (Plugin.SelectionWasAborted(__instance))
				{
					value.SetState((GraffitiState)3);
					__instance.End();
					return false;
				}
				if (Plugin.TakeSelection(__instance) == null)
				{
					return true;
				}
				List<int> value2 = val.Field("targetsHitSequence").GetValue<List<int>>();
				if (value2.Count == 0)
				{
					value2.Add(0);
				}
				AccessTools.Method(typeof(GraffitiGame), "SetState", (Type[])null, (Type[])null).Invoke(__instance, new object[1] { (object)(GraffitiGameState)1 });
				return false;
			}
		}

		[HarmonyPatch(typeof(GraffitiGame), "End")]
		private static class EndPatch
		{
			private static void Prefix(GraffitiGame __instance)
			{
				NativeSprayPose.ResetFor(__instance);
				Plugin.RestorePickerMaps();
			}

			private static void Postfix(GraffitiGame __instance)
			{
				Plugin.FinishSelection(__instance);
			}
		}

		internal static List<GraffitiArt> AvailableArt(List<GraffitiArt> unlocked, GraffitiSize size)
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			if (unlocked != null)
			{
				return unlocked.FindAll((GraffitiArt art) => art != null && art.graffitiSize == size);
			}
			return new List<GraffitiArt>();
		}

		internal static GraffitiArt ResolveArt(GraffitiArtInfo info, List<int> sequence)
		{
			return Plugin.TakeActiveSelection() ?? info.FindBySequence(sequence);
		}
	}
	internal static class NativeSprayPose
	{
		private static GraffitiGame owner;

		private static Animator animator;

		private static AnimatorStateInfo previousState;

		private static float previousSpeed;

		private static bool disabled;

		internal const int OriginalPose = 8;

		internal static bool IsOriginalPose(int choice)
		{
			return choice == 8;
		}

		internal static string AnimationName(int side)
		{
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			if (side < 0 || side >= 8)
			{
				throw new ArgumentOutOfRangeException("side");
			}
			return "grafSlash" + ((object)(Side)side/*cast due to .constrained prefix*/).ToString();
		}

		internal static void Begin(GraffitiGame game, CharacterVisual puppet)
		{
			//IL_0088: Unknown result type (might be due to invalid IL or missing references)
			//IL_008d: Unknown result type (might be due to invalid IL or missing references)
			if (disabled || (Object)(object)game == (Object)null || (Object)(object)puppet == (Object)null || (Object)(object)puppet.anim == (Object)null || owner == game)
			{
				return;
			}
			Reset();
			try
			{
				Animator anim = puppet.anim;
				int num = Random.Range(0, 9);
				if (IsOriginalPose(num))
				{
					owner = game;
					SelectorPaintCloud.Begin(game, puppet, num);
					return;
				}
				int num2 = Animator.StringToHash(AnimationName(num));
				if (!anim.HasState(0, num2))
				{
					owner = game;
					SelectorPaintCloud.Begin(game, puppet, 8);
					return;
				}
				previousState = anim.GetCurrentAnimatorStateInfo(0);
				previousSpeed = anim.speed;
				owner = game;
				animator = anim;
				anim.Play(num2, 0, 0.45f);
				anim.Update(0f);
				anim.speed = 0f;
				SelectorPaintCloud.Begin(game, puppet, num);
			}
			catch (Exception ex)
			{
				disabled = true;
				Reset();
				Debug.LogWarning((object)("Selector pose disabled; native pose retained: " + ex.Message));
			}
		}

		internal static void ResetFor(GraffitiGame game)
		{
			if (owner == game)
			{
				Reset();
			}
			else
			{
				SelectorPaintCloud.ResetFor(game);
			}
		}

		internal static void Reset()
		{
			SelectorPaintCloud.Reset();
			Animator val = animator;
			animator = null;
			owner = null;
			if ((Object)(object)val == (Object)null)
			{
				return;
			}
			try
			{
				val.speed = previousSpeed;
				if (((AnimatorStateInfo)(ref previousState)).fullPathHash != 0)
				{
					val.Play(((AnimatorStateInfo)(ref previousState)).fullPathHash, 0, ((AnimatorStateInfo)(ref previousState)).normalizedTime);
				}
			}
			catch (Exception ex)
			{
				Debug.LogWarning((object)("Selector pose restore failed: " + ex.Message));
			}
		}
	}
	internal static class SelectorPaintCloud
	{
		private static readonly FieldInfo playerField = AccessTools.Field(typeof(GraffitiGame), "player");

		private static readonly FieldInfo spotField = AccessTools.Field(typeof(GraffitiGame), "gSpot");

		private static readonly FieldInfo fastCamDurationField = AccessTools.Field(typeof(GraffitiGame), "fastCamDuration");

		private static readonly FieldInfo hitlagCamDurationField = AccessTools.Field(typeof(GraffitiGame), "hitlagCamDuration");

		private static readonly FieldInfo baseModuleField = AccessTools.Field(typeof(GraffitiGame), "baseModule");

		private static GraffitiGame owner;

		private static GameObject cloud;

		private static GraffitiEffect effect;

		private static BaseModule baseModule;

		private static float speed;

		private static int phase;

		private const int Fast = 1;

		private const int Hitlag = 2;

		private const int Slow = 3;

		private static float timer;

		private static float fastCamDuration;

		private static float hitlagCamDuration;

		private static bool disabled;

		private static ParticleSystem bodyCloud;

		private static ParticleSystem bodyStrokes;

		private static bool bodyReleased;

		private static SelectorForegroundDots foregroundDots;

		private static ParticleSystem dotSystem;

		private const float DotWarmupSeconds = 2f;

		private const float DotPlaybackSpeed = 0.08f;

		private const float DotSettleSeconds = 1.5f;

		private static float dotElapsed;

		internal static Vector2 LocalDirection(int side)
		{
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_0045: Unknown result type (might be due to invalid IL or missing references)
			//IL_0055: Unknown result type (might be due to invalid IL or missing references)
			//IL_0065: Unknown result type (might be due to invalid IL or missing references)
			//IL_0075: 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_0095: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b5: Unknown result type (might be due to invalid IL or missing references)
			return (Vector2)(side switch
			{
				0 => new Vector2(0f, 1f), 
				1 => new Vector2(2f, 1f), 
				2 => new Vector2(1f, 0f), 
				3 => new Vector2(2f, -1f), 
				4 => new Vector2(0f, -1f), 
				5 => new Vector2(-2f, -1f), 
				6 => new Vector2(-1f, 0f), 
				7 => new Vector2(-2f, 1f), 
				_ => new Vector2(0f, 1f), 
			});
		}

		internal static void Begin(GraffitiGame game, CharacterVisual puppet, int side)
		{
			//IL_007e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0084: Expected O, but got Unknown
			//IL_008f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0095: Expected O, but got Unknown
			//IL_00ca: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d4: Expected O, but got Unknown
			//IL_0130: Unknown result type (might be due to invalid IL or missing references)
			//IL_0135: Unknown result type (might be due to invalid IL or missing references)
			//IL_0138: Unknown result type (might be due to invalid IL or missing references)
			//IL_013d: 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_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_0156: 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_0160: Unknown result type (might be due to invalid IL or missing references)
			//IL_0164: Unknown result type (might be due to invalid IL or missing references)
			//IL_0169: Unknown result type (might be due to invalid IL or missing references)
			//IL_0177: Unknown result type (might be due to invalid IL or missing references)
			//IL_017d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0182: Unknown result type (might be due to invalid IL or missing references)
			//IL_0188: Unknown result type (might be due to invalid IL or missing references)
			//IL_018d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0193: 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_019d: Unknown result type (might be due to invalid IL or missing references)
			//IL_019f: Unknown result type (might be due to invalid IL or missing references)
			if (disabled || (Object)(object)game == (Object)null || (Object)(object)puppet == (Object)null || owner == game)
			{
				return;
			}
			Reset();
			try
			{
				if (playerField == null || spotField == null || fastCamDurationField == null || hitlagCamDurationField == null || baseModuleField == null)
				{
					throw new InvalidOperationException("Native graffiti effect fields unavailable.");
				}
				Player val = (Player)playerField.GetValue(game);
				GraffitiSpot val2 = (GraffitiSpot)spotField.GetValue(game);
				fastCamDuration = (float)fastCamDurationField.GetValue(game);
				hitlagCamDuration = (float)hitlagCamDurationField.GetValue(game);
				baseModule = (BaseModule)baseModuleField.GetValue(game);
				if (!((Object)(object)val == (Object)null) && val.VFXPrefabs != null && !((Object)(object)val.VFXPrefabs.graffitiSlash == (Object)null))
				{
					if ((Object)(object)baseModule == (Object)null)
					{
						throw new InvalidOperationException("Native graffiti pause state unavailable.");
					}
					Transform transform = ((Component)puppet).transform;
					Transform val3 = (((Object)(object)val2 == (Object)null) ? transform : ((Component)val2).transform);
					Vector2 val4 = LocalDirection(side);
					Vector3 val5 = val3.up * val4.y - val3.right * val4.x;
					Vector3 normalized = ((Vector3)(ref val5)).normalized;
					cloud = Object.Instantiate<GameObject>(val.VFXPrefabs.graffitiSlash, transform.position + transform.forward + transform.up, Quaternion.LookRotation(-transform.forward, normalized));
					owner = game;
					((Object)cloud).name = "QuickPickSelectorPaintCloud";
					cloud.transform.SetParent(transform, true);
					effect = cloud.GetComponent<GraffitiEffect>();
					if ((Object)(object)effect == (Object)null)
					{
						throw new InvalidOperationException("Native graffiti effect controller unavailable.");
					}
					bodyCloud = (((Object)(object)effect.splat != (Object)null && (Object)(object)effect.splat != (Object)(object)effect.splashes) ? effect.splat : null);
					bodyStrokes = (((Object)(object)effect.strokes != (Object)null && (Object)(object)effect.strokes != (Object)(object)effect.splashes) ? effect.strokes : null);
					speed = 100f;
					phase = 1;
					timer = 0f;
					effect.SetSpeed(speed);
					InitializeDots();
					foregroundDots = new SelectorForegroundDots(game, effect.splashes);
				}
			}
			catch (Exception ex)
			{
				disabled = true;
				Reset();
				Debug.LogWarning((object)("Selector paint cloud disabled: " + ex.Message));
			}
		}

		internal static void ResetFor(GraffitiGame game)
		{
			if (owner == game)
			{
				Reset();
			}
		}

		internal static void Reset()
		{
			if (foregroundDots != null)
			{
				foregroundDots.Dispose();
			}
			foregroundDots = null;
			if ((Object)(object)cloud != (Object)null)
			{
				Object.Destroy((Object)(object)cloud);
			}
			cloud = null;
			effect = null;
			baseModule = null;
			owner = null;
			speed = 0f;
			phase = 0;
			timer = 0f;
			fastCamDuration = 0f;
			hitlagCamDuration = 0f;
			bodyCloud = null;
			bodyStrokes = null;
			bodyReleased = false;
			dotSystem = null;
			dotElapsed = 0f;
		}

		internal static void DrawForegroundDots()
		{
			if (foregroundDots != null)
			{
				foregroundDots.Draw();
			}
		}

		internal static void Tick(float deltaTime)
		{
			if ((Object)(object)cloud == (Object)null || (Object)(object)effect == (Object)null || (Object)(object)baseModule == (Object)null || deltaTime <= 0f || float.IsNaN(deltaTime) || float.IsInfinity(deltaTime))
			{
				return;
			}
			try
			{
				if (baseModule.IsInGamePaused)
				{
					effect.SetSpeed(0f);
					effect.SetStun(0f);
					UpdateDotSpeed(paused: true);
					return;
				}
				dotElapsed += deltaTime;
				dotElapsed = Mathf.Min(dotElapsed, 1.5f);
				speed = NextSpeed(speed, deltaTime);
				effect.SetSpeed(speed);
				effect.SetStun((phase == 2) ? 0f : 1f);
				UpdateDotSpeed(paused: false);
				phase = NextPhase(phase, ref timer, deltaTime, fastCamDuration, hitlagCamDuration);
				UpdateBodySystems();
			}
			catch (Exception ex)
			{
				disabled = true;
				Reset();
				Debug.LogWarning((object)("Selector paint cloud disabled: " + ex.Message));
			}
		}

		private static void UpdateBodySystems()
		{
			//IL_0061: 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_008f: 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)
			if (phase == 3 && !bodyReleased)
			{
				if ((Object)(object)bodyCloud != (Object)null)
				{
					bodyCloud.Stop(false, (ParticleSystemStopBehavior)1);
				}
				if ((Object)(object)bodyStrokes != (Object)null)
				{
					bodyStrokes.Stop(false, (ParticleSystemStopBehavior)1);
				}
				bodyReleased = true;
			}
			if (phase == 3)
			{
				if ((Object)(object)bodyCloud != (Object)null)
				{
					MainModule main = bodyCloud.main;
					((MainModule)(ref main)).simulationSpeed = Mathf.Max(speed, 0.5f);
				}
				if ((Object)(object)bodyStrokes != (Object)null)
				{
					MainModule main2 = bodyStrokes.main;
					((MainModule)(ref main2)).simulationSpeed = Mathf.Max(speed, 0.5f);
				}
			}
		}

		private static void InitializeDots()
		{
			//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_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			dotSystem = effect.splashes;
			if (!((Object)(object)dotSystem == (Object)null))
			{
				MainModule main = dotSystem.main;
				((MainModule)(ref main)).simulationSpeed = 1f;
				EmissionModule emission = dotSystem.emission;
				((EmissionModule)(ref emission)).rateOverTimeMultiplier = ((EmissionModule)(ref emission)).rateOverTimeMultiplier * 0.75f;
				dotSystem.Simulate(2f, false, true, false);
				((EmissionModule)(ref emission)).enabled = false;
				UpdateDotSpeed(baseModule.IsInGamePaused);
				dotSystem.Play(false);
			}
		}

		private static void UpdateDotSpeed(bool paused)
		{
			//IL_0013: 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)
			if (!((Object)(object)dotSystem == (Object)null))
			{
				MainModule main = dotSystem.main;
				((MainModule)(ref main)).simulationSpeed = GetDotSpeed(dotElapsed, paused);
			}
		}

		internal static float GetDotSpeed(float elapsed, bool paused)
		{
			if (!paused)
			{
				return Mathf.Lerp(0.08f, 0f, elapsed / 1.5f);
			}
			return 0f;
		}

		internal static float NextSpeed(float speed, float dt)
		{
			return Mathf.Lerp(speed, 0f, dt * ((speed >= 0.5f) ? 10f : 1f));
		}

		internal static int NextPhase(int phase, ref float timer, float dt, float fastDuration, float hitlagDuration)
		{
			timer += dt;
			if (phase == 1 && timer > fastDuration)
			{
				timer = 0f;
				return 2;
			}
			if (phase == 2 && timer > hitlagDuration)
			{
				timer = 0f;
				return 3;
			}
			return phase;
		}
	}
	internal sealed class SelectorForegroundDots : IDisposable
	{
		private static readonly FieldInfo cameraField = AccessTools.Field(typeof(GraffitiGame), "graffitiCameraTf");

		private readonly ParticleSystem source;

		private readonly ParticleSystemRenderer renderer;

		private readonly Camera view;

		private readonly Texture texture;

		private readonly Color tint = Color.white;

		private readonly Particle[] particles;

		private readonly bool rendererWasEnabled;

		private bool hidden;

		private bool disabled;

		internal SelectorForegroundDots(GraffitiGame game, ParticleSystem dots)
		{
			//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_00ed: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f2: 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)
			try
			{
				source = dots;
				if ((Object)(object)source == (Object)null || cameraField == null)
				{
					return;
				}
				object? value = cameraField.GetValue(game);
				Transform val = (Transform)((value is Transform) ? value : null);
				if ((Object)(object)val == (Object)null)
				{
					return;
				}
				view = ((Component)val).GetComponent<Camera>();
				renderer = ((Component)source).GetComponent<ParticleSystemRenderer>();
				if ((Object)(object)view == (Object)null || (Object)(object)renderer == (Object)null)
				{
					return;
				}
				Material sharedMaterial = ((Renderer)renderer).sharedMaterial;
				if (!((Object)(object)sharedMaterial == (Object)null) && !((Object)(object)sharedMaterial.mainTexture == (Object)null))
				{
					texture = sharedMaterial.mainTexture;
					if (sharedMaterial.HasProperty("_Color"))
					{
						tint = sharedMaterial.GetColor("_Color");
					}
					MainModule main = source.main;
					if (((MainModule)(ref main)).maxParticles > 0 && ((MainModule)(ref main)).maxParticles <= 2048)
					{
						particles = (Particle[])(object)new Particle[((MainModule)(ref main)).maxParticles];
						rendererWasEnabled = ((Renderer)renderer).enabled;
					}
				}
			}
			catch (Exception ex)
			{
				disabled = true;
				Debug.LogWarning((object)("Selector foreground dots unavailable: " + ex.Message));
			}
		}

		internal void Draw()
		{
			//IL_0345: 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_0083: 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_008b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0091: Invalid comparison between Unknown and I4
			//IL_00aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b0: Invalid comparison between Unknown and I4
			//IL_00ce: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e0: 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_00fb: Unknown result type (might be due to invalid IL or missing references)
			//IL_0101: Invalid comparison between Unknown and I4
			//IL_0103: Unknown result type (might be due to invalid IL or missing references)
			//IL_010f: 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_0139: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b2: 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_019e: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b7: Unknown result type (might be due to invalid IL or missing references)
			//IL_01bf: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c8: Unknown result type (might be due to invalid IL or missing references)
			//IL_0205: Unknown result type (might be due to invalid IL or missing references)
			//IL_0207: Unknown result type (might be due to invalid IL or missing references)
			//IL_0211: Unknown result type (might be due to invalid IL or missing references)
			//IL_0216: Unknown result type (might be due to invalid IL or missing references)
			//IL_021b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0225: Unknown result type (might be due to invalid IL or missing references)
			//IL_0258: 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_0281: Unknown result type (might be due to invalid IL or missing references)
			//IL_0292: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a5: Unknown result type (might be due to invalid IL or missing references)
			//IL_02bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_02c2: Unknown result type (might be due to invalid IL or missing references)
			//IL_02c7: Unknown result type (might be due to invalid IL or missing references)
			//IL_02d1: Unknown result type (might be due to invalid IL or missing references)
			//IL_02e1: Unknown result type (might be due to invalid IL or missing references)
			//IL_02fc: Unknown result type (might be due to invalid IL or missing references)
			if (disabled || (Object)(object)source == (Object)null || (Object)(object)renderer == (Object)null || (Object)(object)view == (Object)null || (Object)(object)texture == (Object)null || particles == null || !rendererWasEnabled)
			{
				return;
			}
			if (!((Behaviour)view).isActiveAndEnabled)
			{
				RestoreRenderer();
				return;
			}
			Color color = GUI.color;
			try
			{
				int num = source.GetParticles(particles);
				MainModule main = source.main;
				Transform val = (((int)((MainModule)(ref main)).simulationSpace == 2) ? ((MainModule)(ref main)).customSimulationSpace : ((Component)source).transform);
				bool flag = (int)((MainModule)(ref main)).simulationSpace == 1;
				if (!flag && (Object)(object)val == (Object)null)
				{
					RestoreRenderer();
					return;
				}
				Vector3 val2 = (((int)((MainModule)(ref main)).scalingMode == 0) ? ((Component)source).transform.lossyScale : ((Component)source).transform.localScale);
				float num2 = (((int)((MainModule)(ref main)).scalingMode == 2) ? 1f : Mathf.Max(Mathf.Abs(val2.x), Mathf.Abs(val2.y)));
				Vector3 up = ((Component)view).transform.up;
				float nearClipPlane = view.nearClipPlane;
				if (!hidden)
				{
					((Renderer)renderer).enabled = false;
					hidden = true;
				}
				for (int i = 0; i < num; i++)
				{
					if (((Particle)(ref particles[i])).remainingLifetime <= 0f)
					{
						continue;
					}
					Vector3 val3 = (flag ? ((Particle)(ref particles[i])).position : val.TransformPoint(((Particle)(ref particles[i])).position));
					Vector3 val4 = view.WorldToScreenPoint(val3);
					if (val4.z <= nearClipPlane)
					{
						continue;
					}
					float num3 = ((Particle)(ref particles[i])).GetCurrentSize(source) * num2;
					if (!(num3 <= 0f))
					{
						float num4 = Mathf.Abs(view.WorldToScreenPoint(val3 + up * (num3 * 0.5f)).y - val4.y);
						if (!float.IsNaN(num4) && !float.IsInfinity(num4) && !(num4 <= 0f) && !(val4.x + num4 < 0f) && !(val4.x - num4 > (float)Screen.width) && !(val4.y + num4 < 0f) && !(val4.y - num4 > (float)Screen.height))
						{
							GUI.color = tint * Color32.op_Implicit(((Particle)(ref particles[i])).GetCurrentColor(source));
							GUI.DrawTexture(new Rect(val4.x - num4, (float)Screen.height - val4.y - num4, num4 * 2f, num4 * 2f), texture, (ScaleMode)0, true);
						}
					}
				}
			}
			catch (Exception ex)
			{
				disabled = true;
				RestoreRenderer();
				Debug.LogWarning((object)("Selector foreground dots reverted to native rendering: " + ex.Message));
			}
			finally
			{
				GUI.color = color;
			}
		}

		private void RestoreRenderer()
		{
			if (hidden && (Object)(object)renderer != (Object)null)
			{
				((Renderer)renderer).enabled = rendererWasEnabled;
			}
			hidden = false;
		}

		public void Dispose()
		{
			RestoreRenderer();
			disabled = true;
		}
	}
	internal sealed class SelectionAudio : IDisposable
	{
		internal const int MaxVoices = 3;

		private static readonly MethodInfo randomClipMethod = AccessTools.Method(typeof(AudioManager), "GetRandomAudioClipFromID", new Type[2]
		{
			typeof(SfxCollectionID),
			typeof(AudioClipID)
		}, (Type[])null);

		private static readonly FieldInfo mixerGroupsField = AccessTools.Field(typeof(AudioManager), "mixerGroups");

		private readonly Transform parent;

		private readonly Action<string> log;

		private readonly float[] startedAt = new float[3];

		private GameObject audioRoot;

		private AudioSource[] voices;

		private AudioManager boundManager;

		private Func<SfxCollectionID, AudioClipID, AudioClip> randomClip;

		private AudioMixerGroup uiGroup;

		private bool disabled;

		internal SelectionAudio(Transform parent, Action<string> logger)
		{
			this.parent = parent;
			log = logger;
		}

		internal void Play(AudioManager manager)
		{
			if (disabled || manager == null)
			{
				return;
			}
			try
			{
				if (boundManager != manager)
				{
					StopVoices();
					if (randomClipMethod == null || mixerGroupsField == null)
					{
						throw new InvalidOperationException("Native UI sound routing unavailable.");
					}
					if (!(mixerGroupsField.GetValue(manager) is AudioMixerGroup[] array) || array.Length <= 2 || (Object)(object)array[2] == (Object)null)
					{
						throw new InvalidOperationException("Native UI sound mixer unavailable.");
					}
					Func<SfxCollectionID, AudioClipID, AudioClip> func = (Func<SfxCollectionID, AudioClipID, AudioClip>)Delegate.CreateDelegate(typeof(Func<SfxCollectionID, AudioClipID, AudioClip>), manager, randomClipMethod);
					randomClip = func;
					uiGroup = array[2];
					boundManager = manager;
				}
				AudioClip val = randomClip((SfxCollectionID)13, (AudioClipID)303);
				if (!((Object)(object)val == (Object)null))
				{
					if ((Object)(object)audioRoot == (Object)null)
					{
						CreateVoices();
					}
					int num = FindVoice();
					AudioSource obj = voices[num];
					obj.Stop();
					obj.clip = val;
					obj.outputAudioMixerGroup = uiGroup;
					obj.pitch = 1f;
					obj.Play();
					startedAt[num] = Time.unscaledTime;
				}
			}
			catch (Exception ex)
			{
				disabled = true;
				StopVoices();
				if (log != null)
				{
					log("Selector sounds disabled: " + ex.Message);
				}
			}
		}

		private void CreateVoices()
		{
			//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_0018: Expected O, but got Unknown
			audioRoot = new GameObject("QuickPickSelectionAudio")
			{
				hideFlags = (HideFlags)61
			};
			audioRoot.transform.SetParent(parent, false);
			voices = (AudioSource[])(object)new AudioSource[3];
			for (int i = 0; i < 3; i++)
			{
				AudioSource val = audioRoot.AddComponent<AudioSource>();
				voices[i] = val;
				val.playOnAwake = false;
				val.loop = false;
				val.spatialBlend = 0f;
				val.pitch = 1f;
				val.volume = 1f;
				val.ignoreListenerPause = true;
			}
		}

		private int FindVoice()
		{
			int num = 0;
			for (int i = 0; i < 3; i++)
			{
				if (!voices[i].isPlaying)
				{
					return i;
				}
				if (startedAt[i] < startedAt[num])
				{
					num = i;
				}
			}
			return num;
		}

		private void StopVoices()
		{
			if (voices == null)
			{
				return;
			}
			for (int i = 0; i < voices.Length; i++)
			{
				if ((Object)(object)voices[i] != (Object)null)
				{
					voices[i].Stop();
				}
			}
		}

		public void Dispose()
		{
			disabled = true;
			StopVoices();
			if ((Object)(object)audioRoot != (Object)null)
			{
				Object.Destroy((Object)(object)audioRoot);
			}
			audioRoot = null;
			voices = null;
			boundManager = null;
			randomClip = null;
			uiGroup = null;
		}
	}
	internal sealed class WheelSelection
	{
		internal const int PageSize = 12;

		private bool stickActive;

		private bool stickSuppressed;

		private float suppressionAngle;

		internal int Count { get; private set; }

		internal int SelectedIndex { get; private set; }

		internal int PageStart => SelectedIndex / 12 * 12;

		internal int VisibleCount => Math.Min(12, Count - PageStart);

		internal float PointerAngle { get; private set; }

		internal WheelSelection(int count)
		{
			if (count <= 0)
			{
				throw new ArgumentOutOfRangeException("count");
			}
			Count = count;
		}

		internal void Step(int direction)
		{
			SelectedIndex = (SelectedIndex + direction + Count) % Count;
			SnapPointer();
		}

		internal void SelectIndex(int index)
		{
			if (index < 0 || index >= Count)
			{
				throw new ArgumentOutOfRangeException("index");
			}
			SelectedIndex = index;
			SnapPointer();
			stickActive = false;
			stickSuppressed = false;
		}

		internal void ChangePage(int direction)
		{
			int num = (Count + 12 - 1) / 12;
			int num2 = (SelectedIndex / 12 + direction + num) % num;
			SelectedIndex = Math.Min(num2 * 12 + SelectedIndex % 12, Count - 1);
			SnapPointer();
		}

		private void SnapPointer()
		{
			PointerAngle = (float)(SelectedIndex - PageStart) * 360f / (float)VisibleCount;
		}

		internal void UpdateStick(float x, float y, bool discreteInput)
		{
			float num = x * x + y * y;
			if (num < 0.0625f)
			{
				stickActive = false;
				stickSuppressed = false;
			}
			else
			{
				if (!stickActive && num < 0.16f)
				{
					return;
				}
				float num2 = (float)(Math.Atan2(x, y) * 180.0 / Math.PI);
				if (num2 < 0f)
				{
					num2 += 360f;
				}
				if (discreteInput)
				{
					stickActive = true;
					stickSuppressed = true;
					suppressionAngle = num2;
					return;
				}
				if (stickSuppressed)
				{
					if (Distance(num2, suppressionAngle) < 8f)
					{
						return;
					}
					stickSuppressed = false;
				}
				float num3 = 360f / (float)VisibleCount;
				float b = (float)(SelectedIndex - PageStart) * num3;
				if (!stickActive || Distance(num2, b) > num3 * 0.5f + 4f)
				{
					int num4 = (int)Math.Floor(num2 / num3 + 0.5f) % VisibleCount;
					SelectedIndex = PageStart + num4;
				}
				stickActive = true;
				PointerAngle = num2;
			}
		}

		private static float Distance(float a, float b)
		{
			float num = Math.Abs(a - b) % 360f;
			return Math.Min(num, 360f - num);
		}
	}
	internal sealed class WheelAimInput
	{
		private float leftAnchorX;

		private float leftAnchorY;

		private float rightAnchorX;

		private float rightAnchorY;

		private int owner;

		private bool suppressed;

		internal bool MouseActive => owner == 3;

		internal void Reset()
		{
			leftAnchorX = (leftAnchorY = (rightAnchorX = (rightAnchorY = 0f)));
			owner = 0;
			suppressed = false;
		}

		internal bool Update(float leftX, float leftY, float rightX, float rightY, float mouseX, float mouseY, bool mouseMoved, bool discreteInput, out float x, out float y)
		{
			x = (y = 0f);
			float num = leftX * leftX + leftY * leftY;
			float num2 = rightX * rightX + rightY * rightY;
			float num3 = Square(leftX - leftAnchorX) + Square(leftY - leftAnchorY);
			float num4 = Square(rightX - rightAnchorX) + Square(rightY - rightAnchorY);
			bool flag = num3 > 0.0025f && num >= 0.16f;
			bool flag2 = num4 > 0.0025f && num2 >= 0.16f;
			if (discreteInput)
			{
				leftAnchorX = leftX;
				leftAnchorY = leftY;
				rightAnchorX = rightX;
				rightAnchorY = rightY;
				suppressed = true;
				return false;
			}
			if (flag || num < 0.0625f)
			{
				leftAnchorX = leftX;
				leftAnchorY = leftY;
			}
			if (flag2 || num2 < 0.0625f)
			{
				rightAnchorX = rightX;
				rightAnchorY = rightY;
			}
			if (mouseMoved)
			{
				owner = 3;
				suppressed = false;
			}
			else if (flag || flag2)
			{
				owner = ((!flag2 || (flag && !(num4 > num3))) ? 1 : 2);
				suppressed = false;
			}
			if (suppressed)
			{
				return false;
			}
			if (owner == 1 && num < 0.0625f)
			{
				owner = ((num2 >= 0.16f) ? 2 : 0);
			}
			else if (owner == 2 && num2 < 0.0625f)
			{
				owner = ((num >= 0.16f) ? 1 : 0);
			}
			if (owner == 1)
			{
				x = leftX;
				y = leftY;
				return true;
			}
			if (owner == 2)
			{
				x = rightX;
				y = rightY;
				return true;
			}
			if (owner == 3 && mouseMoved && mouseX * mouseX + mouseY * mouseY >= 0.0625f)
			{
				x = mouseX;
				y = mouseY;
				return true;
			}
			return false;
		}

		private static float Square(float value)
		{
			return value * value;
		}
	}
	internal static class WheelStyle
	{
		internal static Texture2D CreatePointer()
		{
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: Expected O, but got Unknown
			using Stream stream = typeof(WheelStyle).Assembly.GetManifestResourceStream("QuickPickGraffiti.dance-pointer.png");
			using MemoryStream memoryStream = new MemoryStream();
			if (stream == null)
			{
				throw new InvalidOperationException("Dance selector pointer resource is missing.");
			}
			stream.CopyTo(memoryStream);
			Texture2D val = new Texture2D(2, 2, (TextureFormat)4, true);
			((Object)val).hideFlags = (HideFlags)61;
			((Texture)val).filterMode = (FilterMode)2;
			((Texture)val).wrapMode = (TextureWrapMode)1;
			if (!ImageConversion.LoadImage(val, memoryStream.ToArray(), true))
			{
				Object.Destroy((Object)(object)val);
				throw new InvalidOperationException("Dance selector pointer could not be loaded.");
			}
			return val;
		}

		internal static Texture2D CreateBacking(int size)
		{
			//IL_0004: Unknown result type (might be due to invalid IL or missing references)
			//IL_000a: Expected O, but got Unknown
			//IL_00a7: 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_011e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0120: Unknown result type (might be due to invalid IL or missing references)
			Texture2D val = new Texture2D(size, size, (TextureFormat)4, false);
			((Object)val).hideFlags = (HideFlags)61;
			Color[] array = (Color[])(object)new Color[size * size];
			float num = (float)(size - 1) * 0.5f;
			for (int i = 0; i < size; i++)
			{
				for (int j = 0; j < size; j++)
				{
					float num2 = ((float)j - num) / num;
					float num3 = ((float)i - num) / num;
					float num4 = Mathf.Sqrt(num2 * num2 + num3 * num3);
					float num5 = Mathf.Atan2(num2, num3);
					float num6 = 0.945f + 0.035f * Mathf.Cos(8f * num5) + 0.013f * Mathf.Sin(13f * num5);
					float num7 = 0.44f + 0.045f * Mathf.Cos(8f * num5);
					Color clear = Color.clear;
					if (num4 <= num6)
					{
						((Color)(ref clear))..ctor(0.075f, 0.085f, 0.062f, 0.686f);
						if (num4 < num7)
						{
							((Color)(ref clear))..ctor(0.025f, 0.03f, 0.023f, 0.532f);
						}
						if (num4 > num6 - 0.013f)
						{
							((Color)(ref clear))..ctor(0.025f, 0.029f, 0.02f, 1f);
						}
					}
					array[i * size + j] = clear;
				}
			}
			val.SetPixels(array);
			val.Apply(false, true);
			return val;
		}

		internal static Texture2D CreateSelectionGlow(int size)
		{
			//IL_0004: Unknown result type (might be due to invalid IL or missing references)
			//IL_000a: Expected O, but got Unknown
			//IL_008e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0093: Unknown result type (might be due to invalid IL or missing references)
			Texture2D val = new Texture2D(size, size, (TextureFormat)4, false);
			((Object)val).hideFlags = (HideFlags)61;
			Color[] array = (Color[])(object)new Color[size * size];
			float num = (float)(size - 1) * 0.5f;
			for (int i = 0; i < size; i++)
			{
				for (int j = 0; j < size; j++)
				{
					float num2 = ((float)j - num) / num;
					float num3 = ((float)i - num) / num;
					float num4 = Mathf.Sqrt(num2 * num2 + num3 * num3);
					if (Mathf.Abs(Mathf.Atan2(num2, num3)) < 0.24f && num4 > 0.5f && num4 < 0.82f)
					{
						array[i * size + j] = new Color(0.48f, 0.85f, 0.29f, 0.15f);
					}
				}
			}
			val.SetPixels(array);
			val.Apply(false, true);
			return val;
		}
	}
	internal sealed class PaintVisuals : IDisposable
	{
		private const int Sectors = 512;

		private const int Rows = 24;

		private readonly Mesh liquid;

		private readonly Mesh backing;

		private readonly Material liquidMaterial;

		private readonly Material backingMaterial;

		private readonly Texture2D stripe;

		private readonly Vector3[] positions = (Vector3[])(object)new Vector3[12312];

		private readonly Vector2[] uvs = (Vector2[])(object)new Vector2[12312];

		private readonly Color[] liquidColors = (Color[])(object)new Color[12312];

		private readonly WirkleMotion.FlowPoint[] flow = new WirkleMotion.FlowPoint[12312];

		private readonly float[] sx = new float[513];

		private readonly float[] sy = new float[513];

		private readonly float[] outer = new float[513];

		private readonly bool straightAlphaShader;

		private RenderTexture target;

		private float lastReveal = -1f;

		private int renderedFrame = -1;

		private float renderedAge = -1f;

		internal PaintVisuals()
		{
			//IL_00db: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e0: 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_00f9: Expected O, but got Unknown
			//IL_00fb: Unknown result type (might be due to invalid IL or missing references)
			//IL_0100: Unknown result type (might be due to invalid IL or missing references)
			//IL_0108: Unknown result type (might be due to invalid IL or missing references)
			//IL_0118: Expected O, but got Unknown
			//IL_0119: 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)
			//IL_0129: Unknown result type (might be due to invalid IL or missing references)
			//IL_0136: Expected O, but got Unknown
			//IL_0142: Unknown result type (might be due to invalid IL or missing references)
			//IL_0147: Unknown result type (might be due to invalid IL or missing references)
			//IL_0152: Unknown result type (might be due to invalid IL or missing references)
			//IL_015f: Expected O, but got Unknown
			//IL_0276: Unknown result type (might be due to invalid IL or missing references)
			//IL_028a: Unknown result type (might be due to invalid IL or missing references)
			//IL_028f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0209: Unknown result type (might be due to invalid IL or missing references)
			//IL_020e: Unknown result type (might be due to invalid IL or missing references)
			Shader val = Shader.Find("Sprites/Default");
			if ((Object)(object)val == (Object)null)
			{
				val = Shader.Find("UI/Default");
				straightAlphaShader = true;
			}
			if ((Object)(object)val == (Object)null)
			{
				throw new InvalidOperationException("No unlit texture shader is available for the wirkle.");
			}
			try
			{
				stripe = CreateStripe();
				liquidMaterial = new Material(val)
				{
					hideFlags = (HideFlags)61,
					mainTexture = (Texture)(object)stripe
				};
				backingMaterial = new Material(val)
				{
					hideFlags = (HideFlags)61,
					mainTexture = (Texture)(object)Texture2D.whiteTexture
				};
				liquid = new Mesh
				{
					name = "WirkleLiquid",
					hideFlags = (HideFlags)61
				};
				liquid.MarkDynamic();
				backing = new Mesh
				{
					name = "WirkleBacking",
					hideFlags = (HideFlags)61
				};
				for (int i = 0; i <= 512; i++)
				{
					float num = (float)i * (float)Math.PI * 2f / 512f;
					sx[i] = Mathf.Sin(num);
					sy[i]