// Copyright (C) 1997-2004 Alias Systems Corp. // // The information in this file is provided for the exclusive use of the // licensees of Alias. Such users have the right to use, modify, // and incorporate this code into other products for purposes authorized // by the Alias license agreement, without fee. // // ALIAS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, // INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO // EVENT SHALL ALIAS BE LIABLE FOR ANY SPECIAL, INDIRECT OR // CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, // DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER // TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR // PERFORMANCE OF THIS SOFTWARE. // // Alias Script File // // Creation Date: May 25, 1998 // // Procedure Name: // AEhardwareTextureTemplate // // Description: // Procedure to generate template hardware texture controls. // // Input Arguments: // nodeName is the material node name. (currently unused) // attrTokens contains the space deliminated material attribute names. // // Return Value: // None. // proc string getPlugNode( string $plug ) { string $buffer[]; tokenize($plug, ".", $buffer); return size($buffer) > 0 ? $buffer[0] : ""; } proc string getPlugAttr( string $plug ) { string $buffer[]; tokenize($plug, ".", $buffer); return size($buffer) > 1 ? $buffer[size($buffer) - 1] : ""; } // Takes a material plug as argument (say, "phong1.message") // and return an appropriate channelMenu name (eg: "phong_channelMenu") // proc string getChannelMenuNameFromMaterialPlug ( string $materialPlug ) { string $materialType = `nodeType $materialPlug`; if ($materialType == "") { error("getChannelMenuNameFromMaterialPlug(): not a valid materialPlug."); return ""; } return ($materialType+"_channelMenu"); } // Takes a material plug as argument (say, "phong1.message") // and return an appropriate channelMenu name (eg: "phong_qualityMenu") // proc string getQualityMenuNameFromMaterialPlug ( string $materialPlug ) { string $materialType = `nodeType $materialPlug`; if ($materialType == "") { error("getQualityMenuNameFromMaterialPlug(): not a valid materialPlug."); return ""; } return ($materialType+"_qualityMenu"); } proc string getFilterMenuNameFromMaterialPlug ( string $materialPlug ) { string $materialType = `nodeType $materialPlug`; if ($materialType == "") { error("getFilterMenuNameFromMaterialPlug(): not a valid materialPlug."); return ""; } return ($materialType+"_filterMenu"); } // Takes a material plug as argument (say, "phong1.message") // and return an appropriate filterMenu name (eg: "phong_mimapMenu") // proc string getMaterialInfo( string $messagePlug ) { string $materialName[] = `ls $messagePlug`; if ($materialName[0] == "") { // When the user changes the shader type in the attribute // editor, multiple scriptjobs could be assigned to the same // materialInfoNode, but only one of them would relate to the // new shader. Older scriptjobs should exit silently. return ""; } string $connections[] = `listConnections $messagePlug`; for ($item in $connections) if (`objectType $item` == "materialInfo") return $item; return ""; } proc disconnectInfoTexture( string $info ) { // We need to break all connection because we want to ensure the // texture being displayed has a multi index of zero. // // Note: the connections are broken from back to front because // breaking a connection at the end of the multi will not affect // the connections at the start of the multi. string $connections[]; // We need to specify shape because fluids textures are shape nodes // as well as being textures. $connections = `listConnections -connections true -shapes true ($info+".texture")`; for ($i = size($connections); $i > 0; $i -= 2) disconnectAttr ($connections[$i-1]+".message") $connections[$i-2]; } proc string getMaterialPlugFromTexture(string $texturePlug, string $material) // // Description: // Procedure to return the plug on the specified material which is // connected to texturePlug. If there is a bump node between, it will // be by passed to return the correct plug. // // Returns: // The returned plug will be something like "lambert1.color". // { string $materialPlug = ""; string $connections[] = `listConnections -source false -destination true -plugs true $texturePlug`; for ($item in $connections) { string $node = getPlugNode($item); string $type = `objectType $node`; if ($type == "bump2d" || $type == "bump3d") { // The node connected to the output is a bump, we want to // skip over this node and determine the material // attribute connected to the bump. string $bump = $node; string $buffer[] = `listConnections -plugs true -source false -destination true ($bump+".outNormal")`; if (size($buffer) < 1) continue; $item = $buffer[0]; } if (getPlugNode($item) == $material) { $materialPlug = $item; break; } } return $materialPlug; } proc string getTexturePlugFromMaterial(string $materialPlug) // // Description: // Procedure to return the plug on a texture which is connected to // materialPlug. If there is a bump node between, it will be by passed // to return the correct plug. // // Returns: // The returned plug will be something like "file1.outColor". // { string $texturePlug = ""; string $connections[] = `listConnections -source true -destination false -plugs true $materialPlug`; // If there is a bump connected to this channel, skip over it // to get the actual texture. if (size($connections) > 0) { string $node = getPlugNode($connections[0]); string $type = `objectType $node`; if ($type == "bump2d" || $type == "bump3d") { string $bump = $node; $connections = `listConnections -source true -destination false -plugs true ($bump+".bumpValue")`; } } if (size($connections) > 0) $texturePlug = $connections[0]; return $texturePlug; } proc updateChannelMenu( string $attrTokens, string $messagePlug) { string $connections[]; // Make sure we have at least a materialInfo and material. // string $material = getPlugNode($messagePlug); string $info = getMaterialInfo($messagePlug); if ($info == "") return; string $channelMenuName = getChannelMenuNameFromMaterialPlug($messagePlug); // Get the texture currently used for hardware shading. // // This will return a value like "file1.outColor". // string $texturePlug = `getAttr ($info+".texturePlug")`; if ($texturePlug == "") { // There is no texture, set the channel menu to none. optionMenuGrp -e -select 1 -annotation "" $channelMenuName; return; } else if ($texturePlug == ($material+".outColor")) { // The connection is set to display all textures // (ie: bake the whole shader into one texture) // return; } // Get the material plug connected to the texture. // // This will return a value like "lambert1.color". // string $materialPlug = getMaterialPlugFromTexture($texturePlug, $material); if ($materialPlug == "") { // There is no material, set the channel menu to none. optionMenuGrp -e -select 1 -annotation "" $channelMenuName; return; } // Figure out which channel the menu is currently displaying and // if we are already displaying the right item return. // // Querying the annotation will return a plug like "lambert1.color". // string $currentChannelPlug = `optionMenuGrp -q -annotation $channelMenuName`; if ($currentChannelPlug == $materialPlug) return; // Determine the correct item to select in the channel menu based // on the material attribute // int $selectItem = 1; string $annotateItem = ""; string $materialAttr = getPlugAttr($materialPlug); if ($materialAttr != "") { string $channelAttrs[]; tokenize($attrTokens, " ", $channelAttrs); for ($index = 0 ; $index < size($channelAttrs); $index += 1) { // We need to also check the extensions _Color and _FloatValue which // correspond to ramp attribute child parameter extensions. if ($channelAttrs[$index] == $materialAttr || ($channelAttrs[$index] + "_Color") == $materialAttr || ($channelAttrs[$index] + "_FloatValue") == $materialAttr) { $selectItem = $index + 2; $annotateItem = $materialPlug; break; } } } optionMenuGrp -e -select $selectItem -annotation $annotateItem $channelMenuName; } proc updateFilterMenu( string $attrTokens, string $messagePlug) { string $connections[]; // Make sure we have at least a materialInfo and material. // string $material = getPlugNode($messagePlug); string $info = getMaterialInfo($messagePlug); if ($info == "") return; string $filterMenuName = getFilterMenuNameFromMaterialPlug($messagePlug); // Get the texture currently used for hardware shading. // // This will return a value like "file1.outColor". // string $filterPlug = `getAttr ($info+".textureFilter")`; if ($filterPlug == "") { // There is no filter texture, set the channel menu to none. optionMenuGrp -e -select 1 -annotation "" $filterMenuName; return; } int $filterValue = `getAttr ($info+".textureFilter")`; if ($filterValue >= 0) optionMenuGrp -e -select ($filterValue) $filterMenuName; } proc updateQualityMenu( string $attrTokens, string $messagePlug ) { string $info = getMaterialInfo($messagePlug); if ($info == "") return; string $qualityMenuName = getQualityMenuNameFromMaterialPlug($messagePlug); string $connections[] = `listConnections ($info+".texture[0]")`; int $hasTexture = (size($connections) != 0); if ($hasTexture) { if (size($connections) == 0) return; string $texture = $connections[0]; int $index = 1; // default string $buffer[] = `listAttr -string resolution $texture`; // Does the texture have a resolution attribute ? if (size($buffer) != 0) { $index = 2; // low int $resolution = `getAttr ($texture+".resolution")`; if ($resolution >= 4096) $index = 11; // XXXL else if ($resolution >= 3072) $index = 10; // XXL else if ($resolution >= 2048) $index = 9; // XL else if ($resolution >= 1024) $index = 8; // Large else if ($resolution >= 800) $index = 7; // 800 else if ($resolution >= 512) $index = 6; // 512 else if ($resolution >= 256) $index = 5; // higher else if ($resolution >= 128) $index = 4; // high else if ($resolution >= 64) $index = 3; // medium } optionMenuGrp -e -enable true -select $index $qualityMenuName; } else { optionMenuGrp -e -enable false $qualityMenuName; } } // // Procedure Name: // AEhardwareTextureChangedCB // // Description: // Callback which is invoked when the materialInfo texture // attribute changes. This procedure will update the channel and // quality menus. // // Input Arguments: // attrTokens contains the space deliminated material attribute names. // messagePlug is the material message plug. // // Return Value: // None. // global proc AEhardwareTextureChangedCB( string $attrTokens, string $messagePlug) { updateChannelMenu($attrTokens, $messagePlug); updateQualityMenu($attrTokens, $messagePlug); updateFilterMenu($attrTokens, $messagePlug); } // // Procedure Name: // AEhardwareTextureMaterialChangedCB // // Description: // Callback to be invoked when any channel attributes on the // material are changed. As new connections are made and broken // to the material; the menu items in the channel control will // be enabled/disabled. Also, if a texture we are currently // displaying is disconnected we update the materialInfo to // display "None". // // Input Arguments: // menuItem, name of the menu corresponding to this channel // channelPlug, material plug which changed (ie. "lambert1.color") // messagePlug, message plug on the material (ie. "lambert1.message") // // Return Value: // None. // global proc AEhardwareTextureMaterialChangedCB( string $menuItem, string $channelPlug, string $messagePlug ) { string $connections[] = `listConnections -plugs true $channelPlug`; int $hasConnections = (size($connections) != 0); menuItem -e -enable $hasConnections $menuItem; string $info = getMaterialInfo($messagePlug); if ($info == "") return; string $channelMenuName = getChannelMenuNameFromMaterialPlug($messagePlug); // Are we currently displaying this channel ? // string $materialPlug = `optionMenuGrp -q -annotation $channelMenuName`; if ($materialPlug == $channelPlug) { string $texturePlug = getTexturePlugFromMaterial($materialPlug); // Was the connection broken ? if ($texturePlug == "") { disconnectInfoTexture($info); // There is no texture, set the channel menu to none. optionMenuGrp -e -select 1 -annotation "" $channelMenuName; } } } // // Procedure Name: // AEhardwareTextureChannelCB // // Description: // The user has updated the channel menu. This procedure will modify // materialInfo texture connection and the quality menu. // // Input Arguments: // attrTokens contains the space deliminated material attribute names. // messagePlug is the material message plug. // // Return Value: // None. // global proc AEhardwareTextureChannelCB( string $attrTokens, string $messagePlug ) { // Get the material info node. string $info = getMaterialInfo($messagePlug); if ($info == "") return; string $channelMenuName = getChannelMenuNameFromMaterialPlug($messagePlug); // Disconnect the current texture from materialInfo // disconnectInfoTexture($info); // Get the channel to now display. // int $index = `optionMenuGrp -q -select $channelMenuName`; if ($index > 1) { string $material = getPlugNode($messagePlug); string $channelAttrs[]; tokenize($attrTokens, " ", $channelAttrs); string $attr = $channelAttrs[$index - 2]; // If the attribute is not found in the provided tokens, // assume that it is set to 'Combined'. (bake the whole shader // as if it was a texture) // if ($attr == "") { // In order to display all textures at once, we need to // hook up the materialInfo node in a non-standard way: // the "texture[0]" attribute is set to the shader (as opposed // to a standard texture), and the texturePlug is set // to the outColor of the shader. // connectAttr -f ($material+".message") ($info+".texture[0]"); } else { string $materialPlug = ($material+"."+$attr); string $texturePlug = getTexturePlugFromMaterial($materialPlug); // Is a texture connected on this channel ? // if ($texturePlug != "") { // Connect up the new texture to materialInfo. // string $node = getPlugNode($texturePlug); if (size(`listConnections $node`) > 1) { // It may be ambiguous for materialInfo to figure out which // channel to display (for example, if a file texture is // hooked up to both color and bump on a material). We // make a connection to the "textureChannel" to specify // which plug should be used. // connectAttr $texturePlug ($info+".textureChannel"); } // Now let materialInfo do its thing // connectAttr ($node+".message") ($info+".texture[0]"); } } updateQualityMenu( $attrTokens, $messagePlug ); } } // // Procedure Name: // AEhardwareMimapChannelCB // // Description: // The user has updated the channel menu. This procedure will modify // materialInfo texture connection and the quality menu. // // Input Arguments: // attrTokens contains the space deliminated material attribute names. // messagePlug is the material message plug. // // Return Value: // None. // global proc AEhardwareTextureFilterCB( string $attrTokens, string $messagePlug ) { // Get the material info node. string $info = getMaterialInfo($messagePlug); if ($info == "") return; string $filterMenuName = getFilterMenuNameFromMaterialPlug($messagePlug); int $index = `optionMenuGrp -q -select $filterMenuName`; setAttr ($info + ".textureFilter") ($index ); updateFilterMenu( $attrTokens, $messagePlug ); refresh -force; } // // Procedure Name: // AEhardwareTextureQualityCB // // Description: // The user has updated the quality menu. Update the resolution // attribute on the texture. // // Input Arguments: // attrTokens contains the space deliminated material attribute names. // messagePlug is the material message plug. // // Return Value: // None. // global proc AEhardwareTextureQualityCB( string $attrTokens, string $messagePlug ) { // Get the material info node. string $info = getMaterialInfo($messagePlug); if ($info == "") return; string $qualityMenuName = getQualityMenuNameFromMaterialPlug($messagePlug); // Get the texture connected to the material info // string $connections[] = `listConnections ($info+".texture[0]")`; if (size($connections) == 0) return; string $texture = $connections[0]; // Get the user setable quality // int $index = `optionMenuGrp -q -select $qualityMenuName`; string $buffer[] = `listAttr -string resolution $texture`; int $hasResolutionAttr = (size($buffer) != 0); if ($index == 1) { // default // Delete the resolution attribute if it already exists. // if ($hasResolutionAttr) { deleteAttr -at resolution $texture; // Generate a refresh disconnectInfoTexture($info); connectAttr ($texture+".message") ($info+".texture[0]"); } } else { // Create a resolution attribute if one doesn't exist // if (!$hasResolutionAttr) { addAttr -ln resolution -at long -dv 32 $texture; } // Set the resolution attribute on the texture depending on // the quality the user specified. // switch ($index) { case 2: // low setAttr ($texture+".resolution") 32; break; case 3: // medium setAttr ($texture+".resolution") 64; break; case 4: // high setAttr ($texture+".resolution") 128; break; case 5: // higher setAttr ($texture+".resolution") 256; break; case 6: // 512 setAttr ($texture+".resolution") 512; break; case 7: // 800 setAttr ($texture+".resolution") 800; break; case 8: // Large setAttr ($texture+".resolution") 1024; break; case 9: // XL setAttr ($texture+".resolution") 2048; break; case 10: // XXL setAttr ($texture+".resolution") 3072; break; case 11: // XXXL setAttr ($texture+".resolution") 4096; break; } } } // // Procedure Name: // AEhardwareTextureNewCB // // Description: // Callback to create the hardware texture controls. // // Input Arguments: // attrTokens contains the space deliminated material attribute names. // messagePlug is the material message plug. // // Return Value: // None. // global proc AEhardwareTextureNew( string $attrTokens, string $messagePlug ) { $channelMenuName = getChannelMenuNameFromMaterialPlug($messagePlug); $qualityMenuName = getQualityMenuNameFromMaterialPlug($messagePlug); $filterMenuName = getFilterMenuNameFromMaterialPlug($messagePlug); string $channelAttrs[]; tokenize($attrTokens, " ", $channelAttrs); columnLayout -adj true layout; optionMenuGrp -label "Textured channel" $channelMenuName; menuItem -label "None"; for ($item in $channelAttrs) { // The name normalCamera is not well understood by the // user so we will name this menu item bump. if ($item == "normalCamera") menuItem -label "Bump Map"; else menuItem -label (interToUI($item)); } menuItem -label "Combined Textures"; setParent ..; optionMenuGrp -label "Texture resolution" $qualityMenuName; menuItem -label "Default"; menuItem -label "Low (32x32)"; menuItem -label "Medium (64x64)"; menuItem -label "High (128x128)"; menuItem -label "Higher (256x256)"; menuItem -label "512 (512x512)"; menuItem -label "800 (800x800)"; menuItem -label "Large (1024x1024)"; menuItem -label "XL (2048x2048)"; menuItem -label "XXL (3072x3072)"; menuItem -label "XXXL (4096x4096)"; setParent ..; optionMenuGrp -label "Texture Filter" $filterMenuName; menuItem -label "Use Global Settings"; menuItem -label "Nearest (Unfiltered)"; menuItem -label "Bilinear"; menuItem -label "Mipmap Nearest"; menuItem -label "Mipmap Linear"; menuItem -label "Mipmap Bilinear"; menuItem -label "MipMap Trilinear"; setParent ..; setParent ..; AEhardwareTextureReplace($attrTokens, $messagePlug); } // // Procedure Name: // AEhardwareTextureReplaceCB // // Description: // Callback to initialize and install callbacks for the hardware // texture controls. // // Input Arguments: // attrTokens contains the space deliminated material attribute names. // messagePlug is the material message plug. // // Return Value: // None. // global proc AEhardwareTextureReplace( string $attrTokens, string $messagePlug ) { $channelMenuName = getChannelMenuNameFromMaterialPlug($messagePlug); $qualityMenuName = getQualityMenuNameFromMaterialPlug($messagePlug); $filterMenuName = getFilterMenuNameFromMaterialPlug($messagePlug); string $info = getMaterialInfo($messagePlug); int $hasMaterialInfo = ($info != ""); int $hasTexture = ($info != ""); if ($info != "") { string $connections[] = `listConnections ($info+".texture[0]")`; $hasTexture = (size($connections) > 0); scriptJob -parent layout -replacePrevious -disregardIndex -attributeChange ($info+".texture[0]") ("AEhardwareTextureChangedCB \""+$attrTokens+"\" "+$messagePlug); } // Set up some script jobs so we can detect when the user makes a // new connection to our channel attributes. // string $material = getPlugNode($messagePlug); if ($material != "") { string $channelAttrs[]; tokenize($attrTokens, " ", $channelAttrs); string $channelItems[] = `optionMenuGrp -q -itemListShort $channelMenuName`; for ($i = 0; $i < size($channelAttrs); $i += 1) { string $channelPlug = $material+"."+$channelAttrs[$i]; string $menuItem = $channelItems[$i+1]; scriptJob -parent $channelItems[$i+1] -replacePrevious -attributeChange $channelPlug ("AEhardwareTextureMaterialChangedCB "+$menuItem+" "+ $channelPlug+" "+$messagePlug); AEhardwareTextureMaterialChangedCB( $menuItem, $channelPlug, $messagePlug); } } optionMenuGrp -e -enable $hasMaterialInfo -cc ("AEhardwareTextureChannelCB \""+$attrTokens+"\" "+$messagePlug) $channelMenuName; optionMenuGrp -e -enable $hasTexture -cc ("AEhardwareTextureQualityCB \""+$attrTokens+"\" "+$messagePlug) $qualityMenuName; optionMenuGrp -e -enable $hasMaterialInfo -cc ("AEhardwareTextureFilterCB \""+$attrTokens+"\" "+$messagePlug) $filterMenuName; updateChannelMenu($attrTokens, $messagePlug); updateFilterMenu($attrTokens, $messagePlug); updateQualityMenu($attrTokens, $messagePlug); } // // Procedure Name: // AEhardwareTextureTemplate // // Description: // Procedure to generate template hardware texture controls. // // Input Arguments: // nodeName is the material node name. (currently unused) // attrTokens contains the space deliminated material attribute names. // // Return Value: // None. // global proc AEhardwareTextureTemplate( string $nodeName, string $attrTokens ) { editorTemplate -callCustom ("AEhardwareTextureNew \""+$attrTokens+"\"") ("AEhardwareTextureReplace \""+$attrTokens+"\"") "message"; editorTemplate -addControl "materialAlphaGain"; }