// =========================================================================== // 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. // =========================================================================== global int $gBdeNumUdAttrsUsed = 5; global int $gBdeBinaryMode = 0; global int $gBdeDiscreteValueMode = 1; global int $gBdeDiscreteRangeMode = 2; global int $gBdeHexSetMode = 3; global int $gBdeHesNotSetMode = 4; global int $gBdeHesEqualMode = 5; global int $gBdeContinuousMode = 6; global int $gBdeAsColorMode = 7; global string $gBdeDiscreteValName; $gBdeDiscreteValName = (uiRes("m_blindDataEditor.kDiscreteValGlobal")); global string $gBdeDiscreteRangeName; $gBdeDiscreteRangeName = (uiRes("m_blindDataEditor.kDiscreteRangeVal")); global string $gBdeHexValName; $gBdeHexValName = (uiRes("m_blindDataEditor.kHexGlobal")); global string $gBdeContinuousName; $gBdeContinuousName = (uiRes("m_blindDataEditor.kContinuousGlobal")); global string $gBdeAsColorName; $gBdeAsColorName = (uiRes("m_blindDataEditor.kAsColorGlobal")); global string $gBdeTPresetLayout; global string $gBdeQueryColorLayout; global int $gBdeVSSJ = -1; // For debugging purposes proc printCol( float $col[] ) { string $printString = (uiRes("m_blindDataEditor.kColorIs")); print( `format -s $col[0] -s $col[1] -s $col[2] $printString` ); } // Math utils proc int round( float $val ) { float $floor = floor( $val ); if ( $val - $floor < .5 ) return $floor; else return ( $floor + 1 ); } proc int power( int $x, int $y ) { int $newVal = 1; for ( $i = 0; $i < $y; $i++ ) { $newVal *= $x; } return $newVal; } // A bunch of utils to convert a 'hex string' to an int and back // If user's working with hex data they don't want to see the // int equivalent, but mel doesn't have any support for hex representations // of data, so we do it internally // This one's a utility function for the others proc int getHexInt( string $char ) { if ( $char == "A" || $char == "a" ) return 10; else if ( $char == "B" || $char == "b" ) return 11; else if ( $char == "C" || $char == "c" ) return 12; else if ( $char == "D" || $char == "d" ) return 13; else if ( $char == "E" || $char == "e" ) return 14; else if ( $char == "F" || $char == "f" ) return 15; else { int $val = $char; return $val; } } // Another utility function // gets the hex char for a single digit (i.e. <= 15) proc string getHexChar( int $val ) { if ( $val > 15 || $val < 0 ) return "x"; if ( $val < 10 ) { string $ret = $val; return $ret; } switch ( $val ) { case 10: return "A"; case 11: return "B"; case 12: return "C"; case 13: return "D"; case 14: return "E"; case 15: return "F"; default: return "x"; } } // This func gets the char from the string at the specified index proc string getChar( string $str, int $index ) { if ( size( $str ) < $index || 0 >= $index ) return ""; string $ret = `substring $str $index $index`; return $ret; } proc int isHexString( string $str ) { string $sub = `substring $str 1 2`; if ( $sub == "0x" || $sub == "0X" ) return 1; else return 0; } // Takes a hex string and returns an int // This func does no checking on whether the given // string is the right format or not, so care should be taken when // using it. proc int hexStringToInt( string $hex ) { int $size = size( $hex ); string $char; int $value = 0; int $newVal; int $power; for ( $i = $size; $i > 0; --$i ) { $char = getChar( $hex, $i ); if ( $char == "x" || $char == "X" || $char == "" ) break; $power = $size - $i; $newVal = getHexInt( $char ); $newVal = $newVal * (power( 16, $power ) ); $value += $newVal; } return $value; } proc int orInt( int $first, int $second ) { int $newVal = $first + $second; if ( $newVal > 15 ) $newVal = 15; return $newVal; } // Does a ( $first | $second ), and assumes that the strings // are truly hex strings proc string orHexString( string $first, string $second ) { float $sizeF = `size $first`; float $sizeS = `size $second`; int $maxSize = `max $sizeF $sizeS` - 3; int $fIndex = $sizeF; int $sIndex = $sizeS; int $fInt, $sInt; int $newInts[]; for ( $i = 0; $i < $maxSize; $i++ ) { string $f = getChar( $first, $fIndex ); string $s = getChar( $second, $sIndex ); if ( $f == "x" || $f == "X" || $f == "" ) $fInt = 0; else $fInt = getHexInt( $f ); if ( $s == "x" || $s == "X" || $s == "" ) $sInt = 0; else $sInt = getHexInt( $s ); int $newVal = orInt( $fInt, $sInt ); $newInts[$i] = $newVal; $fIndex--; $sIndex--; } string $newString = "0x"; for ( $i = $maxSize; $i >= 0; $i-- ) { string $newChar = getHexChar( $newInts[$i] ); $newString += $newChar; } return $newString; } // Given an int, converts it to a hex string with preceeding "0x" // This function generates 4 byte (8 hex chars) strings proc string intToHexString( int $intVal ) { string $chars[]; float $value = $intVal; for ( $i = 0; $i < 8; $i++ ) { float $mod = `fmod $value 16`; $value = $value - $mod; $value = $value / 16; $chars[$i] = getHexChar( $mod ); } string $ret = "0x"; for ( $i = 7; $i >= 0; $i-- ) $ret += $chars[$i]; return $ret; } // Utility func - checks to see if the given string is in the // given string array proc int stringIsInArray( string $str, string $strArray[] ) { for ( $name in $strArray ) { if ( $str == $name ) return 1; } return 0; } // A few utility functions follow to get various data out of the // blind data template nodes. // This func gets the id assigned to the given template node. // The node is specified by name proc int getId( string $templateNode ) { string $cmd = "getAttr " + $templateNode + ".typeId"; int $id = `eval( $cmd )`; return $id; } // The blindDataType nodes have bdun (blind data user name) and // bduv (blind data user value) attributes with which we can specify // some of the extra data we're tracking for editing purposes. // The following few are generic ones for setting and getting data and name // at a specified index. // The indices that we're using are: // 0: TypeTag (a name which is uniquely mapped to the ID ( a string's a bit easier to // remember than an int) ) // 1: AssociationType (face, vertex, object, any) // 2: Unused // 3: Free Set (whether the user can set the data with whatever value they want, or // is restricted to the predefined presets) // 4: Data Count - how many attributes in this blind data node // 5+: The attributes. The name (bdun[index]) is the long name of the attribute, and // the value is the data type. proc setUserDefinedAttr( string $bdt, int $index, string $name, string $value ) { string $cmd = "setAttr " + $bdt + ".bdui[" + $index + "].bdun -type \"string\" "; $cmd += "\"" + $name + "\""; string $fmtString = (uiRes("m_blindDataEditor.kSetUserDefinedAttr")); print(`format -s $cmd $fmtString` ); eval( $cmd ); $cmd = "setAttr " + $bdt + ".bdui[" + $index + "].bduv -type \"string\" "; $cmd += "\"" + $value + "\""; // print("setUserDefinedAttr " + $cmd + "\n" ); eval( $cmd ); } proc string getUserDefinedAttrName( string $bdt, int $index ) { string $cmd = "getAttr " + $bdt + ".bdui[" + $index + "].bdun"; string $name = `eval( $cmd )`; // print( "getUserDefinedAttrName " + $name + "\n" ); return $name; } proc setUserDefinedAttrName( string $bdt, int $index, string $name ) { string $cmd = "setAttr " + $bdt + ".bdui[" + $index + "].bdun"; $cmd += " -type \"string\" \"" + $name + "\""; // print( "setUserDefinedAttrName " + $cmd + "\n" ); eval( $cmd ); } proc string getUserDefinedAttrVal( string $bdt, int $index ) { string $cmd = "getAttr " + $bdt + ".bdui[" + $index + "].bduv"; string $name = `eval( $cmd )`; // print("getUserDefinedAttrVal " + $name + "\n" ); return $name; } proc setUserDefinedAttrVal( string $bdt, int $index, string $val ) { string $cmd = "setAttr " + $bdt + ".bdui[" + $index + "].bduv"; $cmd += " -type \"string\" \"" + $val + "\""; // print("setUserDefinedAttrVal " + $cmd + "\n" ); eval( $cmd ); } // The following are hardcoded based on the values commented above. // If you change around how you're using the bdun/bduv (user-defined values/names) // you'll need to change the indices here. proc string getTag( string $bdt ) { string $name = getUserDefinedAttrName( $bdt, 0 ); if ( $name == "typeTag" ) return getUserDefinedAttrVal( $bdt, 0 ); else return ""; } proc setTag( string $bdt, string $tag ) { setUserDefinedAttrName( $bdt, 0, "typeTag" ); setUserDefinedAttrVal( $bdt, 0, $tag ); } proc string getAssocType( string $bdt ) { string $name = getUserDefinedAttrName( $bdt, 1 ); if ( $name == "assocType" ) return getUserDefinedAttrVal( $bdt, 1 ); else return ""; } proc setAssocType( string $bdt, string $assocType ) { setUserDefinedAttrName( $bdt, 1, "assocType" ); setUserDefinedAttrVal( $bdt, 1, $assocType ); } proc int getFreeSet( string $bdt ) { string $name = getUserDefinedAttrName( $bdt, 3 ); if ( $name == "freeSet" ) { $name = getUserDefinedAttrVal( $bdt, 3 ); if ( $name == "0" || $name == "" ) return 0; else return 1; } else return 1; } proc setFreeSet( string $bdt, int $freeSet ) { setUserDefinedAttrName( $bdt, 3, "freeSet" ); if ( $freeSet ) setUserDefinedAttrVal( $bdt, 3, "1" ); else setUserDefinedAttrVal( $bdt, 3, "0" ); } // Data count is how many attributes there are for this template node proc int getDataCount( string $bdt ) { string $name = getUserDefinedAttrName( $bdt, 4 ); if ( $name == "dataCount" ) { $name = getUserDefinedAttrVal( $bdt, 4 ); int $count = $name; return $count; } else { string $dynAttrs[] = `listAttr -ud $bdt`; return size( $dynAttrs ); } } proc setDataCount( string $bdt, int $count ) { setUserDefinedAttrName( $bdt, 4, "dataCount" ); string $name = $count; setUserDefinedAttrVal( $bdt, 4, $count ); } // Because we don't know how many long names (attributes) // will be in the node, we start at ($gBdeNumUdAttrsUsed) and // just go up from there. There is thus an implicit order involved // in getting/setting the attrs (which could be returned in any // order if just doing a listAttr-type call) proc string getLongName( string $bdt, int $index ) { global int $gBdeNumUdAttrsUsed; int $i = $gBdeNumUdAttrsUsed + $index; string $name = getUserDefinedAttrName( $bdt, $i ); if ( $name == "" ) { string $dynAttrs[] = `listAttr -ud $bdt`; if ( size( $dynAttrs ) >= $index ) return $dynAttrs[$index]; else return ""; } else return $name; } proc setLongName( string $bdt, int $index, string $attrName ) { global int $gBdeNumUdAttrsUsed; int $i = $gBdeNumUdAttrsUsed + $index; setUserDefinedAttrName( $bdt, $i, $attrName ); } proc string getShortName( string $bdt, int $index ) { string $longName = getLongName( $bdt, $index ); if ( $longName != "" ) { string $cmd = "listAttr -sn " + $bdt + "." + $longName; string $shortName[] = `eval( $cmd )`; return $shortName[0]; } else return ""; } // Data type can be one of: // int // double // hex (equivalent internally to int, but within the editor // you can or and and values together, etc) // boolean // string // binary (internally equivalent to a string) proc string getDataType( string $bdt, int $index ) { global int $gBdeNumUdAttrsUsed; int $i = $gBdeNumUdAttrsUsed + $index; string $type = getUserDefinedAttrVal( $bdt, $i ); if ( $type != "" ) return $type; else { string $dynAttrs[] = `listAttr -ud $bdt`; if ( size( $dynAttrs ) >= $index ) { int $id = getId( $bdt ); string $cmd = "blindDataType -q -id " + $id + " -tn -ldn " + $dynAttrs[$index]; string $types[] = `eval( $cmd )`; return $types[0]; } else return ""; } } proc setDataType( string $bdt, int $index, string $dataType ) { global int $gBdeNumUdAttrsUsed; int $i = $gBdeNumUdAttrsUsed + $index; setUserDefinedAttrVal( $bdt, $i, $dataType ); } // Note that you need the attribute name here for min val // This is a faster lookup (since we're actually checking // the attribute instead of the user-defined data) // Most of the other data is specified by index, however, and // mel won't complain if you pass an int as a string, so take // care that you use the attribute name (can do a getLongName( $bdt, $index) // to get the attr name) proc float getMinVal( string $bdt, string $attrName ) { string $cmd = "attributeQuery -range -n " + $bdt + " " + $attrName; float $range[] = `eval( $cmd )`; return $range[0]; } // Note that you need the attribute name here for min val // This is a faster lookup (since we're actually checking // the attribute instead of the user-defined data) // Most of the other data is specified by index, however, and // mel won't complain if you pass an int as a string, so take // care that you use the attribute name (can do a getLongName( $bdt, $index) // to get the attr name) proc float getMaxVal( string $bdt, string $attrName ) { string $cmd = "attributeQuery -range -n " + $bdt + " " + $attrName; float $range[] = `eval( $cmd )`; return $range[1]; } // Note that you need the attribute name here for min val // This is a faster lookup (since we're actually checking // the attribute instead of the user-defined data) // Most of the other data is specified by index, however, and // mel won't complain if you pass an int as a string, so take // care that you use the attribute name (can do a getLongName( $bdt, $index) // to get the attr name) proc int getRanged( string $bdt, string $attrName ) { string $cmd1 = "attributeQuery -rangeExists -n " + $bdt + " " + $attrName; int $hasRange = `eval( $cmd1 )`; return $hasRange; } // If any of the types are hex, we return "hex". // If there are three attrs, and all three are double/floats // and all three are ranged at [0, 1], we return "asColor". // Otherwise it's normal apply mode... proc string getApplyMode( string $bdt ) { string $dataType[]; int $dataCount = getDataCount( $bdt ); for ( $i = 0; $i < $dataCount; $i++ ) { $dataType[$i] = getDataType( $bdt, $i ); if ( $dataType[$i] == "hex" ) return "hex"; } if ( $dataCount == 3 ) { if ( ($dataType[0] == "double" || $dataType[0] == "float" ) && ($dataType[1] == "double" || $dataType[1] == "float" ) && ($dataType[2] == "double" || $dataType[2] == "float" ) ) { float $min[], $max[]; for ( $i = 0; $i < $dataCount; $i++ ) { $name = getLongName( $bdt, $i ); $min[$i] = getMinVal( $bdt, $name ); $max[$i] = getMaxVal( $bdt, $name ); if ( $min[0] == 0 && $min[1] == 0 && $min[2] == 0 && $max[0] == 1 && $max[1] == 1 && $max[2] == 1 ) return "asColor"; } } } return "normal"; } // $presetName is an identifier for this preset (which will appear at // index $index) // $attrName[] should have the names of the attributes in the order // they appear in the bdun/bduv values, and // $presetVal[] should have the corresponding values for this preset proc setPreset( string $bdt, string $presetName, string $attrName[], string $presetVal[], int $index ) { string $baseCmd = "setAttr " + $bdt + ".bdps[" + $index + "]"; string $cmd = $baseCmd + ".bdpn -type \"string\" "; $cmd += "\"" + $presetName + "\""; // print( $cmd + "\n" ); eval( $cmd ); for ( $i = 0; $i < size( $presetVal ); $i++ ) { string $nextCmd = $baseCmd + ".bdpe[" + $i + "]"; $cmd = $nextCmd + ".bdpa -type \"string\" "; $cmd += "\"" + $attrName[$i] + "\""; // print( $cmd + "\n" ); eval( $cmd ); $cmd = $nextCmd + ".bdpv -type \"string\" "; $cmd += "\"" + $presetVal[$i] + "\""; // print( $cmd + "\n" ); eval( $cmd ); } } // How many presets there are in the given template node (passed by name of node) proc int getPresetCount( string $bdt ) { string $cmd = "attributeQuery -ex -n " + $bdt + " bdps"; if ( `eval( $cmd )` ) { $cmd = "getAttr -size " + $bdt + ".bdps"; int $num = `eval( $cmd )`; return $num; } else return 0; } // Presets are stored according to indices... // Because each preset is a complete set of data, // the order of the presets doesn't matter, and each // preset value is indexed by attribute name, so that // order is not important either. proc string getPresetName( string $bdt, int $index ) { string $cmd = "getAttr " + $bdt + ".bdps[" + $index + "]"; $cmd += ".bdpn"; string $name = `eval( $cmd )`; return $name; } // This is the number of preset values assigned for the given // preset (at index $index). This should match the number of // attributes for this blindDataTemplate node (getDataCount( $bdt ) ). proc int getNumPresetVals( string $bdt, int $index ) { string $cmd = $cmd = "getAttr -size " + $bdt + ".bdps[" + $index + "].bdpe"; int $num = `eval( $cmd )`; return $num; } // Get the presetVal corresponding to the given attribute // for the preset at the given index proc string getPresetVal( string $bdt, int $index, string $attrName ) { string $cmd; string $baseCmd = "getAttr " + $bdt + ".bdps[" + $index + "].bdpe"; int $numVals = getNumPresetVals( $bdt, $index ); for ( $i = 0; $i < $numVals; $i++ ) { $cmd = $baseCmd + "[" + $i + "].bdpa"; string $name = `eval( $cmd )`; if ( $name == $attrName ) { $cmd = $baseCmd + "[" + $i + "].bdpv"; $name = `eval( $cmd )`; return $name; } } return ""; } // The returned stringArray contains an entry (presetVal) for each attribute // in the node. proc string[] getPresetVals( string $bdt, int $index ) { string $ret[]; int $presetCount = getPresetCount( $bdt ); if ( $index > $presetCount ) return $ret; int $dataCount = getDataCount( $bdt ); for ( $i = 0; $i < $dataCount; $i++ ) { $attr = getLongName( $bdt, $i ); $ret[$i] = getPresetVal( $bdt, $index, $attr ); } return $ret; } // Given a typeId, this func returns the name of the // blind data template node with that typeId. // If none matches, the empty string is returned. proc string getTemplateNameFromId( int $id ) { // Bug 150384 check exact type so we don't get subd blind data string $blindDataTemplates[] = `ls -exactType blindDataTemplate`; string $cmd; for ( $bdt in $blindDataTemplates ) { $cmd = "getAttr " + $bdt + ".typeId"; int $thisId = `eval $cmd`; if ( $thisId == $id ) { return $bdt; } } return ""; } // Similarly, this function returns the name of the blind // data template node given the user-defined "tag" for that node. // Again, an empty string is returned if none matches. proc string getTemplateNameFromTag( string $tag ) { // Bug 150384 check exact type so we don't get subd blind data string $blindDataTemplates[] = `ls -exactType blindDataTemplate`; for ( $bdt in $blindDataTemplates ) { $name = getTag( $bdt ); if ( $tag == $name ) return $bdt; } return ""; } // Query/color // What follows is a bunch of utility functions for the query/color tab // (hence the Qc in the function name). // Much of this Qc code will be a little difficult to decipher because // of the necessity to use the full path name ot the controls. // The reason the full pathnames are required is that the // query/color rows can constantly change. Hence we track the name of the // layout (a columnLayout) and get all of the controls relative to this // control. Typically, the layout is the $parent argument to these qc functions. // Sets the value of the specified value field. This value field is a text // field regardless of the data type. // If the index is > 0, the data we're looking at lives in the 'multiList' child. // This multilist has a dataLayout child, which has a child rowLayout#, where // # is the index of the data. proc setQcValue( string $parent, int $index, string $val ) { if ( $index == 0 ) $control = $parent + "|mainLine|value"; else $control = $parent + "|multiList|dataLayout|rowLayout" + $index + "|value"; if ( `textField -q -ex $control` ) textField -e -tx $val $control; } // Gets the text value at the specified $index. proc string getQcValue( string $parent, int $index ) { string $control; if ( $index == 0 ) $control = $parent + "|mainLine|value"; else $control = $parent + "|multiList|dataLayout|rowLayout" + $index + "|value"; if ( `textField -q -ex $control` ) return `textField -q -tx $control`; else return ""; } // Returns the name of the blindDataTemplate node for the specified // query/color row. // The name of the type box can be the 'Tag' of the bdt, for which // the first getTemplateNameFromTag will return the right value. // The type box can also have the id# of the blind data template node, // however; in this case, we do a getTemplateNameFromId and hope this // is the right one. (If it's not, empty string will be returned) proc string getQcSelectedBdt( string $parent ) { string $control = $parent + "|mainLine|type"; string $type = `textField -q -tx $control`; string $name = getTemplateNameFromTag( $type ); if ( $name == "" ) { if ( $type != "" ) { int $id = $type; $name = getTemplateNameFromId( $id ); } } return $name; } proc int getNumQcValues( string $parent ) { int $numVals = 1; string $layout = $parent + "|multiList|dataLayout"; if ( `columnLayout -q -ex $layout` ) { string $children[] = `columnLayout -q -ca $layout`; $numVals += size( $children ); } return $numVals; } // This enable specifies whether user wants to use this // row for qc operation. proc int getQcEnable( string $parent ) { string $control = $parent + "|mainLine|enable"; if ( `checkBox -q -ex $control` ) return `checkBox -q -v $control`; else return 0; } proc setQcEnable( string $parent, int $val ) { string $control = $parent + "|mainLine|enable"; if ( `checkBox -q -ex $control` ) checkBox -e -en true -v $val $control; } // The way it was designed, this type value should be set // with the popup menu for the box. Since it is just a text // box, however, the user can also type in a value. // Acceptable values are the 'tag' for the blind data template, // or the id. Either of these should result in the correct // blind data template being accessed. (see getQcSelectedBdt() ) proc string getQcType( string $parent ) { string $control = $parent + "|mainLine|type"; string $type = ""; if ( `textField -q -ex $control` ) $type = `textField -q -tx $control`; return $type; } // The 'MainColor' is the color of the canvas you see on the main line // of the qc row. If the value chooser is set to be continuous/grayscale // data or asColor data, this canvas is blacked out (and should be disabled) and // the proper color saved in the 'saveColor' canvas. (see getQcSaveColor()). proc setQcMainColor( string $parent, float $color[] ) { string $control = $parent + "|mainLine|canvas"; if ( `canvas -q -ex $control` ) canvas -edit -rgbValue $color[0] $color[1] $color[2] $control; } proc float[] getQcMainColor( string $parent ) { float $color[] = { 0, 0, 0 }; string $control = $parent + "|mainLine|canvas"; if ( `canvas -q -ex $control` ) $color = `canvas -query -rgbValue $control`; return $color; } // The save color is the color of the row as it was before it was blacked out // (because the user selected continuous or asColor, and the grayscale colors // appeared). We need to save this color so if they go back to a discrete color // choice the one it was set to before is restored properly. // This canvas is not visible. proc setQcSaveColor( string $parent, float $color[] ) { string $control = $parent + "|valueLayout|valueForm|valueTypeLayout|saveColor"; if ( `canvas -q -ex $control` ) canvas -edit -rgbValue $color[0] $color[1] $color[2] $control; } proc float[] getQcSaveColor( string $parent ) { float $color[] = { 0, 0, 0 }; string $control = $parent + "|valueLayout|valueForm|valueTypeLayout|saveColor"; if ( `canvas -q -ex $control` ) $color = `canvas -query -rgbValue $control`; return $color; } // This func is used when opening up the blind data editor. // It serves to simplify restoring userPrefs when opening // up the blindDataEditor. proc setQcTypeAndColors( string $parent, string $type, float $mainColor[], float $saveColor[] ) { string $control = $parent + "|mainLine|type"; if ( `textField -q -ex $control` ) { textField -e -tx $type $control; bdeQcChangeType( $parent ); setQcMainColor( $parent, $mainColor ); setQcSaveColor( $parent, $saveColor ); } } // Value enable is a check box specifying whether or not // the 'values' should be used (if unchecked, the user wants // to query/color the data based only on whether the type is // present or not. Otherwise, there are more options for specifying // how to consider the actual value of the data (i.e. a specific value // or range, asColor, etc.) proc int getQcValueEnable( string $parent ) { string $control = $parent + "|mainLine|valueEnable"; if ( `checkBox -q -ex $control` ) return `checkBox -q -v $control`; else return 0; } proc setQcValueEnable( string $parent, int $enable ) { string $control = $parent + "|mainLine|valueEnable"; if ( `checkBox -q -ex $control` ) { checkBox -e -en true -v $enable $control; bdeQcChangeValueEnable( $parent ); } } // These next two functions are just to facilitate saving user data before // the panel is torn off or deleted proc string[] getQcValues( string $parent ) { string $values[]; int $index = 0; int $numVals = getNumQcValues( $parent ); for ( $i = 0; $i < $numVals; $i++ ) { $values[$index++] = getQcValue( $parent, $i ); } return $values; } // Select type appears in the 'valueLayout', a frame that opens when the user // enables the valueEnable checkbox. Select type can be one of: // $gBdeDiscreteValName = "discrete value"; // $gBdeDiscreteRangeName = "discrete range"; // $gBdeHexValName = "hex"; // $gBdeContinuousName = "continuous"; // $gBdeAsColorName = "as color"; proc string getQcSelectType( string $parent ) { string $control = $parent + "|valueLayout|valueForm|valueTypeLayout|valueType"; if ( `optionMenu -q -ex $control` ) return `optionMenu -q -v $control`; else return ""; } // Open or close the 'valueLayout' frame proc toggleCollapseQcSelectType( string $parent, int $open ) { string $control = $parent + "|valueLayout"; if ( `frameLayout -q -ex $control` ) { if ( $open ) frameLayout -e -cl false $control; else frameLayout -e -cl true $control; } } proc setQcSelectType( string $parent, string $val ) { string $control = $parent + "|valueLayout|valueForm|valueTypeLayout|valueType"; if ( `optionMenu -q -ex $control` ) { optionMenu -e -v $val $control; bdeQcOpenValueTab( $parent, 0 ); } } // some funcs to facilitate storing/restoring user values proc string getQcFilledRow( int $index ) { int $numRows = 0; global string $gBdeQueryColorLayout; if ( `columnLayout -q -ex $gBdeQueryColorLayout` ) { string $children[] = `columnLayout -q -ca $gBdeQueryColorLayout`; for ( $child in $children ) { $layout = $gBdeQueryColorLayout + "|" + $child; $type = getQcType( $layout ); if ( $type != "" ) { if ( $numRows == $index ) return $layout; $numRows++; } } } return ""; } proc int getQcNumFilledRows() { int $numRows = 0; global string $gBdeQueryColorLayout; if ( `columnLayout -q -ex $gBdeQueryColorLayout` ) { string $children[] = `columnLayout -q -ca $gBdeQueryColorLayout`; for ( $child in $children ) { $layout = $gBdeQueryColorLayout + "|" + $child; $type = getQcType( $layout ); if ( $type != "" ) $numRows++; } } return $numRows; } // $gBdeQueryColorLayout is the parent qc layout. // The children are all of the current query/color rows. proc int getQcNumRows() { global string $gBdeQueryColorLayout; int $num = 0; if ( `columnLayout -q -ex $gBdeQueryColorLayout` ) { string $children[] = `columnLayout -q -ca $gBdeQueryColorLayout`; $num = size( $children ); } return $num; } // Checks whether this id is defined for any blindDataTemplate nodes in the scene proc int idDefined( int $id ) { // Bug 150384 check exact type so we don't get subd blind data string $blindDataTemplates[] = `ls -exactType blindDataTemplate`; for ( $bdt in $blindDataTemplates ) { string $cmd = "getAttr " + $bdt + ".typeId"; if ( `eval( $cmd )` == $id ) return 1; } return 0; } // Checks whether this tag is defined for any bdt's in the scene proc int tagDefined( string $tag ) { // Bug 150384 check exact type so we don't get subd blind data string $blindDataTemplates[] = `ls -exactType blindDataTemplate`; for ( $bdt in $blindDataTemplates ) { if ( getTag( $bdt ) == $tag ) return 1; } return 0; } // For internal use (creating attr's if using them (at the object level) // instead of (component) blind data proc string getGenericDataType( string $type ) { if ( $type == "string" || $type == "binary" ) return "string"; if ( $type == "double" || $type == "float" ) return "double"; if ( $type == "int" || $type == "hex" ) return "long"; if ( $type == "boolean" ) return "bool"; } // Proper flag for querying poly blind data proc string getDataTypeFlag( string $type ) { if ( $type == "int" || $type == "hex" ) return "-intData"; else if ( $type == "float" || $type == "double" ) return "-doubleData"; else if ( $type == "boolean" ) return "-booleanData"; else if ( $type == "string" ) return "-stringData"; else if ( $type == "binary" ) return "-binaryData"; else { return "-invalidData"; } } // There are a couple of lists this could come from. // bdeTemplateList (Type editor tab) and bdeTypeList (apply tab) // This returns which one is selected. If the selected one has not // tag, an empty string is returned (in this case, use getCurrentId // and the id will be returned) proc string getCurrentTag( string $list ) { string $tags[] = `textScrollList -q -si $list`; if ( "" == $tags[0] ) return ""; else { string $buffer[]; int $numTokens = tokenize( $tags[0], $buffer ); if ( $numTokens == 2 ) return $buffer[0]; else return ""; } } // This returns the id of the selected template in the given list // possible lists are bdeTemplateList (type editor tab) and // bdeTypeList (apply tab) proc int getCurrentId( string $list ) { string $tags[] = `textScrollList -q -si $list`; if ( "" == $tags[0] ) return -1; else { string $buffer[]; int $numTokens = tokenize( $tags[0], $buffer ); if ( $numTokens == 2 ) { int $l = size( $buffer[1] ); string $id = `substring $buffer[1] 2 ($l-1)`; return $id; } else if ( $numTokens == 1 ) { int $id = $buffer[0]; return $id; } else return -1; } } // This returns the id of the selected template in the TypeEditor tab. // if none is selected, or the list doesn't exist // -1 is returned. proc int getTemplateTagId() { int $i, $id; string $blindDataTags[]; string $blindDataIds[]; string $tag = getCurrentTag( "bdeTemplateList" ); if ( "" == $tag ) return getCurrentId( "bdeTemplateList" ); // Bug 150384 check exact type so we don't get subd blind data string $nodes[] = `ls -exactType blindDataTemplate`; for ( $i = 0; $i < size( $nodes ); $i++ ) { string $thisTag = getTag( $nodes[$i] ); if ( $thisTag == $tag ) { $id = getId( $nodes[$i] ); return $id; } } return -1; } // This returns the child of the bdeSingleApplyLayout // (a tabLayout with invisible tabs) corresponding to the // given id. // The apply tab's only child is this bdeSingleApplyLayout, // and each of the id's gets its own layout, which will be // a child of this bdeSingleApplyLayout. // This means that we can switch tabs without having to rebuild // the layout, which is faster after the initial build, and // allows us to keep the user data as he/she has set it without // saving and restoring it. proc string getApplyTab( int $id ) { string $thisTab = "bdeApply" + $id; string $bdt = getTemplateNameFromId( $id ); if ( $bdt == "" ) return ""; string $thisTabLabel = getTag( $bdt ); if ( $thisTabLabel == "" ) $thisTabLabel = "" + $id; string $children[] = `tabLayout -q -ca bdeSingleApplyLayout`; for ( $child in $children ) { if ( $child == $thisTab ) return $child; } return ""; } // Returns the name of the template of the currently selected // item in the apply tab. proc string getCurrentApplyTemplate() { string $tag = getCurrentTag( "bdeTypeList" ); if ( "" == $tag ) { int $id = getCurrentId( "bdeTypeList" ); return getTemplateNameFromId( $id ); } else return getTemplateNameFromTag( $tag ); } // This also returns the name of the template of the currently selected // item in the apply tab (there needn't be two of them, but it's too // late to change it) proc string getSelectedApplyBdt() { string $parent = "bdeSingleApplyLayout"; // We apply the data set at the selected tab string $tab = `tabLayout -q -st $parent`; if ( $tab == "" ) return ""; // $tab looks like bdeApply1200 or something int $length = `size( $tab )`; if ( $length < 9 ) return ""; string $idString = `substring $tab 9 $length`; int $id = $idString; return getTemplateNameFromId( $id ); } // This func is used only to restore the state to what // the user had set before a tear-off or close of the panel proc int setSelectedApply( int $desiredId ) { string $items[] = `textScrollList -q -ai bdeTypeList`; int $numItems = size( $items ); if ( $numItems == 0 ) return 0; for ( $i = 0; $i < $numItems; $i++ ) { string $buffer[]; int $numTokens = tokenize( $items[$i], $buffer ); if ( $numTokens == 2 ) { int $l = size( $buffer[1] ); string $id = `substring $buffer[1] 2 ($l-1)`; if ( $id == $desiredId ) { textScrollList -e -sii ($i+1) bdeTypeList; return 1; } } else if ( $numTokens == 1 ) { int $id = $buffer[0]; if ( $id == $desiredId ) { textScrollList -e -sii ($i+1) bdeTypeList; return 1; } } } return 0; } // This function is used for the apply tab. // It sets the values in the apply tab for the given template // to the given string array values. // It is assumed that there are at least as many values in the string // array as there are data fields (getDataCount()). // If the tab for the given template does not exist, it is created // (through bdeRebuildApplyTab( $id )). proc bdeSetControl( string $bdt, string $newVals[] ) { if ( $bdt == "" ) return; int $dataCount = getDataCount( $bdt ); int $id = getId( $bdt ); if ( getApplyTab( $id ) == "" ) { string $tab = bdeRebuildApplyTab( $id ); if ( $tab == "" ) return; } for ( $i = 0; $i < $dataCount; $i++ ) { string $controlName = "bdeDataValue" + $id + "_" + $i; string $dataType = getDataType( $bdt, $i ); string $dataName = getLongName( $bdt, $i ); int $ranged = getRanged( $bdt, $dataName ); if ( $dataType == "string" || $dataType == "binary" ) { textField -e -tx $newVals[$i] $controlName; } else if ( $dataType == "float" || $dataType == "double" ) { float $value; if ( $newVals[$i] == "" ) $value = 0; else $value = $newVals[$i]; if ( $ranged ) floatSliderGrp -e -v $value $controlName; else floatField -e -v $value $controlName; } else if ( $dataType == "int" ) { int $value; if ( $newVals[$i] == "" ) $value = 0; else $value = $newVals[$i]; if ( $ranged ) intSliderGrp -e -v $value $controlName; else intField -e -v $value $controlName; } else if ( $dataType == "hex" ) { textField -e -tx $newVals[$i] $controlName; } else if ( $dataType == "boolean" ) { if ( $newVals[$i] == "1" || $newVals[$i] == "true" || $newVals[$i] == "TRUE" ) radioButtonGrp -e -sl 2 $controlName; else radioButtonGrp -e -sl 1 $controlName; } } // This canvas exists if the data looks like a color // (i.e. three doubles [0,1].) // We change the canvas to reflect the new data values $control = "bdeColorDataCanvas" + $id; if ( `canvas -q -ex $control` ) { float $col[]; for ( $i = 0; $i < 3; $i++ ) { $controlName = "bdeDataValue" + $id + "_" + $i; $col[$i] = `floatSliderGrp -q -v $controlName`; } canvas -edit -rgbValue $col[0] $col[1] $col[2] $control; } } proc string assocType_melToUI( string $mel ) { string $result = $mel; string $any = (uiRes("m_blindDataEditor.kAny")); string $face = (uiRes("m_blindDataEditor.kFace")); string $vertex = (uiRes("m_blindDataEditor.kVertex")); string $object = (uiRes("m_blindDataEditor.kObject")); string $edge = (uiRes("m_blindDataEditor.kEdge")); string $vertexFace = (uiRes("m_blindDataEditor.kVertexFace")); if( $mel == "any" ) { $result = $any; } else if( $mel == "face" ) { $result = $face; } else if( $mel == "vertex" ) { $result = $vertex; } else if( $mel == "object" ) { $result = $object; } else if( $mel == "edge" ) { $result = $edge; } else if( $mel == "vertexFace" ) { $result = $vertexFace; } else { uiToMelMsg( "assocType_melToUI", $mel, 1 ); } return $result; } proc string assocType_uiToMel( string $ui ) { string $result = $ui; string $any = uiRes( "m_blindDataEditor.kAny" ); string $face = uiRes( "m_blindDataEditor.kFace" ); string $vertex = uiRes( "m_blindDataEditor.kVertex" ); string $object = uiRes( "m_blindDataEditor.kObject" ); string $edge = uiRes( "m_blindDataEditor.kEdge" ); string $vertexFace = uiRes( "m_blindDataEditor.kVertexFace" ); if( $ui == $any ) { $result = "any"; } else if( $ui == $face ) { $result = "face"; } else if( $ui == $vertex ) { $result = "vertex"; } else if( $ui == $object ) { $result = "object"; } else if( $ui == $edge ) { $result = "edge"; } else if( $ui == $vertexFace ) { $result = "vertexFace"; } else { uiToMelMsg( "assocType_uiToMel", $ui, 1 ); } return $result; } proc string dataType_melToUI( string $mel ) { string $result = $mel; string $double = (uiRes("m_blindDataEditor.kDouble")); string $int = (uiRes("m_blindDataEditor.kInt")); string $hex = (uiRes("m_blindDataEditor.kHex")); string $boolean = (uiRes("m_blindDataEditor.kBoolean")); string $string = (uiRes("m_blindDataEditor.kString")); string $binary = (uiRes("m_blindDataEditor.kBinary")); if( $mel == "double" ) { $result = $double; } else if( $mel == "int" ) { $result = $int; } else if( $mel == "hex" ) { $result = $hex; } else if( $mel == "boolean" ) { $result = $boolean; } else if( $mel == "string" ) { $result = $string; } else if( $mel == "binary" ) { $result = $binary; } else { uiToMelMsg( "dataType_melToUI", $mel, 1 ); } return $result; } proc string dataType_uiToMel( string $ui ) { string $result = $ui; string $double = uiRes( "m_blindDataEditor.kDouble" ); string $int = uiRes( "m_blindDataEditor.kInt" ); string $hex = uiRes( "m_blindDataEditor.kHex" ); string $boolean = uiRes( "m_blindDataEditor.kBoolean" ); string $string = uiRes( "m_blindDataEditor.kString" ); string $binary = uiRes( "m_blindDataEditor.kBinary" ); if( $ui == $double ) { $result = "double"; } else if( $ui == $int ) { $result = "int"; } else if( $ui == $hex ) { $result = "hex"; } else if( $ui == $boolean ) { $result = "boolean"; } else if( $ui == $string ) { $result = "string"; } else if( $ui == $binary) { $result = "binary"; } else { uiToMelMsg( "dataType_uiToMel", $ui, 1 ); } return $result; } global proc buildBlindDataEditorContextHelpItems( string $nameRoot, string $menuParent) // // Description: // Build context sensitive menu items // // Input Arguments: // $nameRoot - name to use as the root of all item names // $menuParent - the name of the parent of this menu // // Return Value: // None // { menuItem -label (uiRes("m_blindDataEditor.kHelpBlindDataEditor")) -enableCommandRepeat false -command "showHelp BlindDataEditor"; } // This indicates the user has changed the value of one // of the fields. This typically happens when there is a // manual change of one of the fields (although it can also // be called when the user uses the canvas to do asColor data) global proc bdeChangedValue( int $id ) { string $controlName; string $bdt = getTemplateNameFromId( $id ); if ( $bdt == "" ) return; string $applyMode = getApplyMode( $bdt ); int $presetCount = getPresetCount( $bdt ); // Turn off the preset checkboxes/radiobuttons if ( $applyMode == "hex" ) { for ( $i = 0; $i < $presetCount; $i++ ) { $controlName = "bdeIndicator" + $id + "_" + $i; checkBox -e -v 0 $controlName; } } else { // bdeNoIndicator is an invisible radioButton. // If we turn it on, all the visible ones turn off // (which is what we want here) $controlName = "bdeNoIndicator" + $id; radioButton -e -sl $controlName; } // If we're looking at color data, we change the canvas to reflect // the new data (even though this func may have been called as a // result of this change). Doing so here won't recall this function // (for a recursive loop), so it doesn't matter if this happened // (and we'll just be changing the color to what it was already) $control = "bdeColorDataCanvas" + $id; if ( `canvas -q -ex $control` ) { float $col[]; for ( $i = 0; $i < 3; $i++ ) { $controlName = "bdeDataValue" + $id + "_" + $i; $col[$i] = `floatSliderGrp -q -v $controlName`; } canvas -edit -rgbValue $col[0] $col[1] $col[2] $control; } } // This function is used for splitting up a selection string // (which looks like pPlane1.f[3] // Return string array has 3 strings: // [0]: pPlane1 // [1]: f // [2]: 3 // Note that multiple selections are ignored (i.e. pPlane1.f[3:10] returns // the same string array as pPlane1.f[3]). proc string[] getSelectionComp( string $sel ) { string $rest = ""; string $obj = $sel; int $length = size( $sel ); for ( $i = 1; $i <= $length; $i++ ) { if ( getChar( $sel, $i ) == "." ) { $obj = `substring $sel 1 ($i-1)`; $rest = `substring $sel ($i+1) $length`; break; } } string $comp = ""; $length = size( $rest ); for ( $i = 1; $i <= $length; $i++ ) { if ( getChar( $rest, $i ) == "[" ) { $comp = `substring $rest 1 ($i-1)`; $rest = `substring $rest ($i+1) $length`; break; } } string $index = ""; $length = size( $rest ); for ( $i = 1; $i <= $length; $i++ ) { if ( getChar( $rest, $i ) == ":" ) { $index = `substring $rest 1 ($i-1)`; break; } if ( getChar( $rest, $i ) == "]" ) { $index = `substring $rest 1 ($i-1)`; break; } } string $array[]; $array[0] = $obj; $array[1] = $comp; $array[2] = $index; return $array; } // Color functions: // This function, given an absolute canvas control, // pops up the color editor and sets the canvas to the // new color if OK'd global proc int bdeChangeNamedCanvas( string $canvasName ) { float $oldColor[], $newColor[]; string $buf[], $colStr; $oldColor = `canvas -query -rgbValue $canvasName`; $colStr = `colorEditor -rgb $oldColor[0] $oldColor[1] $oldColor[2]`; $numToks = tokenize( $colStr, $buf ); if ( $buf[3] == 1 ) { $newColor[0] = $buf[0]; $newColor[1] = $buf[1]; $newColor[2] = $buf[2]; canvas -edit -rgbValue $newColor[0] $newColor[1] $newColor[2] $canvasName; return 1; } else return 0; } // This function works similarly to the namedCanvas // function, except that it takes an argument specifying // which query/color row (columnLayout) the user wants to change // the color for. global proc bdeChangeCanvas( string $parent ) { float $oldColor[], $newColor[]; string $buf[], $colStr; string $canvasName = $parent + "|mainLine|canvas"; $oldColor = `canvas -query -rgbValue $canvasName`; $colStr = `colorEditor -rgb $oldColor[0] $oldColor[1] $oldColor[2]`; $numToks = tokenize( $colStr, $buf ); if ( $buf[3] == 1 ) { $newColor[0] = $buf[0]; $newColor[1] = $buf[1]; $newColor[2] = $buf[2]; canvas -edit -rgbValue $newColor[0] $newColor[1] $newColor[2] $canvasName; } } // This function gets called from the apply tab if the data is // "asColor" data and the user presses on the color canvas supplied. // The appropriate calls are made if a change is confirmed // to turn off any presets and set the value fields. global proc bdeChangeColorData( int $id ) { $control = "bdeColorDataCanvas" + $id; if ( bdeChangeNamedCanvas( $control ) ) { string $colStr[]; string $colComp; float $col[] = `canvas -query -rgbValue $control`; for ( $i = 0; $i < 3; $i++ ) { $colComp = $col[$i]; $colStr[$i] = $colComp; } string $bdt = getTemplateNameFromId( $id ); bdeSetControl( $bdt, $colStr ); bdeChangedValue( $id ); } } proc float absDiff( float $a, float $b ) { if ( $a >= $b ) return $a - $b; else return $b - $a; } // See if two colors (rgb) are within $tol of one another proc int colorsEquivalent( float $color1[], float $color2[], float $tol ) { for ( $i = 0; $i < 3; $i++ ) if ( absDiff( $color1[$i], $color2[$i] ) > $tol ) return false; return true; } // This function could use some work. // It uses hard-coded values for 'distinct' colors, looks for // one of these hard-coded colors that's not in the given used // color list. // I'd thought about using a colorIndexSliderGrp, but i wasn't // sure whether the color table value was accessible and consistent // across platforms and systems, and doesn't seem (on my system) // to provide great colors // Called by bdeGetUniqueColor proc float[] getUnusedColor( float $usedR[], float $usedG[], float $usedB[], int $count ) { int $numDefaults = 11; float $r[] = { 1.00, 0.00, 0.00, 1.00, 0.00, 1.00, 0.70, 1.00, 0.50, 0.70, 0.35, 0.70, 0.70 }; float $g[] = { 0.00, 1.00, 0.00, 1.00, 1.00, 0.00, 0.30, 0.50, 0.70, 1.00, 0.35, 0.70, 0.35 }; float $b[] = { 0.00, 0.00, 1.00, 0.00, 1.00, 1.00, 0.40, 0.00, 0.70, 0.00, 0.70, 0.35, 0.35 }; float $defaultColor[] = { 1, 1, 1 }; float $newC[]; float $usedC[]; for ( $i = 0; $i < $numDefaults; $i++ ) { $newC[0] = $r[$i]; $newC[1] = $g[$i]; $newC[2] = $b[$i]; int $ok = true; for ( $j = 0; $j < $count; $j++ ) { $usedC[0] = $usedR[$j]; $usedC[1] = $usedG[$j]; $usedC[2] = $usedB[$j]; if ( colorsEquivalent( $newC, $usedC, 0.01 ) ) $ok = false; } if ( $ok ) return $newC; } return $defaultColor; } // This function fills the usedColor arrays used by getUnusedColor // with all of the appropriate canvases in the query color tab, // and gets a new (unique) one. Not very robust/extensible. proc float[] bdeGetUniqueColor() { global string $gBdeQueryColorLayout; float $usedR[]; float $usedG[]; float $usedB[]; float $newColor[]; string $children[] = `columnLayout -q -ca bdeQueryColorLayout`; for ( $i = 0; $i < size( $children ); $i++ ) { string $child = $children[$i]; string $canvas = $gBdeQueryColorLayout + "|" + $child + "|mainLine|canvas"; if ( `canvas -q -ex $canvas` ) { float $c[] = `canvas -query -rgbValue $canvas`; $usedR[$i] = $c[0]; $usedG[$i] = $c[1]; $usedB[$i] = $c[2]; } } float $col[] = `canvas -query -rgbValue bdeClashColor`; $usedR[$i] = $col[0]; $usedG[$i] = $col[1]; $usedB[$i] = $col[2]; $i++; $col = `canvas -query -rgbValue bdeOutOfRangeColor`; $usedR[$i] = $col[0]; $usedG[$i] = $col[1]; $usedB[$i] = $col[2]; $i++; $col = `canvas -query -rgbValue bdeNoneColor`; $usedR[$i] = $col[0]; $usedG[$i] = $col[1]; $usedB[$i] = $col[2]; $i++; $newColor = getUnusedColor( $usedR, $usedG, $usedB, $i ); return $newColor; } // This function returns the value of the data as set in the apply tab // for the specified template at the specified index proc string bdeGetControl( string $bdt, int $index ) { if ( $bdt == "" ) return ""; int $id = getId( $bdt ); string $controlName = "bdeDataValue" + $id + "_" + $index; string $dataType = getDataType( $bdt, $index ); string $name = getLongName( $bdt, $index ); string $ranged = getRanged( $bdt, $name ); string $ret = ""; if ( $dataType == "string" || $dataType == "binary" ) { if ( `textField -q -ex $controlName` ) $ret = `textField -q -tx $controlName`; } else if ( $dataType == "float" || $dataType == "double" ) { if ( $ranged ) { if ( `floatSliderGrp -q -ex $controlName` ) $ret = `floatSliderGrp -q -v $controlName`; } else { if ( `floatField -q -ex $controlName` ) { float $value = `floatField -q -v $controlName`; $ret = $value; } } } else if ( $dataType == "int" ) { if ( $ranged ) { if ( `intSliderGrp -q -ex $controlName` ) $ret = `intSliderGrp -q -v $controlName`; } else { if ( `intField -q -ex $controlName` ) $ret = `intField -q -v $controlName`; } } else if ( $dataType == "hex" ) { if ( `textField -q -ex $controlName` ) { string $strVal = `textField -q -tx $controlName`; int $val = `hexStringToInt $strVal`; $ret = $val; } } else if ( $dataType == "boolean" ) { if ( `radioButtonGrp -q -ex $controlName` ) { int $val = `radioButtonGrp -q -sl $controlName`; $ret = --$val; } } return $ret; } // This function returns (in a string array) all of the data // set in the apply tab for the specified template node. proc string[] bdeGetControls( string $bdt ) { string $controls[]; int $dataCount = getDataCount( $bdt ); for ( $i = 0; $i < $dataCount; $i++ ) { $controls[$i] = bdeGetControl( $bdt, $i ); } return $controls; } // This function gets called if any of the preset // radio buttons/check boxes change. It sets the // data value fields appropriately. global proc bdeChangedPreset( int $id ) { string $controlName; string $bdt = getTemplateNameFromId( $id ); if ( $bdt == "" ) return; string $applyMode = getApplyMode( $bdt ); int $presetCount = getPresetCount( $bdt ); int $dataCount = getDataCount( $bdt ); if ( $applyMode == "hex" ) { string $newStringVals[]; for ( $i = 0; $i < $dataCount; $i++ ) $newStringVals[$i] = "0"; for ( $i = 0; $i < $presetCount; $i++ ) { $controlName = "bdeIndicator" + $id + "_" + $i; if ( `checkBox -q -v $controlName` ) { for ( $j = 0; $j < $dataCount; $j++ ) { string $attr = getLongName( $bdt, $j ); string $thisVal = getPresetVal( $bdt, $i, $attr ); $newStringVals[$j] = orHexString( $newStringVals[$j], $thisVal ); } } } bdeSetControl( $bdt, $newStringVals ); } else { for ( $i = 0; $i < $presetCount; $i++ ) { string $newVals[]; $controlName = "bdeIndicator" + $id + "_" + $i; if ( `radioButton -q -sl $controlName` ) { $newVals = getPresetVals( $bdt, $i ); bdeSetControl( $bdt, $newVals ); return; } } } } // Controls which frame to open. There are three frames, // which the user can switch between if the data type is // int or float and free set is set. // This function closes the two others and // opens the specified one based on the value of the applyType // optionMenu. global proc bdeChangeApplyType( int $id ) { string $absFrame = "bdeAbsoluteFrame" + $id; string $offFrame = "bdeOffsetFrame" + $id; string $scaFrame = "bdeScaleFrame" + $id; string $preFrame = "bdePresetFrame" + $id; string $control = "bdeApplyType" + $id; string $applyType = `optionMenu -q -v $control`; if ( uiRes( "m_blindDataEditor.kAbsolute" ) == $applyType ) { frameLayout -e -cl false $preFrame; frameLayout -e -cl false $absFrame; frameLayout -e -cl true $offFrame; frameLayout -e -cl true $scaFrame; } else if ( uiRes( "m_blindDataEditor.kOffset" ) == $applyType ) { frameLayout -e -cl true $preFrame; frameLayout -e -cl true $absFrame; frameLayout -e -cl false $offFrame; frameLayout -e -cl true $scaFrame; } else if ( uiRes( "m_blindDataEditor.kScale" ) == $applyType ) { frameLayout -e -cl true $preFrame; frameLayout -e -cl true $absFrame; frameLayout -e -cl true $offFrame; frameLayout -e -cl false $scaFrame; } } // Returns whether relative controls (offset, scale) // make sense for the given template. // If any of the types are not int or double, or if // free set is not true (meaning that user can only choose // the predifined presets), then this returns false // and the relativeControls are not created or accessible. proc int relativeControls( string $bdt ) { if ( !getFreeSet( $bdt ) ) return 0; int $dataCount = getDataCount( $bdt ); for ( $i = 0; $i < $dataCount; $i++ ) { string $dataType = getDataType( $bdt, $i ); if ( $dataType == "string" || $dataType == "binary" || $dataType == "boolean" || $dataType == "hex" ) return 0; } return 1; } // Create a frame that has a floatSlider for each of the // attributes in the blindDataTemplate. // The slider initially has a range of [-10,10], but by // typing in the float field boxes user can expand these // to [-100000,100000], which should be high enough for anything. // Note that you have to specify a field min/max (-fmn/-fmx) // in the floatSliderGrp creation, or the value is taken to // be the min/max. proc createScaleControls( string $bdt ) { if ( $bdt == "" ) return; float $floatMin = -100000, $floatMax = 100000; int $freeSet = getFreeSet( $bdt ); int $id = getId( $bdt ); string $control = "bdeScaleFrame" + $id; frameLayout -cll true -cl true -bv false -lv false $control; columnLayout -adj true -rs 5; int $dataCount = getDataCount( $bdt ); for ( $i = 0; $i < $dataCount; $i++ ) { string $dataType = getDataType( $bdt, $i ); if ( $dataType == "string" || $dataType == "binary" || $dataType == "boolean" || $dataType == "hex" ) continue;; if ( !$freeSet ) continue; $controlName = "bdeDataScale" + $id + "_" + $i; string $text = getLongName( $bdt, $i ); rowLayout -nc 2 -cw 1 80 -cw 2 400; text -label $text; $max = 10; $min = -10; floatSliderGrp -f true -min $min -max $max -fmn $floatMin -fmx $floatMax -v 1 $controlName; setParent ..; } setParent ..; setParent ..; } // Create slider grp for each of the attributes in the blind data template. // If the data is int, an intSliderGrp is created, if float, a floatSliderGrp // is created. // If the data for each attribute is ranged, then // min = getMinVal() - getMaxVal(); max = getMaxVal() - getMinVal() // otherwise, range is [-1,1] for double data and [-100,100] for int data. // Again, these are initial ranges - by typing in numbers in the numeric fields, // you can get a range of [-100000,100000]. proc createOffsetControls( string $bdt ) { if ( $bdt == "" ) return; float $floatMin = -100000, $floatMax = 100000; int $freeSet = getFreeSet( $bdt ); int $id = getId( $bdt ); string $control = "bdeOffsetFrame" + $id; frameLayout -cll true -cl true -bv false -lv false $control; columnLayout -adj true -rs 5; int $dataCount = getDataCount( $bdt ); for ( $i = 0; $i < $dataCount; $i++ ) { string $dataType = getDataType( $bdt, $i ); // Neither of these two should be true if this frame was // created, but we check just to be sure if ( $dataType == "string" || $dataType == "binary" || $dataType == "boolean" || $dataType == "hex" ) continue; if ( !$freeSet ) continue; string $attrName = getLongName( $bdt, $i ); int $ranged = getRanged( $bdt, $attrName ); float $min, $max; $controlName = "bdeDataOffset" + $id + "_" + $i; rowLayout -nc 2 -cw 1 80 -cw 2 400; text -label $attrName; if ( $ranged ) { float $tmpMin = getMinVal( $bdt, $attrName ); float $tmpMax = getMaxVal( $bdt, $attrName ); $min = $tmpMin - $tmpMax; $max = $tmpMax - $tmpMin; } else { if ( $dataType == "int" ) $max = 100; else $max = 1.0; $min = -$max; } if ( $dataType == "int" ) intSliderGrp -f true -min $min -max $max -fmn $floatMin -fmx $floatMax -v 0 $controlName; else floatSliderGrp -f true -min $min -max $max -fmn $floatMin -fmx $floatMax -v 0 $controlName; setParent ..; } setParent ..; setParent ..; } // The absolute controls are the default for the apply tab, // and the only ones if relativeControls() for this $bdt returns false. proc createAbsoluteControls( string $bdt ) { if ( $bdt == "" ) return; int $id = getId( $bdt ); string $controlName = "bdeAbsoluteFrame" + $id; // bdeChangedValue gets called if any of the 'value' // fields/sliders/radiobuttons get changed (by the user) string $changeCommand = "bdeChangedValue (" + $id + ")"; string $dataTypes[]; int $ranged[]; int $min[]; int $max[]; int $freeSet = getFreeSet( $bdt ); // The main frame for this set of controls frameLayout -cll true -cl false -bv false -lv false $controlName; columnLayout -adj true -rs 6; int $dataCount = getDataCount( $bdt ); for ( $i = 0; $i < $dataCount; $i++ ) { string $attr = getLongName( $bdt, $i ); // $controlName here is the same regardless of the type // of control we're making. $controlName = "bdeDataValue" + $id + "_" + $i; $dataTypes[$i] = getDataType( $bdt, $i ); $ranged[$i] = getRanged( $bdt, $attr ); // For string/binary data, create a textField. if ( $dataTypes[$i] == "string" || $dataTypes[$i] == "binary" ) { rowLayout -nc 2 -cw 1 80 -cw 2 120; text -label $attr; textField -cc $changeCommand $controlName; // Disable the textField if user can't freely set it. // (This prevents the user from entering values that // the game engine doesn't support) if ( !$freeSet ) textField -e -en false $controlName; setParent ..; } // For hex types, we also create a textField. MEL doesn't support // hex data in numeric fields, so we've got to internally convert // and set the data. else if ( $dataTypes[$i] == "hex" ) { rowLayout -nc 2 -cw 1 80 -cw 2 90; text -label $attr; textField -w 90 -tx "0x0000" -cc $changeCommand $controlName; // Again, disable the textField if user can't freely set it if ( !$freeSet ) textField -e -en false $controlName; setParent ..; } // Create a couple of radioButtons for boolean data // (Doesn't make sense to test for 'freeSet' here because data can // only be one of two values regardless) else if ( $dataTypes[$i] == "boolean" ) { rowLayout -nc 2 -cw 1 80 -cw 2 400; text -label $attr; radioButtonGrp -nrb 2 -l1 (uiRes("m_blindDataEditor.kFalse")) -l2 (uiRes("m_blindDataEditor.kTrue")) -cc $changeCommand $controlName; radioButtonGrp -e -sl 1 $controlName; setParent ..; } // If we're here we've got numeric (int or float) data else { // Again, we disable the control if user can't free set data. rowLayout -nc 2 -cw 1 80 -cw 2 400; text -label $attr; // If this attr is ranged, we'll want to // make sliders. if ( $ranged[$i] ) { $min[$i] = getMinVal( $bdt, $attr ); $max[$i] = getMaxVal( $bdt, $attr ); if ( $dataTypes[$i] == "int" ) { intSliderGrp -f true -cc $changeCommand -min $min[$i] -max $max[$i] $controlName; if ( !$freeSet ) intSliderGrp -e -en false $controlName; } else { floatSliderGrp -step .0001 -f true -cc $changeCommand -min $min[$i] -max $max[$i] $controlName; if ( !$freeSet ) floatSliderGrp -e -en false $controlName; } } // Not ranged - just use a numeric field. else { if ( $dataTypes[$i] == "int" ) { intField -cc $changeCommand $controlName; if ( !$freeSet ) intField -e -en false $controlName; } else { floatField -cc $changeCommand $controlName; if ( !$freeSet) floatField -e -en false $controlName; } } setParent ..; } } // If the data looks like it could be construed as color // (i.e. 3 floats, [0,1]), we create a canvas for users to // select values with. string $applyMode = getApplyMode( $bdt ); if ( $applyMode == "asColor" ) { rowLayout -nc 2 -cw 1 80 -cw 2 400; separator -st "none"; string $changeColorCommand = "bdeChangeColorData( " + $id + " )"; $controlName = "bdeColorDataCanvas" + $id; canvas -w 80 -h 25 -pc $changeColorCommand -rgbValue 0 0 0 $controlName; setParent ..; } setParent ..; setParent ..; } // This func deletes all of the children of the // main apply tab. global proc bdeDeleteApplyUI() { string $parent = "bdeSingleApplyLayout"; if ( `tabLayout -q -ex $parent` ) { string $children[] = `tabLayout -q -ca $parent`; for ( $child in $children ) deleteUI -lay $child; } } // This function does the work of rebuilding the UI used for // applying blind data for the blind data template with the given id. // If the id is valid, a columnLayout is created as a child of the // main Apply tab. // It returns the name of the newly created columnLayout, or an empty // string if a layout is not created. global proc string bdeRebuildApplyTab( int $id ) { if ( !idDefined( $id ) ) return ""; string $bdt = getTemplateNameFromId( $id ); if ( $bdt == "" ) return ""; string $controlName; string $firstRadio; string $assocType; string $tag; string $text; string $dataType[]; string $longName[]; int $i, $j; string $applyMode = getApplyMode( $bdt ); // What we call this tab (internally) string $thisTab = "bdeApply" + $id; // The label of this tab. The parent tab (bdeSingleApplyLayout) // does not currently display the tabs of it's child layouts. // If this is to change then this label is useful for accessing the tabs. string $thisTabLabel = getTag( $bdt ); if ( $thisTabLabel == "" ) $thisTabLabel = "" + $id; // Parent this layout underneath the main apply tab setParent bdeSingleApplyLayout; columnLayout -adj true $thisTab; int $dataCount = getDataCount( $bdt ); // Display the name(s) and type for each of the attr's in // the given template. for ( $i = 0; $i < $dataCount; $i++ ) { rowColumnLayout -nc 2 -cw 1 105; text -align "left" -label (uiRes("m_blindDataEditor.kLongName")) ; $controlName = "bdeLongDataName" + $id + "_" + $i; $longName[$i] = getLongName( $bdt, $i ); text -align "left" -label $longName[$i] $controlName; text -align "left" -label (uiRes("m_blindDataEditor.kType")); $controlName = "bdeDataType" + $id + "_" + $i; $dataType[$i] = getDataType( $bdt, $i ); text -align "left" -label `dataType_melToUI($dataType[$i])` $controlName; setParent ..; separator -w 400 -h 8; } $numPresets = getPresetCount( $bdt ); // What gets called if the presets are changed. string $changedCmd = "bdeChangedPreset (" + $id + ")"; // A frame layout for the presets so we can close it to // restrict access. The border is invisible, so user can't collapse. // could set -bv to true if there's too much clutter and presets aren't // always used. $controlName = "bdePresetFrame" + $id; frameLayout -cll true -cl false -lv false -bv false $controlName; string $row = `rowColumnLayout -nc 3`; // Use $applyMode (getApplyMode( $bdt )) to see whether we // should use radioButtons or checkboxes. If any of the data // types are hex we use checkboxes. This may be problematic // if there are multiple attributes and not all are hex. // It's not clear to me how to handle this case. if ( $applyMode != "hex" ) { $controlName = $row + "|radioCollection"; radioCollection $controlName; // We make the first in the collection invisible // so that we can select it to turn all the rest off. $controlName = "bdeNoIndicator" + $id; $firstRadio = `radioButton -vis false -h 1 $controlName`; separator -st "none"; separator -st "none"; } for ( $i = 0; $i < $numPresets; $i++ ) { $controlName = "bdeIndicator" + $id + "_" + $i; if ( $applyMode == "hex" ) checkBox -cc $changedCmd -label "" $controlName; else radioButton -label "" -cc $changedCmd $controlName; $presetName = getPresetName( $bdt, $i ); text -label $presetName; for ( $j = 0; $j < $dataCount; $j++ ) { if ( $j != 0 ) { separator -st "none"; separator -st "none"; } $presetVal = getPresetVal( $bdt, $i, $longName[$j] ); text -label $presetVal; } } setParent ..; setParent ..; if ( $numPresets > 0 ) { columnLayout -adj true; separator -w 325 -h 15; setParent ..; } rowLayout -nc 4 -cw 1 80 -cw 2 90 -cw 3 80 -cw 4 90; text -label (uiRes("m_blindDataEditor.kAssocType")); $controlName = "bdeAssocType" + $id; optionMenu $controlName; menuItem -label `assocType_melToUI "face"`; menuItem -label `assocType_melToUI "vertex"`; // BlindDataTemplate supports edge types, but it doesn't seem too many // people use edges for blind data (and we can't false color edges!). // Easy enough to comment this out, however, and should work, or if not, // minor changes should be involved (to assign and query the data at least) // menuItem -label `assocType_melToUI "edge"`; // VertexFace blind data is not fully supported in Maya right now // menuItem -label `assocType_melToUI "vertexFace"`; menuItem -label `assocType_melToUI "object"`; $assocType = getAssocType( $bdt ); // This return "Mel" version // It could be that $assocType is empty, // if this template wasn't set up through the type editor if ( $assocType == "" ) $assocType = "any"; if ( $assocType != "any") { optionMenu -e -v `assocType_melToUI $assocType` -en false $controlName; } text -label (uiRes("m_blindDataEditor.kApplyType")); string $cmd = "bdeChangeApplyType (" + $id + ")"; $controlName = "bdeApplyType" + $id; optionMenu -cc $cmd $controlName; menuItem -label (uiRes("m_blindDataEditor.kAbsolute")); menuItem -label (uiRes("m_blindDataEditor.kOffset")); menuItem -label (uiRes("m_blindDataEditor.kScale")); // We just disable the optionMenu (set at the default value // of "Absolute") if `relativeControls` == false. if ( !relativeControls( $bdt ) ) optionMenu -e -en false $controlName; setParent ..; separator -w 400 -h 8; createAbsoluteControls( $bdt ); // Should really check if relativeControls is true here // before creating all the controls. Creating UI is not a real // fast process. However, some changes to at least bdeChangeApplyType // (to check if the frames exist, etc.) would have to be made in this case, // It's too late to make these changes. createOffsetControls( $bdt ); createScaleControls( $bdt ); // Call this to set the proper frame collapse settings, etc. bdeChangeApplyType( $id ); setParent ..; // This tab tabLayout -e -tabLabel $thisTab $thisTabLabel bdeSingleApplyLayout; return $thisTab; } // This function checks the current apply selection, // (re)builds the layout if necessary, and sets the // main apply tab (bdeSingleApplyLayout) to have this // layout as it's 'selected tab' (visible). global proc bdeRebuildApply() { string $mainLayout = "bdeMainColumnLayout"; string $bdt = getCurrentApplyTemplate(); if ( $bdt == "" ) return; int $id = getId( $bdt ); string $tab = getApplyTab( $id ); if ( $tab == "" ) $tab = bdeRebuildApplyTab( $id ); tabLayout -e -st $tab bdeSingleApplyLayout; } // There are two text scroll lists - one in the apply tab and // one in the type editor tab. These lists are present so that // the whole gamut of blind data templates are available in one // control and can be fairly quickly selected. // We create the entries to look like // tag (#) // if a tag exists (and # indicates the numeric id) or just // # // if there is no tag for a template. global proc bdeRebuildTextScrollLists() { string $cmd, $cmdName; string $tag; string $item; string $blindDataTag[]; string $blindDataId[]; string $lists[] = { "bdeTypeList", "bdeTemplateList" }; // Bug 150384 check exact type so we don't get subd blind data string $nodes[] = `ls -exactType blindDataTemplate`; for ( $i = 0; $i < size( $nodes ); $i++ ) { $blindDataId[$i] = getId( $nodes[$i] ); $blindDataTag[$i] = getTag( $nodes[$i] ); } $cmd = "textScrollList -e"; for ( $i = 0; $i < size( $nodes ); $i++ ) { if ( $blindDataTag[$i] != "" ) $tag = $blindDataTag[$i] + " (" + $blindDataId[$i] + ")"; else $tag = $blindDataId[$i]; $cmd += " -append \""; $cmd += $tag + "\""; } for ( $list in $lists ) { if ( `textScrollList -q -ex $list` ) { textScrollList -e -removeAll $list; $cmdName = $cmd + " " + $list; eval( $cmdName ); } } } // Note that the passed in $layout here should not be the whole // Qc layout, but "$layout|multiList" or the whole row will get // axed. // The frameLayout should be collapsed or we'll get flicker! global proc bdeQcDeleteMultiList( string $layout ) { string $children[] = `frameLayout -q -ca $layout`; for ( $child in $children ) { deleteUI -lay $child; } } // Build the layout for the multi. // We create and delete it each time to ease the // case of switching to a new type that isn't a multi // or has a different number of attrs. // Returns 1 if the layout was built, 0 if not. global proc int bdeQcBuildMultiList( string $parent ) { string $controlName; string $longName; string $layout = $parent + "|multiList"; string $bdt = getQcSelectedBdt( $parent ); if ( $bdt == "" ) return 0; bdeQcDeleteMultiList( $layout ); int $dataCount = getDataCount( $bdt ); if ( $dataCount > 1 ) { setParent $layout; // We create a columnLayout, and then create a // rowLayout for each attribute to ease the ability // to access the controls. // Have to have the columnLayout because the parent's a // frameLayout, which can only have one child. columnLayout dataLayout; for ( $i = 1; $i < $dataCount; $i++ ) { $controlName = "rowLayout" + $i; rowLayout -ut bdeQcMainLineTemplate $controlName; // Would be faster and more efficient to have these // row layouts be templated to be the right sizes and // not use these separators, but i didn't have time to // get the right values. // Using the separators is slower, but ensures that everything // is correctly aligned. separator -st "none"; separator -st "none"; separator -st "none"; $longName = getLongName( $bdt, $i ); text -label $longName longName; textField -w 90 -cc ( "bdeQcChangedValue \"" + $parent + "\"" ) value; separator -st "none"; setParent ..; } setParent ..; return 1; } else return 0; } // This func determines whether the canvas on the given qc line // should be disabled (and blacked out). If so, it stores the old // color in the invisible 'saveCanvas', blacks out the color, and // disables the canvas. // The canvas is blacked and disabled if the template exists and // the value type is set to continuous or asColor. global proc bdeQcDoColorSwap( string $parent ) { global string $gBdeContinuousName; global string $gBdeAsColorName; string $mainLine = $parent + "|mainLine"; string $form = $parent + "|valueLayout|valueForm"; string $mainCanvas = $mainLine + "|canvas"; string $saveCanvas = $parent + "|valueLayout|valueForm|valueTypeLayout|saveColor"; float $noColor[] = { 0, 0, 0 }; string $bdt = getQcSelectedBdt( $parent ); $control = $mainLine + "|valueEnable"; int $valueEnabled = `checkBox -q -v $control`; int $disableIt; if ( $bdt == "" || !$valueEnabled ) $disableIt = false; else { string $om = $form + "|valueTypeLayout|valueType"; string $selectType = `optionMenu -q -v $om`; if ( $selectType == $gBdeContinuousName || $selectType == $gBdeAsColorName ) $disableIt = true; else $disableIt = false; } if ( $disableIt ) { // It may have been disabled already. In this case, we don't want to // save the black color. canvas -e -pc "" $mainCanvas; float $col[] = `canvas -query -rgbValue $mainCanvas`; canvas -edit -rgbValue $noColor[0] $noColor[1] $noColor[2] $mainCanvas; if ( !colorsEquivalent( $noColor, $col, 0.001 ) ) { canvas -edit -rgbValue $col[0] $col[1] $col[2] $saveCanvas; } } else { canvas -e -pc ( "bdeChangeCanvas \"" + $parent + "\"" ) $mainCanvas; float $col[] = `canvas -query -rgbValue $saveCanvas`; canvas -edit -rgbValue $col[0] $col[1] $col[2] $mainCanvas; } } global proc string bdeQcCGetTab( string $selectType ) { global string $gBdeDiscreteValName; global string $gBdeDiscreteRangeName; global string $gBdeHexValName; global string $gBdeContinuousName; global string $gBdeAsColorName; string $desiredTab = "chooser"; if ( $selectType == $gBdeDiscreteValName ) $desiredTab += "DV"; else if ( $selectType == $gBdeDiscreteRangeName ) $desiredTab += "DR"; else if ( $selectType == $gBdeHexValName ) $desiredTab += "U"; else if ( $selectType == $gBdeContinuousName ) $desiredTab += "C"; else if ( $selectType == $gBdeAsColorName) $desiredTab += "AC"; return $desiredTab; } // Called automatically if the user changes one of the values. // If this is the case the presets are turned off. global proc bdeQcChangedValue( string $parent ) { global string $gBdeDiscreteValName; global string $gBdeHexValName; string $mainLine = $parent + "|mainLine"; string $form = $parent + "|valueLayout|valueForm"; string $tab = $form + "|valueChooser"; string $om = $form + "|valueTypeLayout|valueType"; string $bdt = getQcSelectedBdt( $parent ); if ( $bdt == "" ) return; string $value; string $selectType = `optionMenu -q -v $om`; string $thisLayout = bdeQcCGetTab( $selectType ); if ( $selectType == $gBdeDiscreteValName ) { string $layout = $tab + "|" + $thisLayout + "|dvLayout"; $control = $layout + "|qccNoIndicator"; radioButton -e -sl $control; } else if ( $selectType == $gBdeHexValName ) { string $layout = $tab + "|" + $thisLayout + "|uLayout|uDataLayout"; int $numPresets = getPresetCount( $bdt ); for ( $i = 0; $i < $numPresets; $i++ ) { $control = $layout + "|qccIndicator" + $i; checkBox -e -v 0 $control; } } } // Set the value of the given row for the given index. // This gets called by changing the preset, using the // value chooser, etc. global proc bdeQcSetValue( string $parent, int $index, string $value ) { string $mainLine = $parent + "|mainLine"; if ( $index == 0 ) { $control = $mainLine + "|value"; textField -e -tx $value $control; } else { string $layout = $parent + "|multiList|dataLayout|rowLayout" + $index; if ( `rowLayout -q -ex $layout` ) { $control = $layout + "|value"; textField -e -tx $value $control; } } } // This sets up the value fields for the given qc row with // the values from the value chooser frame (ranged data, // presets, continuous, etc.) global proc bdeSetQcValues( string $parent ) { global string $gBdeDiscreteValName; global string $gBdeDiscreteRangeName; global string $gBdeHexValName; global string $gBdeContinuousName; global string $gBdeAsColorName; string $mainLine = $parent + "|mainLine"; string $form = $parent + "|valueLayout|valueForm"; string $tab = $form + "|valueChooser"; string $om = $form + "|valueTypeLayout|valueType"; string $bdt = getQcSelectedBdt( $parent ); if ( $bdt == "" ) return; int $dataCount = getDataCount( $bdt ); int $numTags; string $value; string $selectType = `optionMenu -q -v $om`; string $thisLayout = bdeQcCGetTab( $selectType ); // Discrete value just puts the values corresponding // to the selected (if any) preset into the value fields. if ( $selectType == $gBdeDiscreteValName ) { string $layout = $tab + "|" + $thisLayout + "|dvLayout"; for ( $j = 0; $j < $dataCount; $j++ ) bdeQcSetValue( $parent, $j, "" ); $numPresets = getPresetCount( $bdt ); for ( $i = 0; $i < $numPresets; $i++ ) { $preset = getPresetName( $bdt, $i ); $control = $layout + "|qccIndicator" + $i; if ( `radioButton -q -sl $control` ) { for ( $j = 0; $j < $dataCount; $j++ ) { $control = $layout + "|qccText" + $i + $j; $value = `text -q -label $control`; bdeQcSetValue( $parent, $j, $value ); } } } } // Discrete range checks the use min and use max fields // and the numeric fields, and the value fields are filled // with text which looks like // [x,y], where x/y are either the min/max values or * if // useMin/Max is turned off else if ( $selectType == $gBdeDiscreteRangeName ) { string $layout = $tab + "|" + $thisLayout + "|drLayout"; for ( $i = 0; $i < $dataCount; $i++ ) { string $row = $layout + "|rowLayout" + $i; $value = "["; $control = $row + "|useMin"; $dataType = getDataType( $bdt, $i ); if ( `checkBox -q -v $control` ) { $control = $row + "|minVal"; if ( $dataType == "int" ) { $value += `intField -q -v $control`; intField -e -en true $control; } else { $value += `floatField -q -v $control`; floatField -e -en true $control; } } else { $control = $row + "|minVal"; if ( $dataType == "int" ) intField -e -en false $control; else floatField -e -en false $control; $value += "*"; } $value += ","; $control = $row + "|useMax"; if ( `checkBox -q -v $control` ) { $control = $row + "|maxVal"; if ( $dataType == "int" ) { $value += `intField -q -v $control`; intField -e -en true $control; } else { $value += `floatField -q -v $control`; floatField -e -en true $control; } } else { $control = $row + "|maxVal"; if ( $dataType == "int" ) intField -e -en false $control; else floatField -e -en false $control; $value += "*"; } $value += "]"; bdeQcSetValue( $parent, $i, $value ); } } // Hex values check what setting is selected, and prepends // the appropriate &* string to the value, followed by the // resulting | of all the selected presets. else if ( $selectType == $gBdeHexValName ) { string $layout = $tab + "|" + $thisLayout + "|uLayout"; $control = $layout + "|hexTypeMenu"; string $uiType = `optionMenu -q -v $control`; if($uiType == (uiRes("m_blindDataEditor.kMenuSet"))) { $value = "&| "; } else if($uiType == (uiRes("m_blindDataEditor.kMenuNotSet"))) { $value = "&~ "; } else if($uiType == (uiRes("m_blindDataEditor.kMenuEqual"))) { $value = "&= "; } string $dataValue[]; for ( $i = 0; $i < $dataCount; $i++ ) $dataValue[$i] = "0x0000"; string $dataLayout = $layout + "|uDataLayout"; $numPresets = getPresetCount( $bdt ); for ( $i = 0; $i < $numPresets; $i++ ) { $preset = getPresetName( $bdt, $i ); $control = $dataLayout + "|qccIndicator" + $i; if ( `checkBox -q -v $control` ) { for ( $j = 0; $j < $dataCount; $j++ ) { string $attr = getLongName( $bdt, $j ); string $value = getPresetVal( $bdt, $i, $attr ); $control = $dataLayout + "|qccText" + $i + $j; string $dataString = `text -q -label $control`; $dataValue[$j] = `orHexString $dataValue[$j] $dataString`; } } } for ( $i = 0; $i < $dataCount; $i++ ) { string $newVal = $value + $dataValue[$i]; bdeQcSetValue( $parent, $i, $newVal ); } } // For continuous types, only a "%" is entered in the // value fields, and the min and max colors and values are // checked on the query/color action. // The min and max value fields are set here according to // how the data is set up (with the ranges if they are set, // otherwise [0,1] for double data, [0,100] for int data. else if ( $selectType == $gBdeContinuousName ) { float $min, $max; for ( $i = 0; $i < $dataCount; $i++ ) { string $layout = $tab + "|" + $thisLayout + "|cLayout" + $i; bdeQcSetValue( $parent, $i, "%" ); string $attr = getLongName( $bdt, $i ); $dataType = getDataType( $bdt, $i ); $ranged = getRanged( $bdt, $attr ); if ( $ranged ) { $min = getMinVal( $bdt, $attr ); $max = getMaxVal( $bdt, $attr ); } else { $min = 0; if ( $dataType == "int" ) $max = 100; else $max = 1; } $minControl = $layout + "|minValue"; $maxControl = $layout + "|maxValue"; if ( $dataType == "int" ) { intField -e -v $min $minControl; intField -e -v $max $maxControl; } else { floatField -e -v $min $minControl; floatField -e -v $max $maxControl; } } } // As color simply puts an "@" into all the fields, // and the data itself is then used for color actions. else if ( $selectType == $gBdeAsColorName) { for ( $i = 0; $i < $dataCount; $i++ ) { bdeQcSetValue( $parent, $i, "@" ); } } } // This clears out all of the 'value chooser' UI for the // given Qc row. global proc bdeQcCDeleteTabs( string $parent ) { global string $gBdeDiscreteValName; global string $gBdeDiscreteRangeName; global string $gBdeHexValName; global string $gBdeContinuousName; global string $gBdeAsColorName; string $frame = $parent + "|valueLayout"; string $layout = $frame + "|valueForm|valueChooser"; frameLayout -e -cl true $frame; string $names[] = { $gBdeDiscreteValName, $gBdeDiscreteRangeName, $gBdeHexValName, $gBdeContinuousName, $gBdeAsColorName }; for ( $name in $names ) { string $tab = bdeQcCGetTab( $name ); string $thisLayout = $layout + "|" + $tab; if ( `columnLayout -q -ex $thisLayout` ) { deleteUI -lay $tab; } } } // This function gets called when the value enable is turned // on or when the value chooser type optionMenu changes // If $setValues is true (1), the value fields will get set // with the state of the controls global proc bdeQcOpenValueTab( string $parent, int $setValues ) { global string $gBdeDiscreteValName; global string $gBdeDiscreteRangeName; global string $gBdeHexValName; global string $gBdeContinuousName; global string $gBdeAsColorName; string $mainLine = $parent + "|mainLine"; string $form = $parent + "|valueLayout|valueForm"; string $tab = $form + "|valueChooser"; string $om = $form + "|valueTypeLayout|valueType"; string $selectType = `optionMenu -q -v $om`; string $desiredTab = bdeQcCGetTab( $selectType ); bdeQcDoColorSwap( $parent ); string $children[] = `tabLayout -q -ca $tab`; for ( $child in $children ) { if ( $child == $desiredTab ) { tabLayout -e -st $child $tab; bdeSetQcValues( $parent ); return; } } string $bdt = getQcSelectedBdt( $parent ); if ( $bdt == "" ) return; int $dataCount = getDataCount( $bdt ); int $numTags; string $changeCommand = "bdeSetQcValues \"" + $parent + "\""; setParent $tab; columnLayout $desiredTab; // Create a set of radioButtons for the presets, together with // the name of the presets and the values. // For hex data, the 'hex' option should be used. if ( $selectType == $gBdeDiscreteValName ) { string $row = `rowColumnLayout -nc 2 dvLayout`; $control = $row + "|radioCollection"; radioCollection $control; radioButton -h 1 -vis false qccNoIndicator; separator -h 1 -st "none"; $numPresets = getPresetCount( $bdt ); for ( $i = 0; $i < $numPresets; $i++ ) { $preset = getPresetName( $bdt, $i); $control = "qccIndicator" + $i; radioButton -label $preset -cc $changeCommand $control; for ( $j = 0; $j < $dataCount; $j++ ) { string $attr = getLongName( $bdt, $j ); if ( $j != 0 ) separator -st "none"; string $value = getPresetVal( $bdt, $i, $attr ); $control = "qccText" + $i + $j; text -label $value $control; } } setParent ..; } // Discrete range creates a 'useMin' checkbox, a min numeric field, // a max numeric field, and a useMax checkbox for each of the // attrs for the selected blind data template (each attr can be // range-queried/colored separately) else if ( $selectType == $gBdeDiscreteRangeName ) { columnLayout -adj true drLayout; for ( $i = 0; $i < $dataCount; $i++ ) { string $name = getLongName( $bdt, $i ); text -label $name; $layout = "rowLayout" + $i; rowLayout -nc 5 -cw 1 25 -cw 2 75 -cw 3 85 -cw 4 75 -cw 5 25 $layout; checkBox -label "" -v 1 -cc $changeCommand useMin; float $min, $max; $dataType = getDataType( $bdt, $i ); $ranged = getRanged( $bdt, $name ); if ( $ranged ) { $min = getMinVal( $bdt, $name ); $max = getMaxVal( $bdt, $name ); } else { $min = 0; if ( $dataType == "int" ) $max = 100; else $max = 1; } if ( $dataType == "int" ) intField -w 70 -v $min -cc $changeCommand minVal; else floatField -w 70 -v $min -cc $changeCommand minVal; text -label (uiRes("m_blindDataEditor.kArrowValue")); if ( $dataType == "int" ) { intField -w 70 -v $max -cc $changeCommand maxVal; } else { floatField -w 70 -v $max -cc $changeCommand maxVal; } checkBox -label "" -v 1 -cc $changeCommand useMax; setParent ..; } setParent ..; } // Hex layout has an optionMenu for the 'Compare type' as well as // checkboxes for each of the presets. else if ( $selectType == $gBdeHexValName ) { columnLayout uLayout; optionMenu -label (uiRes("m_blindDataEditor.kCompareType")) -cc $changeCommand hexTypeMenu; menuItem -label (uiRes("m_blindDataEditor.kMenuSet")); menuItem -label (uiRes("m_blindDataEditor.kMenuNotSet")); menuItem -label (uiRes("m_blindDataEditor.kMenuEqual")); separator -h 10 -st "none"; rowColumnLayout -nc 2 uDataLayout; $numPresets = getPresetCount( $bdt ); for ( $i = 0; $i < $numPresets; $i++ ) { $preset = getPresetName( $bdt, $i ); $control = "qccIndicator" + $i; checkBox -label $preset -cc $changeCommand $control; for ( $j = 0; $j < $dataCount; $j++ ) { string $name = getLongName( $bdt, $j ); if ( $j != 0 ) separator -st "none"; string $value = getPresetVal( $bdt, $i, $name ); $control = "qccText" + $i + $j; text -label $value $control; } } setParent ..; setParent ..; } // For each of the attributes a min color slider, min numeric field, // max color slider, and max numeric field are created. // If there is only one attribute, the min color defaults to a dark gray // (i found with black the low end values all looked too close together) // and the max color defaults to white. If there are more, the max color for // the first is red, the max for the second is green, and the max for the // third is blue. So you can track the different attrs on different color // axes. This probably won't make much sense for most cases, but you never // know (and it made sense programmatically to do it this way...) else if ( $selectType == $gBdeContinuousName ) { string $dataType; float $maxR[] = { 1, 0, 0 }; float $maxG[] = { 0, 1, 0 }; float $maxB[] = { 0, 0, 1 }; for ( $i = 0; $i < $dataCount; $i++ ) { $dataType = getDataType( $bdt, $i ); $name = getLongName( $bdt, $i ); text -label $name; $control = "cLayout" + $i; rowColumnLayout -ut bdeQcColorTemplate $control; text -label (uiRes("m_blindDataEditor.kMinimum")); colorSliderGrp -rgb .25 .25 .25 minColor; if ( $dataType == "int" ) intField minValue; else floatField minValue; text -label (uiRes("m_blindDataEditor.kMaximum")); if ( $dataCount == 1 ) colorSliderGrp -rgb 1 1 1 maxColor; else colorSliderGrp -rgb $maxR[$i] $maxG[$i] $maxB[$i] maxColor; if ( $dataType == "int" ) intField maxValue; else floatField maxValue; setParent ..; if ( $i != $dataCount-1 ) separator -w 400 -h 8; } setParent ..; } // We're using the blind data itself as the criterion, so there's // nothing to do for asColor. else if ( $selectType == $gBdeAsColorName) { } if ( $setValues ) bdeSetQcValues( $parent ); // Select the desired tab. The valueChooser is a tabLayout with // invisible tabs, so we can switch between different value chooser // types without rebuilding the layouts if they've been built already, // and we also keep the values set up by the user for the old layouts. tabLayout -e -st $desiredTab $tab; } // Create the valueChooser frame and try to guess which chooser type they'd // want to use based on how the data for this template looks. global proc bdeQcOpenValueChooser( string $parent ) { global string $gBdeDiscreteValName; global string $gBdeDiscreteRangeName; global string $gBdeHexValName; global string $gBdeContinuousName; global string $gBdeAsColorName; string $mainLine = $parent + "|mainLine"; string $frame = $parent + "|valueLayout"; string $om = $frame + "|valueForm|valueTypeLayout|valueType"; string $control = $mainLine + "|valueEnable"; if ( !`checkBox -q -v $control` ) { frameLayout -e -cl true -lv false -bv false $frame; return; } string $bdt = getQcSelectedBdt( $parent ); if ( $bdt == "" ) { frameLayout -e -cl true -lv false -bf false $frame; return; } string $dataType = getDataType( $bdt, 0 ); // If first data type is one of these, really only discrete val makes sense if ( $dataType == "string" || $dataType == "binary" || $dataType == "boolean" ) { optionMenu -e -v $gBdeDiscreteValName $om; } else if ( $dataType == "hex" ) { optionMenu -e -v $gBdeHexValName $om; } else { // We've got numeric data. If there's no free set, it's probably // an enum type, so we give them discrete val with it's presets. // Otherwise, we give them discrete range if the data's ranged, // and discrete val if not. // It's not hard for the user to change this, but it's also not // hard to change this script so that the initial behaviour is // different. int $freeSet = getFreeSet( $bdt ); if ( !$freeSet ) { optionMenu -e -v $gBdeDiscreteValName $om; } else { $name = getLongName( $bdt, 0 ); if ( getRanged( $bdt, $name ) ) { optionMenu -e -v $gBdeContinuousName $om; } else { optionMenu -e -v $gBdeDiscreteValName $om; } } } // Set the values fields, etc. bdeQcOpenValueTab( $parent, 1 ); // Open it up. frameLayout -e -bv true -cl false -lv true $frame; } // This gets called when the type is changed for the given Qc row. // It adds the (initially almost empty) chooser layout. After this // call, the valueTypeLayout just has the optionMenu for selecting the // value type and the invisible saveColor. The rest of the stuff gets // added if and when the user decides he's going to use the value data. // It restricts what value types are available for the selected type // based on the data in that template. // Edit this function if you need to get at some of the value types // for your particular data and they aren't available. global proc bdeQcSetSelectOptions( string $parent ) { global string $gBdeDiscreteValName; global string $gBdeDiscreteRangeName; global string $gBdeHexValName; global string $gBdeContinuousName; global string $gBdeAsColorName; string $bdt = getQcSelectedBdt( $parent ); if ( $bdt == "" ) return; int $dataCount = getDataCount( $bdt ); string $dataType = getDataType( $bdt, 0 ); string $form = $parent + "|valueLayout|valueForm"; setParent $form; string $layout = $form + "|valueTypeLayout"; if ( `columnLayout -q -ex $layout` ) deleteUI -lay $layout; columnLayout -adj true valueTypeLayout; optionMenu -cc ( "bdeQcOpenValueTab ( \"" + $parent + "\", 1 )" ) valueType; // This is the only thing a user can select for these data types. if ( $dataType == "string" || $dataType == "binary" || $dataType == "boolean" ) { menuItem -label $gBdeDiscreteValName; } // Discrete range doesn't make a lot of sense for hex data, but we'll // let them choose it if they want else if ( $dataType == "hex" ) { menuItem -label $gBdeDiscreteValName; menuItem -label $gBdeDiscreteRangeName; menuItem -label $gBdeHexValName; } else { menuItem -label $gBdeDiscreteValName; menuItem -label $gBdeDiscreteRangeName; // Probably only makes sense if $dataCount == 1, but // we'll let them try to make some sense of the 2-3 axis // color data if they want if ( $dataCount <= 3 ) menuItem -label $gBdeContinuousName; // If there are three fields, as color maybe makes sense // If they're not floats ranged [0,1] other modifications // will have to be made, but not hard to convert from int // [0,255] fields to float [0,1] fields when the color action // happens. if ( $dataCount == 3 ) menuItem -label $gBdeAsColorName; } // Create the invisible saveColor canvas and initialize it // with the color from the main canvas. $control = $parent + "|mainLine|canvas"; float $col[] = `canvas -query -rgbValue $control`; canvas -visible false -height 1 -rgbValue $col[0] $col[1] $col[2] saveColor; setParent ..; // Make the form look right. formLayout -e -af valueTypeLayout "top" 5 -af valueTypeLayout "left" 5 -an valueTypeLayout "right" -an valueTypeLayout "bottom" -af valueChooser "top" 0 -af valueChooser "right" 0 -ac valueChooser "left" 5 valueTypeLayout -af valueChooser "bottom" 0 $form; } // Called when the type for a particular qc row changes. // This can be done either through popup menu on the type field, // typing in the type field, or when the editor is first opened or // torn off (and saved prefs fill in the types) global proc bdeQcChangeType( string $parent ) { string $mainLine = $parent + "|mainLine"; string $layoutName; string $bdt = getQcSelectedBdt( $parent ); // Delete the multi list (which may not be full, but that's ok too) // We'll rebuild it later if value enable is checked. $layoutName = $parent + "|multiList"; frameLayout -e -cl true $layoutName; bdeQcDeleteMultiList( $layoutName ); // These may not exist either, but better chuck them out if they do // (or there'll be lots of them when type keeps changing) bdeQcCDeleteTabs( $parent ); // No type for this one -- disable or blank out everything if ( $bdt == "" ) { $controlName = $mainLine + "|type"; textField -e -tx "" $controlName; $controlName = $mainLine + "|enable"; checkBox -e -v 0 $controlName; $controlName = $mainLine + "|valueEnable"; checkBox -e -v 0 -en false $controlName; $controlName = $mainLine + "|longName"; text -e -label "" $controlName; // We only have to blank out the first value as the multi's been nixed bdeQcSetValue( $parent, 0, "" ); } else { // Turn on the row enable (since they've selected it they probably // want to use it) $controlName = $mainLine + "|enable"; checkBox -e -v 1 $controlName; // Turn off the value enable (they've just selected this one, so // we'll assume to start that they want to do a binary on it) $controlName = $mainLine + "|valueEnable"; checkBox -e -en true -v 0 $controlName; // Blank the name (it's not what it was, maybe) $controlName = $mainLine + "|longName"; text -e -label "" $controlName; // Blank all the values int $dataCount = getDataCount ( $bdt ); for ( $i = 0; $i < $dataCount; $i++ ) bdeQcSetValue( $parent, $i, "" ); // Do some setup for the future bdeQcSetSelectOptions( $parent ); } // Not sure that this call is necessary... bdeQcOpenValueChooser( $parent ); // Save colors bdeQcDoColorSwap( $parent ); } // Called when the user changes the 'value Enable' checkbox. global proc bdeQcChangeValueEnable( string $parent ) { string $mainLine = $parent + "|mainLine"; string $controlName = $mainLine + "|valueEnable"; int $enabled = `checkBox -q -v $controlName`; // They turned it on. So we fill in the name, // build the multi and open it up. if ( $enabled ) { string $bdt = getQcSelectedBdt( $parent ); if ( $bdt == "" ) { error( (uiRes("m_blindDataEditor.kChangeValueEnable")) ); return; } $controlName = $mainLine + "|longName"; string $longName = getLongName( $bdt, 0 ); text -e -label $longName $controlName; int $dataCount = getDataCount( $bdt ); if ( $dataCount > 1 ) { bdeQcBuildMultiList( $parent ); $layoutName = $parent + "|multiList"; frameLayout -e -cl false $layoutName; } } // Turned it off. Blank the name and values, // close the multi. else { $controlName = $mainLine + "|longName"; text -e -label "" $controlName; $controlName = $mainLine + "|value"; textField -e -tx "" $controlName; $layoutName = $parent + "|multiList"; frameLayout -e -cl true $layoutName; } bdeQcOpenValueChooser( $parent ); bdeQcDoColorSwap( $parent ); } // Called automatically when the type popup is used for a // query color row. Fills the typeField and then calls bdeQcChangeType // which blanks out other stuff, etc. global proc bdeChangedQcPopup( string $layout, int $id ) { string $bdt = getTemplateNameFromId( $id ); if ( $bdt == "" ) return; string $tag = getTag( $bdt ); string $control = $layout + "|mainLine|type"; if ( $tag != "" ) textField -e -tx $tag $control; else textField -e -tx $id $control; bdeQcChangeType( $layout ); } // Create the type popup for the given qc row // based on what templates exist in the scene. global proc bdeAddQcPopup( string $layout ) { string $command; // Bug 150384 check exact type so we don't get subd blind data string $nodes[] = `ls -exactType blindDataTemplate`; string $blindDataTags[]; int $blindDataIds[]; string $menuItem; string $control = $layout + "|mainLine|type"; popupMenu -aob false -mm false -parent $control typePopup; for ( $i = 0; $i < size( $nodes ); $i++ ) { $blindDataTags[$i] = getTag( $nodes[$i] ); $blindDataIds[$i] = getId( $nodes[$i] ); if ( $blindDataTags[$i] != "" ) $menuItem = $blindDataTags[$i]; else $menuItem = $blindDataIds[$i]; $command = "bdeChangedQcPopup ( \"" + $layout + "\", " + $blindDataIds[$i] + " )"; menuItem -c $command -label $menuItem; } } // If the scene changes, we rebuild all of the popups to reflect // what's in the scene. global proc bdeRebuildPopups() { global string $gBdeQueryColorLayout; if ( `columnLayout -q -ex $gBdeQueryColorLayout` ) { string $children[] = `columnLayout -q -ca $gBdeQueryColorLayout`; for ( $child in $children ) { $layout = $gBdeQueryColorLayout + "|" + $child; $control = $layout + "|mainLine|type|typePopup"; if ( `popupMenu -q -ex $control` ) deleteUI $control; bdeAddQcPopup( $layout ); } } } // Build and add a row to the query/color layout. global proc string bdeAddQueryColorRow( string $parent ) { setParent $parent; // Bug 150384 check exact type so we don't get subd blind data string $nodes[] = `ls -exactType blindDataTemplate`; string $blindDataTags[]; int $blindDataIds[]; string $menuItem[]; for ( $i = 0; $i < size( $nodes ); $i++ ) { $blindDataTags[$i] = getTag( $nodes[$i] ); $blindDataIds[$i] = getId( $nodes[$i] ); if ( $blindDataTags[$i] != "" ) $menuItem[$i] = $blindDataTags[$i]; else $menuItem[$i] = $blindDataIds[$i]; } // This $layout var is how we reference this row. // All qc controls are children/grandchildren/etc. of // this columnLayout. string $layout = `columnLayout -adj true`; // mainLine has the stuff you initially see // (enable box, type field, value enable box, type name, // value field, delete button) rowLayout -ut bdeQcMainLineTemplate mainLine; checkBox -w 20 -label "" enable; textField -w 100 -en true -cc ( "bdeQcChangeType (\"" + $layout + "\")" ) type; bdeAddQcPopup( $layout ); checkBox -w 20 -label "" -en false -cc ( "bdeQcChangeValueEnable \"" + $layout + "\"" ) valueEnable; text -w 60 -label "" longName; textField -w 90 -en true -cc ( "bdeQcChangedValue \"" + $layout + "\"" ) value; separator -st "none"; float $c[] = `bdeGetUniqueColor`; canvas -rgbValue $c[0] $c[1] $c[2] -pc ( "bdeChangeCanvas \"" + $layout + "\"" ) -w 70 -h 25 canvas; button -label (uiRes("m_blindDataEditor.kDelete")) -c ( "bdeQcDeleteRow \"" + $layout + "\"" ); setParent ..; // This one's for multi's // It's empty initially, gets children if necessary frameLayout -cll true -cl true -lv false -bv false multiList; setParent ..; // For space only separator -h 5 -style "none"; // The value layout, initially mostly empty. frameLayout -cll true -cl true -lv false -bv false -label (uiRes("m_blindDataEditor.kSelectValue")) valueLayout; string $form = `formLayout valueForm`; // I had to set the dimensions manually because previously // switching the tabs to a larger one didn't expand the tab. // It's scrollable, so if it goes bigger than the fairly // big dimensions, you can scroll to the rest of the values. tabLayout -iv false -tv false -scr true -cr false valueChooser; setParent ..; setParent ..; setParent ..; separator -h 5 -style "none"; setParent ..; return $layout; } // Gets an empty row for the main qc layout, or, if none exists, // creates a new one. // The name of the layout created or found is returned. proc string getEmptyQcRow() { global string $gBdeQueryColorLayout; if ( `columnLayout -q -ex $gBdeQueryColorLayout` ) { string $children[] = `columnLayout -q -ca $gBdeQueryColorLayout`; for ( $child in $children ) { $layout = $gBdeQueryColorLayout + "|" + $child; $type = getQcType( $layout ); if ( $type == "" ) return $layout; } } return bdeAddQueryColorRow( $gBdeQueryColorLayout ); } // Delete all the rows and build 5 new ones. // This typically gets called on file/new or file/open. global proc bdeRebuildQueryColor() { global string $gBdeQueryColorLayout; if ( `columnLayout -q -ex $gBdeQueryColorLayout` ) { string $children[] = `columnLayout -q -ca $gBdeQueryColorLayout`; for ( $child in $children ) deleteUI -lay $child; // INITIAL NUMBER OF ROWS HERE for ( $i = 0; $i < 5; $i++ ) bdeAddQueryColorRow( $gBdeQueryColorLayout ); } } // Called when you press the 'New' button on the qc tab. global proc bdeNewQcRow() { global string $gBdeQueryColorLayout; bdeAddQueryColorRow( $gBdeQueryColorLayout ); } // Called when you press the delete button on the qc row. global proc bdeQcDeleteRow( string $layout ) { deleteUI -lay $layout; } // This function to determine whether or not the // color/query can work with all of the selected qc rows // The numbers don't have internal meaning - they just have // to be distinct. proc int compatibleMode( int $mode ) { global int $gBdeBinaryMode; global int $gBdeContinuousMode; global int $gBdeAsColorMode; // Can't use variables in a switch switch ( $mode ) { // binary mode case 0: return 0; // Continuous mode case 6: return 2; // as color mode case 7: return 3; // Otherwise the data is discretely ranged or valued. default: return 1; } } // Look at the value and datatype and determine what mode it is proc int parseValueForMode( string $value, string $dataType ) { global int $gBdeDiscreteValueMode; global int $gBdeDiscreteRangeMode; global int $gBdeHexSetMode; global int $gBdeHexNotSetMode; global int $gBdeHexEqualMode; global int $gBdeContinuousMode; global int $gBdeAsColorMode; string $char = `getChar $value 1`; if ( $dataType == "string" || $dataType == "binary" || $dataType == "boolean" ) { return $gBdeDiscreteValueMode; } if ( $char == "@" ) { return $gBdeAsColorMode; } if ( $char == "%" ) { return $gBdeContinuousMode; } if ( $char == "[" ) return $gBdeDiscreteRangeMode; if ( $dataType == "hex" ) { int $length = `size $value`; string $token = `substring $value 1 2`; string $val = `substring $value 4 $length`; if ( $token == "&|" ) return $gBdeHexSetMode; else if ( $token == "&~" ) return $gBdeHexNotSetMode; else if ( $token == "&=" ) return $gBdeHexEqualMode; else // Default: return $gBdeHexEqualMode; } return $gBdeDiscreteValueMode; } // Given the text value, dataType, and mode, figure out what // the actual value is (e.g., if the $value == "&| 0x0010, then // 0x0010 is the value we're after, which gets converted to "16") proc string parseValueForValue( string $value, string $dataType, int $mode ) { global int $gBdeDiscreteValueMode; global int $gBdeDiscreteRangeMode; global int $gBdeHexSetMode; global int $gBdeHexNotSetMode; global int $gBdeHexEqualMode; global int $gBdeContinuousMode; global int $gBdeAsColorMode; string $retString; int $length = `size $value`; string $char = `getChar $value 1`; if ( $dataType == "string" || $dataType == "binary" ) { return $value; } if ( $dataType == "hex" ) { $retString = "0"; for ( $i = 1; $i < $length; $i++ ) { $char = `getChar $value $i`; if ( $char == " " || $char == "&" || $char == "|" || $char == "~" || $char == "=" ) continue; $retString = `substring $value $i $length`; int $val = `hexStringToInt $retString`; $retString = $val; break; } return $retString; } if ( $dataType == "boolean" ) { if ( $char == "0" || $char == "f" || $char == "F" ) return "0"; else return "1"; } if ( $char == "@" ) return ""; else if ( $char == "%" ) return ""; else if ( $char == "[" || $char == "(" || $char == "{" ) return ""; else return $value; } // Which is either "min" (indicating we're looking for the min value) // or something else, indicating max. We assume the $value looks like // [x,y], and return appropriate x/y as a string (it might be *) proc string parseValueForMinMax( string $value, string $which ) { string $val; int $length = `size $value` - 1; string $stripped = `substring $value 2 $length`; string $buffer[]; tokenize $stripped "," $buffer; if ( $which == "min" ) $val = $buffer[0]; else $val = $buffer[1]; return $val; } // Convert a list (usually obtained via `ls -sl`) to // the given assocType ("face", "vertex", "object" ) // Returns as a string array the new list (filtering out // duplicates) proc string[] convList( string $list[], string $assocType ) { string $newList[]; string $filteredList[]; string $convCmd = "polyListComponentConversion"; string $convType = "none"; // We just get the first element of each string in the given array if ( $assocType == "object" ) { string $array[]; for ( $selIndex = 0; $selIndex < size($list); $selIndex++ ) { $array = getSelectionComp( $list[$selIndex] ); $newList[$selIndex] = $array[0]; } } else if ( $assocType == "vertex" ) $convType = " -tv"; else if ( $assocType == "face" ) $convType = " -tf"; else // Just return the list they passed us return $list; if ( $convType != "none" ) { $convCmd += $convType; $newList = `eval $convCmd`; } // Go through our list and filter out any duplicates. string $filteredSel[]; for ( $preIndex = 0, $postIndex = 0; $preIndex < size($newList); $preIndex++ ) { int $foundIt = 0; for ( $i = 0; $i < size($filteredSel); $i++ ) { if ( $filteredSel[$i] == $newList[$preIndex] ) $foundIt = 1; } if ( !$foundIt ) { $filteredSel[$postIndex++] = $newList[$preIndex]; } } return $filteredSel; } // Go through the query/color rows and construct the command to // do the action. If $doColor is true, the action specified is 'Color', // otherwise 'Query'. global proc bdeDoQueryColor( int $doColor ) { global string $gBdeQueryColorLayout; global int $gBdeBinaryMode; global int $gBdeDiscreteRangeMode; global int $gBdeContinuousMode; global int $gBdeAsColorMode; string $parent = $gBdeQueryColorLayout; // Only do the action if something's selected // (Action works on selection only - could easily // change this to work on the whole scene, if desired, // but selection->action is the way maya typically // works). string $selected[] = `ls -sl`; if ( size( $selected ) == 0 ) return; string $layout; string $control; string $tag; string $bdt; int $id; int $ids[]; int $mode; int $modes[]; string $name; string $value; string $values[]; string $assocTypes[]; string $origSelection[]; string $cmd; float $color[]; int $k = -1; if ( $doColor ) { // 'NoneColor' and 'ClashColor' are common to all of the criterion $cmd = "polyColorBlindData "; $color = `canvas -query -rgbValue bdeNoneColor`; $cmd += " -ncr " + $color[0] + " -ncg " + $color[1] + " -ncb " + $color[2]; $color = `canvas -query -rgbValue bdeClashColor`; $cmd += " -ccr " + $color[0] + " -ccg " + $color[1] + " -ccb " + $color[2]; } else $cmd = "polyColorBlindData -q "; string $children[] = `columnLayout -q -ca $parent`; // These children are the different rows. for ( $child in $children ) { $thisParent = $parent + "|" + $child; $layout = $thisParent + "|mainLine"; $control = $layout + "|enable"; // Enable for this line is off, skip this row if ( !`checkBox -q -v $control` ) continue; $bdt = getQcSelectedBdt( $thisParent ); if ( $bdt == "" ) continue; $id = getId ( $bdt ); // Should maybe check if idDefined here... $ids[++$k] = $id; $cmd += " -id " + $id; $assocTypes[$k] = getAssocType( $bdt ); if ( $assocTypes[$k] == "" ) $assocTypes[$k] = "any"; $control = $layout + "|valueEnable"; // Have to specify how many attrs we have int $dataCount = getDataCount( $bdt ); $cmd += " -num " + $dataCount; // If valueEnable isn't checked, the data is considered 'binary' if ( !`checkBox -q -v $control` ) { $modes[$k] = $gBdeBinaryMode; $cmd += " -m " + $gBdeBinaryMode; for ( $i = 0; $i < $dataCount; $i++ ) { $name = getLongName( $bdt, $i ); $cmd += " -n \"" + $name + "\""; } $control = $layout + "|canvas"; $color = `canvas -query -rgbValue $control`; $cmd += " -cr " + $color[0] + " -cg " + $color[1] + " -cb " + $color[2]; continue; } for ( $i = 0; $i < $dataCount; $i++ ) { $name = getLongName( $bdt, $i ); $dataType = getDataType( $bdt, $i ); $value = getQcValue( $thisParent, $i ); if ( $i == 0 ) { $mode = parseValueForMode( $value, $dataType ); $cmd += " -m " + $mode; $modes[$k] = $mode; } $cmd += " -dt \"" + $dataType + "\""; $cmd += " -n \"" + $name + "\""; if ( $mode != $gBdeContinuousMode && $mode != $gBdeDiscreteRangeMode && $mode != $gBdeAsColorMode ) { $value = parseValueForValue( $value, $dataType, $mode ); if ( $value == "" ) { string $warnmsg = (uiRes("m_blindDataEditor.kWarningNoPresetVal")); warning `format -s $tag -s $id -s $name $warnmsg`; return; } $cmd += " -v \"" + $value + "\""; } if ( $mode == $gBdeDiscreteRangeMode ) { string $min = parseValueForMinMax( $value, "min" ); string $max = parseValueForMinMax( $value, "max" ); if ( $min == "*" ) $cmd += " -umn 0"; else { $cmd += " -umn 1"; $cmd += " -mnv " + $min; } if ( $max == "*" ) $cmd += " -umx 0"; else { $cmd += " -umx 1"; $cmd += " -mxv " + $max; } } if ( $mode == $gBdeContinuousMode && $i == 0 ) { $color = `canvas -query -rgbValue bdeOutOfRangeColor`; // Out of range == belowMin == aboveMax // Note that it would be very easy to add separate canvases for // both the below min and above max colors. Wasn't deemed // necessary, and was thought it would clutter things up too // much, but if this functionality is desired, search for // bdeOutOfRangeColor, and replace it's occurrences with // bdeBelowMinColor and bdeAboveMaxColor, then set these flags // accordingly. $cmd += " -bmr " + $color[0] + " -bmg " + $color[1] + " -bmb " + $color[2]; $cmd += " -amr " + $color[0] + " -amg " + $color[1] + " -amb " + $color[2]; } if ( $mode == $gBdeContinuousMode ) { string $layout = $thisParent + "|valueLayout|valueForm|" + "valueChooser|chooserC|"; $layout += "cLayout" + $i; if ( $doColor ) { $control = $layout + "|minColor"; $color = `colorSliderGrp -q -rgb $control`; $cmd += " -mnr " + $color[0] + " -mng " + $color[1] + " -mnb " + $color[2]; $control = $layout + "|maxColor"; $color = `colorSliderGrp -q -rgb $control`; $cmd += " -mxr " + $color[0] + " -mxg " + $color[1] + " -mxb " + $color[2]; } // Need the min and max values for query mode $control = $layout + "|minValue"; float $val; if ( $dataType == "int" ) $val = `intField -q -v $control`; else $val = `floatField -q -v $control`; $cmd += " -mnv " + $val; $control = $layout + "|maxValue"; if ( $dataType == "int" ) $val = `intField -q -v $control`; else $val = `floatField -q -v $control`; $cmd += " -mxv " + $val; } else { // All modes other than continuous simply // give the color of the canvas for this row (except // for asColor, but extra flags in the cmd don't hurt any...) if ( $doColor ) { $control = $layout + "|canvas"; $color = `canvas -query -rgbValue $control`; $cmd += " -cr " + $color[0] + " -cg " + $color[1] + " -cb " + $color[2]; } } } } $numIds = $k++; int $firstMode = compatibleMode( $modes[0] ); string $assocType = $assocTypes[0]; if ( $numIds >= 0 ) { // Check to see if it makes sense to do the command with the // given types. Some go together (e.g. discreteVal and discreteRange), // some do not (binary and continuous) // Also, we'll look at all of the associationTypes. If they're all // set and the same, we'll convert to that type. for ( $i = 1; $i < $numIds; $i++ ) { $assoc = $assocTypes[$i]; $mode = compatibleMode( $modes[$i] ); if ( $mode != $firstMode ) { warning (uiRes("m_blindDataEditor.kWarningCompatibleModes")); return; } if ( $assoc != $assocType ) { $assocType = "any"; } } // Save this so we can reset it after the action is performed. $origSel = `ls -sl`; // $assocType right now has the _common_ assocType for all of the // selected rows. If this is set to something, we convert the selection // to this type (and select it). // This may be more than the user wants - in this case, comment out // the eval in the block. if ( $assocType != "any" ) { string $newSel[] = convList( $origSel, $assocType ); string $select = "select -r "; for ( $sel in $newSel ) $select += "\"" + $sel + "\" "; eval $select; } else { // warning( "Can't figure out the type from the blind data templates." ); // warning( "Selection won't be converted and only selected components will be examined." ); } if ( !$doColor ) { // Then we just do the $cmd and select the result. // If there is nothing returned from the $cmd, we // clear the selection. // You might uncomment out the following print statement // to see (in the script editor) what the arguments are to // the command. This can be useful for debugging as well as // to give you ideas on how to extend the blind data editor. // For this command, the documentation on the polyColorBlindData // command should describe all of the different flags we're using. print( $cmd + "\n" ); string $result[] = `eval( $cmd )`; if ( size( $result ) ) { select -cl; string $cmd = "select -r"; for ( $name in $result ) { $cmd += " "; $cmd += $name; } eval $cmd; } else { select -cl; } } else { // Evaluate the command (which colors the geom for us) // and restore the selection to what it was. // You might uncomment out the following print statement // to see (in the script editor) what the arguments are to // the command. This can be useful for debugging as well as // to give you ideas on how to extend the blind data editor. // For this command, the documentation on the polyColorBlindData // command should describe all of the different flags we're using. print( $cmd + "\n" ); eval( $cmd ); string $select = "select -r "; for ( $sel in $origSel ) $select += "\"" + $sel + "\" "; eval $select; } } } global proc bdeQuery() { bdeDoQueryColor( 0 ); } global proc bdeColor() { bdeDoQueryColor( 1 ); refresh; } // What follows is most of the methods for the type Editor tab. // Most of these have 't' or 'T' somewhere in the name to indicate // it's for the type Editor (the t was initailly for 'Template' - perhaps // a poor choice, but... // Check to see if we should enable the ranged box and fields // If 'fill' is true, we set these based on the selected template's range // settings global proc bdeTRangeCheck( int $i, int $fill ) { global int $gBdeEditingTemplate; if ( $gBdeEditingTemplate ) return; string $control; int $ranged; if ( $fill ) { int $id = `intField -q -v bdeTTypeId`; string $bdt = getTemplateNameFromId( $id ); if ( $bdt != "" ) { $attr = getLongName( $bdt, $i ); $ranged = getRanged( $bdt, $attr ); $control = "bdeTRanged" + $i; checkBox -e -en false -v $ranged $control; if ($ranged) { float $min = getMinVal( $bdt, $attr ); $control = "bdeTIntMin" + $i; intField -e -en false -v $min $control; $control = "bdeTFloatMin" + $i; floatField -e -en false -v $min $control; float $max = getMaxVal( $bdt, $attr ); $control = "bdeTIntMax" + $i; intField -e -en false -v $max $control; $control = "bdeTFloatMax" + $i; floatField -e -en false -v $max $control; } } } int $freeSet = `checkBox -q -v bdeTFreeSet`; $control = "bdeTDataType" + $i; string $dataType = dataType_uiToMel(`optionMenu -q -v $control`); if ( !$freeSet || $dataType == "string" || $dataType == "boolean" || $dataType == "binary" ) { $control = "bdeTRangeFrame" + $i; frameLayout -e -cl true $control; $control = "bdeTIntMinMax" + $i; frameLayout -e -cl true $control; $control = "bdeTFloatMinMax" + $i; frameLayout -e -cl true $control; return; } $control = "bdeTRangeFrame" + $i; frameLayout -e -cl false $control; $control = "bdeTRanged" + $i; $ranged = `checkBox -q -v $control`; if ( !$ranged ) { $control = "bdeTIntMinMax" + $i; frameLayout -e -cl true $control; $control = "bdeTFloatMinMax" + $i; frameLayout -e -cl true $control; return; } if ( $dataType == "float" || $dataType == "double" ) { $control = "bdeTIntMinMax" + $i; frameLayout -e -cl true $control; $control = "bdeTFloatMinMax" + $i; frameLayout -e -cl false $control; } else { $control = "bdeTIntMinMax" + $i; frameLayout -e -cl false $control; $control = "bdeTFloatMinMax" + $i; frameLayout -e -cl true $control; } } // How many data descriptors exist in the layout proc int tNumDescriptors() { int $numUsed = 0; string $children[] = `columnLayout -q -ca bdeTDescriptorLayout`; int $nbDesc = size( $children ); for ( $i = 0; $i < $nbDesc; $i++ ) { $layout = "bdeTDescriptor" + $i; if ( !`frameLayout -q -cl $layout` ) $numUsed++; else return $numUsed; } return $numUsed; } // Do the range check on each of the data descriptors global proc bdeTFreeSetChanged() { int $numDesc = tNumDescriptors(); for ( $i = 0; $i < $numDesc; $i++ ) { bdeTRangeCheck( $i, 0 ); } } // Turn on appropriate buttons global proc bdeTEnableButtons() { global string $gBdeTPresetLayout; button -e -vis true bdeNewDescriptorButton; button -e -vis true bdeNewPresetButton; string $children[] = `columnLayout -q -ca $gBdeTPresetLayout`; for ( $child in $children ) { $layout = $gBdeTPresetLayout + "|" + $child; $control = $layout + "|" + "newButton"; button -e -vis true $control; } } // Turn off appropriate buttons global proc bdeTDisableButtons() { global string $gBdeTPresetLayout; button -e -vis false bdeNewDescriptorButton; button -e -vis false bdeNewPresetButton; string $children[] = `columnLayout -q -ca $gBdeTPresetLayout`; for ( $child in $children ) { $control = $gBdeTPresetLayout + "|" + $child + "|presetNameLayout|deleteButton"; button -e -vis false $control; } } // Delete the given preset global proc bdeTDeletePreset( string $layout ) { deleteUI -lay $layout; } // How many presets exist in the presetLayout // (This says nothing about the template or how many are filled) proc int tNumPresets() { global string $gBdeTPresetLayout; string $children[] = `columnLayout -q -ca $gBdeTPresetLayout`; return size( $children ); } // Delete all of the presets global proc bdeTDestroyPresets() { global string $gBdeTPresetLayout; string $children[] = `columnLayout -q -ca $gBdeTPresetLayout`; string $layout; for ( $child in $children ) { $layout = $gBdeTPresetLayout + "|" + $child; deleteUI -lay $child; } } // Empty out the given descriptor global proc bdeTClearDescriptor( int $i ) { string $control = "bdeTLongName" + $i; textField -e -tx "" -en true $control; $control = "bdeTShortName" + $i; textField -e -tx "" -en true $control; $control = "bdeTDataType" + $i; optionMenu -e -v `dataType_melToUI("double")` -en true $control; $control = "bdeTRangeFrame" + $i; frameLayout -e -cl true $control; $control = "bdeTRanged" + $i; checkBox -e -v 0 -en true $control; $control = "bdeTIntMinMax" + $i; frameLayout -e -cl true $control; $control = "bdeTIntMin" + $i; intField -e -v 0 -en true $control; $control = "bdeTIntMax" + $i; intField -e -v 100 -en true $control; $control = "bdeTFloatMinMax" + $i; frameLayout -e -cl true $control; $control = "bdeTFloatMin" + $i; floatField -e -v 0 -en true $control; $control = "bdeTFloatMax" + $i; floatField -e -v 1.0 -en true $control; } global proc bdeTCollapseAndClearDescriptors() { string $children[] = `columnLayout -q -ca bdeTDescriptorLayout`; int $numDesc = size( $children ); for ( $i = 0; $i < $numDesc; $i++ ) { bdeTClearDescriptor( $i ); $layout = "bdeTDescriptor" + $i; frameLayout -e -cl true $layout; } } global proc bdeTOpenDescriptor( int $i ) { string $layout = "bdeTDescriptor" + $i; if ( !`frameLayout -q -ex $layout` ) bdeTBuildDescriptor( $i ); frameLayout -e -cl false $layout; } // Create the given descriptor and all of it's associated // controls global proc bdeTBuildDescriptor( int $i ) { // We just add one to the this layout. // Hence assumption is that any preceeding ones // should be there already. setParent bdeTDescriptorLayout; string $layout = "bdeTDescriptor" + $i; // It's a frameLayout - so we can collapse it // (but because -bv is false the user can't collapse it) frameLayout -cll true -cl true -lv false -bv false $layout; string $command = "bdeTValueChanged " + $i; columnLayout -adj true -rs 5; rowColumnLayout -nc 2 -cw 1 105; text -align "left" -label (uiRes("m_blindDataEditor.kLongNameText")); string $control = "bdeTLongName" + $i; textField -cc bdeTTypeNameChange $control; text -align "left" -label (uiRes("m_blindDataEditor.kShortNameText")); $control = "bdeTShortName" + $i; textField $control; // Default is "double" text -align "left" -label (uiRes("m_blindDataEditor.kDataType")); $control = "bdeTDataType" + $i; optionMenu -cc $command $control; menuItem -label `dataType_melToUI("double")`; menuItem -label `dataType_melToUI("int")`; menuItem -label `dataType_melToUI("hex")`; menuItem -label `dataType_melToUI("boolean")`; menuItem -label `dataType_melToUI("string")`; menuItem -label `dataType_melToUI("binary")`; setParent ..; // We create all of the range frames, and they start off collapsed $control = "bdeTRangeFrame" + $i; frameLayout -cll true -cl true -lv false -bv false $control; rowColumnLayout -nc 2 -cw 1 105; separator -st "none"; $control = "bdeTRanged" + $i; checkBox -label (uiRes("m_blindDataEditor.kRanged")) -cc $command $control; setParent ..; setParent ..; $control = "bdeTIntMinMax" + $i; frameLayout -cll true -cl true -lv false -bv false $control; string $maxText = (uiRes("m_blindDataEditor.kMaxLabel")); string $minText = (uiRes("m_blindDataEditor.kMinLabel")); rowColumnLayout -nc 2 -cw 1 105; text -align "left" -label $minText; $control = "bdeTIntMin" + $i; intField $control; text -align "left" -label $maxText; $control = "bdeTIntMax" + $i; intField $control; setParent ..; setParent ..; $control = "bdeTFloatMinMax" + $i; frameLayout -cll true -cl true -lv false -bv false $control; rowColumnLayout -nc 2 -cw 1 105; text -align "left" -label $minText; $control = "bdeTFloatMin" + $i; floatField $control; text -align "left" -label $maxText; $control = "bdeTFloatMax" + $i; floatField $control; setParent ..; setParent ..; separator -w 300 -h 15; setParent ..; setParent ..; } // Allow user-editing of all the presets, and // enable the newPreset button. proc tEnablePresets() { global string $gBdeTPresetLayout; global int $gBdeEditingTemplate; string $layout, $control; string $children[] = `columnLayout -q -ca $gBdeTPresetLayout`; int $numDesc = tNumDescriptors(); int $numPresets = tNumPresets(); for ( $i = 0; $i < $numPresets; $i++ ) { $control = $gBdeTPresetLayout + "|" + $children[$i]; $control += "|presetNameLayout|presetTagName"; textField -e -en true $control; for ( $j = 0; $j < $numDesc; $j++ ) { $layout = $gBdeTPresetLayout + "|" + $children[$i] + "|presetValueLayout" + $j; $control = $layout + "|presetValue" + $j; textField -e -en true $control; } } button -e -vis true bdeNewPresetButton; } // (Re)Build all of the existing presets // filling in the appropriate attr names global proc bdeTRebuildPresets() { global string $gBdeTPresetLayout; string $layout, $control; string $children[] = `columnLayout -q -ca $gBdeTPresetLayout`; int $numDesc = tNumDescriptors(); int $numPresets = tNumPresets(); for ( $i = 0; $i < $numPresets; $i++ ) { for ( $j = 0; $j < $numDesc; $j++ ) { $layout = $gBdeTPresetLayout + "|" + $children[$i] + "|presetValueLayout" + $j; $control = "bdeTLongName" + $j; $value = `textField -q -tx $control`; if ( `rowLayout -q -ex $layout` ) { $control = $layout + "|presetDataName" + $j; text -e -label $value $control; } else { $layout = $gBdeTPresetLayout + "|" + $children[$i]; setParent $layout; $layout = "presetValueLayout" + $j; rowLayout -nc 2 -cal 1 "right" $layout; $control = "presetDataName" + $j; text -label $value $control; $control = "presetValue" + $j; textField -w 100 $control; setParent ..; rowLayout -e -cal 1 "right" $layout; } } $layout = $gBdeTPresetLayout + "|" + $children[$i] + "|presetValueLayout" + $numDesc; if ( `rowLayout -q -ex $layout` ) deleteUI -lay $layout; } } // Open a new descriptor. If one exists and is collapsed, // it's cleared and opened. Otherwise, a new one is created. global proc bdeNewDescriptor() { string $children[] = `columnLayout -q -ca bdeTDescriptorLayout`; int $numDesc = size( $children ); for ( $i = 0; $i < $numDesc; $i++ ) { $layout = "bdeTDescriptor" + $i; if ( `frameLayout -q -cl $layout` ) { bdeTClearDescriptor( $i ); frameLayout -e -cl false $layout; bdeTFreeSetChanged(); bdeTRebuildPresets(); return; } } bdeTBuildDescriptor( $numDesc ); $layout = "bdeTDescriptor" + $numDesc; frameLayout -e -cl false $layout; bdeTFreeSetChanged(); bdeTRebuildPresets(); } // I had a remove button, in case you created too many and // decided you didn't want some of them, but i decided to axe this // for simplicity sake. If you hit the 'New' button too many times, // you've gotta start over with a new template. That's not so bad, is it? global proc bdeRemoveDescriptor() { string $children[] = `columnLayout -q -ca bdeTDescriptorLayout`; int $numDesc = size( $children ); for ( $i = 0; $i < $numDesc; $i++ ) { $layout = "bdeTDescriptor" + $i; if ( `frameLayout -q -cl $layout` ) { if ( $i > 1 ) { $layout = "bdeTDescriptor" + ($i-1); frameLayout -e -cl true $layout; bdeTClearDescriptor( $i-1 ); return; } else return; } } if ( $numDesc > 1 ) { $layout = "bdeTDescriptor" + ($numDesc-1); frameLayout -e -cl true $layout; bdeTClearDescriptor( $numDesc-1 ); } bdeTRebuildPresets(); } // Fill the given descriptor with the appropriate data // from the selected blind data template. global proc bdeTFillDescriptor( int $i ) { int $id = `intField -q -v bdeTTypeId`; if ( idDefined( $id ) ) { string $bdt = getTemplateNameFromId( $id ); if ( $bdt == "" ) return; int $dataCount = getDataCount( $bdt ); if ( $i >= $dataCount ) return; string $name = getLongName( $bdt, $i ); string $control = "bdeTLongName" + $i; textField -e -en false -tx $name $control; $name = getShortName( $bdt, $i ); $control = "bdeTShortName" + $i; textField -e -en false -tx $name $control; string $dataType = getDataType( $bdt, $i ); $control = "bdeTDataType" + $i; optionMenu -e -en false -v `dataType_melToUI($dataType)` $control; // This call figures out what to do with the // free set and ranged stuff for this descriptor bdeTRangeCheck( $i, true ); } } // Create a new preset, either because user hit the new preset // button or if an id was selected that has presets defined // First field is the name of the preset, then there is one field // for each of the data descriptors. global proc bdeTNewPreset() { global string $gBdeTPresetLayout; setParent $gBdeTPresetLayout; $layout = `columnLayout -adj true`; rowLayout -nc 3 -cal 3 "center" presetNameLayout; text -label (uiRes("m_blindDataEditor.kPresentName")); textField -w 90 presetTagName; button -label (uiRes("m_blindDataEditor.kPresetDelete")) -w 65 -c ( "bdeTDeletePreset \"" + $layout + "\"" ) deleteButton; setParent ..; int $numDesc = tNumDescriptors(); for ( $i = 0; $i < $numDesc; $i++ ) { $layout = "presetValueLayout" + $i; rowLayout -nc 2 -cal 1 "right" $layout; $control = "bdeTLongName" + $i; $attr = `textField -q -tx $control`; $control = "presetDataName" + $i; text -label $attr $control; $control = "presetValue" + $i; textField -w 90 $control; // separator -st "none"; setParent ..; rowLayout -e -cal 1 "right" $layout; } separator -w 300 -h 8; setParent ..; } // Fill the presets with the ones that are set from the // selected blind data template. global proc bdeTFillPresets() { global string $gBdeTPresetLayout; string $control; string $value; string $layout; int $tagCount; int $id = `intField -q -v bdeTTypeId`; if ( !idDefined( $id ) ) return; string $bdt = getTemplateNameFromId( $id ); if ( $bdt == "" ) return; int $numPresets = getPresetCount( $bdt ); int $dataCount = getDataCount( $bdt ); if ( 0 == $dataCount || 0 == $numPresets ) return; string $children[] = `columnLayout -q -ca $gBdeTPresetLayout`; for ( $i = 0; $i < $numPresets; $i++ ) { $value = getPresetName( $bdt, $i ); $control = $gBdeTPresetLayout + "|" + $children[$i] + "|presetNameLayout|presetTagName"; textField -e -en false -tx $value $control; for ( $j = 0; $j < $dataCount; $j++ ) { $attr = getLongName( $bdt, $j ); $layout = $gBdeTPresetLayout + "|" + $children[$i] + "|presetValueLayout" + $j; $value = getPresetVal( $bdt, $i, $attr ); $control = $layout + "|presetValue" + $j; if ( `textField -q -ex $control` ) textField -e -en false -tx $value $control; } } } // This clears everything out and enables the buttons, etc. // Happens on the 'New' template button or when you want // similar behaviour global proc bdeNewTemplate( int $clearType ) { global int $gBdeEditingTemplate = 0; // We may be getting called from the initCallback on the first // open of the panel. If that's the case, this intField doesn't // exist, and we should return gracefully. if ( !`intField -q -ex bdeTTypeId` ) return; if ( $clearType ) intField -e -v 0 -en true bdeTTypeId; textField -e -tx "" -en true bdeTTypeName; optionMenu -e -v `assocType_melToUI "any"` -en true bdeTAssocType; checkBox -e -en true bdeTFreeSet; string $children[] = `columnLayout -q -ca bdeTDescriptorLayout`; int $numDesc = size( $children ); for ( $i = 0; $i < $numDesc; $i++ ) { $layout = "bdeTDescriptor" + $i; if ( 0 == $i ) frameLayout -e -cl false $layout; else frameLayout -e -cl true $layout; bdeTClearDescriptor( $i ); } textScrollList -e -da bdeTemplateList; bdeTFreeSetChanged(); bdeTDestroyPresets(); bdeTEnableButtons(); } // The id field has changed. global proc bdeTIdChange() { int $id = `intField -q -v bdeTTypeId`; // Is this an existing template? // If so, fill in the values, disable // buttons so user can't delete data that we can't delete // if it exists in the scene, etc. if ( idDefined( $id ) ) { string $bdt = getTemplateNameFromId( $id ); intField -e -en false bdeTTypeId; string $name = getTag( $bdt ); textField -e -en false -tx $name bdeTTypeName; // This is returning MEL type string $assocType = getAssocType( $bdt ); if ( $assocType != "" ) optionMenu -e -en false -v `assocType_melToUI $assocType` bdeTAssocType; else optionMenu -e -en false -v `assocType_melToUI "any"` bdeTAssocType; int $freeSet = getFreeSet( $bdt ); checkBox -e -en false -v $freeSet bdeTFreeSet; bdeTCollapseAndClearDescriptors(); bdeTDestroyPresets(); int $dataCount = getDataCount( $bdt ); for ( $i = 0; $i < $dataCount; $i++ ) { string $layout = "bdeTDescriptor" + $i; if ( !`frameLayout -q -ex $layout` ) bdeTBuildDescriptor( $i ); bdeTFillDescriptor( $i ); frameLayout -e -cl false $layout; } int $presetCount = getPresetCount( $bdt ); for ( $i = 0; $i < $presetCount; $i++ ) bdeTNewPreset(); bdeTRebuildPresets(); bdeTFillPresets(); bdeTDisableButtons(); } // If the id's not defined, this should be a 'new' template already. // Calling bdeNewTemplate will clear out all values if they've been // entered (and would be very annoying if they changed their mind about // the id after entering everything) // else // { // bdeNewTemplate( false ); // } } // If one of the type names changed, we'll rebuild all the presets, as they // have the type names in them (before each preset value field) global proc bdeTTypeNameChange() { bdeTRebuildPresets(); } // They selected a pre-existing template. If they were editing one, they're not // anymore! global proc bdeTNameListChange() { int $id = getTemplateTagId(); if ( $id == -1 ) return; global int $gBdeEditingTemplate = 0; intField -e -v $id bdeTTypeId; bdeTIdChange(); } // Just do a range check and rebuild the presets if one of the // values changed. global proc bdeTValueChanged( int $i ) { bdeTRangeCheck( $i, 0 ); bdeTRebuildPresets(); } // This is called before saving the templates to make sure all // of the entered data is legit. // This function could (should?) be expanded upon - to make // sure that the preset vals match the data type, etc. proc int tCheckValues() { global int $gBdeEditingTemplate; global string $gBdeTPresetLayout; int $id = `intField -q -v bdeTTypeId`; if ( $id < 0 ) { warning (uiRes("m_blindDataEditor.kWarningTypeId")); return 0; } if ( !$gBdeEditingTemplate ) { if ( idDefined( $id ) ) { warning (uiRes("m_blindDataEditor.kWarningIdDefined")); return 0; } } string $typeTag = `textField -q -tx bdeTTypeName`; if ( $typeTag == "" ) { warning (uiRes("m_blindDataEditor.kWarningIdName")); return 0; } if ( !$gBdeEditingTemplate ) { if ( tagDefined( $typeTag ) ) { warning (uiRes("m_blindDataEditor.kWarningTypeTagDefined")); return 0; } } int $numDesc = tNumDescriptors(); int $numPresets = tNumPresets(); string $longName[]; string $shortName[]; // Make sure they've filled long and short names for ( $i = 0; $i < $numDesc; $i++ ) { $control = "bdeTLongName" + $i; $longName[$i] = `textField -q -tx $control`; $control = "bdeTShortName" + $i; $shortName[$i] = `textField -q -tx $control`; if ( $longName[$i] == "" || $shortName[$i] == "" ) { warning (uiRes("m_blindDataEditor.kWarningSpecifyNameDescriptor")); return 0; } } string $children[] = `columnLayout -q -ca $gBdeTPresetLayout`; for ( $i = 0; $i < $numPresets; $i++ ) { string $presetName; string $presetVal[]; $control = $gBdeTPresetLayout + "|" + $children[$i] + "|presetNameLayout|presetTagName"; $presetName = `textField -q -tx $control`; if ( $presetName == "" ) { warning (uiRes("m_blindDataEditor.kWarningPresetName")); return 0; } for ( $j = 0; $j < $numDesc; $j++ ) { $layout = $gBdeTPresetLayout + "|" + $children[$i] + "|presetValueLayout" + $j; $control = $layout + "|presetValue" + $j; $presetVal[$j] = `textField -q -tx $control`; if ( $presetVal[$j] == "" ) { warning (uiRes("m_blindDataEditor.kWarningFillPresetValue")); return 0; } // Could check here if $presetVal[$j] matches the $dataType[$j]... } } return 1; } // If user was 'Edit'ing a pre-existing template, we don't do as much as if // they are saving a new one... // For editing, only the typeTag, assocType, // and presets are editable. global proc bdeSaveEditedTemplate() { global int $gBdeEditingTemplate; global string $gBdeTPresetLayout; int $id = `intField -q -v bdeTTypeId`; string $bdt = getTemplateNameFromId( $id ); if ( $bdt == "" ) return; $gBdeEditingTemplate = 0; string $typeTag = `textField -q -tx bdeTTypeName`; int $numDesc = tNumDescriptors(); int $numPresets = tNumPresets(); string $assocType = assocType_uiToMel(`optionMenu -q -v bdeTAssocType`); setAssocType( $bdt, $assocType ); int $freeSet = `checkBox -q -v bdeTFreeSet`; setFreeSet( $bdt, $freeSet ); string $longName[]; for ( $i = 0; $i < $numDesc; $i++ ) { $control = "bdeTLongName" + $i; $longName[$i] = `textField -q -tx $control`; } string $children[] = `columnLayout -q -ca $gBdeTPresetLayout`; string $presetName; string $presetVal[]; for ( $i = 0; $i < $numPresets; $i++ ) { $control = $gBdeTPresetLayout + "|" + $children[$i] + "|presetNameLayout|presetTagName"; $presetName = `textField -q -tx $control`; for ( $j = 0; $j < $numDesc; $j++ ) { $layout = $gBdeTPresetLayout + "|" + $children[$i] + "|presetValueLayout" + $j; $control = $layout + "|presetValue" + $j; $presetVal[$j] = `textField -q -tx $control`; } setPreset( $bdt, $presetName, $longName, $presetVal, $i ); } bdeForceRebuild(); bdeNewTemplate( true ); } // This gets called when the user hits save // If they were editing a pre-existing one, we call // bdeSaveEditedTemplate, otherwise, save everything global proc bdeSaveTemplate() { global string $gBdeTPresetLayout; global int $gBdeEditingTemplate; string $control; // Make sure everything's filled in. if ( !tCheckValues() ) return; if ( $gBdeEditingTemplate ) { bdeSaveEditedTemplate(); return; } // Just in case $gBdeEditingTemplate = 0; int $id = `intField -q -v bdeTTypeId`; string $typeTag = `textField -q -tx bdeTTypeName`; int $numDesc = tNumDescriptors(); int $numPresets = tNumPresets(); string $assocType = assocType_uiToMel(`optionMenu -q -v bdeTAssocType`); int $freeSet = `checkBox -q -v bdeTFreeSet`; string $longName[]; string $shortName[]; string $dataType[]; int $ranged[]; float $min[]; float $max[]; for ( $i = 0; $i < $numDesc; $i++ ) { $control = "bdeTLongName" + $i; $longName[$i] = `textField -q -tx $control`; $control = "bdeTShortName" + $i; $shortName[$i] = `textField -q -tx $control`; $control = "bdeTDataType" + $i; $dataType[$i] = dataType_uiToMel(`optionMenu -q -v $control`); $control = "bdeTRanged" + $i; $ranged[$i] = `checkBox -q -v $control`; if ( $dataType[$i] == "int" ) { $control = "bdeTIntMin" + $i; $min[$i] = `intField -q -v $control`; $control = "bdeTIntMax" + $i; $max[$i] = `intField -q -v $control`; } else { $control = "bdeTFloatMin" + $i; $min[$i] = `floatField -q -v $control`; $control = "bdeTFloatMax" + $i; $max[$i] = `floatField -q -v $control`; } } string $cmd = "blindDataType -id " + $id; string $dt; for ( $i = 0; $i < $numDesc; $i++ ) { if ( $dataType[$i] == "hex" ) $dt = "int"; else $dt = $dataType[$i]; $cmd += " -dt \"" + $dt + "\""; $cmd += " -ldn \"" + $longName[$i] + "\""; $cmd += " -sdn \"" + $shortName[$i] + "\""; } // Create the blindDataType. // Right now we have all the info that blindDataType command cares // about... // print( $cmd + "\n" ); string $bdt = `eval( $cmd )`; // Here we check each descriptor for whether it's ranged. // If it's ranged we: // delete the attribute from the newly created blindDataTemplate node // create the attribute again on the same blindDataTemplate node, this // time with the min and max values added. // This is a dangerous thing to do, but was the only way to specify at // the dg level what the min and max values are - there's no way to // assign min and max to existing attributes (there is a bug entered for // this somewhere...) Since we know the data type, the long and short names, // and the min and max, it's safe, but be very cautious if you start messing // around with this code!! for ( $i = 0; $i < $numDesc; $i++ ) { if ( !$freeSet || !$ranged[$i] ) continue; if ( $min[$i] == $max[$i] ) continue; string $delCmd = "deleteAttr " + $bdt + "." + $longName[$i]; $cmd = "addAttr -ln " + $longName[$i] + " -sn " + $shortName[$i]; switch( $dataType[$i] ) { case "string": case "binary": case "boolean": continue; // Don't support ranges for these types! case "int": case "hex": $cmd += " -at long"; break; case "float": case "double": $cmd += " -at double"; break; } // print( $delCmd + "\n" ); eval( $delCmd ); $cmd += " -min " + $min[$i]; $cmd += " -max " + $max[$i]; $cmd += " " + $bdt; // print( $cmd + "\n" ); eval( $cmd ); } // All of these set*($bdt,...) calls are using the // user-defined attributes of the new template node. // They are defined above somewhere (do a search). setTag( $bdt, $typeTag ); setAssocType( $bdt, $assocType ); setFreeSet( $bdt, $freeSet ); setDataCount( $bdt, $numDesc ); for ( $i = 0; $i < $numDesc; $i++ ) { setLongName( $bdt, $i, $longName[$i] ); setDataType( $bdt, $i, $dataType[$i] ); } // The presets are set in the blind data template's // preset name/value attributes... string $children[] = `columnLayout -q -ca $gBdeTPresetLayout`; for ( $i = 0; $i < $numPresets; $i++ ) { string $presetName; string $presetVal[]; $control = $gBdeTPresetLayout + "|" + $children[$i] + "|presetNameLayout|presetTagName"; $presetName = `textField -q -tx $control`; for ( $j = 0; $j < $numDesc; $j++ ) { $layout = $gBdeTPresetLayout + "|" + $children[$i] + "|presetValueLayout" + $j; $control = $layout + "|presetValue" + $j; $presetVal[$j] = `textField -q -tx $control`; } setPreset( $bdt, $presetName, $longName, $presetVal, $i ); } bdeForceRebuild(); bdeNewTemplate( true ); } // If the user wants to edit an existing template, we enable the // fields that are editable (enabling the rest could jeopardize the // existing blind data already assigned in the scene - rather than // trying to deal with this rather hairy problem, disallow it. Enabling // editing of, say, data types, can lead to lots of problems - do so at // your own risk). // We also set the $gBdeEditingTemplate var to be true so we know // we're in Edit (and not New) mode global proc bdeEditTemplate() { global int $gBdeEditingTemplate; int $id = `intField -q -v bdeTTypeId`; if ( !idDefined( $id ) ) return; string $bdt = getTemplateNameFromId( $id ); if ( $bdt == "" ) return; $gBdeEditingTemplate = 1; textField -e -en true bdeTTypeName; optionMenu -e -en true bdeTAssocType; checkBox -e -en true bdeTFreeSet; tEnablePresets(); } // Export the current blind data templates to a file. // In most cases the same blind data is going to be used in // all scenes for any one game. Best to set it up initially // and import or reference it into the scenes. // (Referencing will be more convenient if it's possible the // blind data is ever going to change in the game, which is // probably pretty likely...) // // We select the blindDataTemplates, prompt the user to export // them, and then restore the original selection global proc bdeExportTemplates() { string $sel[] = `ls -sl`; // Bug 150384 check exact type so we don't get subd blind data string $templates[] = `ls -exactType blindDataTemplate`; string $cmd = "select -r "; for ( $bdt in $templates ) { $cmd += $bdt; $cmd += " "; } eval $cmd; projectViewer "ExportActive"; $cmd = "select -r "; for ( $sl in $sel ) { $cmd += $sl; $cmd += " "; } eval $cmd; } // This func dumps all of the data we care about contained in the blind // data template nodes in this scene into the given file. // It's actually a callback from the 'fileBrowser' call in bdeDumpTemplates. // // Does a check to see if the file exists and gives a confirm box to overwrite. // Then just writes out all of the data to that file. // This can be useful just for a quick visual check of the data, for sharing // the data between the level designer and the engine programmer, or for the // engine developer to actually parse to ensure that the data in the engine // matches the data used in Maya. // // Easy enough to modify this if it's not printing the data in a format // suitable to your parsing, or if you need more info // (for instance, the number of blind data templates being printed at the // start of the file might make parsing a bit easier). global proc int bdeTextExport( string $fileName, string $fileType ) { string $line, $confirm, $attrName, $presetName, $presetVal; int $i, $j, $fp, $ranged, $dataCount, $presetCount; if ( "" == $fileName ) return 0; if ( `filetest -x $fileName` ) { string $no = (uiRes("m_blindDataEditor.kButtonNo")); string $yes = (uiRes("m_blindDataEditor.kButtonYes")); $confirm = `confirmDialog -title (uiRes("m_blindDataEditor.kConfirm")) -message (uiRes("m_blindDataEditor.kMessageFile")) -button $yes -button $no -defaultButton $yes -cancelButton $no -dismissString $no`; if ( $no == $confirm ) return 0; } $fp = fopen( $fileName, "w" ); if ( 0 == $fp ) { string $warnfile = (uiRes("m_blindDataEditor.kWarningFileCouldNotOpen")); warning `format -s $fileName $warnfile`; return -1; } // Bug 150384 check exact type so we don't get subd blind data string $nodes[] = `ls -exactType "blindDataTemplate"`; for ( $bdt in $nodes ) { $line = "++++++++++++++++++++++++++++++++++++++++++++++\n"; fprint( $fp, $line ); $line = $bdt + "\n"; fprint( $fp, $line ); $line = "ID: "; $line += getId( $bdt ); $line += "\n"; fprint( $fp, $line ); $line = "NAME: "; $line += getTag( $bdt ); $line += "\n"; fprint( $fp, $line ); $line = "ASSOC TYPE: "; $line += getAssocType( $bdt ); $line += "\n"; fprint( $fp, $line ); $line = "FREE SET: "; $line += getFreeSet( $bdt ); $line += "\n"; fprint( $fp, $line ); $dataCount = getDataCount( $bdt ); $line = "DATA COUNT: "; $line += $dataCount; $line += "\n"; fprint( $fp, $line ); for ( $i = 0; $i < $dataCount; $i++ ) { $attrName = getLongName( $bdt, $i ); $line = "\tLONG NAME: "; $line += $attrName; $line += "\n"; fprint( $fp, $line ); $line = "\tSHORT NAME: "; $line += getShortName( $bdt, $i ); $line += "\n"; fprint( $fp, $line ); $line = "\tDATA TYPE: "; $line += getDataType( $bdt, $i ); $line += "\n"; fprint( $fp, $line ); $ranged = getRanged( $bdt, $attrName ); $line = "\tRANGED: "; $line += $ranged; $line += "\n"; fprint( $fp, $line ); if ( $ranged ) { $line = "\t\tMIN VAL: "; $line += getMinVal( $bdt, $attrName ); $line += "\n"; fprint( $fp, $line ); $line = "\t\tMAX VAL: "; $line += getMaxVal( $bdt, $attrName ); $line += "\n"; fprint( $fp, $line ); } if ( $i != $dataCount-1 ) { $line = "\t---------------\n"; fprint( $fp, $line ); } else { fprint( $fp, "\n" ); } } $presetCount = getPresetCount( $bdt ); $line = "PRESET COUNT: "; $line += $presetCount; $line += "\n"; fprint( $fp, $line ); for ( $i = 0; $i < $presetCount; $i++ ) { $presetName = getPresetName( $bdt, $i ); $line = "\tPRESET NAME: "; $line += $presetName; $line += "\n"; fprint( $fp, $line ); for ( $j = 0; $j < $dataCount; $j++ ) { $line = "\t\t"; $attrName = getLongName( $bdt, $j ); $line += $attrName; $line += ": "; $presetVal = getPresetVal( $bdt, $i, $attrName ); $line += $presetVal; $line += "\n"; fprint( $fp, $line ); } } $line = "\n"; fprint( $fp, $line ); } fclose( $fp ); return 1; } // This is what's called when the 'Text Dump' button is hit // Just opens the fileBrowser, and uses 'bdeTextExport' as the callback // (which is the preceeding func and is the guts of the text dump). global proc bdeDumpTemplates() { fileBrowser "bdeTextExport" (uiRes("m_blindDataEditor.kDumpToBrowserTitle")) "" 1; } // ViewSelected // // pretty simple tab that just displays the contents of the selected // component/object. Note that we only handle one component. // It'd be great to display all of the selected in a spreadsheet, but // the spreadsheet ELF stuff is really not very extensible and doesn't // function well due to the fact that blind data on components aren't // really 'attributes' in Maya's context. // So, we just pick the lead selected and display that. // Had also thought of displaying a user-defined locator on the selected // components and having something along the lines of vcr controls to // advance or back up to different components, but i didn't have time // to get this in there. // So it's just this simple thing. // Clear everything out global proc bdeClearViewSelected() { text -e -label "" bdeVsCompName; string $control; int $id, $dataCount; // Bug 150384 check exact type so we don't get subd blind data string $nodes[] = `ls -exactType blindDataTemplate`; int $numTypes = size( $nodes ); if ( $numTypes == 0 ) return; for ( $i = 0; $i < $numTypes; $i++ ) { $id = getId( $nodes[$i] ); $dataCount = getDataCount( $nodes[$i] ); for ( $j = 0; $j < $dataCount; $j++ ) { $control = "bdeVSValue" + $id + "_" + $j; // Originally had this set up as a grayed-out (disabled) // textField, but i was vetoed... // textField -e -tx "" $control; if ( `text -q -ex $control` ) text -e -label "" $control; } } } // The guts - check the value of the 'lead component' // for each of the existing blind data templates in the scene // and set the text to be that value if it exists, empty string if // not. Might do something like "N/A" or something if it doesn't exist // if this is confusing. // This gets called on a scriptJob as well as manually in a few places. // Should ensure that the ViewSelected tab's been created already (see // bdeRebuildViewSelected() below) global proc bdeRefreshViewSelected() { string $array[]; string $control; string $value; string $name; string $dataType; string $compType; string $selected; string $sel[]; int $id, $dataCount; bdeClearViewSelected(); $sel = `ls -sl`; // There's nothing selected... if ( size($sel) == 0 ) return; // $array[0] --> object name // $array[1] --> component type // $array[2] --> component id # $array = getSelectionComp( $sel[0] ); // If this is the case, something is probably wrong... if ( $array[0] == "" ) return; // Don't support vtxFace components, so we'll convert to the next // closest thing, verts. if ( $array[1] == "vtxFace" ) { string $sl[] = `ls -sl`; string $buf[] = `polyListComponentConversion -tv $sl[0]`; $array = getSelectionComp( $buf[0] ); } // "*" means all are selected. We'll take the first element. if ( $array[2] == "*" ) $array[2] = "0"; $selected = $array[0] + "." + $array[1] + "[" + $array[2] + "]"; if ( $array[1] == "f" ) $compType = "face"; else if ( $array[1] == "vtx" ) $compType = "vertex"; // If we got here, maybe the selected is a transform. Let's get the // associated shape and say it's an object. else if ( $array[1] == "" ) { $selected = $array[0]; string $kids[] = `listRelatives -s $selected`; if ( size( $kids ) ) $selected = $kids[0]; $compType = "object"; } else $compType = "unknown"; // We show what's selected (we better, since there's not a straightforward // way of knowing what your lead selection is...) text -e -label $selected bdeVsCompName; // Bug 150384 check exact type so we don't get subd blind data string $nodes[] = `ls -exactType blindDataTemplate`; int $numTypes = size( $nodes ); if ( $numTypes == 0 ) return; for ( $i = 0; $i < $numTypes; $i++ ) { $bdt = $nodes[$i]; $id = getId( $bdt ); $dataCount = getDataCount( $bdt ); for ( $j = 0; $j < $dataCount; $j++ ) { $dataType = getDataType( $bdt, $j ); $name = getLongName( $bdt, $j ); // Blind Data cmd now works for objects too $cmd = "polyQueryBlindData -id " + $id + " -at \"" + $compType + "\""; $cmd += " -ldn " + $name + " " + $selected; if ( $dataType == "int" || $dataType == "hex" || $dataType == "boolean" ) { int $vals[] = `eval( $cmd )`; if ( size( $vals ) ) $value = $vals[0]; else $value = ""; } else if ( $dataType == "float" || $dataType == "double" ) { float $vals[] = `eval( $cmd )`; if ( size( $vals ) ) $value = $vals[0]; else $value = ""; } else { string $vals[] = `eval( $cmd )`; if ( size( $vals ) ) $value = $vals[0]; else $value = ""; } // If there's data and the type is hex, we'll convert to more // user-friendly hex string... if ( $dataType == "hex" && $value != "" ) { int $intVal = $value; $value = intToHexString( $intVal ); } $control = "bdeVSValue" + $id + "_" + $j; // These used to be textField, which i think make a little more sense, // but who am i to argue. // textField -e -tx $value $control; if ( `text -q -ex $control` ) text -e -label $value $control; else { // This shouldn't have happened, but we can handle it somewhat // gracefully. bdeRebuildViewSelected(); return; } } } } // Create the controls. Also calls bdeRefreshViewSelected, // which fills them... global proc bdeRebuildViewSelected() { string $control; string $parent = "selectedLayout"; // This should exist if the window does. if ( !`columnLayout -q -ex $parent` ) return; // Delete the old stuff... string $children[] = `columnLayout -q -ca $parent`; for ( $child in $children ) { deleteUI -lay $child; } // Bug 150384 check exact type so we don't get subd blind data string $nodes[] = `ls -exactType blindDataTemplate`; int $numTypes = size( $nodes ); setParent $parent; for ( $i = 0; $i < $numTypes; $i++ ) { string $bdt = $nodes[$i]; int $id = getId( $bdt ); rowColumnLayout -nc 3 -cw 1 120 -cw 2 80 -cw 3 80; text -align "left" -label $id; int $dataCount = getDataCount( $bdt ); for ( $j = 0; $j < $dataCount; $j++ ) { if ( $j != 0 ) separator -st "none"; $control = "bdeVSLongName" + $id + "_" + $j; string $name = getLongName( $bdt, $j ); text -align "left" -label $name $control; $control = "bdeVSValue" + $id + "_" + $j; // textField -en false $control; text -label "" $control; } setParent ..; columnLayout; separator -h 15 -style "none"; setParent ..; } bdeRefreshViewSelected(); } // End ViewSelected // Force a rebuild of all of the UI. // This happens on file->new/open, // when the panel's torn off, etc. // Pretty drastic, (as it chucks out all of user-defined // data) (and slow!), so don't do it if not necessary. global proc bdeForceRebuild() { // Apply and DataTemplate bdeRebuildTextScrollLists(); bdeRebuildPopups(); // Apply: bdeDeleteApplyUI(); // Query/color // bdeRebuildPopups(); bdeRebuildQueryColor(); // View Selected bdeRebuildViewSelected(); // Data Template bdeNewTemplate( true ); } // This proc gets called before the panel/window is created global proc bdeCreateCallback( string $panel ) { // This next call turns false coloring on for the whole scene. // We found that this makes things hard to edit (because everything // in the scene is black) but if real colors are getting confused // with false color, you might turn this back on // polyColorBlindData -enableFalseColor 1; // Set smooth shading for the scene. We set it on the panel // 'withFocus' if this is a model editor, otherwise we set it // on the first modelEditor panel we find. string $currentPanel = `getPanel -withFocus`; if ( `getPanel -typeOf $currentPanel` == "modelPanel" ) modelEditor -e -da "smoothShaded" $currentPanel; else { string $visPanels[] = `getPanel -vis`; for ( $panel in $visPanels ) { if ( `getPanel -to $panel` == "modelPanel" ) { modelEditor -e -da "smoothShaded" $panel; break; } } } // Add support for the Context Sensitive Help Menu. // addContextHelpProc $panel "buildBlindDataEditorContextHelpItems"; } // This proc gets called just before the panel is // torn off or deleted // We'll save pertinent data here in the form of optionVars // so that next time the panel is opened the values get restored global proc bdeRemoveCallback( string $panel ) { string $cmd = "optionVar "; string $ov; int $iv; string $sv; string $val; // Bug 150384 check exact type so we don't get subd blind data string $nodes[] = `ls -exactType blindDataTemplate`; int $ids[]; int $numNodes = size( $nodes ); optionVar -iv polyBdeNumTemplates $numNodes; for ( $i = 0; $i < $numNodes; $i++ ) { $ids[$i] = getId( $nodes[$i] ); $ov = "polyBdeTemplateId" + $i; optionVar -iv $ov $ids[$i]; $dataCount = getDataCount( $nodes[$i] ); for ( $j = 0; $j < $dataCount; $j++ ) { $val = bdeGetControl( $nodes[$i], $j ); if ( $val != "" ) { $ov = "polyBdeApplyVal" + $i + "_" + $j; optionVar -sv $ov $val; } } } $iv = `checkBox -q -v bdeColorOnApply`; optionVar -iv polyBdeColorOnApply $iv; string $bdt = getSelectedApplyBdt(); if ( $bdt != "" ) { int $id = getId( $bdt ); optionVar -iv polyBdeApplyId $id; } float $nc[] = `canvas -query -rgbValue bdeNoneColor`; float $cc[] = `canvas -query -rgbValue bdeClashColor`; float $oc[] = `canvas -query -rgbValue bdeOutOfRangeColor`; for ( $i = 0; $i < 3; $i++ ) { optionVar -fva polyBdeNoneColor $nc[$i]; optionVar -fva polyBdeClashColor $cc[$i]; optionVar -fva polyBdeOutOfRangeColor $oc[$i]; } int $numRows = getQcNumFilledRows(); optionVar -iv polyBdeNumQcRows $numRows; for ( $i = 0; $i < $numRows; $i++ ) { string $row = getQcFilledRow( $i ); $iv = getQcEnable( $row ); $ov = "polyBdeQcEnable" + $i; optionVar -iv $ov $iv; $sv = getQcType( $row ); $ov = "polyBdeQcType" + $i; optionVar -sv $ov $sv; $iv = getQcValueEnable( $row ); $ov = "polyBdeQcValueEnable" + $i; optionVar -iv $ov $iv; float $color[] = getQcMainColor( $row ); $ov = "polyBdeQcMainColor" + $i; for ( $j = 0; $j < 3; $j++ ) optionVar -fva $ov $color[$j]; $color = getQcSaveColor( $row ); $ov = "polyBdeQcSaveColor" + $i; for ( $j = 0; $j < 3; $j++ ) optionVar -fva $ov $color[$j]; if ( $iv == 1 ) { string $selectType = getQcSelectType( $row ); $ov = "polyBdeQcSelectType" + $i; optionVar -sv $ov $selectType; string $values[] = getQcValues( $row ); int $numVals = size( $values ); $ov = "polyBdeQcNumVals" + $i; optionVar -iv $ov $numVals; for ( $j = 0; $j < $numVals; $j++ ) { $ov = "polyBdeQcValue" + $i + "_" + $j; optionVar -sv $ov $values[$j]; } } } bdeKillViewSelectedSJ(); } // This proc gets called when the panels is deleted global proc bdeDeleteCallback( string $panel ) { // Turn off false coloring... polyColorBlindData -enableFalseColor 0; } // Called automatically on file -new or -open // All of the blind data in the scene is probably // invalid, so we'll make this call here to simplify // clearing out all the controls. global proc bdeInitCallback( string $panel ) { bdeForceRebuild(); } // Fills all of the controls (and creates them if they don't // exist) with the data from the (saved) optionVars if the // blind data templates defining the data exist in the scene. global proc bdeRefreshFromOptionVars() { global string $gBdeQueryColorLayout; int $iv; string $sv; string $ov; int $dataCount; string $bdt; int $id; if ( `optionVar -ex polyBdeColorOnApply` ) { $iv = `optionVar -q polyBdeColorOnApply`; checkBox -e -v $iv bdeColorOnApply; } if ( `optionVar -ex polyBdeNumTemplates` ) { $numIds = `optionVar -q polyBdeNumTemplates`; for ( $i = 0; $i < $numIds; $i++ ) { $ov = "polyBdeTemplateId" + $i; if ( `optionVar -ex $ov` ) { $id = `optionVar -q $ov`; $bdt = getTemplateNameFromId( $id ); if ( $bdt != "" ) { $dataCount = getDataCount( $bdt ); string $vals[]; for ( $j = 0; $j < $dataCount; $j++ ) { $ov = "polyBdeApplyVal" + $i + "_" + $j; if ( `optionVar -ex $ov` ) { $sv = `optionVar -q $ov`; $dataType = getDataType( $bdt, $j ); if ( $dataType == "hex" ) $sv = intToHexString( $sv ); $vals[$j] = $sv; } else $vals[$j] = ""; } bdeSetControl( $bdt, $vals ); } } } } if ( `optionVar -ex polyBdeApplyId` ) { $iv = `optionVar -q polyBdeApplyId`; $successfulSet = setSelectedApply( $iv ); if ( $successfulSet ) bdeRebuildApply(); } if ( `optionVar -ex polyBdeNumQcRows` ) { int $numQcRows = `optionVar -q polyBdeNumQcRows`; for ( $i = 0; $i < $numQcRows; $i++ ) { $ov = "polyBdeQcType" + $i; if ( `optionVar -ex $ov` ) { string $typestr = `optionVar -q $ov`; $bdt = getTemplateNameFromTag( $typestr ); if ( $bdt == "" ) { string $typeidstr = match("[0-9]*", $typestr); if ( $typeidstr != "") $bdt = getTemplateNameFromId( $typeidstr ); } if ( $bdt != "" ) { $row = getEmptyQcRow(); float $mainColor[] = { 0, 0, 0 }; float $saveColor[] = { 0, 0, 0 }; $ov = "polyBdeQcMainColor" + $i; if ( `optionVar -ex $ov` ) $mainColor = `optionVar -q $ov`; $ov = "polyBdeQcSaveColor" + $i; if ( `optionVar -ex $ov` ) $saveColor = `optionVar -q $ov`; setQcTypeAndColors( $row, $typestr, $mainColor, $saveColor ); $ov = "polyBdeQcEnable" + $i; if ( `optionVar -ex $ov` ) { $iv = `optionVar -q $ov`; setQcEnable( $row, $iv ); } $ov = "polyBdeQcValueEnable" + $i; if ( `optionVar -ex $ov` ) { $iv = `optionVar -q $ov`; setQcValueEnable( $row, $iv ); } if ( getQcValueEnable( $row ) ) { $ov = "polyBdeQcSelectType" + $i; if ( `optionVar -ex $ov` ) { $sv = `optionVar -q $ov`; setQcSelectType( $row, $sv ); toggleCollapseQcSelectType( $row, 0 ); } $ov = "polyBdeQcNumVals" + $i; if ( `optionVar -ex $ov` ) { int $numVals = `optionVar -q $ov`; for ( $j = 0; $j < $numVals; $j++ ) { $ov = "polyBdeQcValue" + $i + "_" + $j; if ( `optionVar -ex $ov` ) { $sv = `optionVar -q $ov`; $dataType = getDataType( $bdt, $j ); if ( $dataType == "hex" ) { string $buffer[]; int $numToks = `tokenize $sv " " $buffer`; if ( $numToks == 2 ) { string $hexVal = intToHexString( $buffer[1] ); $sv = $buffer[0] + " " + $hexVal; } } setQcValue( $row, $j, $sv ); } } } } } } } } float $col[]; if ( `optionVar -ex polyBdeNoneColor` ) { $col = `optionVar -q polyBdeNoneColor`; canvas -edit -rgbValue $col[0] $col[1] $col[2] bdeNoneColor; } if ( `optionVar -ex polyBdeClashColor` ) { $col = `optionVar -q polyBdeClashColor`; canvas -edit -rgbValue $col[0] $col[1] $col[2] bdeClashColor; } if ( `optionVar -ex polyBdeOutOfRangeColor` ) { $col = `optionVar -q polyBdeOutOfRangeColor`; canvas -edit -rgbValue $col[0] $col[1] $col[2] bdeOutOfRangeColor; } // Here we delete all of the polyBde* optionVars, in case // some have changed or whatever. They'll get saved again // when we exit anyway... string $vars[] = `optionVar -list`; int $foundOne = false; for ( $var in $vars ) { if ( "polyBde" == `substring $var 1 7` ) { $foundOne = true; optionVar -rm $var; } else if ( $foundOne ) break; } } // Add callback is what gets called to generate the window, // and it contains all of the code to create the controls... global proc bdeAddCallback( string $panel ) { global string $gBdeQueryColorLayout; global string $gBdeTPresetLayout; string $fullName = `scriptedPanel -q -ctl $panel`; string $buffer[]; tokenize $fullName "|" $buffer; $isSeparate = `scriptedPanel -q -to $panel`; string $windowName = ""; if ( $isSeparate ) $windowName = $buffer[0]; // The mainLayout is the whole window. It contains the // bdeMainTabLayout (which is the tabLayout you see when // you open the blindDataEditor) and the buttons at the bottom // (which are always there too) $mainLayout = `formLayout`; tabLayout -tabsVisible true -scrollable true -imw 10 -imh 10 -psc bdeRebuild bdeMainTabLayout; $applyLayout = `formLayout`; $leftApply = `columnLayout -adj true -rs 20`; if (`about -mac`) { textScrollList -w 100 -h 300 -numberOfRows 20 -allowMultiSelection false -sc bdeRebuildApply bdeTypeList; } else { textScrollList -w 100 -numberOfRows 20 -allowMultiSelection false -sc bdeRebuildApply bdeTypeList; } columnLayout -adj true; button -label (uiRes("m_blindDataEditor.kPaintValues")) -c bdePaintValues; // Uncomment out the next call and the Paint Values button // won't bring up the Attribute Paint tool window (which // might get quite annoying) // Note that you can't bring up the attribute paint // tool from the main menu, however - it resets the values and // will probably mess everything up) // button -l "Paint options" -c bdePaintOptions; setParent ..; checkBox -v 0 -label (uiRes("m_blindDataEditor.kColordataonapply")) bdeColorOnApply; setParent ..; // $leftApply tabLayout -tabsVisible false -cr true -imw 10 -imh 10 bdeSingleApplyLayout; setParent ..; setParent ..; // $applyLayout formLayout -e -af $leftApply "top" 10 -af $leftApply "left" 10 -an $leftApply "bottom" -ac bdeSingleApplyLayout "left" 10 $leftApply -af bdeSingleApplyLayout "top" 10 -af bdeSingleApplyLayout "bottom" 10 -af bdeSingleApplyLayout "right" 10 $applyLayout; $qcLayout = `columnLayout`; if (!`uiTemplate -exists bdeQcMainLineTemplate`) uiTemplate bdeQcMainLineTemplate; if ( !`uiTemplate -exists bdeQcColorTemplate` ) uiTemplate bdeQcColorTemplate; // Create the template so that we don't have to define these // things everywhere rowLayout -defineTemplate bdeQcMainLineTemplate -nc 8 -cw 1 25 // Check -cw 2 110 // Type -cw 3 25 //-cat 4 "right" 5 // Check -cw 4 90 // Attr tag -cw 5 100 // Value -cw 6 5 //-cat 7 "left" 0 // Button -cw 7 80 // Canvas -cw 8 80; // Delete button rowColumnLayout -defineTemplate bdeQcColorTemplate -nc 3 -cw 1 25 -cw 2 250 -cw 3 85; string $new = (uiRes("m_blindDataEditor.kNew")); rowLayout -nc 2 -cw 1 120 -cw 2 200 -cat 1 "left" 10; button -label $new -c "bdeNewQcRow"; separator -st "none"; setParent ..; columnLayout; separator -w 400 -h 20; setParent ..; // Could have used other rowLayout templates for the // queryColorHeader as well as the clash color and // out of range color so that we don't have to use all // of these separators. There are only three static ones // here, however, so that's not too big of a deal for // the ease of layout control... rowLayout -ut bdeQcMainLineTemplate bdeQueryColorHeader; separator -st "none"; // Check text -label (uiRes("m_blindDataEditor.kTagId")); separator -st "none"; // A check text -label (uiRes("m_blindDataEditor.kLongNameTextHeader")) ; text -label (uiRes("m_blindDataEditor.kValue")); separator -st "none"; // Canvas separator -st "none"; // A button separator -st "none"; // A button to delete this row setParent ..; $gBdeQueryColorLayout = `columnLayout bdeQueryColorLayout`; setParent ..; separator -h 30 -st "none"; rowLayout -ut bdeQcMainLineTemplate; separator -st "none"; text -label (uiRes("m_blindDataEditor.kClashColor")); separator -st "none"; separator -st "none"; separator -st "none"; separator -st "none"; canvas -width 70 -height 25 -rgbValue 0 1 1 -pc ( "bdeChangeNamedCanvas bdeClashColor" ) bdeClashColor; setParent ..; separator -h 10 -st "none"; rowLayout -ut bdeQcMainLineTemplate; separator -st "none"; text -label (uiRes("m_blindDataEditor.kOutOfRangeColor")); separator -st "none"; separator -st "none"; separator -st "none"; separator -st "none"; canvas -width 70 -height 25 -rgbValue 1 1 0 -pc ( "bdeChangeNamedCanvas bdeOutOfRangeColor" ) bdeOutOfRangeColor; setParent ..; separator -h 10 -st "none"; rowLayout -ut bdeQcMainLineTemplate; separator -st "none"; text -label (uiRes("m_blindDataEditor.kNoneColor")); separator -st "none"; separator -st "none"; separator -st "none"; separator -st "none"; canvas -width 70 -height 25 -rgbValue 0 0 0 -pc ( "bdeChangeNamedCanvas bdeNoneColor" ) bdeNoneColor; setParent ..; setParent ..; // $qcLayout columnLayout -adj true bdeViewSelectedLayout; columnLayout -adj true bdeVSTempLayout; rowLayout -nc 2 -cw 1 160 -cw 2 200; text -label (uiRes("m_blindDataEditor.kDisplayComponent")); text -label "" bdeVsCompName; // Don't need this so much now that i found the script job // on selectionChange, but could prove useful if things // aren't working as expected... // button -l "Refresh" -c "bdeRefreshViewSelected"; setParent ..; setParent ..; separator -w 400 -h 10; columnLayout -adj true selectedLayout; setParent ..; setParent ..; // bdeViewSelectedLayout formLayout bdeDataTemplateLayout; formLayout -w 150 leftLayout; if (`about -mac`) { textScrollList -w 100 -h 300 -numberOfRows 20 -allowMultiSelection false -sc bdeTNameListChange bdeTemplateList; } else { textScrollList -w 100 -numberOfRows 20 -allowMultiSelection false -sc bdeTNameListChange bdeTemplateList; } columnLayout -adj true leftButtonLayout; button -label $new -c ( "bdeNewTemplate 1" ) bdeNewTemplateButton; button -label (uiRes("m_blindDataEditor.kEdit")) -c bdeEditTemplate bdeEditTemplateButton; button -label (uiRes("m_blindDataEditor.kSave")) -c bdeSaveTemplate bdeSaveTemplateButton; separator -h 20 -st "none"; button -label (uiRes("m_blindDataEditor.kExport")) -c bdeExportTemplates; button -label (uiRes("m_blindDataEditor.kTextDump")) -c bdeDumpTemplates; setParent ..; setParent ..; // leftLayout formLayout -e -af bdeTemplateList "left" 0 -af bdeTemplateList "top" 0 -af bdeTemplateList "right" 0 -an bdeTemplateList "bottom" -ac leftButtonLayout "top" 20 bdeTemplateList -af leftButtonLayout "left" 10 -af leftButtonLayout "right" 10 -af leftButtonLayout "bottom" 10 leftLayout; columnLayout -adj true -rs 5 rightLayout; rowColumnLayout -nc 2 -cw 1 105; text -align "left" -label (uiRes("m_blindDataEditor.kId")); intField -cc bdeTIdChange bdeTTypeId; text -align "left" -label (uiRes("m_blindDataEditor.kName")); textField bdeTTypeName; setParent ..; formLayout bdeTCommonLayout; rowColumnLayout -nc 2 -cw 1 105 bdeTCommonRcLayout; text -align "left" -label (uiRes("m_blindDataEditor.kAssociationType")); optionMenu bdeTAssocType; menuItem -label `assocType_melToUI "any"`; menuItem -label `assocType_melToUI "face"`; menuItem -label `assocType_melToUI "vertex"`; menuItem -label `assocType_melToUI "object"`; separator -st "none"; checkBox -label (uiRes("m_blindDataEditor.kFreeSet")) -v 1 -cc bdeTFreeSetChanged bdeTFreeSet; setParent ..; button -vis true -w 105 -label (uiRes("m_blindDataEditor.kNewAttr")) -c "bdeNewDescriptor" bdeNewDescriptorButton; setParent ..; formLayout -e -af bdeTCommonRcLayout "top" 0 -af bdeTCommonRcLayout "left" 0 -an bdeTCommonRcLayout "right" -an bdeTCommonRcLayout "bottom" -ac bdeNewDescriptorButton "top" 0 bdeTCommonRcLayout -an bdeNewDescriptorButton "bottom" -af bdeNewDescriptorButton "left" 0 -an bdeNewDescriptorButton "right" bdeTCommonLayout; columnLayout -adj true bdeTDescriptorLayout; bdeTBuildDescriptor( 0 ); bdeTBuildDescriptor( 1 ); bdeTBuildDescriptor( 2 ); setParent ..; bdeTOpenDescriptor( 0 ); formLayout presetFormLayout; button -vis true -w 105 -label (uiRes("m_blindDataEditor.kNewPreset")) -c "bdeTNewPreset" bdeNewPresetButton; $gBdeTPresetLayout = `columnLayout -adj true`; setParent ..; setParent ..; formLayout -e -af bdeNewPresetButton "top" 0 -af bdeNewPresetButton "left" 0 -an bdeNewPresetButton "right" -ac bdeNewPresetButton "bottom" 0 $gBdeTPresetLayout -af $gBdeTPresetLayout "left" 0 -an $gBdeTPresetLayout "top" -af $gBdeTPresetLayout "bottom" 0 -af $gBdeTPresetLayout "right" 0 presetFormLayout; setParent ..; // rightLayout formLayout -e -af leftLayout "left" 5 -af leftLayout "top" 5 -an leftLayout "right" -af leftLayout "bottom" 5 -ac rightLayout "left" 15 leftLayout -af rightLayout "top" 5 -af rightLayout "right" 5 -af rightLayout "bottom" 5 bdeDataTemplateLayout; setParent ..; // bdeDataTemplateLayout string $apply = (uiRes("m_blindDataEditor.kApply")); tabLayout -e -tabLabel $applyLayout $apply -tabLabel $qcLayout (uiRes("m_blindDataEditor.kColorQuery")) -tabLabel bdeViewSelectedLayout (uiRes("m_blindDataEditor.kView")) -tabLabel bdeDataTemplateLayout (uiRes("m_blindDataEditor.kTypeEditor")) bdeMainTabLayout; setParent ..; // bdeMainTabLayout $bottomCommonLayout = `formLayout`; button -en true -rs false -label $apply -c "bdeApplyData" bdeApplyButton; button -en false -rs false -label (uiRes("m_blindDataEditor.kSetColor")) -c "bdeColor" bdeSetColorButton; button -en false -rs false -label (uiRes("m_blindDataEditor.kQuery")) -c "bdeQuery" bdeQueryButton; button -label (uiRes("m_blindDataEditor.kRemoveColor")) -rs false -c "bdeRemoveColor" bdeRemColorButton; if ( $isSeparate ) { // Qt 4.8 with Alien widgets has some unwanted behaviour finding widgets under mouse // hide the window befoe deleting it,to prevent crash. MAYA-4487 button -label (uiRes("m_blindDataEditor.kClose")) -rs false -c ( "window -edit -vis 0 " + $windowName + "; evalDeferred( \"deleteUI -window " + $windowName + "\")" ) bdeCloseButton; } setParent ..; // Stole the following code from the polyConstraintWindow (which is a panel too). // Gist of it is that if the panel is not torn-off, there's no cancel button. // We also want to align the buttons evenly along the bottom row... // Force the buttons to have a common width, this will not only // look better but also allow the buttons to be centred in the // window. int $divisions = `formLayout -query -numberOfDivisions $bottomCommonLayout`; if ($isSeparate) { int $left = $divisions / 5; // Left division int $lmiddle = $divisions * 2/5; // LMiddle division int $rmiddle = $divisions * 3/5; // RMiddle division int $right = $divisions * 4/5; // Right division formLayout -e -af bdeApplyButton "top" 0 -af bdeApplyButton "bottom" 0 -af bdeApplyButton "left" 0 -ac bdeApplyButton "right" 0 bdeSetColorButton -af bdeSetColorButton "top" 0 -af bdeSetColorButton "bottom" 0 -ap bdeSetColorButton "left" 0 $left -ap bdeSetColorButton "right" 0 $lmiddle -af bdeQueryButton "top" 0 -af bdeQueryButton "bottom" 0 -ap bdeQueryButton "left" 0 $lmiddle -ap bdeQueryButton "right" 0 $rmiddle -af bdeRemColorButton "top" 0 -af bdeRemColorButton "bottom" 0 -ap bdeRemColorButton "left" 0 $rmiddle -ap bdeRemColorButton "right" 0 $right -af bdeCloseButton "top" 0 -af bdeCloseButton "bottom" 0 -ac bdeCloseButton "left" 0 bdeRemColorButton -af bdeCloseButton "right" 0 $bottomCommonLayout; } else { int $left = $divisions / 4; // Left division int $middle = $divisions / 2; // middle division int $right = $divisions * 3/4; // Right division formLayout -e -af bdeApplyButton "top" 0 -af bdeApplyButton "bottom" 0 -af bdeApplyButton "left" 0 -ac bdeApplyButton "right" 0 bdeSetColorButton -af bdeSetColorButton "top" 0 -af bdeSetColorButton "bottom" 0 -ap bdeSetColorButton "left" 0 $left -ap bdeSetColorButton "right" 0 $middle -af bdeQueryButton "top" 0 -af bdeQueryButton "bottom" 0 -ap bdeQueryButton "left" 0 $middle -ap bdeQueryButton "right" 0 $right -af bdeRemColorButton "top" 0 -af bdeRemColorButton "bottom" 0 -ac bdeRemColorButton "left" 0 bdeQueryButton -af bdeRemColorButton "right" 0 $bottomCommonLayout; } formLayout -e -af bdeMainTabLayout "left" 0 -af bdeMainTabLayout "top" 10 -ac bdeMainTabLayout "bottom" 0 $bottomCommonLayout -af bdeMainTabLayout "right" 0 -af $bottomCommonLayout "left" 0 -af $bottomCommonLayout "right" 0 -an $bottomCommonLayout "top" -af $bottomCommonLayout "bottom" 0 $mainLayout; // set the menu bar visibility (can be turned off from UIPrefs) // int $menusOkayInPanels = `optionVar -q allowMenusInPanels`; panel -e -mbv $menusOkayInPanels $panel; bdeForceRebuild(); bdeRefreshFromOptionVars(); } // From the apply tab again... // If we're 'Apply'ing to objects, we're applying dynamic attributes // and we have to do things a bit differently global proc bdeApplyDynamicAttr( string $bdt, string $applyType ) { string $data[]; string $dataType[]; string $longName[]; string $shortName[]; string $control; string $genericType; string $setAttrTypeString; string $addAttrTypeString; string $cmd = "setAttr "; // We use setAttr instead of polyBlindData command... int $dataCount = getDataCount( $bdt ); int $id = getId( $bdt ); string $rawSelList[] = `ls -sl`; string $selList[]; string $nodeList[]; string $sep[]; // We want all the *shapes* from the selection. // Often the selection uses the name of the transform, // so we use the listRelatives -shapes command to get the child // shapes. for ( $i = 0, $j = 0; $i < size( $rawSelList ); $i++ ) { $sep = getSelectionComp( $rawSelList[$i] ); $nodeType = `nodeType $sep[0]`; if ( "transform" == $nodeType ) { string $children[] = `listRelatives -shapes $sep[0]`; for ( $child in $children ) { $selList[$j++] = $child; } } else { $selList[$j++] = $sep[0]; } } // Filter out duplicates. for ( $i = 0, $j = 0; $i < size( $selList ); $i++ ) { int $foundIt = false; for ( $k = 0; $k < size( $nodeList ); $k++ ) { if ( $nodeList[$k] == $selList[$i] ) { $foundIt = true; break; } } if ( !$foundIt ) $nodeList[$j++] = $selList[$i]; } for ( $i = 0; $i < $dataCount; $i++ ) { $control = "bdeLongDataName" + $id + "_" + $i; $longName[$i] = `text -q -label $control`; // $control = "bdeShortDataName" + $id + "_" + $i; // $shortName[$i] = `text -q -l $control`; $shortName[$i] = getShortName( $bdt, $i ); $control = "bdeDataType" + $id + "_" + $i; $dataType[$i] = `text -q -label $control`; $control = "bdeDataValue" + $id + "_" + $i; $data[$i] = bdeGetControl( $bdt, $i ); } // We have to handle the case of the data being there already, and thus // we're just going to modify it, or we have to create the attribute. for ( $nodeIndex = 0; $nodeIndex < size( $nodeList ); $nodeIndex++ ) { string $node = $nodeList[$nodeIndex]; // We create/modify each attribute one by one instead of handling special // cases such as double2 or int3's. // This is more consistent with the component blind data also. for ( $i = 0; $i < $dataCount; $i++ ) { $genericType = getGenericDataType( $dataType[$i] ); if ( $genericType == "string" ) { $addAttrTypeString = " -dt \"string\" "; $setAttrTypeString = " -type \"string\" "; $data[$i] = "\"" + $data[$i] + "\""; } else { $addAttrTypeString = " -at \"" + $genericType + "\" "; $setAttrTypeString = ""; } if ( !`attributeQuery -n $node -ex $longName[$i]` && !`attributeQuery -n $node -ex $shortName[$i]` ) { // The attributes don't exist. // If they're trying to scale or offset the data we don't // let them, because it's not there! if ( $applyType != uiRes("m_blindDataEditor.kAbsolute") ) continue; // Create the attribute $cmd = "addAttr -ln " + $longName[$i] + " -sn " + $shortName[$i] + $addAttrTypeString + $node; // print( $cmd + "\n" ); eval( $cmd ); } else { // The attribute exists in one or both of the names we // think it should be. We check to make sure it's our attribute // and not some internal one or previously-defined one... string $msgExitInternal = (uiRes("m_blindDataEditor.kAttrExitInternal")) ; string $msgExitDiff = (uiRes("m_blindDataEditor.kAttrExitDiff")) ; string $msgSkipping = (uiRes("m_blindDataEditor.kSkipping")) ; if ( `attributeQuery -n $node -ex $longName[$i]` ) { if ( `attributeQuery -n $node -i $longName[$i]` || `attributeQuery -n $node -h $longName[$i]` ) { print `format -stringArg $longName[$i] $msgExitInternal` ; print $msgSkipping ; continue; } $cmd = "getAttr -type " + $node + "." + $longName[$i]; $type = `eval( $cmd )`; if ( $type != $genericType ) { print `format -stringArg $longName[$i] $msgExitDiff` ; print $msgSkipping ; continue; } } if ( `attributeQuery -n $node -ex $shortName[$i]` ) { if ( `attributeQuery -n $node -i $shortName[$i]` || `attributeQuery -n $node -h $shortName[$i]` ) { print `format -stringArg $shortName[$i] $msgExitInternal` ; print $msgSkipping ; continue; } $cmd = "getAttr -type " + $node + "." + $shortName[$i]; $type = `eval( $cmd )`; if ( $type != $genericType ) { print `format -stringArg $shortName[$i] $msgExitDiff` ; print $msgSkipping ; continue; } } } if ( $applyType == uiRes("m_blindDataEditor.kAbsolute") ) { $cmd = "setAttr " + $setAttrTypeString + $node + "." + $longName[$i] + " " + $data[$i]; // print( $cmd + "\n" ); eval( $cmd ); } else { // This shouldn't even happen, but just in case if ( $genericType == "string" || $genericType == "boolean" ) continue; float $floatVal; int $intVal; $cmd = "getAttr " + $setAttrTypeString + $node + "." + $longName[$i]; if ( $genericType == "double" ) $floatVal = `eval( $cmd )`; else if ( $genericType == "int" ) $intVal = `eval( $cmd )`; float $newFloatVal; int $newIntVal; if ( $applyType == uiRes("m_blindDataEditor.kOffset") ) { $controlName = "bdeDataOffset" + $id + "_" + $i; if ( $genericType == "double" ) { float $offset = `floatSliderGrp -q -v $controlName`; $newFloatVal = $floatVal + $offset; } else { int $offset = `intSliderGrp -q -v $controlName`; $newIntVal = $intVal + $offset; } } else { $controlName = "bdeDataScale" + $id + "_" + $i; float $scale = `floatSliderGrp -q -v $controlName`; if ( $genericType == "double" ) $newFloatVal = $floatVal * $scale; else $newIntVal = round( $intVal * $scale ); } int $ranged = getRanged( $bdt, $i ); if ( $ranged ) { // Here's where we clamp the values if the attr's ranged. // If you don't want the data clamped, remove these checks float $min = getMinVal( $bdt, $i ); float $max = getMaxVal( $bdt, $i ); if ( $genericType == "double" ) { if ( $newFloatVal > $max ) $newFloatVal = $max; if ( $newFloatVal < $min ) $newFloatVal = $min; } else { if ( $newIntVal > $max ) $newIntVal = $max; if ( $newIntVal < $min ) $newIntVal = $min; } } $cmd = "setAttr " + $setAttrTypeString + $node + "." + $longName[$i] + " "; if ( $genericType == "double" ) $cmd += $newFloatVal; else $cmd += $newIntVal; // print( $cmd + "\n" ); eval( $cmd ); } } } } // Apply the absolute data // The polyBlindData command works on the selection list by default, // and we're assuming here that that has been converted if it's going // to be. proc applyAbsolute( string $bdt ) { int $id = getId( $bdt ); string $control = "bdeAssocType" + $id; string $assocType = assocType_uiToMel( `optionMenu -q -v $control` ); string $baseCmd = "polyBlindData -id " + $id; $baseCmd += " -associationType \"" + $assocType + "\""; if( $assocType == "object") $baseCmd += " -shape "; int $dataCount = getDataCount( $bdt ); for ( $i = 0; $i < $dataCount; $i++ ) { string $cmd = $baseCmd; string $longName = getLongName( $bdt, $i ); string $dataType = getDataType( $bdt, $i ); string $dataTypeFlag = getDataTypeFlag( $dataType ); $cmd += " -longDataName \"" + $longName + "\""; $cmd += " " + $dataTypeFlag; // The command can handle the data in the form of a string // which makes things a bit easier on us (no conversions!) string $data = bdeGetControl( $bdt, $i ); if ( $dataType == "string" || $dataType == "binary" ) $cmd += " \"" + $data + "\""; else $cmd += " " + $data; // print( $cmd + "\n" ); eval ( $cmd ); } } // Apply scale or offset values. This is a bit trickier, because we've // got to get the data first. We use the polyQueryBlindData command // and if the data's not there we skip it. proc applyRelative( string $bdt, string $applyType, string $assocType ) { string $dataType; string $control; int $id = getId( $bdt ); int $dataCount = getDataCount( $bdt ); for ( $i = 0; $i < $dataCount; $i++ ) { string $dataType = getDataType( $bdt, $i ); string $attrName = getLongName( $bdt, $i ); if ( $dataType == "string" || $dataType == "binary" || $dataType == "boolean" || $dataType == "hex" ) continue; string $cmd = "polyQueryBlindData -id " + $id; $cmd += " -ldn " + $attrName + " -sc"; print( $cmd + "\n" ); string $sc[] = `eval( $cmd )`; for ( $j = 0; $j < size( $sc ); $j++ ) { $attr = $sc[$j++]; $val = $sc[$j]; string $buf[]; int $numTokens = tokenize( $attr, ".", $buf ); if ( $numTokens != 3 ) continue; $comp = $buf[0] + "." + $buf[1]; float $floatVal, $newFloatVal; int $intVal, $newIntVal; if ( $dataType == "double" ) $floatVal = $val; else $intVal = $val; if ( $applyType == uiRes("m_blindDataEditor.kOffset") ) { $control = "bdeDataOffset" + $id + "_" + $i; if ( $dataType == "double" ) { float $offset = `floatSliderGrp -q -v $control`; $newFloatVal = $floatVal + $offset; } else { int $offset = `intSliderGrp -q -v $control`; $newIntVal = $intVal + $offset; } } else { $control = "bdeDataScale" + $id + "_" + $i; float $scale = `floatSliderGrp -q -v $control`; if ( $dataType == "double" ) $newFloatVal = $floatVal * $scale; else $newIntVal = round( $intVal * $scale ); } int $ranged = getRanged( $bdt, $attrName ); if ( $ranged ) { // This is where the clamping happens for poly component // blind data. Comment out these checks if you don't want // the values to be clamped at the min and max. float $min = getMinVal( $bdt, $attrName ); float $max = getMaxVal( $bdt, $attrName ); if ( $dataType == "double" ) { if ( $newFloatVal > $max ) $newFloatVal = $max; if ( $newFloatVal < $min ) $newFloatVal = $min; } else { if ( $newIntVal > $max ) $newIntVal = $max; if ( $newIntVal < $min ) $newIntVal = $min; } } $cmd = "polyBlindData -id " + $id + " -at \"" + $assocType; $cmd += "\" -ldn \"" + $attrName + "\" "; if ( $dataType == "double" ) $cmd += "-dbd " + $newFloatVal; else $cmd += "-ind " + $newIntVal; $cmd += " " + $comp; // print( $cmd + "\n" ); eval( $cmd ); } } } // This gets called when the 'apply' button is hit, or on mouse up // when the attribute paint tool is working. // Figures out things like component selection global proc bdeApplyData() { string $parent = "bdeSingleApplyLayout"; string $selected[] = `ls -sl`; if ( size( $selected ) == 0 ) return; string $bdt = getSelectedApplyBdt(); if ( $bdt == "" ) return; int $id = getId( $bdt ); string $controlName = "bdeAssocType" + $id; string $assocType = assocType_uiToMel( `optionMenu -q -v $controlName` ); string $control = "bdeApplyType" + $id; string $applyType = `optionMenu -q -v $control`; // Dynamic stuff does the conversions implicitly. if ( $assocType == "object" ) { // bdeApplyDynamicAttr( $bdt, $applyType ); applyAbsolute( $bdt ); if ( `checkBox -q -v bdeColorOnApply` ) bdeDoQueryColor( 1 ); return; } else // Convert to desired assocType and do the apply. // Let's hope this is what's desired from the user // If not, comment out this code... { string $origSel[] = `ls -sl`; string $newSel[] = convList( $origSel, $assocType ); string $select = "select -r "; for ( $sel in $newSel ) $select += "\"" + $sel + "\" "; eval $select; } if ( $applyType == uiRes("m_blindDataEditor.kAbsolute") ) applyAbsolute( $bdt ); else applyRelative( $bdt, $applyType, $assocType ); if ( `checkBox -q -v bdeColorOnApply` ) bdeColor(); } // We just turn off the mode. This removes the // false coloring from all of the poly components. global proc bdeRemoveColor() { polyColorBlindData -efc 0; } // Call this so the scriptJob script doesn't keep getting // called even though we don't care about refreshing the viewSelected tab. global proc bdeKillViewSelectedSJ() { global int $gBdeVSSJ; if ( $gBdeVSSJ == -1 ) return; scriptJob -kill $gBdeVSSJ; $gBdeVSSJ = -1; } global proc bdeStartViewSelectedSJ() { global int $gBdeVSSJ; if ( $gBdeVSSJ != -1 ) return; $gBdeVSSJ = `scriptJob -event "SelectionChanged" bdeRefreshViewSelected`; } // Fix up the buttons (enabling/disabling as appropriate), // rebuild the textscroll lists, popups, etc. global proc bdeRebuild() { bdeKillViewSelectedSJ(); bdeRebuildTextScrollLists(); bdeRebuildPopups(); int $tab = `tabLayout -q -sti bdeMainTabLayout`; if ( 1 == $tab ) // Apply! { // Fix buttons: Apply and Cancel only button -e -en true bdeApplyButton; button -e -en false bdeSetColorButton; button -e -en false bdeQueryButton; } else if ( 2 == $tab ) // Color/Query { button -e -en false bdeApplyButton; button -e -en true bdeSetColorButton; button -e -en true bdeQueryButton; } else if ( 3 == $tab ) // View selected { // bdeRebuildViewSelected(); bdeStartViewSelectedSJ(); button -e -en false bdeApplyButton; button -e -en false bdeSetColorButton; button -e -en false bdeQueryButton; bdeRefreshViewSelected(); } else if ( 4 == $tab ) // Template editor { button -e -en false bdeApplyButton; button -e -en false bdeSetColorButton; button -e -en false bdeQueryButton; // bdeNewTemplate( true ); } } // This was copied from initContexts.mel // proc rememberCtxSettings( string $ctxName ) // // This method sees if an optionVar has been defined // for the tool. If it has, the string it contains // is evaluated to set the tool settings. SuperContexts // should not be saved this way, since they have no // particular settings. // { if ( `optionVar -exists $ctxName` ){ string $cmd = `optionVar -q $ctxName`; catch( `eval($cmd)` ); } else { // create an empty option var so that this // will be saved. optionVar -sv $ctxName ""; } } global proc bdeFacetMask() { setComponentPickMask "Facet" true; } global proc bdeVertexMask() { setComponentPickMask "Point" true; } // Paint on the values. global proc bdePaintValues() { string $bdt = getSelectedApplyBdt(); if ( ""== $bdt ) { warning (uiRes("m_blindDataEditor.kWarningNoBlindDataId")); return; } int $id = getId( $bdt ); string $controlName = "bdeAssocType" + $id; string $assocType = assocType_uiToMel( `optionMenu -q -v $controlName` ); string $preStrokeCmd; // Shouldn't be too hard to fix things up for object (dyn attr) painting if ( $assocType == "object" ) { warning (uiRes("m_blindDataEditor.kWarningPaintWorks")); return; } else if ( $assocType == "vertex" ) $preStrokeCmd = "bdeVertexMask"; else if ( $assocType == "face" ) $preStrokeCmd = "bdeFacetMask"; global string $gBdeBrushToolCtx; // Set the ToolContext up... if ( $gBdeBrushToolCtx == "" ) { // This xpm doesn't show up on NT... $gBdeBrushToolCtx = `eval "artSelectCtx -i1 \"paintVertexColour.png\" \ -ads false \ bdeBrushToolCtx"`; rememberCtxSettings $gBdeBrushToolCtx; } string $cmd; $cmd = "artSelectCtx -e"; $cmd += " -bsc " + $preStrokeCmd; $cmd += " -asc bdeApplyData"; $cmd += " " + $gBdeBrushToolCtx; eval $cmd; setToolTo $gBdeBrushToolCtx; // I think this isn't working even if this button exists??? // Anyway, if this is bugging you comment it out, and uncomment the // paintOptionsOptions button code in the AddCallback if ( !`button -q -ex bdePaintOptions` ) toolPropertyWindow; } global proc bdePaintOptions() { toolPropertyWindow; } global proc bdeClosedWindow() { polyColorBlindData -enableFalseColor 0; } // Not used anymore global proc bdeForceRefresh( string $windowName ) { if ( `window -ex $windowName` ) bdeForceRebuild(); } // Initialize the blind data editor as a scripted panel global proc initBlindDataEditor() { if ( !`scriptedPanelType -q -ex blindDataEditor` ) { scriptedPanelType -createCallback bdeCreateCallback -initCallback bdeInitCallback -addCallback bdeAddCallback -removeCallback bdeRemoveCallback -deleteCallback bdeDeleteCallback -unique true -label (localizedPanelLabel( "Blind Data Editor" )) blindDataEditor; } } // The 'main' of this script. It registers the // panel type if it doesn't already exist, and then // creates a torn off version of the panel. Once it's registered, // it can be pulled up like a regular panel. global proc blindDataEditor() { if (!isLegacyViewportEnabled()) return; initBlindDataEditor(); tearOffRestorePanel (localizedPanelLabel( "Blind Data Editor" )) "blindDataEditor" 1; }