//----------------------------------------------------------------------------- // Copyright (c) 2012 GarageGames, LLC // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to // deal in the Software without restriction, including without limitation the // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or // sell copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS // IN THE SOFTWARE. //----------------------------------------------------------------------------- $PE_PARTICLEEDITOR_DEFAULT_FILENAME = "art/particles/managedParticleData.cs"; //============================================================================================= // PE_ParticleEditor. //============================================================================================= //--------------------------------------------------------------------------------------------- function PE_ParticleEditor::guiSync( %this ) { // Populate the selector with the particles assigned // to the current emitter. %containsCurrParticle = false; %popup = PEP_ParticleSelector; %popup.clear(); foreach$( %particle in PE_EmitterEditor.currEmitter.particles ) { if( %particle.getId() == PE_ParticleEditor.currParticle ) %containsCurrParticle = true; %popup.add( %particle, %particle.getId() ); } // Just in case the particle doesn't exist, fallback gracefully if( !%containsCurrParticle ) PE_ParticleEditor.currParticle = getWord( PE_EmitterEditor.currEmitter.particles, 0 ).getId(); %data = PE_ParticleEditor.currParticle; %popup.sort(); %popup.setSelected( %data ); %bitmap = MaterialEditorGui.searchForTexture( %data.getName(), %data.textureName ); if( %bitmap !$= "" ) { PE_ParticleEditor-->PEP_previewImage.setBitmap( %bitmap ); PE_ParticleEditor-->PEP_previewImageName.setText( %bitmap ); PE_ParticleEditor-->PEP_previewImageName.tooltip = %bitmap; } else { PE_ParticleEditor-->PEP_previewImage.setBitmap( "" ); PE_ParticleEditor-->PEP_previewImageName.setText( "None" ); PE_ParticleEditor-->PEP_previewImageName.tooltip = "None"; } PE_ParticleEditor-->PEP_inverseAlpha.setValue( %data.useInvAlpha ); PE_ParticleEditor-->PEP_lifetimeMS_slider.setValue( %data.lifetimeMS ); PE_ParticleEditor-->PEP_lifetimeMS_textEdit.setText( %data.lifetimeMS ); PE_ParticleEditor-->PEP_lifetimeVarianceMS_slider.setValue( %data.lifetimeVarianceMS ); PE_ParticleEditor-->PEP_lifetimeVarianceMS_textEdit.setText( %data.lifetimeVarianceMS ); PE_ParticleEditor-->PEP_inheritedVelFactor_slider.setValue( %data.inheritedVelFactor ); PE_ParticleEditor-->PEP_inheritedVelFactor_textEdit.setText( %data.inheritedVelFactor ); PE_ParticleEditor-->PEP_constantAcceleration_slider.setValue( %data.constantAcceleration ); PE_ParticleEditor-->PEP_constantAcceleration_textEdit.setText( %data.constantAcceleration ); PE_ParticleEditor-->PEP_gravityCoefficient_slider.setValue( %data.gravityCoefficient ); PE_ParticleEditor-->PEP_gravityCoefficient_textEdit.setText( %data.gravityCoefficient ); PE_ParticleEditor-->PEP_dragCoefficient_slider.setValue( %data.dragCoefficient ); PE_ParticleEditor-->PEP_dragCoefficient_textEdit.setText( %data.dragCoefficient ); PE_ParticleEditor-->PEP_windCoefficient_slider.setValue( %data.windCoefficient ); PE_ParticleEditor-->PEP_windCoefficient_textEdit.setText( %data.windCoefficient ); PE_ParticleEditor-->PEP_spinRandomMin_slider.setValue( %data.spinRandomMin ); PE_ParticleEditor-->PEP_spinRandomMin_textEdit.setText( %data.spinRandomMin ); PE_ParticleEditor-->PEP_spinRandomMax_slider.setValue( %data.spinRandomMax ); PE_ParticleEditor-->PEP_spinRandomMax_textEdit.setText( %data.spinRandomMax ); PE_ParticleEditor-->PEP_spinRandomMax_slider.setValue( %data.spinRandomMax ); PE_ParticleEditor-->PEP_spinRandomMax_textEdit.setText( %data.spinRandomMax ); PE_ParticleEditor-->PEP_spinSpeed_slider.setValue( %data.spinSpeed ); PE_ParticleEditor-->PEP_spinSpeed_textEdit.setText( %data.spinSpeed ); PE_ColorTintSwatch0.color = %data.colors[ 0 ]; PE_ColorTintSwatch1.color = %data.colors[ 1 ]; PE_ColorTintSwatch2.color = %data.colors[ 2 ]; PE_ColorTintSwatch3.color = %data.colors[ 3 ]; PE_ParticleEditor-->PEP_pointSize_slider0.setValue( %data.sizes[ 0 ] ); PE_ParticleEditor-->PEP_pointSize_textEdit0.setText( %data.sizes[ 0 ] ); PE_ParticleEditor-->PEP_pointSize_slider1.setValue( %data.sizes[ 1 ] ); PE_ParticleEditor-->PEP_pointSize_textEdit1.setText( %data.sizes[ 1 ] ); PE_ParticleEditor-->PEP_pointSize_slider2.setValue( %data.sizes[ 2 ] ); PE_ParticleEditor-->PEP_pointSize_textEdit2.setText( %data.sizes[ 2 ] ); PE_ParticleEditor-->PEP_pointSize_slider3.setValue( %data.sizes[ 3 ] ); PE_ParticleEditor-->PEP_pointSize_textEdit3.setText( %data.sizes[ 3 ] ); PE_ParticleEditor-->PEP_pointTime_slider0.setValue( %data.times[ 0 ] ); PE_ParticleEditor-->PEP_pointTime_textEdit0.setText( %data.times[ 0 ] ); PE_ParticleEditor-->PEP_pointTime_slider1.setValue( %data.times[ 1 ] ); PE_ParticleEditor-->PEP_pointTime_textEdit1.setText( %data.times[ 1 ] ); PE_ParticleEditor-->PEP_pointTime_slider2.setValue( %data.times[ 2 ] ); PE_ParticleEditor-->PEP_pointTime_textEdit2.setText( %data.times[ 2 ] ); PE_ParticleEditor-->PEP_pointTime_slider3.setValue( %data.times[ 3 ] ); PE_ParticleEditor-->PEP_pointTime_textEdit3.setText( %data.times[ 3 ] ); //particle animation PE_ParticleEditor-->PEP_animateTexture.setValue( %data.animateTexture ); PE_ParticleEditor-->PEP_framesPerSec_slider.setValue( %data.framesPerSec ); PE_ParticleEditor-->PEP_framesPerSec_textEdit.setText( %data.framesPerSec ); PE_ParticleEditor-->PEP_animTexFramesList_textEdit.setText( %data.animTexFrames ); PE_ParticleEditor-->PEP_animTileCount_textEdit.setText( %data.animTexTiling ); } //--------------------------------------------------------------------------------------------- // Generic updateParticle method function PE_ParticleEditor::updateParticle(%this, %propertyField, %value, %isSlider, %onMouseUp) { PE_ParticleEditor.setParticleDirty(); %particle = PE_ParticleEditor.currParticle; %last = Editor.getUndoManager().getUndoAction(Editor.getUndoManager().getUndoCount() - 1); if( (%isSlider) && (%last.isSlider) && (!%last.onMouseUp) ) { %last.field = %propertyField; %last.isSlider = %isSlider; %last.onMouseUp = %onMouseUp; %last.newValue = %value; } else { %action = ParticleEditor.createUndo(ActionUpdateActiveParticle, "Update Active Particle"); %action.particle = %particle; %action.field = %propertyField; %action.isSlider = %isSlider; %action.onMouseUp = %onMouseUp; %action.newValue = %value; %action.oldValue = %particle.getFieldValue( %propertyField ); ParticleEditor.submitUndo( %action ); } %particle.setFieldValue( %propertyField, %value ); %particle.reload(); } //--------------------------------------------------------------------------------------------- // Special case updateEmitter methods function PE_ParticleEditor::updateParticleTexture( %this, %action ) { if( %action ) { %texture = MaterialEditorGui.openFile("texture"); if( %texture !$= "" ) { PE_ParticleEditor-->PEP_previewImage.setBitmap(%texture); PE_ParticleEditor-->PEP_previewImageName.setText(%texture); PE_ParticleEditor-->PEP_previewImageName.tooltip = %texture; PE_ParticleEditor.updateParticle( "textureName", %texture ); } } else { PE_ParticleEditor-->PEP_previewImage.setBitmap(""); PE_ParticleEditor-->PEP_previewImageName.setText(""); PE_ParticleEditor-->PEP_previewImageName.tooltip = ""; PE_ParticleEditor.updateParticle( "textureName", "" ); } } //--------------------------------------------------------------------------------------------- function PE_ParticleEditor::updateLifeFields( %this, %isRandom, %value, %isSlider, %onMouseUp ) { PE_ParticleEditor.setParticleDirty(); %particle = PE_ParticleEditor.currParticle; //Transfer values over to gui controls. if( %isRandom ) { %value ++; if( %value > PE_ParticleEditor-->PEP_lifetimeMS_slider.getValue() ) { PE_ParticleEditor-->PEP_lifetimeMS_textEdit.setText( %value ); PE_ParticleEditor-->PEP_lifetimeMS_slider.setValue( %value ); } } else { %value --; if( %value < PE_ParticleEditor-->PEP_lifetimeVarianceMS_slider.getValue() ) { PE_ParticleEditor-->PEP_lifetimeVarianceMS_textEdit.setText( %value ); PE_ParticleEditor-->PEP_lifetimeVarianceMS_slider.setValue( %value ); } } // Submit undo. %last = Editor.getUndoManager().getUndoAction(Editor.getUndoManager().getUndoCount() - 1); if( (%isSlider) && (%last.isSlider) && (!%last.onMouseUp) ) { %last.isSlider = %isSlider; %last.onMouseUp = %onMouseUp; %last.newValueLifetimeMS = PE_ParticleEditor-->PEP_lifetimeMS_textEdit.getText(); %last.newValueLifetimeVarianceMS = PE_ParticleEditor-->PEP_lifetimeVarianceMS_textEdit.getText(); } else { %action = ParticleEditor.createUndo(ActionUpdateActiveParticleLifeFields, "Update Active Particle"); %action.particle = %particle; %action.isSlider = %isSlider; %action.onMouseUp = %onMouseUp; %action.newValueLifetimeMS = PE_ParticleEditor-->PEP_lifetimeMS_textEdit.getText(); %action.oldValueLifetimeMS = %particle.lifetimeMS; %action.newValueLifetimeVarianceMS = PE_ParticleEditor-->PEP_lifetimeVarianceMS_textEdit.getText(); %action.oldValueLifetimeVarianceMS = %particle.lifetimeVarianceMS; ParticleEditor.submitUndo( %action ); } %particle.lifetimeMS = PE_ParticleEditor-->PEP_lifetimeMS_textEdit.getText(); %particle.lifetimeVarianceMS = PE_ParticleEditor-->PEP_lifetimeVarianceMS_textEdit.getText(); %particle.reload(); } //--------------------------------------------------------------------------------------------- function PE_ParticleEditor::updateSpinFields( %this, %isMax, %value, %isSlider, %onMouseUp ) { PE_ParticleEditor.setParticleDirty(); %particle = PE_ParticleEditor.currParticle; // Transfer values over to gui controls. if( %isMax ) { %value ++; if( %value > PE_ParticleEditor-->PEP_spinRandomMax_slider.getValue() ) { PE_ParticleEditor-->PEP_spinRandomMax_textEdit.setText( %value ); PE_ParticleEditor-->PEP_spinRandomMax_slider.setValue( %value ); } } else { %value --; if( %value < PE_ParticleEditor-->PEP_spinRandomMin_slider.getValue() ) { PE_ParticleEditor-->PEP_spinRandomMin_textEdit.setText( %value ); PE_ParticleEditor-->PEP_spinRandomMin_slider.setValue( %value ); } } // Submit undo. %last = Editor.getUndoManager().getUndoAction(Editor.getUndoManager().getUndoCount() - 1); if( (%isSlider) && (%last.isSlider) && (!%last.onMouseUp) ) { %last.isSlider = %isSlider; %last.onMouseUp = %onMouseUp; %last.newValueSpinRandomMax = PE_ParticleEditor-->PEP_spinRandomMax_textEdit.getText(); %last.newValueSpinRandomMin = PE_ParticleEditor-->PEP_spinRandomMin_textEdit.getText(); } else { %action = ParticleEditor.createUndo(ActionUpdateActiveParticleSpinFields, "Update Active Particle"); %action.particle = %particle; %action.isSlider = %isSlider; %action.onMouseUp = %onMouseUp; %action.newValueSpinRandomMax = PE_ParticleEditor-->PEP_spinRandomMax_textEdit.getText(); %action.oldValueSpinRandomMax = %particle.spinRandomMax; %action.newValueSpinRandomMin = PE_ParticleEditor-->PEP_spinRandomMin_textEdit.getText(); %action.oldValueSpinRandomMin = %particle.spinRandomMin; ParticleEditor.submitUndo( %action ); } %particle.spinRandomMax = PE_ParticleEditor-->PEP_spinRandomMax_textEdit.getText(); %particle.spinRandomMin = PE_ParticleEditor-->PEP_spinRandomMin_textEdit.getText(); %particle.reload(); } //--------------------------------------------------------------------------------------------- function PE_ParticleEditor::onNewParticle( %this ) { // Bail if the user selected the same particle. %id = PEP_ParticleSelector.getSelected(); if( %id == PE_ParticleEditor.currParticle ) return; // Load new particle if we're not in a dirty state if( PE_ParticleEditor.dirty ) { MessageBoxYesNoCancel("Save Existing Particle?", "Do you want to save changes to

