using System;
using System.Collections;
using System.IO;
using System.Runtime.InteropServices;
using UnityEngine;
using Valve.VR;

public class SteamVR_Render : MonoBehaviour
{
	public static EVREye eye { get; private set; }

	public static SteamVR_Render instance
	{
		get
		{
			if (SteamVR_Render._instance == null)
			{
				SteamVR_Render._instance = UnityEngine.Object.FindObjectOfType<SteamVR_Render>();
				if (SteamVR_Render._instance == null)
				{
					SteamVR_Render._instance = new GameObject("[SteamVR]").AddComponent<SteamVR_Render>();
				}
			}
			return SteamVR_Render._instance;
		}
	}

	private void OnDestroy()
	{
		SteamVR_Render._instance = null;
	}

	private void OnApplicationQuit()
	{
		SteamVR_Render.isQuitting = true;
		SteamVR.SafeDispose();
	}

	public static void Add(SteamVR_Camera vrcam)
	{
		if (!SteamVR_Render.isQuitting)
		{
			SteamVR_Render.instance.AddInternal(vrcam);
		}
	}

	public static void Remove(SteamVR_Camera vrcam)
	{
		if (!SteamVR_Render.isQuitting && SteamVR_Render._instance != null)
		{
			SteamVR_Render.instance.RemoveInternal(vrcam);
		}
	}

	public static SteamVR_Camera Top()
	{
		if (!SteamVR_Render.isQuitting)
		{
			return SteamVR_Render.instance.TopInternal();
		}
		return null;
	}

	private void AddInternal(SteamVR_Camera vrcam)
	{
		Camera component = vrcam.GetComponent<Camera>();
		int num = this.cameras.Length;
		SteamVR_Camera[] array = new SteamVR_Camera[num + 1];
		int num2 = 0;
		for (int i = 0; i < num; i++)
		{
			Camera component2 = this.cameras[i].GetComponent<Camera>();
			if (i == num2 && component2.depth > component.depth)
			{
				array[num2++] = vrcam;
			}
			array[num2++] = this.cameras[i];
		}
		if (num2 == num)
		{
			array[num2] = vrcam;
		}
		this.cameras = array;
	}

	private void RemoveInternal(SteamVR_Camera vrcam)
	{
		int num = this.cameras.Length;
		int num2 = 0;
		for (int i = 0; i < num; i++)
		{
			SteamVR_Camera x = this.cameras[i];
			if (x == vrcam)
			{
				num2++;
			}
		}
		if (num2 == 0)
		{
			return;
		}
		SteamVR_Camera[] array = new SteamVR_Camera[num - num2];
		int num3 = 0;
		for (int j = 0; j < num; j++)
		{
			SteamVR_Camera steamVR_Camera = this.cameras[j];
			if (steamVR_Camera != vrcam)
			{
				array[num3++] = steamVR_Camera;
			}
		}
		this.cameras = array;
	}

	private SteamVR_Camera TopInternal()
	{
		if (this.cameras.Length > 0)
		{
			return this.cameras[this.cameras.Length - 1];
		}
		return null;
	}

	public static bool pauseRendering
	{
		get
		{
			return SteamVR_Render._pauseRendering;
		}
		set
		{
			SteamVR_Render._pauseRendering = value;
			CVRCompositor compositor = OpenVR.Compositor;
			if (compositor != null)
			{
				compositor.SuspendRendering(value);
			}
		}
	}

	private IEnumerator RenderLoop()
	{
		for (;;)
		{
			yield return new WaitForEndOfFrame();
			if (!SteamVR_Render.pauseRendering)
			{
				CVRCompositor compositor = OpenVR.Compositor;
				if (compositor != null)
				{
					if (!compositor.CanRenderScene())
					{
						continue;
					}
					compositor.SetTrackingSpace(this.trackingSpace);
				}
				SteamVR_Overlay overlay = SteamVR_Overlay.instance;
				if (overlay != null)
				{
					overlay.UpdateOverlay();
				}
				this.RenderExternalCamera();
			}
		}
		yield break;
	}

	private void RenderExternalCamera()
	{
		if (this.externalCamera == null)
		{
			return;
		}
		if (!this.externalCamera.gameObject.activeInHierarchy)
		{
			return;
		}
		int num = (int)Mathf.Max(this.externalCamera.config.frameSkip, 0f);
		if (Time.frameCount % (num + 1) != 0)
		{
			return;
		}
		this.externalCamera.AttachToCamera(this.TopInternal());
		this.externalCamera.RenderNear();
		this.externalCamera.RenderFar();
	}

	private void OnInputFocus(params object[] args)
	{
		bool flag = (bool)args[0];
		if (flag)
		{
			if (this.pauseGameWhenDashboardIsVisible)
			{
				Time.timeScale = this.timeScale;
			}
			SteamVR_Camera.sceneResolutionScale = this.sceneResolutionScale;
		}
		else
		{
			if (this.pauseGameWhenDashboardIsVisible)
			{
				this.timeScale = Time.timeScale;
				Time.timeScale = 0f;
			}
			this.sceneResolutionScale = SteamVR_Camera.sceneResolutionScale;
			SteamVR_Camera.sceneResolutionScale = 0.5f;
		}
	}

