using System;
using UnityEngine;

namespace RenderHeads.Media.AVProVideo
{
	[AddComponentMenu("AVPro Video/Apply To Mesh", 300)]
	[HelpURL("http://renderheads.com/product/avpro-video/")]
	public class ApplyToMesh : MonoBehaviour
	{
		public MediaPlayer Player
		{
			get
			{
				return this._media;
			}
			set
			{
				if (this._media != value)
				{
					this._media = value;
					this._isDirty = true;
				}
			}
		}

		public Texture2D DefaultTexture
		{
			get
			{
				return this._defaultTexture;
			}
			set
			{
				if (this._defaultTexture != value)
				{
					this._defaultTexture = value;
					this._isDirty = true;
				}
			}
		}

		public Renderer MeshRenderer
		{
			get
			{
				return this._mesh;
			}
			set
			{
				if (this._mesh != value)
				{
					this._mesh = value;
					this._isDirty = true;
				}
			}
		}

		public string TexturePropertyName
		{
			get
			{
				return this._texturePropertyName;
			}
			set
			{
				if (this._texturePropertyName != value)
				{
					this._texturePropertyName = value;
					this._propTexture = Shader.PropertyToID(this._texturePropertyName);
					this._isDirty = true;
				}
			}
		}

		public Vector2 Offset
		{
			get
			{
				return this._offset;
			}
			set
			{
				if (this._offset != value)
				{
					this._offset = value;
					this._isDirty = true;
				}
			}
		}

		public Vector2 Scale
		{
			get
			{
				return this._scale;
			}
			set
			{
				if (this._scale != value)
				{
					this._scale = value;
					this._isDirty = true;
				}
			}
		}

		public void ForceUpdate()
		{
			this._isDirty = true;
			this.LateUpdate();
		}

		private void Awake()
		{
			if (ApplyToMesh._propStereo == 0 || ApplyToMesh._propAlphaPack == 0)
			{
				ApplyToMesh._propStereo = Shader.PropertyToID("Stereo");
				ApplyToMesh._propAlphaPack = Shader.PropertyToID("AlphaPack");
				ApplyToMesh._propApplyGamma = Shader.PropertyToID("_ApplyGamma");
			}
			if (ApplyToMesh._propChromaTex == 0)
			{
				ApplyToMesh._propChromaTex = Shader.PropertyToID("_ChromaTex");
			}
			if (ApplyToMesh._propUseYpCbCr == 0)
			{
				ApplyToMesh._propUseYpCbCr = Shader.PropertyToID("_UseYpCbCr");
			}
		}

		private void LateUpdate()
		{
			bool flag = false;
			if (this._media != null && this._media.TextureProducer != null)
			{
				Texture texture = (this._media.FrameResampler != null && this._media.FrameResampler.OutputTexture != null) ? this._media.FrameResampler.OutputTexture[0] : null;
				Texture texture2 = (!this._media.m_Resample) ? this._media.TextureProducer.GetTexture(0) : texture;
				if (texture2 != null)
				{
					if (texture2 != this._lastTextureApplied)
					{
						this._isDirty = true;
					}
					if (this._isDirty)
					{
						int num = (!this._media.m_Resample) ? this._media.TextureProducer.GetTextureCount() : 1;
						for (int i = 0; i < num; i++)
						{
							Texture texture3 = (this._media.FrameResampler != null && this._media.FrameResampler.OutputTexture != null) ? this._media.FrameResampler.OutputTexture[i] : null;
							texture2 = ((!this._media.m_Resample) ? this._media.TextureProducer.GetTexture(i) : texture3);
							if (texture2 != null)
							{
								this.ApplyMapping(texture2, this._media.TextureProducer.RequiresVerticalFlip(), i);
							}
						}
					}
					flag = true;
				}
			}
			if (!flag)
			{
				if (this._defaultTexture != this._lastTextureApplied)
				{
					this._isDirty = true;
				}
				if (this._isDirty)
				{
					this.ApplyMapping(this._defaultTexture, false, 0);
				}
			}
		}

