//=== Movie.js ================================================================
//
// Generates a sequence of frames that with temporary suspension of disbelief
// looks like a movie!
//
// History
// Who When     What
// --- -------- ---------------------------------------------------------------
// pah 11/03/08 Tidied up for ArtCAM 2008
//-----------------------------------------------------------------------------

// Calling page must have paramsDiv & libraryDiv objects for these functions
// show and manipulate

function plugin_main()
{
   if(artcam.ProjectAssembly==null)
   {
      return;
   }

   HideAllLibraryDivs();

   paramsDiv.style.display = "";

   // Store global variables and function calls
   globalStore.OnAnimate = OnAnimate;
   globalStore.OnOutputChanged = OnOutputChanged;
   globalStore.UpdateTotalFrames = UpdateTotalFrames;

   // Create the parameters in paramsDiv (this must exist)
   Write_paramsDiv();

   // Initialise any button classes we have just created
   InitialiseButtonDivs();
   
   // If help is NOT visible turn it off
   if (artcam.DisplayHelp)
      ToggleHelp();
}

function Write_paramsDiv()
{
   // Empty any existing content
   paramsDiv.innerHTML = "";

   // Create an array to hold the HTML
   var hArr = new Array();
   hArr.push( "<b>"+gCreateMovie+":</b><br><br>");
   
   hArr.push( "<table border=0 cellspacing=0 cellpadding=1 width=100% style='table-layout:fixed;margin-left:3px'>");
   hArr.push( " <colgroup><col width = 20%> <col width = 80% ></colgroup>");
   
   hArr.push( " <tr HELPTAG style='DISPLAY:none'>"  );
   hArr.push( "  <td></td>" );
   hArr.push( "  <td>" + gMovieHelp1 + "<br></td>"  );
   hArr.push( " </tr>"  );
     
   hArr.push( " <tr>");
   hArr.push( "  <td><b>"+gNameEdit+":</b></td>");
   hArr.push( "  <td><input id=NameEdit style='margin-left:1px' type=edit></td>");
   hArr.push( " </tr>");
   
   hArr.push( " <tr HELPTAG style='DISPLAY:none'>"  );
   hArr.push( "  <td></td>" );
   hArr.push( "  <td>" + gMovieHelp2 + "<br></td>"  );
   hArr.push( " </tr>"  );   
   
   hArr.push( " <tr>" );
   hArr.push( "  <td></td>");
   hArr.push( "  <td><input id=CompressedImagesCheck style='margin-left:1px' type=checkbox checked>");
   hArr.push( "  "+gCompressedImages+"</td>");
   hArr.push( " </tr>");
   
   hArr.push( " <tr HELPTAG style='DISPLAY:none'>"  );
   hArr.push( "  <td></td>" );
   hArr.push( "  <td>" + gMovieHelp3 + "<br></td>"  );
   hArr.push( " </tr>"  );
   
   hArr.push( " <tr>");
   hArr.push( "  <td colspan=2>&nbsp;</td>");
   hArr.push( " </tr> ");
   
   hArr.push( " <tr>");
   hArr.push( "  <td><b>"+gCreate+":</b></td>");
   hArr.push( "  <td><input type=radio onclick='globalStore.OnOutputChanged()' name=outputradio checked><b>"+gViewerEdit+"</b></td>");
   hArr.push( " </tr>" );
   
   
   hArr.push( " <tr>");
   hArr.push( "  <td></td>");
   hArr.push( "  <td>");
   
   hArr.push( "   <table id=FramesTable1 border=0 cellspacing=0 cellpadding=1 width=100% style='margin-left:3px'>");
   
   hArr.push( "    <tr HELPTAG style='DISPLAY:none'>"  );
   hArr.push( "     <td colspan=2>" + gMovieHelp4 + "<br></td>"  );
   hArr.push( "    </tr>"  );
   
   hArr.push( "    <tr>");
   hArr.push( "     <td width=1>"+gFramesEdit+":</td>");
   hArr.push( "     <td width=100%><input id=FramesEdit1 style='margin-left:1px' type=edit value=8 onkeyup='globalStore.UpdateTotalFrames()' number size=2 maxLength=3 positive integer>"+gPerAxis+"</td>");
   hArr.push( "    </tr> ");
   
   hArr.push( "    <tr> ");
   hArr.push( "     <td></td>");
   hArr.push( "     <td>("+gTotalFrames+" <span id=TotalFrames>0</span>)</td>");
   hArr.push( "    </tr>");
   
   hArr.push( "    <tr HELPTAG style='DISPLAY:none'>"  );
   hArr.push( "     <td colspan=2>" + gMovieHelp5 + "<br></td>"  );
   hArr.push( "    </tr>"  );
   
   hArr.push( "    <tr>" );
   hArr.push( "     <td colspan=2>");
   hArr.push( "      <input type=checkbox id=displayNow>"+gDisplayOnceCreated);
   hArr.push( "     </td>" );
   hArr.push( "    </tr>" );
       
   hArr.push( "    <tr HELPTAG style='DISPLAY:none'>"  );
   hArr.push( "     <td colspan=2>" + gMovieHelp6 + "<br></td>"  );
   hArr.push( "    </tr>"  );
   
   hArr.push( "   </table>");   
   hArr.push( "  </td>");
   hArr.push( " </tr>" );
   
   hArr.push( " <tr>");
   hArr.push( "  <td colspan=2>&nbsp;</td>");
   hArr.push( " </tr> ");
   
   hArr.push( " <tr>");
   hArr.push( "  <td></td>");
   hArr.push( "  <td><input type=radio onclick='globalStore.OnOutputChanged()' name=outputradio><b>"+gImagesOnly+"</b></td>");
   hArr.push( " </tr>" );
   
   hArr.push( " <tr>");  
   hArr.push( "  <td></td>");
   hArr.push( "  <td>");
   hArr.push( "   <table id=FramesTable2 border=0 cellspacing=0 cellpadding=1 width=100% style='margin-left:3px'>");
   
   hArr.push( "    <tr HELPTAG style='DISPLAY:none'>"  );
   hArr.push( "     <td colspan=2>" + gMovieHelp7 + "<br></td>"  );
   hArr.push( "    </tr>"  );
   
   hArr.push( "    <tr>");
   hArr.push( "     <td>"+gFramesEdit+":</td>");
   hArr.push( "     <td><input id=FramesEdit2 style='margin-left:1px' type=edit value=36 number size=2 maxLength=3 positive integer></td>");
   hArr.push( "    </tr>" );
   
   hArr.push( "    <tr>");
   hArr.push( "     <td>"+gUseAxis+":</td>");
   hArr.push( "     <td>");
   hArr.push( "      <input type=checkbox id=xaxis><b><font color='red'>X</font></b>");
   hArr.push( "      <input type=checkbox id=yaxis><b><font color='green'>Y</font></b>");
   hArr.push( "      <input type=checkbox id=zaxis checked><b><font color='blue'>Z</font></b>");
   hArr.push( "     </td>");
   hArr.push( "    </tr>"); 
   
   hArr.push( "    <tr HELPTAG style='DISPLAY:none'>"  );
   hArr.push( "     <td colspan=2>" + gMovieHelp8 + "<br></td>"  );
   hArr.push( "    </tr>"  );    
      
   hArr.push( "   </table>");
   hArr.push( "  </td>");
   hArr.push( " </tr>");
   hArr.push( "</table>");
   
   hArr.push( "<br>" );
   
   hArr.push( "<div class='mouseOut' button_name='forward_button' targetFunction='globalStore.OnAnimate' style='width=30px;float:right;'>");
   hArr.push( "<img alt=" + gAcceptButtonAlt + " id=back_img src ='" + artcam.HtmlRootDir + "../SharedImages/accept.gif' align=absmiddle border=0 width=30 height=30>");
   hArr.push( "</div>");

   // Add the back button HTML to the array
   AddBackButtonHTML(hArr);

   // Bung all our HTML into the div and display it
   paramsDiv.innerHTML = hArr.join("\n");
   globalStore.name_edit       = NameEdit;
   globalStore.name_edit.value = artcam.ProjectAssembly.Name;
   globalStore.FramesEdit1     = FramesEdit1;
   globalStore.FramesEdit2     = FramesEdit2;
   globalStore.displayNow      = displayNow;
   globalStore.x_axis_check    = xaxis;
   globalStore.y_axis_check    = yaxis;
   globalStore.z_axis_check    = zaxis;
   globalStore.outputradio     = outputradio;
   globalStore.ImageExtension  = ".jpg";

   SubclassNumberEditControls();

   // Ensure our DIV and SPAN state is correct
   globalStore.OnOutputChanged();
   globalStore.UpdateTotalFrames();
   
   paramsDiv.style.display = "";
}

