// 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.");
		%mod = "creator";
	}
	%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 creator.");
		%mod = "creator";
	}
	%filename = %mod @ "/" @ $ParticleEditor::currParticle @ ".cs";
	$ParticleEditor::currParticle.save(%filename);
}

