using System;
using System.Drawing;
using System.Drawing.Imaging;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;
using System.Data;
using Microsoft.DirectX;
using Microsoft.DirectX.Direct3D;
using System.Runtime.InteropServices;

namespace Sample10_FlashTexture
{
	/// <summary>
	/// Summary description for Form1.
	/// </summary>
	public class Form1 : System.Windows.Forms.Form
	{
		/// <summary>
		/// Required designer variable.
		/// </summary>
		private System.ComponentModel.Container components = null;

		public Form1()
		{
			//
			// Required for Windows Form Designer support
			//
			InitializeComponent();

			//
			// TODO: Add any constructor code after InitializeComponent call
			//
		}

		/// <summary>
		/// Clean up any resources being used.
		/// </summary>
		protected override void Dispose( bool disposing )
		{
			if( disposing )
			{
				if (components != null) 
				{
					components.Dispose();
				}
			}
			base.Dispose( disposing );
		}

		#region Windows Form Designer generated code
		/// <summary>
		/// Required method for Designer support - do not modify
		/// the contents of this method with the code editor.
		/// </summary>
		private void InitializeComponent()
		{
			this.timer1 = new System.Timers.Timer();
			this.f_in_box__control1 = new f_in_box__lib.f_in_box__control();
			((System.ComponentModel.ISupportInitialize)(this.timer1)).BeginInit();
			this.SuspendLayout();
			// 
			// timer1
			// 
			this.timer1.Enabled = true;
			this.timer1.SynchronizingObject = this;
			this.timer1.Elapsed += new System.Timers.ElapsedEventHandler(this.timer1_Elapsed);
			// 
			// f_in_box__control1
			// 
			this.f_in_box__control1.Context = null;
			this.f_in_box__control1.FlashProperty_AlignMode = 0;
			this.f_in_box__control1.FlashProperty_AllowScriptAccess = "";
			this.f_in_box__control1.FlashProperty_BackgroundColor = -1;
			this.f_in_box__control1.FlashProperty_Base = "";
			this.f_in_box__control1.FlashProperty_BGColor = "";
			this.f_in_box__control1.FlashProperty_DeviceFont = false;
			this.f_in_box__control1.FlashProperty_EmbedMovie = false;
			this.f_in_box__control1.FlashProperty_FlashVars = "";
			this.f_in_box__control1.FlashProperty_FrameNum = -1;
			this.f_in_box__control1.FlashProperty_Loop = true;
			this.f_in_box__control1.FlashProperty_Menu = true;
			this.f_in_box__control1.FlashProperty_Movie = "";
			this.f_in_box__control1.FlashProperty_MovieData = "";
			this.f_in_box__control1.FlashProperty_Playing = true;
			this.f_in_box__control1.FlashProperty_Quality = 1;
			this.f_in_box__control1.FlashProperty_Quality2 = "High";
			this.f_in_box__control1.FlashProperty_SAlign = "";
			this.f_in_box__control1.FlashProperty_Scale = "ShowAll";
			this.f_in_box__control1.FlashProperty_ScaleMode = 0;
			this.f_in_box__control1.FlashProperty_Stacking = "";
			this.f_in_box__control1.FlashProperty_SWRemote = "";
			this.f_in_box__control1.FlashProperty_WMode = "Transparent";
			this.f_in_box__control1.Location = new System.Drawing.Point(128, 111);
			this.f_in_box__control1.Name = "f_in_box__control1";
			this.f_in_box__control1.Size = new System.Drawing.Size(176, 168);
			this.f_in_box__control1.StandardMenu = false;
			this.f_in_box__control1.TabIndex = 2;
			this.f_in_box__control1.Text = "f_in_box__control1";
			this.f_in_box__control1.TransparentMode = true;
			this.f_in_box__control1.OnFlashPaint += new f_in_box__lib.f_in_box__control.OnFlashPaintEventHandler(this.f_in_box__control1_OnFlashPaint);
			this.f_in_box__control1.OnUpdateRect += new f_in_box__lib.f_in_box__control.OnUpdateRectEventHandler(this.f_in_box__control1_OnUpdateRect);
			// 
			// Form1
			// 
			this.AutoScaleBaseSize = new System.Drawing.Size(5, 13);
			this.ClientSize = new System.Drawing.Size(432, 390);
			this.Controls.Add(this.f_in_box__control1);
			this.Name = "Form1";
			this.Text = "Sample 10 - Flash Texture";
			this.Load += new System.EventHandler(this.Form1_Load);
			((System.ComponentModel.ISupportInitialize)(this.timer1)).EndInit();
			this.ResumeLayout(false);

		}
		#endregion

