Update of Particle Editor to standardize it up and utilize inspectors rather than adhoc guis

This commit is contained in:
JeffR 2025-12-21 16:39:19 -06:00
parent 1f5a4267ac
commit 12ebebff46
31 changed files with 5091 additions and 6095 deletions

View file

@ -0,0 +1,398 @@
//-----------------------------------------------------------------------------
// 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_AFXChoreoEditor_DEFAULT_FILENAME = "data/managedChoreographyData." @ $TorqueScriptFileExtension;
//=============================================================================================
// PE_AFXChoreoEditor.
//=============================================================================================
function PE_AFXChoreoEditor::init(%this)
{
datablock afxChoreographerData(PE_AFXChoreoEditor_NotDirtyEmitter)
{
};
%this.unlistedSet.add(PE_AFXChoreoEditor_NotDirtyEmitter);
}
function PE_AFXChoreoEditor::openEditorTab(%this)
{
PE_Window.text = ":: Particle Editor - AFX Choreographer";
%this.guiSync();
ParticleEditor.activeEditor = %this;
if( !%this.dirty )
%this.setNotDirty();
if( isObject( $ParticleEditor::choreographyNode ) )
$ParticleEditor::choreographyNode.setHidden(false);
}
function PE_AFXChoreoEditor::closeEditorTab(%this)
{
if( isObject( $ParticleEditor::choreographyNode) )
$ParticleEditor::choreographyNode.delete();
}
//---------------------------------------------------------------------------------------------
function PE_AFXChoreoEditor::guiSync( %this )
{
%this-->inspector.refresh();
}
function PE_AFXChoreoEditor::resetVizNode(%this, %tform)
{
/*if( !isObject( $ParticleEditor::choreographyNode ) )
{
if( !isObject( TestChoreographyData ) )
{
datablock afxChoreographerData( TestChoreographyData )
{
timeMultiple = 1;
};
}
$ParticleEditor::choreographyNode = new afxChoreographer()
{
position = getWords( %tform, 0, 2 );
rotation = getWords( %tform, 3, 6 );
datablock = TestChoreographyData;
parentGroup = MissionCleanup;
};
}
else
{
$ParticleEditor::choreographyNode.setTransform( %tform );
%clientObject = $ParticleEditor::choreographyNode.getClientObject();
if( isObject( %clientObject ) )
%clientObject.setTransform( %tform );
ParticleEditor.updateVizNode();
}
if (EWorldEditor.getSelectionSize()>0)
{
%obj = EWorldEditor.getSelectedObject(0);
if (%obj.isMemberOfClass("afxChoreographerData"))
$ParticleEditor::choreographyNode.sethidden(true);
}*/
}
function PE_AFXChoreoEditor::updateVizNode(%this)
{
/*if( isObject( $ParticleEditor::choreographyNode ) )
{
%id = %this.currChoreography;
%clientObject = $ParticleEditor::choreographyNode.getClientObject();
if( isObject( %clientObject ) )
%clientObject.assignFieldsFrom( %id );
}
else
%this.resetVizNode(); */
}
//------------------------------------------------------------------------------
function PE_AFXChoreoEditor::selectObject(%this, %obj)
{
if( isObject(%obj )
&& %obj.getName() $= %this-->popupMenu.text )
return;
//FIXME: disregards particle tab dirty state
if( %this.dirty )
{
%savedChoreography = %this.currChoreography;
toolsMessageBoxYesNoCancel("Save Existing AFX Choreographer?",
"Do you want to save changes to <br><br>" @ %savedChoreography.getName(),
"PE_AFXChoreoEditor.saveChoreography(" @ %savedChoreography@ "); PE_AFXChoreoEditor.loadNewChoreography(" @ %obj @ ");",
"PE_AFXChoreoEditor.saveChoreographyDialogDontSave(" @ %savedChoreography @ "); PE_AFXChoreoEditor.loadNewChoreography(" @ %obj @ ");"
);
}
else
{
%this.loadNewChoreography(%obj);
}
}
//---------------------------------------------------------------------------------------------
function PE_AFXChoreoEditor::loadNewChoreography( %this, %choreography )
{
%this-->popupMenu.setText(%choreography.getName());
%this-->inspector.inspect(%choreography);
if( isObject( %choreography ) )
%current = %choreography.getId();
else
%current = %this-->popupMenu.text;
%this.currChoreography = %current;
PE_AFXChoreoEditor_NotDirtyChoreography.assignFieldsFrom( %current );
PE_AFXChoreoEditor_NotDirtyChoreography.originalName = %current.name;
%this.guiSync();
%this.setNotDirty();
//PE_ParticleEditor.loadNewParticle( getWord( %current.particles, 0 ) );
%this.guiSync();
PE_AFXChoreoEditor.updateVizNode();
}
//---------------------------------------------------------------------------------------------
function PE_AFXChoreoEditor::onInspectorFieldModified(%this, %object, %fieldName, %arrayIndex, %oldValue, %newValue)
{
%action = ParticleEditor.createUndo(ActionUpdateActiveChoreography, "Update Active AFX Choreographer");
%action.choreography = %object;
%action.field = %fieldName;
%action.isSlider = false;
%action.onMouseUp = true;
%action.newValue = %newValue;
%action.oldValue = %oldValue;
ParticleEditor.submitUndo( %action );
}
// Generic updateChoreography method
function PE_AFXChoreoEditor::updateChoreography( %this, %propertyField, %value, %isSlider, %onMouseUp )
{
PE_AFXChoreoEditor.setDirty();
%choreography = %this.currChoreography;
%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(ActionUpdateActiveChoreography, "Update Active AFX Choreographer");
%action.choreography = %choreography;
%action.field = %propertyField;
%action.isSlider = %isSlider;
%action.onMouseUp = %onMouseUp;
%action.newValue = %value;
%action.oldValue = %choreography.getFieldValue( %propertyField );
ParticleEditor.submitUndo( %action );
}
%choreography.setFieldValue( %propertyField, %value );
%choreography.reload();
}
//---------------------------------------------------------------------------------------------
function PE_AFXChoreoEditor::setDirty( %this )
{
%this.text = "*Choreography";
%this.dirty = true;
if(!startsWith(%this-->PopupMenu.text, "*"))
{
%this-->PopupMenu.text = "*" @ %this-->PopupMenu.text;
}
%choreography = %this.currChoreography;
%filename = %choreography.getFilename();
%editorFilename = "tools/particleEditor/scripts/afxChoreographyEditor.ed." @ $TorqueScriptFileExtension;
if( %filename $= "" || %filename $= %editorFilename )
%this.saver.setDirty( %choreography, $PE_AFXChoreoEditor_DEFAULT_FILENAME );
else
%this.saver.setDirty( %choreography );
}
//---------------------------------------------------------------------------------------------
function PE_AFXChoreoEditor::setNotDirty( %this )
{
PE_AFXChoreoEditor.text = "Choreography";
PE_AFXChoreoEditor.dirty = false;
if(startsWith(%this-->PopupMenu.text, "*"))
{
%this-->PopupMenu.text = stripChars(%this-->PopupMenu.text, "*");
}
%this.saver.clearAll();
}
//---------------------------------------------------------------------------------------------
// Create Functionality
function PE_AFXChoreoEditor::showNewDialog( %this )
{
if( PE_AFXChoreoEditor.dirty )
{
toolsMessageBoxYesNoCancel("Save AFX Choreographer Changes?",
"Do you wish to save the changes made to the <br>current choreography before changing the choreography?",
"PE_AFXChoreoEditor.saveChoreography( " @ PE_AFXChoreoEditor.currChoreography.getName() @ " ); PE_AFXChoreoEditor.createChoreography();",
"PE_AFXChoreoEditor.saveChoreographyDialogDontSave( " @ PE_AFXChoreoEditor.currChoreography.getName() @ " ); PE_AFXChoreoEditor.createChoreography();"
);
}
else
{
PE_AFXChoreoEditor.createChoreography();
}
}
//---------------------------------------------------------------------------------------------
function PE_AFXChoreoEditor::createChoreography( %this )
{
AssetBrowser_SelectModule.showDialog("PE_AFXChoreoEditor.pickedNewChoreographyTargetModule");
AssetBrowser_SelectModuleWindow.selectWindow();
}
function PE_AFXChoreoEditor::pickedNewChoreographyTargetModule( %this, %module )
{
ParticleEditorCreatePrompt.show("Choreography", "afxChoreographerData", "PE_AFXChoreoEditor.doCreateNewChoreography(\"" @ %module @ "\");" );
}
function PE_AFXChoreoEditor::doCreateNewChoreography( %this, %module )
{
//Sanity checks
%newName = ParticleEditorCreatePrompt-->nameText.getText();
if(%newName $= "")
{
toolsMessageBoxOK("Error", "New Choreography requires a name!");
return;
}
Canvas.popDialog(ParticleEditorCreatePrompt);
%sourceDB = ParticleEditorCreatePrompt-->CopySourceDropdown.getText();
if(%sourceDB $= "")
%sourceDB = DefaultChoreography;
%moduleDef = ModuleDatabase.findModule(%module);
PE_AFXChoreoEditor.targetModule = %module;
$PE_AFXChoreoEditor_DEFAULT_FILENAME = %moduleDef.ModulePath @ "/scripts/managedData/managedChoreographyData." @ $TorqueScriptFileExtension;
if(!isDirectory(filePath($PE_AFXChoreoEditor_DEFAULT_FILENAME)))
{
AssetBrowser.dirHandler.createFolder(filePath($PE_AFXChoreoEditor_DEFAULT_FILENAME));
}
// Create a new choreography.
%choreography = getUniqueName( %newName );
eval("datablock ChoreographyData( " @ %choreography @ " : " @ %sourceDB @ " ){};");
// Submit undo.
%action = ParticleEditor.createUndo( ActionCreateNewChoreography, "Create New AFX Choreographer" );
%action.prevChoreography = PE_AFXChoreoEditor.currChoreography;
%action.choreography = %choreography.getId();
%action.choreographyName = %choreography;
ParticleEditor.submitUndo( %action );
// Execute action.
%action.redo();
%this.saver.setDirty(%choreography, $PE_AFXChoreoEditor_DEFAULT_FILENAME);
%this.loadNewChoreography(%choreography);
%this.setDirty();
}
//---------------------------------------------------------------------------------------------
function PE_AFXChoreoEditor::showDeleteDialog( %this )
{
if( PE_AFXChoreoEditor.currChoreography.getName() $= "DefaultChoreography" )
{
toolsMessageBoxOK( "Error", "Cannot delete DefaultChoreography");
return;
}
if( isObject( PE_AFXChoreoEditor.currChoreography ) )
{
toolsMessageBoxYesNoCancel("Delete Choreography?",
"Are you sure you want to delete<br><br>" @ PE_AFXChoreoEditor.currChoreography.getName() @ "<br><br> Choreography deletion won't take affect until the level is exited.",
"PE_AFXChoreoEditor.saveChoreographyDialogDontSave( " @ PE_AFXChoreoEditor.currChoreography.getName() @ " ); PE_AFXChoreoEditor.deleteChoreography();"
);
}
}
//---------------------------------------------------------------------------------------------
function PE_AFXChoreoEditor::deleteChoreography( %this )
{
%choreography = PE_AFXChoreoEditor.currChoreography;
// Create undo.
%action = ParticleEditor.createUndo( ActionDeleteChoreography, "Delete AFX Choreographer" );
%action.choreography = %choreography;
%action.choreographyFname = %choreography.getFilename();
ParticleEditor.submitUndo( %action );
// Execute action.
%action.redo();
}
//---------------------------------------------------------------------------------------------
function PE_AFXChoreoEditor::saveChoreography( %this, %choreography )
{
if ( %choreography $= "" )
{
%choreography = %this.currChoreography;
%newName = %this.currChoreography.getName();
}
else
{
%newName = %choreography.getName();
}
%this.currChoreography.setName( %newName );
PE_AFXChoreoEditor_NotDirtyChoreography.assignFieldsFrom( %choreography );
PE_AFXChoreoEditor_NotDirtyChoreography.originalName = %newName;
%this.saver.saveDirty();
%this.loadNewChoreography(%newName.getId());
}
//---------------------------------------------------------------------------------------------
function PE_AFXChoreoEditor::saveChoreographyDialogDontSave( %this, %choreography)
{
%choreography.setName( PE_AFXChoreoEditor_NotDirtyChoreography.originalName );
%choreography.assignFieldsFrom( PE_AFXChoreoEditor_NotDirtyChoreography );
PE_AFXChoreoEditor.setNotDirty();
}

