context: // 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("creator/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 creator.");
  
gt: 		%mod = "creator";