Decompiled source of SagaLens v0.1.7

BepInEx/plugins/SagaLens/SagaLens.dll

Decompiled 5 days ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using BepInEx;
using BepInEx.Configuration;
using HarmonyLib;
using TMPro;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.InputSystem;
using UnityEngine.UI;

[assembly: AssemblyInformationalVersion("0.1.7")]
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: AssemblyDescription("Valheim Photo Mode. Coded with the assistance of ChatGPT 6.0.")]
[assembly: AssemblyFileVersion("0.1.7.0")]
[assembly: AssemblyTitle("Saga Lens")]
[assembly: AssemblyVersion("0.1.7.0")]
namespace ValheimPhotoMode;

internal static class CameraRules
{
	internal const float MinimumDistance = 0.12f;

	internal const float MaximumFov = 130f;

	internal static float WheelSteps(float raw)
	{
		if (float.IsNaN(raw) || float.IsInfinity(raw))
		{
			return 0f;
		}
		float val = ((Math.Abs(raw) >= 10f) ? (raw / 120f) : raw);
		return Math.Max(-8f, Math.Min(8f, val));
	}

	internal static float Dolly(float distance, float forward, float wheel, float maximum)
	{
		float num = Math.Max(0.025f, Math.Min(1.5f, distance * 0.15f));
		return Math.Max(0.12f, Math.Min(maximum, distance - forward - wheel * num));
	}
}
internal sealed class FrozenEffects
{
	private struct LightState
	{
		internal bool Enabled;

		internal float Intensity;

		internal float Range;

		internal Color Color;
	}

	private readonly List<ParticleSystem> particles = new List<ParticleSystem>();

	private readonly Dictionary<Light, LightState> lights = new Dictionary<Light, LightState>();

	private bool frozen;

	internal void Freeze(Vector3 centre, float radius)
	{
		//IL_0027: Unknown result type (might be due to invalid IL or missing references)
		//IL_002c: Unknown result type (might be due to invalid IL or missing references)
		//IL_002d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0032: Unknown result type (might be due to invalid IL or missing references)
		//IL_007c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0082: Invalid comparison between Unknown and I4
		//IL_008a: Unknown result type (might be due to invalid IL or missing references)
		//IL_008f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0090: Unknown result type (might be due to invalid IL or missing references)
		//IL_0095: Unknown result type (might be due to invalid IL or missing references)
		//IL_00dc: 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)
		if (frozen)
		{
			return;
		}
		frozen = true;
		ParticleSystem[] array = Object.FindObjectsByType<ParticleSystem>((FindObjectsSortMode)0);
		foreach (ParticleSystem val in array)
		{
			Vector3 val2 = ((Component)val).transform.position - centre;
			if (!(((Vector3)(ref val2)).sqrMagnitude > radius * radius) && val.isPlaying)
			{
				particles.Add(val);
				val.Pause(false);
			}
		}
		Light[] array2 = Object.FindObjectsByType<Light>((FindObjectsSortMode)0);
		foreach (Light val3 in array2)
		{
			if ((int)val3.type != 1)
			{
				Vector3 val4 = ((Component)val3).transform.position - centre;
				if (((Vector3)(ref val4)).sqrMagnitude <= radius * radius)
				{
					lights[val3] = new LightState
					{
						Enabled = ((Behaviour)val3).enabled,
						Intensity = val3.intensity,
						Range = val3.range,
						Color = val3.color
					};
				}
			}
		}
	}

	internal void Hold()
	{
		//IL_00af: Unknown result type (might be due to invalid IL or missing references)
		if (!frozen)
		{
			return;
		}
		foreach (ParticleSystem particle in particles)
		{
			if (Object.op_Implicit((Object)(object)particle) && particle.isPlaying)
			{
				particle.Pause(false);
			}
		}
		foreach (KeyValuePair<Light, LightState> light in lights)
		{
			if (Object.op_Implicit((Object)(object)light.Key))
			{
				Light key = light.Key;
				LightState value = light.Value;
				((Behaviour)key).enabled = value.Enabled;
				key.intensity = value.Intensity;
				key.range = value.Range;
				key.color = value.Color;
			}
		}
	}

	internal void Resume()
	{
		if (!frozen)
		{
			return;
		}
		foreach (ParticleSystem particle in particles)
		{
			if (Object.op_Implicit((Object)(object)particle) && particle.isPaused)
			{
				particle.Play(false);
			}
		}
		particles.Clear();
		lights.Clear();
		frozen = false;
	}
}
internal sealed class NativePhotoHints
{
	private sealed class Hint
	{
		internal RectTransform root;

		internal TMP_Text label;

		internal string binding;

		internal readonly List<RectTransform> tokens = new List<RectTransform>();

		internal float width;
	}

	private readonly Transform parent;

	private readonly TMP_Text keyStyle;

	private readonly TMP_Text labelStyle;

	private readonly Image keyBackground;

	private readonly List<Hint> hints = new List<Hint>();

	private readonly TMP_Text status;

	private int count;

	internal NativePhotoHints(Transform parent, TMP_Text nativeKey, TMP_Text nativeLabel, Image background)
	{
		this.parent = parent;
		keyStyle = nativeKey;
		labelStyle = nativeLabel;
		keyBackground = background;
		status = Text(parent, "Status", labelStyle);
		status.alignment = (TextAlignmentOptions)514;
	}

	internal static Image FindKeyBackground(TMP_Text key)
	{
		//IL_0047: Unknown result type (might be due to invalid IL or missing references)
		//IL_004d: Expected O, but got Unknown
		if (!Object.op_Implicit((Object)(object)key))
		{
			return null;
		}
		Transform transform = key.transform;
		int num = 0;
		while (Object.op_Implicit((Object)(object)transform) && num < 3)
		{
			Image component = ((Component)transform).GetComponent<Image>();
			if (Object.op_Implicit((Object)(object)component) && Object.op_Implicit((Object)(object)component.sprite))
			{
				return component;
			}
			foreach (Transform item in transform)
			{
				Transform val = item;
				component = ((Component)val).GetComponent<Image>();
				if (Object.op_Implicit((Object)(object)component) && Object.op_Implicit((Object)(object)component.sprite))
				{
					return component;
				}
			}
			num++;
			transform = transform.parent;
		}
		return null;
	}

	private static RectTransform Rect(Transform parent, string name)
	{
		//IL_0016: Unknown result type (might be due to invalid IL or missing references)
		//IL_002b: 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_0031: Unknown result type (might be due to invalid IL or missing references)
		//IL_0037: Unknown result type (might be due to invalid IL or missing references)
		//IL_003e: Unknown result type (might be due to invalid IL or missing references)
		RectTransform component = new GameObject(name, new Type[1] { typeof(RectTransform) }).GetComponent<RectTransform>();
		((Transform)component).SetParent(parent, false);
		Vector2 anchorMin = (component.anchorMax = Vector2.zero);
		component.anchorMin = anchorMin;
		component.pivot = Vector2.zero;
		return component;
	}

	private TMP_Text Text(Transform parent, string value, TMP_Text style)
	{
		//IL_005a: 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_0042: Unknown result type (might be due to invalid IL or missing references)
		RectTransform val = Rect(parent, value);
		TextMeshProUGUI val2 = ((Component)val).gameObject.AddComponent<TextMeshProUGUI>();
		if (Object.op_Implicit((Object)(object)style))
		{
			((TMP_Text)val2).font = style.font;
			((TMP_Text)val2).fontSharedMaterial = style.fontSharedMaterial;
			((TMP_Text)val2).fontStyle = style.fontStyle;
			((Graphic)val2).color = ((Graphic)style).color;
		}
		else
		{
			((TMP_Text)val2).font = TMP_Settings.defaultFontAsset;
			((Graphic)val2).color = Color.white;
		}
		((TMP_Text)val2).fontSize = 24f;
		((TMP_Text)val2).textWrappingMode = (TextWrappingModes)0;
		((TMP_Text)val2).richText = false;
		((TMP_Text)val2).alignment = (TextAlignmentOptions)4097;
		((Graphic)val2).raycastTarget = false;
		((TMP_Text)val2).text = value;
		return (TMP_Text)(object)val2;
	}

