/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Copyright (c) 2013 Raytrix GmbH. All rights reserved.
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
#pragma once


namespace RxExampleApiCameraNet01 {

	using namespace System;
	using namespace System::ComponentModel;
	using namespace System::Collections;
	using namespace System::Windows::Forms;
	using namespace System::Data;
	using namespace System::Drawing;

	using namespace Rx::NET;
	using namespace Rx::ApiLF::NET;

	/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
	/// <summary>
	/// 	Summary for Form1
	/// 	
	/// 	WARNING: If you change the name of this class, you will need to change the
	/// 	         'Resource File Name' property for the managed resource compiler tool associated with all .resx files this
	/// 	         class depends on.  Otherwise, the designers will not be able to interact properly with localized resources
	/// 	         associated with this form.
	/// </summary>
	/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
	public ref class Form1 : public System::Windows::Forms::Form
	{
	private: System::Windows::Forms::Panel^  panelClu;


	public: 
		Form1(void)
		{
			InitializeComponent();
			//
			//TODO: Add the constructor code here
			//
			m_uRay = 0;
			m_uCamIdx = -1;
			bDisableToolEvents = false;
		}

	protected:

		/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>
		/// 	Clean up any resources being used.
		/// </summary>
		/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
		~Form1()
		{
			if (components)
			{
				delete components;
			}
		}

		// The CLUViz Control instance
		CLUViz::NET::ViewCtrl^ m_xCluView;

		// The CLUViz Engine instance
		CLUViz::NET::EngineCtrl^ m_xCluEngine;

		// This variable holds the handle to the currently loaded ray image
		unsigned int m_uRay;

		// The current selected cam index
		unsigned int m_uCamIdx;
		bool bDisableToolEvents;


	private:
		/// <summary>
		/// Required designer variable.
		/// </summary>

	private: System::ComponentModel::IContainer^  components;
	private: System::Windows::Forms::Panel^  panel1;
	private: System::Windows::Forms::GroupBox^  groupBox1;
	private: System::Windows::Forms::NumericUpDown^  UDFramerate;
	private: System::Windows::Forms::Label^  label1;
	private: System::Windows::Forms::ComboBox^  CBCameras;
	private: System::Windows::Forms::Label^  label3;
	private: System::Windows::Forms::Label^  label2;
	private: System::Windows::Forms::NumericUpDown^  UDExp;
	private: System::Windows::Forms::SplitContainer^  splitContainer1;
	private: System::Windows::Forms::Button^  butSingleCapture;
	private: System::Windows::Forms::Timer^  timer1;
	private: System::Windows::Forms::Button^  butStopVideo;
	private: System::Windows::Forms::Button^  butStartVideo;
	private: System::Windows::Forms::ToolStripContainer^  toolStripContainer1;
	private: System::Windows::Forms::StatusStrip^  statusStrip1;
	private: System::Windows::Forms::ToolStripStatusLabel^  toolFPS;
	private: System::Windows::Forms::SplitContainer^  splitContainer2;
	private: System::Windows::Forms::Panel^  panelStatus;
	private: System::Windows::Forms::RichTextBox^  rtboxStatus;


#pragma 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>
			 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
			 void InitializeComponent(void)
			 {
				 this->components = (gcnew System::ComponentModel::Container());
				 this->panelClu = (gcnew System::Windows::Forms::Panel());
				 this->panel1 = (gcnew System::Windows::Forms::Panel());
				 this->groupBox1 = (gcnew System::Windows::Forms::GroupBox());
				 this->butStopVideo = (gcnew System::Windows::Forms::Button());
				 this->butStartVideo = (gcnew System::Windows::Forms::Button());
				 this->butSingleCapture = (gcnew System::Windows::Forms::Button());
				 this->label3 = (gcnew System::Windows::Forms::Label());
				 this->label2 = (gcnew System::Windows::Forms::Label());
				 this->UDExp = (gcnew System::Windows::Forms::NumericUpDown());
				 this->UDFramerate = (gcnew System::Windows::Forms::NumericUpDown());
				 this->label1 = (gcnew System::Windows::Forms::Label());
				 this->CBCameras = (gcnew System::Windows::Forms::ComboBox());
				 this->splitContainer1 = (gcnew System::Windows::Forms::SplitContainer());
				 this->timer1 = (gcnew System::Windows::Forms::Timer(this->components));
				 this->toolStripContainer1 = (gcnew System::Windows::Forms::ToolStripContainer());
				 this->statusStrip1 = (gcnew System::Windows::Forms::StatusStrip());
				 this->toolFPS = (gcnew System::Windows::Forms::ToolStripStatusLabel());
				 this->splitContainer2 = (gcnew System::Windows::Forms::SplitContainer());
				 this->panelStatus = (gcnew System::Windows::Forms::Panel());
				 this->rtboxStatus = (gcnew System::Windows::Forms::RichTextBox());
				 this->panel1->SuspendLayout();
				 this->groupBox1->SuspendLayout();
				 (cli::safe_cast<System::ComponentModel::ISupportInitialize^  >(this->UDExp))->BeginInit();
				 (cli::safe_cast<System::ComponentModel::ISupportInitialize^  >(this->UDFramerate))->BeginInit();
				 (cli::safe_cast<System::ComponentModel::ISupportInitialize^  >(this->splitContainer1))->BeginInit();
				 this->splitContainer1->Panel1->SuspendLayout();
				 this->splitContainer1->Panel2->SuspendLayout();
				 this->splitContainer1->SuspendLayout();
				 this->toolStripContainer1->BottomToolStripPanel->SuspendLayout();
				 this->toolStripContainer1->ContentPanel->SuspendLayout();
				 this->toolStripContainer1->SuspendLayout();
				 this->statusStrip1->SuspendLayout();
				 (cli::safe_cast<System::ComponentModel::ISupportInitialize^  >(this->splitContainer2))->BeginInit();
				 this->splitContainer2->Panel1->SuspendLayout();
				 this->splitContainer2->Panel2->SuspendLayout();
				 this->splitContainer2->SuspendLayout();
				 this->panelStatus->SuspendLayout();
				 this->SuspendLayout();
				 // 
				 // panelClu
				 // 
				 this->panelClu->Dock = System::Windows::Forms::DockStyle::Fill;
				 this->panelClu->Location = System::Drawing::Point(0, 0);
				 this->panelClu->Name = L"panelClu";
				 this->panelClu->Size = System::Drawing::Size(581, 392);
				 this->panelClu->TabIndex = 0;
				 // 
				 // panel1
				 // 
				 this->panel1->Controls->Add(this->groupBox1);
				 this->panel1->Controls->Add(this->label1);
				 this->panel1->Controls->Add(this->CBCameras);
				 this->panel1->Dock = System::Windows::Forms::DockStyle::Left;
				 this->panel1->Location = System::Drawing::Point(0, 0);
				 this->panel1->Name = L"panel1";
				 this->panel1->Size = System::Drawing::Size(221, 392);
				 this->panel1->TabIndex = 1;
				 // 
				 // groupBox1
				 // 
				 this->groupBox1->Controls->Add(this->butStopVideo);
				 this->groupBox1->Controls->Add(this->butStartVideo);
				 this->groupBox1->Controls->Add(this->butSingleCapture);
				 this->groupBox1->Controls->Add(this->label3);
				 this->groupBox1->Controls->Add(this->label2);
				 this->groupBox1->Controls->Add(this->UDExp);
				 this->groupBox1->Controls->Add(this->UDFramerate);
				 this->groupBox1->Location = System::Drawing::Point(18, 67);
				 this->groupBox1->Name = L"groupBox1";
				 this->groupBox1->Size = System::Drawing::Size(184, 238);
				 this->groupBox1->TabIndex = 2;
				 this->groupBox1->TabStop = false;
				 this->groupBox1->Text = L"Camera Control";
				 // 
				 // button3
				 // 
				 this->butStopVideo->Enabled = false;
				 this->butStopVideo->Location = System::Drawing::Point(10, 90);
				 this->butStopVideo->Name = L"button3";
				 this->butStopVideo->Size = System::Drawing::Size(168, 23);
				 this->butStopVideo->TabIndex = 6;
				 this->butStopVideo->Text = L"Stop Video";
				 this->butStopVideo->UseVisualStyleBackColor = true;
				 this->butStopVideo->Click += gcnew System::EventHandler(this, &Form1::butStopVideo_Click);
				 // 
				 // button2
				 // 
				 this->butStartVideo->Location = System::Drawing::Point(9, 61);
				 this->butStartVideo->Name = L"button2";
				 this->butStartVideo->Size = System::Drawing::Size(169, 23);
				 this->butStartVideo->TabIndex = 5;
				 this->butStartVideo->Text = L"Start Video";
				 this->butStartVideo->UseVisualStyleBackColor = true;
				 this->butStartVideo->Click += gcnew System::EventHandler(this, &Form1::butStartVideo_Click);
				 // 
				 // button1
				 // 
				 this->butSingleCapture->Location = System::Drawing::Point(9, 32);
				 this->butSingleCapture->Name = L"button1";
				 this->butSingleCapture->Size = System::Drawing::Size(169, 23);
				 this->butSingleCapture->TabIndex = 4;
				 this->butSingleCapture->Text = L"Capture single image";
				 this->butSingleCapture->UseVisualStyleBackColor = true;
				 this->butSingleCapture->Click += gcnew System::EventHandler(this, &Form1::butSingleCapture_Click);
				 // 
				 // label3
				 // 
				 this->label3->AutoSize = true;
				 this->label3->Location = System::Drawing::Point(6, 167);
				 this->label3->Name = L"label3";
				 this->label3->Size = System::Drawing::Size(79, 13);
				 this->label3->TabIndex = 3;
				 this->label3->Text = L"Exposure [ ms ]";
				 // 
				 // label2
				 // 
				 this->label2->AutoSize = true;
				 this->label2->Location = System::Drawing::Point(6, 128);
				 this->label2->Name = L"label2";
				 this->label2->Size = System::Drawing::Size(83, 13);
				 this->label2->TabIndex = 2;
				 this->label2->Text = L"Framerate [ fps ]";
				 // 
				 // UDExp
				 // 
				 this->UDExp->Increment = System::Decimal(gcnew cli::array< System::Int32 >(4) {10, 0, 0, 0});
				 this->UDExp->Location = System::Drawing::Point(9, 183);
				 this->UDExp->Name = L"UDExp";
				 this->UDExp->Size = System::Drawing::Size(169, 20);
				 this->UDExp->TabIndex = 1;
				 this->UDExp->ValueChanged += gcnew System::EventHandler(this, &Form1::UDExp_ValueChanged);
				 // 
				 // UDFramerate
				 // 
				 this->UDFramerate->DecimalPlaces = 2;
				 this->UDFramerate->Location = System::Drawing::Point(9, 144);
				 this->UDFramerate->Name = L"UDFramerate";
				 this->UDFramerate->Size = System::Drawing::Size(169, 20);
				 this->UDFramerate->TabIndex = 0;
				 this->UDFramerate->ValueChanged += gcnew System::EventHandler(this, &Form1::UDFramerate_ValueChanged);
				 // 
				 // label1
				 // 
				 this->label1->AutoSize = true;
				 this->label1->Location = System::Drawing::Point(24, 14);
				 this->label1->Name = L"label1";
				 this->label1->Size = System::Drawing::Size(51, 13);
				 this->label1->TabIndex = 1;
				 this->label1->Text = L"Cameras:";
				 // 
				 // CBCameras
				 // 
				 this->CBCameras->DropDownStyle = System::Windows::Forms::ComboBoxStyle::DropDownList;
				 this->CBCameras->FormattingEnabled = true;
				 this->CBCameras->Location = System::Drawing::Point(27, 30);
				 this->CBCameras->Name = L"CBCameras";
				 this->CBCameras->Size = System::Drawing::Size(169, 21);
				 this->CBCameras->TabIndex = 0;
				 this->CBCameras->SelectedIndexChanged += gcnew System::EventHandler(this, &Form1::CBCameras_SelectedIndexChanged);
				 // 
				 // splitContainer1
				 // 
				 this->splitContainer1->Dock = System::Windows::Forms::DockStyle::Fill;
				 this->splitContainer1->FixedPanel = System::Windows::Forms::FixedPanel::Panel1;
				 this->splitContainer1->IsSplitterFixed = true;
				 this->splitContainer1->Location = System::Drawing::Point(0, 0);
				 this->splitContainer1->Name = L"splitContainer1";
				 // 
				 // splitContainer1.Panel1
				 // 
				 this->splitContainer1->Panel1->Controls->Add(this->panel1);
				 // 
				 // splitContainer1.Panel2
				 // 
				 this->splitContainer1->Panel2->Controls->Add(this->panelClu);
				 this->splitContainer1->Size = System::Drawing::Size(798, 392);
				 this->splitContainer1->SplitterDistance = 213;
				 this->splitContainer1->TabIndex = 2;
				 // 
				 // timer1
				 // 
				 this->timer1->Interval = 200;
				 this->timer1->Tick += gcnew System::EventHandler(this, &Form1::timer1_Tick);
				 // 
				 // toolStripContainer1
				 // 
				 // 
				 // toolStripContainer1.BottomToolStripPanel
				 // 
				 this->toolStripContainer1->BottomToolStripPanel->Controls->Add(this->statusStrip1);
				 // 
				 // toolStripContainer1.ContentPanel
				 // 
				 this->toolStripContainer1->ContentPanel->Controls->Add(this->splitContainer2);
				 this->toolStripContainer1->ContentPanel->Size = System::Drawing::Size(798, 516);
				 this->toolStripContainer1->Dock = System::Windows::Forms::DockStyle::Fill;
				 this->toolStripContainer1->Location = System::Drawing::Point(0, 0);
				 this->toolStripContainer1->Name = L"toolStripContainer1";
				 this->toolStripContainer1->Size = System::Drawing::Size(798, 563);
				 this->toolStripContainer1->TabIndex = 3;
				 this->toolStripContainer1->Text = L"toolStripContainer1";
				 // 
				 // statusStrip1
				 // 
				 this->statusStrip1->Dock = System::Windows::Forms::DockStyle::None;
				 this->statusStrip1->Items->AddRange(gcnew cli::array< System::Windows::Forms::ToolStripItem^  >(1) {this->toolFPS});
				 this->statusStrip1->Location = System::Drawing::Point(0, 0);
				 this->statusStrip1->Name = L"statusStrip1";
				 this->statusStrip1->Size = System::Drawing::Size(798, 22);
				 this->statusStrip1->TabIndex = 0;
				 // 
				 // toolFPS
				 // 
				 this->toolFPS->Name = L"toolFPS";
				 this->toolFPS->Size = System::Drawing::Size(0, 17);
				 // 
				 // splitContainer2
				 // 
				 this->splitContainer2->Dock = System::Windows::Forms::DockStyle::Fill;
				 this->splitContainer2->Location = System::Drawing::Point(0, 0);
				 this->splitContainer2->Name = L"splitContainer2";
				 this->splitContainer2->Orientation = System::Windows::Forms::Orientation::Horizontal;
				 // 
				 // splitContainer2.Panel1
				 // 
				 this->splitContainer2->Panel1->Controls->Add(this->splitContainer1);
				 // 
				 // splitContainer2.Panel2
				 // 
				 this->splitContainer2->Panel2->Controls->Add(this->panelStatus);
				 this->splitContainer2->Size = System::Drawing::Size(798, 516);
				 this->splitContainer2->SplitterDistance = 392;
				 this->splitContainer2->TabIndex = 3;
				 // 
				 // panelStatus
				 // 
				 this->panelStatus->Controls->Add(this->rtboxStatus);
				 this->panelStatus->Dock = System::Windows::Forms::DockStyle::Fill;
				 this->panelStatus->Location = System::Drawing::Point(0, 0);
				 this->panelStatus->Name = L"panelStatus";
				 this->panelStatus->Size = System::Drawing::Size(798, 120);
				 this->panelStatus->TabIndex = 0;
				 // 
				 // rtboxStatus
				 // 
				 this->rtboxStatus->Dock = System::Windows::Forms::DockStyle::Fill;
				 this->rtboxStatus->Location = System::Drawing::Point(0, 0);
				 this->rtboxStatus->Name = L"rtboxStatus";
				 this->rtboxStatus->ReadOnly = true;
				 this->rtboxStatus->Size = System::Drawing::Size(798, 120);
				 this->rtboxStatus->TabIndex = 0;
				 this->rtboxStatus->Text = L"";
				 // 
				 // Form1
				 // 
				 this->AutoScaleDimensions = System::Drawing::SizeF(6, 13);
				 this->AutoScaleMode = System::Windows::Forms::AutoScaleMode::Font;
				 this->ClientSize = System::Drawing::Size(798, 563);
				 this->Controls->Add(this->toolStripContainer1);
				 this->Name = L"Form1";
				 this->Text = L"Form1";
				 this->FormClosing += gcnew System::Windows::Forms::FormClosingEventHandler(this, &Form1::Form1_FormClosing);
				 this->Shown += gcnew System::EventHandler(this, &Form1::Form1_Shown);
				 this->panel1->ResumeLayout(false);
				 this->panel1->PerformLayout();
				 this->groupBox1->ResumeLayout(false);
				 this->groupBox1->PerformLayout();
				 (cli::safe_cast<System::ComponentModel::ISupportInitialize^  >(this->UDExp))->EndInit();
				 (cli::safe_cast<System::ComponentModel::ISupportInitialize^  >(this->UDFramerate))->EndInit();
				 this->splitContainer1->Panel1->ResumeLayout(false);
				 this->splitContainer1->Panel2->ResumeLayout(false);
				 (cli::safe_cast<System::ComponentModel::ISupportInitialize^  >(this->splitContainer1))->EndInit();
				 this->splitContainer1->ResumeLayout(false);
				 this->toolStripContainer1->BottomToolStripPanel->ResumeLayout(false);
				 this->toolStripContainer1->BottomToolStripPanel->PerformLayout();
				 this->toolStripContainer1->ContentPanel->ResumeLayout(false);
				 this->toolStripContainer1->ResumeLayout(false);
				 this->toolStripContainer1->PerformLayout();
				 this->statusStrip1->ResumeLayout(false);
				 this->statusStrip1->PerformLayout();
				 this->splitContainer2->Panel1->ResumeLayout(false);
				 this->splitContainer2->Panel2->ResumeLayout(false);
				 (cli::safe_cast<System::ComponentModel::ISupportInitialize^  >(this->splitContainer2))->EndInit();
				 this->splitContainer2->ResumeLayout(false);
				 this->panelStatus->ResumeLayout(false);
				 this->ResumeLayout(false);

			 }
#pragma endregion

			 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
			 /// <summary>
			 ///    Executes the status message action.
			 /// </summary>
			 ///
			 /// <param name="eSource">	   	Source for the. </param>
			 /// <param name="eMsg">	   	The message. </param>
			 /// <param name="sSourceName">	[in,out] If non-null, name of the source. </param>
			 /// <param name="sMessage">   	[in,out] If non-null, the message. </param>
			 /// <param name="iValue">	   	Zero-based index of the value. </param>
			 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
			 void OnStatusMessage(Rx::ApiLF::NET::EStatusSource eSource, Rx::ApiLF::NET::EStatusMessage eMsg, System::String^ sSourceName, System::String^ sMessage, System::Int32 iValue)
			 {
				 if ( (int(eMsg) & int(Rx::ApiLF::NET::EStatusMsgGrp::Text)) != 0 )
				 {
					 String^ sText = String::Format("{0}: {1}\n", sSourceName, sMessage);
					 rtboxStatus->Text += sText;
					 rtboxStatus->SelectionStart = rtboxStatus->Text->Length;
					 rtboxStatus->ScrollToCaret();
				 }
			 }

			 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
			 /// <summary>
			 ///    Creates a new image.
			 /// </summary>
			 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
			 void NewImage()
			 {
				 // Capture an image
				 RxApiLF::RxCamDoCapture(m_uCamIdx);

				 // Refocus this image
				 RxApiLF::RxFocusOnPlane(0.5);

				 // Read image format of resultant refocused image.
				 // The RxApi holds a number of result images on the CUDA card,
				 // so that they are only copied back to the host memory when needed.
				 ImageFormat^ xImgF;
				 RxApiLF::RxGetImageFormat(EImgID::Focus, xImgF);

				 // Initialize the CLUScript variables iWidth and iHeight with 
				 // the dimensions of the refocused image.
				 m_xCluView->SetVarNumber("iWidth", xImgF->iWidth);
				 m_xCluView->SetVarNumber("iHeight", xImgF->iHeight);

				 // Execute the script with ToolName == "Image_Create".
				 // This prepared the image view for an image of the given size.
				 // The image itself is not copied at this point.
				 m_xCluView->ExecScript("Image_Create");

				 // If the refocused image is of luminance type, we need to select
				 // a different shader for the image display.
				 if (xImgF->ePixelType == Rx::InteropNet::Runtime28::EPixelType::Lum || xImgF->ePixelType == Rx::InteropNet::Runtime28::EPixelType::LumA)
				 {
					 m_xCluView->ExecScript("Image_Lum_Enable");
				 }

				 int iTexID = 0;
				 // Get the OpenGL texture ID of the texture that will contain the 
				 // displayed image.
				 m_xCluView->GetVarNumber("texImage", iTexID);

				 // Register this texture ID with the RxApi, as the texture ID
				 // for displaying the refocused image. The texture is automatically
				 // (re-)initialized by this call to the correct type and size.
				 RxApiLF::RxSetPar(EPar::Gl_TexFocusLeftID, (unsigned int) iTexID);

				 // Copy the refocused image held on the CUDA device to the OpenGL texture
				 // with ID iTexID.
				 RxApiLF::RxGlUpdateTex((unsigned int) EImgID::Focus);

				 // Tell the CLU control to redraw the current scene tree.
				 // This does not re-execute the script itself.
				 // It needs to be called to ensure that the new content of
				 // the image texture is displayed.
				 m_xCluView->Update();
			 }

			 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
			 /// <summary>
			 ///    Updates the image.
			 /// </summary>
			 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
			 void UpdateImage()
			 {
				 // Capture an image
				 RxApiLF::RxCamDoCapture(m_uCamIdx);

				 // Refocus this image
				 RxApiLF::RxFocusOnPlane(0.5);

				 // Update the OpenGL texture from CUDA memory.
				 RxApiLF::RxGlUpdateTex((unsigned int) EImgID::Focus);

				 // Update the CLU control view
				 m_xCluView->Update();
			 }

			 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
			 /// <summary>
			 ///    Form 1 shown.
			 /// </summary>
			 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
			 System::Void Form1_Shown(System::Object^  sender, System::EventArgs^  e) 
			 {
				 CBCameras->Enabled = false;
				 butSingleCapture->Enabled = false;
				 butStartVideo->Enabled = false;
				 UDFramerate->Enabled = false;
				 UDExp->Enabled = false; 

				 this->Update();

				 // Initialize the RxApi. This always has to be called first.
				 bool bRes = RxApiLF::RxInit();
				 if (!bRes)
				 {
					 String^ sError = "";
					 RxApiLF::RxGetLastError(sError);
					 Windows::Forms::MessageBox::Show(String::Format("Error initializing ApiLF: {0}", sError));
					 return;
				 }

				 // Automatically select an appropriate CUDA device, that can
				 // directly communicate with an OpenGL rendering context.
				 // This allows us to directly copy images from CUDA memory to
				 // OpenGL texture memory, which is much faster, than first copying
				 // the image back to the host memory and then again to the 
				 // OpenGl card.
				 // However, if CUDA/OpenGL interoperability is selected, we
				 // must create a local OpenGL rendering context and make it
				 // active in the same thread as the RxApi.
				 RxApiLF::RxCudaSelectDevice(-1, true);

				 // Start the CLU engine
				 m_xCluEngine = gcnew CLUViz::NET::EngineCtrl();
				 m_xCluEngine->Start();

				 // Now create the CLU control and embed it into the "panelClu" control.
				 // Changes in size and position of panelClu are automatically applied
				 // to the CLU control.
				 // Since the CLU control display runs in a separate thread, we must
				 // create an OpenGL rendering context for the CUDA thread (this thread)
				 // that shares its texture memory with the OpenGL rendering context in
				 // the CLU control thread. This is done automatically by setting the second
				 // parameter to "true".
				 m_xCluView = gcnew CLUViz::NET::ViewCtrl(panelClu, true, 0);
				 // We now have to make this shared rendering context current,
				 // since otherwise all CUDA commands will fail. That is,
				 // CUDA is only initialized once this rendering context is made current.
				 // Note that the shared rendering context for this thread is attached to
				 // an invisible dummy window that is held internally.
				 m_xCluView->MakeCurrentSharedRC();

				 // Now set the visualization CLUScript from the resources.
				 System::Resources::ResourceManager^ xResMgr = gcnew System::Resources::ResourceManager( "RxExampleApiCameraNet01.CluScript", GetType()->Assembly );
				 String^ sScript = (String^) xResMgr->GetObject("View_Image_01");
				 m_xCluView->SetScript(sScript);

				 this->Update();

				 // Register Status message event handler
				 RxApiLF::StatusMessage += gcnew StatusMessageHandler(this, &Form1::OnStatusMessage);


				 // Now register all available cameras
				 RxApiLF::RxCamDriverInit();
				 RxApiLF::RxCamRegister();

				 // Get number of available cameras
				 unsigned int uCamCnt;
				 RxApiLF::RxGetPar( EPar::Cam_Count, uCamCnt );

				 // Add them to combo box
				 if(uCamCnt > 0)
				 {
					 for(unsigned uCamIdx = 0; uCamIdx < uCamCnt; uCamIdx++)
					 {
						 String^ sCamName, ^sCamType;

						 // Open the camera for usage
						 RxApiLF::RxCamOpen(uCamIdx);

						 // Get ID of Camera iCamIdx - this is the serial number
						 RxApiLF::RxCamGetPar(uCamIdx, EPar::Cam_ID, sCamName);

						 // Get Type of Camera iCamIdx - this is something like "R11C" or "R5M"
						 RxApiLF::RxCamGetPar(uCamIdx, EPar::Cam_Type, sCamType);

						 // Set Camera trigger mode to software snapshot
						 RxApiLF::RxCamSetPar(uCamIdx, EPar::Cam_TriggerMode, (unsigned) ECameraTriggerMode::Software_SnapShot);

						 CBCameras->Items->Add(sCamType + "- SN: " + sCamName);
					 }

					 CBCameras->SelectedIndex = 0;
					 CBCameras->Enabled = true;
					 butSingleCapture->Enabled = true;
					 butStartVideo->Enabled = true;
				 }
				 else
				 {
					 // No cameras found
					 CBCameras->Items->Add("No Cameras found!");
					 CBCameras->SelectedIndex = 0;
				 }


			 }

	/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
	/// <summary>
	/// 	Uninitialize and free everything when the main form is closed.
	/// </summary>
	/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
	System::Void Form1_FormClosing(System::Object^  sender, System::Windows::Forms::FormClosingEventArgs^  e) 
			 {
				 timer1->Enabled = false;

				 // Get number of available cameras
				 unsigned int uCamCnt;
				 RxApiLF::RxGetPar( EPar::Cam_Count, uCamCnt );

				 // Close all open cameras
				 for(unsigned uCamIdx = 0; uCamIdx < uCamCnt; uCamIdx++)
				 {
					 // Close the camera
					 RxApiLF::RxCamClose(uCamIdx);
				 }

				 // End the CLU engine. This closes all CLU controls
				 m_xCluEngine->End();
				 // Finalize the RxApi. This frees all internal memory also on the CUDA device.
				 RxApiLF::RxFinalize();
			 }

		/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>
		/// 	Cameras selected index changed.
		/// </summary>
		/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
		System::Void CBCameras_SelectedIndexChanged(System::Object^  sender, System::EventArgs^  e) 
		{
			// If another camera is selected
			if(CBCameras->SelectedIndex != m_uCamIdx)
			{
				// Stop capturing
				RxApiLF::RxCamStopCapture(m_uCamIdx);
			}

			m_uCamIdx = CBCameras->SelectedIndex;
			bDisableToolEvents = true;

			// Select camera trigger mode
			RxApiLF::RxCamSetPar( m_uCamIdx, EPar::Cam_TriggerMode, (unsigned) ECameraTriggerMode::Software_SnapShot );

			// Prepare camera for capturing
			unsigned int uRay;
			RxApiLF::RxCamStartCapture(m_uCamIdx, uRay);
			m_uRay = uRay;


			double dMin, dMax, dVal;
			// Get current framerate and framerate range
			RxApiLF::RxCamGetParRange(m_uCamIdx, EPar::Cam_FramesPerSecond, dMin, dMax);
			if(RxApiLF::RxCamGetPar(m_uCamIdx, EPar::Cam_FramesPerSecond, dVal))
			{
				if ( dVal < dMin ) dVal = dMin;
				else if ( dVal > dMax ) dVal = dMax;

				// Set control			 
				UDFramerate->Minimum = Convert::ToDecimal(dMin);
				UDFramerate->Maximum = Convert::ToDecimal(dMax);
				UDFramerate->Value = Convert::ToDecimal(dVal);
				UDFramerate->Enabled = true;
			}
			else
			{
				UDFramerate->Enabled = false;
			}


			// Get current exposure and exposure range
			RxApiLF::RxCamGetParRange(m_uCamIdx, EPar::Cam_Exposure, dMin, dMax);
			if(RxApiLF::RxCamGetPar(m_uCamIdx, EPar::Cam_Exposure, dVal))
			{
				if ( dVal < dMin ) dVal = dMin;
				else if ( dVal > dMax ) dVal = dMax;

				// Set control
				UDExp->Minimum = Convert::ToDecimal(dMin);
				UDExp->Maximum = Convert::ToDecimal(dMax);
				UDExp->Value = Convert::ToDecimal(dVal);
				UDExp->Enabled = true;
			}
			else
			{
				UDExp->Enabled = false;
			}

			// Take a new Image
			NewImage();
			bDisableToolEvents = false;
		}

		/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>
		/// 	On framerate value changed.
		/// </summary>
		/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
		System::Void UDFramerate_ValueChanged(System::Object^  sender, System::EventArgs^  e) 
		{
			if(bDisableToolEvents)
				return;

			bDisableToolEvents = true;

			bool bResult;
			double dVal, dMin, dMax;
			UDFramerate->Enabled = false;

			// Set framerate
			bResult = RxApiLF::RxCamSetPar(m_uCamIdx, EPar::Cam_FramesPerSecond, Convert::ToDouble(UDFramerate->Value));

			// Get framerate - in some cases the framerate differs from the value
			RxApiLF::RxCamGetPar(m_uCamIdx, EPar::Cam_FramesPerSecond, dVal);
			UDFramerate->Value = Convert::ToDecimal(dVal);

			// Get exposure - in some cases the exposure is changed by setting the framerate
			RxApiLF::RxCamGetParRange(m_uCamIdx, EPar::Cam_Exposure, dMin, dMax);
			RxApiLF::RxCamGetPar(m_uCamIdx, EPar::Cam_Exposure, dVal);

			if ( dVal < dMin ) dVal = dMin;
			else if ( dVal > dMax ) dVal = dMax;
			
			// Set control
			UDExp->Minimum = Convert::ToDecimal(dMin);
			UDExp->Maximum = Convert::ToDecimal(dMax);
			UDExp->Value = Convert::ToDecimal(dVal);

			// Take a new Image
			UpdateImage();

			UDFramerate->Enabled = true;
			bDisableToolEvents = false;
		}

		/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>
		/// 	On exposure value changed.
		/// </summary>
		/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
		System::Void UDExp_ValueChanged(System::Object^  sender, System::EventArgs^  e) 
		{
			if(bDisableToolEvents)
				return;

			bDisableToolEvents = true;
			double dVal, dMin, dMax;
			UDExp->Enabled = false;

			// Set exposure
			RxApiLF::RxCamSetPar(m_uCamIdx, EPar::Cam_Exposure, Convert::ToDouble(UDExp->Value));

			// Get exposure - in some cases the exposure differs from the value
			RxApiLF::RxCamGetPar(m_uCamIdx, EPar::Cam_Exposure, dVal);
			UDExp->Value = Convert::ToDecimal(dVal);

			// Get framerate - in some cases the framerate is changed by setting the exposure
			RxApiLF::RxCamGetParRange(m_uCamIdx, EPar::Cam_FramesPerSecond, dMin, dMax);
			RxApiLF::RxCamGetPar(m_uCamIdx, EPar::Cam_FramesPerSecond, dVal);

			if ( dVal < dMin ) dVal = dMin;
			else if ( dVal > dMax ) dVal = dMax;

			// Set control
			UDFramerate->Minimum = Convert::ToDecimal(dMin);
			UDFramerate->Maximum = Convert::ToDecimal(dMax);
			UDFramerate->Value = Convert::ToDecimal(dVal);

			// Take a new Image
			UpdateImage();

			UDExp->Enabled = true;
			bDisableToolEvents = false;
		}

		/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>
		/// 	Timer 1 tick.
		/// </summary>
		/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
		System::Void timer1_Tick(System::Object^  sender, System::EventArgs^  e) 
		{

			// Capture an image
			UpdateImage();

			double dVal;

			// Get actual frames per second
			RxApiLF::RxCamGetPar(m_uCamIdx, EPar::Cam_ActualFramesPerSecond, dVal);
			toolFPS->Text = Convert::ToString(dVal) + " fps";
		}

		/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>
		/// 	But start video click.
		/// </summary>
		/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
		System::Void butSingleCapture_Click(System::Object^  sender, System::EventArgs^  e) 
		{
			// Take a new Image
			UpdateImage();
		}

		/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>
		/// 	But single capture click.
		/// </summary>
		/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
		System::Void butStartVideo_Click(System::Object^  sender, System::EventArgs^  e) 
		{
			butStopVideo->Enabled = true;
			butStartVideo->Enabled = false;
			butSingleCapture->Enabled = false;

			RxApiLF::RxCamStopCapture( m_uCamIdx );
			RxApiLF::RxRayDelete( m_uRay );

			// Enable Video Mode in API
			RxApiLF::RxCamSetPar( m_uCamIdx, EPar::Cam_TriggerMode, (unsigned) ECameraTriggerMode::Camera_FreeRun );

			RxApiLF::RxCamStartCapture(m_uCamIdx, m_uRay);

			timer1->Enabled = true;
		}

		/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>
		/// 	But stop video click.
		/// </summary>
		/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
		System::Void butStopVideo_Click(System::Object^  sender, System::EventArgs^  e) 
		{
			timer1->Enabled = false;

			RxApiLF::RxCamStopCapture( m_uCamIdx );
			RxApiLF::RxRayDelete( m_uRay );

			// Enable Video Mode in API
			RxApiLF::RxCamSetPar( m_uCamIdx, EPar::Cam_TriggerMode, (unsigned) ECameraTriggerMode::Software_SnapShot );

			RxApiLF::RxCamStartCapture(m_uCamIdx, m_uRay);

			butStartVideo->Enabled = true;
			butSingleCapture->Enabled = true;
			butStopVideo->Enabled = false;
		}
	};
}