function OnAnimate()
{
   if (artcam.ProjectAssembly==null) {
      artcam.MessageBox(gNoSelectedAssembly);
      return;
   }

   if(!artcam.ModelLoaded) {
      //alert(gNo3DViewforRendering);
      //return;
   }

   if (CompressedImagesCheck.checked)
   {
      globalStore.ImageExtension = ".jpg";
   }
   else
   {
      globalStore.ImageExtension = ".bmp";
   }
   
   var movie_directory = GetMovieFolder();
   if (movie_directory == "")
      return false;
   
   movie_directory += "Movie";
   
   var DirSelector = artcam.CreateFileSelector();
   if (DirSelector == null)
      return false;
   
   if (!DirSelector.DirectoryExists(movie_directory))
   {
      if (!DirSelector.CreateDirectory(movie_directory))
      {
         artcam.MessageBox(gFailedtoCreateMovieDirectory);
         return false;
      }
   }

   movie_directory += "\\" + globalStore.name_edit.value;

   if (DirSelector.DirectoryExists(movie_directory))
   {
      if(confirm(gOverwriteExistingMovie))
         DirSelector.DeleteDirectory(movie_directory);
      else
         return false;
   }

   if (!DirSelector.CreateDirectory(movie_directory))
   {
      artcam.MessageBox(gFailedtoCreateMovieDirectory);
      return false;
   }

   var image_directory = movie_directory + "\\images";

   if (DirSelector.DirectoryExists(image_directory))
   {
      if(confirm(gOverwriteExistingMovie))
         DirSelector.DeleteDirectory(image_directory);
      else
         return false;
   }

   if (!DirSelector.CreateDirectory(image_directory))
   {
      artcam.MessageBox(gFailedtoCreateMovieDirectory);
      return false;
   }

   if(globalStore.outputradio[0].checked)
   {
      var step_size = 360/globalStore.FramesEdit1.getValue();
      if(!CreateTwiddleFrames(movie_directory, step_size))
         return;
      CreateViewerPage(movie_directory, image_directory, DirSelector);
   }
   else
   {
      var step_size = 360/globalStore.FramesEdit2.getValue();
      CreateFramesOnly(movie_directory, step_size);
   }
}

 
function GetMovieFolder()
{
   // Get the previous folder, if any
   var currDir = artcam.RetrieveString("MovieWizard", "Folder", "C:\\");
   
   // Ask artcam for the directory chooser
   var DirSelector = artcam.CreateFileSelector();
   DirSelector.ExistingDirectory(gSelectMovieFolder, currDir);
   if (!DirSelector.DirectorySelected())
     return "";

   currDir = DirSelector.SelectedPath() + "\\";
   currDir = TrimDirectory(currDir);
   
   artcam.StoreString("MovieWizard", "Folder", currDir);
   
   return currDir;
}   


