2024-03-20 18:08:17 -06:00

1292 lines
40 KiB
C#

//---------------------------------------------------------------
// Original Tribes 2 Editor by Drew "Mongo" Zilm
//
// Torque port and changes by Bruce "Monster" Wallace
// Big thanks to Drew for creating the base this particle Editor
// Was built from. And thanks to all those that helped or will
// help make it a great tool.
//---------------------------------------------------------------
// vers. 1.11a 09/05/02 Eric Forhan
// *Numerous bugs repaired--caps, misspells, etc.
// *Rearranged GUI--all particle and emitter settings on proper pages
// maxed-out and tested most settings ranges.
// *Found out that SpinSpeed is never saved or loaded (even in T2 version).
// +(Fixed in 1.12)
// *Made defaults.cs always run so that defaultEmitterNode is accessible
//
// notes: +Still does not run all the saved custom emitters
// v. 1.12 repaired spinSpeed. Now saves and loads properly--EJF
//------------Path Settings--------------------------------------
// I hope to eliminate the need for these soon
// Path to exported particle datablocks
$PE::SaveFilePath = expandFilename("~/Particles/");
// Path to particle .png files
// Make sure particletest.png is here, or, if the image path is changed, then
// change it in Saves.cs as well -- EJF
$PE::ParticleImagePath = expandFilename("~/Particles/*.png");
//---------------------------------------------------------------
//set defaults
function ParticleEditor::initializeParticleEditor(%this)
{
%this.maxSaves = 50;
//edit mode
$adjustment = 1;
%this.editMode = "position";
//end edit mode
%this.parChoices = 0;
DefaultEmitter.particles.windCoefficient = 0;
%this.initEmitterCount();
%this.FillTextureList();
%this.FillEmitterPopups(ParticleEditorEmitterPopup);
%this.FillEmitterPopups(ParticleEditorReplacePopup);
%this.FillLoadList();
%this.parIndex = 0;
%this.saveIndex = 1;
%this.parDataBlock = "DefaultEmitterNode";
%this.parCurrent = "";
%this.lifetimeMS = "";
}
function ParticleEditor::initEmitterCount(%this)
{
for(%i = 0; %i < DataBlockGroup.getCount(); %i++)
{
%obj = DataBlockGroup.getObject(%i);
if(%obj.getClassName() $= ParticleEmitterData)
{
%this.Emitters[%this.parChoices] = %obj.getName();
%this.parChoices++;
}
}
// TODO: Add Datablocks saved in Saves.cs
}
function ParticleEditor::replaceDefaultEmitter(%this, %control)
{
%index = %this.findEmitterString(%control, %control.getValue());
if(%index)
%this.setEmitter(%this.emitters[%index], DefaultEmitter);
localClientConnection.transmitDataBlocks(0);
}
function ParticleEditor::changeEmitter(%this, %control, %value)
{
if(%value !$= "")
{
%this.parDataBlock = "DefaultEmitterNode";
PE_toggleDataBlock.setValue("Default");
%texture = DefaultEmitter.particles.textureName;
%index = %this.findEmitterString(%control, %value);
if(%control $= particleEditorEmitterPopup)
{
%this.setEmitter(DefaultEmitter, %this.emitters[%index]);
EMITTER_TEXT.setValue(%this.emitters[%index]);
%this.parIndex = %index;
particleEditorSavePopup.setValue("");
}
else if(%control $= particleEditorSavePopup)
{
%this.readSave($Particle::Save[%index]);
%this.saveIndex = %index;
ParticleEditorEmitterPopup.setValue("");
}
if(%texture !$= DefaultEmitter.particles.textureName)
localClientConnection.transmitDataBlocks(0);
%this.getParticleMax();
%this.recreateEmitter();
}
}
function ParticleEditor::findEmitterString(%this, %source, %value)
{
%this.parCurrent = 0;
if((%source $= particleEditorEmitterPopup) || (%source $= ParticleEditorReplacePopup))
{
for(%i = 1; %i <= %this.parChoices; %i++)
{
if(%value $= %this.emitters[%i])
return %i;
}
}
else if(%source $= particleEditorSavePopup)
{
for(%i = 1; ($Particle::Save[%i] !$= ""); %i++)
{
if(%value $= getField($Particle::Save[%i], 0))
return %i;
}
}
return 0;
}
function ParticleEditor::nextEmitter(%this, %source)
{
%this.parDataBlock = "DefaultEmitterNode";
PE_toggleDataBlock.setValue("Default");
%texture = DefaultEmitter.particles.textureName;
if(%source $= "DefaultCycleButton")
{
if (%this.parIndex && (%this.parIndex < %this.parChoices) )
%this.parIndex++;
else
%this.parIndex = 1;
%this.setEmitter(DefaultEmitter, %this.emitters[%this.parIndex]);
EMITTER_TEXT.setValue(%this.emitters[%this.parIndex]);
particleEditorSavePopup.setValue("");
ParticleEditorEmitterPopup.setValue(%this.emitters[%this.parIndex]);
}
else if(%source $= "CustomCycleButton")//NewParticle.cs
{
if($Particle::Save[%this.saveIndex] $= "")
%this.saveIndex = 1;
if($Particle::Save[%this.saveIndex] $= "")
return;
%this.readSave($Particle::Save[%this.saveIndex]);
%this.saveIndex++;
}
if(%texture !$= DefaultEmitter.particles.textureName)
localClientConnection.transmitDataBlocks(0);
%this.getParticleMax();
%this.recreateEmitter();
}
function ParticleEditor::createEmitter(%this)
{
if(%this.lastPosition)
{
%position = %this.lastPosition;
%this.lastPosition = false;
}
else
%position = localClientConnection.getControlObject().getWorldBoxCenter();
%emitter = new ParticleEmitterNode() {
position = %position;
rotation = "1 0 0 0";
scale = "1 1 1";
dataBlock = %this.parDataBlock;
emitter = DefaultEmitter;
velocity = "1";
};
MissionCleanup.add( %emitter );
%this.parObject = %emitter;
}
function ParticleEditor::recreateEmitter(%this)
{
%obj = %this.parObject;
%this.updateHUD();
if(%this.delay) //emitter is in a loop must handle this
{
cancel( %this.loopThread );
%this.loopThread = %this.schedule(( PE_emitterLife ), loopEmitter, %delay);
if( isObject( %obj ) )
{
%this.lastPosition = %obj.position;
%obj.delete();
%this.parObject = false;
}
}
else if(%this.parObject) //there is an object already
{
%this.lastPosition = %obj.position;
%obj.delete();
%this.parObject = false;
}
else
%this.lastPosition = false;
%this.createEmitter();
localClientConnection.transmitDataBlocks(0);
}
function ParticleEditor::deleteCurrentObject(%this)
{
%obj = %this.parObject;
if( %obj )
{
Emitter_Text.setValue("");
ParticleEditorTextureList.setValue("");
ParticleEditorEmitterPopup.setValue("");
particleEditorSavePopup.setValue("");
PE_CurrentEmitter.setValue("");
%obj.delete();
}
if( %this.delay )
{
%this.delay = false;
PE_modeButton.text = "Constant";
cancel(%this.loopThread);
}
%this.parObject = false;
}
function ParticleEditor::toggleParticleDatablock(%this, %control)
{
if(%this.parDataBlock $= "DefaultEmitterNode")
{
%this.parDataBlock = "DoubleTimeEmitterNode";
//%control.setValue("Double");
%control.setText("Double");
}
else if(%this.parDataBlock $= "DoubleTimeEmitterNode")
{
%this.parDataBlock = "HalfTimeEmitterNode";
//%control.setValue("Half");
%control.setText("Half");
}
else
{
%this.parDataBlock = "DefaultEmitterNode";
//%control.setValue("Default");
%control.setText("Default");
}
if( %this.parObject )
%this.recreateEmitter();
}
function ParticleEditor::colorParticle(%this, %word, %value)
{
if(%this.parCurrentMax)
{
for(%i = 0; %i < 4; %i++)
{
%this.rgb[%i] = getWord(DefaultParticle.colors[%this.parCurrent], %i);
if(%i == %word)
%this.rgb[%i] = %value;
}
DefaultParticle.colors[%this.parCurrent] = "";
DefaultParticle.colors[%this.parCurrent] = (%this.rgb[0] @ " " @
%this.rgb[1] @ " " @ %this.rgb[2] @ " " @ %this.rgb[3]);
}
}
function ParticleEditor::dropEmitterAtCamera(%this)
{
%obj = %this.ParObject;
if( isObject(%obj) )
{
%obj.position = localClientConnection.getControlObject().getWorldBoxCenter();
%this.recreateEmitter();
}
else if( %this.delay )
{
%this.lastPosition = localClientConnection.getControlObject().getWorldBoxCenter();
%this.recreateEmitter();
}
}
function ParticleEditor::leaveEmitterInWorld(%this)
{
//you must reboot T2 to add a work in progress to the datablock list
if( particleEditor.parObject )
{
%emitterName = Emitter_Text.getValue();
if( isObject( %emitterName ) )
{
if( !isObject( MissionParticles ) )
{
%group = new simGroup( MissionParticles );
MissionGroup.add( MissionParticles );
}
%emitter = new ParticleEmitterNode() {
position = %this.parObject.position;
rotation = "1 0 0 0";
scale = "1 1 1";
dataBlock = %this.parDataBlock;
emitter = %emitterName;
velocity = "1";
};
MissionParticles.add( %emitter );
%this.deleteCurrentObject();
}
else
MessageBoxOK( "Datablock Failure", "Current particle must be converted into a datablock by exporting from Load/Save menu and reloading Torque. Unable to place non-datablocks in mission.");
}
else
MessageBoxOK( "Object Failed", "Currently there is no particle to add to the world.");
}
function ParticleEditor::replaceCurrentEmitter(%this)
{
//warning, no checks here but there is always a DefaultEmitter
%this.setEmitter(%this.emitters[%this.parIndex], DefaultEmitter);
}
function ParticleEditor::nextParticle(%this)
{
if(%this.parCurrentMax)//if there are particles
{
if(%this.parCurrent >= (%this.parCurrentMax-1))
%this.parCurrent = 0;
else
%this.parCurrent++;
}
%this.updateHud();
}
function ParticleEditor::checktime(%this, %value)
{
if(%this.parCurrent == 0)
DefaultEmitter.particles.times[%this.parCurrent] = 0;
else if((%this.parCurrent+1) == %this.parCurrentMax)
DefaultEmitter.particles.times[%this.parCurrent] = 1;
else
{
if(%value == 1)
DefaultEmitter.particles.times[%this.parCurrent] = 0.99;
else if(%value == 0)
DefaultEmitter.particles.times[%this.parCurrent] = 0.01;
else
DefaultEmitter.particles.times[%this.parCurrent] = %value;
}
}
function ParticleEditor::getParticleMax(%this)
{
%this.parCurrent = 0;
%this.parCurrentMax = 0;
for(%i = 0; DefaultParticle.times[%i] != 1; %i++)
%this.parCurrentMax++;
%this.parCurrentMax++;
}
function ParticleEditor::addParticle(%this)
{
if( %this.parCurrentMax < 5 )
{
DefaultParticle.times[ (%this.parCurrentMax - 1) ] = 0.75;
DefaultParticle.times[ %this.parCurrentMax ] = 1.0; //new end
%this.parCurrentMax++;
%this.recreateEmitter();
}
}
function ParticleEditor::removeParticle(%this)
{
if( %this.parCurrentMax > 2)
{
if( %this.parCurrent >= ( %this.parCurrentMax - 1) )
{
%this.parCurrent = 0;
Particle_Text.setValue(1);
}
DefaultParticle.times[ (%this.parCurrentMax - 2) ] = 1.0; //remove one
%this.parCurrentMax = ( %this.parCurrentMax - 1 );
%this.recreateEmitter();
}
}
function ParticleEditor::setSameSize(%this)
{
for(%i = 0; %i < %this.parCurrentMax; %i++)
{
if( %i != %this.parCurrent )
DefaultParticle.sizes[ %i ] = DefaultParticle.sizes[ %this.parCurrent ];
%this.recreateEmitter();
}
}
function ParticleEditor::setEmitter(%this, %destination, %reference)
{
if(%reference.getClassName() $= "ParticleEmitterData")
{
%destination.ejectionPeriodMS = %reference.ejectionPeriodMS;
%destination.periodVarianceMS = %reference.periodVarianceMS;
%destination.ejectionVelocity = %reference.ejectionVelocity;
%destination.velocityVariance = %reference.velocityVariance;
%destination.ejectionOffset = %reference.ejectionOffset;
%destination.thetaMin = %reference.thetaMin;
%destination.thetaMax = %reference.thetaMax;
%destination.phiReferenceVel = %reference.phiReferenceVel;
%destination.phiVariance = %reference.phiVariance;
%destination.overrideAdvances = %reference.overrideAdvances;
PE_emitterLife.setValue( %reference.lifetimeMS );
%destination.orientParticles = %reference.orientParticles;
%destination.orientOnVelocity = %reference.orientOnVelocity;
//the following line had a spelling error, but fixing it causes errors in the PE
//%desination.particles = %reference.particles;
%this.setParticle(%reference, %destination);
}
else
echo("Error: not an emitter object.");
}
function ParticleEditor::setParticle(%this, %reference, %destination)
{
if(%reference.particles.getClassName() $= "ParticleData")
{
%destination.particles.dragCoefficient = %reference.particles.dragCoefficient;
%destination.particles.gravityCoefficient = %reference.particles.gravityCoefficient;
%destination.particles.inheritedVelFactor = %reference.particles.inheritedVelFactor;
%destination.particles.constantAcceleration = %reference.particles.constantAcceleration;
%destination.particles.lifetimeMS = %reference.particles.lifetimeMS;
%destination.particles.lifetimeVarianceMS = %reference.particles.lifetimeVarianceMS;
%destination.particles.useInvAlpha = %reference.particles.useInvAlpha;
%destination.particles.spinRandomMin = %reference.particles.spinRandomMin;
%destination.particles.spinRandomMax = %reference.particles.spinRandomMax;
%destination.particles.textureName = %reference.particles.textureName;
// added by EJF
%destination.particles.spinSpeed = %reference.particles.spinSpeed;
//
%destination.particles.windCoefficient = %reference.particles.windCoefficient;
for(%i = 0; !%done; %i++)
{
if( %reference.particles.times[%i] == 1 )
%done = true;
$Data::Block[0] = $Data::Block[0] @
%destination.particles.times[%i] = %reference.particles.times[%i];
}
%done = false;
for(%i = 0; !%done; %i++)
{
if( %reference.particles.times[%i] == 1 )
%done = true;
$Data::Block[0] = $Data::Block[0] @
%destination.particles.colors[%i] = %reference.particles.colors[%i];
}
%done = false;
for(%i = 0; !%done; %i++)
{
if( %reference.particles.times[%i] == 1 )
%done = true;
$Data::Block[0] = $Data::Block[0] @
%destination.particles.sizes[%i] = %reference.particles.sizes[%i];
}
}
else
echo("Error: not a particle object.");
}
function ParticleEditor::printEmitter(%this, %reference)
{
error("**************Emitter*******************************");
echo("ejectionPeriodMS: " @ %reference.ejectionPeriodMS);
echo("Variance MS: " @ %reference.periodVarianceMS);
echo("Velocity: " @ %reference.ejectionVelocity);
echo("VelVAR: " @ %reference.velocityVariance);
echo("Offset: " @ %reference.ejectionOffset);
echo("ThetaMIN: " @ %reference.thetaMin);
echo("ThetaMAX: " @ %reference.thetaMax);
echo("PHIrefVAL: " @ %reference.phiReferenceVel);
echo("PHIVAR: " @ %reference.phiVariance);
echo("OrientParticles: " @ %reference.orientParticles);
echo("OrientOnVelocity: " @ %reference.orientOnVelocity);
echo("overrideAdvances: " @ %reference.overrideAdvances);
error("**************Emitter*******************************");
}
function ParticleEditor::printParticle(%this, %reference)
{
error("**************Particle*******************************");
echo("Drag: " @ %reference.particles.dragCoefficient);
echo("Gravity: " @ %reference.particles.gravityCoefficient);
echo("Wind: " @ %reference.particles.windCoefficient);
echo("InhVEL: " @ %reference.particles.inheritedVelFactor);
echo("Accel: " @ %reference.particles.constantAcceleration);
echo("Life: " @ %reference.particles.lifetimeMS);
echo("LifeVAR: " @ %reference.particles.lifetimeVarianceMS);
echo("InvAlpha: " @ %reference.particles.useInvAlpha);
echo("SpinMIN: " @ %reference.particles.spinRandomMin);
echo("SpinMAX: " @ %reference.particles.spinRandomMax);
echo("Texture: " @ %reference.particles.textureName);
echo("spinSpeed: " @ %reference.particles.spinSpeed);
echo("Color 1: " @ %reference.particles.colors[0]);
echo("Color 2: " @ %reference.particles.colors[1]);
echo("Color 3: " @ %reference.particles.colors[2]);
echo("Color 4: " @ %reference.particles.colors[3]);
echo("Size 1: " @ %reference.particles.sizes[0]);
echo("Size 2: " @ %reference.particles.sizes[1]);
echo("Size 3: " @ %reference.particles.sizes[2]);
echo("Size 4: " @ %reference.particles.sizes[3]);
echo("Times 1: " @ %reference.particles.times[0]);
echo("Times 2: " @ %reference.particles.times[1]);
echo("Times 3: " @ %reference.particles.times[2]);
echo("Times 4: " @ %reference.particles.times[3]);
error("**************Particle*******************************");
}
function ParticleEditor::getsavePattern(%this)
{
%i = 0;
%emitterChars = 7; //7 characters
%name = EMITTER_TEXT.getValue();
%length = strLen(%name);
%substring = getSubStr( %name, ( %length - %emitterChars), %emitterChars);
if( %substring $= "Emitter" )
%particleName = ( getSubStr(%name, 0, ( %length - %emitterChars )) @ "Particle" );
else
{
%particleName = ( %name @ "Particle" );
Emitter_Text.setValue( %name @ "Emitter" );
%this.updateHud();
}
%file[%i] = ( EMITTER_TEXT.getValue() );
%file[%i++] = %particleName;
%file[%i++] = DefaultEmitter.ejectionPeriodMS;
%file[%i++] = DefaultEmitter.periodVarianceMS;
%file[%i++] = DefaultEmitter.ejectionVelocity;
%file[%i++] = DefaultEmitter.velocityVariance;
%file[%i++] = DefaultEmitter.ejectionOffset;
%file[%i++] = DefaultEmitter.thetaMin;
%file[%i++] = DefaultEmitter.thetaMax;
%file[%i++] = DefaultEmitter.phiReferenceVel;
%file[%i++] = DefaultEmitter.phiVariance;
%file[%i++] = DefaultEmitter.orientParticles;
%file[%i++] = DefaultEmitter.orientOnVelocity;
%file[%i++] = DefaultEmitter.overrideAdvances;
%file[%i++] = PE_emitterLife.getValue();
%file[%i++] = DefaultEmitter.particles.dragCoefficient;
%file[%i++] = DefaultEmitter.particles.gravityCoefficient;
%file[%i++] = DefaultEmitter.particles.inheritedVelFactor;
%file[%i++] = DefaultEmitter.particles.constantAcceleration;
%file[%i++] = DefaultEmitter.particles.lifetimeMS;
%file[%i++] = DefaultEmitter.particles.lifetimeVarianceMS;
%file[%i++] = DefaultEmitter.particles.useInvAlpha;
%file[%i++] = DefaultEmitter.particles.spinRandomMin;
%file[%i++] = DefaultEmitter.particles.spinRandomMax;
%file[%i++] = DefaultEmitter.particles.windCoefficient;
%file[%i++] = DefaultEmitter.particles.textureName;
//added spinspeed to saves --ejf
%file[%i++] = DefaultEmitter.particles.spinSpeed;
for(%j = 0; !%done; %j++)
{
if( DefaultEmitter.particles.times[%j] == 1 )
%done = true;
%file[%i++] = DefaultEmitter.particles.times[%j];
}
%done = false;
for(%j = 0; !%done; %j++)
{
if( DefaultEmitter.particles.times[%j] == 1 )
%done = true;
%file[%i++] = DefaultEmitter.particles.colors[%j];
}
%done = false;
for(%j = 0; !%done; %j++)
{
if( DefaultEmitter.particles.times[%j] == 1 )
%done = true;
%file[%i++] = DefaultEmitter.particles.sizes[%j];
}
%total = %i;
%string = "";
for(%i=0; %i <= %total; %i++)
{
if(%i)
%string = %string @ "\n" @ %file[%i];
else
%string = %file[%i];
}
return %string;
}
function ParticleEditor::readSave(%this, %list)
{
%i = 1;
EMITTER_TEXT.setValue(getField(%list,0));
particleEditorEmitterPopup.setValue("");
particleEditorSavePopup.setValue(getField(%list,0));
DefaultEmitter.ejectionPeriodMS = getField(%list, (%i++));
DefaultEmitter.periodVarianceMS = getField(%list, (%i++));
DefaultEmitter.ejectionVelocity = getField(%list, (%i++));
DefaultEmitter.velocityVariance = getField(%list, (%i++));
DefaultEmitter.ejectionOffset = getField(%list, (%i++));
DefaultEmitter.thetaMin = getField(%list, (%i++));
DefaultEmitter.thetaMax = getField(%list, (%i++));
DefaultEmitter.phiReferenceVel = getField(%list, (%i++));
DefaultEmitter.phiVariance = getField(%list, (%i++));
DefaultEmitter.orientParticles = getField(%list, (%i++));
DefaultEmitter.orientOnVelocity = getField(%list, (%i++));
DefaultEmitter.overrideAdvances = getField(%list, (%i++));
PE_emitterLife.setValue( mFloor( getField(%list, (%i++)) ) );
DefaultEmitter.particles.dragCoefficient = getField(%list, (%i++));
DefaultEmitter.particles.gravityCoefficient = getField(%list, (%i++));
DefaultEmitter.particles.inheritedVelFactor = getField(%list, (%i++));
DefaultEmitter.particles.constantAcceleration = getField(%list, (%i++));
DefaultEmitter.particles.lifetimeMS = getField(%list, (%i++));
DefaultEmitter.particles.lifetimeVarianceMS = getField(%list, (%i++));
DefaultEmitter.particles.useInvAlpha = getField(%list, (%i++));
DefaultEmitter.particles.spinRandomMin = getField(%list, (%i++));
DefaultEmitter.particles.spinRandomMax = getField(%list, (%i++));
DefaultEmitter.particles.windCoefficient = getField(%list, (%i++));
DefaultEmitter.particles.textureName = getField(%list, (%i++));
//added spinSpeed--ejf
DefaultEmitter.particles.spinSpeed = getField(%list, (%i++));
for(%j = 0; !%done; %j++)
{
if( DefaultEmitter.particles.times[%j] == 1 )
%done = true;
DefaultEmitter.particles.times[%j] = getField(%list, %i++);
}
%done = false;
for(%j = 0; !%done; %j++)
{
if( DefaultEmitter.particles.times[%j] == 1 )
%done = true;
DefaultEmitter.particles.colors[%j] = getField(%list, %i++);
}
%done = false;
for(%j = 0; !%done; %j++)
{
if( DefaultEmitter.particles.times[%j] == 1 )
%done = true;
DefaultEmitter.particles.sizes[%j] = getField(%list, %i++);
}
ParticleEditorTextureList.setValue(DefaultEmitter.particles.textureName);
}
// TODO: Look over this and related functions and see if other options for saving would be useful or optimized.
function ParticleEditor::saveEmitter(%this)
{
%control = particleEditorSavePopup;
if(%this.parObject)
{
%list = %this.getSavePattern();
for(%i = 1;( (%i < %this.maxSaves) && (!%saved) ); %i++)
{
%emitter = Emitter_Text.getValue();
if( ($PARTICLE::SAVE[%i] $= "") || (%emitter $= getWord($PARTICLE::SAVE[%i],0)) )
{
if( $PARTICLE::SAVE[%i] $= "" )//this is new
%control.add(%emitter, (%i-1));
$PARTICLE::SAVE[%i] = %list;
%this.changeEmitter(%control, %emitter);
particleEditorSavePopup.setValue(%emitter);
%saved = true;
}
}
echo("Exporting $PARTICLE::* to Saves.cs");
export("$PARTICLE::*", "./Saves.cs", False);
}
}
// TODO: Look at options for the save file path and look over this in general
function ParticleEditor::createDataBlock(%this, %reference)
{
//name the particle appropriately
%emitterChars = 7; //7 characters
%name = EMITTER_TEXT.getValue();
%length = strLen(%name);
%substring = getSubStr( %name, ( %length - %emitterChars), %emitterChars);
if( %substring $= "Emitter" )
%particleName = ( getSubStr(%name, 0, ( %length - %emitterChars )) @ "Particle" );
else
%particleName = ( %name @ "Particle" );
//call it a particle
%this.saveEmitter();
$Data::Block[0] ="datablock ParticleData(" @ %particleName @ ")" @
"\n{" @
"\n dragCoefficient = " @ %reference.particles.dragCoefficient @ ";" @
"\n gravityCoefficient = " @ %reference.particles.gravityCoefficient @ ";" @
"\n windCoefficient = " @ %reference.particles.windCoefficient @ ";" @
"\n inheritedVelFactor = " @ %reference.particles.inheritedVelFactor @ ";" @
"\n constantAcceleration = " @ %reference.particles.constantAcceleration @ ";" @
"\n lifetimeMS = " @ %reference.particles.lifetimeMS @ ";" @
"\n lifetimeVarianceMS = " @ %reference.particles.lifetimeVarianceMS @ ";" @
"\n useInvAlpha = " @ %reference.particles.useInvAlpha @ ";" @
"\n spinRandomMin = " @ %reference.particles.spinRandomMin @ ";" @
"\n spinRandomMax = " @ %reference.particles.spinRandomMax @ ";" @
"\n textureName = \"" @ %reference.particles.texturename @ "\";" @
// added spinSpeed -- ejf
"\n spinSpeed = " @ %reference.particles.spinSpeed @ ";";
for(%i = 0; !%done; %i++)
{
if( %reference.particles.times[%i] == 1 )
%done = true;
$Data::Block[0] = $Data::Block[0] @
"\n times[" @ %i @ "] = " @ %reference.particles.times[%i] @ ";";
}
%done = false;
for(%i = 0; !%done; %i++)
{
if( %reference.particles.times[%i] == 1 )
%done = true;
$Data::Block[0] = $Data::Block[0] @
"\n colors[" @ %i @ "] = \"" @ %reference.particles.colors[%i] @ "\";";
}
%done = false;
for(%i = 0; !%done; %i++)
{
if( %reference.particles.times[%i] == 1 )
%done = true;
$Data::Block[0] = $Data::Block[0] @
"\n sizes[" @ %i @ "] = " @ %reference.particles.sizes[%i] @ ";";
}
$Data::Block[0] = $Data::Block[0] @ "\n};\n\n";
//end particle data
$Data::Block[1] = "datablock ParticleEmitterData(" @ EMITTER_TEXT.getValue() @ ")" @
"\n{" @
"\n ejectionPeriodMS = " @ %reference.ejectionPeriodMS @ ";" @
"\n periodVarianceMS = " @ %reference.periodVarianceMS @ ";" @
"\n ejectionVelocity = " @ %reference.ejectionVelocity @ ";" @
"\n velocityVariance = " @ %reference.velocityVariance @ ";" @
"\n ejectionOffset = " @ %reference.ejectionOffset @ ";" @
"\n thetaMin = " @ %reference.thetaMin @ ";" @
"\n thetaMax = " @ %reference.thetaMax @ ";" @
"\n phiReferenceVel = " @ %reference.phiReferenceVel @ ";" @
"\n phiVariance = " @ %reference.phiVariance @ ";" @
"\n overrideAdvances = " @ %reference.overrideAdvances @ ";";
if( PE_emitterLife.getValue() )
$Data::Block[1] = $Data::Block[1] @
"\n lifetimeMS = " @ PE_emitterLife.getValue() @ ";";
$Data::Block[1] = $Data::Block[1] @
"\n orientParticles= " @ %reference.orientParticles @ ";" @
"\n orientOnVelocity = " @ %reference.orientOnVelocity @ ";" @
"\n particles = \"" @ %particleName @ "\";" @
"\n};";
echo("Exporting Datablock....");
%filename = Emitter_Text.getValue();
%filename = fileBase( %filename );
if ( %filename $= "" )
return;
new fileObject( "saveFile" );
saveFile.openForWrite( $PE::SaveFilePath @ %filename @ ".cs" );
saveFile.writeLine($Data::Block[0] @ $Data::Block[1]);
saveFile.close();
saveFile.delete();
}
function ParticleEditor::loopEmitter(%this, %delay)
{
%obj = %this.parObject;
if(%this.delay) //keep looping
{
if( isObject( %obj ) )
{
%this.lastPosition = %obj.position;
%obj.delete();
%this.parObject = "";
%this.loopThread = %this.schedule( ( PE_emitterLifeDelay.getValue() ), loopEmitter, %delay);
}
else//create new one
{
%this.createEmitter();
%this.loopThread = %this.schedule( ( PE_emitterLife.getValue() ), loopEmitter, %delay);
}
}
else //no more loops
{
if( !isObject(%obj) )
%this.createEmitter();
cancel(%this.loopThread);
}
}
function ParticleEditor::toggleLoopDelay(%this, %delay)
{
if(%this.delay)
{
%this.delay = false;
PE_modeButton.text = "Constant";
%this.loopEmitter(false);
}
else
{
%this.delay = true;
PE_modeButton.text = "Simulation Loop";
%this.loopEmitter(%delay);
}
}
function ParticleEditor::changeEmitterLife(%this, %value)
{
%obj = %this.parObject;
%life = mFloor( %value );
PE_emitterLifeText.setValue( %life );
PE_emitterLifeTextWorld.setValue( %life );
if(%this.delay)
{
if( isObject(%obj) )
{
%this.lastPosition = %obj.position;
%obj.delete();
}
%this.createEmitter();
cancel(%this.loopThread);
if ( %life )
%this.loopThread = %this.schedule( ( PE_emitterLife.getValue() ), loopEmitter, %delay);
else
{
PE_modeButton.text = "Constant";
%this.delay = false;
}
}
}
function ParticleEditor::changeOrientation(%this, %spot, %adjustment)
{
%obj = %this.parObject;
if( isObject(%obj) )
{
if( %this.editMode $= "position")
%change = %obj.position;
else
%change = %obj.rotation;
}
else if( %this.delay ) //if its looping
%change = %this.lastPosition;
if( %change )
{
for(%i = 0; %i < 3; %i++)
{
if(%i == %spot)
%temp[%i] = ( getWord(%change, %spot) + %adjustment );
else
{
%temp[%i] = getWord(%change, %i);
if( !%temp[%i] )
%temp[%i] = 0;
}
}
if( %this.editMode $= "position")
%change = (%temp[0] @ " " @ %temp[1] @ " " @ %temp[2]);
else
%change = (%temp[0] @ " " @ %temp[1] @ " " @ %temp[2]);
if( isObject(%obj) )
%obj.position = %change;
else
%this.lastPosition = %change;
%this.recreateEmitter();
}
}
function ParticleEditor::toggleEditMode(%this)
{
if( %this.EditMode $= "position" )
{
%state = "Rotate";
%this.EditMode = "rotation";
}
else
{
%state = "Move";
%this.EditMode = "position";
}
Edit_Mode.setValue(%state);
}
function ParticleEditor::SaveMission(%this)
{
//open the save dialog
if( !isObject( Emitter_Text.getValue() ) )
{
MessageBoxYesNo("CONFIRM", "The current particle isn't a datablock and therefore can't be saved in mission.. save anyway?" ,
"canvas.pushDialog( EditorSaveMissionDlg ); ");
}
else
canvas.pushDialog( EditorSaveMissionDlg );
}
function ParticleEditor::nextTexture(%this, %change)
{
%current = ParticleEditorTextureList.getSelected();
if( %change > 0 ) //positive
{
%current++;
}
else if( %change < 0 ) //negative
{
%current--;
if ( %current < 0 )
{
%current = (ParticleEditorTextureList.size() - 2);
}
}
ParticleEditorTextureList.setSelected( %current );
%currentValue = ParticleEditorTextureList.getValue();
%this.emitterSliderUpdate(ParticleEditorTextureList, %currentValue);
}
//////////////////////////////
//gui functions and controls
//////////////////////////////
function particleEditor::onWake(%this)
{
if(!particleEditor.initialized)
{
ParticleEditor.initializeParticleEditor();
ParticleEditor.initialized = true;
}
ParticleEditor.soundHandle = alxPlay(AudioButtonOver, 0, 0, 0);
if (!Canvas.isCursorOn())
CursorOn();
ParticleEditor.setPane(particleEditor.pane, particleEditor.tab);
ParticleEditor.updatehud();
}
function ParticleEditor::FillEmitterPopups(%this, %control)
{
if(ParticleEditor.parChoices)
for(%i = 1; %i <= ParticleEditor.parChoices; %i++)
%control.add(ParticleEditor.emitters[%i],(%i-1),1);
}
function ParticleEditorTextureList::FillItem()
{
%textures = 0;
for(%i = 1; %i <= ParticleEditor.parChoices; %i++)
{
%duplicate = false;
%current = ParticleEditor.Emitters[%i].particles.textureName;
for(%j = 0; %j <= %textures; %j++)
{
if(%current $= %texture[%j])
%duplicate = true;
}
if((%current !$= "") && (!%duplicate))
{
ParticleEditorTextureList.add(%current,(%i-1),1);
%texture[%textures] = %current;
%textures++;
}
}
}
function particleEditor::onSleep()
{
if(isObject(ParticleEditor.soundHandle))
{
alxStop(ParticleEditor.soundHandle);
ParticleEditor.soundHandle = "";
}
if (Canvas.isCursorOn())
CursorOff();
}
function ParticleEditor::updateHud(%this)
{
if(DefaultEmitter $= "")
{
EMITTER_TEXT.setValue("");
ParticleEditorEmitterPopup.setValue("");
}
if( %this.parCurrentMax )
{
PARTICLE_TEXT.setValue( ( %this.parCurrent + 1) );
PE_Total_Particles.setValue( %this.parCurrentMax -1 );
}
else
{
PARTICLE_TEXT.setValue("0");
PE_Total_Particles.setValue("0");
}
R_SLIDER.setValue(getWord(DefaultEmitter.particles.colors[ParticleEditor.parCurrent],0));
G_SLIDER.setValue(getWord(DefaultEmitter.particles.colors[ParticleEditor.parCurrent],1));
B_SLIDER.setValue(getWord(DefaultEmitter.particles.colors[ParticleEditor.parCurrent],2));
O_SLIDER.setValue(getWord(DefaultEmitter.particles.colors[ParticleEditor.parCurrent],3));
ParticleEditorTextureList.setValue(DefaultEmitter.particles.textureName);
Wind_Slider.setValue(DefaultEmitter.particles.windCoefficient);
PE_CurrentEmitter.setValue(EMITTER_TEXT.getValue());
ORIENT.setValue(DefaultEmitter.orientParticles);
ORIENT_VELOCITY.setValue(DefaultEmitter.orientOnVelocity);
OVERRIDE_ADVANCES.setValue(DefaultEmitter.overrideAdvances);
EPERIOD_SLIDER.setValue(DefaultEmitter.ejectionPeriodMS);
EVARIANCE_SLIDER.setValue(DefaultEmitter.periodVarianceMS);
EVELOCITY_SLIDER.setValue(DefaultEmitter.ejectionVelocity);
EOFFSET_SLIDER.setValue(DefaultEmitter.ejectionOffset);
EVELVARIANCE_SLIDER.setValue(DefaultEmitter.velocityVariance);
EOFFSET_SLIDER.setValue(DefaultEmitter.ejectionOffset);
THETAMIN_SLIDER.setValue(DefaultEmitter.thetaMin);
THETAMAX_SLIDER.setValue(DefaultEmitter.thetaMax);
PHIREFVEL_SLIDER.setValue(DefaultEmitter.phiReferenceVel);
PHIVAR_SLIDER.setValue(DefaultEmitter.phiVariance);
SIZES_SLIDER.setValue(DefaultEmitter.particles.sizes[ParticleEditor.parCurrent]);
TIMES_SLIDER.setValue(DefaultEmitter.particles.times[ParticleEditor.parCurrent]);
if( (ParticleEditor.parCurrent) && (ParticleEditor.parCurrent < (ParticleEditor.parCurrentMax - 1)) )
{
TIMES_SLIDER.setVisible(1);
Blend_Text.setVisible(1);
}
else //hide them when they can't be used anyway
{
TIMES_SLIDER.setVisible(0);
Blend_Text.setVisible(0);
}
DRAG_SLIDER.setValue(DefaultEmitter.particles.dragCoefficient);
GRAVITY_SLIDER.setValue(DefaultEmitter.particles.gravityCoefficient);
InVELOCITY_SLIDER.setValue(DefaultEmitter.particles.inheritedVelFactor);
ConACC_SLIDER.setValue(DefaultEmitter.particles.constantAcceleration);
INV_ALPHA.setValue(DefaultEmitter.particles.useInvAlpha);
LifeMS_SLIDER.setValue(DefaultEmitter.particles.lifetimeMS);
LifeVAR_SLIDER.setValue(DefaultEmitter.particles.lifetimeVarianceMS);
SpinMIN_SLIDER.setValue(DefaultEmitter.particles.spinRandomMin);
SpinMAX_SLIDER.setValue(DefaultEmitter.particles.spinRandomMax);
//text
PE_emitterLifeText.setValue(mFloor( PE_emitterLife.getValue() ) );
PE_emitterLifeTextWorld.setValue( PE_emitterLifeText.getValue() );
PE_redText.setValue(R_SLIDER.getValue());
PE_greenText.setValue(G_SLIDER.getValue());
PE_blueText.setValue(B_SLIDER.getValue());
PE_opacityText.setValue(O_SLIDER.getValue());
}
function ParticleEditor::emitterSliderUpdate(%this, %slider, %value)
{
switch$ ( %slider )
{
case "EPERIOD_SLIDER":
DefaultEmitter.ejectionPeriodMS = %value;
case "EVARIANCE_SLIDER":
DefaultEmitter.periodVarianceMS = %value;
case "EVELOCITY_SLIDER":
DefaultEmitter.ejectionVelocity = %value;
case "EVELVARIANCE_SLIDER":
DefaultEmitter.velocityVariance = %value;
case "EOFFSET_SLIDER":
DefaultEmitter.ejectionOffset = %value;
case "THETAMIN_SLIDER":
DefaultEmitter.thetaMin = %value;
case "THETAMAX_SLIDER":
DefaultEmitter.thetaMax = %value;
case "PHIREFVEL_SLIDER":
DefaultEmitter.phiReferenceVel = %value;
case "PHIVAR_SLIDER":
DefaultEmitter.phiVariance = %value;
case "ORIENT_VELOCITY":
DefaultEmitter.orientOnVelocity = %value;
case "ORIENT":
DefaultEmitter.orientParticles = %value;
case "OVERRIDE_ADVANCES":
DefaultEmitter.overrideAdvances = %value;
case "ParticleEditorTextureList":
DefaultEmitter.particles.textureName = %value;
case "Wind_Slider":
DefaultEmitter.particles.windCoefficient = %value;
case "SIZES_SLIDER":
DefaultEmitter.particles.sizes[ParticleEditor.parCurrent] = %value;
case "TIMES_SLIDER":
ParticleEditor.checktime(%value);
case "DRAG_SLIDER":
DefaultEmitter.particles.dragCoefficient = %value;
case "GRAVITY_SLIDER":
DefaultEmitter.particles.gravityCoefficient = %value;
case "InVELOCITY_SLIDER":
DefaultEmitter.particles.inheritedVelFactor = %value;
case "ConACC_SLIDER":
DefaultEmitter.particles.constantAcceleration = %value;
case "INV_ALPHA":
DefaultEmitter.particles.useInvAlpha = %value;
case "LifeMS_SLIDER":
DefaultEmitter.particles.lifetimeMS = %value;
case "LifeVAR_SLIDER":
DefaultEmitter.particles.lifetimeVarianceMS = %value;
case "SpinMIN_SLIDER":
DefaultEmitter.particles.spinRandomMin = %value;
case "SpinMAX_SLIDER":
DefaultEmitter.particles.spinRandomMax = %value;
case "SpinSPEED_SLIDER":
DefaultEmitter.particles.spinSpeed = %value;
case "R_SLIDER":
ParticleEditor.colorParticle(0, %value);
case "G_SLIDER":
ParticleEditor.colorParticle(1, %value);
case "B_SLIDER":
ParticleEditor.colorParticle(2, %value);
case "O_SLIDER":
ParticleEditor.colorParticle(3, %value);
}
if(ParticleEditor.parObject)
particleEditor.recreateEmitter();
}
function ParticleEditor::setPane(%this, %pane, %tab)
{
if(%pane $= "") //set default pane
{
%pane = "LoadSavePane";
%tab = "LoadSaveTab";
}
LoadSavePane.setVisible(false);
Particle1Pane.setVisible(false);
//Particle2Pane.setVisible(false);
//Particle3Pane.setVisible(false);
//Particle4Pane.setVisible(false);
EmitterPane.setVisible(false);
WorldPane.setVisible(false);
LoadSaveTab.setValue(false);
Particle1Tab.setValue(false);
//Particle2Tab.setValue(false);
//Particle3Tab.setValue(false);
//Particle4Tab.setValue(false);
EmitterTab.setValue(false);
WorldTab.setValue(false);
%pane.setVisible(true);
%tab.setValue(true);
ParticleEditor.pane = %pane;
ParticleEditor.tab = %tab;
}
function ParticleEditor::fillLoadList()
{
for(%i = 1; ($PARTICLE::SAVE[%i] !$= ""); %i++)
{
particleEditorSavePopup.add(getWord($PARTICLE::SAVE[%i],0), (%i-1));
}
}
// TODO: Clean this function up
function ParticleEditor::fillTextureList()
{
%index = 0; //initialize
ParticleEditorTexturePopup.add( "particles" , %index );
%fileSpec = $PE::ParticleImagePath;
%overhead = ( strLen(%fileSpec) - 4 ); //5 is for (*.png)
for ( %file = findFirstFile( %fileSpec ); %file !$= ""; %file = findNextFile( %fileSpec ) )
{
%length = strLen( %file );
%groupAdded = false;
//%texture = getSubStr( %file, %overhead, (%length - 5) );
%texture = %file;
//find root group
if( (%lastGroup $= getSubStr( %file, %overhead, strLen(%lastGroup) ) ) && ( %lastGroup !$= "") )//same group as last?
%group = %lastGroup;
else
{
%groupIndex = %overhead; //start in the textures group
%group = "";
for(%i = %overhead; %i < %length ; %i++)
{
%test = getSubStr( %file, %i, 1);//current char
if( %test $= "/") //root down
{
%group = getSubStr( %file, %groupIndex, (%i - %groupIndex) );
%groupIndex = ( %i + 1 );
}
}
}
//find out if this texture has a group available
for(%j = 0; %j <= %index; %j++)
{
if( %group $= "")
{
%groupAdded = true;
%flagged = false;
%existing = false;
for(%l = 0; !%flagged && !%existing; %l++)
{
if( ParticleEditorTexturePopup.texture[ 0, %l ] $= "" )
{
ParticleEditorTexturePopup.texture[ 0, %l ] = %texture;
%flagged = true;
%lastGroup = %group;
}
if( ParticleEditorTexturePopup.texture[ 0, %l ] $= %texture )
{
%existing = true;
%flagged = true;
%lastGroup = %group;
}
}
}
else if( (ParticleEditorTexturePopup.getTextByID( %j ) $= %group) )
{
%groupAdded = true;
%flagged = false;
for(%l = 0; !%flagged; %l++)
{
if( ParticleEditorTexturePopup.texture[ %j, %l ] $= "" )
{
ParticleEditorTexturePopup.texture[ %j, %l ] = %texture;
%flagged = true;
%lastGroup = %group;
}
}
}
}
if( !%groupAdded )//making a new group
{
ParticleEditorTexturePopup.add( %group, ( %index++ ) );
ParticleEditorTexturePopup.texture[ %index, 0 ] = %texture;
%lastGroup = %group;
}
}
}
function ParticleEditor::textureFill(%this, %element, %fileSpec)
{
ParticleEditorTextureList.clear();
for(%i = 0; ParticleEditorTexturePopup.texture[ %element, %i ] !$= ""; %i++)
ParticleEditorTextureList.add( ParticleEditorTexturePopup.texture[ %element, %i ], %i );
}