		/// <summary>
		/// The main entry point for the application.
		/// </summary>
		[STAThread]
		static void Main() 
		{
			Application.Run(new Form1());
		}

		private Device _Device = null; 
		private const int nVertices = 5; 
		private VertexBuffer _VertexBuffer = null;
		private IndexBuffer _IndexBuffer = null; 
		private CustomVertex.PositionTextured[] vertex = new CustomVertex.PositionTextured[nVertices];
		private static short[] indices = {
											 4, 0, 3,
											 4, 1, 0, 
											 4, 2, 1, 
											 4, 3, 2
										 };
		private Vector3 _Camera = new Vector3(0, 0, -5);
		private Vector3 _At = new Vector3(0, 0, 0);
		private Vector3 _Up = new Vector3(0, 1, 0);
		private float _FieldOfView = (float)Math.PI / 4;
		private float _Hither = 2f;
		private float _Yon = 50f;
		private float _Angle = 1f;
		private bool _DeviceState = true;
		private bool _DeviceLost = false;

		private System.Timers.Timer timer1;
		public f_in_box__lib.f_in_box__control f_in_box__control1;

		PresentParameters _PresentParameters = new PresentParameters();

		const int _Width = 256;
		const int _Height = 256;

		private bool Started = false;

		private void Form1_Load(object sender, System.EventArgs e)
		{
			vertex[0] = new CustomVertex.PositionTextured( -1.0f, +1.0f, 0.0f, 0, 1 );
			vertex[1] = new CustomVertex.PositionTextured( -1.0f, -1.0f, 0.0f, 0, 0 );
			vertex[2] = new CustomVertex.PositionTextured( +1.0f, -1.0f, 0.0f, 1, 0 );
			vertex[3] = new CustomVertex.PositionTextured( +1.0f, +1.0f, 0.0f, 1, 1 );
			vertex[4] = new CustomVertex.PositionTextured( 0.0f, 0.0f, 5.0f / (float)Math.Sqrt(2), 0.5f, 0.5f );

			_PresentParameters.Windowed = true;
			_PresentParameters.SwapEffect = SwapEffect.Discard;
			_PresentParameters.EnableAutoDepthStencil = true;
			_PresentParameters.AutoDepthStencilFormat = DepthFormat.D16;

			_Device = new Device(0, DeviceType.Hardware, this, CreateFlags.SoftwareVertexProcessing, _PresentParameters);

			_Device.DeviceReset += new EventHandler(OnCreateDevice);
			_Device.DeviceResizing += new CancelEventHandler(OnDeviceResize);

			OnCreateDevice(_Device, null);

			f_in_box__control1.TransparentMode = true;
			f_in_box__control1.Width = _Width;
			f_in_box__control1.Height = _Height;
			f_in_box__control1.PutMovieFromStream(this.GetType().Assembly.GetManifestResourceStream("Sample10_FlashTexture.movie.swf"));
			f_in_box__control1.FlashMethod_Play();
			f_in_box__control1.Visible = false;
			f_in_box__control1.FlashProperty_BackgroundColor = 0xffff00;

			Started = true;
		}

		private void OnCreateDevice(object sender, EventArgs e) 
		{
			timer1.Enabled = false;

			SetUpCamera();

			_VertexBuffer = 
				new VertexBuffer(
					typeof(CustomVertex.PositionTextured ), 
					nVertices, 
					_Device, 
					Usage.Dynamic | Usage.WriteOnly, 
					CustomVertex.PositionTextured.Format, 
					Pool.Default);

			_IndexBuffer = 
				new IndexBuffer(
					typeof(short), 
					indices.Length, 
					_Device, 
					Usage.WriteOnly, 
					Pool.Default);

			if (null == e) 
			{
				_VertexBuffer.Created += new EventHandler(OnVertexBufferCreate);
				_IndexBuffer.Created += new EventHandler(OnIndexBufferCreate);

				OnVertexBufferCreate(_VertexBuffer, null);
				OnIndexBufferCreate(_IndexBuffer, null);
			} 
		}
 