	internal void Begin()
	{
		count = 0;
	}

	internal void Add(string action, string binding)
	{
		//IL_02b1: Unknown result type (might be due to invalid IL or missing references)
		//IL_02cf: Unknown result type (might be due to invalid IL or missing references)
		//IL_0304: Unknown result type (might be due to invalid IL or missing references)
		//IL_0312: 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_01b5: Unknown result type (might be due to invalid IL or missing references)
		//IL_01c7: 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_0249: Unknown result type (might be due to invalid IL or missing references)
		//IL_025e: 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_0278: 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_027e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0285: Unknown result type (might be due to invalid IL or missing references)
		Hint hint;
		if (count == hints.Count)
		{
			hint = new Hint();
			hint.root = Rect(parent, "Photo hint");
			hint.label = Text((Transform)(object)hint.root, action, labelStyle);
			hints.Add(hint);
		}
		else
		{
			hint = hints[count];
		}
		count++;
		((Component)hint.root).gameObject.SetActive(true);
		hint.label.text = action;
		if (hint.binding != binding)
		{
			foreach (RectTransform token in hint.tokens)
			{
				Object.Destroy((Object)(object)((Component)token).gameObject);
			}
			hint.tokens.Clear();
			hint.binding = binding;
			string[] array = binding.Replace("+", "|+|").Replace("/", "|/|").Split(new char[1] { '|' });
			foreach (string text in array)
			{
				string text2 = text.Trim();
				if (text2.Length != 0)
				{
					bool flag = text2 == "+" || text2 == "/";
					RectTransform val = Rect((Transform)(object)hint.root, "Key " + text2);
					if (!flag && Object.op_Implicit((Object)(object)keyBackground))
					{
						Image val2 = ((Component)val).gameObject.AddComponent<Image>();
						val2.sprite = keyBackground.sprite;
						val2.type = keyBackground.type;
						((Graphic)val2).color = ((Graphic)keyBackground).color;
						((Graphic)val2).material = ((Graphic)keyBackground).material;
						val2.pixelsPerUnitMultiplier = keyBackground.pixelsPerUnitMultiplier;
						((Graphic)val2).raycastTarget = false;
					}
					TMP_Text val3 = Text((Transform)(object)val, text2, flag ? labelStyle : keyStyle);
					val3.alignment = (TextAlignmentOptions)4098;
					float num = val3.GetPreferredValues(text2).x + (float)(flag ? 4 : 18);
					val.sizeDelta = new Vector2(num, 34f);
					RectTransform rectTransform = val3.rectTransform;
					rectTransform.anchorMin = Vector2.zero;
					rectTransform.anchorMax = Vector2.one;
					Vector2 offsetMin = (rectTransform.offsetMax = Vector2.zero);
					rectTransform.offsetMin = offsetMin;
					hint.tokens.Add(val);
				}
			}
		}
		float x = hint.label.GetPreferredValues(action).x;
		hint.label.rectTransform.sizeDelta = new Vector2(x, 34f);
		x += 9f;
		foreach (RectTransform token2 in hint.tokens)
		{
			token2.anchoredPosition = new Vector2(x, 0f);
			x += token2.sizeDelta.x + 4f;
		}
		hint.width = x - 4f;
		hint.root.sizeDelta = new Vector2(hint.width, 34f);
	}

	internal void Finish(string message)
	{
		//IL_003d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0043: Expected O, but got Unknown
		//IL_0049: Unknown result type (might be due to invalid IL or missing references)
		//IL_004e: Unknown result type (might be due to invalid IL or missing references)
		//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_0210: Unknown result type (might be due to invalid IL or missing references)
		//IL_022b: Unknown result type (might be due to invalid IL or missing references)
		//IL_019f: Unknown result type (might be due to invalid IL or missing references)
		for (int i = count; i < hints.Count; i++)
		{
			((Component)hints[i].root).gameObject.SetActive(false);
		}
		RectTransform val = (RectTransform)parent;
		Rect rect = val.rect;
		float num = Mathf.Max(300f, ((Rect)(ref rect)).width - 48f);
		List<List<Hint>> list = new List<List<Hint>>();
		List<float> list2 = new List<float>();
		for (int j = 0; j < count; j++)
		{
			Hint hint = hints[j];
			if (list.Count == 0 || list2[list2.Count - 1] + 24f + hint.width > num)
			{
				list.Add(new List<Hint>());
				list2.Add(0f);
			}
			int index = list.Count - 1;
			if (list[index].Count > 0)
			{
				list2[index] += 24f;
			}
			list[index].Add(hint);
			list2[index] += hint.width;
		}
		for (int k = 0; k < list.Count; k++)
		{
			Rect rect2 = val.rect;
			float num2 = (((Rect)(ref rect2)).width - list2[k]) * 0.5f;
			foreach (Hint item in list[k])
			{
				item.root.anchoredPosition = new Vector2(num2, (float)(18 + (list.Count - 1 - k) * 44));
				num2 += item.width + 24f;
			}
		}
		status.text = message;
		status.rectTransform.anchoredPosition = new Vector2(24f, (float)(22 + list.Count * 44));
		status.rectTransform.sizeDelta = new Vector2(num, 32f);
	}
}
internal sealed class PhotoEnvironment
{
	private static readonly FieldInfo Fraction = AccessTools.Field(typeof(EnvMan), "m_smoothDayFraction");

	private static readonly MethodInfo Render = AccessTools.Method(typeof(EnvMan), "SetEnv", (Type[])null, (Type[])null);

	private static readonly FieldInfo CurrentParticles = AccessTools.Field(typeof(EnvMan), "m_currentPSystems");

	private readonly List<EnvSetup> weather = new List<EnvSetup>();

	private readonly Dictionary<ParticleSystem, bool> simulated = new Dictionary<ParticleSystem, bool>();

	private EnvMan owner;

	private int selection = -1;

	private float? time;

	private bool applied;

	private float wet;

	internal static bool Allowed
	{
		get
		{
			if (Object.op_Implicit((Object)(object)ZNet.instance))
			{
				return ZNet.IsSinglePlayer;
			}
			return false;
		}
	}

	internal string Weather
	{
		get
		{
			if (selection >= 0)
			{
				return weather[selection].m_name;
			}
			return "Natural";
		}
	}

	internal string Clock
	{
		get
		{
			if (!time.HasValue)
			{
				return "Natural";
			}
			int num = Mathf.FloorToInt(time.Value * 1440f);
			return (num / 60).ToString("00") + ":" + (num % 60).ToString("00");
		}
	}

	internal void Begin()
	{
		owner = EnvMan.instance;
		selection = -1;
		time = null;
		applied = false;
		weather.Clear();
		if (!Object.op_Implicit((Object)(object)owner) || !Allowed)
		{
			return;
		}
		string[] array = new string[8] { "Clear", "Heath clear", "Misty", "LightRain", "Rain", "ThunderStorm", "Snow", "SnowStorm" };
		foreach (string name in array)
		{
			List<EnvSetup> environments = owner.m_environments;
			Func<EnvSetup, bool> predicate = (EnvSetup e) => e.m_name == name;
			EnvSetup val = environments.FirstOrDefault(predicate);
			if (val != null)
			{
				weather.Add(val);
			}
		}
		wet = Shader.GetGlobalFloat("_Wet");
	}

