/* * All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or * its licensors. * * For complete copyright and license terms please see the LICENSE at the root of this * distribution (the "License"). All use of this software is governed by the License, * or, if provided, by the license below or the license accompanying this file. Do not * remove or modify any license notices. This file is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * */ // List of the current animLayers known to the Utilities, this is // used to determine operations performed in the Maya main workflow and // keep the data backend synchronized with it. global string $g_animLayers[]; //! Forces a refresh of the Lumberyard Animation Manager and Lumberyard Animation Pane. global proc LumberyardUtilitiesUpdateAnimationUI() { if(`window -exists LUMBERYARDANIMATIONMANAGER_WINDOW`) { LumberyardAnimationManagerReadExports(); } if(`window -exists LUMBERYARDTOOL_MAIN_WINDOW`) { LumberyardAnimationPaneReadExports(); } } //! Generates a unique animation export name based on a requested name. /*! \param $requestedName The desired name that may be changed to guarantee uniqueness. */ global proc string LumberyardUtilitiesGetUniqueAnimationName(string $requestedName) { if ($requestedName == "") { $requestedName = "animationExport"; } return `LumberyardUtilitiesVerifyAnimationRequestName $requestedName ""`; } //! Verify if requested name is valid and return a proper name for the animation. /* \param $requestedName The desired name of the animation. \param $currentName The current name of the animation. */ global proc string LumberyardUtilitiesVerifyAnimationRequestName(string $requestedName, string $currentName) { return `LumberyardVerifySceneObjectRequestNameWithPrefix $requestedName $currentName "LUMBERYARD_ANIMATIONEXPORT_GROUP|"`; } /////////////////////////////////////////////////////////////////// // For manipulating layer data //! Returns the list of animLayers defined by Maya. /*! \note This will return the identical ordering to Maya, but only if displaying them newest animLayer first, which is the default view. It will not guarantee identical ordering for other Maya animLayer displays. */ global proc string[] LumberyardUtilitiesGetAnimLayers() { string $layers[]; if(`animLayer -query -exists "BaseAnimation"`) { $layers = `animLayer -query -children "BaseAnimation"`; $layers = `LumberyardUtilitiesReverseStringArray $layers`; } $layers[size($layers)] = "BaseAnimation"; return $layers; } //! This removes the specified animLayers from the active list for all animation exports. /*! \param $removeLayers The name of all animLayers that should be removed. */ proc LumberyardUtilitiesRemoveAnimLayers(string $removeLayers[]) { if(`objExists "LUMBERYARD_ANIMATIONEXPORT_GROUP"`) { string $exportNodes[] = `listRelatives -children "LUMBERYARD_ANIMATIONEXPORT_GROUP"`; for($exportNode in $exportNodes) { string $exportLayers[] = `LumberyardUtilitiesGetAnimationExportLayers $exportNode`; $exportLayers = `stringArrayRemove $removeLayers $exportLayers`; LumberyardUtilitiesSetAnimationExportLayers($exportNode, $exportLayers); LumberyardUtilitiesUpdateAnimationUI(); } } } //! This will update an old animLayer name to a new name for all animation exports' active animLayer list. /*! \param $oldName The name of the animLayer to replace. \param $newName The name that should be stored in its place. */ proc LumberyardUtilitiesRenameAnimLayer(string $oldName, string $newName) { if(`objExists "LUMBERYARD_ANIMATIONEXPORT_GROUP"`) { string $exportNodes[] = `listRelatives -children "LUMBERYARD_ANIMATIONEXPORT_GROUP"`; for($exportNode in $exportNodes) { string $exportLayers[] = `LumberyardUtilitiesGetAnimationExportLayers $exportNode`; int $index = `stringArrayFind $oldName 0 $exportLayers`; if($index >= 0) { $exportLayers[$index] = $newName; } LumberyardUtilitiesSetAnimationExportLayers($exportNode, $exportLayers); LumberyardUtilitiesUpdateAnimationUI(); } } } //! Callback which queries Maya animLayer state, and synchronizes the data backend with the current state. /*! \note This should be called whenever an animLayer is added, removed, renamed or deleted in Maya. If animLayer is manipulated by scripts, this should be called after any operations of these types. */ global proc LumberyardUtilitiesUpdateAnimationLayers() { global string $g_animLayers[]; string $layers[]; $layers = `ls -type "animLayer"`; if(size($g_animLayers) == size($layers)) { // A layer was renamed string $oldNames[]; string $newName; for($animLayer in $g_animLayers) { if(!`stringArrayContains $animLayer $layers`) { $oldNames[size($oldNames)] = $animLayer; } } if(size($oldNames) > 1) { print("Warning: Received multiple rename requests in a single operation, removing nodes instead\n"); LumberyardUtilitiesRemoveAnimLayers($oldNames); $g_animLayers = $layers; return; } if(size($oldNames) == 0) { // No renamed asset found return; } for($animLayer in $layers) { if(!`stringArrayContains $animLayer $g_animLayers`) { $newName = $animLayer; } } LumberyardUtilitiesRenameAnimLayer($oldNames[0], $newName); } else if(size($g_animLayers) > size($layers)) { // One or more layers were deleted if(`objExists "LUMBERYARD_ANIMATIONEXPORT_GROUP"`) { string $deletedLayers[]; for($animLayer in $g_animLayers) { if(!`stringArrayContains $animLayer $layers`) { // Deleted Layer $deletedLayers[size($deletedLayers)] = $animLayer; } } string $exportNodes[] = `listRelatives -children "LUMBERYARD_ANIMATIONEXPORT_GROUP"`; for($exportNode in $exportNodes) { LumberyardUtilitiesRemoveAnimLayers($deletedLayers); } } } // Store layer list for next AnimLayer operation $g_animLayers = $layers; } //! Utility function to create a command that will generate correct export behavior based on animLayer settings. /*! \param $exportLayerString The string attribute encoding animLayer selections for an animation export. \note The default behavior is to mute any layers not contained in the exportLayer selections during export. */ proc string LumberyardUtilitiesConvertAnimLayerStringToCommand(string $exportLayerString) { string $exportLayers[] = `stringToStringArray $exportLayerString ","`; string $validLayers[] = `LumberyardUtilitiesGetAnimLayers`; string $command = ""; for($i = 0; $i < size($validLayers); $i++) { if($validLayers[$i] != "BaseAnimation") { int $value = !`stringArrayContains $validLayers[$i] $exportLayers`; $command = $command + "setAttr " + $validLayers[$i] + ".mute " + $value + ";"; } } return $command; } //! Upgrades the old Crytek format for animLayer commands into the new Lumberyard format. /*! \param $animLayerCommand The animLayer command for an animation export encoded in Crytek format. */ proc string[] LumberyardUtilitiesUpgradeAnimLayerCommand(string $animLayerCommand) { string $animLayers[]; string $commands[]; int $numCommands = `tokenize $animLayerCommand ";" $commands`; string $elements[]; for($i = 0; $i < $numCommands; $i = $i + 2) { tokenize $commands[$i] " " $elements; // Validate for proper command formatting. if(size($elements) == 3) { int $value = (int)$elements[2]; if($value != 0) { tokenize $elements[1] "." $elements; if(size($elements) == 2) { $animLayers[size($animLayers)] = $elements[0]; } } } } return $animLayers; } //! Upgrades old Crytek into properly formatted Lumberyard animation export data. /*! \note The old Crytek format used a single monolithic string that was constantly built and tokenized to store this data. The data was moved into a node attributes to make it less computationally expensive, as well as easier to read and manipulate. Note that this is a destructive operation, the old Crytek data is removed to prevent detecting old data every time the file is opened. \todo We may consider backing up the Crytek data in a separate location so it can be restored if it is requested by customers, but we would prefer to only forward port data in the long term. */ global proc int LumberyardUtilitiesUpgradeAnimationData() { string $exportStringsRaw[] = `cryAnimGetRanges`; if(size($exportStringsRaw) >= 1 && $exportStringsRaw[0] != "") { string $upgradeChoice = `confirmDialog -title "Upgrade" -message "Detected old animation data. Do you wish to upgrade it to the new tool format? (This operation will remove the old data)" -button "Yes" -button "No" -defaultButton "Yes" -cancelButton "No" -dismissString "No"`; if($upgradeChoice == "Yes") { string $exportStringsRaw[] = `cryAnimGetRanges`; cryAnimRemoveAllAnimRanges(); for($exportStringRaw in $exportStringsRaw) { string $exportParameters[] = `python("mau.AMZN_DecodeAnimRangeString(\"" + $exportStringRaw + "\")")`; string $exportLayers[]; if(size($exportParameters) >= 6) { $exportLayers = `LumberyardUtilitiesUpgradeAnimLayerCommand $exportParameters[5]`; } LumberyardUtilitiesCreateAnimationExport($exportParameters[0], $exportParameters[1], $exportParameters[2], $exportParameters[3], $exportParameters[4], $exportLayers); } } else { return false; } } return true; } //! Creates the node to contain animation export data, and store requested values in the node /*! \param $startFrame The first frame to export for the animation \param $endFrame The last frame to export for the animation \param $exportName The name of the i_caf file to generate when exporting the animation \param $rootJoint The root joint to use when exporting the animation. Only joints below the root will be exported. \param $exportPath The absolute path to store the i_caf when exporting the animation. \param $exportLayers A list of the layers that should be active (not muted) when exporting the animation. */ global proc LumberyardUtilitiesCreateAnimationExport(int $startFrame, int $endFrame, string $exportName, string $rootJoint, string $exportPath, string $exportLayers[]) { if(!`objExists "LUMBERYARD_EXPORT_GROUP"`) { group -world -empty -name "LUMBERYARD_EXPORT_GROUP"; } if(!`objExists "LUMBERYARD_ANIMATIONEXPORT_GROUP"`) { group -empty -parent "LUMBERYARD_EXPORT_GROUP" -name "LUMBERYARD_ANIMATIONEXPORT_GROUP"; } else { string $parents[] = `listRelatives -parent "LUMBERYARD_ANIMATIONEXPORT_GROUP"`; if (!stringArrayContains("LUMBERYARD_EXPORT_GROUP", $parents)) { parent ("LUMBERYARD_ANIMATIONEXPORT_GROUP", "LUMBERYARD_EXPORT_GROUP"); } } string $newExportNode = `createNode "transform" -name AnimationExport -parent "LUMBERYARD_ANIMATIONEXPORT_GROUP"`; addAttr -longName "shouldExport" -attributeType bool $newExportNode; setAttr ($newExportNode+".shouldExport") 1; LumberyardUtilitiesSetAnimationStartFrame($newExportNode, $startFrame); LumberyardUtilitiesSetAnimationEndFrame($newExportNode, $endFrame); LumberyardUtilitiesSetAnimationExportName($newExportNode, $exportName); LumberyardUtilitiesSetAnimationRootJoint($newExportNode, $rootJoint); LumberyardUtilitiesSetAnimationExportPath($newExportNode, $exportPath); LumberyardUtilitiesSetAnimationExportLayers($newExportNode, $exportLayers); } //! Deletes an animation export and its data /*! \param $exportNode The name of the animation export node to delete */ global proc LumberyardUtilitiesDeleteAnimationExport(string $exportNode) { if(!`objExists ("LUMBERYARD_ANIMATIONEXPORT_GROUP|" + $exportNode)`) { return; } delete ("LUMBERYARD_ANIMATIONEXPORT_GROUP|" + $exportNode); LumberyardUtilitiesUpdateAnimationUI(); } //! Returns a list of all animation exports in the scene global proc string[] LumberyardUtilitiesGetAnimationExportNodes() { string $exportNodes[]; if(`objExists "LUMBERYARD_ANIMATIONEXPORT_GROUP"`) { $exportNodes = `listRelatives -children "LUMBERYARD_ANIMATIONEXPORT_GROUP"`; } return $exportNodes; } //! Returns true if the animation export node exists, and has all required attributes /*! \param $exportNode The name of the animation export node to validate */ global proc int LumberyardUtilitiesAnimationExportIsValid(string $exportNode) { string $fullname = "LUMBERYARD_ANIMATIONEXPORT_GROUP|"+$exportNode; if (!`objExists $fullname`) { return false; } if (!`attributeExists "startFrame" $fullname`) { return false; } if (!`attributeExists "endFrame" $fullname`) { return false; } if (!`attributeExists "exportName" $fullname`) { return false; } if (!`attributeExists "rootJoint" $fullname`) { return false; } if(!`attributeExists "exportPath" $fullname`) { return false; } return true; } //! Sets an integer attribute on an animation export node, creating it if needed /*! \param $exportNode The node to set the attribute on \param $attribute The name of the attribute to set \param $value The value to store in the attribute */ proc LumberyardUtilitiesSetAnimationIntAttr(string $exportNode, string $attribute, int $value) { if(!`attributeExists $attribute $exportNode`) { addAttr -longName $attribute -attributeType long $exportNode; } setAttr ("LUMBERYARD_ANIMATIONEXPORT_GROUP|" + $exportNode + "." + $attribute) $value; } //! Sets a string attribute on an animation export node, creating it if needed /*! \param $exportNode The node to set the attribute on \param $attribute The name of the attribute to set \param $value The value to store in the attribute */ proc LumberyardUtilitiesSetAnimationStringAttr(string $exportNode, string $attribute, string $value) { if(!`attributeExists $attribute $exportNode`) { addAttr -longName $attribute -dataType "string" $exportNode; } setAttr -type "string" ("LUMBERYARD_ANIMATIONEXPORT_GROUP|" + $exportNode + "." + $attribute) $value; } //! Gets the value of an animation export node attribute if it exists. If not, returns a default value. /*! \param $exportNode The animation export node to fetch the value for. \param $attribute The name of the attribute to query. \param $defaultValue The default value that will be returned if the attribute or node are not found. \note This always returns a string. The caller is responsible to cast the return value to the appropriate type. */ proc string LumberyardUtilitiesGetAnimationAttr(string $exportNode, string $attribute, string $defaultValue) { string $return = $defaultValue; if(`LumberyardUtilitiesAnimationExportIsValid $exportNode`) { $return = `getAttr ("LUMBERYARD_ANIMATIONEXPORT_GROUP|" + $exportNode + "." + $attribute) $exportNode`; } return $return; } //! Sets the start frame value for an animation export /*! \param $exportNode The name of the animation export node to set the start frame for \param $startFrame The first frame for the animation export. */ global proc LumberyardUtilitiesSetAnimationStartFrame(string $exportNode, int $startFrame) { LumberyardUtilitiesSetAnimationIntAttr($exportNode, "startFrame", $startFrame); } //! Gets the start frame value for an animation export /*! \param $exportNode The name of the animation export node to get the start frame for */ global proc int LumberyardUtilitiesGetStartFrame(string $exportNode) { string $value = `LumberyardUtilitiesGetAnimationAttr $exportNode "startFrame" "-1"`; int $intValue = (int)$value; return $intValue; } //! Sets the end frame value for an animation export /*! \param $exportNode The name of the animation export node to set the end frame for \param $endFrame The last frame for the animation export. */ global proc LumberyardUtilitiesSetAnimationEndFrame(string $exportNode, int $endFrame) { LumberyardUtilitiesSetAnimationIntAttr($exportNode, "endFrame", $endFrame); } //! Gets the end frame value for an animation export /*! \param $exportNode The name of the animation export node to get the end frame for */ global proc int LumberyardUtilitiesGetAnimationEndFrame(string $exportNode) { string $value = `LumberyardUtilitiesGetAnimationAttr $exportNode "endFrame" "-1"`; int $intValue = (int)$value; return $intValue; } //! Sets the export name value for an animation export /*! \param $exportNode The name of the animation export node to set the export name for \param $exportName The name of the i_caf to create for the animation export. */ global proc string LumberyardUtilitiesSetAnimationExportName(string $exportNode, string $exportName) { LumberyardUtilitiesSetAnimationStringAttr($exportNode, "exportName", $exportName); if(`window -exists LUMBERYARDTOOL_MAIN_WINDOW`) { LumberyardAnimationPaneReadExports(); } return $exportName; } //! Gets the export name value for an animation export /*! \param $exportNode The name of the animation export node to get the export name for */ global proc string LumberyardUtilitiesGetAnimationExportName(string $exportNode) { return `LumberyardUtilitiesGetAnimationAttr $exportNode "exportName" ""`; } //! Sets the root joint value for an animation export /*! \param $exportNode The name of the animation export node to set the root joint for \param $rootJoint The root joint for the animation export. Only joints below this will be exported. */ global proc LumberyardUtilitiesSetAnimationRootJoint(string $exportNode, string $rootJoint) { LumberyardUtilitiesSetAnimationStringAttr($exportNode, "rootJoint", $rootJoint); } //! Gets the root joint value for an animation export /*! \param $exportNode The name of the animation export node to get the root joint for */ global proc string LumberyardUtilitiesGetAnimationRootJoint(string $exportNode) { return `LumberyardUtilitiesGetAnimationAttr $exportNode "rootJoint" ""`; } //! Sets the export layers used for an animation export /*! \param $exportNode The name of the animation export node to set the export layers for. \param $exportLayers A list containing all animLayers that should be active when exporting the animation export. */ global proc LumberyardUtilitiesSetAnimationExportLayers(string $exportNode, string $exportLayers[]) { string $exportLayerString = `stringArrayToString $exportLayers ","`; LumberyardUtilitiesSetAnimationStringAttr($exportNode, "exportLayers", $exportLayerString); } //! Gets a list of the export layers used for an animation export /*! \param $exportNode The name of the animation export node to get the export layers for. */ global proc string[] LumberyardUtilitiesGetAnimationExportLayers(string $exportNode) { string $animLayerString = `LumberyardUtilitiesGetAnimationAttr $exportNode "exportLayers" ""`; string $animLayers[] = `stringToStringArray $animLayerString ","`; if(!`stringArrayContains "BaseAnimation" $animLayers`) { $animLayers[size($animLayers)] = "BaseAnimation"; } return $animLayers; } //! Sets the export path value for an animation export /*! \param $exportNode The name of the animation export node to set the export path for \param $exportPath The absolute export path used when generating the i_caf for the animation export. */ global proc string LumberyardUtilitiesSetAnimationExportPath(string $exportNode, string $exportPath) { $exportPath = `cryExportFixupPath $exportPath`; LumberyardUtilitiesSetAnimationStringAttr($exportNode, "exportPath", $exportPath); return $exportPath; } //! Gets the export path value for an animation export /*! \param $exportNode The name of the animation export node to get the export path for */ global proc string LumberyardUtilitiesGetAnimationExportPath(string $exportNode) { return `LumberyardUtilitiesGetAnimationAttr $exportNode "exportPath" ""`; } ////////////////////////////////////////////////////////////////////////// // Functions tied to buttons //! Sets the start and end frame for an animation export to match the Maya timeline /*! \param $exportName The name of the animation export node to snap to the Maya timeline. */ global proc LumberyardUtilitiesSnapAnimationToTimeline(string $exportNode) { if(!`LumberyardUtilitiesAnimationExportIsValid $exportNode`) { return; } int $startFrame = `playbackOptions -query -minTime`; int $endFrame = `playbackOptions -query -maxTime`; setAttr ($exportNode+".startFrame") $startFrame; setAttr ($exportNode+".endFrame") $endFrame; if(`window -exists LUMBERYARDANIMATIONMANAGER_WINDOW`) { LumberyardAnimationManagerReadExports(); } } //! Exports all animation exports that have the shouldExport attribute set to true. /*! \param $blockOnWarnings If not zero/false, this will keep Export Progress UI from blocking for user input for warnings. \note $blockOnWarnings is only intended for use for batch operations at this time. */ global proc LumberyardUtilitiesExportSelectedAnimations(int $blockOnWarnings) { if(!`objExists "LUMBERYARD_ANIMATIONEXPORT_GROUP"`) { return; } string $children[] = `listRelatives -children "LUMBERYARD_ANIMATIONEXPORT_GROUP"`; for($child in $children) { if(`LumberyardUtilitiesAnimationExportIsValid $child`) { string $fullname = "LUMBERYARD_ANIMATIONEXPORT_GROUP|"+$child; int $shouldExport = `getAttr ($fullname+".shouldExport")`; if($shouldExport != 0) { string $startFrame = `getAttr ($fullname+".startFrame")`; string $endFrame = `getAttr ($fullname+".endFrame")`; string $exportName = `getAttr ($fullname+".exportName")`; string $rootJoint = `getAttr ($fullname+".rootJoint")`; string $exportPath = `getAttr ($fullname+".exportPath")`; string $exportLayers = `getAttr ($fullname+".exportLayers")`; string $layerCommand = `LumberyardUtilitiesConvertAnimLayerStringToCommand $exportLayers`; cryIssueAnimationExportCommand($startFrame, $endFrame, $exportName, $rootJoint, $exportPath, $layerCommand, $blockOnWarnings, LumberyardExportGetAdditionalExportOptions()); } } } }