		private void ApplyMapping(Texture texture, bool requiresYFlip, int plane = 0)
		{
			if (this._mesh != null)
			{
				this._isDirty = false;
				Material[] materials = this._mesh.materials;
				if (materials != null)
				{
					foreach (Material material in materials)
					{
						if (material != null)
						{
							if (plane == 0)
							{
								material.SetTexture(this._propTexture, texture);
								this._lastTextureApplied = texture;
								if (texture != null)
								{
									if (requiresYFlip)
									{
										material.SetTextureScale(this._propTexture, new Vector2(this._scale.x, -this._scale.y));
										material.SetTextureOffset(this._propTexture, Vector2.up + this._offset);
									}
									else
									{
										material.SetTextureScale(this._propTexture, this._scale);
										material.SetTextureOffset(this._propTexture, this._offset);
									}
								}
							}
							else if (plane == 1 && material.HasProperty(ApplyToMesh._propUseYpCbCr) && material.HasProperty(ApplyToMesh._propChromaTex))
							{
								material.EnableKeyword("USE_YPCBCR");
								material.SetTexture(ApplyToMesh._propChromaTex, texture);
								if (requiresYFlip)
								{
									material.SetTextureScale(ApplyToMesh._propChromaTex, new Vector2(this._scale.x, -this._scale.y));
									material.SetTextureOffset(ApplyToMesh._propChromaTex, Vector2.up + this._offset);
								}
								else
								{
									material.SetTextureScale(ApplyToMesh._propChromaTex, this._scale);
									material.SetTextureOffset(ApplyToMesh._propChromaTex, this._offset);
								}
							}
							if (this._media != null)
							{
								if (material.HasProperty(ApplyToMesh._propStereo))
								{
									Helper.SetupStereoMaterial(material, this._media.m_StereoPacking, this._media.m_DisplayDebugStereoColorTint);
								}
								if (material.HasProperty(ApplyToMesh._propAlphaPack))
								{
									Helper.SetupAlphaPackedMaterial(material, this._media.m_AlphaPacking);
								}
								if (material.HasProperty(ApplyToMesh._propApplyGamma) && this._media.Info != null)
								{
									Helper.SetupGammaMaterial(material, this._media.Info.PlayerSupportsLinearColorSpace());
								}
							}
						}
					}
				}
			}
		}

		private void OnEnable()
		{
			if (this._mesh == null)
			{
				this._mesh = base.GetComponent<MeshRenderer>();
				if (this._mesh == null)
				{
					Debug.LogWarning("[AVProVideo] No mesh renderer set or found in gameobject");
				}
			}
			this._propTexture = Shader.PropertyToID(this._texturePropertyName);
			this._isDirty = true;
			if (this._mesh != null)
			{
				this.LateUpdate();
			}
		}

		private void OnDisable()
		{
			this.ApplyMapping(this._defaultTexture, false, 0);
		}

		[Header("Media Source")]
		[SerializeField]
		private MediaPlayer _media;

		[Tooltip("Default texture to display when the video texture is preparing")]
		[SerializeField]
		private Texture2D _defaultTexture;

		[Space(8f)]
		[Header("Renderer Target")]
		[SerializeField]
		private Renderer _mesh;

		[SerializeField]
		private string _texturePropertyName = "_MainTex";

		[SerializeField]
		private Vector2 _offset = Vector2.zero;

		[SerializeField]
		private Vector2 _scale = Vector2.one;

		private bool _isDirty;

		private Texture _lastTextureApplied;

		private int _propTexture;

		private static int _propStereo;

		private static int _propAlphaPack;

		private static int _propApplyGamma;

		private const string PropChromaTexName = "_ChromaTex";

		private static int _propChromaTex;

		private const string PropUseYpCbCrName = "_UseYpCbCr";

		private static int _propUseYpCbCr;
	}
}
