// =========================================================================== // 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. // =========================================================================== // // // Creation Date: 31 Oct 1996 // // Description: // Adding new attributes to a particle object. // // Contents // getAttrListDAA Return a complete list of render attributes. // getAttrInfoDAA Return the attribute description. // getDefaultDAA Return the default value of the attribute. // getParticlesDAA Return a list of particle objects. // getModeDAA Returns id of active tab. // findAttrDAA Check if attribute already exists. // setMinMaxModeDAA Enable/disable the min max textfields. // doAddPreDAA Add a predefined attribute to an object. // doAddNewDAA Add a new attribute to an object. // doAddControlDAA ??? // setBlendKeysDAA ??? // setNodeKeysDAA ??? // doItDAA Do the actual addAttr command. // okayDAA Okay button callback. // addDAA Add button callback. // makeNewAttrDAA Build the New Attribute tab. // makeParticleDAA Build the Particle attr tab. // makeNewPoseDAA Build the Control tab. // createWinDAA Create the window and controls. // registerDAA Register all the callbacks. // resetDAA Reset the dialog when posting. // dynAddAttrWin Main entry point. Create and post dialog. // // Static data used by this dialog. // global string $gAttrTypeDAA[]; // Predefined attribute descriptions. global string $gObjectsDAA[]; // List of selected objects. global int $gDataTypeDAA = 2; // Data Type: float, int, ... global int $gScalarAryDAA = 1; // Attribute type: 1 = scalar, 2 = array. global int $gParticleModeDAA = 0; // Particle mode: 1 = allow array, 0 = no arrays. // ========== getAttrListDAA ========== // // Description: // Return a complete list of render attributes. Each particle // render plug-in is queried for its attribute list. This list // is then sorted and duplicate entries are removed. The global // array gAttrTypeDAA stores the data type for each attribute // for future reference. // global proc string[] getAttrListDAA( ) { global string $gAttrTypeDAA[]; string $finalAry[]; // Get a complete list of render attributes. // string $attrAry[] = `particleRenderInfo -q -attrListAll`; // Add some special predefined attrs which aren't associated // with rendering. // int $i = size( $attrAry ); $attrAry[$i] = "parentU:-:floatArray"; $i++; $attrAry[$i] = "parentV:-:floatArray"; $i++; $attrAry[$i] = "parentId:-:floatArray"; $i++; $attrAry[$i] = "goalU:-:floatArray"; $i++; $attrAry[$i] = "goalV:-:floatArray"; $i++; $attrAry[$i] = "goalWeight0PP:-:floatArray"; $i++; $attrAry[$i] = "goalWeight1PP:-:floatArray"; $i++; $attrAry[$i] = "goalWeight2PP:-:floatArray"; $i++; $attrAry[$i] = "goalWeight3PP:-:floatArray"; $i++; $attrAry[$i] = "goalWeight4PP:-:floatArray"; $i++; $attrAry[$i] = "goalOffset:-:vectorArray"; $i++; $attrAry[$i] = "collisionU:-:floatArray"; $i++; $attrAry[$i] = "collisionV:-:floatArray"; $i++; $attrAry[$i] = "collisionGeometryIndex:-:floatArray"; $i++; $attrAry[$i] = "collisionActiveGeometryIndex:-:floatArray"; $i++; $attrAry[$i] = "collisionPosition:-:vectorArray"; $i++; $attrAry[$i] = "collisionWorldPosition:-:vectorArray"; $i++; $attrAry[$i] = "collisionNormal:-:vectorArray"; $i++; $attrAry[$i] = "collisionWorldNormal:-:vectorArray"; $i++; $attrAry[$i] = "collisionIncomingVelocity:-:vectorArray"; $i++; $attrAry[$i] = "collisionWorldIncomingVelocity:-:vectorArray"; $i++; $attrAry[$i] = "collisionOutgoingVelocity:-:vectorArray"; $i++; $attrAry[$i] = "collisionWorldOutgoingVelocity:-:vectorArray"; $i++; $attrAry[$i] = "collisionForce:-:vectorArray"; $i++; $attrAry[$i] = "collisionWorldForce:-:vectorArray"; $i++; $attrAry[$i] = "collisionComponentId:-:floatArray"; $i++; $attrAry[$i] = "collisionSelfComponentId:-:floatArray"; $i++; $attrAry[$i] = "collisionTime:-:floatArray"; $i++; $attrAry[$i] = "traceDepthPP:-:floatArray"; $i++; $attrAry[$i] = "birthWorldPosition:-:vectorArray"; $i++; $attrAry[$i] = "birthPosition:-:vectorArray"; $i++; $attrAry[$i] = "pointFieldScalePP:-:floatArray"; $i++; $attrAry[$i] = "collideStrengthPP:-:floatArray"; $i++; $attrAry[$i] = "frictionScalePP:-:floatArray"; $i++; $attrAry[$i] = "stickinessScalePP:-:floatArray"; $i++; $attrAry[$i] = "bounceScalePP:-:floatArray"; $i++; $attrAry[$i] = "viscosityScalePP:-:floatArray"; $i++; $attrAry[$i] = "surfaceTensionScalePP:-:floatArray"; $i++; $attrAry[$i] = "restDensityPP:-:floatArray"; $i++; $attrAry[$i] = "rotationPP:-:vectorArray"; $i++; $attrAry[$i] = "rotationDampPP:-:floatArray"; $i++; $attrAry[$i] = "rotationFrictionPP:-:floatArray"; $i++; $attrAry[$i] = "angularVelocityPP:-:vectorArray"; $i++; $attrAry[$i] = "userScalar1PP:-:floatArray"; $i++; $attrAry[$i] = "userScalar2PP:-:floatArray"; $i++; $attrAry[$i] = "userScalar3PP:-:floatArray"; $i++; $attrAry[$i] = "userScalar4PP:-:floatArray"; $i++; $attrAry[$i] = "userScalar5PP:-:floatArray"; $i++; $attrAry[$i] = "userVector1PP:-:vectorArray"; $i++; $attrAry[$i] = "userVector2PP:-:vectorArray"; $i++; $attrAry[$i] = "userVector3PP:-:vectorArray"; $i++; $attrAry[$i] = "userVector4PP:-:vectorArray"; $i++; $attrAry[$i] = "userVector5PP:-:vectorArray"; $i++; // Re-sort array so attributes appear in correct order. // $attrAry = sort( $attrAry ); int $attrCnt = size( $attrAry ); for ($i = 0; $i < $attrCnt; $i++) { string $tokenAry[]; tokenize( $attrAry[$i], ":", $tokenAry ); $finalAry[$i] = $tokenAry[0]; $gAttrTypeDAA[$i] = $attrAry[$i]; } return( $finalAry ); } // ========== getAttrInfoDAA ========== // // Description: // Return the attribute information from the global // array of predefined attributes. // proc string getAttrInfoDAA( string $attrName ) { global string $gAttrTypeDAA[]; string $tokenAry[]; int $arrayCnt = size( $gAttrTypeDAA ); for ($i = 0; $i < $arrayCnt; $i++) { tokenize( $gAttrTypeDAA[$i], ":", $tokenAry ); if ($attrName == $tokenAry[0]) { return( $gAttrTypeDAA[$i] ); } } return( "" ); } // ========== getDefaultDAA ========== // // Description: // Return the default value of the attribute. // proc string getDefaultDAA( string $attrName ) { global string $gAttrTypeDAA[]; for ($i = 0; $i < size( $gAttrTypeDAA ); $i++) { string $tokenAry[]; tokenize( $gAttrTypeDAA[$i], ":", $tokenAry ); if ($attrName == $tokenAry[0]) { return( "-dv "+$tokenAry[1] ); } } return( "" ); } // ========== getParticlesDAA ========== // // Description: // Return a list of particle objects from the current // selection list. // proc string[] getParticlesDAA() { string $listA[] = `ls -selection -dag -leaf -showType`; string $listB[]; int $n = 0; for ($i = 0; $i < size( $listA ); $i += 2) { if ($listA[$i+1] == "particle" || $listA[$i+1] == "nParticle") { $listB[$n++] = $listA[$i]; } } return( $listB ); } // ========== getModeDAA ========== // // Description: // Returns the id of the active tab. This abstracts the // tab indecies and labels, in case the tabs are reordered // or relabeled. Be sure and update this proc if the tabs // are re-ordered, or if a new tab is added. // // Return Values: // // 1 - New Attribute tab // 2 - Particle Attribute tab // 3 - Control tab // proc int getModeDAA() { global string $gAddAttrWin; setParent $gAddAttrWin; int $activeTab = `tabLayout -q -sti tabLyt`; switch( $activeTab ) { case 1 : return( 1 ); case 2 : return( 2 ); case 3 : return( 3 ); } } // ========== findAttrDAA ========== // // Description: // Check if the attribute already exists. // proc int findAttrDAA( string $object, string $attr ) { string $attrAry[] = `listAttr $object`; for ($i = 0; $i < size( $attrAry ); $i++) { if ($attr == $attrAry[$i]) { return( 1 ); } } return( 0 ); } // ========== setMinMaxModeDAA ========== // // Description: // Enable/disable the min/max/default textfields. // Inspect the current selections for Data Type and // Attribute Type to determine if the textfields should // be dimmed or enabled. // global proc setMinMaxModeDAA(int $buttonId ) { global int $gDataTypeDAA; global int $gScalarAryDAA; global int $gParticleModeDAA; // Particle mode: 1 = allow array, 0 = no arrays. global string $gAddAttrWin; setParent $gAddAttrWin; // Each time a radio button is pressed, need to validate // the combination of data type and attribute type. Since // the particle object only knows about vectorAry and floatAry // attributes, don't allow the user to add intAry and boolAry. // switch ($buttonId) { case 1 : // Vector button. Arrays are okay radioButton -e -enable $gParticleModeDAA arrayBtn; radioButton -e -enable 1 scalarBtn; break; case 2 : // Float button. Arrays are okay. radioButton -e -enable $gParticleModeDAA arrayBtn; radioButton -e -enable 1 scalarBtn; break; case 3 : // Integer button. No arrays. radioButton -e -enable false arrayBtn; radioButton -e -enable 1 -select scalarBtn; $gScalarAryDAA = 1; break; case 4 : // Boolean button. No arrays. radioButton -e -enable false arrayBtn; radioButton -e -enable 1 -select scalarBtn; $gScalarAryDAA = 1; break; case 5 : // Scalar button. All types are okay. radioButton -e -enable true intBtn; radioButton -e -enable true boolBtn; radioButton -e -enable true stringBtn; radioButton -e -enable true enumBtn; radioButton -e -enable 1 scalarBtn; break; case 6 : // Array button. Integer, Boolean, string, enum not allowed. radioButton -e -enable false intBtn; radioButton -e -enable false boolBtn; radioButton -e -enable false stringBtn; radioButton -e -enable false enumBtn; radioButton -e -enable 1 scalarBtn; if ((`radioButton -q -select intBtn`) || (`radioButton -q -select boolBtn`)) { radioButton -e -select floatBtn; $gDataTypeDAA = 2; } break; case 7 : // String button. No arrays radioButton -e -enable false arrayBtn; $gScalarAryDAA = 1; break; case 8 : // Enum button. No arrays radioButton -e -enable false arrayBtn; $gScalarAryDAA = 1; break; default: // No button pressed, simply updating dialog. break; } // Enable/disable the textfield portion of the dialog. // int $mode = 1; int $enumSelected = `radioButton -q -select enumBtn`; if (`radioButton -q -select arrayBtn`) { $mode = 0; } else if (`radioButton -q -select vectorBtn` || `radioButton -q -select boolBtn` || `radioButton -q -select stringBtn` || $enumSelected ) { $mode = 0; } frameLayout -e -enable $mode minMaxLyt; global string $gAddAttrEnumScrollList; global string $gAddAttrEnumTextGrp; global string $gAddAttrEnumText; if( $enumSelected ) { attrEnumScrollList_fill( "", $gAddAttrEnumScrollList, $gAddAttrEnumTextGrp, $gAddAttrEnumText ); } else { attrEnumScrollList_clear( $gAddAttrEnumScrollList, $gAddAttrEnumTextGrp, $gAddAttrEnumText ); } // frameLayout -e -enable $enumSelected enumLyt; if (`radioButton -q -select arrayBtn`) { checkBox -e -enable 1 initBtn; } else { checkBox -e -enable 0 initBtn; } } // ========== correctDefVal ========== // // Description: // Correct default value field when min/max and default value changed. // The default value should not be less than min value or larger than // max value. // global proc correctDefVal() { string $minFldStr = `textField -q -text minFld`; string $maxFldStr = `textField -q -text maxFld`; float $defValFloat = `textField -q -text defFld`; if( size( $minFldStr ) && size( $maxFldStr ) ) { float $minValFloat = $minFldStr; float $maxValFloat = $maxFldStr; float $newMinVal = min( $minValFloat, $maxValFloat ); float $newMaxVal = max( $minValFloat, $maxValFloat ); $minFldStr = $newMinVal; $maxFldStr = $newMaxVal; } if (size($maxFldStr) > 0) { float $maxValFloat = $maxFldStr; if ($defValFloat > $maxValFloat) { textField -e -text $maxValFloat defFld; string $warn = (uiRes("m_dynAddAttrWin.kDefValLargerThanMaxWarn")); warning(`format -s $defValFloat -s $maxValFloat $warn`); } } if (size($minFldStr) > 0) { float $minValFloat = $minFldStr; if ($defValFloat < $minValFloat) { textField -e -text $minValFloat defFld; string $warn = (uiRes("m_dynAddAttrWin.kDefValLessThanMinWarn")); warning(`format -s $defValFloat -s $minValFloat $warn`); } } } // ========== doAddPreDAA ========== // // Description: // Add a predefined attribute to an object. For predefined // attributes, the type is stored in an array indexed by the // attribute name. Predefined attributes are only added to // particle objects. All predefined attributes are set to // be keyable. // proc doAddPreDAA( string $attr, string $object ) { // Make sure we have a particle object. If $object is not a particle, // see if it has a particle child, and use it. // int $isParticle = (`nodeType $object` == "particle") || (`nodeType $object` == "nParticle"); if (!$isParticle) { // If the node itself is not a particle, see if it has a particle // as a child shape. If so, add the attribute to it. // string $relatives[] = `listRelatives -c $object`; for ($i = 0; $i < size($relatives); $i++) { if ((`nodeType $relatives[$i]` == "particle") || (`nodeType $relatives[$i]` == "nParticle")) { $object = $relatives[$i]; $isParticle = true; break; } } } if ($isParticle) { string $attrInfo = getAttrInfoDAA( $attr ); if ($attrInfo != "") { dynAddParticleAttr( $object, $attrInfo ); } } else { string $warn = (uiRes("m_dynAddAttrWin.kParticleShapeWarn")); warning(`format -s $attr $warn`); } } // ========== doAddNewDAA ========== // // Description: // Add an new user attribute to an object. // proc doAddNewDAA( string $attr, string $object ) { global string $gAddAttrWin; global int $gDataTypeDAA; global int $gScalarAryDAA; string $attrType; setParent $gAddAttrWin; // Check if the attribute already exists. // if (findAttrDAA( $object, $attr)) { string $attrExistsError = (uiRes("m_dynAddAttrWin.kAttrExistsError")); error(`format -s $attr $attrExistsError`); return; } global string $gAddAttrEnumScrollList; global string $gAddAttrEnumTextGrp; int $isParticle = (`nodeType $object` == "particle" || `nodeType $object` == "nParticle"); // Set the attribute data type. // switch ($gDataTypeDAA) { case 1 : // vector if (($gScalarAryDAA == 2) && $isParticle ) { $attrType = "-dt vectorArray"; } else { $attrType = "-at double3"; } break; case 2 : // float if (($gScalarAryDAA == 2) && $isParticle ) { $attrType = "-dt doubleArray"; } else { $attrType = "-at double"; } break; case 3 : // int if (($gScalarAryDAA == 2) && $isParticle ) { $attrType = "-dt Int32Array"; } else { $attrType = "-at long"; } break; case 4 : // boolean if (($gScalarAryDAA == 2) && $isParticle ) { $attrType = "-dt Int32Array"; } else { $attrType = "-at bool"; } break; case 7 : // string $attrType = "-dt \"string\""; break; case 8 : // enum string $enumString = attrEnumScrollList_enumString( $gAddAttrEnumScrollList, $gAddAttrEnumTextGrp ); $attrType = "-at \"enum\" "; if( size( $enumString ) > 0 ) { $attrType += ( "-en \"" + $enumString + "\"" ); } break; } // set the nice name // string $niceName = " "; string $niceNameX = " "; string $niceNameY = " "; string $niceNameZ = " "; if( `textFieldGrp -q -enable niceNameGrp` ) { $niceName = ( "-nn \"" + `textFieldGrp -q -text niceNameGrp` + "\" " ); $niceNameX =( "-nn \"" + `textFieldGrp -q -text niceNameGrp` + " X\" " ); $niceNameY =( "-nn \"" + `textFieldGrp -q -text niceNameGrp` + " Y\" " ); $niceNameZ =( "-nn \"" + `textFieldGrp -q -text niceNameGrp` + " Z\" " ); } string $range = ""; // set min/max/default value only when they are enabled // string $minVal; if (`textField -q -enable minFld`) $minVal = `textField -q -text minFld`; string $maxVal; if (`textField -q -enable maxFld`) $maxVal = `textField -q -text maxFld`; string $defVal; if (`textField -q -enable defFld`) $defVal = `textField -q -text defFld`; // In case they entered both min and max values, // make sure min is the smaller and max is the larger. // if( size( $minVal ) && size( $maxVal ) ) { float $minValFloat = $minVal; float $maxValFloat = $maxVal; float $newMinVal = min( $minValFloat, $maxValFloat ); float $newMaxVal = max( $minValFloat, $maxValFloat ); $minVal = $newMinVal; $maxVal = $newMaxVal; } if (size( $minVal )) { $range += (" -min " + $minVal); } if (size( $maxVal )) { $range += (" -max " + $maxVal); } if (size( $defVal )) { $range += (" -dv " + $defVal); } // Add the initial state attribute first. // if (($gScalarAryDAA == 2) && `checkBox -q -value initBtn`) { string $initAttr = $attr+"0"; if (findAttrDAA( $object, $initAttr)) { // // Do not fail if the initial state attribute already exists. // If this attribute was added, but then deleted, the initial // state attribute may not have been deleted. Now, if they // want to add the attribute again, the initial state // version will already be there. This should not be an // error. // // Rob Tesdahl, Jan 15, 1999 // // error( $initAttr+": initial state attr. already exists." ); // return; string $initialStateWarn = (uiRes("m_dynAddAttrWin.kInitialStateAttr")); warning(`format -s $initAttr $initialStateWarn`); } else { evalEcho( "addAttr -ln \"" + $initAttr + "\" " + $niceName + $attrType + " " + $range + " " + $object + ";" ); } } // Now add the user attribute. // evalEcho( "addAttr -ln \"" + $attr + "\" " + $niceName + $attrType + " " + $range + " " + $object + ";" ); // If we're adding a compound triple, we MUST add the // children or the parent will not show up in the attribute editor. // if( $attrType == "-at double3" ) { evalEcho( "addAttr -ln \"" + $attr + "X\" " + $niceNameX + "-at double -p " + $attr + " " + $range + " " + $object + ";" ); evalEcho( "addAttr -ln \"" + $attr + "Y\" " + $niceNameY + "-at double -p " + $attr + " " + $range + " " + $object + ";" ); evalEcho( "addAttr -ln \"" + $attr + "Z\" " + $niceNameZ + "-at double -p " + $attr + " " + $range + " " + $object + ";" ); } // When adding type vector scalar, must actually set the // value because the getAttr command fails otherwise. // if (($gDataTypeDAA == 1) && ($gScalarAryDAA == 1)) { evalEcho( "setAttr -type double3 "+$object+"."+$attr+" 0 0 0;" ); } // Set the keyable state of the attribute. // int $keyDisp = `radioButtonGrp -q -sl attrKeyDispGrp`; if ( $keyDisp != 3 ) { string $keyDispFlags = " "; if( $keyDisp == 1 ) { $keyDispFlags = "-keyable true "; } else if( $keyDisp == 2 ) { $keyDispFlags = "-channelBox true "; } string $objAttr = ( $object + "." + $attr ); evalEcho( "setAttr -e" + $keyDispFlags + $objAttr + ";" ); // A compound isn't keyable unless all its children are. // if( $attrType == "-at double3" ) { evalEcho( "setAttr -e" + $keyDispFlags + $objAttr + "X;" ); evalEcho( "setAttr -e" + $keyDispFlags + $objAttr + "Y;" ); evalEcho( "setAttr -e" + $keyDispFlags + $objAttr + "Z;" ); } } } // ========== doAddControlDAA ========== // // Description: // // proc doAddControlDAA( string $attr, string $object ) { global string $gAddAttrWin; setParent $gAddAttrWin; // set the nice name // string $niceName = " "; if( `textFieldGrp -q -enable niceNamePoseGrp` ) { $niceName = ( "-nn \"" + `textFieldGrp -q -text niceNamePoseGrp` + "\" " ); } evalEcho("addAttr -ln \""+$attr+"\" " + $niceName + " -at double -min 0 -max 1 -dv 0 "+$object+";"); if (`nodeType $object` == "blendShape") { string $itemAry[] = `textScrollList -q -si attrLst2`; if (size($itemAry)) { setNodeKeysDAA $attr $object; } else { setBlendKeysDAA $attr $object; } } else { setNodeKeysDAA $attr $object; } // Set the keyable/displayable state of the attribute. // int $keyDisp = `radioButtonGrp -q -sl attrKeyDispGrp`; string $keyDispFlags = " "; if ($keyDisp == 1) { $keyDispFlags = "-keyable true "; } else if( $keyDisp == 2 ) { $keyDispFlags = "-channelBox true "; } eval( "setAttr -e" + $keyDispFlags + $object + "." + $attr + ";" ); } global proc setBlendKeysDAA(string $attr,string $object) { $ct=`blendShape -q -wc $object`; $oattr=$object+"."+$attr; setAttr $oattr 1; for ($i=0;$i<$ct;$i++) { $wattr=$object+".w["+$i+"]"; $w=`getAttr $wattr`; setDrivenKeyframe -cd $oattr -v $w $wattr; } setAttr $oattr 0; for ($i=0;$i<$ct;$i++) { $wattr=$object+".w["+$i+"]"; setDrivenKeyframe -cd $oattr -v 0 $wattr; } setAttr $oattr 1; } global proc setNodeKeysDAA(string $attr,string $object) { global string $gAddAttrWin; setParent $gAddAttrWin; string $itemAry[] = `textScrollList -q -si attrLst2`; $oattr=$object+"."+$attr; setAttr $oattr 1; for ($i = 0; $i < size( $itemAry ); $i++) { $wattr=$object+"."+$itemAry[$i]; $w=`getAttr $wattr`; setDrivenKeyframe -cd $oattr -v $w $wattr; } setAttr $oattr 0; for ($i = 0; $i < size( $itemAry ); $i++) { $wattr=$object+"."+$itemAry[$i]; // need to be able to set this to the default value setDrivenKeyframe -cd $oattr -v 0 $wattr; } setAttr $oattr 1; } // ========== doItDAA ========== // // Description: // Execute the actual addAttr command. This depends on // the current dialog mode. If adding predefined attributes, // then get a list of attributes from the scrolled list, and // add them. If adding a new attribute, then get the attribute // type and name before adding it. Called from the OK and Add // button callbacks. // proc int doItDAA() { // Build the addAttr command based on the selection. // global string $gObjectsDAA[]; // List of selected objects. global string $gAddAttrWin; setParent $gAddAttrWin; string $specifyAttrError = (uiRes("m_dynAddAttrWin.kSpecityAttrError")); switch (`getModeDAA`) { case 1 : // New Attribute tab { string $attrName = `textFieldGrp -q -text longNameGrp`; // No spaces are allowed in the attribute name, so // we remove them here. // string $aName = `substitute " " $attrName ""`; while ( $aName != $attrName ){ $attrName = $aName; $aName = `substitute " " $attrName ""`; } // FIX_LATER: // What happens when spaces are removed from longName, // but the niceName keeps the spaces? // if (size( $attrName ) == 0) { error ($specifyAttrError); return( 0 ); } for ($n = 0; $n < size( $gObjectsDAA ); $n++) { doAddNewDAA( $attrName, $gObjectsDAA[$n] ); } } break; case 2 : // Particle Attribute { // Add a predefined particle attribute. // string $itemAry[] = `textScrollList -q -si attrLst`; for ($n = 0; $n < size( $gObjectsDAA ); $n++) { for ($i = 0; $i < size( $itemAry ); $i++) { doAddPreDAA( $itemAry[$i], $gObjectsDAA[$n] ); } } } break; case 3 : // Control tab { string $attrName = `textFieldGrp -q -text longNamePoseGrp`; if (size( $attrName ) == 0) { error ($specifyAttrError); return( 0 ); } for ($n = 0; $n < size( $gObjectsDAA ); $n++) { doAddControlDAA( $attrName, $gObjectsDAA[$n] ); } } break; default : { error (uiRes("m_dynAddAttrWin.kUnknownModeError")); return( 0 ); } } dynUpdateDeleteAttrWin; // Inform the delete window to update itself. // This is better than callbacks... dynUpdateRenameAttrWin; // Inform the rename window to update itself. // This is better than callbacks... return( 1 ); } // ========== okayDAA ========== // // SYNOPSIS // Okay button callback. // global proc okayDAA() { global string $gAddAttrWin; if (`doItDAA`) window -e -vis 0 $gAddAttrWin; } // ========== addDAA ========== // // Description: // Add button callback. Add the selected attribute, then reset // the dialog and keep it posted. Also change the label on the // Cancel button to Close. // global proc addDAA() { global string $gAddAttrWin; setParent $gAddAttrWin; if (`doItDAA`) { resetDAA; button -e -label (uiRes("m_dynAddAttrWin.kClose")) -w 60 -h 26 cancelBtn; } } // ========== makeNewAttrDAA ========== // // Description: // Build the widgets for the New tab. // global proc updateNiceOverrideDAA() { if(( `textFieldGrp -q -text niceNameGrp` == "" ) || (!`checkBoxGrp -q -v1 niceOverrideGrp` )) { string $value = `textFieldGrp -q -text longNameGrp`; textFieldGrp -e -text `interToUI $value` niceNameGrp; } textFieldGrp -e -en `checkBoxGrp -q -v1 niceOverrideGrp` niceNameGrp; } global proc makeNewAttrDAA( string $parent ) { global string $gAddAttrEnumScrollList = ""; global string $gAddAttrEnumTextGrp = ""; global string $gAddAttrEnumText = ""; // Create a tab for these controls. // setParent $parent; $scrollLayout = `scrollLayout -childResizable true`; $form = `columnLayout -adj true`; // Attribute name textfield. // textFieldGrp -label (uiRes("m_dynAddAttrWin.kAttributeName")) -cc "updateNiceOverrideDAA" longNameGrp; checkBoxGrp -label (uiRes("m_dynAddAttrWin.kOverrideNice")) -cc "updateNiceOverrideDAA" niceOverrideGrp; textFieldGrp -en false -label (uiRes("m_dynAddAttrWin.kNiceName")) niceNameGrp; radioButtonGrp -label (uiRes("m_dynAddAttrWin.kMakeAttribute")) -nrb 3 -label1 (uiRes("m_dynAddAttrWin.kKeyable")) -label2 (uiRes("m_dynAddAttrWin.kDisplayable")) -label3 (uiRes("m_dynAddAttrWin.kHidden")) attrKeyDispGrp; // Data Type frame. // frameLayout -label (uiRes("m_dynAddAttrWin.kDataType")) -cll false dataTypeLyt; formLayout -nd 100 typeLyt; radioCollection dataTypeRad; radioButton -label (uiRes("m_dynAddAttrWin.kVector")) -h 24 vectorBtn; formLayout -e -af vectorBtn left 4 -af vectorBtn top 0 typeLyt; radioButton -label (uiRes("m_dynAddAttrWin.kFloat")) -h 24 -select floatBtn; formLayout -e -aoc floatBtn left 0 vectorBtn -ac floatBtn top 0 vectorBtn typeLyt; radioButton -label (uiRes("m_dynAddAttrWin.kInteger")) -h 24 intBtn; formLayout -e -af intBtn left 100 -af intBtn top 0 typeLyt; radioButton -label (uiRes("m_dynAddAttrWin.kBoolean")) -h 24 boolBtn; formLayout -e -aoc boolBtn left 0 intBtn -ac boolBtn top 0 intBtn typeLyt; radioButton -label (uiRes("m_dynAddAttrWin.kString")) -h 24 stringBtn; formLayout -e -af stringBtn left 200 -af stringBtn top 0 typeLyt; radioButton -label (uiRes("m_dynAddAttrWin.kEnum")) -h 24 enumBtn; formLayout -e -aoc enumBtn left 0 stringBtn -ac enumBtn top 0 stringBtn typeLyt; setParent $form; // Attribute Type frame. // frameLayout -label (uiRes("m_dynAddAttrWin.kAttributeType")) -cll false attrTypeLyt; formLayout -nd 100 attrFormLyt; radioCollection attrTypeRad; radioButton -label (uiRes("m_dynAddAttrWin.kScalar")) -select -h 24 scalarBtn; formLayout -e -af scalarBtn left 14 -af scalarBtn top 4 attrFormLyt; radioButton -label (uiRes("m_dynAddAttrWin.kPerParticleArray")) -h 24 arrayBtn; formLayout -e -af arrayBtn left 100 -af arrayBtn top 4 attrFormLyt; checkBox -label (uiRes("m_dynAddAttrWin.kAddInitialStateAttribute")) -enable 0 -v 1 initBtn; formLayout -e -aoc initBtn left 0 arrayBtn -ac initBtn top 0 arrayBtn attrFormLyt; setParent $form; // Min/Max frame. // frameLayout -label (uiRes("m_dynAddAttrWin.kNumericAttributeProperties")) -cll false minMaxLyt; formLayout -nd 100 minMaxFormLyt; text -label (uiRes("m_dynAddAttrWin.kMinimum")) minTxt; formLayout -e -af minTxt left 4 -af minTxt top 4 minMaxFormLyt; text -label (uiRes("m_dynAddAttrWin.kMaximum")) maxTxt; formLayout -e -af maxTxt left 4 -ac maxTxt top 10 minTxt minMaxFormLyt; text -label (uiRes("m_dynAddAttrWin.kDefault")) defTxt; formLayout -e -af defTxt left 4 -ac defTxt top 8 maxTxt minMaxFormLyt; textField minFld; formLayout -e -af minFld left 80 -af minFld top 0 -af minFld right 4 minMaxFormLyt; textField maxFld; formLayout -e -aoc maxFld left 0 minFld -ac maxFld top 3 minFld -af maxFld right 4 minMaxFormLyt; textField -text "0" defFld; formLayout -e -aoc defFld left 0 maxFld -ac defFld top 3 maxFld -af defFld right 4 minMaxFormLyt; if(`about -mac`) { // adjust textFld height and vertical spacing between the fields int $textFieldHeight = 28; textField -e -h $textFieldHeight minFld; textField -e -h $textFieldHeight maxFld; textField -e -h $textFieldHeight defFld; } setParent $form; // Enum frame. // frameLayout -label (uiRes("m_dynAddAttrWin.kEnumNames")) -collapsable false enumLyt; formLayout; string $uiBits[] = `attrEnumScrollList( false )`; $gAddAttrEnumScrollList = $uiBits[0]; $gAddAttrEnumTextGrp = $uiBits[1]; $gAddAttrEnumText = $uiBits[2]; tabLayout -edit -tabLabel $scrollLayout (uiRes("m_dynAddAttrWin.kNew")) $parent; } // ========== makeParticleDAA ========== // // Description: // Build the widgets for the Particle tab. // global proc makeParticleDAA( string $parent ) { // Create a tab for these controls. // setParent $parent; formLayout ParticleLyt; // Create a scrolled list for the attribute names. // textScrollList -allowMultiSelection true attrLst; formLayout -e -af attrLst left 0 -af attrLst top 0 -af attrLst right 0 -af attrLst bottom 0 ParticleLyt; // Add attributes to scrolled list. // string $attrAry[] = getAttrListDAA(); for ($i = 0; $i < size( $attrAry ); $i++) { textScrollList -e -a $attrAry[$i] attrLst; } // Give the tab a nice label, and return its name. // setParent $parent; tabLayout -e -tl ParticleLyt (uiRes("m_dynAddAttrWin.kParticle")) $parent; } // ========== makeNewPoseWinDAA ========== // // Description: // // global proc updateNiceOverridePoseDAA() { if(( `textFieldGrp -q -text niceNamePoseGrp` == "" ) || (!`checkBoxGrp -q -v1 niceOverridePoseGrp` )) { string $value = `textFieldGrp -q -text longNamePoseGrp`; textFieldGrp -e -text `interToUI $value` niceNamePoseGrp; } textFieldGrp -e -en `checkBoxGrp -q -v1 niceOverridePoseGrp` niceNamePoseGrp; } global proc makeNewPoseDAA( string $parent ) { // Create a tab for these controls. // setParent $parent; formLayout ControlInfoLyt; string $colLyt = `columnLayout -adj true`; // Attribute name textfield. // textFieldGrp -label (uiRes("m_dynAddAttrWin.kAttributePoseName")) -cc "updateNiceOverridePoseDAA" longNamePoseGrp; checkBoxGrp -label (uiRes("m_dynAddAttrWin.kOverridePoseNice")) -cc "updateNiceOverridePoseDAA" niceOverridePoseGrp; textFieldGrp -en false -label (uiRes("m_dynAddAttrWin.kNicePoseName")) niceNamePoseGrp; separator -horizontal true sep2; setParent ..; // Attribute list. // textScrollList -allowMultiSelection true attrLst2; formLayout -e -af attrLst2 left 0 -af attrLst2 right 0 -ac attrLst2 top 0 $colLyt -af attrLst2 bottom 0 ControlInfoLyt; // Give the tab a nice label, and return its name. // setParent $parent; tabLayout -e -tl ControlInfoLyt (uiRes("m_dynAddAttrWin.kControl")) $parent; } // ========== createWinDAA ========== // // SYNOPSIS // Create the window and all the controls. // proc createWinDAA() { global string $gAddAttrWin; int $width = 500; int $height = 525; if( `about -mac` ) { $height = 640; } else if( `about -linux` ) { $height = 580; } window -title (uiRes("m_dynAddAttrWin.kAddAttribute")) -minimizeButton false -maximizeButton false -width $width -height $height -menuBar true -retain $gAddAttrWin; menu -label (uiRes("m_dynAddAttrWin.kHelp")) -helpMenu true; menuItem -label (uiRes("m_dynAddAttrWin.kHelponAddingAttributes")) -enableCommandRepeat false -command "showHelp AddAttribute"; formLayout -nd 100 workLyt; // Create user controls. // button -label (uiRes("m_dynAddAttrWin.kOK")) -h 26 okBtn; button -label (uiRes("m_dynAddAttrWin.kAdd")) -h 26 addBtn; button -label (uiRes("m_dynAddAttrWin.kCancel")) -h 26 cancelBtn; separator -horizontal true sep1; formLayout -e -af okBtn left 5 -ap okBtn right 3 33 -af okBtn bottom 5 -ap addBtn left 2 33 -ap addBtn right 3 66 -af addBtn bottom 5 -ap cancelBtn left 2 66 -af cancelBtn right 5 -af cancelBtn bottom 5 -af sep1 left 0 -af sep1 right 0 -ac sep1 bottom 5 okBtn workLyt; tabLayout tabLyt; setParent ..; formLayout -e -af tabLyt left 0 -af tabLyt top 0 -af tabLyt right 0 -ac tabLyt bottom 4 sep1 workLyt; setParent ..; // workLyt makeNewAttrDAA( "tabLyt" ); makeParticleDAA( "tabLyt" ); makeNewPoseDAA( "tabLyt" ); } // ========== registerDAA ========== // // SYNOPSIS // Register the callbacks. // proc registerDAA() { global int $gDataTypeDAA; global int $gScalarAryDAA; global string $gAddAttrWin; setParent $gAddAttrWin; button -e -c ("okayDAA") okBtn; button -e -c ("addDAA") addBtn; button -e -c ("window -e -vis 0 "+$gAddAttrWin) cancelBtn; radioButton -e -onc ("$gDataTypeDAA = 1; setMinMaxModeDAA 1") vectorBtn; radioButton -e -onc ("$gDataTypeDAA = 2; setMinMaxModeDAA 2") floatBtn; radioButton -e -onc ("$gDataTypeDAA = 3; setMinMaxModeDAA 3") intBtn; radioButton -e -onc ("$gDataTypeDAA = 4; setMinMaxModeDAA 4") boolBtn; radioButton -e -onc ("$gScalarAryDAA = 1; setMinMaxModeDAA 5") scalarBtn; radioButton -e -onc ("$gScalarAryDAA = 2; setMinMaxModeDAA 6") arrayBtn; // Not quite sure if we need to set gDataTypeDAA for string and enum? radioButton -e -onc ("$gDataTypeDAA = 7; setMinMaxModeDAA 7") stringBtn; radioButton -e -onc ("$gDataTypeDAA = 8; setMinMaxModeDAA 8") enumBtn; textField -e -cc ("setParent "+$gAddAttrWin+"; correctDefVal; setFocus maxFld;") minFld; textField -e -cc ("setParent "+$gAddAttrWin+"; correctDefVal; setFocus defFld;") maxFld; textField -e -cc ("setParent "+$gAddAttrWin+"; correctDefVal; setFocus minFld;") defFld; tabLayout -e -preSelectCommand ("resetDAA") tabLyt; } // ========== resetDAA ========== // // Description: // Reset the active tab. Called when the dialog is posted, // when the user selects a new tab, and after the user has // added an attribute. // global proc resetDAA() { global string $gObjectsDAA[]; // List of selected objects. global int $gParticleModeDAA; // Enable particle array mode. global int $gScalarAryDAA; global string $gAddAttrWin; global string $gAddAttrEnumScrollList; global string $gAddAttrEnumTextGrp; global string $gAddAttrEnumText; setParent $gAddAttrWin; switch (`getModeDAA`) { case 1 : // New: adding user defined attributes. { textFieldGrp -e -text "" longNameGrp; textFieldGrp -e -text "" niceNameGrp; checkBoxGrp -e -v1 false niceOverrideGrp; textFieldGrp -e -en false niceNameGrp; textField -e -text "" minFld; textField -e -text "" maxFld; textField -e -text "0" defFld; attrEnumScrollList_clear( $gAddAttrEnumScrollList, $gAddAttrEnumTextGrp, $gAddAttrEnumText ); radioButtonGrp -e -sl 1 attrKeyDispGrp; if ($gParticleModeDAA) { if ((`radioButton -q -select vectorBtn`) || (`radioButton -q -select floatBtn`)) { radioButton -e -enable 1 arrayBtn; } else { radioButton -e -enable 0 arrayBtn; } } else { radioButton -e -select scalarBtn; $gScalarAryDAA = 1; checkBox -e -value false initBtn; radioButton -e -enable false arrayBtn; radioButton -e -enable true intBtn; radioButton -e -enable true boolBtn; setMinMaxModeDAA( 0 ); } } break; case 2 : // Predefined: adding particle attributes. textScrollList -e -deselectAll attrLst; break; case 3 : // Control: add attrs to pose control. textScrollList -e -ra attrLst2; string $attrAry[] = `listAttr -s -k -m $gObjectsDAA[0]`; for ($i = 0; $i < size( $attrAry ); $i++) { textScrollList -e -a $attrAry[$i] attrLst2; } textFieldGrp -e -text "" longNamePoseGrp; textFieldGrp -e -text "" niceNamePoseGrp; checkBoxGrp -e -v1 false niceOverridePoseGrp; textFieldGrp -e -en false niceNamePoseGrp; break; } } // ========== dynAddAttrWin ========== // // SYNOPSIS // Create and show the add attribute dialog. A list of particle // objects can be specified. If a list is specified, this procedure // does not verify that the objects are all particle objects. If // an empty array is passed in, then the current selection list is // used. In this case, only valid particle objects are used. // global proc int dynAddAttrWin( string $objects[] ) { global string $gAddAttrWin = "AddAttrWin"; global string $gObjectsDAA[]; global int $gParticleModeDAA; global int $gDynAddAttrUpdateJob = 0; // If $objects[] is empty, then use the current selection list. // if (size( $objects ) == 0) { string $pObjects[] = `selectedNodes`; if (size( $pObjects ) == 0) { // If the window is not yet open, just issue an error. // If it is already open, disable the Okay and Add buttons // if ( `window -exists $gAddAttrWin` && `window -q -vis $gAddAttrWin` ){ setParent $gAddAttrWin; disable -v on okBtn; disable -v on addBtn; window -e -title (uiRes("m_dynAddAttrWin.kNothingSelected")) $gAddAttrWin; return( 1 ); } else { error (uiRes("m_dynAddAttrWin.kNoObjectsError")); return( 0 ); } } else { $gObjectsDAA = $pObjects; } } else { $gObjectsDAA = $objects; } // The window is created only once. // if ( ! `window -exists $gAddAttrWin`) { createWinDAA; registerDAA; } else { // just in case the buttons were dimmed... setParent $gAddAttrWin; disable -value off okBtn; disable -value off addBtn; } // Set the window title to indicate if one or more objects // are selected. // setParent $gAddAttrWin; if (size( $gObjectsDAA ) > 1) { string $attributeWndTitle = (uiRes("m_dynAddAttrWin.kAttributeWndTitle")); window -e -title (`format -s $gObjectsDAA[0] $attributeWndTitle`) $gAddAttrWin; } else { string $windowTitle = (uiRes("m_dynAddAttrWin.kWindowTitle")); window -e -title (`format -s $gObjectsDAA[0] $windowTitle`) $gAddAttrWin; } button -e -label (uiRes("m_dynAddAttrWin.kCancelOption")) -h 26 cancelBtn; // Checked the object list. If there are any non-particle // objects, dim the array button. // $gParticleModeDAA = 1; for ($n = 0; $n < size( $gObjectsDAA ); $n++) { if (`nodeType $gObjectsDAA[$n]` != "particle" && `nodeType $gObjectsDAA[$n]` != "nParticle") { $gParticleModeDAA = 0; break; } } // Create a script job that will update the window // the next time the selection changes. // if ( $gDynAddAttrUpdateJob == 0 ){ $gDynAddAttrUpdateJob = `scriptJob -protected -parent $gAddAttrWin -event "SelectionChanged" "dynUpdateAttrWin"`; } // Reset the dialog and post it. // resetDAA; showWindow $gAddAttrWin; return( 1 ); }