Below is an example demonstrating how to save the settings of an asset save filter as a JSON template file that can be loaded and applied by another script.
See Also:
// Define an anonymous function; // serves as our main loop, // limits the scope of variables (function(){ // Get the arguments passed in var s_aArgs = getArguments(); // Initialize 'static' variables that hold modifier key state var s_bShiftPressed = false; var s_bControlPressed = false; var s_bAltPressed = false; var s_bMetaPressed = false; // If the "Action" global transient is defined, and its the correct type if( typeof( Action ) != "undefined" && Action.inherits( "DzScriptAction" ) ){ // If the current key sequence for the action is not pressed if( !App.isKeySequenceDown( Action.shortcut ) ){ updateModifierKeyState(); } // If the "Action" global transient is not defined } else if( typeof( Action ) == "undefined" ) { updateModifierKeyState(); } /*********************************************************************/ // void : A function for updating the keyboard modifier state function updateModifierKeyState() { // Get the current modifier key state var nModifierState = App.modifierKeyState(); // Update variables that hold modifier key state s_bShiftPressed = (nModifierState & 0x02000000) != 0; s_bControlPressed = (nModifierState & 0x04000000) != 0; s_bAltPressed = (nModifierState & 0x08000000) != 0; s_bMetaPressed = (nModifierState & 0x10000000) != 0; }; /*********************************************************************/ // void : A function for printing only if debugging function debug() { // If we are not debugging if( !s_bAltPressed ){ // We are done... return; } // Convert the arguments object into an array var aArguments = [].slice.call( arguments ); // Print the array print( aArguments.join(" ") ); }; /*********************************************************************/ // String : A function for retrieving a translation if one exists function text( sText ) { // If the version of the application supports qsTr() if( typeof( qsTr ) != "undefined" ){ // Return the translated (if any) text return qsTr( sText ); } // Return the original text return sText; }; /*********************************************************************/ // Boolean : A function for testing whether or not a QObject instance // inherits one of a list of types function inheritsType( oObject, aTypeNames ) { // If the object does not define the 'inherits' function if( !oObject || typeof( oObject.inherits ) != "function" ){ // We are done... it is not a QObject return false; } // Iterate over the list of type names for( var i = 0, nTypes = aTypeNames.length; i < nTypes; i += 1 ){ // If the object does not inherit the 'current' type if( !oObject.inherits( aTypeNames[i] ) ){ // Next!! continue; } // Return the result return true; } // Return the result return false; }; /*********************************************************************/ // DzNode : A function for getting the root of a node function getRootNode( oNode ) { // If we have a node and it is a bone if( oNode && inheritsType( oNode, ["DzBone"] ) ){ // We want the skeleton return oNode.getSkeleton(); } // Return the original node return oNode; }; /*********************************************************************/ // DzComboBox : A function for building a save filter combobox function buildSaveFilterCombobox( wCmb, aExclude ) { // Get the asset IO manager var oAssetIOMgr = App.getAssetIOMgr(); // Declare variables we'll be using as we iterate var oAssetIOFilter, oSettings; // Define the list of filters; in display order var aFilters = [ "DzSceneAssetFilter", "DzSceneSubsetAssetFilter", "DzHierarchicalMaterialAssetFilter", "DzHierarchicalPoseAssetFilter", "DzWearablesAssetFilter", "DzCharacterAssetFilter", "DzPropertiesAssetFilter", "DzShapingAssetFilter", "DzPoseAssetFilter", "DzMaterialAssetFilter", "DzShaderAssetFilter", "DzCameraAssetFilter", "DzLightAssetFilter", "DzRenderSettingsAssetFilter", "DzSimulationSettingsAssetFilter", "DzDFormAssetFilter", "DzLayerAssetFilter", "DzPuppeteerAssetFilter", "---", "DzSceneSupportAssetFilter", "DzNodeSupportAssetFilter", "DzMorphSupportAssetFilter", "DzUVSupportAssetFilter", "DzShaderSupportAssetFilter", ]; // Declare working variables var sFilter; var nIdx; // Get the number of items in our list var nFilters = aFilters.length; // Iterate over our list for( var i = 0; i < nFilters; i += 1 ){ // Get the 'current' filter sFilter = aFilters[i]; // If the 'filter' is in the exclude list if( aExclude.indexOf( sFilter ) > -1 ) { // Next!! continue; } // If the 'filter' is a separator if( sFilter == "---" ) { // Insert a separator at the end wCmb.insertSeparator( wCmb.count ); // Next!! continue; } // Find the filter index nIdx = oAssetIOMgr.findFilter( sFilter ); // If the filter was not found if( nIdx < 0 ){ // Next!! continue; } // Get the filter oAssetIOFilter = oAssetIOMgr.getFilter( nIdx ); // Add the filter to the choices wCmb.addItem( oAssetIOFilter.getDescription().replace( "...", "" ), oAssetIOFilter.className() ); // Clean up; do not leak memory oAssetIOFilter.deleteLater(); } // Insert a separator between filters we have // explicitly handled and those we have not wCmb.insertSeparator( wCmb.count ); // Get the number of filters nFilters = oAssetIOMgr.getNumFilters(); // Iterate over all filters for( var i = 0; i < nFilters; i += 1 ){ // Get the 'current' filter oAssetIOFilter = oAssetIOMgr.getFilter( i ); // Get the filter classname sFilter = oAssetIOFilter.className(); // If the 'filter' has already been added // or it is in the exclude list if( aFilters.indexOf( sFilter ) > -1 || aExclude.indexOf( sFilter ) > -1 ){ // Clean up; do not leak memory oAssetIOFilter.deleteLater(); // Next!! continue; } // Add the filter to the choices wCmb.addItem( oAssetIOFilter.getDescription().replace( "...", "" ), oAssetIOFilter.className() ); // Clean up; do not leak memory oAssetIOFilter.deleteLater(); } }; /*********************************************************************/ // String : A function for getting input from the user function getAssetFilter( sTitle, aExclude ) { // Get the current style var oStyle = App.getStyle(); // Get pixel metrics from the current style var nMargin = oStyle.pixelMetric( "DZ_GeneralMargin" ); var nBtnHeight = oStyle.pixelMetric( "DZ_ButtonHeight" ); // Create a basic dialog var wDlg = new DzBasicDialog(); // Get the wrapped widget for the dialog var oDlgWgt = wDlg.getWidget(); // Strip the space for a settings key var sKey = sTitle.replace( / /g, "" ) + "Dlg"; // Set an [unique] object name on the wrapped dialog widget; // this is used for recording position and size separately // from all other [uniquely named] DzBasicDialog instances oDlgWgt.objectName = sKey; // Set the title of the dialog wDlg.caption = text( sTitle ); // Create a widget var wMainWgt = new DzWidget( wDlg ); // Create a grid layout var lytMain = new DzGridLayout( wMainWgt ); lytMain.margin = nMargin; lytMain.spacing = nMargin; lytMain.setColStretch( 1, 1 ); // Initialize var nRow = 0; // Create a label var wLabel = new DzLabel( wMainWgt ); wLabel.text = text( "Filter :" ); wLabel.alignment = DzWidget.AlignRight | DzWidget.AlignVCenter; // Add the label to the layout lytMain.addWidget( wLabel, nRow, 0 ); // Create a combo box var wSaveFilterCmb = new DzComboBox( wMainWgt ); // Populate the combobox with save filters buildSaveFilterCombobox( wSaveFilterCmb, aExclude ); // Set the height wSaveFilterCmb.setFixedHeight( nBtnHeight ); // Add the combo box to the layout lytMain.addWidget( wSaveFilterCmb, nRow, 1 ); nRow += 1; // Add the main widget to the dialog wDlg.addWidget( wMainWgt ); // Get the minimum size of the dialog var sizeHint = oDlgWgt.minimumSizeHint; // Set the fixed height of the dialog wDlg.setFixedHeight( sizeHint.height ); // If the user accepts the dialog if( wDlg.exec() ){ // Return the user's choice return wSaveFilterCmb.itemData( wSaveFilterCmb.currentItem ); } // Return an empty string return ""; }; /*********************************************************************/ // String : A function for getting string input from the user function getUserString( sTitle, sLabel, sHint, sText, aOptions ) { // Create a basic dialog var wDlg = new DzBasicDialog(); // Get the wrapped widget for the dialog var oDlgWgt = wDlg.getWidget(); // Set the title of the dialog wDlg.caption = text( sTitle ); // Strip the space for a settings key var sKey = sTitle.replace( / /g, "" ) + "Dlg"; // Set an [unique] object name on the wrapped dialog widget; // this is used for recording position and size separately // from all other [uniquely named] DzBasicDialog instances oDlgWgt.objectName = sKey; // Create a widget var wMainWgt = new DzWidget( wDlg ); // Get the current style var oStyle = App.getStyle(); // Get the height for buttons var nMargin = oStyle.pixelMetric( "DZ_GeneralMargin" ); // Create a horizontal box layout var lytMain = new DzHBoxLayout( wMainWgt ); lytMain.margin = nMargin; lytMain.spacing = nMargin; // Create a label var wLabel = new DzLabel( wMainWgt ); wLabel.text = sLabel; wLabel.alignment = DzWidget.AlignRight | DzWidget.AlignVCenter; // Add the label to the layout lytMain.addWidget( wLabel ); // Create a combo edit var wCmbEdit = new DzComboEdit( wMainWgt ); wCmbEdit.submenuDelimiter = "/"; wCmbEdit.menuSelectionIncludesPath = true; wCmbEdit.placeholderText = sHint; wCmbEdit.text = sText; wCmbEdit.addItems( aOptions ); // Add the line edit to the layout lytMain.addWidget( wCmbEdit ); // Add the widget to the dialog wDlg.addWidget( wMainWgt ); // Get the minimum size of the dialog var sizeHint = oDlgWgt.minimumSizeHint; // Set the fixed size of the dialog wDlg.setFixedHeight( sizeHint.height ); // If the user accepts the dialog if( wDlg.exec() ){ // Return the user's input return wCmbEdit.text; } // Return an empty string return ""; }; /*********************************************************************/ // String : A function for getting the path of a script that resides next to this script function getAdjacentScriptPath( sName, bNotify ) { // Create a file info object for this file var oFileInfo = new DzFileInfo( getScriptFileName() ); // Define the base path of the script we will call; without the file extension var sBasePath = String( "%1/%2" ).arg( oFileInfo.path() ).arg( sName ); // Clean up; do not leak memory oFileInfo.deleteLater(); // Create a script object var oScript = new DzScript(); // Attempt to find our script; doing it this way, we can debug with an // ascii file and distribute a binary [encrypted] file with the same name... // without having to update the contents of the script or manually handle // the file extensions; requires 3.0.1.5 or newer var sScriptPath = oScript.getScriptFile( sBasePath ); // Clean up; do not leak memory oScript.deleteLater(); // If a script is not found if( sScriptPath.isEmpty() && bNotify ){ // Define message strings var sTitle = text( "File Not Found" ); var sMessage = text( "A '%1.ds(a|b|e)' file could not be found." ).arg( sBasePath ); var sButton = text( "&OK" ); // Inform the user MessageBox.information( sMessage, sTitle, sButton ); } // Return the result return sScriptPath; }; /*********************************************************************/ // Boolean : A function for executing a script that resides next to this script function executeAdjacentScript( sName, aArgs ) { // Initialize var bResult = true; // Get the path of our script var sScriptPath = getAdjacentScriptPath( sName, true ); // If a script is found if( !sScriptPath.isEmpty() ){ // Create a script object var oScript = new DzScript(); // If the script loads if( oScript.loadFromFile( sScriptPath ) ){ // Execute the script with our argument if( !oScript.execute( aArgs ) ){ // Update our variable bResult = false; } // If the script does not load } else { // Define message strings var sTitle = text( "Read Error" ); var sMessage = text( "The '%1' file could not be loaded." ).arg( sScriptPath ); var sButton = text( "&OK" ); // Inform the user MessageBox.information( sMessage, sTitle, sButton ); } // Clean up; do not leak memory oScript.deleteLater(); } // Return the result return bResult; }; /*********************************************************************** ***** DsFileSystem Prototype ***** ***********************************************************************/ // Create an interface object var s_oFileSystem = new DsFileSystem(); /*********************************************************************/ function DsFileSystem() { }; /***********************************************************************/ DsFileSystem.superclass = Object; /*********************************************************************/ // Array<String|DzDir> : Method for collecting an array of directory objects DsFileSystem.prototype.getDirectories = function( oDir, regxFilter, nFilter, nSort, sType, bRecurse ) { // Provide feedback debug( String("DsFileSystem::getDirectories( %1, \"%2\", %3, %4, \"%5\", %6 )") .arg( oDir.path() ) .arg( regxFilter ) .arg( nFilter ) .arg( nSort ) .arg( sType ) .arg( bRecurse ) ); // Declare working variable var sAbsPath; // Get the directory names var aDirs = oDir.entryList( regxFilter, nFilter, nSort ); // Iterate over the directory names for( var i = 0, nDirs = aDirs.length; i < nDirs; i += 1 ){ // Get the absolute path of the 'current' directory sAbsPath = String( "%1/%2" ).arg( oDir.absPath() ).arg( aDirs[ i ] ); // Based on the type requested switch( sType ){ default: case "String": // Update the name with the absolute path of the directory aDirs[ i ] = sAbsPath; // If we are recursing if( bRecurse ){ // Recursively collect the directory paths aDirs = aDirs.concat( this.getSubDirectories( new DzDir( sAbsPath ), regxFilter, nFilter, nSort, sType ) ); } break; case "DzDir": // Update the name with a directory object aDirs[ i ] = new DzDir( sAbsPath ); // If we are recursing if( bRecurse ){ // Recursively collect the directories aDirs = aDirs.concat( this.getSubDirectories( aDirs[ i ], regxFilter, nFilter, nSort, sType ) ); } break; } } // Return the result return aDirs; }; /*********************************************************************/ // Array<String|DzDir> : Method for recursively collecting an array of directory objects DsFileSystem.prototype.getSubDirectories = function( oDir, regxFilter, nFilter, nSort, sType ) { // Provide feedback debug( String( "DsFileSystem::getSubDirectories( %1, \"%2\", %3, %4, \"%5\" )" ) .arg( oDir.path() ) .arg( regxFilter ) .arg( nFilter ) .arg( nSort ) .arg( sType ) ); // Initialize var aSubDirs = []; // Get the immediate child directories var aDirs = this.getDirectories( oDir, regxFilter, nFilter, nSort, sType, true ); // Iterate over the directories for( var i = 0, nDirs = aDirs.length; i < nDirs; i += 1 ){ // Based on the type requested switch( sType ){ default: case "String": // Recursively collect the directory paths aSubDirs = aDirs.concat( this.getSubDirectories( new DzDir( aDirs[ i ] ), regxFilter, nFilter, nSort, sType ) ); break; case "DzDir": // Recursively collect the directories aSubDirs = aDirs.concat( this.getSubDirectories( aDirs[ i ], regxFilter, nFilter, nSort, sType, true ) ); break; } } // Return the result return aSubDirs; }; /*********************************************************************/ // Array<String|DzFileInfo|DzFile> : Method for collecting an array of files DsFileSystem.prototype.getFiles = function( oDir, regxFilter, nFilter, nSort, sType ) { // Provide feedback debug( String( "DsFileSystem::getFiles( %1, \"%2\", %3, %4, \"%5\" )" ) .arg( oDir.path() ) .arg( regxFilter ) .arg( nFilter ) .arg( nSort ) .arg( sType ) ); // Declare working variable var sAbsFilePath; // Get the file names var aFiles = oDir.entryList( regxFilter, nFilter, nSort ); // Iterate over the file names for( var i = 0, nFiles = aFiles.length; i < nFiles; i += 1 ){ // Get the absolute path of the 'current' file sAbsFilePath = oDir.absFilePath( aFiles[ i ] ); // Based on the type requested switch( sType ){ default: case "String": // Update the name with the absolute path of a file aFiles[ i ] = sAbsFilePath; break; case "DzFileInfo": // Update the name with a file info object aFiles[ i ] = new DzFileInfo( sAbsFilePath ); break; case "DzFile": // Update the name with a file object aFiles[ i ] = new DzFile( sAbsFilePath ); break; } } // Return the result return aFiles; }; /*********************************************************************/ // Array<String|DzDir> : Method for retrieving a list of directories DsFileSystem.prototype.getDirectoryList = function( sPath, sFilter, sType, bRecurse, bRelative ) { // Declare the output var aDirs = []; // Create a directory object var oBaseDir = new DzDir( sPath ); // If the directory doesn't exist if( !oBaseDir.exists() ){ // Clean up; do not leak memory oBaseDir.deleteLater(); // We are done... return aDirs; } // Get the directories var aDirs = this.getDirectories( oBaseDir, sFilter, DzDir.Dirs | DzDir.NoDotAndDotDot, DzDir.Name, sType, bRecurse ); // Clean up; do not leak memory oBaseDir.deleteLater(); // If we do not want relative paths if( !bRelative ){ // Return the result return aDirs; } // Declare working variables var sAbsPath, sRelPath; var oDir; // Iterate over the directories for( var i = 0, nDirs = aDirs.length; i < nDirs; i += 1 ){ // Based on the type requested switch( sType ){ default: case "String": // Get the 'current' path sAbsPath = aDirs[ i ]; // Get the relative portion of the path sRelPath = sAbsPath.substring( sPath.length ); // Update the path aDirs[ i ] = sRelPath; break; case "DzDir": // Get the 'current' directory oDir = aDirs[ i ]; // Get the path sAbsPath = oDir.path(); // Get the relative portion of the path sRelPath = sAbsPath.substring( sPath.length ); // Update the path oDir.setPath( sRelPath ); // Update the directory aDirs[ i ] = oDir; break; } } // Return the result return aDirs; }; /*********************************************************************/ // Array<String|DzFileInfo|DzFile> : Method for retrieving a list of files DsFileSystem.prototype.getFileList = function( sPath, sFilter, sType, bRecurse ) { // Initialize var aFiles = []; // Create a directory object var oBaseDir = new DzDir( sPath ); // If the directory doesn't exist if( !oBaseDir.exists() ){ // Clean up; do not leak memory oBaseDir.deleteLater(); // We are done... return aFiles; } // Get the files from the specified directory aFiles = this.getFiles( oBaseDir, sFilter, DzDir.Files, DzDir.Name, sType ); // Clean up; do not leak memory oBaseDir.deleteLater(); // If we are recursing if( bRecurse ){ // Declare working variable var oDir; // Get the directories var aDirs = this.getDirectoryList( sPath, "*", "DzDir", bRecurse ); // Iterate over the directories for( var i = 0, nDirs = aDirs.length; i < nDirs; i += 1 ){ // Get the 'current' directory oDir = aDirs[ i ]; // Append the files from the 'current' directory to the output aFiles = aFiles.concat( this.getFiles( oDir, sFilter, DzDir.Files, DzDir.Name, sType ) ); // Clean up; do not leak memory oDir.deleteLater(); } } // Return the result return aFiles; }; /*********************************************************************/ // Define common message variables var sTitle = text( "Critical Error" ); var sMessage = text( "An asset filter with the class name " + "\"%1\" could not be found.").arg( sClassName ) var sButton = text( "&OK" ); // Get the root node of the primary selection var oRootNode = getRootNode( Scene.getPrimarySelection() ); // If we do not have a selection if( !oRootNode ){ // Define message strings sTitle = text( "Selection Error" ); sMessage = text( "A node in the scene must be selected to continue." ); // Inform the user MessageBox.information( sMessage, sTitle, sButton ); // We are done... return; } // Initialize var sClassName = ""; // If an arg was passed in, and it is a string if( s_aArgs.length == 1 && typeof( s_aArgs[0] ) == "string" ){ // Update the classname of the filter to use sClassName = s_aArgs[0]; // If we are executed "standalone" } else { // Define the list of filters to exclude; i.e., those that either // provide no options, or do not make sense to templatize var aExclude = [ "DzSceneAssetFilter", "DzPuppeteerAssetFilter" ]; // If the version of the application is older than 4.11.0.229 if( App.version64 < 0x0004000b000000e5 ){ // Exclude filters that had a bug with displaying their option dialog aExclude = aExclude.concat( [ "DzMaterialAssetFilter", "DzShaderAssetFilter" ] ); } // Define the class name of the asset filter we want to use sClassName = getAssetFilter( "Save Filter Template Save", aExclude ); } // If the user cancelled if( sClassName.isEmpty() ){ // We are done... return; } // Get the asset IO manager var oAssetIOMgr = App.getAssetIOMgr(); // Find the index of the asset filter with the class name we want var nAssetIOFilter = oAssetIOMgr.findFilter( sClassName ); // If we did not find an asset filter with the class name we wanted if( nAssetIOFilter < 0 ){ // Inform the user MessageBox.critical( sMessage, sTitle, sButton ); // We are done... return; } // Get the asset filter at the prescribed index var oAssetIOFilter = oAssetIOMgr.getFilter( nAssetIOFilter ); // If we do not have a valid asset filter if( !oAssetIOFilter ){ // Inform the user MessageBox.critical( sMessage, sTitle, sButton ); // We are done... return; } // Construct the path for the template file var sTemplatePath = String( "%1/Save Filter Settings Templates/%2/%3" ) .arg( App.getAppDataPath() ) .arg( sClassName ) .arg( oRootNode.name ); // Create a directory object for template files var oTemplateDir = new DzDir( sTemplatePath ); // Make sure the template directory exists; // if it does not exist and cannot be created if( !oTemplateDir.mkpath( sTemplatePath ) ){ // Define message strings sTitle = text( "Resource Error" ); sMessage = text( "The settings template directory could not be created: %1" ) .arg( sTemplatePath ); // Inform the user MessageBox.warning( sMessage, sTitle, sButton, "" ); // Clean up; do not leak memory oAssetIOFilter.deleteLater(); // We are done... return; } // Create a settings object var oSettings = new DzFileIOSettings(); // Display the options dialog and record the settings; // if the user cancels if( !oAssetIOFilter.getOptions( oSettings, true, "" ) ){ // Clean up; do not leak memory oAssetIOFilter.deleteLater(); // We are done... return; } // Debug debug( "Settings:", oSettings.toJsonString() ); // Define the file extension var sExt = "json"; // Get the list of template files var aPaths = s_oFileSystem.getFileList( sTemplatePath, "*." + sExt, "String", true ); // Declare working variables var sPath; var nStart, nEnd; // Iterate over the template paths for( var i = 0, nPaths = aPaths.length; i < nPaths; i += 1 ){ // Get the 'current' path sPath = aPaths[ i ]; // Set the start/end of the substring nStart = sTemplatePath.length + 1; nEnd = sPath.length - sExt.length - 1; // Get the relative basename aPaths[ i ] = sPath.substring( nStart, nEnd ); } // Initialize var sTemplateFile = ""; // Declasre working variable var nIdx; // Define common variables var sTmpTitle = text( "Save Filter Template Save" ); var sTmpLabel = text( "Name:" ); var sTmpHint = text( "Enter a name for the template..." ); var sTmpText = ""; // Do this at least once do { // Prompt the user for the path/name of the template sTmpText = getUserString( sTmpTitle, sTmpLabel, sTmpHint, sTmpText, aPaths ); // If the user cancelled if( sTmpText.isEmpty() ){ // Clear sTemplateFile = ""; // If the user did not cancel } else { // Construct the path sTemplateFile = String( "%1/%2.json" ) .arg( sTemplatePath ) .arg( sTmpText ); } // If the template path is not defined if( sTemplateFile.isEmpty() ){ // Clean up; do not leak memory oAssetIOFilter.deleteLater(); // We are done... return; } // Get the index of the last slash nIdx = sTemplateFile.lastIndexOf( "/" ); // Make sure the template directory exists; // if it does not exist and cannot be created if( nIdx > -1 && !oTemplateDir.mkpath( sTemplateFile.substring( 0, nIdx ) ) ){ // Define message strings sTitle = text( "Resource Error" ); sMessage = text( "The template directory could not be created: %1" ) .arg( sTemplatePath ); // Inform the user MessageBox.warning( sMessage, sTitle, sButton, "" ); } // Keep prompting until the user indicates that it is either // OK to (over)write the file, or they provide a unique path/name } while( !MainWindow.checkExistingFile( sTemplateFile ) ); // Define the key used to select a node in node based filters var sKey = "RootLabel"; // If this key is present if( oSettings.hasKey( sKey ) ){ // Remove the value; cause the filter to use primary selection oSettings.removeValue( sKey ); } // Define the key used to refer to a node in node based filters sKey = "NodeNames"; // If the key is present if( oSettings.hasKey( sKey ) ){ // Get the settings var oNamesSettings = oSettings.getSettingsValue( sKey ); // If we have the settings and it has the root node's name as a key if( oNamesSettings && oNamesSettings.hasKey( oRootNode.name ) ){ // Get the node settings var oNodeSettings = oNamesSettings.getSettingsValue( oRootNode.name ); // If we have the settings if( oNodeSettings ){ // Copy the settings to a new settings with a name we can replace on read var oSelectionSettings = oNamesSettings.setSettingsValue( "@selection", oNodeSettings ); // Remove the node named setting oNamesSettings.removeValue( oRootNode.name ); } } } // Create a new file object var oTemplateFile = new DzFile( sTemplateFile ); // Open the file for writing oTemplateFile.open( DzFile.WriteOnly ); // Convert the settings object to a string var sTemplateData = oSettings.toJsonString(); // Write the template data to the file var nResult = oTemplateFile.write( sTemplateData ); // Close the file oTemplateFile.close(); // If there was no error if( nResult > -1 ){ // Debug debug( "Saved:", sTemplateFile ); // If there was an error } else { // Debug debug( "Error saving:", sTemplateFile ); } // Clean up; do not leak memory oTemplateFile.deleteLater(); oTemplateDir.deleteLater(); oAssetIOFilter.deleteLater(); // Create a file info object for this file var oFileInfo = new DzFileInfo( getScriptFileName() ); // Construct the name of an adjacent script to look for var sScriptName = String("%1_%2").arg( oFileInfo.baseName() ).arg( sClassName ); // If we have an adjacent script for the chosen filter if( !getAdjacentScriptPath( sScriptName, false ).isEmpty() ) { // Execute the adjacent script executeAdjacentScript( sScriptName, [ sTemplateFile ] ); } // Clean up; do not leak memory oFileInfo.deleteLater(); // Finalize the function and invoke })();