// =========================================================================== // Copyright 2018 Autodesk, Inc. All rights reserved. // // Use of this software is subject to the terms of the Autodesk license // agreement provided at the time of installation or download, or which // otherwise accompanies this software in either electronic or hard copy form. // =========================================================================== // ---------------------------------------------------------------------------- // ---------------------------------------------------------------------------- // Functions defined in this file (gameFbxExporterUtilities.mel): // // global proc string gameExp_GetPrefixedName(string $name) // global proc gameExp_ChangeExportType(int $tabIndex) // global proc gameExp_CreateExportTypeUIComponents() // global proc gameExp_CreateFileFormatComponents() // global proc gameExp_CreateAdvanceSettingsGearButton() // global proc string gameExp_CreatePathUIComponents() // global proc string gameExp_ProvideUniqueName(string $name, string $uniqueNameLst[]) // global proc int gameExp_OverwriteExistingFile(string $path) // global proc int gameExp_OverwriteExistingFiles(string $fileNameList[], int $overwriteListLimit) // global proc gameExp_CreateFilenamePreview() // global proc gameExp_ShowMessage(string $message, int $msgType) // // ---------------------------------------------------------------------------- // ---------------------------------------------------------------------------- // ---------------------------------------------------------------------------- // ---------------------------------------------------------------------------- // Add a name prefix for all UI that are used in all tabs but created in // one place. // ---------------------------------------------------------------------------- // ---------------------------------------------------------------------------- global proc string gameExp_GetPrefixedName(string $name) { global string $gameExporterPrefix; return ($gameExporterPrefix + $name); } // ---------------------------------------------------------------------------- // ---------------------------------------------------------------------------- // Change the Tab selected. // ---------------------------------------------------------------------------- // ---------------------------------------------------------------------------- global proc gameExp_ChangeExportType(int $tabIndex) { tabLayout -e -selectTabIndex $tabIndex gameExporterTabLayout; gameExp_UpdatePrefix(); } // ---------------------------------------------------------------------------- // ---------------------------------------------------------------------------- // Create the Export Type UI Components // ---------------------------------------------------------------------------- // ---------------------------------------------------------------------------- global proc gameExp_CreateExportTypeUIComponents() { global string $gGameFbxExporterCurrentNode; global int $gGameExporterWindowHeight[]; string $gameExporterMainFormLayout = gameExp_GetPrefixedName("gameExporterMainFormLayout"); setParent $gameExporterMainFormLayout; if( size($gGameFbxExporterCurrentNode) ) { string $gameExporterExportSet = gameExp_GetPrefixedName("gameExporterExportSet"); int $exportSetIndex = `getAttr($gGameFbxExporterCurrentNode + ".exportSetIndex")`; optionMenu -edit -select $exportSetIndex -changeCommand ("setAttr(\"" + $gGameFbxExporterCurrentNode + ".exportSetIndex\") `optionMenu -q -select " + $gameExporterExportSet + "`; gameExp_CreateExportTypeUIComponents;") $gameExporterExportSet; string $gameExporterExportSelectionSet = gameExp_GetPrefixedName("gameExporterExportSelectionSet"); optionMenu -edit -enable ($exportSetIndex == 3) -changeCommand ("setAttr(\"" + $gGameFbxExporterCurrentNode + ".selectionSetName\") -type \"string\" \"#1\"") $gameExporterExportSelectionSet; gameExp_CreateSelectionSetList(); } string $gameExporterExportTypeFormLayout = gameExp_GetPrefixedName("gameExporterExportTypeFormLayout"); if (`layout -exists $gameExporterExportTypeFormLayout`) { deleteUI -layout $gameExporterExportTypeFormLayout; } formLayout $gameExporterExportTypeFormLayout; int $tabIndex = `tabLayout -q -selectTabIndex gameExporterTabLayout`; if( $tabIndex == 1 ) { // Model gameExp_ModelLayoutOrder($gameExporterExportTypeFormLayout); } else if ( $tabIndex == 2 ) { // Animation Clips gameExp_AnimationLayoutOrder($gameExporterExportTypeFormLayout); } else if ( $tabIndex == 3 ) { // Time Editor Clips gameExp_AnimationLayoutOrder($gameExporterExportTypeFormLayout); // Refresh clips cte_ClipModifiedCallback(); } window -e -height $gGameExporterWindowHeight[$tabIndex] gameExporterWindow; // Attach the export type form layout to the main form layout string $gameExporterSubCommonFormLayout = gameExp_GetPrefixedName("gameExporterSubCommonFormLayout"); formLayout -edit -attachControl $gameExporterExportTypeFormLayout "top" 0 $gameExporterSubCommonFormLayout -attachForm $gameExporterExportTypeFormLayout "left" 0 -attachForm $gameExporterExportTypeFormLayout "right" 0 -attachForm $gameExporterExportTypeFormLayout "bottom" 0 $gameExporterMainFormLayout; setParent ..; } // ---------------------------------------------------------------------------- // ---------------------------------------------------------------------------- // Create the File Format Components // ---------------------------------------------------------------------------- // ---------------------------------------------------------------------------- global proc gameExp_CreateFileFormatComponents() { global string $gGameFbxExporterCurrentNode; int $labelWidth = 60; if ( `about -uiLanguage` == "ja_JP" ) { $labelWidth += 30; } int $optionMenuWidth = 1; string $gameExporterFileTypeLabel = gameExp_GetPrefixedName("gameExporterFileTypeLabel"); text -label (getPluginResource( "gameFbxExporter", "kGameExporterFileTypeLabel" )) -width $labelWidth -align "left" -annotation (getPluginResource( "gameFbxExporter", "kGameExporterAnnFileTypeLabel" )) $gameExporterFileTypeLabel; string $gameExporterFileType = gameExp_GetPrefixedName("gameExporterFileType"); optionMenu -width $optionMenuWidth $gameExporterFileType; menuItem -label (getPluginResource( "gameFbxExporter", "kGameExporterFileTypeBinary" )); menuItem -label (getPluginResource( "gameFbxExporter", "kGameExporterFileTypeASCII" )); string $gameExporterFBXVersionLabel = gameExp_GetPrefixedName("gameExporterFBXVersionLabel"); text -label (getPluginResource( "gameFbxExporter", "kGameExporterFBXVersionLabel" )) -width $labelWidth -align "left" -annotation (getPluginResource( "gameFbxExporter", "kGameExporterAnnFBXVersionLabel" )) $gameExporterFBXVersionLabel; string $gameExporterFBXVersion = gameExp_GetPrefixedName("gameExporterFBXVersion"); // ask the FBX plug-in the list of supported versions&descriptions string $vlist[] = `FBXExportFileVersion -vl`; //vlist is in the form: "FBX201600" "FBX201400" "FBX201300" ... string $uivlist[] = `FBXExportFileVersion -uivl`; //uivlist is in the form: "FBX 2016/2017" "FBX 2014/2015" "FBX 2013" ... string $dlist[] = `FBXExportFileVersion -dl`; //dlist is in the form: "Compatible with Autodesk 2016 applications/FBX plug-ins" int $setAnn = size($vlist) == size($dlist); // both lists must have the same number of entries optionMenu -width $optionMenuWidth $gameExporterFBXVersion; for ($i = 0; $i < size($uivlist); $i++) { // make the menu item (with annotation if the right conditions are met) string $ann = ($setAnn==true) ? $dlist[$i] : ""; menuItem -label $uivlist[$i] -annotation $ann; } if( size($gGameFbxExporterCurrentNode) ) { // .fileType is 0-1 so increment by 1 for optionMenu. optionMenu -edit -select (`getAttr($gGameFbxExporterCurrentNode + ".fileType")` +1) -changeCommand ("setAttr(\"" + $gGameFbxExporterCurrentNode + ".fileType\") (`optionMenu -q -select " + $gameExporterFileType + "` -1)") $gameExporterFileType; // Compute which FBX version to select string $fileVersion = `getAttr($gGameFbxExporterCurrentNode + ".fileVersion")`; // Set default value if needed if ($fileVersion == "") { $fileVersion = gameExp_SetDefaultFileVersion(); } // get the index of $fileVersion in the fbxVersions list int $currentItem = stringArrayFind($fileVersion, 0, $vlist); if ($currentItem == -1) $currentItem = 0; // not found. Select first version (most recent one!) $currentItem += 1; // items in the menu are 1 based optionMenu -edit -select $currentItem $gameExporterFBXVersion; optionMenu -edit -changeCommand ("int $userFileVersion = `optionMenu -q -select " + $gameExporterFBXVersion + "` - 1; setAttr -type \"string\" \"" + $gGameFbxExporterCurrentNode + ".fileVersion\" `gameExp_GetFBXFileVersion($userFileVersion)`") $gameExporterFBXVersion; } } // ---------------------------------------------------------------------------- // ---------------------------------------------------------------------------- // Create the Advance Settings (Gear) button // ---------------------------------------------------------------------------- // ---------------------------------------------------------------------------- global proc gameExp_CreateAdvanceSettingsGearButton() { string $gameExporterAdvanceSettings = gameExp_GetPrefixedName("gameExporterAdvanceSettings"); string $advanceSettingsTitle = (getPluginResource( "gameFbxExporter", "kGameExporterAdvanceSettingsTitle" )); symbolButton -image "advancedSettings.png" -annotation (getPluginResource( "gameFbxExporter","kGameExporterAnnAdvanceSettings")) -command ("layoutDialog -title \"" + $advanceSettingsTitle + "\" -uiScript \"gameExp_CreateAdvanceSettingsUIComponents\" -parent gameExporterWindow;") $gameExporterAdvanceSettings; } // ---------------------------------------------------------------------------- // ---------------------------------------------------------------------------- // Create the Path UI Components // ---------------------------------------------------------------------------- // ---------------------------------------------------------------------------- global proc string gameExp_CreatePathUIComponents() { global string $gGameFbxExporterCurrentNode; string $form = `formLayout`; frameLayout -label (getPluginResource( "gameFbxExporter", "kGameExporterPath" )) -collapse 0 -collapsable 1 -width 10 gameExporterPath; string $subForm = `formLayout`; string $gameExporterViewInFBXReview = gameExp_GetPrefixedName("gameExporterViewInFBXReview"); int $offset = 5; if (`about -macOS`) { $offset = 0; } checkBoxGrp -columnWidth 1 190 -columnAttach 1 "right" $offset -label (getPluginResource( "gameFbxExporter", "kGameExporterViewInFBXReview" )) -annotation (getPluginResource( "gameFbxExporter","kGameExporterAnnViewInFBXReview")) $gameExporterViewInFBXReview; if(`about -linux64`) { // Not supported on linux checkBoxGrp -e -enable false $gameExporterViewInFBXReview; } text -label (getPluginResource( "gameFbxExporter", "kGameExporterPathLabel" )) gameExporterExportPathLabel; string $gameExporterExportPath = gameExp_GetPrefixedName("gameExporterExportPath"); textField -placeholderText (getPluginResource( "gameFbxExporter", "kGameExporterPlaceholderTextPath" )) -annotation (getPluginResource( "gameFbxExporter", "kGameExporterAnnPath" )) $gameExporterExportPath; string $gameExporterBrowserBtn = gameExp_GetPrefixedName("gameExporterBrowserBtn"); symbolButton -image "browseFolder.png" -annotation (getPluginResource( "gameFbxExporter","kGameExporterAnnBrowseDirectory")) -command "gameExp_BrowseFolder" $gameExporterBrowserBtn; string $gameExporterExportFilename = gameExp_GetPrefixedName("gameExporterExportFilename"); textField -annotation (getPluginResource( "gameFbxExporter", "kGameExporterAnnFilename" )) -cc "gameExp_CreateFilenamePreview" $gameExporterExportFilename; string $gameExporterExportFilenamePreview = ""; // Filename preview $gameExporterExportFilenamePreview = gameExp_GetPrefixedName("gameExporterExportFilenamePreview"); textField -noBackground true -enable false -editable false $gameExporterExportFilenamePreview; string $gameExporterExportBtn = gameExp_GetPrefixedName("gameExporterExportBtn"); button -label (getPluginResource( "gameFbxExporter", "kGameExporterExportMesh" )) -command "gameExp_DoExport" $gameExporterExportBtn; if(size($gGameFbxExporterCurrentNode)) { // -fileName flag will only work with a textField. connectControl -preventContextualMenu true -fileName $gameExporterExportPath ($gGameFbxExporterCurrentNode + ".exportPath"); connectControl -preventContextualMenu true $gameExporterExportFilename ($gGameFbxExporterCurrentNode + ".exportFilename"); connectControl -preventContextualMenu true -index 2 $gameExporterViewInFBXReview ($gGameFbxExporterCurrentNode + ".viewInFBXReview"); int $exportType = `getAttr($gGameFbxExporterCurrentNode + ".exportTypeIndex")`; int $splitType = `getAttr ($gGameFbxExporterCurrentNode + ".fileSplitType")`; string $placeholder = $splitType == 2 ? (getPluginResource( "gameFbxExporter", "kGameExporterPlaceholderClipFilePrefix" )) : (getPluginResource( "gameFbxExporter", "kGameExporterPlaceholderFileName" )); if ($exportType == 1) { // Model int $modelFileMode = `getAttr ($gGameFbxExporterCurrentNode + ".modelFileMode")`; $placeholder = $modelFileMode == 2 ? (getPluginResource( "gameFbxExporter", "kGameExporterPlaceholderModelFilePrefix" )) : (getPluginResource( "gameFbxExporter", "kGameExporterPlaceholderFileName" )); } textField -e -placeholderText $placeholder $gameExporterExportFilename; } string $anchor = $gameExporterExportPath; formLayout -edit -attachForm $gameExporterViewInFBXReview "top" 5 -attachForm $gameExporterViewInFBXReview "right" 10 -attachControl gameExporterExportPathLabel "top" 8 $gameExporterViewInFBXReview -attachForm gameExporterExportPathLabel "left" 12 -attachControl $gameExporterExportPath "top" 5 $gameExporterViewInFBXReview -attachControl $gameExporterExportPath "left" 3 gameExporterExportPathLabel -attachControl $gameExporterExportPath "right" 2 $gameExporterBrowserBtn -attachControl $gameExporterBrowserBtn "top" 5 $gameExporterViewInFBXReview -attachForm $gameExporterBrowserBtn "right" 5 -attachControl $gameExporterExportFilename "top" 3 $gameExporterExportPath -attachForm $gameExporterExportFilename "left" 11 -attachForm $gameExporterExportFilename "right" 11 $subForm; // Filename preview $anchor = $gameExporterExportFilenamePreview; formLayout -edit -attachControl $gameExporterExportFilenamePreview "top" 3 $gameExporterExportFilename -attachForm $gameExporterExportFilenamePreview "left" 11 -attachForm $gameExporterExportFilenamePreview "right" 11 $subForm; formLayout -edit -attachControl $gameExporterExportBtn "top" 5 $anchor -attachForm $gameExporterExportBtn "left" 12 -attachForm $gameExporterExportBtn "right" 12 $subForm; setParent ..; setParent ..; formLayout -edit -attachForm gameExporterPath "top" 0 -attachForm gameExporterPath "left" 0 -attachForm gameExporterPath "right" 0 -attachForm gameExporterPath "bottom" 0 $form; setParent ..; // generate the filename preview from the prefix/filename stored in the // gGameFbxExporterCurrentNode gameExp_CreateFilenamePreview(); return $form; } // ---------------------------------------------------------------------------- // ---------------------------------------------------------------------------- // Returns a unique name based on the name and a list of names to validate the // uniqueness of the name. // Ex: // aaa -> aaa01 // aaa090 -> aaa091 // aaa00099 -> aaa00100 // ---------------------------------------------------------------------------- // ---------------------------------------------------------------------------- global proc string gameExp_ProvideUniqueName(string $name, string $uniqueNameLst[]) { while(stringArrayCount($name, $uniqueNameLst)) { string $endsWithNumber = `match "[0-9]+$" $name`; if(size($endsWithNumber)) { int $nbZeros = 0; //string to int int $number = $endsWithNumber; int $stringSize = size($endsWithNumber); int $intToStringSizeBefore = size(string($number)); // Keep how many zeros we have lost from the string convertion to int Ex: "0010" -> ? 10 : 2 zeros // if($stringSize != $intToStringSizeBefore) { $nbZeros = ($stringSize - $intToStringSizeBefore); } $number++; int $intToStringSizeAfter = size(string($number)); if($nbZeros && ($intToStringSizeBefore != $intToStringSizeAfter)) { // If the incremented number is +1 digit than before, // remove one of the zero(s) to add. $nbZeros = $nbZeros - 1; } // Get the name without the ending digits $name = python("(\"" + $name + "\")[:-" + size($endsWithNumber) + "]"); // Add the zero(s) lost in the "string to int" conversion // Also if the incremented number has added one new digit // a zero will be removed. for( $i=0; $i < $nbZeros; $i++) { $name = ($name + "0"); } $name = ( $name + $number ); } else { $name = ($name + "01"); } } return $name; } // ---------------------------------------------------------------------------- // ---------------------------------------------------------------------------- // If a file already exists, ask the user if he wants to overwrite it. // ---------------------------------------------------------------------------- // ---------------------------------------------------------------------------- global proc int gameExp_OverwriteExistingFile(string $path) { if( `filetest -f $path` ) { string $msg = getPluginResource( "gameFbxExporter", "kGameExporterOverwriteMessage" ); string $ok = getPluginResource( "gameFbxExporter", "kGameExporterYesLabel" ); string $cancel = getPluginResource( "gameFbxExporter", "kGameExporterNoLabel" ); string $icon = "information"; string $file = basename($path, ""); $msg = `format -s ("\"" + $file + "\"") $msg`; string $overwrite = `confirmDialog -parent gameExporterWindow -title (getPluginResource( "gameFbxExporter", "kGameExporterReplaceFile" )) -message $msg -button $ok -button $cancel -icon $icon -defaultButton $cancel -cancelButton $cancel`; if( $overwrite == $cancel ) { return 0; } } return 1; } // ---------------------------------------------------------------------------- // ---------------------------------------------------------------------------- // If multiple files already exists, ask the user if he wants to overwrite it. // ---------------------------------------------------------------------------- // ---------------------------------------------------------------------------- global proc int gameExp_OverwriteExistingFiles(string $fileNameList[], int $overwriteListLimit) { string $fileList; int $nbFileOverwrite = 0; for ($i=0; $i < size($fileNameList) && $nbFileOverwrite < $overwriteListLimit; $i++) { string $path = $fileNameList[$i]; if( `filetest -f $path` ) { $nbFileOverwrite++; if($nbFileOverwrite != $overwriteListLimit) { $fileList = size($fileList) ? ($fileList + ", " + basename($path, "")) : basename($path, ""); } else { $fileList = $fileList + ", ..."; } } } if( size($fileList) ) { string $msg; if ( size($fileList) > 1 ) { $msg = getPluginResource( "gameFbxExporter", "kGameExporterOverwriteMultifileMessage" ); } else { $msg = getPluginResource( "gameFbxExporter", "kGameExporterOverwriteMessage" ); } string $ok = getPluginResource( "gameFbxExporter", "kGameExporterYesLabel" ); string $cancel = getPluginResource( "gameFbxExporter", "kGameExporterNoLabel" ); string $icon = "information"; $msg = `format -s ("\"" + $fileList + "\"") $msg`; string $overwrite = `confirmDialog -parent gameExporterWindow -title (getPluginResource( "gameFbxExporter", "kGameExporterReplaceFile" )) -message $msg -button $ok -button $cancel -icon $icon -defaultButton $cancel -cancelButton $cancel`; if( $overwrite == $cancel ) { return 0; } } return 1; } // ---------------------------------------------------------------------------- // ---------------------------------------------------------------------------- // Create the FilenamePreview string // This is the callback triggered by the file name field text changed and // terminated by either a TAB or ENTER keypress (also called when: // - selection changes // - animation clip name is changed // - animation clip active toggle changes state // - creating the Model & Animation clip UI // ---------------------------------------------------------------------------- // ---------------------------------------------------------------------------- global proc gameExp_CreateFilenamePreview() { global string $gGameFbxExporterCurrentNode; if ($gGameFbxExporterCurrentNode == "") return; string $fileOrPrefix = `getAttr($gGameFbxExporterCurrentNode + ".exportFilename")`; int $exportType = `getAttr($gGameFbxExporterCurrentNode + ".exportTypeIndex")`; int $splitType = `getAttr ($gGameFbxExporterCurrentNode + ".fileSplitType")`; int $singleFileOut = ($splitType == 1) ? true : false; string $filenames[]; if ($exportType == 1) { // Model export $modelFileMode = `getAttr ($gGameFbxExporterCurrentNode + ".modelFileMode")`; $singleFileOut = ($modelFileMode==1) ? true : false; string $roots[]; if (!$singleFileOut) { // we need to collect the root nodes only when the user wants // to export to multiple files. gameExp_GetRoots($roots); } // get all possible file names $filenames = gameExp_GenerateFilenameList($roots, $fileOrPrefix); } else { int $nbAnimClips = `getAttr -size ($gGameFbxExporterCurrentNode + ".animClips")`; string $file = `getAttr($gGameFbxExporterCurrentNode + ".exportFilename")`; string $fileNameTmp = `substitute ".fbx" $file ""`; string $name[]; float $start[], $end[]; $filenames = gameExp_GenerateClipFilenameList($nbAnimClips, $fileNameTmp, $name, $start, $end); } // Show the filename preview only if we have something to display string $preview = ""; int $showFilenamePreview = size($filenames) > 0; if ($showFilenamePreview) { // use the first entry in the list $preview = $filenames[0]; if (!$singleFileOut && size($filenames) > 1) { $preview += " ..."; } } string $gameExporterExportFilenamePreview = gameExp_GetPrefixedName("gameExporterExportFilenamePreview"); textField -edit -visible $showFilenamePreview $gameExporterExportFilenamePreview; textField -edit -text $preview $gameExporterExportFilenamePreview; } // ---------------------------------------------------------------------------- // ---------------------------------------------------------------------------- // Show a pop-up window message. // ---------------------------------------------------------------------------- // ---------------------------------------------------------------------------- global proc gameExp_ShowMessage(string $message, int $msgType) { // 0- None 1- information, 2- warning, 3- critical string $icon = $msgType < 2 ? ( $msgType ? "information" : "" ) : ($msgType == 2 ? "warning" : "critical"); confirmDialog -title (getPluginResource( "gameFbxExporter", "kGameExporterWindowTitle" )) -parent gameExporterWindow -message $message -icon $icon -button (getPluginResource( "gameFbxExporter", "kGameExporterOkLabel" )); }