// The Particle Editor!
// Edits both emitters and their particles in realtime in game.
// 
// Open the particle editor to spawn a test emitter in front of the player.
// Edit the sliders, check boxes, and text fields and see the results in
// realtime.  Switch between emitters and particles with the buttons in the
// top left corner.  When in particle mode, the only particles available will
// be those assigned to the current emitter to avoid confusion.  In the top
// right corner, there is a button marked "Drop Emitter", which will spawn the
// test emitter in front of the player again, and a button marked "Restart
// Emitter", which will play the particle animation again.

//TODO: animTexName on Particles (max 50)

function toggleParticleEditor(%val)
{
   if (!%val)
      return;

   if ($ParticleEditor::isOpen)
   {
      Canvas.popDialog(ParticleEditor);
      $ParticleEditor::isOpen = false;
      return;
   }

   if (!isObject(ParticleEditor))
   {
      exec("common/editor/ParticleEditor.gui");
      ParticleEditor.initEditor();
   }
   ParticleEditor.startup();

   Canvas.pushDialog(ParticleEditor);
   $ParticleEditor::isOpen = true;
}


function ParticleEditor::startup(%this)
{
   $ParticleEditor::activeEditor.updateControls();
   if (!isObject($ParticleEditor::emitterNode))
      %this.resetEmitterNode();
}

function ParticleEditor::initEditor(%this)
{
   echo("Initializing ParticleEmitterData and ParticleData DataBlocks...");

   %count = DatablockGroup.getCount();
   %emitterCount = 0;
   %particleCount = 0;

   PEE_EmitterSelector.clear();
   PEE_EmitterParticleSelector1.clear();
   PEE_EmitterParticleSelector2.clear();
   PEE_EmitterParticleSelector3.clear();
   PEE_EmitterParticleSelector4.clear();
   PEP_ParticleSelector.clear();
   for (%i = 0; %i < %count; %i++)
   {
      %obj = DatablockGroup.getObject(%i);
      if (%obj.getClassName() $= "ParticleEmitterData")
      {
         PEE_EmitterSelector.add(%obj.getName(), %emitterCount);
         %emitterCount++;
      }
      if (%obj.getClassName() $= "ParticleData")
      {
         PEE_EmitterParticleSelector1.add(%obj.getName(), %particleCount);
         PEE_EmitterParticleSelector2.add(%obj.getName(), %particleCount);
         PEE_EmitterParticleSelector3.add(%obj.getName(), %particleCount);
         PEE_EmitterParticleSelector4.add(%obj.getName(), %particleCount);
         %particleCount++;
      }
   }
   PEE_EmitterParticleSelector2.add("", %particleCount); //insert a blank space
   PEE_EmitterParticleSelector3.add("", %particleCount); //insert a blank space
   PEE_EmitterParticleSelector4.add("", %particleCount); //insert a blank space

   echo("Found" SPC %emitterCount SPC "emitters and" SPC %particleCount SPC "particles.");

   PEE_EmitterSelector.sort();
   PEE_EmitterParticleSelector1.sort();
   PEE_EmitterParticleSelector2.sort();
   PEE_EmitterParticleSelector3.sort();
   PEE_EmitterParticleSelector4.sort();

   PEE_EmitterSelector.setSelected(0);

   %this.openEmitterPane();
 }

function PE_EmitterEditor::updateControls(%this)
{
   %id = PEE_EmitterSelector.getSelected();
   %data = PEE_EmitterSelector.getTextById(%id);

   PEE_ejectionPeriodMS.setValue(   %data.ejectionPeriodMS);
   PEE_periodVarianceMS.setValue(   %data.periodVarianceMS);
   PEE_ejectionVelocity.setValue(   %data.ejectionVelocity);
   PEE_velocityVariance.setValue(   %data.velocityVariance);
   PEE_ejectionOffset.setValue(     %data.ejectionOffset);
   PEE_lifetimeMS.setValue(         %data.lifetimeMS);
   PEE_lifetimeVarianceMS.setValue( %data.lifetimeVarianceMS);
   PEE_thetaMin.setValue(           %data.thetaMin);
   PEE_thetaMax.setValue(           %data.thetaMax);
   PEE_phiReferenceVel.setValue(    %data.phiReferenceVel);
   PEE_phiVariance.setValue(        %data.phiVariance);
   PEE_overrideAdvance.setValue(    %data.overrideAdvance);
   PEE_orientParticles.setValue(    %data.orientParticles);
   PEE_orientOnVelocity.setValue(   %data.orientOnVelocity);
   PEE_useEmitterSizes.setValue(    %data.useEmitterSizes);
   PEE_useEmitterColors.setValue(   %data.useEmitterColors);

   PEE_EmitterParticleSelector1.setText(getField(%data.particles, 0));
   PEE_EmitterParticleSelector2.setText(getField(%data.particles, 1));
   PEE_EmitterParticleSelector3.setText(getField(%data.particles, 2));
   PEE_EmitterParticleSelector4.setText(getField(%data.particles, 3));

   $ParticleEditor::currEmitter = %data;
}