//=== TrimDirectory ===========================================================
//
// Tidy up a directory string
//
// History
// Who When     What
// --- -------- ---------------------------------------------------------------
// pah 11/03/08 Copied from 2D machining wizard
//-----------------------------------------------------------------------------
function TrimDirectory(dir)
{
   // We tidy up a directory string
   // Trim off any white space and add a final backslash if needed
   // This can all be done in one line with a regexp. 
   return dir.replace(/^\s*(.*?)\\*\s*$/, "$1\\");
}


//=== CreateFramesOnly ========================================================
//
// Create the frames
//
// History
// Who When     What
// --- -------- ---------------------------------------------------------------
// pah 13/03/08 Added this header. Set to 1 million pixels, ok for most end
//              user displays
//-----------------------------------------------------------------------------
function CreateFramesOnly(movie_directory, step_size)
{
   var xrot_step; 
   var yrot_step; 
   var zrot_step;

   globalStore.x_axis_check.checked ? xrot_step=step_size : xrot_step=0;
   globalStore.y_axis_check.checked ? yrot_step=step_size : yrot_step=0;
   globalStore.z_axis_check.checked ? zrot_step=step_size : zrot_step=0;

   var xrot=0; 
   var yrot=0; 
   var zrot=0;

   // set up the progress bar
   var frames = globalStore.FramesEdit2.getValue();
   var progress_count = 0;
   var progress_bar = artcam.CreateProgressBar( gCreatingImages, frames, true );

   for(var index=0; index<globalStore.FramesEdit2.getValue(); index++)
   {
      var image_filepath = movie_directory + "\\images\\" + globalStore.name_edit.value + "_" + index + globalStore.ImageExtension;
      var workplane = artcam.ProjectAssembly.GetWorkplane();
      workplane.Transform(0,0,0,1,1,1,xrot,0,0,0,0,0,true);
      workplane.Transform(0,0,0,1,1,1,0,yrot,0,0,0,0,true);
      workplane.Transform(0,0,0,1,1,1,0,0,zrot,0,0,0,true);
      artcam.ProjectAssembly.SetWorkplane(workplane);
      artcam.Refresh3dView();
      
      // Increment progress bar and set the text in it
      // This will also flush all the paint events
      if(progress_bar.UserCancelled())
      {
         artcam.MessageBox(gProcessCancelled);
         // Reset Assembly
         var workplane = artcam.ProjectAssembly.GetWorkplane();
         workplane.Transform(0,0,0,1,1,1,0,0,-zrot,0,0,0,true);
         workplane.Transform(0,0,0,1,1,1,0,-yrot,0,0,0,0,true);
         workplane.Transform(0,0,0,1,1,1,-xrot,0,0,0,0,0,true);
         artcam.ProjectAssembly.SetWorkplane(workplane);

         artcam.Refresh3dView();
         progress_bar.hide_progress();
         return;
      }
      progress_bar.SetPos(++progress_count);
      progress_bar.SetText(gFrame + " " + progress_count + " " + gOf + " " + frames);

      // Without this, we don't seem able to press the cancel button!
      var date = new Date();
      var time = date.getTime();
      var time2 = date.getTime();
      while( (time2-time)<100 )
      {
         date = new Date();
         time2 = date.getTime();
      }
      artcam.ThreeDView.Save3DViewImageScaled( image_filepath, 1000000 );
      var workplane = artcam.ProjectAssembly.GetWorkplane();
      workplane.Transform(0,0,0,1,1,1,0,0,-zrot,0,0,0,true);
      workplane.Transform(0,0,0,1,1,1,0,-yrot,0,0,0,0,true);
      workplane.Transform(0,0,0,1,1,1,-xrot,0,0,0,0,0,true);
      artcam.ProjectAssembly.SetWorkplane(workplane);
      xrot+=xrot_step;
      yrot+=yrot_step;
      zrot+=zrot_step;
   }
   artcam.Refresh3dView();
}