	internal void ShiftTime(float amount)
	{
		if (Allowed && Object.op_Implicit((Object)(object)owner))
		{
			time = Mathf.Repeat((time.HasValue ? time.Value : owner.GetDayFraction()) + amount, 1f);
		}
	}

	internal void CycleWeather()
	{
		if (Allowed && Object.op_Implicit((Object)(object)owner))
		{
			RestoreParticles();
			selection++;
			if (selection >= weather.Count)
			{
				selection = -1;
			}
			if (selection < 0 && !time.HasValue)
			{
				Reset();
			}
		}
	}

	internal void Apply(bool frozen)
	{
		if (!Allowed)
		{
			Reset();
		}
		else
		{
			if (!Object.op_Implicit((Object)(object)owner) || (Object)(object)owner != (Object)(object)EnvMan.instance || (!time.HasValue && selection < 0))
			{
				return;
			}
			if (!frozen)
			{
				RestoreParticles();
			}
			applied = true;
			Paint((selection < 0) ? owner.GetCurrentEnvironment() : weather[selection], time.HasValue ? time.Value : owner.GetDayFraction());
			if (!frozen || selection < 0 || weather[selection].m_psystems == null)
			{
				return;
			}
			GameObject[] psystems = weather[selection].m_psystems;
			foreach (GameObject val in psystems)
			{
				if (!Object.op_Implicit((Object)(object)val) || !val.activeInHierarchy)
				{
					continue;
				}
				ParticleSystem[] componentsInChildren = val.GetComponentsInChildren<ParticleSystem>();
				foreach (ParticleSystem val2 in componentsInChildren)
				{
					if (!simulated.ContainsKey(val2))
					{
						simulated[val2] = val2.isPlaying;
					}
					val2.Simulate(Mathf.Min(Time.unscaledDeltaTime, 0.05f), false, false, false);
				}
			}
		}
	}

	private void RestoreParticles()
	{
		foreach (KeyValuePair<ParticleSystem, bool> item in simulated)
		{
			if (Object.op_Implicit((Object)(object)item.Key) && item.Value && item.Key.isPaused)
			{
				item.Key.Play(false);
			}
		}
		simulated.Clear();
	}

	private void Paint(EnvSetup env, float fraction)
	{
		if (env != null)
		{
			GameObject[] outgoing = (GameObject[])CurrentParticles.GetValue(owner);
			float num = Mathf.Sqrt(Mathf.Max(1f - Mathf.Clamp01(fraction / 0.25f), Mathf.Clamp01((fraction - 0.75f) / 0.25f)));
			float num2 = Mathf.Sqrt(1f - Mathf.Clamp01(Mathf.Abs(fraction - 0.5f) / 0.25f));
			float num3 = Mathf.Min(1f - Mathf.Clamp01((fraction - 0.26f) / (0f - owner.m_sunHorizonTransitionL)), 1f - Mathf.Clamp01((fraction - 0.26f) / owner.m_sunHorizonTransitionH));
			float num4 = Mathf.Min(1f - Mathf.Clamp01((fraction - 0.74f) / (0f - owner.m_sunHorizonTransitionH)), 1f - Mathf.Clamp01((fraction - 0.74f) / owner.m_sunHorizonTransitionL));
			float num5 = num2 + num + num3 + num4;
			float num6 = (float)Fraction.GetValue(owner);
			try
			{
				Fraction.SetValue(owner, fraction);
				Render.Invoke(owner, new object[6]
				{
					env,
					num2 / num5,
					num / num5,
					num3 / num5,
					num4 / num5,
					Time.unscaledDeltaTime
				});
			}
			finally
			{
				Fraction.SetValue(owner, num6);
			}
			ClearOutgoingWeather(outgoing, (GameObject[])CurrentParticles.GetValue(owner));
		}
	}

	private static void ClearOutgoingWeather(GameObject[] outgoing, GameObject[] incoming)
	{
		if (outgoing == null || object.ReferenceEquals(outgoing, incoming))
		{
			return;
		}
		HashSet<ParticleSystem> hashSet = new HashSet<ParticleSystem>();
		if (incoming != null)
		{
			foreach (GameObject val in incoming)
			{
				if (Object.op_Implicit((Object)(object)val))
				{
					ParticleSystem[] componentsInChildren = val.GetComponentsInChildren<ParticleSystem>(true);
					foreach (ParticleSystem item in componentsInChildren)
					{
						hashSet.Add(item);
					}
				}
			}
		}
		foreach (GameObject val2 in outgoing)
		{
			if (!Object.op_Implicit((Object)(object)val2))
			{
				continue;
			}
			ParticleSystem[] componentsInChildren2 = val2.GetComponentsInChildren<ParticleSystem>(true);
			foreach (ParticleSystem val3 in componentsInChildren2)
			{
				if (!hashSet.Contains(val3))
				{
					val3.Clear(false);
				}
			}
		}
	}

	internal void Reset()
	{
		RestoreParticles();
		time = null;
		selection = -1;
		if (!applied)
		{
			return;
		}
		applied = false;
		if (!Object.op_Implicit((Object)(object)owner) || !((Object)(object)owner == (Object)(object)EnvMan.instance))
		{
			return;
		}
		try
		{
			Paint(owner.GetCurrentEnvironment(), owner.GetDayFraction());
		}
		finally
		{
			Shader.SetGlobalFloat("_Wet", wet);
		}
	}
}
internal static class PhotoFiles
{
	internal static string DirectoryPath(string configured)
	{
		if (!string.IsNullOrWhiteSpace(configured))
		{
			return Path.GetFullPath(Environment.ExpandEnvironmentVariables(configured));
		}
		string folderPath = Environment.GetFolderPath(Environment.SpecialFolder.MyPictures);
		if (string.IsNullOrEmpty(folderPath))
		{
			folderPath = Environment.GetFolderPath(Environment.SpecialFolder.Personal);
		}
		if (string.IsNullOrEmpty(folderPath))
		{
			throw new IOException("No Pictures or Documents folder is available. Set OutputDirectory in the config.");
		}
		return Path.Combine(folderPath, "Valheim Photo Mode");
	}

	internal static string Save(string directory, byte[] png)
	{
		if (png == null || png.Length == 0)
		{
			throw new IOException("Screenshot encoding returned no image.");
		}
		Directory.CreateDirectory(directory);
		string text = Path.Combine(directory, "Valheim_" + DateTime.Now.ToString("yyyy-MM-dd_HH-mm-ss-fff") + "_" + Guid.NewGuid().ToString("N").Substring(0, 8) + ".png");
		string text2 = text + ".part";
		bool flag = false;
		try
		{
			using (FileStream fileStream = new FileStream(text2, FileMode.CreateNew, FileAccess.Write, FileShare.None))
			{
				flag = true;
				fileStream.Write(png, 0, png.Length);
			}
			File.Move(text2, text);
			return text;
		}
		finally
		{
			if (flag && File.Exists(text2))
			{
				File.Delete(text2);
			}
		}
	}
}
[BepInPlugin("au.tyvalheim.photomode", "Saga Lens - Photo Mode", "0.1.7")]
public sealed class Plugin : BaseUnityPlugin
{
	public const string Id = "au.tyvalheim.photomode";

	public const string Version = "0.1.7";

	internal static Plugin Instance;

	internal static bool ReadingInput;

	internal bool Active;

	internal bool Frozen;