function PE_ParticleEditor::updateControls(%this)
{
   %id = PEP_ParticleSelector.getSelected();
   %data = PEP_ParticleSelector.getTextById(%id);

   PEP_dragCoefficient.setValue(     %data.dragCoefficient);
   PEP_windCoefficient.setValue(     %data.windCoefficient);
   PEP_gravityCoefficient.setValue(  %data.gravityCoefficient);
   PEP_inheritedVelFactor.setValue(  %data.inheritedVelFactor);
   PEP_constantAcceleration.setValue(%data.constantAcceleration);
   PEP_lifetimeMS.setValue(          %data.lifetimeMS);
   PEP_lifetimeVarianceMS.setValue(  %data.lifetimeVarianceMS);
   PEP_spinSpeed.setValue(           %data.spinSpeed);
   PEP_spinRandomMin.setValue(       %data.spinRandomMin);
   PEP_framesPerSec.setValue(        %data.framesPerSec);
   PEP_spinRandomMax.setValue(       %data.spinRandomMax);
   PEP_useInvAlpha.setValue(         %data.useInvAlpha);
   PEP_animateTexture.setValue(      %data.animateTexture);
   PEP_times0.setText(               %data.times[0]);
   PEP_times1.setText(               %data.times[1]);
   PEP_times2.setText(               %data.times[2]);
   PEP_times3.setText(               %data.times[3]);
   PEP_sizes0.setText(               %data.sizes[0]);
   PEP_sizes1.setText(               %data.sizes[1]);
   PEP_sizes2.setText(               %data.sizes[2]);
   PEP_sizes3.setText(               %data.sizes[3]);
   PEP_colors0.setText(              %data.colors[0]);
   PEP_colors1.setText(              %data.colors[1]);
   PEP_colors2.setText(              %data.colors[2]);
   PEP_colors3.setText(              %data.colors[3]);
   PEP_textureName.setText(          %data.textureName);

   $ParticleEditor::currParticle =   %data;
}

function ParticleEditor::openEmitterPane(%this)
{
   PE_Window.setText("Particle Editor - Emitters");
   PE_EmitterEditor.setVisible(true);
   PE_EmitterButton.setActive(false);
   PE_ParticleEditor.setVisible(false);
   PE_ParticleButton.setActive(true);
   PE_EmitterEditor.updateControls();
   $ParticleEditor::activeEditor = PE_EmitterEditor;
}

function ParticleEditor::openParticlePane(%this)
{
   PE_Window.setText("Particle Editor - Particles");
   PE_EmitterEditor.setVisible(false);
   PE_EmitterButton.setActive(true);
   PE_ParticleEditor.setVisible(true);
   PE_ParticleButton.setActive(false);

   PEP_ParticleSelector.clear();
   PEP_ParticleSelector.add(PEE_EmitterParticleSelector1.getText(), 0);
   %count = 1;
   if (PEE_EmitterParticleSelector2.getText() !$= "")
   {
      PEP_ParticleSelector.add(PEE_EmitterParticleSelector2.getText(), %count);
      %count++;
   }
   if (PEE_EmitterParticleSelector3.getText() !$= "")
   {
      PEP_ParticleSelector.add(PEE_EmitterParticleSelector3.getText(), %count);
      %count++;
   }
   if (PEE_EmitterParticleSelector4.getText() !$= "")
      PEP_ParticleSelector.add(PEE_EmitterParticleSelector4.getText(), %count);

   PEP_ParticleSelector.sort();
   PEP_ParticleSelector.setSelected(0);   //select the PEE_EmitterParticleSelector1 particle

   PE_ParticleEditor.updateControls();
   $ParticleEditor::activeEditor = PE_ParticleEditor;
}