View file

@ -0,0 +1,398 @@
//-----------------------------------------------------------------------------
// 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_AFXZodiacEditor_DEFAULT_FILENAME = "data/managedZodiacData." @ $TorqueScriptFileExtension;
//=============================================================================================
// PE_AFXZodiacEditor.
//=============================================================================================
function PE_AFXZodiacEditor::init(%this)
{
datablock afxZodiacData(PE_AFXZodiacEditor_NotDirtyEmitter)
{
};
%this.unlistedSet.add(PE_AFXZodiacEditor_NotDirtyEmitter);
}
function PE_AFXZodiacEditor::openEditorTab(%this)
{
PE_Window.text = ":: Particle Editor - AFX Zodiacs";
%this.guiSync();
ParticleEditor.activeEditor = %this;
if( !%this.dirty )
%this.setNotDirty();
if( isObject( $ParticleEditor::zodiacNode ) )
$ParticleEditor::zodiacNode.setHidden(false);
}
function PE_AFXZodiacEditor::closeEditorTab(%this)
{
if( isObject( $ParticleEditor::zodiacNode) )
$ParticleEditor::zodiacNode.delete();
}
//---------------------------------------------------------------------------------------------
function PE_AFXZodiacEditor::guiSync( %this )
{
%this-->inspector.refresh();
}
function PE_AFXZodiacEditor::resetVizNode(%this, %tform)
{
/*if( !isObject( $ParticleEditor::zodiacNode ) )
{
if( !isObject( TestZodiacData ) )
{
datablock ZodiacData( TestZodiacData )
{
timeMultiple = 1;
};
}
$ParticleEditor::zodiacNode = new afxZodiacPolysoupRenderer()
{
position = getWords( %tform, 0, 2 );
rotation = getWords( %tform, 3, 6 );
datablock = TestZodiacData;
parentGroup = MissionCleanup;
};
}
else
{
$ParticleEditor::zodiacNode.setTransform( %tform );
%clientObject = $ParticleEditor::zodiacNode.getClientObject();
if( isObject( %clientObject ) )
%clientObject.setTransform( %tform );
ParticleEditor.updateVizNode();
}
if (EWorldEditor.getSelectionSize()>0)
{
%obj = EWorldEditor.getSelectedObject(0);
if (%obj.isMemberOfClass("afxZodiacData"))
$ParticleEditor::zodiacNode.sethidden(true);
} */
}
function PE_AFXZodiacEditor::updateVizNode(%this)
{
/*if( isObject( $ParticleEditor::zodiacNode ) )
{
%id = %this.currZodiac;
%clientObject = $ParticleEditor::zodiacNode.getClientObject();
if( isObject( %clientObject ) )
%clientObject.assignFieldsFrom( %id );
}
else
%this.resetVizNode(); */
}
//------------------------------------------------------------------------------
function PE_AFXZodiacEditor::selectObject(%this, %obj)
{
if( isObject(%obj )
&& %obj.getName() $= %this-->popupMenu.text )
return;
//FIXME: disregards particle tab dirty state
if( %this.dirty )
{
%savedZodiac = %this.currZodiac;
toolsMessageBoxYesNoCancel("Save Existing Zodiac?",
"Do you want to save changes to <br><br>" @ %savedZodiac.getName(),
"PE_AFXZodiacEditor.saveZodiac(" @ %savedZodiac@ "); PE_AFXZodiacEditor.loadNewZodiac(" @ %obj @ ");",
"PE_AFXZodiacEditor.saveZodiacDialogDontSave(" @ %savedZodiac @ "); PE_AFXZodiacEditor.loadNewZodiac(" @ %obj @ ");"
);
}
else
{
%this.loadNewZodiac(%obj);
}
}
//---------------------------------------------------------------------------------------------
function PE_AFXZodiacEditor::loadNewZodiac( %this, %zodiac )
{
%this-->popupMenu.setText(%zodiac.getName());
%this-->inspector.inspect(%zodiac);
if( isObject( %zodiac ) )
%current = %zodiac.getId();
else
%current = %this-->popupMenu.text;
%this.currZodiac = %current;
PE_AFXZodiacEditor_NotDirtyZodiac.assignFieldsFrom( %current );
PE_AFXZodiacEditor_NotDirtyZodiac.originalName = %current.name;
%this.guiSync();
%this.setNotDirty();
//PE_ParticleEditor.loadNewParticle( getWord( %current.particles, 0 ) );
%this.guiSync();
PE_AFXZodiacEditor.updateVizNode();
}
//---------------------------------------------------------------------------------------------
function PE_AFXZodiacEditor::onInspectorFieldModified(%this, %object, %fieldName, %arrayIndex, %oldValue, %newValue)
{
%action = ParticleEditor.createUndo(ActionUpdateActiveZodiac, "Update Active AFX Zodiac");
%action.zodiac = %object;
%action.field = %fieldName;
%action.isSlider = false;
%action.onMouseUp = true;
%action.newValue = %newValue;
%action.oldValue = %oldValue;
ParticleEditor.submitUndo( %action );
}
// Generic updateZodiac method
function PE_AFXZodiacEditor::updateZodiac( %this, %propertyField, %value, %isSlider, %onMouseUp )
{
PE_AFXZodiacEditor.setDirty();
%zodiac = %this.currZodiac;
%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(ActionUpdateActiveZodiac, "Update Active AFX Zodiac");
%action.zodiac = %zodiac;
%action.field = %propertyField;
%action.isSlider = %isSlider;
%action.onMouseUp = %onMouseUp;
%action.newValue = %value;
%action.oldValue = %zodiac.getFieldValue( %propertyField );
ParticleEditor.submitUndo( %action );
}
%zodiac.setFieldValue( %propertyField, %value );
%zodiac.reload();
}
//---------------------------------------------------------------------------------------------
function PE_AFXZodiacEditor::setDirty( %this )
{
%this.text = "*Zodiac";
%this.dirty = true;
if(!startsWith(%this-->PopupMenu.text, "*"))
{
%this-->PopupMenu.text = "*" @ %this-->PopupMenu.text;
}
%zodiac = %this.currZodiac;
%filename = %zodiac.getFilename();
%editorFilename = "tools/particleEditor/scripts/afxZodiacEditor.ed." @ $TorqueScriptFileExtension;
if( %filename $= "" || %filename $= %editorFilename )
%this.saver.setDirty( %zodiac, $PE_AFXZodiacEditor_DEFAULT_FILENAME );
else
%this.saver.setDirty( %zodiac );
}
//---------------------------------------------------------------------------------------------
function PE_AFXZodiacEditor::setNotDirty( %this )
{
PE_AFXZodiacEditor.text = "Zodiac";
PE_AFXZodiacEditor.dirty = false;
if(startsWith(%this-->PopupMenu.text, "*"))
{
%this-->PopupMenu.text = stripChars(%this-->PopupMenu.text, "*");
}
%this.saver.clearAll();
}
//---------------------------------------------------------------------------------------------
// Create Functionality
function PE_AFXZodiacEditor::showNewDialog( %this )
{
if( PE_AFXZodiacEditor.dirty )
{
toolsMessageBoxYesNoCancel("Save Zodiac Changes?",
"Do you wish to save the changes made to the <br>current zodiac before changing the zodiac?",
"PE_AFXZodiacEditor.saveZodiac( " @ PE_AFXZodiacEditor.currZodiac.getName() @ " ); PE_AFXZodiacEditor.createZodiac();",
"PE_AFXZodiacEditor.saveZodiacDialogDontSave( " @ PE_AFXZodiacEditor.currZodiac.getName() @ " ); PE_AFXZodiacEditor.createZodiac();"
);
}
else
{
PE_AFXZodiacEditor.createZodiac();
}
}
//---------------------------------------------------------------------------------------------
function PE_AFXZodiacEditor::createZodiac( %this )
{
AssetBrowser_SelectModule.showDialog("PE_AFXZodiacEditor.pickedNewZodiacTargetModule");
AssetBrowser_SelectModuleWindow.selectWindow();
}
function PE_AFXZodiacEditor::pickedNewZodiacTargetModule( %this, %module )
{
ParticleEditorCreatePrompt.show("Zodiac", "afxZodiacData", "PE_AFXZodiacEditor.doCreateNewZodiac(\"" @ %module @ "\");" );
}
function PE_AFXZodiacEditor::doCreateNewZodiac( %this, %module )
{
//Sanity checks
%newName = ParticleEditorCreatePrompt-->nameText.getText();
if(%newName $= "")
{
toolsMessageBoxOK("Error", "New Zodiac requires a name!");
return;
}
Canvas.popDialog(ParticleEditorCreatePrompt);
%sourceDB = ParticleEditorCreatePrompt-->CopySourceDropdown.getText();
if(%sourceDB $= "")
%sourceDB = DefaultZodiac;
%moduleDef = ModuleDatabase.findModule(%module);
PE_AFXZodiacEditor.targetModule = %module;
$PE_AFXZodiacEditor_DEFAULT_FILENAME = %moduleDef.ModulePath @ "/scripts/managedData/managedZodiacData." @ $TorqueScriptFileExtension;
if(!isDirectory(filePath($PE_AFXZodiacEditor_DEFAULT_FILENAME)))
{
AssetBrowser.dirHandler.createFolder(filePath($PE_AFXZodiacEditor_DEFAULT_FILENAME));
}
// Create a new zodiac.
%zodiac = getUniqueName( %newName );
eval("datablock ZodiacData( " @ %zodiac @ " : " @ %sourceDB @ " ){};");
// Submit undo.
%action = ParticleEditor.createUndo( ActionCreateNewZodiac, "Create New AFX Zodiac" );
%action.prevZodiac = PE_AFXZodiacEditor.currZodiac;
%action.zodiac = %zodiac.getId();
%action.zodiacName = %zodiac;
ParticleEditor.submitUndo( %action );
// Execute action.
%action.redo();
%this.saver.setDirty(%zodiac, $PE_AFXZodiacEditor_DEFAULT_FILENAME);
%this.loadNewZodiac(%zodiac);
%this.setDirty();
}
//---------------------------------------------------------------------------------------------
function PE_AFXZodiacEditor::showDeleteDialog( %this )
{
if( PE_AFXZodiacEditor.currZodiac.getName() $= "DefaultZodiac" )
{
toolsMessageBoxOK( "Error", "Cannot delete DefaultZodiac");
return;
}
if( isObject( PE_AFXZodiacEditor.currZodiac ) )
{
toolsMessageBoxYesNoCancel("Delete Zodiac?",
"Are you sure you want to delete<br><br>" @ PE_AFXZodiacEditor.currZodiac.getName() @ "<br><br> Zodiac deletion won't take affect until the level is exited.",
"PE_AFXZodiacEditor.saveZodiacDialogDontSave( " @ PE_AFXZodiacEditor.currZodiac.getName() @ " ); PE_AFXZodiacEditor.deleteZodiac();"
);
}
}
//---------------------------------------------------------------------------------------------
function PE_AFXZodiacEditor::deleteZodiac( %this )
{
%zodiac = PE_AFXZodiacEditor.currZodiac;
// Create undo.
%action = ParticleEditor.createUndo( ActionDeleteZodiac, "Delete Zodiac" );
%action.zodiac = %zodiac;
%action.zodiacFname = %zodiac.getFilename();
ParticleEditor.submitUndo( %action );
// Execute action.
%action.redo();
}
//---------------------------------------------------------------------------------------------
function PE_AFXZodiacEditor::saveZodiac( %this, %zodiac )
{
if ( %zodiac $= "" )
{
%zodiac = %this.currZodiac;
%newName = %this.currZodiac.getName();
}
else
{
%newName = %zodiac.getName();
}
%this.currZodiac.setName( %newName );
PE_AFXZodiacEditor_NotDirtyZodiac.assignFieldsFrom( %zodiac );
PE_AFXZodiacEditor_NotDirtyZodiac.originalName = %newName;
%this.saver.saveDirty();
%this.loadNewZodiac(%newName.getId());
}
//---------------------------------------------------------------------------------------------
function PE_AFXZodiacEditor::saveZodiacDialogDontSave( %this, %zodiac)
{
%zodiac.setName( PE_AFXZodiacEditor_NotDirtyZodiac.originalName );
%zodiac.assignFieldsFrom( PE_AFXZodiacEditor_NotDirtyZodiac );
PE_AFXZodiacEditor.setNotDirty();
}