		private void OnVertexBufferCreate(object sender, EventArgs e) 
		{
			_VertexBuffer.SetData(vertex, 0, LockFlags.None);
		}
      
		private void OnIndexBufferCreate(object sender, EventArgs e) 
		{
			_IndexBuffer.SetData(indices, 0, LockFlags.None);

			timer1.Enabled = true;
		}       
    
		private void OnDeviceResize(object sender, CancelEventArgs e) 
		{
			_DeviceState = !_DeviceState;
		}     
   
		private void SetUpCamera()  
		{
			float AspectRatio = (float)ClientSize.Width / (float)ClientSize.Height; 

			_Device.Transform.Projection = 
				Matrix.PerspectiveFovLH((float)_FieldOfView, AspectRatio, (float)_Hither, (float)_Yon);         

			_Device.Transform.View = Matrix.LookAtLH(_Camera, _At, _Up);
			
			_Device.RenderState.Lighting = false;
		}

		void AttemptRecovery()
		{
			try
			{
				_Device.TestCooperativeLevel(); 
			}
			catch (DeviceLostException)
			{
			}
			catch (DeviceNotResetException)
			{
				try
				{
					_Device.Reset(_PresentParameters); 
					_DeviceLost = false; 
				} 
				catch (DeviceLostException)
				{   
				}
			}
		}

		Texture _FlashTexture = null;
		System.Drawing.Rectangle _UpdatedRect;

		[DllImport("user32.dll", EntryPoint = "SendMessageA", CallingConvention = CallingConvention.StdCall)]
		public static extern int SendMessage(IntPtr hWnd, uint uMsg, int wParam, int lParam);
		private const int WM_PAINT = 0x000f;

		private void f_in_box__control1_OnUpdateRect(object sender, System.Drawing.Rectangle UpdatedRect)
		{
			f_in_box__lib.f_in_box__control f_in_box__control = (f_in_box__lib.f_in_box__control)sender;

			_UpdatedRect = UpdatedRect;

			SendMessage(f_in_box__control.Handle, WM_PAINT, 0, 0);
		}

		private void f_in_box__control1_OnFlashPaint(object sender, System.IntPtr pPixelPointer)
		{
			if (!Started)
				return;

			f_in_box__lib.f_in_box__control f_in_box__control = (f_in_box__lib.f_in_box__control)sender;

			if (null == _FlashTexture)
				_FlashTexture = new Texture(_Device, _Width, _Height, 1, Usage.None, Format.A8R8G8B8, Pool.Managed);

			GraphicsStream gs = _FlashTexture.LockRectangle(0, LockFlags.Discard);
			byte[] pixels = new byte[_Width * _Height * 4];
			System.Runtime.InteropServices.Marshal.Copy(pPixelPointer, pixels, 0, _Width * _Height * 4);

			gs.Write(pixels, 0, pixels.Length);

			_FlashTexture.UnlockRectangle(0);
		}

		private void timer1_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
		{
			if (null == _Device)
				return;

			if (_DeviceLost)
				AttemptRecovery(); 

			if (null == _FlashTexture)
				return;

			try
			{
				_Device.Clear(ClearFlags.Target | ClearFlags.ZBuffer, Color.Khaki, 1f, 0);     
				_Device.BeginScene();

				_Device.VertexFormat = CustomVertex.PositionTextured.Format;

				_Device.SetTexture(0, _FlashTexture);
					
				_Device.SetStreamSource(0, _VertexBuffer, 0);
				_Device.Indices = _IndexBuffer;

				_Angle += 0.05f;
				if (_Angle > 360)
					_Angle = 1f;

				_Device.Transform.World = Matrix.RotationYawPitchRoll(0, -.75f, _Angle);

				_Device.DrawIndexedPrimitives(PrimitiveType.TriangleList, 0, 0, nVertices, 0, indices.Length /3);

				_Device.EndScene();
				
				_Device.Present();
			}

			catch (DeviceLostException)
			{
				_DeviceLost = true; 
			}
		}
	}
}