function PE_EmitterEditor::updateEmitter(%this)
{
   $ParticleEditor::currEmitter.ejectionPeriodMS = PEE_ejectionPeriodMS.getValue();
   $ParticleEditor::currEmitter.periodVarianceMS = PEE_periodVarianceMS.getValue();
   if ($ParticleEditor::currEmitter.periodVarianceMS >= $ParticleEditor::currEmitter.ejectionPeriodMS)
   {
      $ParticleEditor::currEmitter.periodVarianceMS = $ParticleEditor::currEmitter.ejectionPeriodMS - 1;
      PEE_periodVarianceMS.setValue($ParticleEditor::currEmitter.periodVarianceMS);
   }
   $ParticleEditor::currEmitter.ejectionVelocity   = PEE_ejectionVelocity.getValue();
   $ParticleEditor::currEmitter.velocityVariance   = PEE_velocityVariance.getValue();
   if ($ParticleEditor::currEmitter.velocityVariance >= $ParticleEditor::currEmitter.ejectionVelocity)
   {
      $ParticleEditor::currEmitter.velocityVariance = $ParticleEditor::currEmitter.ejectionVelocity - 0.01;
      if ($ParticleEditor::currEmitter.velocityVariance < 0)
         $ParticleEditor::currEmitter.velocityVariance = 0;
      PEE_velocityVariance.setValue($ParticleEditor::currEmitter.velocityVariance);
   }
   $ParticleEditor::currEmitter.ejectionOffset     = PEE_ejectionOffset.getValue();
   $ParticleEditor::currEmitter.lifetimeMS         = PEE_lifetimeMS.getValue();
   $ParticleEditor::currEmitter.lifetimeVarianceMS = PEE_lifetimeVarianceMS.getValue();
   if ($ParticleEditor::currEmitter.lifetimeMS == 0)
   {
      $ParticleEditor::currEmitter.lifetimeVarianceMS = 0;
      PEE_lifetimeVarianceMS.setValue($ParticleEditor::currEmitter.lifetimeVarianceMS);
   }
   else if ($ParticleEditor::currEmitter.lifetimeVarianceMS >= $ParticleEditor::currEmitter.lifetimeMS)
   {
      $ParticleEditor::currEmitter.lifetimeVarianceMS = $ParticleEditor::currEmitter.lifetimeMS - 1;
      PEE_lifetimeVarianceMS.setValue($ParticleEditor::currEmitter.lifetimeVarianceMS);
   }
   $ParticleEditor::currEmitter.thetaMin           = PEE_thetaMin.getValue();
   $ParticleEditor::currEmitter.thetaMax           = PEE_thetaMax.getValue();
   $ParticleEditor::currEmitter.phiReferenceVel    = PEE_phiReferenceVel.getValue();
   $ParticleEditor::currEmitter.phiVariance        = PEE_phiVariance.getValue();
   $ParticleEditor::currEmitter.overrideAdvance    = PEE_overrideAdvance.getValue();
   $ParticleEditor::currEmitter.orientParticles    = PEE_orientParticles.getValue();
   $ParticleEditor::currEmitter.orientOnVelocity   = PEE_orientOnVelocity.getValue();
   $ParticleEditor::currEmitter.useEmitterSizes    = PEE_useEmitterSizes.getValue();
   $ParticleEditor::currEmitter.useEmitterColors   = PEE_useEmitterColors.getValue();
   $ParticleEditor::currEmitter.particles          = PEE_EmitterParticleSelector1.getText();

   if (PEE_EmitterParticleSelector2.getText() !$= "")
      $ParticleEditor::currEmitter.particles = $ParticleEditor::currEmitter.particles TAB PEE_EmitterParticleSelector2.getText();
   if (PEE_EmitterParticleSelector3.getText() !$= "")
      $ParticleEditor::currEmitter.particles = $ParticleEditor::currEmitter.particles TAB PEE_EmitterParticleSelector3.getText();
   if (PEE_EmitterParticleSelector4.getText() !$= "")
      $ParticleEditor::currEmitter.particles = $ParticleEditor::currEmitter.particles TAB PEE_EmitterParticleSelector4.getText();

   $ParticleEditor::currEmitter.reload();                        
}

