// =========================================================================== // 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. // =========================================================================== // // Procedure Name: // AEhlslShaderTemplate // // Description Name; // Creates the attribute editor controls for the hlsl shader node // // Input Value: // nodeName // // Output Value: // None // // // Procedure Name: // AEhlslShaderTemplate // //////////////////////////////////////////////////////////////////////// // "HLSL Shader" Layout // //////////////////////////////////////////////////////////////////////// // This procedure is invoked when necessary to construct the controls // for a shader. Generally, this is only when we are displaying a // hlslShader node for the first time. // global proc AEhlslShader_shaderNew( string $sNodeAttr ) { global int $gAEhlslShader_iLayout; // IN: AE instance id for callbacks // HLSL File setUITemplate -pst attributeEditorTemplate; rowLayout -nc 3; AEhwShader_fileNameControls( "shader", // attribute name "Shader File", // label "", // annotation "fx", // file classification "", // file filter "/renderData/shaders" ); // project directory setParent ..; separator -style none; // Clean up. Initialize the controls. setParent ..; setUITemplate -ppt; AEhlslShader_shaderReplace( $sNodeAttr ); } // AEhlslShader_shaderNew // This procedure is invoked to connect a given hlslShader node to the UI // controls. If the layout already exists, the Attribute Editor will // call this routine instead of AEhlslShader_shaderNew. // global proc AEhlslShader_shaderReplace( string $sNodeAttr ) { global int $gAEhlslShader_iLayout; // IN: AE instance id for callbacks string $sNodeName = `match "^[^.]*" $sNodeAttr`; string $sa[]; string $s; // HLSL file name connectControl -fileName tfFileName $sNodeAttr; } // AEhlslShader_shaderReplace //////////////////////////////////////////////////////////////////////// // "Technique" Controls // //////////////////////////////////////////////////////////////////////// // Setup the technique UI (probably for the first time) // global proc AEhlslShader_techniqueNew( string $sNodeAttr ) { global int $gAEhlslShader_iLayout; // IN: AE instance id for callbacks // Technique setUITemplate -pst attributeEditorTemplate; columnLayout -adj 1 hlslTechniqueLayout; setParent ..; separator -style none; // Clean up. Initialize the controls. setParent ..; setUITemplate -ppt; AEhlslShader_techniqueReplace( $sNodeAttr ); } // AEhlslShader_shaderNew // Move our technique UI over to the specified node/attr // global proc AEhlslShader_techniqueReplace( string $sNodeAttr ) { global int $gAEhlslShader_iLayout; // IN: AE instance id for callbacks AEhlslShader_techniqueLayout( $sNodeAttr ); // When "technique" attribute is changed update our technique list // Use evalDeferred to avoid trying to replace the scriptJob from inside a callback // from the scriptJob (as you can't/shouldn't try and replace a running script) string $sNodeName = `match "^[^.]*" $sNodeAttr`; scriptJob -parent rbgTechnique0 -replacePrevious -killWithScene -compressUndo 1 -attributeChange ( $sNodeName + ".technique" ) ( "evalDeferred( \"AEhlslShader_techniqueUpdate " + $gAEhlslShader_iLayout + "\")" ); scriptJob -parent hlslTechniqueLayout -replacePrevious -killWithScene -compressUndo 1 -attributeChange ( $sNodeName + ".techniques" ) ( "evalDeferred( \"AEhlslShader_techniqueLayout " + $sNodeAttr + "\")" ); } // AEhlslShader_techniqueReplace // Create "Technique" radio buttons // global proc AEhlslShader_techniqueLayout( string $sNodeAttr ) { string $sNodeName = `match "^[^.]*" $sNodeAttr`; // Get list of technique names defined in the current HLSL file. string $saTechniques[] = `getAttr ( $sNodeName + ".techniques" )`; int $nTechnique = size( $saTechniques ); if ( !$nTechnique ) { $saTechniques[0] = "None defined\t0"; $nTechnique = 1; } // Get list of existing controls. string $saControls[] = `layout -q -childArray hlslTechniqueLayout`; int $nControl = size( $saControls ); setParent hlslTechniqueLayout; setUITemplate -pst attributeEditorTemplate; // Delete any surplus controls, in LIFO order to avoid crashing Maya. while ( $nControl > $nTechnique ) deleteUI $saControls[ --$nControl ]; // Create or update a radio button per technique. string $sa[]; string $sCmd = "AEhlslShader_techniqueChoice " + $sNodeName + " "; string $sActiveTechnique = `getAttr ( $sNodeName + ".technique" )`; int $iTechnique; for ( $iTechnique = 0; $iTechnique < $nTechnique; ++$iTechnique ) { string $rbg = "rbgTechnique" + $iTechnique; if ( $iTechnique >= $nControl ) { if ( $iTechnique == 0 ) radioButtonGrp -numberOfRadioButtons 1 -label "Technique" $rbg; else radioButtonGrp -numberOfRadioButtons 1 -shareCollection rbgTechnique0 $rbg; } string $name = $saTechniques[ $iTechnique]; radioButtonGrp -e -label1 $name -on1 ( $sCmd + " \"" + $name + "\"" ) $rbg; if( $name == $sActiveTechnique ) { radioButtonGrp -e -select 1 $rbg; } } setParent ..; setUITemplate -ppt; } // AEhlslShader_techniqueReplace // Callback when user chooses a "technique" radio button // global proc AEhlslShader_techniqueChoice( string $sNodeName, string $sChoice ) { string $sCmd = "setAttr -type \"string\" " + $sNodeName + ".technique" + " \"" + $sChoice + "\""; print ( $sCmd + ";\n" ); evalDeferred $sCmd; // use evalDeferred so Maya will display // the setAttr command on undo/redo } // AEhlslShader_techniqueChoice // Callback when value of "technique" attribute changes // global proc AEhlslShader_techniqueUpdate( int $iLayout ) { string $sNodeName = AEhwShader_beginCallback( $iLayout ); if( size( $sNodeName ) > 0 ) { // Get new value and find its index in the list of techniques. string $sActiveTechnique = `getAttr ( $sNodeName + ".technique" )`; string $saTechniques[] = `hlslShader -listTechniques $sNodeName`; int $nTechnique = size( $saTechniques ); int $i; for ( $i = 0; $i < $nTechnique; ++$i ) if ( $sActiveTechnique == `match "^[^\t]*" $saTechniques[ $i ]` ) break; // Select corresponding button. radioButtonGrp -e -select 1 ( "rbgTechnique" + $i ); } } //////////////////////////////////////////////////////////////////////// // Description field // //////////////////////////////////////////////////////////////////////// // Create the diagnostics box // global proc AEhlslShader_descriptionNew( string $sNodeAttr ) { global int $gAEhlslShader_iLayout; // IN: AE instance id for callbacks textFieldGrp -l "Description" -editable 0 tfHLSLDescription; AEhlslShader_descriptionReplace( $sNodeAttr ); } // This procedure is invoked to connect a given hlslShader node to the UI // controls. If the layout already exists, the Attribute Editor will // call this routine instead of AEhlslShader_shaderNew. // global proc AEhlslShader_descriptionReplace( string $sNodeAttr ) { global int $gAEhlslShader_iLayout; // IN: AE instance id for callbacks string $description = `getAttr $sNodeAttr`; textFieldGrp -e -text $description -visible (size( $description) != 0) tfHLSLDescription; // Use evalDeferred to avoid trying to replace the scriptJob from inside a callback // from the scriptJob (as you can't/shouldn't try and replace a running script) scriptJob -parent tfHLSLDescription -replacePrevious -killWithScene -runOnce 1 -compressUndo 1 -attributeChange ( $sNodeAttr ) ( "evalDeferred( \"AEhlslShader_descriptionReplace " + $sNodeAttr + "\")" ); } //////////////////////////////////////////////////////////////////////// // Diagnostics field // //////////////////////////////////////////////////////////////////////// // Create the diagnostics box // global proc AEhlslShader_diagnosticsNew( string $sNodeAttr ) { global int $gAEhlslShader_iLayout; // IN: AE instance id for callbacks scrollField -height 100 -editable 0 tfHLSLDiagnostics; AEhlslShader_diagnosticsReplace( $sNodeAttr ); } // This procedure is invoked to connect a given hlslShader node to the UI // controls. If the layout already exists, the Attribute Editor will // call this routine instead of AEhlslShader_shaderNew. // global proc AEhlslShader_diagnosticsReplace( string $sNodeAttr ) { global int $gAEhlslShader_iLayout; // IN: AE instance id for callbacks scrollField -e -text `getAttr $sNodeAttr` tfHLSLDiagnostics; // Use evalDeferred to avoid trying to replace the scriptJob from inside a callback // from the scriptJob (as you can't/shouldn't try and replace a running script) scriptJob -parent tfHLSLDiagnostics -replacePrevious -killWithScene -runOnce 1 -compressUndo 1 -attributeChange ( $sNodeAttr ) ( "evalDeferred( \"AEhlslShader_diagnosticsReplace " + $sNodeAttr + "\")" ); } //////////////////////////////////////////////////////////////////////// // UVLinks Support // //////////////////////////////////////////////////////////////////////// // This procedure is invoked by the generic AEhwShaderTemplate.mel. // The procedure needs to be of the form ("AE" + ($nodeType) + "_uvLinks"). // The function signature should be as below: // // global proc string[] AEnodeType_uvLinks( string $nodeName, string $paramName ) // global proc string[] AEhlslShader_uvLinks( string $nodeName, string $paramName ) { string $uvLinks[] = `hlslShader -uvl $paramName $nodeName`; return $uvLinks; } //////////////////////////////////////////////////////////////////////// // Main "HLSL Shader" Template // //////////////////////////////////////////////////////////////////////// global int $hlslShaderTemplateInitialised = 0; global proc AEhlslShaderTemplate ( string $node ) { global int $hlslShaderTemplateInitialised; if( $hlslShaderTemplateInitialised == 0) { source "AEhwShaderTemplate.mel"; $hlslShaderTemplateInitialised = 1; } AEhwShaderTemplateHeader( $node); // Shader Data editorTemplate -beginLayout (uiRes("m_AEhlslShaderTemplate.kShader")) -collapse false; editorTemplate -callCustom AEhlslShader_shaderNew AEhlslShader_shaderReplace shader; editorTemplate -callCustom AEhlslShader_techniqueNew AEhlslShader_techniqueReplace techniques; editorTemplate -callCustom AEhlslShader_descriptionNew AEhlslShader_descriptionReplace description; editorTemplate -endLayout; AEhwShaderTemplateParameters( $node); editorTemplate -beginLayout (uiRes("m_AEhlslShaderTemplate.kDiagnostics")) -collapse true; editorTemplate -callCustom AEhlslShader_diagnosticsNew AEhlslShader_diagnosticsReplace diagnostics; editorTemplate -endLayout; AEhwShaderTemplateFooter( $node); }