	private bool orbit = true;

	private bool hidePlayer;

	private bool hideHud = true;

	private bool capturing;

	private float releaseAt;

	private float yaw;

	private float pitch;

	private float roll;

	private float distance;

	private float fov;

	private float originalFov;

	private float originalNear;

	private float originalSkyFov;

	private float nextRenderScan;

	private float nextCanvasScan;

	private Camera skyCamera;

	private readonly FrozenEffects effects = new FrozenEffects();

	private readonly PhotoEnvironment environment = new PhotoEnvironment();

	private float homeYaw;

	private float homePitch;

	private float homeDistance;

	private int lastBusyFrame = -2;

	private Vector3 lastSubjectPosition;

	private Vector3 position;

	private Vector3 pivot;

	private Camera camera;

	private Player subject;

	private CursorLockMode originalLock;

	private bool originalCursor;

	private Harmony harmony;

	private GameObject strip;

	private NativePhotoHints hints;

	private float nextHintRefresh;

	private string notice = "";

	private float noticeUntil;

	private readonly Dictionary<Renderer, bool> renderers = new Dictionary<Renderer, bool>();

	private readonly Dictionary<Canvas, bool> canvases = new Dictionary<Canvas, bool>();

	private readonly Dictionary<string, ConfigEntry<KeyboardShortcut>> keys = new Dictionary<string, ConfigEntry<KeyboardShortcut>>();

	private ConfigEntry<bool> freezeDefault;

	private ConfigEntry<float> speed;

	private ConfigEntry<float> sensitivity;

	private ConfigEntry<float> range;

	private ConfigEntry<string> output;

	internal static bool CapturingInput
	{
		get
		{
			if (Object.op_Implicit((Object)(object)Instance))
			{
				if (!Instance.Active)
				{
					return Time.unscaledTime < Instance.releaseAt;
				}
				return true;
			}
			return false;
		}
	}

	internal static bool PauseScene
	{
		get
		{
			if (Object.op_Implicit((Object)(object)Instance) && Instance.Active && Instance.Frozen && Object.op_Implicit((Object)(object)ZNet.instance))
			{
				return ZNet.IsSinglePlayer;
			}
			return false;
		}
	}