View file

@ -0,0 +1,490 @@
//-----------------------------------------------------------------------------
// 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_ExplosionEditor_DEFAULT_FILENAME = "data/managedExplosionData." @ $TorqueScriptFileExtension;
//=============================================================================================
// PE_ExplosionEditor.
//=============================================================================================
function PE_ExplosionEditor::init(%this)
{
datablock ExplosionData(PE_ExplosionEditor_NotDirtyEmitter)
{
emitters = "DefaultEmitter";
};
%this.unlistedSet.add(PE_ExplosionEditor_NotDirtyEmitter);
}
function PE_ExplosionEditor::openEditorTab(%this)
{
PE_Window.text = ":: Particle Editor - Explosions";
%this.guiSync();
ParticleEditor.activeEditor = %this;
if( !%this.dirty )
%this.setNotDirty();
if( isObject( $ParticleEditor::explosionNode ) )
$ParticleEditor::explosionNode.setHidden(false);
}
function PE_ExplosionEditor::closeEditorTab(%this)
{
if( isObject( $ParticleEditor::explosionNode) )
$ParticleEditor::explosionNode.delete();
}
//---------------------------------------------------------------------------------------------
function PE_ExplosionEditor::guiSync( %this )
{
%this-->inspector.refresh();
}
function PE_ExplosionEditor::resetVizNode(%this, %tform)
{
if( !isObject( $ParticleEditor::explosionNode ) )
{
if( !isObject( TestExplosionData ) )
{
datablock ExplosionData( TestExplosionData )
{
timeMultiple = 1;
};
}
$ParticleEditor::explosionNode = new Explosion()
{
position = getWords( %tform, 0, 2 );
rotation = getWords( %tform, 3, 6 );
datablock = TestExplosionData;
parentGroup = MissionCleanup;
};
}
else
{
$ParticleEditor::explosionNode.setTransform( %tform );
%clientObject = $ParticleEditor::explosionNode.getClientObject();
if( isObject( %clientObject ) )
%clientObject.setTransform( %tform );
%this.updateVizNode();
}
if (EWorldEditor.getSelectionSize()>0)
{
%obj = EWorldEditor.getSelectedObject(0);
if (%obj.isMemberOfClass("Explosion"))
$ParticleEditor::explosionNode.sethidden(true);
}
}
function PE_ExplosionEditor::updateVizNode(%this)
{
if( isObject( $ParticleEditor::explosionNode ) )
{
%id = %this.currExplosion;
%clientObject = $ParticleEditor::explosionNode.getClientObject();
if( isObject( %clientObject ) )
%clientObject.assignFieldsFrom( %id );
}
else
%this.resetVizNode();
}
//------------------------------------------------------------------------------
function PE_ExplosionEditor::selectObject(%this, %obj)
{
if( isObject(%obj )
&& %obj.getName() $= %this-->popupMenu.text )
return;
//FIXME: disregards particle tab dirty state
if( %this.dirty )
{
if( PE_ParticleEditor.dirty )
{
toolsMessageBoxYesNo("Save Existing Explosion?",
"Do you want to save changes to <br><br>" @ %this.currParticle.getName(),
"PE_ParticleEditor.saveParticle(" @ %this.currParticle @ ");"
);
}
%savedExplosion = %this.currExplosion;
toolsMessageBoxYesNoCancel("Save Existing Explosion?",
"Do you want to save changes to <br><br>" @ %savedExplosion.getName(),
"PE_ExplosionEditor.saveExplosion(" @ %savedExplosion@ "); PE_ExplosionEditor.loadNewExplosion(" @ %obj @ ");",
"PE_ExplosionEditor.saveExplosionDialogDontSave(" @ %savedExplosion @ "); PE_ExplosionEditor.loadNewExplosion(" @ %obj @ ");"
);
}
else
{
%this.loadNewExplosion(%obj);
}
}
//---------------------------------------------------------------------------------------------
function PE_ExplosionEditor::loadNewExplosion( %this, %explosion )
{
%this-->popupMenu.setText(%explosion.getName());
%this-->inspector.inspect(%explosion);
if( isObject( %explosion ) )
%current = %explosion.getId();
else
%current = %this-->popupMenu.text;
%this.currExplosion = %current;
PE_ExplosionEditor_NotDirtyExplosion.assignFieldsFrom( %current );
PE_ExplosionEditor_NotDirtyExplosion.originalName = %current.name;
%this.guiSync();
%this.setNotDirty();
//PE_ParticleEditor.loadNewParticle( getWord( %current.particles, 0 ) );
%this.guiSync();
PE_ExplosionEditor.updateVizNode();
}
//---------------------------------------------------------------------------------------------
function PE_ExplosionEditor::onInspectorFieldModified(%this, %object, %fieldName, %arrayIndex, %oldValue, %newValue)
{
%action = ParticleEditor.createUndo(ActionUpdateActiveExplosion, "Update Active Explosion");
%action.explosion = %object;
%action.field = %fieldName;
%action.isSlider = false;
%action.onMouseUp = true;
%action.newValue = %newValue;
%action.oldValue = %oldValue;
ParticleEditor.submitUndo( %action );
}
// Generic updateExplosion method
function PE_ExplosionEditor::updateExplosion( %this, %propertyField, %value, %isSlider, %onMouseUp )
{
PE_ExplosionEditor.setDirty();
%explosion = %this.currExplosion;
%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(ActionUpdateActiveExplosion, "Update Active Explosion");
%action.explosion = %explosion;
%action.field = %propertyField;
%action.isSlider = %isSlider;
%action.onMouseUp = %onMouseUp;
%action.newValue = %value;
%action.oldValue = %explosion.getFieldValue( %propertyField );
ParticleEditor.submitUndo( %action );
}
%explosion.setFieldValue( %propertyField, %value );
%explosion.reload();
}
//---------------------------------------------------------------------------------------------
function PE_ExplosionEditor::updateParticlesFields( %this )
{
%particles = "";
for( %i = 1; %i < 5; %i ++ )
{
%explosionParticle = "PEE_ExplosionParticle" @ %i;
%popup = %explosionParticle-->PopUpMenu;
%text = %popup.getText();
if( %text $= "" || %text $= "None" )
continue;
if( %particles $= "" )
%particles = %text;
else
%particles = %particles SPC %text;
}
%changedEditParticle = 1;
%currParticle = PE_ParticleEditor.currParticle.getName();
foreach$( %particleName in %particles )
{
if( %particleName $= %currParticle )
{
%changedEditParticle = 0;
break;
}
}
// True only if the currently edited particle has not been found and the
// ParticleEditor is dirty.
if( %changedEditParticle && PE_ParticleEditor.dirty )
{
toolsMessageBoxYesNoCancel("Save Particle Changes?",
"Do you wish to save the changes made to the <br>current particle before changing the particle?",
"PE_ParticleEditor.saveParticle( " @ PE_ParticleEditor.currParticle.getName() @ " ); PE_ExplosionEditor.updateExplosion( \"particles\"," @ %particles @ ");",
"PE_ParticleEditor.saveParticleDialogDontSave( " @ PE_ParticleEditor.currParticle.getName() @ " ); PE_ExplosionEditor.updateExplosion( \"particles\"," @ %particles @ ");",
"PE_ExplosionEditor.guiSync();" );
}
else
{
PE_ExplosionEditor.updateExplosion( "particles", %particles );
}
}
//---------------------------------------------------------------------------------------------
function PE_ExplosionEditor::setDirty( %this )
{
%this.text = "*Explosion";
%this.dirty = true;
if(!startsWith(%this-->PopupMenu.text, "*"))
{
%this-->PopupMenu.text = "*" @ %this-->PopupMenu.text;
}
%explosion = %this.currExplosion;
%filename = %explosion.getFilename();
%editorFilename = "tools/particleEditor/scripts/explosionEditor.ed." @ $TorqueScriptFileExtension;
if( %filename $= "" || %filename $= %editorFilename )
%this.saver.setDirty( %explosion, $PE_ExplosionEditor_DEFAULT_FILENAME );
else
%this.saver.setDirty( %explosion );
}
//---------------------------------------------------------------------------------------------
function PE_ExplosionEditor::setNotDirty( %this )
{
PE_ExplosionEditor.text = "Explosion";
PE_ExplosionEditor.dirty = false;
if(startsWith(%this-->PopupMenu.text, "*"))
{
%this-->PopupMenu.text = stripChars(%this-->PopupMenu.text, "*");
}
%this.saver.clearAll();
}
//---------------------------------------------------------------------------------------------
// Create Functionality
function PE_ExplosionEditor::showNewDialog( %this )
{
//FIXME: disregards particle tab dirty state
// Open a dialog if the current explosion is dirty.
if( PE_ParticleEditor.dirty )
{
toolsMessageBoxYesNo("Save Existing Particle?",
"Do you want to save changes to <br><br>" @ PE_ParticleEditor.currParticle.getName(),
"PE_ParticleEditor.saveParticle(" @ PE_ParticleEditor.currParticle @ ");"
);
}
if( PE_ExplosionEditor.dirty )
{
toolsMessageBoxYesNoCancel("Save Explosion Changes?",
"Do you wish to save the changes made to the <br>current explosion before changing the explosion?",
"PE_ExplosionEditor.saveExplosion( " @ PE_ExplosionEditor.currExplosion.getName() @ " ); PE_ExplosionEditor.createExplosion();",
"PE_ExplosionEditor.saveExplosionDialogDontSave( " @ PE_ExplosionEditor.currExplosion.getName() @ " ); PE_ExplosionEditor.createExplosion();"
);
}
else
{
PE_ExplosionEditor.createExplosion();
}
}
//---------------------------------------------------------------------------------------------
function PE_ExplosionEditor::createExplosion( %this )
{
AssetBrowser_SelectModule.showDialog("PE_ExplosionEditor.pickedNewExplosionTargetModule");
AssetBrowser_SelectModuleWindow.selectWindow();
}
function PE_ExplosionEditor::pickedNewExplosionTargetModule( %this, %module )
{
ParticleEditorCreatePrompt.show("Explosion", "ExplosionData", "PE_ExplosionEditor.doCreateNewExplosion(\"" @ %module @ "\");" );
}
function PE_ExplosionEditor::doCreateNewExplosion( %this, %module )
{
//Sanity checks
%newName = ParticleEditorCreatePrompt-->nameText.getText();
if(%newName $= "")
{
toolsMessageBoxOK("Error", "New Explosion requires a name!");
return;
}
Canvas.popDialog(ParticleEditorCreatePrompt);
%sourceDB = ParticleEditorCreatePrompt-->CopySourceDropdown.getText();
if(%sourceDB $= "")
%sourceDB = DefaultExplosion;
%moduleDef = ModuleDatabase.findModule(%module);
PE_ExplosionEditor.targetModule = %module;
$PE_ExplosionEditor_DEFAULT_FILENAME = %moduleDef.ModulePath @ "/scripts/managedData/managedExplosionData." @ $TorqueScriptFileExtension;
if(!isDirectory(filePath($PE_ExplosionEditor_DEFAULT_FILENAME)))
{
AssetBrowser.dirHandler.createFolder(filePath($PE_ExplosionEditor_DEFAULT_FILENAME));
}
// Create a new explosion.
%explosion = getUniqueName( %newName );
eval("datablock ExplosionData( " @ %explosion @ " : " @ %sourceDB @ " ){};");
// Submit undo.
%action = ParticleEditor.createUndo( ActionCreateNewExplosion, "Create New Explosion" );
%action.prevExplosion = PE_ExplosionEditor.currExplosion;
%action.explosion = %explosion.getId();
%action.explosionName = %explosion;
ParticleEditor.submitUndo( %action );
// Execute action.
%action.redo();
%this.saver.setDirty(%explosion, $PE_ExplosionEditor_DEFAULT_FILENAME);
%this.loadNewExplosion(%explosion);
%this.setDirty();
}
//---------------------------------------------------------------------------------------------
function PE_ExplosionEditor::showDeleteDialog( %this )
{
if( PE_ExplosionEditor.currExplosion.getName() $= "DefaultExplosion" )
{
toolsMessageBoxOK( "Error", "Cannot delete DefaultExplosion");
return;
}
if( isObject( PE_ExplosionEditor.currExplosion ) )
{
toolsMessageBoxYesNoCancel("Delete Explosion?",
"Are you sure you want to delete<br><br>" @ PE_ExplosionEditor.currExplosion.getName() @ "<br><br> Explosion deletion won't take affect until the level is exited.",
"PE_ExplosionEditor.saveExplosionDialogDontSave( " @ PE_ExplosionEditor.currExplosion.getName() @ " ); PE_ExplosionEditor.deleteExplosion();"
);
}
}
//---------------------------------------------------------------------------------------------
function PE_ExplosionEditor::deleteExplosion( %this )
{
%explosion = PE_ExplosionEditor.currExplosion;
// Create undo.
%action = ParticleEditor.createUndo( ActionDeleteExplosion, "Delete Explosion" );
%action.explosion = %explosion;
%action.explosionFname = %explosion.getFilename();
ParticleEditor.submitUndo( %action );
// Execute action.
%action.redo();
}
//---------------------------------------------------------------------------------------------
function PE_ExplosionEditor::saveExplosion( %this, %explosion )
{
if ( %explosion $= "" )
{
%explosion = %this.currExplosion;
%newName = %this.currExplosion.getName();
}
else
{
%newName = %explosion.getName();
}
//Sanity check our sub-explosions so we don't have recursions!
for(%i=0; %i < getWordCount(%explosion.subExplosion); %i++)
{
%subExpl = getWord(%explosion.subExplosion, %i);
if(%subExpl.getId() == %explosion.getId())
{
toolsMessageBoxOK("Error!", "Cannot save because subExplosion[" @ %i @ "] is pointed at this explosion, which would create a loop!");
return;
}
for(%si=0; %si < getWordCount(%subExpl.subExplosion); %si++)
{
%subSubExpl = getWord(%subExpl.subExplosion, %i);
if(%subSubExpl.getId() == %explosion.getId())
{
toolsMessageBoxOK("Error!", "Cannot save because subExplosion[" @ %i @ "] has a subExplosion that is pointed at this explosion, which would create a loop!");
return;
}
}
}
%this.currExplosion.setName( %newName );
PE_ExplosionEditor_NotDirtyExplosion.assignFieldsFrom( %explosion );
PE_ExplosionEditor_NotDirtyExplosion.originalName = %newName;
%this.saver.saveDirty();
%this.loadNewExplosion(%newName.getId());
}
//---------------------------------------------------------------------------------------------
function PE_ExplosionEditor::saveExplosionDialogDontSave( %this, %explosion)
{
%explosion.setName( PE_ExplosionEditor_NotDirtyExplosion.originalName );
%explosion.assignFieldsFrom( PE_ExplosionEditor_NotDirtyExplosion );
PE_ExplosionEditor.setNotDirty();
}