" @ PE_ParticleEditor.currParticle.getName(), "PE_ParticleEditor.saveParticle(" @ PE_ParticleEditor.currParticle @ ");", "PE_ParticleEditor.saveParticleDialogDontSave(" @ PE_ParticleEditor.currParticle @ "); PE_ParticleEditor.loadNewParticle();" ); } else { PE_ParticleEditor.loadNewParticle(); } } //--------------------------------------------------------------------------------------------- function PE_ParticleEditor::loadNewParticle( %this, %particle ) { if( isObject( %particle ) ) %particle = %particle.getId(); else %particle = PEP_ParticleSelector.getSelected(); PE_ParticleEditor.currParticle = %particle; %particle.reload(); PE_ParticleEditor_NotDirtyParticle.assignFieldsFrom( %particle ); PE_ParticleEditor_NotDirtyParticle.originalName = %particle.getName(); PE_ParticleEditor.guiSync(); PE_ParticleEditor.setParticleNotDirty(); } //--------------------------------------------------------------------------------------------- function PE_ParticleEditor::setParticleDirty( %this ) { PE_ParticleEditor.text = "Particle *"; PE_ParticleEditor.dirty = true; %particle = PE_ParticleEditor.currParticle; if( %particle.getFilename() $= "" || %particle.getFilename() $= "tools/particleEditor/particleParticleEditor.ed.cs" ) PE_ParticleSaver.setDirty( %particle, $PE_PARTICLEEDITOR_DEFAULT_FILENAME ); else PE_ParticleSaver.setDirty( %particle ); } //--------------------------------------------------------------------------------------------- function PE_ParticleEditor::setParticleNotDirty( %this ) { PE_ParticleEditor.text = "Particle"; PE_ParticleEditor.dirty = false; PE_ParticleSaver.clearAll(); } //--------------------------------------------------------------------------------------------- function PE_ParticleEditor::showNewDialog( %this, %replaceSlot ) { // Open a dialog if the current Particle is dirty if( PE_ParticleEditor.dirty ) { MessageBoxYesNoCancel("Save Particle Changes?", "Do you wish to save the changes made to the
current particle before changing the particle?", "PE_ParticleEditor.saveParticle( " @ PE_ParticleEditor.currParticle.getName() @ " ); PE_ParticleEditor.createParticle( " @ %replaceSlot @ " );", "PE_ParticleEditor.saveParticleDialogDontSave( " @ PE_ParticleEditor.currParticle.getName() @ " ); PE_ParticleEditor.createParticle( " @ %replaceSlot @ " );" ); } else { PE_ParticleEditor.createParticle( %replaceSlot ); } } //--------------------------------------------------------------------------------------------- function PE_ParticleEditor::createParticle( %this, %replaceSlot ) { // Make sure we have a spare slot on the current emitter. if( !%replaceSlot ) { %numExistingParticles = getWordCount( PE_EmitterEditor.currEmitter.particles ); if( %numExistingParticles > 3 ) { MessageBoxOK( "Error", "An emitter cannot have more than 4 particles assigned to it." ); return; } %particleIndex = %numExistingParticles; } else %particleIndex = %replaceSlot - 1; // Create the particle datablock and add to the emitter. %newParticle = getUniqueName( "newParticle" ); datablock ParticleData( %newParticle : DefaultParticle ) { }; // Submit undo. %action = ParticleEditor.createUndo( ActionCreateNewParticle, "Create New Particle" ); %action.particle = %newParticle.getId(); %action.particleIndex = %particleIndex; %action.prevParticle = ( "PEE_EmitterParticleSelector" @ ( %particleIndex + 1 ) ).getSelected(); %action.emitter = PE_EmitterEditor.currEmitter; ParticleEditor.submitUndo( %action ); // Execute action. %action.redo(); } //--------------------------------------------------------------------------------------------- function PE_ParticleEditor::showDeleteDialog( %this ) { // Don't allow deleting DefaultParticle. if( PE_ParticleEditor.currParticle.getName() $= "DefaultParticle" ) { MessageBoxOK( "Error", "Cannot delete DefaultParticle"); return; } // Check to see if the particle emitter has more than 1 particle on it. if( getWordCount( PE_EmitterEditor.currEmitter.particles ) == 1 ) { MessageBoxOK( "Error", "At least one particle must remain on the particle emitter."); return; } // Bring up requester for confirmation. if( isObject( PE_ParticleEditor.currParticle ) ) { MessageBoxYesNoCancel( "Delete Particle?", "Are you sure you want to delete

