Decompiled source of Wide Angle Camera v3.2.1

WideAngleCamera/wk.barackobusiness.wideangle.dll

Decompiled 3 weeks ago
using System;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Configuration;
using DarkMachine.UI;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using UnityEngine;
using UnityEngine.Rendering;
using UnityEngine.SceneManagement;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("wk.barackobusiness.wideangle")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("3.2.0.0")]
[assembly: AssemblyInformationalVersion("3.2.0+2033533dc63bc54b84330f36ae2dc8e11618775b")]
[assembly: AssemblyProduct("Wide Angle Camera")]
[assembly: AssemblyTitle("wk.barackobusiness.wideangle")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("3.2.0.0")]
[module: UnverifiableCode]
[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 WideAngleCamera
{
	public class CameraManager : MonoBehaviour
	{
		public static CameraManager Instance;

		public static CameraManager HandInstance;

		private Camera front;

		private Camera back;

		private Camera right;

		private Camera left;

		private Camera up;

		private Camera down;

		private RenderTexture cubemap;

		private Material screen;

		private WideAnglePlugin.Projection projection;

		private Func<WideAnglePlugin.Projection, float> GetBound;

		private float curFOV;

		private float sprintFOV;

		private ENT_Player player;

		private GameSettings settings;

		private FieldInfo sliding;

		public float FOV
		{
			get
			{
				return screen.GetFloat("_FOV");
			}
			internal set
			{
				screen.SetFloat("_FOV", value);
			}
		}

		internal void Init(Material projector, Camera orig, bool useBack, int size, WideAnglePlugin.Projection projection, Func<WideAnglePlugin.Projection, float> bound)
		{
			//IL_0118: Unknown result type (might be due to invalid IL or missing references)
			//IL_0122: Expected O, but got Unknown
			player = ENT_Player.GetPlayer();
			settings = SettingsManager.settings;
			curFOV = settings.playerFOV;
			sprintFOV = curFOV + 15f;
			sliding = typeof(ENT_Player).GetField("isSliding", BindingFlags.Instance | BindingFlags.NonPublic);
			front = ((Component)((Component)this).transform.Find("Front")).GetComponent<Camera>();
			back = ((Component)((Component)this).transform.Find("Back")).GetComponent<Camera>();
			left = ((Component)((Component)this).transform.Find("Left")).GetComponent<Camera>();
			right = ((Component)((Component)this).transform.Find("Right")).GetComponent<Camera>();
			up = ((Component)((Component)this).transform.Find("Up")).GetComponent<Camera>();
			down = ((Component)((Component)this).transform.Find("Down")).GetComponent<Camera>();
			((Component)back).gameObject.SetActive(useBack);
			SetupCams(orig, size);
			cubemap = new RenderTexture(size, size, 16);
			((Texture)cubemap).dimension = (TextureDimension)4;
			screen = projector;
			screen.mainTexture = (Texture)(object)cubemap;
			FOV = curFOV;
			this.projection = projection;
			GetBound = bound;
		}

		private void Update()
		{
			if ((Object)(object)screen == (Object)null)
			{
				return;
			}
			Graphics.CopyTexture((Texture)(object)front.targetTexture, 0, (Texture)(object)cubemap, 4);
			if (((Component)back).gameObject.activeSelf)
			{
				Graphics.CopyTexture((Texture)(object)back.targetTexture, 0, (Texture)(object)cubemap, 5);
			}
			Graphics.CopyTexture((Texture)(object)right.targetTexture, 0, (Texture)(object)cubemap, 0);
			Graphics.CopyTexture((Texture)(object)left.targetTexture, 0, (Texture)(object)cubemap, 1);
			Graphics.CopyTexture((Texture)(object)up.targetTexture, 0, (Texture)(object)cubemap, 3);
			Graphics.CopyTexture((Texture)(object)down.targetTexture, 0, (Texture)(object)cubemap, 2);
			if (!player.IsLocked())
			{
				curFOV = Mathf.Clamp(curFOV + ((GameEntity)player).curBuffs.GetBuff("addFOV"), 75f, GetBound(projection));
				FOV = Math.ExpDecay(FOV, curFOV, 5f, Time.deltaTime);
				curFOV = settings.playerFOV;
				sprintFOV = curFOV + 15f;
			}
			if (!player.IsMoveLocked() && !CommandConsole.IsConsoleVisible())
			{
				bool flag = (bool)sliding.GetValue(player);
				if (player.IsSprinting() && player.IsGrounded(false) && !flag && !settings.disableSprintFov)
				{
					curFOV = sprintFOV;
				}
			}
		}

		private void OnDestroy()
		{
			cubemap.Release();
		}

		private void SetupCams(Camera orig, int size)
		{
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: Expected O, but got Unknown
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			Camera[] subCameras = GetSubCameras();
			foreach (Camera obj in subCameras)
			{
				obj.targetTexture = new RenderTexture(size, size, 16);
				obj.depth = orig.depth;
				obj.clearFlags = orig.clearFlags;
				obj.cullingMask = orig.cullingMask;
				obj.depthTextureMode = (DepthTextureMode)1;
			}
		}

		internal Camera[] GetSubCameras()
		{
			return (Camera[])(object)new Camera[6] { front, back, left, right, up, down };
		}
	}
	public class HelpingHand : MonoBehaviour
	{
		private ENT_Player player;

		private void Update()
		{
			if ((Object)(object)player != (Object)null)
			{
				Hand[] hands = player.hands;
				foreach (Hand val in hands)
				{
					if (val.IsHolding() || val.IsLocked())
					{
						((Component)val.handBase).gameObject.layer = 28;
					}
					else
					{
						((Component)val.handBase).gameObject.layer = 8;
					}
				}
			}
			else
			{
				player = ENT_Player.GetPlayer();
			}
		}
	}
	[BepInPlugin("wk.barackobusiness.wideangle", "Wide Angle Camera", "3.2.0")]
	public class WideAnglePlugin : BaseUnityPlugin
	{
		private enum Quality
		{
			VeryLow = 0x100,
			Low = 0x200,
			Normal = 0x400,
			Extreme = 0x800
		}

		public enum Projection
		{
			Stereographic,
			Equidistant,
			Equisolid,
			Panini
		}

		private ConfigEntry<Quality> quality;

		private ConfigEntry<Projection> projection;

		private ConfigEntry<float> Z;

		private ConfigEntry<bool> syncSprites;

		private ConfigEntry<bool> renderBackface;

		private ConfigEntry<bool> allowExtreme;

		private GameObject wideAngleCamera;

		private Shader wideAngleShader;

		private Harmony patcher;

		private void Awake()
		{
			//IL_00ed: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f7: Expected O, but got Unknown
			quality = ((BaseUnityPlugin)this).Config.Bind<Quality>("General", "Cubemap Resolution", Quality.Low, "The default side length of a face on the cubemap. This setting controls quality and performance.");
			projection = ((BaseUnityPlugin)this).Config.Bind<Projection>("Projection Configuration", "Projection Technique", Projection.Stereographic, "The technique used to project the environment onto your screen.\r\nStereographic projection draws a ray through each point on the sphere onto the projected plane. Just like standard rectilinear, only the projection point is at the north pole instead of the origin of the sphere.\r\nIt is conformal, as in locally angles of intersections are preserved; circles remain circular at any given position on screen. This is the recommended and likely most comfortable projection to play with.\r\nEquidistant projection maps points on the viewing sphere to the projected plane such that distance from the center corresponds directly to angle measure between that point and the center on the globe.\r\nEquisolid projection maps the viewing sphere to a disk such that area on the disk accurately represents area at all regions of the sphere.\r\nPanini projects from a cylinder onto your view. The straightness of vertical lines is retained from rectilinear projection while allowing for a much wider field of view.");
			Z = ((BaseUnityPlugin)this).Config.Bind<float>("Projection Configuration", "Projection Z Component", 1f, "The Z coordinate relative to the center of the panosphere that the projection point lies on.\r\nOnly applies to stereographic and panini projection (currently only panini projection implemented)");
			syncSprites = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "Synchronize Sprites", true, "Whether to synchronize sprite objects (such as hands) or not. When synchronized, a second wide angle projection camera is created with the sole purpose to render sprites in world space.\r\nThis incurs a not insignificant rendering cost however hands and other sprites in the world will appear in their appropriate positions.");
			renderBackface = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "Enable backface", false, "Whether to render behind the player or not. Incurs additional performance cost but resolves black borders on the edges of the screen at high fields of view. Perhaps necessary for normal fovs on ultrawide screens.");
			allowExtreme = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "Allow Extreme Fields of View", false, "Whether the mod should allow you to select a field of view value close to the theoretical limits of the projection or set a reasonable upper bound.");
			if (LoadAssetBundle())
			{
				SceneManager.sceneLoaded += OnSceneLoaded;
				patcher = new Harmony("wk.barackobusiness.wideangle");
				patcher.PatchAll(typeof(UT_CameraTakeoverPatches));
				if (syncSprites.Value)
				{
					patcher.PatchAll(typeof(DEN_Hopper_TickPatches));
				}
				((BaseUnityPlugin)this).Logger.LogInfo((object)"Wide angle views are NOW possible");
			}
		}

		private void OnSceneLoaded(Scene scene, LoadSceneMode mode)
		{
			//IL_00db: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e5: Expected O, but got Unknown
			//IL_00fa: 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_0225: Expected O, but got Unknown
			//IL_027f: Unknown result type (might be due to invalid IL or missing references)
			if (((Scene)(ref scene)).name == "Intro")
			{
				return;
			}
			Func<Projection, float> func = (allowExtreme.Value ? new Func<Projection, float>(HardBound) : new Func<Projection, float>(SoftBound));
			if (((Scene)(ref scene)).name == "Main-Menu")
			{
				((Component)GameObject.Find("Canvas - Screens").transform.Find("Screens/Canvas - Screen - Settings/Settings Menu/SettingsParent/Settings Pane/Video Settings/Main Panel/Tab - Video/Column - Video/SliderAsset - FOV/Slider")).GetComponent<SubmitSlider>().maxValue = func(projection.Value);
				return;
			}
			((Component)GameObject.Find("Pause").transform.Find("Pause Menu/Settings Menu/SettingsParent/Settings Pane/Video Settings/Main Panel/Tab - Video/Column - Video/SliderAsset - FOV/Slider")).GetComponent<SubmitSlider>().maxValue = func(projection.Value);
			Transform transform = ((Component)Camera.main).transform;
			GameObject val = SetupProjector("Geometry Screen");
			((Renderer)val.GetComponent<MeshRenderer>()).material = new Material(wideAngleShader);
			val.transform.localPosition = new Vector3(0f, 0f, 0.5f);
			val.transform.SetParent(transform, false);
			val.layer = 31;
			if (projection.Value == Projection.Panini)
			{
				((Renderer)val.GetComponent<MeshRenderer>()).material.SetFloat("_D", Z.Value);
			}
			GameObject obj = Object.Instantiate<GameObject>(wideAngleCamera, transform, false);
			((Object)obj).name = "Wide Angle Camera";
			CameraManager cameraManager = obj.AddComponent<CameraManager>();
			cameraManager.Init(((Renderer)val.GetComponent<MeshRenderer>()).material, Camera.main, renderBackface.Value, (int)quality.Value, projection.Value, func);
			CameraManager.Instance = cameraManager;
			Camera.main.nearClipPlane = 0f;
			Camera.main.farClipPlane = 1f;
			Camera.main.cullingMask = int.MinValue;
			Camera.main.orthographic = true;
			Camera.main.orthographicSize = 0.75f;
			Camera.main.useOcclusionCulling = false;
			Camera.main.clearFlags = (CameraClearFlags)4;
			if (syncSprites.Value)
			{
				GameObject val2 = SetupProjector("Hand Screen");
				Material val3 = new Material(wideAngleShader);
				val3.SetOverrideTag("RenderType", "Transparent");
				val3.renderQueue = 3000;
				val3.SetInt("_SrcBlend", 5);
				val3.SetInt("_DstBlend", 10);
				((Renderer)val2.GetComponent<MeshRenderer>()).material = val3;
				val2.transform.localPosition = new Vector3(0f, 0f, 0.25f);
				val2.transform.SetParent(transform, false);
				val2.layer = 31;
				if (projection.Value == Projection.Panini)
				{
					((Renderer)val2.GetComponent<MeshRenderer>()).material.SetFloat("_D", Z.Value);
				}
				Camera component = ((Component)transform.Find("Inventory Camera")).GetComponent<Camera>();
				GameObject val4 = Object.Instantiate<GameObject>(wideAngleCamera, transform, false);
				((Object)val4).name = "Wide Angle Hand Camera";
				CameraManager cameraManager2 = val4.AddComponent<CameraManager>();
				cameraManager2.Init(((Renderer)val2.GetComponent<MeshRenderer>()).material, component, renderBackface.Value, (int)quality.Value, projection.Value, func);
				CameraManager.HandInstance = cameraManager2;
				Camera[] subCameras = cameraManager2.GetSubCameras();
				foreach (Camera obj2 in subCameras)
				{
					obj2.clearFlags = (CameraClearFlags)2;
					obj2.cullingMask = 268435456;
				}
				val4.AddComponent<HelpingHand>();
			}
		}

		public float SoftBound(Projection projection)
		{
			Func<float, float> func = Mathf.Sin;
			Func<float, float> func2 = Mathf.Asin;
			Func<float, float> func3 = Mathf.Tan;
			Func<float, float> func4 = Mathf.Atan;
			float num = MathF.PI / 180f;
			float num2 = Mathf.Sqrt(1f + Camera.main.aspect * Camera.main.aspect);
			return Mathf.Floor(projection switch
			{
				Projection.Stereographic => 4f * func4(func3(315f * num * 0.25f) / num2) / num, 
				Projection.Equidistant => 360f / num2, 
				Projection.Equisolid => 4f * func2(func(360f * num * 0.25f) / num2) / num, 
				Projection.Panini => 170f, 
				_ => 350f, 
			});
		}

		public float HardBound(Projection projection)
		{
			return projection switch
			{
				Projection.Stereographic => 350f, 
				Projection.Equidistant => 360f, 
				Projection.Equisolid => 360f, 
				Projection.Panini => 170f, 
				_ => 350f, 
			};
		}

		private GameObject SetupProjector(string name)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Expected O, but got Unknown
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0064: Unknown result type (might be due to invalid IL or missing references)
			//IL_0081: 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_0097: Unknown result type (might be due to invalid IL or missing references)
			//IL_009c: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_00d7: 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_00e3: Unknown result type (might be due to invalid IL or missing references)
			//IL_0113: Expected O, but got Unknown
			Mesh val = new Mesh();
			((Object)val).name = "Triangle";
			val.vertices = (Vector3[])(object)new Vector3[3]
			{
				new Vector3(-1f, -1f, 0f),
				new Vector3(3f, -1f, 0f),
				new Vector3(-1f, 3f, 0f)
			};
			val.uv = (Vector2[])(object)new Vector2[3]
			{
				new Vector2(0f, 0f),
				new Vector2(2f, 0f),
				new Vector2(0f, 2f)
			};
			val.triangles = new int[3] { 2, 1, 0 };
			val.RecalculateBounds();
			GameObject val2 = new GameObject(name);
			MeshFilter val3 = val2.AddComponent<MeshFilter>();
			MeshRenderer obj = val2.AddComponent<MeshRenderer>();
			((Renderer)obj).receiveShadows = false;
			((Renderer)obj).lightProbeUsage = (LightProbeUsage)0;
			((Renderer)obj).shadowCastingMode = (ShadowCastingMode)0;
			((Renderer)obj).motionVectorGenerationMode = (MotionVectorGenerationMode)2;
			((Renderer)obj).reflectionProbeUsage = (ReflectionProbeUsage)0;
			val3.sharedMesh = val;
			return val2;
		}

		private bool LoadAssetBundle()
		{
			AssetBundle val = AssetBundle.LoadFromFile(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location) + "\\WideAngleAssets");
			if ((Object)(object)val == (Object)null)
			{
				((BaseUnityPlugin)this).Logger.LogError((object)"Wide angle views are NOT possible, please ensure the asset bundle is present in the same folder as the plugin");
				return false;
			}
			wideAngleCamera = val.LoadAsset<GameObject>("Wide Angle Camera");
			Shader[] array = val.LoadAllAssets<Shader>();
			foreach (Shader val2 in array)
			{
				if (((Object)val2).name == "Custom/" + projection.Value)
				{
					wideAngleShader = val2;
				}
			}
			if ((Object)(object)wideAngleCamera == (Object)null || (Object)(object)wideAngleShader == (Object)null)
			{
				((BaseUnityPlugin)this).Logger.LogError((object)"Wide angle views are NOT possible, please reacquire the asset bundle from https://github.com/BarackOBusiness/WKWideAngleCamera");
			}
			Object.DontDestroyOnLoad((Object)(object)wideAngleCamera);
			Object.DontDestroyOnLoad((Object)(object)wideAngleShader);
			return true;
		}
	}
	public static class Math
	{
		public static float ExpDecay(float a, float b, float decay, float dt)
		{
			return b + (a - b) * Mathf.Exp((0f - decay) * dt);
		}
	}
	public static class UT_CameraTakeoverPatches
	{
		[HarmonyPatch(typeof(UT_CameraTakeover), "Update")]
		[HarmonyPostfix]
		public static void Postfix_Update(UT_CameraTakeover __instance, ref bool ___active)
		{
			CameraManager instance = CameraManager.Instance;
			if (___active)
			{
				float num = Math.ExpDecay(instance.FOV, __instance.fov, __instance.speed, Time.deltaTime);
				Debug.Log((object)$"Trying to set FOV, current {instance.FOV}, target {num}");
				instance.FOV = num;
			}
		}
	}
	public static class DEN_Hopper_TickPatches
	{
		[HarmonyPatch(typeof(DEN_Hopper_Tick), "Start")]
		[HarmonyPostfix]
		public static void Postfix_Start(DEN_Hopper_Tick __instance)
		{
			CollectionExtensions.Do<Transform>(from t in ((Component)((Component)__instance).transform).GetComponentsInChildren<Transform>(true)
				where ((Component)t).gameObject.layer == 8 && ((Object)t).name != "Effect_BloodSplatter"
				select t, (Action<Transform>)delegate(Transform t)
			{
				((Component)t).gameObject.layer = 28;
			});
		}
	}
	public static class MyPluginInfo
	{
		public const string PLUGIN_GUID = "wk.barackobusiness.wideangle";

		public const string PLUGIN_NAME = "Wide Angle Camera";

		public const string PLUGIN_VERSION = "3.2.0";
	}
}