//=== CreateTwiddleFrames =====================================================
//
// Create the twiddle frames
//
// History
// Who When     What
// --- -------- ---------------------------------------------------------------
// pah 13/03/08 Added this header. Set to 1 million pixels, ok for most end
//              user displays
//-----------------------------------------------------------------------------
function CreateTwiddleFrames(movie_directory, step_size)
{
   // Throw up a stop window
   gStop = false;
   ww = 190;
   wh = 100;
   sw = screen.availWidth;
   sh = screen.availHeight;

   var yrot_step = step_size; 
   var zrot_step = step_size;

   var yrot=0; 
   var zrot=0;

   // set up the progress bar
   var frames = globalStore.FramesEdit1.getValue();
   var progress_count = 0;
   var progress_bar = artcam.CreateProgressBar( gCreatingMovie, frames * frames, true );

   for(var zindex=0; zindex<frames; zindex++)
   {
      artcam.ProjectAssembly.Transform(0,0,0,1,1,1,0,0,zrot_step,0,0,0,false,false);
      // ejp 10/09/04 - immediately update the counter so that cancel can reverse the transformation         
      zrot+=zrot_step;
      for(var yindex=0; yindex<frames; yindex++)
      {
         var image_filepath = movie_directory + "\\images\\" + globalStore.name_edit.value + "_" + zindex + "_" + yindex  + globalStore.ImageExtension;
         artcam.ProjectAssembly.Transform(0,0,0,1,1,1,0,yrot_step,0,0,0,0,false,false);
         // ejp 10/09/04 - immediately update the counter so that cancel can reverse the transformation         
         yrot+=yrot_step;

         artcam.FlushPaintEvents();
         artcam.Refresh3dView();
         //alert("Z=" + zrot + ", Y=" + yrot);
         
         // Increment progress bar and set the text in it
         // This will also flush all the paint events
         if(progress_bar.UserCancelled())
         {
            artcam.MessageBox(gProcessCancelled);
            // Reset Assembly
            artcam.ProjectAssembly.Transform(0,0,0,1,1,1,0,-yrot,0,0,0,0,false,false);
            artcam.ProjectAssembly.Transform(0,0,0,1,1,1,0,0,-zrot,0,0,0,false,false);
            artcam.Refresh3dView();
            progress_bar.hide_progress();
            return false;
         }
         progress_bar.SetPos(++progress_count);
         progress_bar.SetText(gFrame + " " + progress_count + " " + gOf + " " + frames * frames);

         // Without this, we don't seem able to press the cancel button!
         var date = new Date();
         var time = date.getTime();
         var time2 = date.getTime();
         while( (time2-time)<100 )
         {
            date = new Date();
            time2 = date.getTime();
         }
         // Now save the view below
         artcam.ThreeDView.Save3DViewImageScaled( image_filepath, 1000000 );
      }
   }

   progress_bar.hide_progress();

   artcam.Refresh3dView();
   return true;
}

