Decompiled source of SpectatorCamPlus v1.0.0

BepInEx/plugins/SpectatorCameraPlus/SpectatorCameraPlus.dll

Decompiled a day ago
using System;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using Microsoft.CodeAnalysis;
using Unity.XR.CoreUtils;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: AssemblyCompany("SpectatorCameraPlus")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("SpectatorCameraPlus")]
[assembly: AssemblyTitle("SpectatorCameraPlus")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.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 SpectatorCameraPlus
{
	[BepInPlugin("com.mrbub.spectatorcameraplus", "SpectatorCameraPlus", "1.0.0")]
	public class Plugin : BaseUnityPlugin
	{
		public static ConfigEntry<float> PositionSmoothTime;

		public static ConfigEntry<float> RotationSmoothTime;

		public static ConfigEntry<float> FieldOfView;

		public static ConfigEntry<bool> SmoothingEnabled;

		public static ConfigEntry<float> NearClipPlane;

		public static ConfigEntry<bool> StabilizationEnabled;

		public static ConfigEntry<float> StabilizationStrength;

		public static ConfigEntry<float> RotationDeadzone;

		public static ConfigEntry<float> PositionDeadzone;

		private SpectatorCameraController _cameraController;

		public static Plugin Instance { get; private set; }

		public static ManualLogSource Log => ((BaseUnityPlugin)Instance).Logger;

		private void Awake()
		{
			Instance = this;
			InitConfig();
			((BaseUnityPlugin)this).Logger.LogInfo((object)"SpectatorCameraPlus v1.0.0 loaded!");
		}

		private void InitConfig()
		{
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: Expected O, but got Unknown
			//IL_006b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0075: Expected O, but got Unknown
			//IL_00c8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d2: Expected O, but got Unknown
			//IL_0105: Unknown result type (might be due to invalid IL or missing references)
			//IL_010f: Expected O, but got Unknown
			//IL_0162: Unknown result type (might be due to invalid IL or missing references)
			//IL_016c: Expected O, but got Unknown
			//IL_019f: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a9: Expected O, but got Unknown
			//IL_01dc: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e6: Expected O, but got Unknown
			PositionSmoothTime = ((BaseUnityPlugin)this).Config.Bind<float>("Smoothing", "PositionSmoothTime", 0.15f, new ConfigDescription("Position smoothing time in seconds (lower = snappier, higher = smoother)", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.01f, 1f), Array.Empty<object>()));
			RotationSmoothTime = ((BaseUnityPlugin)this).Config.Bind<float>("Smoothing", "RotationSmoothTime", 0.1f, new ConfigDescription("Rotation smoothing time in seconds (lower = snappier, higher = smoother)", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.01f, 1f), Array.Empty<object>()));
			SmoothingEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("Smoothing", "Enabled", true, "Enable camera smoothing for a less jarring spectator view");
			FieldOfView = ((BaseUnityPlugin)this).Config.Bind<float>("Camera", "FieldOfView", 90f, new ConfigDescription("Spectator camera field of view", (AcceptableValueBase)(object)new AcceptableValueRange<float>(30f, 120f), Array.Empty<object>()));
			NearClipPlane = ((BaseUnityPlugin)this).Config.Bind<float>("Camera", "NearClipPlane", 0.01f, new ConfigDescription("Near clip plane distance (lower = less clipping through nearby objects)", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.001f, 0.3f), Array.Empty<object>()));
			StabilizationEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("Stabilization", "Enabled", true, "Enable camera stabilization to reduce shakiness from rapid head movements");
			StabilizationStrength = ((BaseUnityPlugin)this).Config.Bind<float>("Stabilization", "Strength", 0.7f, new ConfigDescription("How much to dampen rapid movements (0 = none, 1 = maximum)", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1f), Array.Empty<object>()));
			RotationDeadzone = ((BaseUnityPlugin)this).Config.Bind<float>("Stabilization", "RotationDeadzone", 2f, new ConfigDescription("Ignore rotation changes smaller than this (degrees per second)", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 15f), Array.Empty<object>()));
			PositionDeadzone = ((BaseUnityPlugin)this).Config.Bind<float>("Stabilization", "PositionDeadzone", 0.01f, new ConfigDescription("Ignore position changes smaller than this (meters per second)", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 0.1f), Array.Empty<object>()));
		}

		private void Update()
		{
			if (!((Object)(object)_cameraController != (Object)null) && (!((Object)(object)Camera.main == (Object)null) || Camera.allCamerasCount != 0))
			{
				_cameraController = SpectatorCameraController.Create();
				((BaseUnityPlugin)this).Logger.LogInfo((object)"SpectatorCameraController initialized");
			}
		}
	}
	public static class PluginInfo
	{
		public const string PLUGIN_GUID = "com.mrbub.spectatorcameraplus";

		public const string PLUGIN_NAME = "SpectatorCameraPlus";

		public const string PLUGIN_VERSION = "1.0.0";
	}
	public class SpectatorCameraController : MonoBehaviour
	{
		private Camera _spectatorCamera;

		private Transform _targetTransform;

		private Camera _vrCamera;

		private Vector3 _currentVelocity;

		private Vector3 _smoothedPosition;

		private Quaternion _smoothedRotation;

		private bool _initialized;

		private Vector3 _lastTargetPosition;

		private Quaternion _lastTargetRotation;

		private Vector3 _stabilizedTargetPosition;

		private Quaternion _stabilizedTargetRotation;

		private Vector3 _positionVelocity;

		private float _angularVelocity;

		public static SpectatorCameraController Create()
		{
			//IL_0005: 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_0010: Expected O, but got Unknown
			GameObject val = new GameObject("SpectatorCameraPlus");
			Object.DontDestroyOnLoad((Object)val);
			return val.AddComponent<SpectatorCameraController>();
		}

		private void Awake()
		{
			_spectatorCamera = ((Component)this).gameObject.AddComponent<Camera>();
			_spectatorCamera.stereoTargetEye = (StereoTargetEyeMask)0;
			_spectatorCamera.depth = 100f;
			_spectatorCamera.fieldOfView = Plugin.FieldOfView.Value;
			_spectatorCamera.targetTexture = null;
			Plugin.Log.LogInfo((object)"Spectator camera created");
		}

		private void Start()
		{
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: 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_0037: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			//IL_0059: 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_0076: Unknown result type (might be due to invalid IL or missing references)
			//IL_007b: Unknown result type (might be due to invalid IL or missing references)
			FindTargetTransform();
			CopyVRCameraSettings();
			if ((Object)(object)_targetTransform != (Object)null)
			{
				_smoothedPosition = _targetTransform.position;
				_smoothedRotation = _targetTransform.rotation;
				_lastTargetPosition = _targetTransform.position;
				_lastTargetRotation = _targetTransform.rotation;
				_stabilizedTargetPosition = _targetTransform.position;
				_stabilizedTargetRotation = _targetTransform.rotation;
				_initialized = true;
			}
		}

		private void CopyVRCameraSettings()
		{
			//IL_006a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0080: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)_spectatorCamera == (Object)null))
			{
				_spectatorCamera.nearClipPlane = Plugin.NearClipPlane.Value;
				if ((Object)(object)_vrCamera != (Object)null)
				{
					_spectatorCamera.farClipPlane = _vrCamera.farClipPlane;
					_spectatorCamera.cullingMask = _vrCamera.cullingMask;
					_spectatorCamera.clearFlags = _vrCamera.clearFlags;
					_spectatorCamera.backgroundColor = _vrCamera.backgroundColor;
				}
			}
		}

		private void FindTargetTransform()
		{
			//IL_00ad: Unknown result type (might be due to invalid IL or missing references)
			XROrigin val = Object.FindObjectOfType<XROrigin>();
			if ((Object)(object)val != (Object)null && (Object)(object)val.Camera != (Object)null)
			{
				_targetTransform = ((Component)val.Camera).transform;
				_vrCamera = val.Camera;
				Plugin.Log.LogInfo((object)("Target found via XROrigin: " + ((Object)_targetTransform).name));
				return;
			}
			Camera main = Camera.main;
			if ((Object)(object)main != (Object)null)
			{
				_targetTransform = ((Component)main).transform;
				_vrCamera = main;
				Plugin.Log.LogInfo((object)("Target found via Camera.main: " + ((Object)_targetTransform).name));
				return;
			}
			Camera[] allCameras = Camera.allCameras;
			foreach (Camera val2 in allCameras)
			{
				if ((int)val2.stereoTargetEye != 0)
				{
					_targetTransform = ((Component)val2).transform;
					_vrCamera = val2;
					Plugin.Log.LogInfo((object)("Target found via stereo camera: " + ((Object)_targetTransform).name));
					return;
				}
			}
			if (Camera.allCamerasCount > 0)
			{
				Camera val3 = Camera.allCameras[0];
				_targetTransform = ((Component)val3).transform;
				_vrCamera = val3;
				Plugin.Log.LogInfo((object)("Fallback target: " + ((Object)_targetTransform).name));
			}
		}

		private void LateUpdate()
		{
			//IL_0024: 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_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_0046: 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_0057: Unknown result type (might be due to invalid IL or missing references)
			//IL_005c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_006d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0079: Unknown result type (might be due to invalid IL or missing references)
			//IL_007e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d8: 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_00e4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e9: Unknown result type (might be due to invalid IL or missing references)
			//IL_0175: Unknown result type (might be due to invalid IL or missing references)
			//IL_0181: 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_0189: 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_0190: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fd: Unknown result type (might be due to invalid IL or missing references)
			//IL_010e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0113: Unknown result type (might be due to invalid IL or missing references)
			//IL_011a: Unknown result type (might be due to invalid IL or missing references)
			//IL_011f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0141: Unknown result type (might be due to invalid IL or missing references)
			//IL_0146: 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_0163: 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_01ad: 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)
			if ((Object)(object)_targetTransform == (Object)null)
			{
				FindTargetTransform();
				return;
			}
			if (!_initialized)
			{
				_smoothedPosition = _targetTransform.position;
				_smoothedRotation = _targetTransform.rotation;
				_lastTargetPosition = _targetTransform.position;
				_lastTargetRotation = _targetTransform.rotation;
				_stabilizedTargetPosition = _targetTransform.position;
				_stabilizedTargetRotation = _targetTransform.rotation;
				_initialized = true;
				CopyVRCameraSettings();
			}
			_spectatorCamera.fieldOfView = Plugin.FieldOfView.Value;
			_spectatorCamera.nearClipPlane = Plugin.NearClipPlane.Value;
			Vector3 stabilizedPos;
			Quaternion stabilizedRot;
			if (Plugin.StabilizationEnabled.Value)
			{
				ApplyStabilization(out stabilizedPos, out stabilizedRot);
			}
			else
			{
				stabilizedPos = _targetTransform.position;
				stabilizedRot = _targetTransform.rotation;
			}
			if (Plugin.SmoothingEnabled.Value)
			{
				_smoothedPosition = Vector3.SmoothDamp(_smoothedPosition, stabilizedPos, ref _currentVelocity, Plugin.PositionSmoothTime.Value);
				_smoothedRotation = Quaternion.Slerp(_smoothedRotation, stabilizedRot, 1f - Mathf.Exp(-10f / Plugin.RotationSmoothTime.Value * Time.deltaTime));
				((Component)this).transform.position = _smoothedPosition;
				((Component)this).transform.rotation = _smoothedRotation;
			}
			else
			{
				((Component)this).transform.position = stabilizedPos;
				((Component)this).transform.rotation = stabilizedRot;
				_smoothedPosition = stabilizedPos;
				_smoothedRotation = stabilizedRot;
			}
			_lastTargetPosition = _targetTransform.position;
			_lastTargetRotation = _targetTransform.rotation;
		}

		private void ApplyStabilization(out Vector3 stabilizedPos, out Quaternion stabilizedRot)
		{
			//IL_0038: 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)
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_004c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0051: Unknown result type (might be due to invalid IL or missing references)
			//IL_0057: Unknown result type (might be due to invalid IL or missing references)
			//IL_0062: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_00af: 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_00c1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d2: 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)
			//IL_013e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0149: Unknown result type (might be due to invalid IL or missing references)
			//IL_0150: Unknown result type (might be due to invalid IL or missing references)
			//IL_0155: Unknown result type (might be due to invalid IL or missing references)
			//IL_015c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0161: Unknown result type (might be due to invalid IL or missing references)
			//IL_00eb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f0: Unknown result type (might be due to invalid IL or missing references)
			float deltaTime = Time.deltaTime;
			if (deltaTime <= 0f)
			{
				stabilizedPos = _stabilizedTargetPosition;
				stabilizedRot = _stabilizedTargetRotation;
				return;
			}
			float value = Plugin.StabilizationStrength.Value;
			Vector3 val = _targetTransform.position - _lastTargetPosition;
			_positionVelocity = val / deltaTime;
			float num = Quaternion.Angle(_lastTargetRotation, _targetTransform.rotation);
			_angularVelocity = num / deltaTime;
			if (((Vector3)(ref _positionVelocity)).magnitude < Plugin.PositionDeadzone.Value)
			{
				stabilizedPos = _stabilizedTargetPosition;
			}
			else
			{
				float num2 = Mathf.Lerp(1f, 0.1f, value);
				_stabilizedTargetPosition = Vector3.Lerp(_stabilizedTargetPosition, _targetTransform.position, num2);
				stabilizedPos = _stabilizedTargetPosition;
			}
			if (_angularVelocity < Plugin.RotationDeadzone.Value)
			{
				stabilizedRot = _stabilizedTargetRotation;
				return;
			}
			float num3 = (_angularVelocity - Plugin.RotationDeadzone.Value) / 90f;
			num3 = Mathf.Clamp01(num3);
			float num4 = Mathf.Lerp(0.05f, 1f, num3) * Mathf.Lerp(1f, 0.3f, value);
			_stabilizedTargetRotation = Quaternion.Slerp(_stabilizedTargetRotation, _targetTransform.rotation, num4);
			stabilizedRot = _stabilizedTargetRotation;
		}

		public void SnapToTarget()
		{
			//IL_0016: 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_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_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: 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_004e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			//IL_0059: 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_0076: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)_targetTransform == (Object)null))
			{
				_smoothedPosition = _targetTransform.position;
				_smoothedRotation = _targetTransform.rotation;
				_stabilizedTargetPosition = _targetTransform.position;
				_stabilizedTargetRotation = _targetTransform.rotation;
				_currentVelocity = Vector3.zero;
				((Component)this).transform.position = _smoothedPosition;
				((Component)this).transform.rotation = _smoothedRotation;
			}
		}
	}
}