	private void Awake()
	{
		//IL_019a: Unknown result type (might be due to invalid IL or missing references)
		//IL_01a4: Expected O, but got Unknown
		//IL_01d9: Unknown result type (might be due to invalid IL or missing references)
		//IL_01e3: Expected O, but got Unknown
		//IL_0218: Unknown result type (might be due to invalid IL or missing references)
		//IL_0222: Expected O, but got Unknown
		//IL_0252: Unknown result type (might be due to invalid IL or missing references)
		//IL_025c: Expected O, but got Unknown
		Instance = this;
		Bind("Toggle", (KeyCode)293);
		Bind("Capture", (KeyCode)13);
		Bind("CameraMode", (KeyCode)9);
		Bind("Character", (KeyCode)118);
		Bind("HUD", (KeyCode)104);
		Bind("Freeze", (KeyCode)112);
		Bind("Reset", (KeyCode)114);
		Bind("Forward", (KeyCode)119);
		Bind("Back", (KeyCode)115);
		Bind("Left", (KeyCode)97);
		Bind("Right", (KeyCode)100);
		Bind("Up", (KeyCode)32);
		Bind("Down", (KeyCode)306);
		Bind("Fast", (KeyCode)304);
		Bind("Slow", (KeyCode)308);
		Bind("TimeEarlier", (KeyCode)281);
		Bind("TimeLater", (KeyCode)280);
		Bind("Weather", (KeyCode)278);
		Bind("NaturalConditions", (KeyCode)279);
		Bind("RollLeft", (KeyCode)113);
		Bind("RollRight", (KeyCode)101);
		Bind("WiderLens", (KeyCode)91);
		Bind("NarrowerLens", (KeyCode)93);
		freezeDefault = ((BaseUnityPlugin)this).Config.Bind<bool>("Camera", "FreezeSinglePlayer", true, "Freeze on entry in offline single-player only. P toggles. Multiplayer always stays live.");
		speed = ((BaseUnityPlugin)this).Config.Bind<float>("Camera", "MovementSpeed", 4f, new ConfigDescription("Metres per second; Shift is 3x faster.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.1f, 15f), new object[0]));
		sensitivity = ((BaseUnityPlugin)this).Config.Bind<float>("Camera", "MouseSensitivity", 0.12f, new ConfigDescription("Degrees per mouse pixel.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.01f, 1f), new object[0]));
		range = ((BaseUnityPlugin)this).Config.Bind<float>("Camera", "MaximumDistance", 40f, new ConfigDescription("Camera tether to the player; does not load remote scenery.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(5f, 60f), new object[0]));
		output = ((BaseUnityPlugin)this).Config.Bind<string>("Capture", "OutputDirectory", "", "Empty saves to Pictures/Valheim Photo Mode. An absolute custom path is supported. PNG at current screen resolution.");
		harmony = new Harmony("au.tyvalheim.photomode");
		harmony.PatchAll();
	}

	private void Bind(string name, KeyCode key)
	{
		//IL_0013: Unknown result type (might be due to invalid IL or missing references)
		//IL_001a: Unknown result type (might be due to invalid IL or missing references)
		keys[name] = ((BaseUnityPlugin)this).Config.Bind<KeyboardShortcut>("Keys", name, new KeyboardShortcut(key, (KeyCode[])(object)new KeyCode[0]), "Photo-mode binding. Restart the game after editing. Escape always exits.");
	}

	private bool Held(string name)
	{
		//IL_000c: 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)
		//IL_0014: Unknown result type (might be due to invalid IL or missing references)
		//IL_001d: Unknown result type (might be due to invalid IL or missing references)
		KeyboardShortcut value = keys[name].Value;
		if ((int)((KeyboardShortcut)(ref value)).MainKey != 0 && ZInput.GetKey(((KeyboardShortcut)(ref value)).MainKey, true))
		{
			return ((KeyboardShortcut)(ref value)).Modifiers.All((KeyCode k) => ZInput.GetKey(k, true));
		}
		return false;
	}

	private bool Pressed(string name)
	{
		//IL_000c: 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)
		//IL_0014: Unknown result type (might be due to invalid IL or missing references)
		//IL_001d: Unknown result type (might be due to invalid IL or missing references)
		KeyboardShortcut value = keys[name].Value;
		if ((int)((KeyboardShortcut)(ref value)).MainKey != 0 && ZInput.GetKeyDown(((KeyboardShortcut)(ref value)).MainKey, true))
		{
			return ((KeyboardShortcut)(ref value)).Modifiers.All((KeyCode k) => ZInput.GetKey(k, true));
		}
		return false;
	}

	private string Key(string name)
	{
		//IL_000c: 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)
		//IL_0029: Unknown result type (might be due to invalid IL or missing references)
		//IL_002f: Expected I4, but got Unknown
		KeyboardShortcut value = keys[name].Value;
		return string.Join(" + ", ((KeyboardShortcut)(ref value)).Modifiers.Concat((IEnumerable<KeyCode>)(object)new KeyCode[1] { (KeyCode)(int)((KeyboardShortcut)(ref value)).MainKey }).Select(KeyName).ToArray());
	}

	private static string KeyName(KeyCode key)
	{
		//IL_0000: Unknown result type (might be due to invalid IL or missing references)
		//IL_0001: Unknown result type (might be due to invalid IL or missing references)
		//IL_0002: Unknown result type (might be due to invalid IL or missing references)
		//IL_0005: Invalid comparison between Unknown and I4
		//IL_0007: Unknown result type (might be due to invalid IL or missing references)
		//IL_000a: Unknown result type (might be due to invalid IL or missing references)
		//IL_001c: Expected I4, but got Unknown
		//IL_0050: Unknown result type (might be due to invalid IL or missing references)
		//IL_001c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0022: Unknown result type (might be due to invalid IL or missing references)
		//IL_0030: Expected I4, but got Unknown
		if ((int)key != 13)
		{
			switch (key - 91)
			{
			default:
				switch (key - 305)
				{
				case 1:
					return "L Ctrl";
				case 0:
					return "R Ctrl";
				}
				break;
			case 0:
				return "[";
			case 2:
				return "]";
			case 1:
				break;
			}
			return ((object)key).ToString().Replace("Alpha", "").Replace("Left", "L ")
				.Replace("Right", "R ");
		}
		return "Enter";
	}

	private static bool Typing()
	{
		if (TextInput.IsVisible() || UnifiedPopup.WasVisibleThisFrame() || (Object.op_Implicit((Object)(object)Chat.instance) && Chat.instance.HasFocus()))
		{
			return true;
		}
		if (Object.op_Implicit((Object)(object)TextInput.instance) && Object.op_Implicit((Object)(object)TextInput.instance.m_panel) && TextInput.instance.m_panel.activeInHierarchy)
		{
			return true;
		}
		GameObject val = (Object.op_Implicit((Object)(object)EventSystem.current) ? EventSystem.current.currentSelectedGameObject : null);
		if (Object.op_Implicit((Object)(object)val) && val.activeInHierarchy)
		{
			if (!Object.op_Implicit((Object)(object)val.GetComponentInParent<TMP_InputField>()))
			{
				return Object.op_Implicit((Object)(object)val.GetComponentInParent<InputField>());
			}
			return true;
		}
		return false;
	}

	private static bool Busy()
	{
		if (!Typing() && !Console.IsVisible() && !Menu.IsVisible())
		{
			return StoreGui.IsVisible();
		}
		return true;
	}

	private void Update()
	{
		//IL_014f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0154: Unknown result type (might be due to invalid IL or missing references)
		//IL_0119: 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_012f: 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_013e: Unknown result type (might be due to invalid IL or missing references)
		//IL_02ec: Unknown result type (might be due to invalid IL or missing references)
		//IL_02e5: Unknown result type (might be due to invalid IL or missing references)
		//IL_02f1: Unknown result type (might be due to invalid IL or missing references)
		//IL_041e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0423: Unknown result type (might be due to invalid IL or missing references)
		//IL_0498: Unknown result type (might be due to invalid IL or missing references)
		//IL_049f: Unknown result type (might be due to invalid IL or missing references)
		//IL_04a6: Unknown result type (might be due to invalid IL or missing references)
		//IL_04ab: Unknown result type (might be due to invalid IL or missing references)
		//IL_04b8: Unknown result type (might be due to invalid IL or missing references)
		//IL_05b3: Unknown result type (might be due to invalid IL or missing references)
		//IL_05b8: Unknown result type (might be due to invalid IL or missing references)
		//IL_05ba: Unknown result type (might be due to invalid IL or missing references)
		//IL_05bc: Unknown result type (might be due to invalid IL or missing references)
		//IL_05c1: Unknown result type (might be due to invalid IL or missing references)
		//IL_05c6: Unknown result type (might be due to invalid IL or missing references)
		//IL_051b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0520: Unknown result type (might be due to invalid IL or missing references)
		//IL_052c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0531: Unknown result type (might be due to invalid IL or missing references)
		//IL_0536: Unknown result type (might be due to invalid IL or missing references)
		//IL_0547: Unknown result type (might be due to invalid IL or missing references)
		//IL_054d: Unknown result type (might be due to invalid IL or missing references)
		//IL_055d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0562: Unknown result type (might be due to invalid IL or missing references)
		//IL_0578: Unknown result type (might be due to invalid IL or missing references)
		//IL_057d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0582: Unknown result type (might be due to invalid IL or missing references)
		//IL_0589: Unknown result type (might be due to invalid IL or missing references)
		//IL_058e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0590: Unknown result type (might be due to invalid IL or missing references)
		//IL_0595: Unknown result type (might be due to invalid IL or missing references)
		//IL_05a0: Unknown result type (might be due to invalid IL or missing references)
		//IL_05a5: Unknown result type (might be due to invalid IL or missing references)
		//IL_05aa: Unknown result type (might be due to invalid IL or missing references)
		//IL_05fb: Unknown result type (might be due to invalid IL or missing references)
		//IL_0601: Unknown result type (might be due to invalid IL or missing references)
		//IL_0611: Unknown result type (might be due to invalid IL or missing references)
		//IL_0616: Unknown result type (might be due to invalid IL or missing references)
		//IL_0626: Unknown result type (might be due to invalid IL or missing references)
		//IL_062b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0630: Unknown result type (might be due to invalid IL or missing references)
		ReadingInput = true;
		try
		{
			if (!Active)
			{
				bool flag = Busy();
				if (flag)
				{
					lastBusyFrame = Time.frameCount;
				}
				if (Time.unscaledTime >= releaseAt && !flag && Time.frameCount > lastBusyFrame + 1 && Pressed("Toggle"))
				{
					Enter();
				}
			}
			else if (!Object.op_Implicit((Object)(object)subject) || (Object)(object)subject != (Object)(object)Player.m_localPlayer || ((Character)subject).IsDead() || ((Character)subject).IsTeleporting() || ((Character)subject).InCutscene() || !Object.op_Implicit((Object)(object)camera) || !Application.isFocused)
			{
				Exit();
			}
			else if (Pressed("Toggle") || ZInput.GetKeyDown((KeyCode)27, true))
			{
				if (!capturing)
				{
					Exit();
				}
			}
			else if (Busy())
			{
				if (!capturing)
				{
					Exit();
				}
			}
			else
			{
				if (capturing)
				{
					return;
				}
				if (orbit)
				{
					pivot += ((Component)subject).transform.position - lastSubjectPosition;
				}
				lastSubjectPosition = ((Component)subject).transform.position;
				if (Pressed("CameraMode"))
				{
					SwitchCameraMode();
				}
				if (Pressed("Character"))
				{
					hidePlayer = !hidePlayer;
					UpdateVisibility(force: true);
				}
				if (Pressed("HUD"))
				{
					hideHud = !hideHud;
					UpdateVisibility(force: true);
				}
				if (Pressed("Freeze"))
				{
					if (!Object.op_Implicit((Object)(object)ZNet.instance) || !ZNet.IsSinglePlayer)
					{
						SetFrozen(value: false);
						Notify("Multiplayer stays live");
					}
					else
					{
						SetFrozen(!Frozen);
					}
				}
				if (Pressed("Reset"))
				{
					ResetPose();
				}
				if (PhotoEnvironment.Allowed)
				{
					float num = (float)((Held("TimeLater") ? 1 : 0) - (Held("TimeEarlier") ? 1 : 0)) * Time.unscaledDeltaTime / 48f;
					if (num != 0f)
					{
						environment.ShiftTime(num);
					}
					if (Pressed("Weather"))
					{
						environment.CycleWeather();
					}
					if (Pressed("NaturalConditions"))
					{
						environment.Reset();
					}
				}
				float num2 = Mathf.Min(Time.unscaledDeltaTime, 0.05f);
				float num3 = (Held("Slow") ? 0.15f : (Held("Fast") ? 3f : 1f));
				float num4 = speed.Value * num2 * num3;
				Mouse current = Mouse.current;
				Vector2 val = ((current == null) ? Vector2.zero : ((InputControl<Vector2>)(object)((Pointer)current).delta).ReadValue());
				yaw += val.x * sensitivity.Value;
				pitch = Mathf.Clamp(pitch - val.y * sensitivity.Value, -85f, 85f);
				if (orbit)
				{
					yaw += (float)(((Held("Right") ? 1 : 0) - (Held("Left") ? 1 : 0)) * 45) * num2 * num3;
				}
				roll = Mathf.Clamp(roll + (float)(((Held("RollRight") ? 1 : 0) - (Held("RollLeft") ? 1 : 0)) * 30) * num2, -90f, 90f);
				fov = Mathf.Clamp(fov + (float)(((Held("WiderLens") ? 1 : 0) - (Held("NarrowerLens") ? 1 : 0)) * 30) * num2, 15f, 130f);
				Quaternion val2 = Quaternion.Euler(pitch, yaw, roll);
				Vector3 val3 = default(Vector3);
				((Vector3)(ref val3))..ctor((float)((Held("Right") ? 1 : 0) - (Held("Left") ? 1 : 0)), (float)((Held("Up") ? 1 : 0) - (Held("Down") ? 1 : 0)), (float)((Held("Forward") ? 1 : 0) - (Held("Back") ? 1 : 0)));
				val3 = Vector3.ClampMagnitude(val3, 1f) * num4;
				float num5 = ((current == null) ? 0f : ((InputControl<Vector2>)(object)current.scroll).ReadValue().y);
				if (Mathf.Approximately(num5, 0f))
				{
					num5 = ZInput.GetMouseScrollWheel();
				}
				float num6 = CameraRules.WheelSteps(num5);
				if (orbit)
				{
					distance = CameraRules.Dolly(distance, val3.z, num6, range.Value);
					pivot += Vector3.up * val3.y;
					pivot = ((Component)subject).transform.position + Vector3.ClampMagnitude(pivot - ((Component)subject).transform.position, range.Value * 0.5f);
					position = pivot - val2 * Vector3.forward * distance;
				}
				else
				{
					position += val2 * val3;
					fov = Mathf.Clamp(fov - num6 * 3f, 15f, 130f);
				}
				position = ((Component)subject).transform.position + Vector3.ClampMagnitude(position - ((Component)subject).transform.position, range.Value);
				if (Pressed("Capture"))
				{
					((MonoBehaviour)this).StartCoroutine(Capture());
				}
			}
		}
		catch (Exception ex)
		{
			((BaseUnityPlugin)this).Logger.LogError((object)ex);
			if (Active)
			{
				Exit();
			}
		}
		finally
		{
			ReadingInput = false;
		}
	}

	private void Enter()
	{
		//IL_009a: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ba: Unknown result type (might be due to invalid IL or missing references)
		//IL_00da: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ea: 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_00f9: 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_0128: Unknown result type (might be due to invalid IL or missing references)
		//IL_012d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0133: 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_019a: Unknown result type (might be due to invalid IL or missing references)
		//IL_01a0: Invalid comparison between Unknown and I4
		//IL_01d9: Unknown result type (might be due to invalid IL or missing references)
		//IL_01df: Invalid comparison between Unknown and I4
		subject = Player.m_localPlayer;
		camera = (Object.op_Implicit((Object)(object)GameCamera.instance) ? ((Component)GameCamera.instance).GetComponent<Camera>() : null);
		if (Object.op_Implicit((Object)(object)subject) && !((Character)subject).IsDead() && !((Character)subject).IsTeleporting() && !((Character)subject).InCutscene() && Object.op_Implicit((Object)(object)camera))
		{
			originalFov = camera.fieldOfView;
			originalNear = camera.nearClipPlane;
			homeYaw = ((Component)camera).transform.eulerAngles.y;
			homePitch = Mathf.DeltaAngle(0f, ((Component)camera).transform.eulerAngles.x);
			homeDistance = Mathf.Clamp(Vector3.Distance(((Component)camera).transform.position, ((Component)subject).transform.position + Vector3.up * 1.3f), 2f, 8f);
			lastSubjectPosition = ((Component)subject).transform.position;
			originalLock = Cursor.lockState;
			originalCursor = Cursor.visible;
			environment.Begin();
			Active = true;
			SetFrozen(freezeDefault.Value && Object.op_Implicit((Object)(object)ZNet.instance) && ZNet.IsSinglePlayer);
			orbit = true;
			hideHud = !Object.op_Implicit((Object)(object)Minimap.instance) || (int)Minimap.instance.m_mode != 2;
			hidePlayer = false;
			ResetPose();
			EnsureStrip();
			UpdateVisibility(force: true);
			Notify((Object.op_Implicit((Object)(object)Minimap.instance) && (int)Minimap.instance.m_mode == 2) ? ("Map photo ready - " + Key("Capture") + " saves; " + Key("HUD") + " toggles HUD") : (Frozen ? "Frozen" : "Live world"));
		}
	}

	private void ResetPose()
	{
		//IL_000c: 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)
		//IL_001b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0020: Unknown result type (might be due to invalid IL or missing references)
		//IL_0025: Unknown result type (might be due to invalid IL or missing references)
		//IL_0067: Unknown result type (might be due to invalid IL or missing references)
		//IL_007d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0082: Unknown result type (might be due to invalid IL or missing references)
		//IL_0087: Unknown result type (might be due to invalid IL or missing references)
		//IL_0092: Unknown result type (might be due to invalid IL or missing references)
		//IL_0097: Unknown result type (might be due to invalid IL or missing references)
		//IL_009c: Unknown result type (might be due to invalid IL or missing references)
		pivot = ((Component)subject).transform.position + Vector3.up * 1.55f;
		yaw = homeYaw;
		pitch = homePitch;
		roll = 0f;
		distance = homeDistance;
		fov = originalFov;
		position = pivot - Quaternion.Euler(pitch, yaw, 0f) * Vector3.forward * distance;
	}

	private void SetFrozen(bool value)
	{
		//IL_001c: Unknown result type (might be due to invalid IL or missing references)
		if (value && !Frozen)
		{
			effects.Freeze(((Component)subject).transform.position, range.Value + 30f);
		}
		if (!value)
		{
			effects.Resume();
		}
		Frozen = value;
	}

	private void SwitchCameraMode()
	{
		//IL_0026: Unknown result type (might be due to invalid IL or missing references)
		//IL_002b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0035: Unknown result type (might be due to invalid IL or missing references)
		//IL_003a: Unknown result type (might be due to invalid IL or missing references)
		//IL_003f: 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_004b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0050: Unknown result type (might be due to invalid IL or missing references)
		//IL_0055: Unknown result type (might be due to invalid IL or missing references)
		//IL_0086: Unknown result type (might be due to invalid IL or missing references)
		//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_0091: 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)
		//IL_0099: Unknown result type (might be due to invalid IL or missing references)
		orbit = !orbit;
		if (orbit)
		{
			pivot = ((Component)subject).transform.position + Vector3.up * 1.55f;
			Vector3 val = pivot - position;
			distance = Mathf.Clamp(((Vector3)(ref val)).magnitude, 0.12f, range.Value);
			if (((Vector3)(ref val)).sqrMagnitude > 0.0001f)
			{
				Quaternion val2 = Quaternion.LookRotation(val, Vector3.up);
				Vector3 eulerAngles = ((Quaternion)(ref val2)).eulerAngles;
				yaw = eulerAngles.y;
				pitch = Mathf.Clamp(Mathf.DeltaAngle(0f, eulerAngles.x), -85f, 85f);
			}
		}
		Notify(orbit ? "Orbit — mouse or A/D circles character" : "Free — mouse looks, A/D strafes");
	}

	internal void ApplyCamera(Camera sky)
	{
		//IL_0022: 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)
		if (!Active || !Object.op_Implicit((Object)(object)camera))
		{
			return;
		}
		((Component)camera).transform.SetPositionAndRotation(position, Quaternion.Euler(pitch, yaw, roll));
		camera.fieldOfView = fov;
		camera.nearClipPlane = 0.01f;
		if (Object.op_Implicit((Object)(object)sky))
		{
			if (!Object.op_Implicit((Object)(object)skyCamera))
			{
				skyCamera = sky;
				originalSkyFov = sky.fieldOfView;
			}
			sky.fieldOfView = fov;
		}
		ZCursor.LockState = (CursorLockMode)1;
		ZCursor.Hide();
	}

	private void LateUpdate()
	{
		if (!Active)
		{
			return;
		}
		if (PauseScene)
		{
			effects.Hold();
		}
		else if (Frozen)
		{
			SetFrozen(value: false);
		}
		try
		{
			environment.Apply(PauseScene);
		}
		catch (Exception ex)
		{
			((BaseUnityPlugin)this).Logger.LogError((object)ex);
			Exit();
			return;
		}
		UpdateVisibility(force: false);
		if (Object.op_Implicit((Object)(object)strip))
		{
			strip.SetActive(!capturing);
		}
		if (hints != null && Time.unscaledTime >= nextHintRefresh)
		{
			nextHintRefresh = Time.unscaledTime + 0.1f;
			hints.Begin();
			hints.Add("Photo", Key("Capture"));
			hints.Add(orbit ? "Free camera" : "Orbit camera", Key("CameraMode"));
			hints.Add(orbit ? "Distance" : "Move", orbit ? (Key("Forward") + " / " + Key("Back")) : (Key("Forward") + " / " + Key("Left") + " / " + Key("Back") + " / " + Key("Right")));
			if (orbit)
			{
				hints.Add("Circle", Key("Left") + " / " + Key("Right"));
			}
			hints.Add("Height", Key("Up") + " / " + Key("Down"));
			hints.Add("Fast", Key("Fast"));
			hints.Add("Slow", Key("Slow"));
			hints.Add(orbit ? "Orbit" : "Look", "Mouse");
			hints.Add(orbit ? "Distance" : "Lens", "Wheel");
			hints.Add(hidePlayer ? "Show character" : "Hide character", Key("Character"));
			hints.Add(hideHud ? "Show HUD" : "Hide HUD", Key("HUD"));
			if (Object.op_Implicit((Object)(object)ZNet.instance) && ZNet.IsSinglePlayer)
			{
				hints.Add(PauseScene ? "Resume" : "Freeze", Key("Freeze"));
			}
			hints.Add("Tilt", Key("RollLeft") + " / " + Key("RollRight"));
			hints.Add("Lens " + Mathf.RoundToInt(fov) + "°", Key("WiderLens") + " / " + Key("NarrowerLens"));
			hints.Add("Reset", Key("Reset"));
			hints.Add("Exit", Key("Toggle") + " / Esc");
			if (PhotoEnvironment.Allowed)
			{
				hints.Add("Time " + environment.Clock, Key("TimeEarlier") + " / " + Key("TimeLater"));
				hints.Add("Weather " + environment.Weather, Key("Weather"));
				hints.Add("Natural conditions", Key("NaturalConditions"));
			}
			string text = (PhotoEnvironment.Allowed ? "" : "Time & weather unavailable in multiplayer.");
			if (Time.unscaledTime < noticeUntil)
			{
				text = text + ((text.Length > 0) ? "   " : "") + notice;
			}
			hints.Finish(text);
		}
	}

	private void EnsureStrip()
	{
		//IL_0048: Unknown result type (might be due to invalid IL or missing references)
		//IL_0052: Expected O, but got Unknown
		//IL_008e: Unknown result type (might be due to invalid IL or missing references)
		if (Object.op_Implicit((Object)(object)strip))
		{
			return;
		}
		strip = new GameObject("Photo controls", new Type[3]
		{
			typeof(RectTransform),
			typeof(Canvas),
			typeof(CanvasScaler)
		});
		Canvas component = strip.GetComponent<Canvas>();
		component.renderMode = (RenderMode)0;
		component.sortingOrder = 32000;
		CanvasScaler component2 = strip.GetComponent<CanvasScaler>();
		component2.uiScaleMode = (ScaleMode)1;
		component2.referenceResolution = new Vector2(1920f, 1080f);
		component2.matchWidthOrHeight = 0.5f;
		KeyHints instance = KeyHints.instance;
		TMP_Text val = (TMP_Text)(object)(Object.op_Implicit((Object)(object)instance) ? instance.m_buildMenuKey : null);
		TMP_Text val2 = null;
		if (Object.op_Implicit((Object)(object)instance) && Object.op_Implicit((Object)(object)instance.m_primaryAttackKB))
		{
			val2 = ((IEnumerable<TMP_Text>)instance.m_primaryAttackKB.GetComponentsInChildren<TMP_Text>(true)).FirstOrDefault((Func<TMP_Text, bool>)((TMP_Text t) => !Object.op_Implicit((Object)(object)NativePhotoHints.FindKeyBackground(t))));
		}
		if (!Object.op_Implicit((Object)(object)val2))
		{
			val2 = val;
		}
		Image val3 = NativePhotoHints.FindKeyBackground(val);
		if (!Object.op_Implicit((Object)(object)val3))
		{
			((BaseUnityPlugin)this).Logger.LogWarning((object)"Native keycap artwork was not available; photo hints will use text until the UI is recreated.");
		}
		hints = new NativePhotoHints(strip.transform, val, val2, val3);
	}

	private void UpdateVisibility(bool force)
	{
		if (hidePlayer)
		{
			if (force || Time.unscaledTime >= nextRenderScan)
			{
				nextRenderScan = Time.unscaledTime + 0.25f;
				Renderer[] componentsInChildren = ((Component)subject).GetComponentsInChildren<Renderer>(true);
				foreach (Renderer val in componentsInChildren)
				{
					if (!renderers.ContainsKey(val))
					{
						renderers[val] = val.forceRenderingOff;
					}
				}
			}
			foreach (Renderer key in renderers.Keys)
			{
				if (Object.op_Implicit((Object)(object)key))
				{
					key.forceRenderingOff = true;
				}
			}
		}
		else
		{
			foreach (KeyValuePair<Renderer, bool> renderer in renderers)
			{
				if (Object.op_Implicit((Object)(object)renderer.Key))
				{
					renderer.Key.forceRenderingOff = renderer.Value;
				}
			}
			renderers.Clear();
		}
		if (hideHud)
		{
			if (force || Time.unscaledTime >= nextCanvasScan)
			{
				nextCanvasScan = Time.unscaledTime + 0.25f;
				Canvas[] array = Object.FindObjectsByType<Canvas>((FindObjectsSortMode)0);
				foreach (Canvas val2 in array)
				{
					if (Object.op_Implicit((Object)(object)val2) && (Object)(object)((Component)val2).gameObject != (Object)(object)strip && !canvases.ContainsKey(val2))
					{
						canvases[val2] = ((Behaviour)val2).enabled;
					}
				}
			}
			{
				foreach (Canvas key2 in canvases.Keys)
				{
					if (Object.op_Implicit((Object)(object)key2))
					{
						((Behaviour)key2).enabled = false;
					}
				}
				return;
			}
		}
		foreach (KeyValuePair<Canvas, bool> canvase in canvases)
		{
			if (Object.op_Implicit((Object)(object)canvase.Key))
			{
				((Behaviour)canvase.Key).enabled = canvase.Value;
			}
		}
		canvases.Clear();
	}

	private IEnumerator Capture()
	{
		capturing = true;
		if (Object.op_Implicit((Object)(object)strip))
		{
			strip.SetActive(false);
		}
		yield return (object)new WaitForEndOfFrame();
		Texture2D image = null;
		try
		{
			if (Active && Object.op_Implicit((Object)(object)camera))
			{
				image = ScreenCapture.CaptureScreenshotAsTexture();
				if (!Object.op_Implicit((Object)(object)image))
				{
					throw new InvalidOperationException("No rendered frame was available.");
				}
				string text = PhotoFiles.Save(PhotoFiles.DirectoryPath(output.Value), ScreenshotEncoding.EncodeOpaquePng(image));
				((BaseUnityPlugin)this).Logger.LogInfo((object)("Screenshot saved: " + text));
				Notify("Saved " + Path.GetFileName(text));
			}
		}
		catch (Exception ex)
		{
			((BaseUnityPlugin)this).Logger.LogError((object)ex);
			Notify("Photo failed — see BepInEx log");
		}
		finally
		{
			if (Object.op_Implicit((Object)(object)image))
			{
				Object.Destroy((Object)(object)image);
			}
			capturing = false;
			if (Object.op_Implicit((Object)(object)strip) && Active)
			{
				strip.SetActive(true);
			}
		}
	}

	private void Notify(string message)
	{
		((BaseUnityPlugin)this).Logger.LogInfo((object)message);
		notice = message;
		noticeUntil = Time.unscaledTime + 5f;
	}

	private void Exit()
	{
		//IL_0160: Unknown result type (might be due to invalid IL or missing references)
		Active = false;
		try
		{
			environment.Reset();
		}
		catch (Exception ex)
		{
			((BaseUnityPlugin)this).Logger.LogError((object)ex);
		}
		SetFrozen(value: false);
		releaseAt = Time.unscaledTime + 0.2f;
		foreach (KeyValuePair<Renderer, bool> renderer in renderers)
		{
			if (Object.op_Implicit((Object)(object)renderer.Key))
			{
				renderer.Key.forceRenderingOff = renderer.Value;
			}
		}
		renderers.Clear();
		foreach (KeyValuePair<Canvas, bool> canvase in canvases)
		{
			if (Object.op_Implicit((Object)(object)canvase.Key))
			{
				((Behaviour)canvase.Key).enabled = canvase.Value;
			}
		}
		canvases.Clear();
		if (Object.op_Implicit((Object)(object)camera))
		{
			camera.fieldOfView = originalFov;
			camera.nearClipPlane = originalNear;
		}
		if (Object.op_Implicit((Object)(object)skyCamera))
		{
			skyCamera.fieldOfView = originalSkyFov;
		}
		skyCamera = null;
		if (Object.op_Implicit((Object)(object)strip))
		{
			strip.SetActive(false);
		}
		Cursor.lockState = originalLock;
		Cursor.visible = originalCursor;
	}

	private void OnDisable()
	{
		if (Active)
		{
			Exit();
		}
	}

	private void OnDestroy()
	{
		if (Active)
		{
			Exit();
		}
		if (Object.op_Implicit((Object)(object)strip))
		{
			Object.Destroy((Object)(object)strip);
		}
		if (harmony != null)
		{
			harmony.UnpatchSelf();
		}
		if ((Object)(object)Instance == (Object)(object)this)
		{
			Instance = null;
		}
	}
}
[HarmonyPatch(typeof(GameCamera), "UpdateCamera")]
internal static class CameraPatch
{
	private static bool Prefix(Camera ___m_skyCamera)
	{
		if (!Object.op_Implicit((Object)(object)Plugin.Instance) || !Plugin.Instance.Active)
		{
			return true;
		}
		Plugin.Instance.ApplyCamera(___m_skyCamera);
		return false;
	}
}
[HarmonyPatch(typeof(EventSystem), "Update")]
internal static class UiInputPatch
{
	private static bool Prefix()
	{
		return !Plugin.CapturingInput;
	}
}
[HarmonyPatch(typeof(GameCamera), "UpdateFOV")]
internal static class FovPatch
{
	private static bool Prefix()
	{
		if (Object.op_Implicit((Object)(object)Plugin.Instance))
		{
			return !Plugin.Instance.Active;
		}
		return true;
	}
}
[HarmonyPatch(typeof(GameCamera), "ScreenShot")]
internal static class NativeCapturePatch
{
	private static bool Prefix()
	{
		return !Plugin.CapturingInput;
	}
}
[HarmonyPatch(typeof(GameCamera), "UpdateMouseCapture")]
internal static class CursorPatch
{
	private static bool Prefix()
	{
		if (Object.op_Implicit((Object)(object)Plugin.Instance))
		{
			return !Plugin.Instance.Active;
		}
		return true;
	}
}
[HarmonyPatch(typeof(Game), "IsPaused")]
internal static class PausePatch
{
	private static void Postfix(ref bool __result)
	{
		if (Plugin.PauseScene)
		{
			__result = true;
		}
	}
}
[HarmonyPatch(typeof(Player), "TakeInput")]
internal static class PlayerInputPatch
{
	private static void Postfix(Player __instance, ref bool __result)
	{
		if ((Object)(object)__instance == (Object)(object)Player.m_localPlayer && Plugin.CapturingInput)
		{
			__result = false;
		}
	}
}
[HarmonyPatch(typeof(PlayerController), "TakeInput")]
internal static class ControllerPatch
{
	private static void Postfix(Player ___m_character, ref bool __result)
	{
		if ((Object)(object)___m_character == (Object)(object)Player.m_localPlayer && Plugin.CapturingInput)
		{
			__result = false;
		}
	}
}
[HarmonyPatch]
internal static class ButtonsPatch
{
	private static IEnumerable<MethodBase> TargetMethods()
	{
		try
		{
			string[] array = new string[3] { "GetButton", "GetButtonDown", "GetButtonUp" };
			foreach (string name in array)
			{
				yield return AccessTools.Method(typeof(ZInput), name, new Type[1] { typeof(string) }, (Type[])null);
			}
		}
		finally
		{
		}
		try
		{
			string[] array2 = new string[3] { "GetKey", "GetKeyDown", "GetKeyUp" };
			foreach (string name2 in array2)
			{
				yield return AccessTools.Method(typeof(ZInput), name2, new Type[2]
				{
					typeof(KeyCode),
					typeof(bool)
				}, (Type[])null);
			}
		}
		finally
		{
		}
	}

	private static bool Prefix(ref bool __result)
	{
		if (Plugin.ReadingInput || !Plugin.CapturingInput)
		{
			return true;
		}
		__result = false;
		return false;
	}
}
internal static class ScreenshotEncoding
{
	internal static byte[] EncodeOpaquePng(Texture2D frame)
	{
		//IL_0021: Unknown result type (might be due to invalid IL or missing references)
		//IL_0027: Expected O, but got Unknown
		if (!Object.op_Implicit((Object)(object)frame))
		{
			throw new ArgumentNullException("frame");
		}
		Texture2D val = new Texture2D(((Texture)frame).width, ((Texture)frame).height, (TextureFormat)3, false);
		try
		{
			val.SetPixels32(frame.GetPixels32());
			val.Apply(false, false);
			return ImageConversion.EncodeToPNG(val);
		}
		finally
		{
			if (Application.isPlaying)
			{
				Object.Destroy((Object)(object)val);
			}
			else
			{
				Object.DestroyImmediate((Object)(object)val);
			}
		}
	}
}