function CreateViewerPage(movie_directory, image_directory, DirSelector)
{
   var max_images = globalStore.FramesEdit1.getValue() - 1;
	var txtArr = new Array();
	txtArr.push( "<html>");
	txtArr.push( "<head>");
	txtArr.push( "<style type='text/css'>");
	txtArr.push( "BODY{background-color:buttonface; font-family:arial,helvetica; font-size:12pt; text-align:justify; color:black;}");
	txtArr.push( "H1{FONT-WEIGHT:bold; FONT-SIZE:16pt; COLOR: #FFFFFF; BACKGROUND-COLOR: #345789; FONT-FAMILY: Arial, Helvetica, sans-serif; TEXT-ALIGN:center;}");
	txtArr.push( "H2{FONT-WEIGHT:bold; FONT-SIZE:14pt; COLOR:#345789; FONT-FAMILY:Arial, Helvetica, sans-serif; TEXT-ALIGN:left; margin-bottom:0; margin-top:6; TEXT-ALIGN:center;}");
	txtArr.push( "H3{FONT-WEIGHT:bold; FONT-SIZE:12pt; COLOR:#345789; FONT-FAMILY:Arial, Helvetica, sans-serif; TEXT-ALIGN:left; margin-bottom:0; margin-top:6}");
	txtArr.push( "</style>");
	txtArr.push( "</head>");
	txtArr.push( "<body>");
	txtArr.push( "<H1><b>ArtCAM JewelSmith - Object Viewer</b></H1>");
	txtArr.push( "<H2>" + globalStore.name_edit.value  + "</H2>");
	txtArr.push( "<table align=center id=summary_table cellspacing=0 cellpadding=0 border=0>");
   for(var index=0;index<globalStore.FramesEdit1.getValue();index++)
   {
      for(var index2=0;index2<globalStore.FramesEdit1.getValue();index2++)
      {
         txtArr.push( "<tr id=Row_" + index + "_" + index2 + " style='display:none'><td align=center><img src='images\\" + globalStore.name_edit.value  + "_" + index + "_" + index2 + globalStore.ImageExtension + "'></td></tr>");
      }
   }

   // Set the Indices to the last image, which will be the start image
   index--;
   index2--;

   txtArr.push( "<script>Row_"+index+"_"+index2+".style.display = ''</script>");
   txtArr.push( "<table align=center id=nudgeDiv border=0 cellspacing=0 cellpadding=0 style='table-layout:fixed'>");
   txtArr.push( "<colgroup><col width=32><col width=32><col width=32></colgroup>");
   txtArr.push( "<tr>");
   txtArr.push( "   <td height=32></td>");
   txtArr.push( "   <td height=32>");
   txtArr.push( "     <img id='NudgeYNegative' src='images/yneg.gif' ");
   txtArr.push( "        onmouseover='this.src = \"images/yneg_h.gif\"'");
   txtArr.push( "        onmouseout='this.src= \"images/yneg.gif\"'");
   txtArr.push( "        onclick='OnStepImage(1,0)'>");
   txtArr.push( "   </td>");
   txtArr.push( "   <td height=32></td>");
   txtArr.push( "</tr>");
   txtArr.push( "<tr>");
   txtArr.push( "   <td height=32>");
   txtArr.push( "     <img id='NudgeXNegative' src='images/xneg.gif' ");
   txtArr.push( "        onmouseover='this.src = \"images/xneg_h.gif\"'");
   txtArr.push( "        onmouseout='this.src= \"images/xneg.gif\"'");
   txtArr.push( "        onclick='OnStepImage(0,1)'>");
   txtArr.push( "   </td>");
   txtArr.push( "   <td height=32><img src='images/middle.gif'></td>");
   txtArr.push( "   <td height=32>");
   txtArr.push( "     <img id='NudgeXPositive' src='images/xpos.gif' ");
   txtArr.push( "        onmouseover='this.src = \"images/xpos_h.gif\"'");
   txtArr.push( "        onmouseout='this.src= \"images/xpos.gif\"'");
   txtArr.push( "        onclick='OnStepImage(0,0)'>");
   txtArr.push( "   </td>");
   txtArr.push( "</tr>");
   txtArr.push( "<tr>");
   txtArr.push( "   <td height=32></td>");
   txtArr.push( "   <td height=32>");
   txtArr.push( "     <img id='NudgeYPositive' src='images/ypos.gif' ");
   txtArr.push( "        onmouseover='this.src = \"images/ypos_h.gif\"'");
   txtArr.push( "        onmouseout='this.src= \"images/ypos.gif\"'");
   txtArr.push( "        onclick='OnStepImage(1,1)'>");
   txtArr.push( "   </td>");
   txtArr.push( "   <td height=32></td>");
   txtArr.push( "</tr>");
   txtArr.push( "<tr align=center>");
   txtArr.push( "  <td colspan=3 align=center>");
   txtArr.push( "    <input type=button id='spin_button' onclick='OnStartSpin()' value='Spin'>");
   txtArr.push( "  </td>");
   txtArr.push( "</tr>");
   txtArr.push( "</table>");

   txtArr.push( "<script>");
   txtArr.push( "var z_index = "+index+";");
   txtArr.push( "var y_index = "+index2+";");
   txtArr.push( "var max_images = " + max_images + ";");
  
   txtArr.push( "function OnStepImage(direction, positive)");
   txtArr.push( "{");
   txtArr.push( "  var row_id = 'Row_' + z_index + '_' + y_index;");
   txtArr.push( "  var row_object = document.getElementById(row_id);");
   txtArr.push( "  row_object.style.display = 'none';");
   txtArr.push( "   switch(direction)");
   txtArr.push( "   {");
   txtArr.push( "   case 0:");
   txtArr.push( "      if(positive)");
   txtArr.push( "         z_index++;");
   txtArr.push( "      else");
   txtArr.push( "         z_index--;");
   txtArr.push( "      break;");
   txtArr.push( "   case 1:");
   txtArr.push( "      if(positive)");
   txtArr.push( "         y_index++;");
   txtArr.push( "      else");
   txtArr.push( "        y_index--;");
   txtArr.push( "      break;");
   txtArr.push( "   default:");
   txtArr.push( "      return;");
   txtArr.push( "      break;");
   txtArr.push( "   }");
   
   txtArr.push( "   if(y_index<0)");
   txtArr.push( "      y_index = max_images;");
   txtArr.push( "   if(y_index>max_images)");
   txtArr.push( "      y_index = 0;");
   
   txtArr.push( "   if(z_index<0)");
   txtArr.push( "      z_index = max_images;");
   txtArr.push( "   if(z_index>max_images)");
   txtArr.push( "      z_index = 0;");

   txtArr.push( "  row_id = 'Row_' + z_index + '_' + y_index;");
   txtArr.push( "  row_object = document.getElementById(row_id);");
   txtArr.push( "  row_object.style.display = '';");
   txtArr.push( "}");

   txtArr.push( "function OnStartSpin()");
   txtArr.push( "{");
   txtArr.push( "   spin_button_object = document.getElementById('spin_button');");
   txtArr.push( "   spin_button_object.value = 'Stop';");
   txtArr.push( "   spin_button_object.onclick = OnStopSpin;");
   txtArr.push( "   gInterval = window.setInterval('CycleZ()',300);");
   txtArr.push( "}");
   
   txtArr.push( "function OnStopSpin()");
   txtArr.push( "{");
   txtArr.push( "   spin_button_object = document.getElementById('spin_button');");
   txtArr.push( "   spin_button_object.value = 'Spin';");
   txtArr.push( "   spin_button_object.onclick = OnStartSpin;");
   txtArr.push( "   window.clearInterval(gInterval);");
   txtArr.push( "   gInterval = 0;");
   txtArr.push( "}");
   
   txtArr.push( "function CycleZ()");
   txtArr.push( "{");
   txtArr.push( "var row_id = 'Row_' + z_index + '_' + y_index;");
   txtArr.push( "var row_object = document.getElementById(row_id);");
   txtArr.push( "row_object.style.display = 'none';");

   txtArr.push( "   z_index++;");
   txtArr.push( "   if(z_index<0)");
   txtArr.push( "      z_index = max_images;");
   txtArr.push( "   if(z_index>max_images)");
   txtArr.push( "      z_index = 0;");

   txtArr.push( " row_id = 'Row_' + z_index + '_' + y_index;");
   txtArr.push( " row_object = document.getElementById(row_id);");
   txtArr.push( "row_object.style.display = '';");

   txtArr.push( "}");
   txtArr.push( "</script>");
   
   txtArr.push( "</body>");
   txtArr.push( "</html>");
	
	var output_html = txtArr.join("\n");
	var info_filepath = movie_directory +  "\\" + globalStore.name_edit.value + ".htm";
	DirSelector.WriteTextFile(info_filepath, output_html);

 
   // Copy image files across from our images directory to the movie directory for the arrows
   var splitPath = artcam.CreateSplitPath( globalStore.PluginImageSrc ); 
   var dirList = artcam.CreateDirectoryList( artcam.HtmlRootDir + splitPath.Directory + "images");
   
   dirList.StartList("*.gif");
   while( dirList.ItemIsValid() )
   {  
      if( !dirList.ItemIsDirectory() )
      {
         splitPath.Path = dirList.ItemPath;
         DirSelector.CopyFile(splitPath.Path, image_directory + "\\" + splitPath.File + "." + splitPath.Extension, true);
      }
      dirList.NextItem();
   }
   dirList.EndList(); // Ensure the search handle is freed immediately

   // Now open this if requested
   if(globalStore.displayNow.checked)
   {
      var vidwin = window.open(info_filepath, "vidwin");
      vidwin.focus();
   }
}


function OnOutputChanged()
{
   // Show hide appropriate div's 
   if(outputradio[0].checked)
   {
      FramesTable1.disabled = false;
      FramesEdit1.disabled = false;
      FramesEdit2.disabled = true;
      FramesTable2.disabled = true;     
   }
   else
   {
      FramesTable2.disabled = false;
      FramesEdit2.disabled = false;
      FramesEdit1.disabled = true;
      FramesTable1.disabled = true;
   }
}

function UpdateTotalFrames()
{
   TotalFrames.innerText = FramesEdit1.getValue() * FramesEdit1.getValue();
}