" @ PE_ParticleEditor.currParticle.getName() @ "

Particle deletion won't take affect until the engine is quit.", "PE_ParticleEditor.saveParticleDialogDontSave( " @ PE_ParticleEditor.currParticle.getName() @ " ); PE_ParticleEditor.deleteParticle();", "", "" ); } } //--------------------------------------------------------------------------------------------- function PE_ParticleEditor::deleteParticle( %this ) { %particle = PE_ParticleEditor.currParticle; // Submit undo. %action = ParticleEditor.createUndo( ActionDeleteParticle, "Delete Particle" ); %action.particle = %particle; %action.emitter = PE_EmitterEditor.currEmitter; ParticleEditor.submitUndo( %action ); // Execute action. %action.redo(); } //--------------------------------------------------------------------------------------------- function PE_ParticleEditor::saveParticle( %this, %particle ) { %particle.setName( PEP_ParticleSelector.getText() ); PE_ParticleEditor_NotDirtyParticle.assignFieldsFrom( %particle ); PE_ParticleEditor_NotDirtyParticle.originalName = %particle.getName(); PE_ParticleSaver.saveDirty(); PE_ParticleEditor.setParticleNotDirty(); ParticleEditor.createParticleList(); } //--------------------------------------------------------------------------------------------- function PE_ParticleEditor::saveParticleDialogDontSave( %this, %particle ) { %particle.setName( PE_ParticleEditor_NotDirtyParticle.originalName ); %particle.assignFieldsFrom( PE_ParticleEditor_NotDirtyParticle ); PE_ParticleEditor.setParticleNotDirty(); } //============================================================================================= // PE_ColorTintSwatch. //============================================================================================= //--------------------------------------------------------------------------------------------- function PE_ColorTintSwatch::updateParticleColor( %this, %color ) { %arrayNum = %this.arrayNum; %r = getWord( %color, 0 ); %g = getWord( %color, 1 ); %b = getWord( %color, 2 ); %a = getWord( %color, 3 ); %color = %r SPC %g SPC %b SPC %a; %this.color = %color; PE_ParticleEditor.updateParticle( "colors[" @ %arrayNum @ "]", %color ); } //============================================================================================= // PEP_ParticleSelector_Control. //============================================================================================= //--------------------------------------------------------------------------------------------- function PEP_ParticleSelector_Control::onRenameItem( %this ) { Parent::onRenameItem( %this ); //FIXME: need to check for validity of name and name clashes PE_ParticleEditor.setParticleDirty(); // Resort menu. %this-->PopupMenu.sort(); } //============================================================================================= // PEP_NewParticleButton. //============================================================================================= //--------------------------------------------------------------------------------------------- function PEP_NewParticleButton::onDefaultClick( %this ) { PE_ParticleEditor.showNewDialog(); } //--------------------------------------------------------------------------------------------- function PEP_NewParticleButton::onCtrlClick( %this ) { for( %i = 1; %i < 5; %i ++ ) { %popup = "PEE_EmitterParticleSelector" @ %i; if( %popup.getSelected() == PEP_ParticleSelector.getSelected() ) { %replaceSlot = %i; break; } } PE_ParticleEditor.showNewDialog( %replaceSlot ); }