function PE_ParticleEditor::updateParticle(%this)
{
   $ParticleEditor::currParticle.dragCoefficient      = PEP_dragCoefficient.getValue();
   $ParticleEditor::currParticle.windCoefficient      = PEP_windCoefficient.getValue();
   $ParticleEditor::currParticle.gravityCoefficient   = PEP_gravityCoefficient.getValue();
   $ParticleEditor::currParticle.inheritedVelFactor   = PEP_inheritedVelFactor.getValue();
   $ParticleEditor::currParticle.constantAcceleration = PEP_constantAcceleration.getValue();
   $ParticleEditor::currParticle.lifetimeMS           = PEP_lifetimeMS.getValue();
   $ParticleEditor::currParticle.lifetimeVarianceMS   = PEP_lifetimeVarianceMS.getValue();
   if ($ParticleEditor::currParticle.lifetimeVarianceMS >= $ParticleEditor::currParticle.lifetimeMS)
   {
      $ParticleEditor::currParticle.lifetimeVarianceMS = $ParticleEditor::currParticle.lifetimeMS - 1;
      PEP_lifetimeVarianceMS.setValue($ParticleEditor::currParticle.lifetimeVarianceMS);
   }
   $ParticleEditor::currParticle.spinSpeed            = PEP_spinSpeed.getValue();
   $ParticleEditor::currParticle.spinRandomMin        = PEP_spinRandomMin.getValue();
   $ParticleEditor::currParticle.spinRandomMax        = PEP_spinRandomMax.getValue();
   $ParticleEditor::currParticle.framesPerSec         = PEP_framesPerSec.getValue();
   $ParticleEditor::currParticle.useInvAlpha          = PEP_useInvAlpha.getValue();
   $ParticleEditor::currParticle.animateTexture       = PEP_animateTexture.getValue();

   $ParticleEditor::currParticle.times[0]             = PEP_times0.getValue();
   $ParticleEditor::currParticle.times[1]             = PEP_times1.getValue();
   $ParticleEditor::currParticle.times[2]             = PEP_times2.getValue();
   $ParticleEditor::currParticle.times[3]             = PEP_times3.getValue();
   $ParticleEditor::currParticle.sizes[0]             = PEP_sizes0.getValue();
   $ParticleEditor::currParticle.sizes[1]             = PEP_sizes1.getValue();
   $ParticleEditor::currParticle.sizes[2]             = PEP_sizes2.getValue();
   $ParticleEditor::currParticle.sizes[3]             = PEP_sizes3.getValue();
   $ParticleEditor::currParticle.colors[0]            = PEP_colors0.getValue();
   $ParticleEditor::currParticle.colors[1]            = PEP_colors1.getValue();
   $ParticleEditor::currParticle.colors[2]            = PEP_colors2.getValue();
   $ParticleEditor::currParticle.colors[3]            = PEP_colors3.getValue();

   $ParticleEditor::currParticle.textureName          = PEP_textureName.getValue();

   $ParticleEditor::currParticle.reload();                        
}

function PE_EmitterEditor::onNewEmitter(%this)
{
   ParticleEditor.updateEmitterNode();
   PE_EmitterEditor.updateControls();
}

function PE_ParticleEditor::onNewParticle(%this)
{
   PE_ParticleEditor.updateControls();
}

function ParticleEditor::resetEmitterNode(%this)
{
   %tform = ServerConnection.getControlObject().getEyeTransform();
   %vec = VectorNormalize(ServerConnection.getControlObject().getForwardVector());
   %vec = VectorScale(%vec, 4);
   %tform = setWord(%tform, 0, getWord(%tform, 0) + getWord(%vec, 0));
   %tform = setWord(%tform, 1, getWord(%tform, 1) + getWord(%vec, 1));
   %tform = setWord(%tform, 2, getWord(%tform, 2) + getWord(%vec, 2));

   if (!isObject($ParticleEditor::emitterNode))
   {
      if (!isObject(TestEmitterNodeData))
      {
         datablock ParticleEmitterNodeData(TestEmitterNodeData)
         {
            timeMultiple = 1;
         };
      }

      $ParticleEditor::emitterNode = new ParticleEmitterNode()
      {
         emitter = PEE_EmitterSelector.getText();
         velocity = 1;
         position = getWords(%tform, 0, 2);
         rotation = getWords(%tform, 3, 6);
         datablock = TestEmitterNodeData;
      };
      //grab the client-side emitter node so we can reload the emitter datablock
      $ParticleEditor::clientEmitterNode = $ParticleEditor::emitterNode+1;
   }
   else
   {
      $ParticleEditor::clientEmitterNode.setTransform(%tform);
      ParticleEditor.updateEmitterNode();
   }
}

function ParticleEditor::updateEmitterNode()
{
   $ParticleEditor::clientEmitterNode.setEmitterDataBlock(PEE_EmitterSelector.getText().getId());
}

function PE_EmitterEditor::save(%this)
{
   %mod = $currentMod;
   if (%mod $= "")
   {
      warn("Warning: No mod detected, saving in common.");
      %mod = "common";
   }
   %filename = %mod @ "/" @ $ParticleEditor::currEmitter @ ".cs";
   $ParticleEditor::currEmitter.save(%filename);
}

function PE_ParticleEditor::save(%this)
{
   %mod = $currentMod;
   if (%mod $= "")
   {
      warn("Warning: No mod detected, saving in common.");
      %mod = "common";
   }
   %filename = %mod @ "/" @ $ParticleEditor::currParticle @ ".cs";
   $ParticleEditor::currParticle.save(%filename);
}