	private void OnQuit(params object[] args)
	{
		Application.Quit();
	}

	private void OnEnable()
	{
		base.StartCoroutine("RenderLoop");
		SteamVR_Utils.Event.Listen("input_focus", new SteamVR_Utils.Event.Handler(this.OnInputFocus));
		SteamVR_Utils.Event.Listen("Quit", new SteamVR_Utils.Event.Handler(this.OnQuit));
	}

	private void OnDisable()
	{
		base.StopAllCoroutines();
		SteamVR_Utils.Event.Remove("input_focus", new SteamVR_Utils.Event.Handler(this.OnInputFocus));
		SteamVR_Utils.Event.Remove("Quit", new SteamVR_Utils.Event.Handler(this.OnQuit));
	}

	private void Awake()
	{
		if (this.externalCamera == null && File.Exists(this.externalCameraConfigPath))
		{
			GameObject original = Resources.Load<GameObject>("SteamVR_ExternalCamera");
			GameObject gameObject = UnityEngine.Object.Instantiate<GameObject>(original);
			gameObject.gameObject.name = "External Camera";
			this.externalCamera = gameObject.transform.GetChild(0).GetComponent<SteamVR_ExternalCamera>();
			this.externalCamera.configPath = this.externalCameraConfigPath;
			this.externalCamera.ReadConfig();
		}
	}

	private void FixedUpdate()
	{
	}

	private void Update()
	{
		if (this.poseUpdater == null)
		{
			this.poseUpdater = new GameObject("poseUpdater")
			{
				transform = 
				{
					parent = base.transform
				}
			}.AddComponent<SteamVR_UpdatePoses>();
		}
		SteamVR_Controller.Update();
		CVRSystem system = OpenVR.System;
		if (system != null)
		{
			VREvent_t vrevent_t = default(VREvent_t);
			uint uncbVREvent = (uint)Marshal.SizeOf(typeof(VREvent_t));
			for (int i = 0; i < 64; i++)
			{
				if (!system.PollNextEvent(ref vrevent_t, uncbVREvent))
				{
					break;
				}
				EVREventType eventType = (EVREventType)vrevent_t.eventType;
				if (eventType != EVREventType.VREvent_InputFocusCaptured)
				{
					if (eventType != EVREventType.VREvent_InputFocusReleased)
					{
						if (eventType != EVREventType.VREvent_HideRenderModels)
						{
							if (eventType != EVREventType.VREvent_ShowRenderModels)
							{
								string name = Enum.GetName(typeof(EVREventType), vrevent_t.eventType);
								if (name != null)
								{
									SteamVR_Utils.Event.Send(name.Substring(8), new object[]
									{
										vrevent_t
									});
								}
							}
							else
							{
								SteamVR_Utils.Event.Send("hide_render_models", new object[]
								{
									false
								});
							}
						}
						else
						{
							SteamVR_Utils.Event.Send("hide_render_models", new object[]
							{
								true
							});
						}
					}
					else if (vrevent_t.data.process.pid == 0u)
					{
						SteamVR_Utils.Event.Send("input_focus", new object[]
						{
							true
						});
					}
				}
				else if (vrevent_t.data.process.oldPid == 0u)
				{
					SteamVR_Utils.Event.Send("input_focus", new object[]
					{
						false
					});
				}
			}
		}
		Application.targetFrameRate = -1;
		Application.runInBackground = true;
		QualitySettings.maxQueuedFrames = -1;
		QualitySettings.vSyncCount = 0;
		if (this.lockPhysicsUpdateRateToRenderFrequency && Time.timeScale > 0f)
		{
			SteamVR instance = SteamVR.instance;
			if (instance != null)
			{
				Compositor_FrameTiming compositor_FrameTiming = default(Compositor_FrameTiming);
				compositor_FrameTiming.m_nSize = (uint)Marshal.SizeOf(typeof(Compositor_FrameTiming));
				instance.compositor.GetFrameTiming(ref compositor_FrameTiming, 0u);
				Time.fixedDeltaTime = Time.timeScale / instance.hmd_DisplayFrequency;
				Time.maximumDeltaTime = Time.fixedDeltaTime * compositor_FrameTiming.m_nNumFramePresents;
			}
		}
	}

	public bool pauseGameWhenDashboardIsVisible = true;

	public bool lockPhysicsUpdateRateToRenderFrequency = true;

	public SteamVR_ExternalCamera externalCamera;

	public string externalCameraConfigPath = "externalcamera.cfg";

	public ETrackingUniverseOrigin trackingSpace = ETrackingUniverseOrigin.TrackingUniverseStanding;

	private static SteamVR_Render _instance;

	private static bool isQuitting;

	private SteamVR_Camera[] cameras = new SteamVR_Camera[0];

	public TrackedDevicePose_t[] poses = new TrackedDevicePose_t[16];

	public TrackedDevicePose_t[] gamePoses = new TrackedDevicePose_t[0];

	private static bool _pauseRendering;

	private float sceneResolutionScale = 1f;

	private float timeScale = 1f;

	private SteamVR_UpdatePoses poseUpdater;
}