View file

@ -0,0 +1,605 @@
//-----------------------------------------------------------------------------
// 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_EMITTEREDITOR_DEFAULT_FILENAME = "data/managedParticleEmitterData." @ $TorqueScriptFileExtension;
//=============================================================================================
// PE_EmitterEditor.
//=============================================================================================
function PE_EmitterEditor::init(%this)
{
datablock ParticleEmitterData(PE_EmitterEditor_NotDirtyEmitter)
{
particles = "DefaultParticle";
};
%this.unlistedSet.add(PE_EmitterEditor_NotDirtyEmitter);
}
//---------------------------------------------------------------------------------------------
function PE_EmitterEditor::openEditorTab(%this)
{
PE_Window.text = ":: Particle Editor - Emitters";
%this.guiSync();
ParticleEditor.activeEditor = %this;
if( !%this.dirty )
%this.setNotDirty();
}
function PE_EmitterEditor::closeEditorTab(%this)
{
if( isObject( $ParticleEditor::emitterNode) )
$ParticleEditor::emitterNode.delete();
}
//---------------------------------------------------------------------------------------------
function PE_EmitterEditor::guiSync( %this )
{
%this-->inspector.refresh();
}
function PE_EmitterEditor::resetVizNode(%this, %tform)
{
if( !isObject( $ParticleEditor::emitterNode ) )
{
if( !isObject( TestEmitterNodeData ) )
{
datablock ParticleEmitterNodeData( TestEmitterNodeData )
{
timeMultiple = 1;
};
}
$ParticleEditor::emitterNode = new ParticleEmitterNode()
{
emitter = $ThisControl.currEmitter;
velocity = 1;
position = getWords( %tform, 0, 2 );
rotation = getWords( %tform, 3, 6 );
datablock = TestEmitterNodeData;
parentGroup = MissionCleanup;
};
}
else
{
$ParticleEditor::emitterNode.setTransform( %tform );
%clientObject = $ParticleEditor::emitterNode.getClientObject();
if( isObject( %clientObject ) )
%clientObject.setTransform( %tform );
%this.updateVizNode();
}
if (EWorldEditor.getSelectionSize()>0)
{
%obj = EWorldEditor.getSelectedObject(0);
if (%obj.isMemberOfClass("ParticleEmitterNode"))
$ParticleEditor::emitterNode.sethidden(true);
}
}
function PE_EmitterEditor::updateVizNode(%this)
{
if( isObject( $ParticleEditor::emitterNode ) )
{
%id = %this-->PopupMenu.getText();
%clientObject = $ParticleEditor::emitterNode.getClientObject();
if( isObject( %clientObject ) )
%clientObject.setEmitterDataBlock( %id );
}
else
%this.resetVizNode();
}
//------------------------------------------------------------------------------
function PE_EmitterEditor::selectObject(%this, %obj)
{
if( isObject(%obj )
&& %obj.getName() $= %this-->popupMenu.text )
return;
//FIXME: disregards particle tab dirty state
if( %this.dirty )
{
if( PE_ParticleEditor.dirty )
{
toolsMessageBoxYesNo("Save Existing Emitter?",
"Do you want to save changes to <br><br>" @ %this.currParticle.getName(),
"PE_ParticleEditor.saveParticle(" @ %this.currParticle @ ");"
);
}
%savedEmitter = %this.currEmitter;
toolsMessageBoxYesNoCancel("Save Existing Emitter?",
"Do you want to save changes to <br><br>" @ %savedEmitter.getName(),
"PE_EmitterEditor.saveEmitter(" @ %savedEmitter@ "); PE_EmitterEditor.loadNewEmitter(" @ %obj @ ");",
"PE_EmitterEditor.saveEmitterDialogDontSave(" @ %savedEmitter @ "); PE_EmitterEditor.loadNewEmitter(" @ %obj @ ");"
);
}
else
{
%this.loadNewEmitter(%obj);
}
}
//---------------------------------------------------------------------------------------------
function PE_EmitterEditor::loadNewEmitter( %this, %emitter )
{
%this-->popupMenu.setText(%emitter.getName());
%this-->inspector.inspect(%emitter);
if( isObject( %emitter ) )
%current = %emitter.getId();
else
%current = %this-->popupMenu.text;
%this.currEmitter = %current;
PE_EmitterEditor_NotDirtyEmitter.assignFieldsFrom( %current );
PE_EmitterEditor_NotDirtyEmitter.originalName = %current.name;
%this.guiSync();
%this.setNotDirty();
//PE_ParticleEditor.loadNewParticle( getWord( %current.particles, 0 ) );
%this.guiSync();
ParticleEditor.updateEmitterNode();
}
//---------------------------------------------------------------------------------------------
function PE_EmitterEditor::onInspectorFieldModified(%this, %object, %fieldName, %arrayIndex, %oldValue, %newValue)
{
%action = ParticleEditor.createUndo(ActionUpdateActiveEmitter, "Update Active Emitter");
%action.emitter = %object;
%action.field = %fieldName;
%action.isSlider = false;
%action.onMouseUp = true;
%action.newValue = %newValue;
%action.oldValue = %oldValue;
ParticleEditor.submitUndo( %action );
}
// Generic updateEmitter method
function PE_EmitterEditor::updateEmitter( %this, %propertyField, %value, %isSlider, %onMouseUp )
{
PE_EmitterEditor.setDirty();
%emitter = %this.currEmitter;
%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(ActionUpdateActiveEmitter, "Update Active Emitter");
%action.emitter = %emitter;
%action.field = %propertyField;
%action.isSlider = %isSlider;
%action.onMouseUp = %onMouseUp;
%action.newValue = %value;
%action.oldValue = %emitter.getFieldValue( %propertyField );
ParticleEditor.submitUndo( %action );
}
%emitter.setFieldValue( %propertyField, %value );
%emitter.reload();
}
//---------------------------------------------------------------------------------------------
function PE_EmitterEditor::updateParticlesFields( %this )
{
%particles = "";
for( %i = 1; %i < 5; %i ++ )
{
%emitterParticle = "PEE_EmitterParticle" @ %i;
%popup = %emitterParticle-->PopUpMenu;
%text = %popup.getText();
if( %text $= "" || %text $= "None" )
continue;
if( %particles $= "" )
%particles = %text;
else
%particles = %particles SPC %text;
}
%changedEditParticle = 1;
%currParticle = PE_ParticleEditor.currParticle.getName();
foreach$( %particleName in %particles )
{
if( %particleName $= %currParticle )
{
%changedEditParticle = 0;
break;
}
}
// True only if the currently edited particle has not been found and the
// ParticleEditor is dirty.
if( %changedEditParticle && PE_ParticleEditor.dirty )
{
toolsMessageBoxYesNoCancel("Save Particle Changes?",
"Do you wish to save the changes made to the <br>current particle before changing the particle?",
"PE_ParticleEditor.saveParticle( " @ PE_ParticleEditor.currParticle.getName() @ " ); PE_EmitterEditor.updateEmitter( \"particles\"," @ %particles @ ");",
"PE_ParticleEditor.saveParticleDialogDontSave( " @ PE_ParticleEditor.currParticle.getName() @ " ); PE_EmitterEditor.updateEmitter( \"particles\"," @ %particles @ ");",
"PE_EmitterEditor.guiSync();" );
}
else
{
PE_EmitterEditor.updateEmitter( "particles", %particles );
}
}
//---------------------------------------------------------------------------------------------
function PE_EmitterEditor::setDirty( %this )
{
%this.text = "*Emitter";
%this.dirty = true;
if(!startsWith(%this-->PopupMenu.text, "*"))
{
%this-->PopupMenu.text = "*" @ %this-->PopupMenu.text;
}
%emitter = %this.currEmitter;
%filename = %emitter.getFilename();
%editorFilename = "tools/particleEditor/scripts/particleEmitterEditor.ed." @ $TorqueScriptFileExtension;
if( %filename $= "" || %filename $= %editorFilename )
%this.saver.setDirty( %emitter, $PE_EMITTEREDITOR_DEFAULT_FILENAME );
else
%this.saver.setDirty( %emitter );
}
//---------------------------------------------------------------------------------------------
function PE_EmitterEditor::setNotDirty( %this )
{
PE_EmitterEditor.text = "Emitter";
PE_EmitterEditor.dirty = false;
if(startsWith(%this-->PopupMenu.text, "*"))
{
%this-->PopupMenu.text = stripChars(%this-->PopupMenu.text, "*");
}
%this.saver.clearAll();
}
//---------------------------------------------------------------------------------------------
// Create Functionality
function PE_EmitterEditor::showNewDialog( %this )
{
// Open a dialog if the current emitter is dirty.
if( PE_ParticleEditor.dirty )
{
toolsMessageBoxYesNo("Save Existing Particle?",
"Do you want to save changes to <br><br>" @ PE_ParticleEditor.currParticle.getName(),
"PE_ParticleEditor.saveParticle(" @ PE_ParticleEditor.currParticle @ ");"
);
}
if( PE_EmitterEditor.dirty )
{
toolsMessageBoxYesNoCancel("Save Emitter Changes?",
"Do you wish to save the changes made to the <br>current emitter before changing the emitter?",
"PE_EmitterEditor.saveEmitter( " @ PE_EmitterEditor.currEmitter.getName() @ " ); PE_EmitterEditor.createEmitter();",
"PE_EmitterEditor.saveEmitterDialogDontSave( " @ PE_EmitterEditor.currEmitter.getName() @ " ); PE_EmitterEditor.createEmitter();"
);
}
else
{
PE_EmitterEditor.createEmitter();
}
}
//---------------------------------------------------------------------------------------------
function PE_EmitterEditor::createEmitter( %this )
{
AssetBrowser_SelectModule.showDialog("PE_EmitterEditor.pickedNewEmitterTargetModule");
AssetBrowser_SelectModuleWindow.selectWindow();
}
function PE_EmitterEditor::pickedNewEmitterTargetModule( %this, %module )
{
ParticleEditorCreatePrompt.show("Emitter", "ParticleEmitterData", "PE_EMitterEditor.doCreateNewEmitter(\"" @ %module @ "\");" );
}
function PE_EmitterEditor::doCreateNewEmitter( %this, %module )
{
//Sanity checks
%newName = ParticleEditorCreatePrompt-->nameText.getText();
if(%newName $= "")
{
toolsMessageBoxOK("Error", "New Emitter requires a name!");
return;
}
Canvas.popDialog(ParticleEditorCreatePrompt);
%sourceDB = ParticleEditorCreatePrompt-->CopySourceDropdown.getText();
if(%sourceDB $= "")
%sourceDB = DefaultEmitter;
%moduleDef = ModuleDatabase.findModule(%module);
PE_EmitterEditor.targetModule = %module;
$PE_EMITTEREDITOR_DEFAULT_FILENAME = %moduleDef.ModulePath @ "/scripts/managedData/managedParticleEmitterData." @ $TorqueScriptFileExtension;
if(!isDirectory(filePath($PE_EMITTEREDITOR_DEFAULT_FILENAME)))
{
AssetBrowser.dirHandler.createFolder(filePath($PE_EMITTEREDITOR_DEFAULT_FILENAME));
}
// Create a new emitter.
%emitter = getUniqueName( %newName );
eval("datablock ParticleEmitterData( " @ %emitter @ " : " @ %sourceDB @ " ){};");
// Submit undo.
%action = ParticleEditor.createUndo( ActionCreateNewEmitter, "Create New Emitter" );
%action.prevEmitter = PE_EmitterEditor.currEmitter;
%action.emitter = %emitter.getId();
%action.emitterName = %emitter;
ParticleEditor.submitUndo( %action );
// Execute action.
%action.redo();
%this.saver.setDirty(%emitter, $PE_EMITTEREDITOR_DEFAULT_FILENAME);
%this.loadNewEmitter(%emitter);
%this.setDirty();
}
//---------------------------------------------------------------------------------------------
function PE_EmitterEditor::showDeleteDialog( %this )
{
if( PE_EmitterEditor.currEmitter.getName() $= "DefaultEmitter" )
{
toolsMessageBoxOK( "Error", "Cannot delete DefaultEmitter");
return;
}
if( isObject( PE_EmitterEditor.currEmitter ) )
{
toolsMessageBoxYesNoCancel("Delete Emitter?",
"Are you sure you want to delete<br><br>" @ PE_EmitterEditor.currEmitter.getName() @ "<br><br> Emitter deletion won't take affect until the level is exited.",
"PE_EmitterEditor.saveEmitterDialogDontSave( " @ PE_EmitterEditor.currEmitter.getName() @ " ); PE_EmitterEditor.deleteEmitter();"
);
}
}
//---------------------------------------------------------------------------------------------
function PE_EmitterEditor::deleteEmitter( %this )
{
%emitter = PE_EmitterEditor.currEmitter;
// Create undo.
%action = ParticleEditor.createUndo( ActionDeleteEmitter, "Delete Emitter" );
%action.emitter = %emitter;
%action.emitterFname = %emitter.getFilename();
ParticleEditor.submitUndo( %action );
// Execute action.
%action.redo();
}
//---------------------------------------------------------------------------------------------
function PE_EmitterEditor::saveEmitter( %this, %emitter )
{
if ( %emitter $= "" )
{
%emitter = %this.currEmitter;
%newName = %this.currEmitter.getName();
}
else
{
%newName = %emitter.getName();
}
%this.currEmitter.setName( %newName );
PE_EmitterEditor_NotDirtyEmitter.assignFieldsFrom( %emitter );
PE_EmitterEditor_NotDirtyEmitter.originalName = %newName;
%this.saver.saveDirty();
%this.loadNewEmitter(%newName.getId());
}
//---------------------------------------------------------------------------------------------
function PE_EmitterEditor::saveEmitterDialogDontSave( %this, %emitter)
{
%emitter.setName( PE_EmitterEditor_NotDirtyEmitter.originalName );
%emitter.assignFieldsFrom( PE_EmitterEditor_NotDirtyEmitter );
PE_EmitterEditor.setNotDirty();
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
function ParticleEditor::addParticleSlot(%this, %field, %emitterObj)
{
if(getWordCount(%emitterObj.particles) >= 4)
{
toolsMessageBoxOK("Error", "Cannot add more than 4 particle slots to this emitter.");
return;
}
%updatedParticlesList = %emitterObj.particles SPC "DefaultParticle";
%action = ParticleEditor.createUndo(ActionUpdateActiveEmitter, "Add new Emitter Particle Slot");
%action.emitter = %emitterObj;
%action.field = "particles";
%action.newValue = %updatedParticlesList;
%action.oldValue = %emitterObj.particles;
ParticleEditor.submitUndo( %action );
}
function ParticleEditor::changeParticleSlot(%this, %field, %emitterObj, %slotIdx)
{
%groupIdx = PE_ParticleDataTypes.getIndexFromKey("Particle");
%typesList = getField(PE_ParticleDataTypes.getValue(%groupIdx), 0);
%editorName = getField(PE_ParticleDataTypes.getValue(%groupIdx), 1);
%listSet = new SimSet(){ internalName = "Particles[" @ %slotIdx @ "]"; };
foreach( %obj in DatablockGroup )
{
echo(%typesList);
%typesListCount = getWordCount(%typesList);
for(%i=0; %i < %typesListCount; %i++)
{
%type = getWord(%typesList, %i);
if( %obj.isMemberOfClass( %type ) )
{
// Filter out emitters on the PE_ParticleEditor.unlistedSet list.
%unlistedFound = false;
foreach( %unlisted in PE_ParticleEditor.unlistedSet ){
if( %unlisted.getId() == %obj.getId() )
{
%unlistedFound = true;
break;
}
}
if( %unlistedFound )
continue;
// To prevent our default emitters from getting changed,
// prevent them from populating the list. Default emitters
// should only be used as a template for creating new ones.
if ( %obj.getName() $= "DefaultParticle")
continue;
if(%slotIdx > 0)
{
//Confirm our options to the particle in slot 0's image to maintain batching
%slot0ParticleDB = getWord(%emitterObj.particles, 0);
%textureAsset = %slot0ParticleDB.textureAsset;
if(%textureAsset !$= %obj.textureAsset)
continue;
}
if(%typesListCount > 1)
{
%typeSet = %listSet.findObjectByInternalName(%type);
if(!isObject(%typeSet))
{
%typeSet = new SimSet(){ internalName = %type; };
%listSet.add(%typeSet);
}
%typeSet.add(%obj);
}
else
{
%listSet.add(%obj);
}
%listCount++;
}
}
}
ContextedDropdownListGui.show(%listSet, "Edit Particle Slot[" @ %slotIdx @ "]", "ParticleEditor.editSlot = " @ %slotIdx @ ";ParticleEditor.updateParticleSlot", %field);
%particleData = getWord(%emitterObj.particles, %slotIdx);
if(%particleData !$= "")
{
ContextedDropdownListGui.seekItemObject(%particleData.getId());
}
}
function ParticleEditor::updateParticleSlot(%this, %newParticle)
{
if(ParticleEditor.editSlot $= "")
return;
%updatedParticlesList = setWord(PE_EmitterEditor.currEmitter.particles, ParticleEditor.editSlot, %newParticle);
%action = ParticleEditor.createUndo(ActionUpdateActiveEmitter, "Edit Active Emitter Particle Slot");
%action.emitter = PE_EmitterEditor.currEmitter;
%action.field = "particles";
%action.newValue = %updatedParticlesList;
%action.oldValue = PE_EmitterEditor.currEmitter.particles;
ParticleEditor.submitUndo( %action );
ParticleEditor.editSlot = "";
//%field.apply(%updatedParticlesList, %slotIdx);
//%this-->inspector.refresh();
}
function ParticleEditor::editParticleSlot(%this, %field, %emitterObj, %slotIdx)
{
%particleName = getWord(%emitterObj.particles, %slotIdx);
ParticleEditor.open(%particleName);
}
function ParticleEditor::clearParticleSlot(%this, %field, %emitterObj, %slotIdx)
{
%updatedParticlesList = removeWord(%emitterObj.particles, %slotIdx);
%action = ParticleEditor.createUndo(ActionUpdateActiveEmitter, "Clear Active Emitter Particle Slot");
%action.emitter = %emitterObj;
%action.field = "particles";
%action.newValue = %updatedParticlesList;
%action.oldValue = %emitterObj.particles;
ParticleEditor.submitUndo( %action );
//%field.apply(%updatedParticlesList, %slotIdx);
//%this-->inspector.refresh();
}

View file

@ -0,0 +1,396 @@
//-----------------------------------------------------------------------------
// 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 = "data/managedParticleData." @ $TorqueScriptFileExtension;
//=============================================================================================
// PE_ParticleEditor.
//=============================================================================================
function PE_ParticleEditor::init(%this)
{
datablock ParticleData(PE_ParticleEditor_NotDirtyParticle)
{
textureName = "art/particles/defaultParticle";
};
%this.unlistedSet.add(PE_ParticleEditor_NotDirtyParticle);
}
//---------------------------------------------------------------------------------------------
function PE_ParticleEditor::openEditorTab(%this)
{
PE_Window.text = ":: Particle Editor - Particles";
%this.guiSync();
ParticleEditor.activeEditor = %this;
if( !%this.dirty )
%this.setNotDirty();
}
function PE_ParticleEditor::closeEditorTab(%this)
{
if( isObject( $ParticleEditor::emitterNode) )
$ParticleEditor::emitterNode.delete();
}
//---------------------------------------------------------------------------------------------
function PE_ParticleEditor::guiSync( %this )
{
%this-->inspector.refresh();
}
function PE_ParticleEditor::resetVizNode(%this, %tform)
{
PE_EmitterEditor.resetVizNode(%tform);
}
function PE_ParticleEditor::updateVizNode(%this)
{
PE_EmitterEditor.updateVizNode();
}
//---------------------------------------------------------------------------------------------
function PE_ParticleEditor::selectObject(%this, %obj)
{
// Bail if the user selected the same particle.
if( %obj == %this.currParticle )
return;
// Load new particle if we're not in a dirty state
if( %this.dirty )
{
toolsMessageBoxYesNoCancel("Save Existing Particle?",
"Do you want to save changes to <br><br>" @ %this.currParticle.getName(),
"PE_ParticleEditor.saveParticle(" @ %this.currParticle @ ");",
"PE_ParticleEditor.saveParticleDialogDontSave(" @ %this.currParticle @ "); PE_ParticleEditor.loadNewParticle(" @ %obj @ ");"
);
}
else
{
%this.loadNewParticle(%obj);
}
}
//---------------------------------------------------------------------------------------------
function PE_ParticleEditor::loadNewParticle( %this, %particle )
{
%this-->popupMenu.setText(%particle.getName());
%this-->inspector.inspect(%particle);
if( isObject( %particle ) )
%current = %particle.getId();
else
%current = %this-->popupMenu.text;
%this.currParticle = %current;
error("PE_ParticleEditor::loadNewParticle() - Loading particle: " @ %current.getName());
error("Particle TextureName: " @ %current.getTexture());
error("ReloadingParticle...");
%current.reload();
PE_ParticleEditor_NotDirtyParticle.assignFieldsFrom( %current );
PE_ParticleEditor_NotDirtyParticle.originalName = %current.getName();
error("Post duplicate Particle TextureName: " @ %current.getTexture());
error("Post duplicate PE_ParticleEditor_NotDirtyParticle TextureName: " @ PE_ParticleEditor_NotDirtyParticle.getTexture());
%this.guiSync();
%this.setNotDirty();
}
//---------------------------------------------------------------------------------------------
function PE_ParticleEditor::onInspectorFieldModified(%this, %object, %fieldName, %arrayIndex, %oldValue, %newValue)
{
%action = ParticleEditor.createUndo(ActionUpdateActiveParticler, "Update Active Particle");
%action.particle = %object;
%action.field = %fieldName;
%action.isSlider = false;
%action.onMouseUp = true;
%action.newValue = %newValue;
%action.oldValue = %oldValue;
ParticleEditor.submitUndo( %action );
%object.reload();
}
// Generic updateParticle method
function PE_ParticleEditor::updateParticle(%this, %propertyField, %value, %isSlider, %onMouseUp)
{
PE_ParticleEditor.setDirty();
%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();
}
//---------------------------------------------------------------------------------------------
function PE_ParticleEditor::setDirty( %this )
{
this.text = "*Particle";
this.dirty = true;
if(!startsWith(%this-->PopupMenu.text, "*"))
{
%this-->PopupMenu.text = "*" @ %this-->PopupMenu.text;
}
%particle = this.currParticle;
%filename = %particle.getFilename();
%editorFilename = "tools/particleEditor/scripts/particleParticleEditor.ed." @ $TorqueScriptFileExtension;
if( %filename $= "" || %filename $= %editorFilename )
%this.saver.setDirty( %particle, $PE_PARTICLEEDITOR_DEFAULT_FILENAME );
else
%this.saver.setDirty( %particle );
}
//---------------------------------------------------------------------------------------------
function PE_ParticleEditor::setNotDirty( %this )
{
PE_ParticleEditor.text = "Particle";
PE_ParticleEditor.dirty = false;
if(startsWith(%this-->PopupMenu.text, "*"))
{
%this-->PopupMenu.text = stripChars(%this-->PopupMenu.text, "*");
}
%this.saver.clearAll();
}
//---------------------------------------------------------------------------------------------
function PE_ParticleEditor::showNewDialog( %this, %replaceSlot )
{
// Open a dialog if the current Particle is dirty
if( this.dirty )
{
toolsMessageBoxYesNoCancel("Save Particle Changes?",
"Do you wish to save the changes made to the <br>current particle before changing the particle?",
"PE_ParticleEditor.saveParticle( " @ this.currParticle.getName() @ " ); PE_ParticleEditor.createParticle( " @ %replaceSlot @ " );",
"PE_ParticleEditor.saveParticleDialogDontSave( " @ this.currParticle.getName() @ " ); PE_ParticleEditor.createParticle( " @ %replaceSlot @ " );"
);
}
else
{
this.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 )
{
toolsMessageBoxOK( "Error", "An emitter cannot have more than 4 particles assigned to it." );
return;
}
%particleIndex = %numExistingParticles;
}
else
%particleIndex = %replaceSlot - 1;
%this.newParticleSlot = %particleIndex;
if(%replaceSlot $= "" || %replaceSlot != 0)
{
AssetBrowser_SelectModule.showDialog("PE_ParticleEditor.pickedNewParticleTargetModule");
AssetBrowser_SelectModuleWindow.selectWindow();
}
else
{
%this.pickedNewParticleTargetModule(PE_EmitterEditor.targetModule);
}
}
function PE_ParticleEditor::pickedNewParticleTargetModule( %this, %module )
{
ParticleEditorCreatePrompt.show("Particle", "ParticleData", "PE_ParticleEditor.doCreateNewParticle(\"" @ %module @ "\");" );
}
function PE_ParticleEditor::doCreateNewEmitter(%this, %module)
{
//Sanity checks
%newName = ParticleEditorCreatePrompt-->nameText.getText();
if(%newName $= "")
{
toolsMessageBoxOK("Error", "New Particle requires a name!");
return;
}
Canvas.popDialog(ParticleEditorCreatePrompt);
%sourceDB = ParticleEditorCreatePrompt-->CopySourceDropdown.getText();
if(%sourceDB $= "")
%sourceDB = DefaultParticle;
%moduleDef = ModuleDatabase.findModule(%module);
$PE_PARTICLEEDITOR_DEFAULT_FILENAME = %moduleDef.ModulePath @ "/scripts/managedData/managedParticleData." @ $TorqueScriptFileExtension;
if(!isDirectory(filePath($PE_PARTICLEEDITOR_DEFAULT_FILENAME)))
{
AssetBrowser.dirHandler.createFolder(filePath($PE_PARTICLEEDITOR_DEFAULT_FILENAME));
}
// Create the particle datablock and add to the emitter.
%particle = getUniqueName( %newName );
eval("datablock ParticleData( " @ %particle @ " : " @ %sourceDB @ " ){};");
// Submit undo.
%action = ParticleEditor.createUndo( ActionCreateNewParticle, "Create New Particle" );
%action.particle = %particle.getId();
%action.particleIndex = %this.newParticleSlot;
%action.prevParticle = ( "PEE_EmitterParticleSelector" @ ( PE_ParticleEditor.newParticleSlot + 1 ) ).getSelected();
%action.emitter = PE_EmitterEditor.currEmitter;
ParticleEditor.submitUndo( %action );
// Execute action.
%action.redo();
%this.saver.setDirty(%particle, $PE_PARTICLEEDITOR_DEFAULT_FILENAME);
%this.loadNewParticle(%particle);
%this.setDirty();
}
//---------------------------------------------------------------------------------------------
function PE_ParticleEditor::showDeleteDialog( %this )
{
// Don't allow deleting DefaultParticle.
if( PE_ParticleEditor.currParticle.getName() $= "DefaultParticle" )
{
toolsMessageBoxOK( "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 )
{
toolsMessageBoxOK( "Error", "At least one particle must remain on the particle emitter.");
return;
}
// Bring up requester for confirmation.
if( isObject( PE_ParticleEditor.currParticle ) )
{
toolsMessageBoxYesNoCancel( "Delete Particle?",
"Are you sure you want to delete<br><br>" @ %this.currParticle.getName() @ "<br><br> Particle deletion won't take affect until the engine is quit.",
"PE_ParticleEditor.saveParticleDialogDontSave( " @ %this.currParticle.getName() @ " ); PE_ParticleEditor.deleteParticle();",
"",
""
);
}
}
//---------------------------------------------------------------------------------------------
function PE_ParticleEditor::deleteParticle( %this )
{
%particle = %this.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 )
{
if ( %particle $= "" )
{
%particle = %this.currParticle;
%newName = %this.currParticle.getName();
}
else
{
%newName = %particle.getName();
}
%this.currParticle.setName( %newName );
PE_ParticleEditor_NotDirtyParticle.assignFieldsFrom( %particle );
PE_ParticleEditor_NotDirtyParticle.originalName = %newName;
%this.saver.saveDirty();
%this.loadNewParticle(%newName.getId());
}
//---------------------------------------------------------------------------------------------
function PE_ParticleEditor::saveParticleDialogDontSave( %this, %particle )
{
%particle.setName( PE_ParticleEditor_NotDirtyParticle.originalName );
%particle.assignFieldsFrom( PE_ParticleEditor_NotDirtyParticle );
%this.setNotDirty();
}

View file

@ -0,0 +1,469 @@
//-----------------------------------------------------------------------------
// 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_RibbonParticleEditor_DEFAULT_FILENAME = "data/managedParticleData." @ $TorqueScriptFileExtension;
//=============================================================================================
// PE_RibbonParticleEditor.
//=============================================================================================
function PE_RibbonParticleEditor::init(%this)
{
datablock RibbonData(PE_RibbonParticleEditor_NotDirtyEmitter)
{
};
%this.unlistedSet.add(PE_RibbonParticleEditor_NotDirtyEmitter);
}
function PE_RibbonParticleEditor::openEditorTab(%this)
{
PE_Window.text = ":: Particle Editor - Ribbons";
%this.guiSync();
ParticleEditor.activeEditor = %this;
if( !%this.dirty )
%this.setNotDirty();
if( isObject( $ParticleEditor::ribbonNode ) )
$ParticleEditor::ribbonNode.setHidden(false);
}
function PE_RibbonParticleEditor::closeEditorTab(%this)
{
if( isObject( $ParticleEditor::ribbonNode) )
$ParticleEditor::ribbonNode.delete();
}
//---------------------------------------------------------------------------------------------
function PE_RibbonParticleEditor::guiSync( %this )
{
%this-->inspector.refresh();
}
function PE_RibbonParticleEditor::resetVizNode(%this, %tform)
{
if( !isObject( $ParticleEditor::ribbonNode ) )
{
if( !isObject( TestRibbonEmitterNodeData ) )
{
datablock RibbonNodeData( TestRibbonEmitterNodeData )
{
timeMultiple = 1;
};
}
$ParticleEditor::ribbonNode = new RibbonNode()
{
ribbon = $ThisControl.currRibbon;
position = getWords( %tform, 0, 2 );
rotation = getWords( %tform, 3, 6 );
datablock = TestRibbonEmitterNodeData;
parentGroup = MissionCleanup;
};
}
else
{
$ParticleEditor::ribbonNode.setTransform( %tform );
%clientObject = $ParticleEditor::ribbonNode.getClientObject();
if( isObject( %clientObject ) )
%clientObject.setTransform( %tform );
%this.updateVizNode();
}
if (EWorldEditor.getSelectionSize()>0)
{
%obj = EWorldEditor.getSelectedObject(0);
if (%obj.isMemberOfClass("RibbonNodeData"))
$ParticleEditor::ribbonNode.sethidden(true);
}
}
function PE_RibbonParticleEditor::updateVizNode(%this)
{
if( isObject( $ParticleEditor::ribbonNode ) )
{
%id = %this-->PopupMenu.getText();
%clientObject = $ParticleEditor::ribbonNode.getClientObject();
if( isObject( %clientObject ) )
%clientObject.setRibbonDataBlock( %id );
}
else
%this.resetVizNode();
}
//------------------------------------------------------------------------------
function PE_RibbonParticleEditor::selectObject(%this, %obj)
{
if( isObject(%obj )
&& %obj.getName() $= %this-->popupMenu.text )
return;
//FIXME: disregards particle tab dirty state
if( %this.dirty )
{
if( PE_ParticleEditor.dirty )
{
toolsMessageBoxYesNo("Save Existing Ribbon?",
"Do you want to save changes to <br><br>" @ %this.currParticle.getName(),
"PE_ParticleEditor.saveParticle(" @ %this.currParticle @ ");"
);
}
%savedRibbon = %this.currRibbon;
toolsMessageBoxYesNoCancel("Save Existing Ribbon?",
"Do you want to save changes to <br><br>" @ %savedRibbon.getName(),
"PE_RibbonParticleEditor.saveRibbon(" @ %savedRibbon@ "); PE_RibbonParticleEditor.loadNewRibbon(" @ %obj @ ");",
"PE_RibbonParticleEditor.saveRibbonDialogDontSave(" @ %savedRibbon @ "); PE_RibbonParticleEditor.loadNewRibbon(" @ %obj @ ");"
);
}
else
{
%this.loadNewRibbon(%obj);
}
}
//---------------------------------------------------------------------------------------------
function PE_RibbonParticleEditor::loadNewRibbon( %this, %ribbon )
{
%this-->popupMenu.setText(%ribbon.getName());
%this-->inspector.inspect(%ribbon);
if( isObject( %ribbon ) )
%current = %ribbon.getId();
else
%current = %this-->popupMenu.text;
%this.currRibbon = %current;
PE_RibbonParticleEditor_NotDirtyRibbon.assignFieldsFrom( %current );
PE_RibbonParticleEditor_NotDirtyRibbon.originalName = %current.name;
%this.guiSync();
%this.setNotDirty();
//PE_ParticleEditor.loadNewParticle( getWord( %current.particles, 0 ) );
%this.guiSync();
PE_RibbonParticleEditor.updateVizNode();
}
//---------------------------------------------------------------------------------------------
function PE_RibbonParticleEditor::onInspectorFieldModified(%this, %object, %fieldName, %arrayIndex, %oldValue, %newValue)
{
%action = ParticleEditor.createUndo(ActionUpdateActiveRibbon, "Update Active Ribbon");
%action.ribbon = %object;
%action.field = %fieldName;
%action.isSlider = false;
%action.onMouseUp = true;
%action.newValue = %newValue;
%action.oldValue = %oldValue;
ParticleEditor.submitUndo( %action );
}
// Generic updateRibbon method
function PE_RibbonParticleEditor::updateRibbon( %this, %propertyField, %value, %isSlider, %onMouseUp )
{
PE_RibbonParticleEditor.setDirty();
%ribbon = %this.currRibbon;
%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(ActionUpdateActiveRibbon, "Update Active Ribbon");
%action.ribbon = %ribbon;
%action.field = %propertyField;
%action.isSlider = %isSlider;
%action.onMouseUp = %onMouseUp;
%action.newValue = %value;
%action.oldValue = %ribbon.getFieldValue( %propertyField );
ParticleEditor.submitUndo( %action );
}
%ribbon.setFieldValue( %propertyField, %value );
%ribbon.reload();
}
//---------------------------------------------------------------------------------------------
function PE_RibbonParticleEditor::updateParticlesFields( %this )
{
%particles = "";
for( %i = 1; %i < 5; %i ++ )
{
%ribbonParticle = "PEE_RibbonParticle" @ %i;
%popup = %ribbonParticle-->PopUpMenu;
%text = %popup.getText();
if( %text $= "" || %text $= "None" )
continue;
if( %particles $= "" )
%particles = %text;
else
%particles = %particles SPC %text;
}
%changedEditParticle = 1;
%currParticle = PE_ParticleEditor.currParticle.getName();
foreach$( %particleName in %particles )
{
if( %particleName $= %currParticle )
{
%changedEditParticle = 0;
break;
}
}
// True only if the currently edited particle has not been found and the
// ParticleEditor is dirty.
if( %changedEditParticle && PE_ParticleEditor.dirty )
{
toolsMessageBoxYesNoCancel("Save Particle Changes?",
"Do you wish to save the changes made to the <br>current particle before changing the particle?",
"PE_ParticleEditor.saveParticle( " @ PE_ParticleEditor.currParticle.getName() @ " ); PE_RibbonParticleEditor.updateRibbon( \"particles\"," @ %particles @ ");",
"PE_ParticleEditor.saveParticleDialogDontSave( " @ PE_ParticleEditor.currParticle.getName() @ " ); PE_RibbonParticleEditor.updateRibbon( \"particles\"," @ %particles @ ");",
"PE_RibbonParticleEditor.guiSync();" );
}
else
{
PE_RibbonParticleEditor.updateRibbon( "particles", %particles );
}
}
//---------------------------------------------------------------------------------------------
function PE_RibbonParticleEditor::setDirty( %this )
{
%this.text = "*Ribbon";
%this.dirty = true;
if(!startsWith(%this-->PopupMenu.text, "*"))
{
%this-->PopupMenu.text = "*" @ %this-->PopupMenu.text;
}
%ribbon = %this.currRibbon;
%filename = %ribbon.getFilename();
%editorFilename = "tools/particleEditor/scripts/particleRibbonEditor.ed." @ $TorqueScriptFileExtension;
if( %filename $= "" || %filename $= %editorFilename )
%this.saver.setDirty( %ribbon, $PE_RibbonParticleEditor_DEFAULT_FILENAME );
else
%this.saver.setDirty( %ribbon );
}
//---------------------------------------------------------------------------------------------
function PE_RibbonParticleEditor::setNotDirty( %this )
{
PE_RibbonParticleEditor.text = "Ribbon";
PE_RibbonParticleEditor.dirty = false;
if(startsWith(%this-->PopupMenu.text, "*"))
{
%this-->PopupMenu.text = stripChars(%this-->PopupMenu.text, "*");
}
%this.saver.clearAll();
}
//---------------------------------------------------------------------------------------------
// Create Functionality
function PE_RibbonParticleEditor::showNewDialog( %this )
{
//FIXME: disregards particle tab dirty state
// Open a dialog if the current ribbon is dirty.
if( PE_ParticleEditor.dirty )
{
toolsMessageBoxYesNo("Save Existing Ribbon?",
"Do you want to save changes to <br><br>" @ PE_ParticleEditor.currParticle.getName(),
"PE_ParticleEditor.saveParticle(" @ PE_ParticleEditor.currParticle @ ");"
);
}
if( PE_RibbonParticleEditor.dirty )
{
toolsMessageBoxYesNoCancel("Save Ribbon Changes?",
"Do you wish to save the changes made to the <br>current ribbon before changing the ribbon?",
"PE_RibbonParticleEditor.saveRibbon( " @ PE_RibbonParticleEditor.currRibbon.getName() @ " ); PE_RibbonParticleEditor.createRibbon();",
"PE_RibbonParticleEditor.saveRibbonDialogDontSave( " @ PE_RibbonParticleEditor.currRibbon.getName() @ " ); PE_RibbonParticleEditor.createRibbon();"
);
}
else
{
PE_RibbonParticleEditor.createRibbon();
}
}
//---------------------------------------------------------------------------------------------
function PE_RibbonParticleEditor::createRibbon( %this )
{
AssetBrowser_SelectModule.showDialog("PE_RibbonParticleEditor.pickedNewRibbonTargetModule");
AssetBrowser_SelectModuleWindow.selectWindow();
}
function PE_RibbonParticleEditor::pickedNewRibbonTargetModule( %this, %module )
{
ParticleEditorCreatePrompt.show("Ribbon", "RibbonData", "PE_RibbonParticleEditor.doCreateNewRibbon(\"" @ %module @ "\");" );
}
function PE_RibbonParticleEditor::doCreateNewRibbon( %this, %module )
{
//Sanity checks
%newName = ParticleEditorCreatePrompt-->nameText.getText();
if(%newName $= "")
{
toolsMessageBoxOK("Error", "New Ribbon requires a name!");
return;
}
Canvas.popDialog(ParticleEditorCreatePrompt);
%sourceDB = ParticleEditorCreatePrompt-->CopySourceDropdown.getText();
if(%sourceDB $= "")
%sourceDB = DefaultRibbon;
%moduleDef = ModuleDatabase.findModule(%module);
PE_RibbonParticleEditor.targetModule = %module;
$PE_RibbonParticleEditor_DEFAULT_FILENAME = %moduleDef.ModulePath @ "/scripts/managedData/managedRibbonData." @ $TorqueScriptFileExtension;
if(!isDirectory(filePath($PE_RibbonParticleEditor_DEFAULT_FILENAME)))
{
AssetBrowser.dirHandler.createFolder(filePath($PE_RibbonParticleEditor_DEFAULT_FILENAME));
}
// Create a new ribbon.
%ribbon = getUniqueName( %newName );
eval("datablock RibbonData( " @ %ribbon @ " : " @ %sourceDB @ " ){};");
// Submit undo.
%action = ParticleEditor.createUndo( ActionCreateNewRibbon, "Create New Ribbon" );
%action.prevRibbon = PE_RibbonParticleEditor.currRibbon;
%action.ribbon = %ribbon.getId();
%action.ribbonName = %ribbon;
ParticleEditor.submitUndo( %action );
// Execute action.
%action.redo();
%this.saver.setDirty(%ribbon, $PE_RibbonParticleEditor_DEFAULT_FILENAME);
%this.loadNewRibbon(%ribbon);
%this.setDirty();
}
//---------------------------------------------------------------------------------------------
function PE_RibbonParticleEditor::showDeleteDialog( %this )
{
if( PE_RibbonParticleEditor.currRibbon.getName() $= "BasicRibbon" )
{
toolsMessageBoxOK( "Error", "Cannot delete BasicRibbon");
return;
}
if( isObject( PE_RibbonParticleEditor.currRibbon ) )
{
toolsMessageBoxYesNoCancel("Delete Ribbon?",
"Are you sure you want to delete<br><br>" @ PE_RibbonParticleEditor.currRibbon.getName() @ "<br><br> Ribbon deletion won't take affect until the level is exited.",
"PE_RibbonParticleEditor.saveRibbonDialogDontSave( " @ PE_RibbonParticleEditor.currRibbon.getName() @ " ); PE_RibbonParticleEditor.deleteRibbon();"
);
}
}
//---------------------------------------------------------------------------------------------
function PE_RibbonParticleEditor::deleteRibbon( %this )
{
%ribbon = PE_RibbonParticleEditor.currRibbon;
// Create undo.
%action = ParticleEditor.createUndo( ActionDeleteRibbon, "Delete Ribbon" );
%action.ribbon = %ribbon;
%action.ribbonFname = %ribbon.getFilename();
ParticleEditor.submitUndo( %action );
// Execute action.
%action.redo();
}
//---------------------------------------------------------------------------------------------
function PE_RibbonParticleEditor::saveRibbon( %this, %ribbon )
{
if ( %ribbon $= "" )
{
%ribbon = %this.currRibbon;
%newName = %this.currRibbon.getName();
}
else
{
%newName = %ribbon.getName();
}
%this.currRibbon.setName( %newName );
PE_RibbonParticleEditor_NotDirtyRibbon.assignFieldsFrom( %ribbon );
PE_RibbonParticleEditor_NotDirtyRibbon.originalName = %newName;
%this.saver.saveDirty();
%this.loadNewRibbon(%newName.getId());
}
//---------------------------------------------------------------------------------------------
function PE_RibbonParticleEditor::saveRibbonDialogDontSave( %this, %ribbon)
{
%ribbon.setName( PE_RibbonParticleEditor_NotDirtyRibbon.originalName );
%ribbon.assignFieldsFrom( PE_RibbonParticleEditor_NotDirtyRibbon );
PE_RibbonParticleEditor.setNotDirty();
}