├── .github └── ISSUE_TEMPLATE.md ├── .gitignore ├── CHANGELOG.md ├── LICENSE ├── LICENSE.md ├── README.md ├── mel ├── README.md ├── tweenMachine.mel ├── tweenMachine.png └── xml_lib.mel └── python ├── tweenMachine.png └── tween_machine.py /.github/ISSUE_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | Thanks for filing an issue - I'm happy to help, even with answering questions, just please make sure you can answer 2 | a few questions first: 3 | 4 | # Bugs: 5 | 6 | - [ ] Are you using the Python or MEL version? The MEL version is unsupported and only included as legacy. 7 | 8 | - [ ] Is this a bug or a workflow issue? 9 | 10 | # Filing a bug: 11 | 12 | - [ ] Version of the Python script 13 | - [ ] Short description of what is happening 14 | - [ ] Expected result 15 | - [ ] Actual result 16 | - [ ] Steps to reproduce 17 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .idea 2 | *.py[doc] -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | 3.0.0 (April 21, 2017) 2 | ----------------------- 3 | - Rewritten in Python, MEL is no longer supported 4 | - Easily favor poses on different body parts in different ways using multiple sets 5 | - Organize sets in collapsable custom groups (see screen shot) 6 | - Control how sets and groups affect the ticks on the timeline 7 | - Create an overshoot pose by enabling overshoot mode 8 | - Adjust the UI to use sliders, buttons, or both 9 | - Affect only the channels highlighted in the channel box for selected objects 10 | - Easily work with character sets, either by using a single custom slider, or by importing character set info into tweenMachine 11 | - Use Maya’s “special” tick color to identify keys made with tweenMachine 12 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 Alex Widener 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | License is currently being determined. 2 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # TweenMachine 2 | 3 | --------------------- 4 | ### The easiest way to create breakdown poses in Maya 5 | 6 | Say you’re creating poses for your character with stepped keys, and have created key poses on frames 1 and 10. 7 | You want to make a breakdown pose on frame 7, but you want it to favor the first pose by 70%. The following comparison 8 | shows how this would be accomplished both with and without tweenMachine. 9 | 10 | |Manual Process | Tween Machine | 11 | |------------------------------------------------|------------------------------------------------------| 12 | |Select all controls on the character | Select all controls on the character | 13 | |Change interpolation on all keyframes to linear | Left-click on frame 7 in the timeline | 14 | |Left-click on frame 3 in the timeline | Adjust a slider in the tweenMachine interface to -70 | 15 | |Middle-click on frame 7 in the timeline | | 16 | |Set a key | | 17 | |Change interpolation on all keyframes to stepped| | 18 | 19 | 20 | If you’re not happy with the results, you’ve got a lot of steps to repeat if you’re doing it the manual way. With 21 | tweenMachine, you simply adjust the slider and see the results immediately. Better still, if you’ve created a custom 22 | set that controls the entire character, you can skip the first step and save even more time. 23 | 24 | Will tweenMachine create perfect breakdown poses? Not likely, but it will get you closer to your goal a lot faster than 25 | other methods. You spend less time with busywork and more time making actual progress. 26 | 27 | Tween Machine was originally developed by [Justin Barrett](http://www.justinsbarrett.com/) and used extensively throughout 28 | the animation and visual effects industries for years. 29 | 30 | Development was taken over by [Alex Widener](https://github.com/alexwidener) in February 2018. 31 | 32 | | Contribution | Author | 33 | |----------------------------------|-----------------------------------------------------| 34 | |tweenMachine.mel/ tweenMachine.py | [Justin S. Barrett](http://www.justinsbarrett.com/) | 35 | |xml_lib.mel | J. Adrian Herbez | 36 | |Maya Shelf Icon | [Keith Lango](http://keithlango.squarespace.com/) | 37 | 38 | 39 | ## Updates 40 | Subscribe to very infrequent and non-spammy email updates about new versions [at this link](https://github.us18.list-manage.com/subscribe?u=21f14bb7b1c884b7f2d517b57&id=a966b6ab32). 41 | 42 | ## Installation 43 | 44 | Animators: Do not copy the file listed directly above, as tweenMachine is in active development and will be for the next few weeks. Instead, go to the [Releases](https://github.com/alexwidener/tweenMachine/releases) tab above the files, and download version 3.0.0. 45 | 46 | Version 3.1.0 will come out at some point and be a restructure/rewrite/with many new features and a new look. Please check back for updates. 47 | 48 | ### Windows: 49 | 50 | Move the tweenMachine.py file to your default Maya scripts directory. 51 | 52 | `C:/Users/username/Documents/maya/version_number/scripts` 53 | 54 | Save the icon into the “prefs/icons” folder for the same Maya version. 55 | 56 | `C:/Users/username/Documents/maya/version_number/prefs/icon` 57 | 58 | Once everything is installed, open Maya. In the script editor, type the following in a Python tab: 59 | 60 | ``` 61 | import tweenMachine 62 | tweenMachine.start() 63 | ``` 64 | 65 | Highlight the line, then select `File–>Save Selected to Shelf` to turn it into a shelf button. Use the Shelf Editor to 66 | assign the icon to the shelf button. 67 | 68 | ### Mac OS: 69 | 70 | Move the tweenMachine.py file to your default Maya scripts directory. 71 | 72 | `/Users/username/Library/Preferences/Autodesk/maya/version_number/scripts` 73 | 74 | Save the icon into the “prefs/icons” folder for the same Maya version. 75 | 76 | `/Users/username/Library/Preferences/Autodesk/maya/version_number/prefs/icon` 77 | 78 | 79 | Once everything is installed, open Maya. In the script editor, type the following in a Python tab: 80 | 81 | ``` 82 | import tweenMachine 83 | tweenMachine.start() 84 | ``` 85 | 86 | Highlight the line, then select `File–>Save Selected to Shelf` to turn it into a shelf button. Use the Shelf Editor to 87 | assign the icon to the shelf button. 88 | 89 | ### Linux 90 | Do all the same stuff wherever your maya scripts folder is. You can find it by entering the following in a Maya Script Editor: 91 | 92 | ``` 93 | import sys 94 | for s in sys.path: 95 | print(s) 96 | ``` 97 | 98 | And then find the `maya/version_number/scripts/` folder and follow the same steps as above. 99 | 100 | ## Usage 101 | 102 | When running tweenMachine for the first time, it will open with a bare-bones interface. There’s a single slider labeled 103 | “Selected”, and a group of seven buttons below the slider. In this mode, tweenMachine operates only on selected objects. 104 | Click between two keys on the timeline, and adjust the “Selected” slider to create a new breakdown key. The values set 105 | for the new breakdown key will be biased toward the surrounding keys on the timeline based on how you set the slider. 106 | In the slider’s default position, the new keys will be exactly halfway between the surrounding keys. Slider values to 107 | the left will favor the new key toward the previous key, while values to the right will favor the next key. Clicking one 108 | of the buttons will set the slider to a preset value. If you wish, you can highlight individual channels in Maya’s 109 | channel box, and tweenMachine will only perform its work on those channels, leaving others untouched. 110 | 111 | That covers the core operation of tweenMachine, but there are additional features available through various menu items. A full breakdown of all menu items is covered in the next section 112 | 113 | ### Menu 114 | 115 | The functions for all (currently available) tweenMachine menu items are as follows… 116 | 117 | `Options > Show` 118 | 119 | Contains Menu Bar and Label visibility toggles, plus radio buttons that let you select if you want to see the slider, 120 | the buttons, or both. 121 | 122 | `Options > Mode… > Window` 123 | 124 | Sets the interface to be a standard floating window. 125 | 126 | `Options > Mode… > Toolbar` 127 | 128 | Sets the interface to toolbar mode, allowing you to place it next to other Maya toolbars in the main window. 129 | 130 | `Options > Overshoot` 131 | 132 | Toggles “overshoot mode” for all sliders. By default, the range of all sliders is -100 to 100. When “overshoot mode” is 133 | active, the range of all sliders changes to -150 to 150. Using this mode allows you to create overshoot poses on the 134 | right end of the sliders in the 101-150 range, while using it in the -101 to -150 range on the left end effectively 135 | creates anticipation poses. 136 | 137 | `Options > Special Tick Color` 138 | 139 | Toggles the tick color used for keys added using the tweenMachine. When off (default), the standard tick color is used. 140 | When on, the “special” tick color is used. 141 | 142 | ### Buttons 143 | 144 | The buttons below each set slider provide a quick way to set the slider to predictable values. By default they are set 145 | to mimic the style of pose favoring familiar to 2D animators. The center button is an exact halfway point between the 146 | two poses, and spreading out from the center on either side, the remaining buttons represent pose favoring by 1/3, 1/5, 147 | and 1/8 in their respective directions.By holding the mouse over any button, an annotation popup will appear showing the 148 | numerical value assigned to that button. 149 | 150 | While the button values and colors are locked in this version (unless you manually tweak them), the Python version will 151 | eventually allow them to be easily customized. 152 | -------------------------------------------------------------------------------- /mel/README.md: -------------------------------------------------------------------------------- 1 | The MEL version is no longer supported. This is kept in place purely for legacy reasons. 2 | 3 | -------------------------------------------------------------------------------- /mel/tweenMachine.mel: -------------------------------------------------------------------------------- 1 | /* -------------------------------------------------------------------------- 2 | tweenMachine.mel - MEL Script 3 | -------------------------------------------------------------------------- 4 | 5 | DESCRIPTION: 6 | Creates a new key inbetween the previous and next keys, using a 7 | slider to adjust the "bias" or weight that each key has over the 8 | new key. Requested/inspired by Doron Meir. 9 | 10 | USAGE: 11 | source tweenMachine; tweenMachine; 12 | 13 | AUTHOR: 14 | Justin S Barrett - http://www.justinsbarrett.com 15 | 16 | ADDITIONAL CREDITS: 17 | xml_lib.mel: J. Adrian Herbez 18 | 19 | COPYRIGHT: 20 | Copyright 2005-2017 Justin S Barrett - All Rights Reserved 21 | 22 | VERSIONS: 23 | 2.00 - Initial release of upgrade 24 | 2.01 - fixed issue with "Add Groups" UI display 25 | - fixed timeline tick display issue 26 | - disabled auto-refresh when opening a scene 27 | - added support for character sets 28 | 2.02 - removed need to source file before running 29 | - added support for special tick color (v7 and higher) 30 | 2.03 - updated tick color support for Maya 200X versions 31 | 2.04 - bug fix related to character set support 32 | 2.05 - fix issue that prevented group and set dialogs from working in newer 33 | versions of Maya 34 | - fix bug that cropped off sliders and buttons for user defined sets 35 | in newer versions of Maya 36 | 2.0.6 - Fixed a bug where selecting attributes in the channel box would not 37 | find the proper animCurve nodes for tweening 38 | - Changed the version numbering scheme 39 | - Moved sourcing of xml_lib out of base procedure 40 | 2.0.7 - After tweening, focus is now set to the main Maya window instead of 41 | the last active panel. 42 | 2.0.8 - Improved selected channel parsing to handle missing node/attribute 43 | combinations, and attributes with no connected curves 44 | 2.0.9 - Removed redundant declaration of $nodes[] in main tween proc 45 | - Fractional keyframe times now supported (finally!) 46 | 2.1.0 - Updated to store button and slider visibility in data nodes so that 47 | the Python version can properly read them if the user migrates 48 | 2.1.1 - Updated to fix warning that began appearing in Maya 2016.5 49 | 2.1.2 - Added Help menu 50 | 51 | */ 52 | 53 | // ************************************************************************ 54 | // Source needed libraries 55 | // ************************************************************************ 56 | 57 | source xml_lib.mel; 58 | 59 | // ************************************************************************ 60 | // Global Variables 61 | // ************************************************************************ 62 | 63 | global string $tmVersion = "2.1.2"; 64 | 65 | // ************************************************************************ 66 | // Core procedures 67 | // ************************************************************************ 68 | 69 | global proc tweenMachine() { 70 | 71 | // Global Variables 72 | global string $tmGroups[], $tmSets[], $tmButtonRGB[], $tmSelConArray; 73 | global int $tmNumButtons, $tmSliderWidth, $tmShowButtons, $tmShowSliders, $tmButtonRowPad, $mayaVers, $tmSpecTick; 74 | global float $tmButtonVal[]; 75 | global string $tmVersion; 76 | 77 | clear $tmGroups; 78 | clear $tmSets; 79 | 80 | $tmSliderWidth = 200; 81 | $mayaVers = (int) startString(`about -v`,1); 82 | $tmSpecTick = 0; 83 | 84 | // OS check -- this will probably go away once the UI is built using forms 85 | if (`about -mac`) { 86 | $tmButtonRowPad = 10; 87 | } else { 88 | $tmButtonRowPad = 1; 89 | } 90 | 91 | if (`window -q -ex tweenMachineWin`) deleteUI tweenMachineWin ; 92 | 93 | // Make Window 94 | window -w 300 -h 5 -mnb 1 -mxb 0 -menuBar 1 -mbv 1 -rtf 1 -s 1 -t ("tweenMachine - " + $tmVersion) -in "tweenMachine" tweenMachineWin; 95 | 96 | menu -l "File" tmFile; 97 | menuItem -l "New..." -en 1 -c "tmNew"; 98 | menuItem -d true; 99 | menuItem -l "Open..." -en 1 -c "tmLoadFromFile"; 100 | menuItem -l "Save..." -en 1 -c "fileBrowser \"tmSaveToFile\" \"Save\" \"\" 1"; 101 | 102 | menu -l "Tools" tmTools; 103 | menuItem -l "Add Set..." -en 0 -c "tmAddSetUI" tmAddSetMI; 104 | menuItem -l "Add Group..." -c "tmAddGroupUI"; 105 | menuItem -d true; 106 | menuItem -l "Manage Sets..." -en 1 -c "tmSGMBuildUI(0)"; 107 | menuItem -l "Manage Groups..." -en 1 -c "tmSGMBuildUI(1)"; 108 | //menuItem -d true; 109 | //menuItem -l "Manage Buttons..." -en 0; 110 | menuItem -d true; 111 | menuItem -l "Character Sets..." -sm 1; 112 | menuItem -l "Add Character Group" -c "tmAddCharacterGroup"; 113 | menuItem -l "Import Character Sets" -c "tmImportCharSets"; 114 | 115 | menu -l "Options" -to 1 tmOptions; 116 | menuItem -l "Sliders" -cb 1 -c "tmShowChange" tmSliderTog; 117 | menuItem -l "Buttons" -cb 1 -c "tmShowChange" tmButtonTog; 118 | menuItem -d true; 119 | menuItem -l "Overshoot" -cb 0 -c "tmToggleOvershoot" tmOvershootTog; 120 | if ($mayaVers > 6 || $mayaVers == 2) { 121 | menuItem -d true; 122 | menuItem -l "Special Tick Color" -cb 0 -c "$tmSpecTick = 1-$tmSpecTick"; 123 | } 124 | 125 | menu -l "Help" -helpMenu true; 126 | menuItem -l "Support" -c "launch -web \"http://justinsbarrett.com/tweenMachine-support/\""; 127 | menuItem -l "Docs" -c "launch -web \"http://justinsbarrett.com/tweenMachine-docs-mel/\""; 128 | 129 | columnLayout -adj 1 -cat "both" 0 tmMainGroupCL; 130 | 131 | tmBuildAllGroups; 132 | 133 | showWindow tweenMachineWin ; 134 | 135 | 136 | //scriptJob -p tweenMachineWin -e "SceneOpened" "deleteUI tweenMachineWin; tweenMachine;"; 137 | scriptJob -p tweenMachineWin -e "NewSceneOpened" "deleteUI tweenMachineWin;"; 138 | scriptJob -uid tweenMachineWin "tmRestoreTimeControl"; 139 | 140 | } 141 | 142 | // -------------------------------------------------------------------------- 143 | 144 | global proc tmNew () { 145 | 146 | global string $tmGroups[]; 147 | 148 | string $c = "Yes"; 149 | if (size($tmGroups) > 0) $c = `confirmDialog -t "Start over?" -m "Erase all tweenMachine data?" -b "Yes" -b "No" -db "Yes" -cb "No" -ds "No"`; 150 | 151 | if ($c != "No") { 152 | delete tmXML1; 153 | tweenMachine; 154 | } 155 | } 156 | 157 | // -------------------------------------------------------------------------- 158 | 159 | global proc tmBuildAllGroups () { 160 | 161 | // start with the default data 162 | tmDefaultData; 163 | 164 | // build the "Selected" set no matter what 165 | tmBuildSet ("Main", "Selected"); 166 | timeControl -e -mlc animationList timeControl1; 167 | 168 | separator -style "none" -h 5; 169 | 170 | // create master selectionConnection object 171 | if (!`selectionConnection -ex tmMasterSC`) selectionConnection -lst tmMasterSC; 172 | 173 | // If data exists in scene, pull the options and interface data from it 174 | // if not, build XML data using default values 175 | 176 | int $XMLexists = `objExists tmXML1`; 177 | if ($XMLexists) { 178 | tmReadXML; 179 | } else { 180 | tmDefaultXML; 181 | } 182 | 183 | setParent tweenMachineWin; 184 | } 185 | 186 | // -------------------------------------------------------------------------- 187 | 188 | global proc tmDefaultData () { 189 | 190 | global int $tmNumButtons, $tmShowButtons, $tmShowSliders; 191 | global float $tmButtonVal[]; 192 | global string $tmGroups[], $tmSets[], $tmButtonRGB[]; 193 | 194 | clear $tmGroups; 195 | clear $tmSets; 196 | 197 | $tmNumButtons = 7; 198 | $tmShowButtons = 1; 199 | $tmShowSliders = 1; 200 | 201 | clear $tmButtonVal; 202 | 203 | $tmButtonVal[0] = -75; 204 | $tmButtonVal[1] = -60; 205 | $tmButtonVal[2] = -33; 206 | $tmButtonVal[3] = 0; 207 | $tmButtonVal[4] = 33; 208 | $tmButtonVal[5] = 60; 209 | $tmButtonVal[6] = 75; 210 | 211 | int $i; 212 | for ($i=0; $i<$tmNumButtons; $i++) $tmButtonRGB[$i] = "0.6 0.6 0.6"; 213 | 214 | } 215 | 216 | // -------------------------------------------------------------------------- 217 | 218 | global proc tmDefaultXML () { 219 | 220 | global int $tmNumButtons, $tmShowButtons, $tmShowSliders; 221 | global float $tmButtonVal[]; 222 | global string $tmGroups[], $tmSets[], $tmButtonRGB[]; 223 | 224 | // build XML-based data structure 225 | 226 | makeNode ("tmXML",1); 227 | makeNode ("tmOptions",0); 228 | makeNode ("tmSliderVis",0); 229 | addContent ("1"); 230 | closeTag; 231 | makeNode ("tmButtonVis",0); 232 | addContent ("1"); 233 | closeTag; 234 | makeNode ("tmButtons id=\"7\"",0); 235 | for ($i=0; $i<$tmNumButtons; $i++) { 236 | makeNode ("tmButton",0); 237 | makeNode ("tmButtonRGB",0); 238 | addContent ($tmButtonRGB[$i]); 239 | closeTag; 240 | makeNode ("tmButtonValue",0); 241 | addContent ($tmButtonVal[$i]); 242 | closeTag; 243 | closeTag; 244 | } 245 | closeTag; 246 | closeTag; 247 | makeNode ("tmGroups",0); 248 | closeTag; 249 | closeTag; 250 | 251 | select -cl; 252 | } 253 | 254 | // ************************************************************************ 255 | // Ticks and Toggles 256 | // ************************************************************************ 257 | 258 | global proc tmShowChange () { 259 | 260 | global string $tmSets[]; 261 | 262 | int $sliderState = `menuItem -q -cb tmSliderTog`; 263 | int $buttonState = `menuItem -q -cb tmButtonTog`; 264 | int $sliderEnable = `menuItem -q -en tmSliderTog`; 265 | int $buttonEnable = `menuItem -q -en tmButtonTog`; 266 | 267 | // Store button and slider visibility in data nodes 268 | setAttr "tmSliderVis1.data" $sliderState -type "string"; 269 | setAttr "tmButtonVis1.data" $buttonState -type "string"; 270 | 271 | // Modify UI based on new settings 272 | if (!$sliderState && $buttonState) { 273 | menuItem -e -en 0 tmButtonTog; 274 | for ($set in $tmSets) { 275 | string $fullName = $set + "Bias"; 276 | floatSliderGrp -e -m 0 $fullName; 277 | rowLayout -e -rat 1 "top" 5 -rat 2 "top" 10 ($set + "OuterRow"); 278 | } 279 | } 280 | 281 | if ($sliderState && !$buttonEnable) { 282 | menuItem -e -en 1 tmButtonTog; 283 | for ($set in $tmSets) { 284 | string $fullName = $set + "Bias"; 285 | floatSliderGrp -e -m 1 $fullName; 286 | rowLayout -e -rat 1 "bottom" 10 -rat 2 "top" 0 ($set + "OuterRow"); 287 | } 288 | } 289 | 290 | if ($sliderState && !$buttonState) { 291 | menuItem -e -en 0 tmSliderTog; 292 | for ($set in $tmSets) { 293 | string $fullName = $set + "Buttons"; 294 | rowLayout -e -m 0 $fullName; 295 | rowLayout -e -rat 1 "top" 3 ($set + "OuterRow"); 296 | } 297 | } 298 | 299 | if (!$sliderEnable && $buttonState) { 300 | menuItem -e -en 1 tmSliderTog; 301 | for ($set in $tmSets) { 302 | string $fullName = $set + "Buttons"; 303 | rowLayout -e -m 1 $fullName; 304 | rowLayout -e -rat 1 "bottom" 10 ($set + "OuterRow"); 305 | } 306 | } 307 | 308 | } 309 | 310 | // -------------------------------------------------------------------------- 311 | 312 | global proc tmToggleOvershoot () { 313 | 314 | global string $tmSets[]; 315 | float $oldMin, $newMin, $newMax; 316 | 317 | $oldMin = `floatSliderGrp -q -min tmMainSelectedSetBias`; 318 | 319 | if ($oldMin == -100) { 320 | $newMin = -150; 321 | $newMax = 150; 322 | } else { 323 | $newMin = -100; 324 | $newMax = 100; 325 | } 326 | 327 | for ($set in $tmSets) { 328 | string $fullName = $set + "Bias"; 329 | float $oldVal = `floatSliderGrp -q -v $fullName`; 330 | float $newVal = `clamp $newMin $newMax $oldVal`; 331 | floatSliderGrp -e -min $newMin -max $newMax -v $newVal $fullName; 332 | } 333 | 334 | } 335 | 336 | // -------------------------------------------------------------------------- 337 | 338 | global proc tmTickToggle (string $objName, string $objParent) { 339 | 340 | global string $tmSets[], $tmGroups[]; 341 | 342 | if ($objName == "tmMainSelectedSet") { 343 | 344 | // swap selectionConnection 345 | int $selChk = `checkBox -q -v tmMainSelectedSetTicks`; 346 | if (!$selChk) { 347 | timeControl -e -mlc tmMasterSC timeControl1; 348 | } else { 349 | timeControl -e -mlc animationList timeControl1; 350 | } 351 | 352 | // toggle "enable" setting for all 353 | int $en = 1-(`checkBox -q -v tmMainSelectedSetTicks`); 354 | 355 | for ($grp in $tmGroups) { 356 | string $grpTk = $grp + "Ticks"; 357 | checkBox -e -en $en $grpTk; 358 | 359 | for ($set in tmSetsInGroup($grp,1)) { 360 | int $v = `checkBox -q -v $grpTk`; 361 | string $setTk = $set + "Ticks"; 362 | if ($v && $en) checkBox -e -en 1 $setTk; 363 | if (!$v && $en) checkBox -e -en 0 $setTk; 364 | if ($v && !$en) checkBox -e -en 0 $setTk; 365 | } 366 | } 367 | } else { 368 | string $objTk = $objName + "Ticks"; 369 | if (startsWith($objName,"tm")) { 370 | // object is a set 371 | string $objSC = $objName + "SC"; 372 | string $parSC = "tm" + $objParent + "GroupSC"; 373 | 374 | int $tkStat = `checkBox -q -v $objTk`; 375 | if ($tkStat) { 376 | selectionConnection -e -add $objSC $parSC; 377 | } else { 378 | selectionConnection -e -rm $objSC $parSC; 379 | } 380 | } else { 381 | // object is a group 382 | string $objSC = "tm" + $objName + "GroupSC"; 383 | string $parSC = "tmMasterSC"; 384 | 385 | int $tkStat = `checkBox -q -v $objTk`; 386 | if ($tkStat) { 387 | selectionConnection -e -add $objSC $parSC; 388 | } else { 389 | selectionConnection -e -rm $objSC $parSC; 390 | } 391 | 392 | for ($set in tmSetsInGroup($objName,1)) { 393 | string $setTk = $set + "Ticks"; 394 | int $s = 1-(`checkBox -q -en $setTk`); 395 | checkBox -e -en $s $setTk; 396 | } 397 | 398 | } 399 | } 400 | } 401 | 402 | 403 | // ************************************************************************ 404 | // Manage sets and groups 405 | // ************************************************************************ 406 | 407 | global proc tmSGMBuildUI (int $mode) { 408 | 409 | // $mode: 0 = manage sets, 1 = manage groups 410 | 411 | global string $sgmArray[], $tmGroups[]; 412 | string $winTitle; 413 | 414 | if (!$mode) $winTitle = "Manage Sets"; else $winTitle = "Manage Groups"; 415 | 416 | if (`window -ex tmSGMWin`) deleteUI tmSGMWin; 417 | 418 | window -t $winTitle -w 250 -h 250 -rtf 1 tmSGMWin; 419 | 420 | formLayout -w 250 -nd 100 tmSGMFormLayout; 421 | 422 | textScrollList -ams 0 -sc ("tmSGMSelect(" + $mode + ")") -dkc ("tmSGMDelete(" + $mode + ",1)") -da tmSGMList; 423 | if (!$mode) textScrollList -e -dcc "tmSGMMembers" tmSGMList; 424 | 425 | optionMenu -l "Manage:" -cc "tmSGMMode" tmSGMMode; 426 | menuItem -l "Sets"; 427 | menuItem -l "Groups"; 428 | optionMenu -e -sl ($mode+1) tmSGMMode; 429 | setParent tmSGMFormLayout; 430 | 431 | optionMenu -l "in group: " -cc "tmSGMRebuildList" -m (1-$mode) tmSGMGroups; 432 | for ($grp in $tmGroups) menuItem -l $grp; 433 | setParent tmSGMFormLayout; 434 | 435 | button -l "Move Up" -al "center" -w 80 -vis 0 -h 1 sgmUp; 436 | button -l "Move Down" -al "center" -w 80 -vis 0 -h 1 sgmDown; 437 | 438 | //button -l "Move Up" -al "center" -w 80 -en 0 -c ("tmReorderSGMList(-1," + $mode + ")") sgmUp; 439 | //button -l "Move Down" -al "center" -w 80 -en 0 -c ("tmReorderSGMList(1," + $mode + ")") sgmDown; 440 | 441 | button -l "Rename" -al "center" -w 80 -en 0 -c ("tmSGMRename(" + $mode + ")") sgmRen; 442 | button -l "Delete" -al "center" -w 80 -en 0 -c ("tmSGMDelete(" + $mode + ",1)") sgmDel; 443 | button -l "Properties..." -al "center" -w 80 -en 0 -m 0 -c "tmSGMProperties" sgmProp; 444 | //button -l "Properties..." -al "center" -w 80 -en 0 -m (1-$mode) -c "tmSGMProperties" sgmProp; 445 | 446 | formLayout -e 447 | 448 | -af tmSGMMode "top" 5 449 | -af tmSGMMode "left" 5 450 | 451 | -ac tmSGMGroups "left" 10 tmSGMMode 452 | -af tmSGMGroups "top" 5 453 | 454 | -af sgmUp "right" 5 455 | -ac sgmUp "top" 5 tmSGMMode 456 | 457 | -af sgmDown "right" 5 458 | -ac sgmDown "top" 2 sgmUp 459 | 460 | -af sgmRen "right" 5 461 | -ac sgmRen "top" 2 sgmDown 462 | 463 | -af sgmDel "right" 5 464 | -ac sgmDel "top" 2 sgmRen 465 | 466 | -af sgmProp "right" 5 467 | -ac sgmProp "top" 2 sgmDel 468 | 469 | -ac tmSGMList "top" 5 tmSGMMode 470 | -ac tmSGMList "right" 5 sgmUp 471 | -af tmSGMList "bottom" 5 472 | -af tmSGMList "left" 5 473 | 474 | tmSGMFormLayout; 475 | 476 | showWindow tmSGMWin; 477 | 478 | tmSGMRebuildList; 479 | 480 | } 481 | 482 | // ------------------------------------------------------------------------ 483 | 484 | global proc tmSGMMode () { 485 | int $i = (`optionMenu -q -sl tmSGMMode`)-1; 486 | tmSGMBuildUI($i); 487 | } 488 | 489 | // ------------------------------------------------------------------------ 490 | 491 | global proc tmSGMSelect (int $mode) { 492 | button -e -en 1 sgmRen; 493 | button -e -en 1 sgmDel; 494 | //if (!$mode) button -e -en 1 sgmProp; 495 | int $item[]; 496 | $item = `textScrollList -q -sii tmSGMList`; 497 | int $numItems = `textScrollList -q -ni tmSGMList`; 498 | //if ($item[0] > 1) button -e -en 1 sgmUp; else button -e -en 0 sgmUp; 499 | //if ($item[0] < $numItems) button -e -en 1 sgmDown; else button -e -en 0 sgmDown; 500 | } 501 | 502 | // ------------------------------------------------------------------------ 503 | 504 | global proc tmReorderSGMList (int $dir, int $mode) { 505 | global string $sgmArray[]; 506 | 507 | int $item[], $index; 508 | $item = `textScrollList -q -sii tmSGMList`; 509 | $index = $item[0]-1; 510 | $sgmArray = stringArrayMoveItem($sgmArray,$index,$dir); 511 | 512 | textScrollList -e -ra tmSGMList; 513 | 514 | for ($i in $sgmArray) { 515 | textScrollList -e -append $i tmSGMList; 516 | } 517 | textScrollList -e -sii ($item[0]+$dir) tmSGMList; 518 | tmSGMSelect($mode); 519 | button -e -en 1 sgmApp; 520 | 521 | } 522 | 523 | // ------------------------------------------------------------------------ 524 | 525 | global proc tmSGMRebuildList() { 526 | 527 | global string $tmGroups[], $sgmArray[]; 528 | 529 | int $mode = (`optionMenu -q -sl tmSGMMode`)-1; 530 | 531 | clear $sgmArray; 532 | if (!$mode) { 533 | string $group = `optionMenu -q -v tmSGMGroups`; 534 | $sgmArray = tmSetsInGroup($group,0); 535 | } else { 536 | $sgmArray = $tmGroups; 537 | } 538 | 539 | textScrollList -e -ra tmSGMList; 540 | 541 | for ($item in $sgmArray) textScrollList -e -append $item tmSGMList; 542 | 543 | textScrollList -e -da tmSGMList; 544 | button -e -en 0 sgmRen; 545 | button -e -en 0 sgmDel; 546 | button -e -en 0 sgmDown; 547 | button -e -en 0 sgmUp; 548 | 549 | } 550 | 551 | // ------------------------------------------------------------------------ 552 | 553 | global proc tmSGMRename(int $mode) { 554 | 555 | global string $tmGroups[]; 556 | string $modeName[], $item[], $group; 557 | $modeName[0] = " set"; 558 | $modeName[1] = " group"; 559 | 560 | $item = `textScrollList -q -si tmSGMList`; 561 | string $oldName = $item[0]; 562 | 563 | if ($mode == 1 && $oldName == "CharacterSet") { 564 | confirmDialog -t "Rename not allowed" -m "You are not allowed to rename this item."; 565 | return; 566 | } 567 | 568 | string $result = `promptDialog -t ("Rename" + $modeName[$mode]) -message "Enter new name:" -b "OK" -b "Cancel" 569 | -defaultButton "OK" -cancelButton "Cancel" 570 | -dismissString "Cancel"`; 571 | 572 | if ($result == "OK") { 573 | string $newName = `promptDialog -q -text`; 574 | if (`isValidObjectName($newName)`) { 575 | if (!$mode) { 576 | $group = `optionMenu -q -v tmSGMGroups`; 577 | string $oldNameLong = "tm" + $group + $oldName + "Set"; 578 | string $newNameLong = "tm" + $group + $newName + "Set"; 579 | 580 | if (`objExists $newNameLong`) { 581 | confirmDialog -t "Set exists" -m "A set by that name already exists. Please choose a new name."; 582 | return; 583 | } 584 | 585 | tmSGMRenameSet ($group, $oldNameLong, $newNameLong); 586 | 587 | text -e -l ($newName) ($newNameLong + "Label"); 588 | 589 | // change id in XML data node 590 | string $grpObj = tmFindInXML("tmGroup","tmGroups1",".id",$group); 591 | string $setObj = tmFindInXML("tmSet",$grpObj,".id",$oldName); 592 | setAttr -type "string" ($setObj + ".id") $newName; 593 | 594 | tmSGMRebuildList; 595 | } else { 596 | for ($grp in $tmGroups) { 597 | if ($grp == $newName) { 598 | confirmDialog -t "Group exists" -m "A group by that name already exists. Please choose a new name."; 599 | return; 600 | } 601 | } 602 | 603 | $group = $oldName; 604 | string $oldPrefix = "tm" + $group; 605 | string $newPrefix = "tm" + $newName; 606 | 607 | // rename and relabel group frameLayout 608 | renameUI ($oldPrefix + "Group") ($newPrefix + "Group"); 609 | frameLayout -e -l $newName ($newPrefix + "Group"); 610 | 611 | // rename columnLayout 612 | renameUI ($oldPrefix + "GroupCL") ($newPrefix + "GroupCL"); 613 | 614 | // rename tick check box, and change command 615 | string $checkCommand = "tmTickToggle(\"" + $newName + "\", \"Main\")"; 616 | renameUI ($oldName + "Ticks") ($newName + "Ticks"); 617 | checkBox -e -cc $checkCommand ($newName + "Ticks"); 618 | 619 | // rename group SC 620 | renameUI ($oldPrefix + "GroupSC") ($newPrefix + "GroupSC"); 621 | 622 | // rename sets in group 623 | string $set; 624 | for ($set in tmSetsInGroup($group,0)) { 625 | string $oldName = $oldPrefix + $set + "Set"; 626 | string $newName = $newPrefix + $set + "Set"; 627 | tmSGMRenameSet ($group, $oldName, $newName); 628 | } 629 | 630 | // rename item in $tmGroups array 631 | int $g; 632 | for ($g=0; $g<=size($tmGroups); $g++) if ($tmGroups[$g] == $group) $tmGroups[$g] = $newName; 633 | 634 | // change ID in XML data node 635 | string $grpObj = tmFindInXML("tmGroup","tmGroups1",".id",$group); 636 | setAttr -type "string" ($grpObj + ".id") $newName; 637 | 638 | tmSGMRebuildList; 639 | 640 | } 641 | } else { 642 | confirmDialog -t "Invalid name" -m "The name entered is not valid.\nSet and group names must be valid Maya object names."; 643 | } 644 | } 645 | } 646 | 647 | // ------------------------------------------------------------------------ 648 | 649 | global proc tmSGMRenameSet(string $group, string $oldName, string $newName) { 650 | 651 | global string $tmSets[]; 652 | global int $tmNumButtons; 653 | global float $tmButtonVal[]; 654 | 655 | rename $oldName $newName; 656 | renameUI ($oldName + "SC") ($newName + "SC"); 657 | renameUI ($oldName + "Spacer") ($newName + "Spacer"); 658 | renameUI ($oldName + "OuterRow") ($newName + "OuterRow"); 659 | 660 | renameUI ($oldName + "Bias") ($newName + "Bias"); 661 | floatSliderGrp -e -cc ("tmSliderStart(\"" + $newName + "\");") ($newName + "Bias"); 662 | 663 | string $checkCommand = "tmTickToggle(\"" + $newName + "\", \"" + $group + "\")"; 664 | renameUI ($oldName + "Ticks") ($newName + "Ticks"); 665 | checkBox -e -cc $checkCommand ($newName + "Ticks"); 666 | 667 | renameUI ($oldName + "Buttons") ($newName + "Buttons"); 668 | int $i; 669 | for ($i=0; $i<$tmNumButtons; $i++) { 670 | string $buttonName = $newName + "Button" + $i; 671 | renameUI ($oldName + "Button" + $i) $buttonName; 672 | canvas -e -pc ("tmButtonStart(" + $tmButtonVal[$i] + ", \"" + $newName + "\")") $buttonName ; 673 | } 674 | 675 | renameUI ($oldName + "Label") ($newName + "Label"); 676 | 677 | // rename item in $tmSets array 678 | int $s; 679 | for ($s=0; $s<=size($tmSets); $s++) if ($tmSets[$s] == $oldName) $tmSets[$s]= $newName; 680 | 681 | } 682 | 683 | // ------------------------------------------------------------------------ 684 | 685 | global proc tmSGMDelete(int $mode, int $confirm) { 686 | 687 | global string $tmSets[], $tmGroups[], $sgmArray[]; 688 | 689 | string $modeName[]; 690 | $modeName[0] = " set?"; 691 | $modeName[1] = " group?"; 692 | 693 | string $i[], $item; 694 | int $iP[], $itemPos; 695 | $i = `textScrollList -q -si tmSGMList`; 696 | $iP = `textScrollList -q -sii tmSGMList`; 697 | $item = $i[0]; 698 | $itemPos = $iP[0]-1; 699 | 700 | // display confirmation if $confirm is 1 701 | string $c; 702 | if ($confirm) { 703 | string $confirmMsg = "Are you sure you want to delete the \"" + $item + "\"" + $modeName[$mode]; 704 | $c = `confirmDialog -t ("Delete" + $modeName[$mode]) -m $confirmMsg -b "Yes" -b "No" -db "Yes" -cb "No" -ds "No"`; 705 | } else $c = "Yes"; 706 | 707 | if ($c == "Yes") { 708 | if (!$mode) { 709 | // query group from UI 710 | string $group = `optionMenu -q -v tmSGMGroups`; 711 | 712 | // build name of full set 713 | $setName = "tm" + $group + $item + "Set"; 714 | 715 | // remove set from $tmSets array 716 | $tmSets = stringArrayRemove ({$setName},$tmSets); 717 | 718 | // remove setSC from groupSC, and delete setSC 719 | string $setSC = $setName + "SC"; 720 | string $grpSC = "tm" + $group + "GroupSC"; 721 | selectionConnection -e -rm $setSC $grpSC; 722 | 723 | // remove set from group in main window 724 | deleteUI ($setName + "Spacer"); 725 | deleteUI ($setName + "OuterRow"); 726 | 727 | // remove set from XML 728 | for ($set in tmSetsInGroup($group,2)) { 729 | int $setOrder = `getAttr ($set + ".order")`; 730 | if ($setOrder == $itemPos) delete $set; 731 | if ($setOrder > $itemPos) setAttr -type "string" ($set + ".order") ($setOrder -1); 732 | } 733 | 734 | // remove set 735 | delete $setName; 736 | 737 | tmSGMRebuildList; 738 | 739 | } else { 740 | // remove group from $tmGroups array 741 | $tmGroups = stringArrayRemove ({$item},$tmGroups); 742 | 743 | // remove groupSC from masterSC 744 | selectionConnection -e -rm ("tm" + $item + "GroupSC") tmMasterSC; 745 | 746 | // remove all sets in group from $tmSets array 747 | string $set; 748 | for ($set in tmSetsInGroup($item,1)) { 749 | $tmSets = stringArrayRemove ({$set},$tmSets); 750 | } 751 | 752 | if (!size($tmGroups)) menuItem -e -en 0 tmAddSetMI; 753 | 754 | // remove group from UI 755 | deleteUI ("tm" + $item + "Group"); 756 | 757 | // remove group from XML 758 | for ($grp in getByType("tmGroups1","tmGroup")) { 759 | int $grpOrder = `getAttr ($grp + ".order")`; 760 | if ($grpOrder == $itemPos) delete $grp; 761 | if ($grpOrder > $itemPos) setAttr -type "string" ($grp + ".order") ($grpOrder-1); 762 | } 763 | 764 | tmSGMRebuildList; 765 | } 766 | 767 | } 768 | } 769 | 770 | // ************************************************************************ 771 | // Build sets and groups 772 | // ************************************************************************ 773 | 774 | global proc tmBuildGroup (string $groupName, int $order) { 775 | 776 | global string $tmGroups[]; 777 | 778 | print ("Building group: " + $groupName + "..."); 779 | 780 | $tmGroups[$order] = $groupName; 781 | string $grpPrefix = "tm" + $groupName; 782 | string $checkCommand = "tmTickToggle(\"" + $groupName + "\", \"Main\")"; 783 | 784 | setParent tmMainGroupCL; 785 | 786 | int $s = 1-(`checkBox -q -v tmMainSelectedSetTicks`); 787 | frameLayout -l $groupName -cl 1 -cll 1 ($grpPrefix + "Group"); 788 | columnLayout -adj true ($grpPrefix + "GroupCL"); 789 | checkBox -l "Toggle All" -v 1 -en $s -cc $checkCommand ($groupName + "Ticks"); 790 | 791 | setParent tweenMachineWin; 792 | 793 | // make selectionConnection for group and add to master 794 | string $grpSC = $grpPrefix + "GroupSC"; 795 | selectionConnection -p ($grpPrefix + "GroupCL") -lst $grpSC; 796 | selectionConnection -e -add $grpSC tmMasterSC; 797 | 798 | print ("done.\n"); 799 | 800 | } 801 | 802 | // ------------------------------------------------------------------------ 803 | 804 | global proc tmBuildSet (string $groupName, string $setName) { 805 | 806 | global string $tmSets[]; 807 | global int $tmSliderWidth, $tmShowSliders; 808 | 809 | $setLabel = $setName; 810 | 811 | $setName = "tm" + $groupName + $setName + "Set"; 812 | $tmSets[size($tmSets)] = $setName; 813 | 814 | // if first set (Selected), check and disable 815 | // if second set or later, check only; enable based on current Selected set check status 816 | int $tickCheck, $tickEnable; 817 | if (size($tmSets)==1) { 818 | $tickCheck = 1; 819 | $tickEnable = 0; 820 | } else { 821 | $tickCheck = 1; 822 | $tickEnable = 1-(`checkBox -q -v tmMainSelectedSetTicks`); 823 | checkBox -e -en 1 tmMainSelectedSetTicks; 824 | } 825 | 826 | string $groupCLName = "tm" + $groupName + "GroupCL"; // this will need to change to the name of the group form 827 | setParent ($groupCLName); 828 | 829 | separator -style "none" -h 7 ($setName + "Spacer"); // this will go away once the form system is used 830 | 831 | string $checkCommand = "tmTickToggle(\"" + $setName + "\", \"" + $groupName + "\")"; 832 | rowLayout -nc 2 -adj 2 -w 330 -h 30 -rat 1 "bottom" 10 -cat 1 "both" 5 -cal 1 "right" ($setName + "OuterRow"); 833 | columnLayout -adj 1; 834 | rowLayout -nc 2 -adj 2 -cw2 20 70 -rat 1 "bottom" 5 -rat 2 "bottom" 5; 835 | checkBox -l "" -v $tickCheck -en $tickEnable -cc $checkCommand -rs 1 ($setName + "Ticks"); 836 | text -l $setLabel -al "right" ($setName + "Label"); 837 | setParent ..; 838 | setParent ..; 839 | columnLayout; 840 | floatSliderGrp -field 1 -min -100.0 -max 100.0 -v 0 -adj 2 -m $tmShowSliders -cw2 40 $tmSliderWidth -cc ("tmSliderStart(\"" + $setName + "\");") ($setName + "Bias"); 841 | 842 | tmBuildButtonRow ($setName); 843 | 844 | setParent $groupCLName; 845 | 846 | // make selectionConnection for set and add to parent group's selectionConnection 847 | if ($setName != "tmMainSelectedSet" && $setName != "tmCharacterSetCurrentSet") { 848 | string $setSC = $setName + "SC"; 849 | string $grpSC = "tm" + $groupName + "GroupSC"; 850 | selectionConnection -p ($setName + "OuterRow") -obj $setName $setSC; 851 | selectionConnection -e -add $setSC $grpSC; 852 | } 853 | 854 | 855 | } 856 | 857 | // ------------------------------------------------------------------------ 858 | 859 | global proc tmBuildButtonRow (string $setName) { 860 | 861 | global int $tmNumButtons, $tmSliderWidth, $tmShowButtons, $tmButtonRowPad; 862 | global float $tmButtonVal[]; 863 | global string $tmButtonRGB[]; 864 | 865 | int $totalSpace = ($tmNumButtons) * 5; 866 | int $buttonWidth = floor((($tmSliderWidth)-$totalSpace)/$tmNumButtons); 867 | int $leftover = ($tmSliderWidth) - ($totalSpace + ($tmNumButtons * $buttonWidth)) + $tmButtonRowPad; 868 | 869 | string $rowLayoutName = $setName + "Buttons"; 870 | if (`rowLayout -exists $rowLayoutName`) deleteUI $rowLayoutName; 871 | 872 | string $rowBuilder = "rowLayout -nc " + ($tmNumButtons + 1) + " -w 300 -h 15 -m " + $tmShowButtons + " -cw 1 " + ($leftover + 40); 873 | 874 | int $i; 875 | for ($i=1; $i<=$tmNumButtons; $i++) 876 | $rowBuilder += " -cw " + ($i + 1) + " " + ($buttonWidth + 5); 877 | $rowBuilder += " " + $rowLayoutName + ";"; 878 | 879 | eval $rowBuilder; 880 | 881 | text -l "" -h 12; 882 | 883 | for ($i=0; $i<$tmNumButtons; $i++) { 884 | 885 | string $buttonName = $setName + "Button" + $i; 886 | string $canvasBuilder = "canvas -rgb " + $tmButtonRGB[$i] + " -width " + $buttonWidth; 887 | $canvasBuilder += " -h 10 -ann " + $tmButtonVal[$i] + " -pc \"tmButtonStart(" + $tmButtonVal[$i] + ",\\\"" + $setName + "\\\")\" " + $buttonName + ";"; 888 | eval $canvasBuilder; 889 | 890 | } 891 | } 892 | 893 | // ************************************************************************ 894 | // Add Sets and Groups 895 | // ************************************************************************ 896 | 897 | global proc tmAddGroupUI () { 898 | 899 | string $result = `promptDialog -title "Add Group" 900 | -message "Enter name of new group" 901 | -button "OK" -button "Cancel" 902 | -defaultButton "OK" -cancelButton "Cancel" 903 | -dismissString "Cancel"`; 904 | 905 | if ($result == "OK") 906 | tmAddGroup(`promptDialog -q -text`); 907 | 908 | } 909 | 910 | // ------------------------------------------------------------------------ 911 | 912 | global proc tmAddGroup (string $newGroup) { 913 | 914 | global string $tmGroups[], $currParent; 915 | 916 | if (`isValidObjectName($newGroup)`) { 917 | if (`frameLayout -ex ("tm" + $newGroup + "Group")`) { 918 | confirmDialog -t "Group exists" -m "A group by that name already exists. Please choose a new name."; 919 | } else { 920 | 921 | $currParent = "tmGroups1"; 922 | int $order = size($tmGroups); 923 | string $nodeString = "tmGroup id=\"" + $newGroup + "\" order=\"" + $order + "\""; 924 | makeNode ($nodeString,0); 925 | 926 | select -cl; 927 | 928 | tmBuildGroup ($newGroup, $order); 929 | 930 | if (!`menuItem -q -en tmAddSetMI`) menuItem -e -en 1 tmAddSetMI; 931 | 932 | } 933 | } else { 934 | confirmDialog -t "Invalid name" -m "The name entered is not valid.\nGroup names must be valid Maya object names."; 935 | } 936 | 937 | } 938 | 939 | // ------------------------------------------------------------------------ 940 | 941 | global proc tmAddSetUI () { 942 | 943 | global string $tmGroups[]; 944 | 945 | window -t "Add Set" -w 150 -h 110 -rtf 1 -s true -mnb 0 -mxb 0 tmSetUIWin; 946 | 947 | string $command = "tmAddSet(`ls -sl`,`textField -q -tx tmSetUIText`,`optionMenu -q -v tmSelectGroup`)"; 948 | formLayout -w 50 -nd 10 tmSetUIFL; 949 | 950 | text -l "Enter name of new set:" tmSetUILabel1; 951 | textField -ec $command tmSetUIText; 952 | 953 | text -l "Add new set to group:" tmSetUILabel2; 954 | optionMenu tmSelectGroup; 955 | for ($grp in $tmGroups) menuItem -l $grp; 956 | setParent tmSetUIFL; 957 | button -l "OK" -al "center" -c $command tmSetUIOK; 958 | 959 | formLayout -e 960 | 961 | -af tmSetUILabel1 "top" 5 962 | -af tmSetUILabel1 "left" 5 963 | -af tmSetUILabel1 "right" 5 964 | 965 | -ac tmSetUIText "top" 5 tmSetUILabel1 966 | -af tmSetUIText "left" 5 967 | -af tmSetUIText "right" 5 968 | 969 | -ac tmSetUILabel2 "top" 5 tmSetUIText 970 | -af tmSetUILabel2 "left" 5 971 | -af tmSetUILabel2 "right" 5 972 | 973 | -ac tmSelectGroup "top" 5 tmSetUILabel2 974 | -af tmSelectGroup "left" 5 975 | -af tmSelectGroup "right" 5 976 | 977 | -ac tmSetUIOK "top" 7 tmSelectGroup 978 | -ap tmSetUIOK "left" 0 2 979 | -ap tmSetUIOK "right" 0 8 980 | -af tmSetUIOK "bottom" 5 981 | 982 | tmSetUIFL; 983 | 984 | showWindow tmSetUIWin; 985 | 986 | } 987 | 988 | // ------------------------------------------------------------------------ 989 | 990 | global proc tmAddSet (string $nodes[], string $newSet, string $groupName) { 991 | 992 | global string $tmGroups[], $tmSets[], $currParent; 993 | 994 | if (!size($nodes)) { 995 | confirmDialog -t "Nothing Selected" -m "You must select one or more objects to make a new set."; 996 | return; 997 | } 998 | 999 | if (`isValidObjectName($newSet)`) { 1000 | 1001 | string $set; 1002 | for ($set in tmSetsInGroup($groupName,0)) { 1003 | if ($newSet == $set) { 1004 | confirmDialog -t "Set exists in selected group" -m "A set by that name already exists in the selected group.\nPlease choose a new set name, or pick a different group."; 1005 | return; 1006 | } 1007 | } 1008 | 1009 | string $longSetName = "tm" + $groupName + $newSet + "Set"; 1010 | 1011 | // create new set 1012 | sets -n $longSetName $nodes; 1013 | select -r $nodes; 1014 | 1015 | string $groups[]; 1016 | $groups = getByType("tmGroups1","tmGroup"); 1017 | 1018 | for ($grp in $groups) { 1019 | if(`getAttr($grp+".id")` == $groupName) { 1020 | $currParent = $grp; 1021 | } 1022 | } 1023 | 1024 | string $sets[]; 1025 | $sets = getByType($currParent,"tmSet"); 1026 | int $order = size($sets); 1027 | 1028 | string $nodeString = "tmSet id=\"" + $newSet + "\" order=\"" + $order + "\""; 1029 | makeNode ($nodeString,0); 1030 | 1031 | for ($n in $nodes) { 1032 | makeNode ("tmObject",0); 1033 | addContent ($n); 1034 | closeTag; 1035 | } 1036 | 1037 | select -r $nodes; 1038 | 1039 | tmBuildSet ($groupName, $newSet); 1040 | 1041 | if (`window -ex tmSetUIWin`) textField -e -tx "" tmSetUIText; 1042 | string $parentLayout = "tm" + $groupName + "Group"; 1043 | frameLayout -e -cl 0 $parentLayout; 1044 | } else { 1045 | confirmDialog -t "Invalid name" -m "The name entered is not valid.\nSet names must be valid Maya object names."; 1046 | } 1047 | 1048 | } 1049 | // ************************************************************************ 1050 | // Character set utilities 1051 | // ************************************************************************ 1052 | 1053 | global proc tmAddCharacterGroup () { 1054 | 1055 | global string $tmGroups[], $currParent; 1056 | 1057 | // check to see if custom set already exists 1058 | if (`frameLayout -ex "tmCharacterSetGroup"`) { 1059 | confirmDialog -t "Group exists" -m "A group and set that control the current character set already exist."; 1060 | return; 1061 | } 1062 | 1063 | // add group 1064 | $currParent = "tmGroups1"; 1065 | int $order = size($tmGroups); 1066 | string $nodeString = "tmGroup id=\"CharacterSet\" order=\"" + $order + "\""; 1067 | makeNode ($nodeString,0); 1068 | 1069 | tmBuildGroup ("CharacterSet", $order); 1070 | 1071 | if (!`menuItem -q -en tmAddSetMI`) menuItem -e -en 1 tmAddSetMI; 1072 | 1073 | // add set named "Current" 1074 | 1075 | makeNode ("tmSet id=\"Current\" order=\"0\"",0); 1076 | 1077 | makeNode ("tmObject",0); 1078 | addContent ("tmCustomCharacterSet"); 1079 | closeTag; 1080 | 1081 | tmBuildSet ("CharacterSet", "Current"); 1082 | 1083 | } 1084 | 1085 | proc tmGetSubChars (string $curChar, string $group) { 1086 | int $i; 1087 | string $ind, $subChars[], $obj, $charSet; 1088 | 1089 | $charSet = $curChar; 1090 | // if name has namespace, replace colon with underscore 1091 | if (`match ".*:.*" $curChar` != "") $curChar = `substitute ":" $curChar "_"`; 1092 | 1093 | print ("Adding set for sub-character: " + $charSet + "\n"); 1094 | tmAddSet ({$charSet}, $curChar, $group); 1095 | select -cl; 1096 | 1097 | $subChars = `character -q $charSet`; 1098 | 1099 | for ($obj in $subChars) if (`nodeType $obj` == "character") tmGetSubChars ($obj, $group); 1100 | } 1101 | 1102 | global proc tmImportCharSets () { 1103 | 1104 | string $chars[], $subChars[], $obj, $charSet; 1105 | $chars = `currentCharacters`; 1106 | 1107 | for ($char in $chars) { 1108 | $charSet = $char; 1109 | // if name has namespace, replace colon with underscore 1110 | if (`match ".*:.*" $char` != "") $char = `substitute ":" $char "_"`; 1111 | 1112 | if (`frameLayout -ex ("tm" + $char + "Group")`) 1113 | print ("Skipping character: " + $char + " . Group already exists.\n"); 1114 | else { 1115 | print ("Adding group and set for parent character: " + $charSet + "\n"); 1116 | 1117 | tmAddGroup ($char); 1118 | tmAddSet ({$charSet}, $char, $char); 1119 | select -cl; 1120 | 1121 | $subChars = `character -q $charSet`; 1122 | 1123 | for ($obj in $subChars) if (`nodeType $obj` == "character") tmGetSubChars ($obj, $char); 1124 | 1125 | } 1126 | } 1127 | } 1128 | 1129 | // ************************************************************************ 1130 | // Read from XML data in scene 1131 | // ************************************************************************ 1132 | 1133 | global proc tmReadXML () { 1134 | 1135 | global string $tmGroups[], $tmSets[], $tmButtonRGB[]; 1136 | global int $tmNumButtons, $tmShowButtons, $tmShowSliders; 1137 | global float $tmButtonVal[]; 1138 | 1139 | clear $tmGroups; 1140 | clear $tmSets; 1141 | clear $tmButtonVal; 1142 | clear $tmButtonRGB; 1143 | 1144 | $tmSets[0] = "tmMainSelectedSet"; 1145 | 1146 | // read button/slider visibility settings 1147 | $tmShowSliders = getData("tmSliderVis1"); 1148 | $tmShowButtons = getData("tmButtonVis1"); 1149 | menuItem -e -cb $tmShowSliders tmSliderTog; 1150 | menuItem -e -cb $tmShowButtons tmButtonTog; 1151 | 1152 | // read button values and RGB settings 1153 | $tmNumButtons = (int) `getAttr ("tmButtons1.id")`; 1154 | 1155 | int $i; 1156 | for ($i=0; $i<$tmNumButtons; $i++) { 1157 | string $buttonVal = "tmButtonValue" + ($i+1); 1158 | $tmButtonVal[$i] = `getData ($buttonVal)`; 1159 | string $buttonRGB = "tmButtonRGB" + ($i+1); 1160 | $tmButtonRGB[$i] = `getData ($buttonRGB)`; 1161 | } 1162 | 1163 | // read groups 1164 | 1165 | string $groups[]; 1166 | $groups = getByType ("tmGroups1","tmGroup"); 1167 | 1168 | for ($grp in $groups) { 1169 | 1170 | string $grpId = `getAttr ($grp + ".id")`; 1171 | int $grpOrd = `getAttr ($grp + ".order")`; 1172 | $tmGroups[$grpOrd] = $grpId; 1173 | tmBuildGroup ($grpId,$grpOrd); 1174 | 1175 | // get sets in the group and put them in order 1176 | 1177 | string $sets[]; 1178 | $sets = getByType ($grp, "tmSet"); 1179 | 1180 | string $tmpSet[]; 1181 | clear $tmpSet; 1182 | 1183 | for ($set in $sets) { 1184 | 1185 | int $setOrd = `getAttr ($set + ".order")`; 1186 | $tmpSet[$setOrd] = $set; 1187 | 1188 | } 1189 | 1190 | // build sets into groups 1191 | for ($i=0; $i\n"; 1258 | fprint $fileId "\n"; 1259 | 1260 | // export data for options 1261 | fprint $fileId " \n"; 1262 | 1263 | // need to add script to export Options data 1264 | fprint $fileId (" " + $tmShowSliders + "\n"); 1265 | fprint $fileId (" " + $tmShowButtons + "\n"); 1266 | fprint $fileId (" \n"); 1267 | 1268 | int $i = 0; 1269 | for ($i=0; $i<$tmNumButtons; $i++) { 1270 | fprint $fileId " \n"; 1271 | fprint $fileId (" " + $tmButtonRGB[$i] + "\n"); 1272 | fprint $fileId (" " + $tmButtonVal[$i] + "\n"); 1273 | fprint $fileId " \n"; 1274 | } 1275 | 1276 | fprint $fileId (" \n"); 1277 | fprint $fileId " \n"; 1278 | 1279 | // export data for groups and sets 1280 | fprint $fileId " \n"; 1281 | 1282 | string $groups[]; 1283 | $groups = getByType ("tmGroups1","tmGroup"); 1284 | 1285 | for ($grp in $groups) { 1286 | 1287 | string $grpId = `getAttr ($grp + ".id")`; 1288 | string $grpOrd = `getAttr ($grp + ".order")`; 1289 | fprint $fileId (" \n"); 1290 | 1291 | string $sets[]; 1292 | $sets = getByType ($grp,"tmSet"); 1293 | 1294 | for ($set in $sets) { 1295 | string $setId = `getAttr ($set + ".id")`; 1296 | string $order = `getAttr ($set + ".order")`; 1297 | fprint $fileId (" \n"); 1300 | 1301 | string $tmObjects[]; 1302 | $tmObjects = getByType ($set,"tmObject"); 1303 | 1304 | for ($obj in $tmObjects) { 1305 | string $objName = getData($obj); 1306 | fprint $fileId (" " + $objName + "\n"); 1307 | } 1308 | fprint $fileId (" \n"); 1309 | } 1310 | fprint $fileId " \n"; 1311 | } 1312 | 1313 | fprint $fileId " \n"; 1314 | fprint $fileId "\n"; 1315 | fclose $fileId; 1316 | 1317 | // return true to close browser dialog 1318 | return 1; 1319 | 1320 | } else { 1321 | fileBrowser tmSaveToFile "Save" "" 1; 1322 | return 0; 1323 | } 1324 | 1325 | } 1326 | 1327 | // -------------------------------------------------------------------------- 1328 | 1329 | global proc tmLoadFromFile () { 1330 | 1331 | global string $tmSets[]; 1332 | 1333 | string $c; 1334 | // if a set exists, confirm that user wants to load new data 1335 | if (size($tmSets) > 1) $c = `confirmDialog -t "Replace data?" -m "Replace current data with data from file?" -b "Yes" -b "No" -db "Yes" -cb "No" -ds "No"`; 1336 | 1337 | if ($c != "No") { 1338 | 1339 | // show file browser dialog (fileDialog) for user to choose file 1340 | string $file = `fileDialog -dm "*.xml"`; 1341 | if ($file != "") { 1342 | 1343 | // delete existing XML data 1344 | delete tmXML1; 1345 | 1346 | // load XML data from file 1347 | loadXML ($file); 1348 | 1349 | // check that data is valid tweenMachine data 1350 | string $s[] = `ls -sl`; 1351 | string $test[]; 1352 | $test = getByType ("XML1","tmOptions"); 1353 | if (size($test)==0) { 1354 | confirmDialog -t "Invalid file" -m "Selected file does not contain valid tweenMachine data."; 1355 | } else { 1356 | rename XML1 tmXML1; 1357 | select -cl; 1358 | tweenMachine; 1359 | } 1360 | } 1361 | } 1362 | 1363 | } 1364 | 1365 | // ************************************************************************ 1366 | // Starters and main TM procedure 1367 | // ************************************************************************ 1368 | 1369 | global proc tmSliderStart (string $name) { 1370 | 1371 | string $nodes[], $biasCtl; 1372 | 1373 | $biasCtl = $name + "Bias"; 1374 | $poseBias = (`floatSliderGrp -q -v $biasCtl` + 100) / 200; 1375 | 1376 | if (startsWith($name,"tmCharacterSet")) 1377 | $nodes = `currentCharacters`; 1378 | else if ($biasCtl == "tmMainSelectedSetBias") 1379 | $nodes = `ls -sl`; 1380 | else 1381 | $nodes = `sets -q $name`; 1382 | 1383 | 1384 | tween_Machine ($poseBias,$nodes); 1385 | 1386 | } 1387 | 1388 | // -------------------------------------------------------------------------- 1389 | 1390 | global proc tmButtonStart (float $poseBias, string $name) { 1391 | 1392 | string $nodes[]; 1393 | 1394 | $biasCtl = $name + "Bias"; 1395 | floatSliderGrp -e -v $poseBias $biasCtl; 1396 | $poseBias = ($poseBias + 100) / 200; 1397 | 1398 | if (startsWith ($name, "tmCharacterSet")) 1399 | $nodes = `currentCharacters`; 1400 | else if ($biasCtl == "tmMainSelectedSetBias") 1401 | $nodes = `ls -sl`; 1402 | else 1403 | $nodes = `sets -q $name`; 1404 | 1405 | tween_Machine ($poseBias,$nodes); 1406 | 1407 | } 1408 | 1409 | // -------------------------------------------------------------------------- 1410 | 1411 | global proc tween_Machine(float $poseBias, string $nodes[]) { 1412 | 1413 | global int $tmSpecTick; 1414 | string $curves[], $attrs[], $tmp[], $crv, $attr, $biasCtl, $full; 1415 | 1416 | // Get selected range on timeline 1417 | float $timeRng[] = `timeControl -q -ra timeControl1`; 1418 | int $timeC = $timeRng[0]; // current keyframe, where new key will be added 1419 | 1420 | // Get names of selected attributes in channel box 1421 | $attrs = `channelBox -q -sma "mainChannelBox"`; 1422 | // If attributes are selected, build list of curves connected to them 1423 | if (size($attrs)) { 1424 | clear $curves; 1425 | for ($node in $nodes) { 1426 | for ($att in $attrs) { 1427 | $full = $node + "." + $att; 1428 | if (!objExists($full)) 1429 | continue; 1430 | $tmp = `keyframe -q -name $full`; 1431 | if (!size($tmp)) 1432 | continue; 1433 | $curves[size($curves)] = $tmp[0]; 1434 | } 1435 | } 1436 | } else { 1437 | // Get names of all keyframed curves on all selected objects 1438 | $curves = `keyframe -q -name $nodes` ; 1439 | } 1440 | 1441 | waitCursor -state on ; 1442 | 1443 | // Process each curve 1444 | for ($crv in $curves) { 1445 | 1446 | // Find time for next and previous keys... 1447 | float $timeP = `findKeyframe -which previous $crv`; 1448 | float $timeN = `findKeyframe -which next $crv`; 1449 | 1450 | // Find previous and next tangent types 1451 | string $tanInPs[] = `keyTangent -time $timeP -q -itt $crv`; 1452 | string $tanOutPs[] = `keyTangent -time $timeP -q -ott $crv`; 1453 | string $tanInNs[] = `keyTangent -time $timeN -q -itt $crv`; 1454 | string $tanOutNs[] = `keyTangent -time $timeN -q -ott $crv`; 1455 | 1456 | // Set new in and out tangent types based on previous and next tangent types 1457 | string $tanInC = $tanOutPs[0]; 1458 | string $tanOutC = $tanInNs[0]; 1459 | 1460 | // However...if any of the types (previous or next) is "fixed", then use the global (default) tangent instead 1461 | if (($tanInPs[0] == "fixed") || 1462 | ($tanOutPs[0] == "fixed") || 1463 | ($tanInNs[0] == "fixed") || 1464 | ($tanOutNs[0] == "fixed")) 1465 | { 1466 | string $tanInGs[] = `keyTangent -q -g -itt`; 1467 | string $tanOutGs[] = `keyTangent -q -g -ott`; 1468 | $tanInC = $tanInGs[0]; 1469 | $tanOutC = $tanOutGs[0]; 1470 | } 1471 | else 1472 | { 1473 | if ($tanOutNs[0] == "step") 1474 | $tanOutC = $tanOutNs[0]; 1475 | } 1476 | 1477 | // Find previous and next key values 1478 | float $valPs[] = `keyframe -time $timeP -q -valueChange $crv` ; 1479 | float $valNs[] = `keyframe -time $timeN -q -valueChange $crv` ; 1480 | 1481 | float $valP = $valPs[0] ; 1482 | float $valN = $valNs[0] ; 1483 | 1484 | // Find difference in value between previous and next keys 1485 | float $diff = $valN - $valP ; 1486 | 1487 | // Find percentage of difference to use based on Pose Bias value 1488 | float $diffToUse = $diff * $poseBias; 1489 | 1490 | // Find current key value by adding amount used to previous key 1491 | float $valC = $valP + $diffToUse; 1492 | 1493 | // Set new keyframe 1494 | setKeyframe -t $timeC -v $valC -ott $tanOutC $crv; 1495 | if ($tmSpecTick) 1496 | keyframe -tds on -t $timeC $crv; 1497 | 1498 | if ($tanInC != "step") 1499 | keyTangent -t $timeC -itt $tanInC $crv; 1500 | 1501 | } 1502 | 1503 | currentTime -e $timeC; 1504 | global string $gMainWindow; 1505 | setFocus $gMainWindow; 1506 | waitCursor -state off ; 1507 | 1508 | } 1509 | 1510 | // ************************************************************************ 1511 | // Misc. helper procedures 1512 | // ************************************************************************ 1513 | 1514 | global proc string[] tmSetsInGroup (string $group, int $type) { 1515 | // $size: 0 for short set names, 1 for full set names, 2 for XML object names 1516 | 1517 | global string $tmSets[]; 1518 | string $setsInGroup[]; 1519 | 1520 | if ($type < 2) { 1521 | for ($set in $tmSets) { 1522 | string $setSW = "tm" + $group; 1523 | if (startsWith ($set, $setSW)) { 1524 | if ($type == 0) { 1525 | $set = `substitute $setSW $set ""`; 1526 | $set = `substitute "Set" $set ""`; 1527 | } 1528 | $setsInGroup[size($setsInGroup)] = $set; 1529 | } 1530 | } 1531 | } else { 1532 | for ($grp in getByType("tmGroups1","tmGroup")) { 1533 | if (`getAttr ($grp + ".id")` == $group) $setsInGroup = getByType($grp,"tmSet"); 1534 | } 1535 | } 1536 | 1537 | return $setsInGroup; 1538 | } 1539 | 1540 | // -------------------------------------------------------------------------- 1541 | 1542 | global proc string tmFindInXML (string $type, string $parent, string $att, string $val) { 1543 | 1544 | // find set or group in XML data with parent $parent where attribute $att = value $val 1545 | // $type = 0 (set) or 1 (group) 1546 | 1547 | string $foundObj; 1548 | 1549 | string $obj; 1550 | for($obj in getByType($parent,$type)) { 1551 | string $v = `getAttr ($obj + $att)`; 1552 | if ($v == $val) $foundObj = $obj; 1553 | } 1554 | 1555 | return $foundObj; 1556 | } 1557 | 1558 | // -------------------------------------------------------------------------- 1559 | 1560 | global proc tmRestoreTimeControl () { 1561 | timeControl -e -mlc animationList timeControl1; 1562 | } -------------------------------------------------------------------------------- /mel/tweenMachine.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/boredstiff/tweenMachine/dd509747c9bfb0b2bd3a7fc3635ea840ed7bfacd/mel/tweenMachine.png -------------------------------------------------------------------------------- /mel/xml_lib.mel: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | xml_lib.mel 4 | J. Adrian Herbez 5 | 6 | This script is meant to be used as a library, rather than a standalone script. To use the script, place the following line at the top of your MEL script: 7 | 8 | source xml_lib.mel; 9 | 10 | That will give you access to all of the functions defined herein. The script will parse XML data and store it into a scene in the form of empty transform nodes, parented to preserve the hierarchy in the file. 11 | 12 | */ 13 | 14 | global string $currParent; 15 | 16 | global proc string getData(string $node) 17 | { 18 | string $output; 19 | 20 | if (catch($output = `getAttr ($node+".data")`)) 21 | { 22 | warning("Specified node has no data - try requesting attributes, or examining the children nodes"); 23 | } 24 | 25 | return $output; 26 | } 27 | 28 | 29 | // this procedure returns an array of all the attributes of the given node 30 | // at a minimum, there should always be a type attribute holding the type of node 31 | // each attribute is listed as attName=value 32 | // break it apart with tokenize, or just use MEL's getAttr directly 33 | global proc string[] getAtts(string $node) 34 | { 35 | string $atts[] = `listAttr -ud $node`; 36 | 37 | string $list[]; 38 | string $temp; 39 | 40 | for ($i in $atts) 41 | { 42 | $temp = $i; 43 | $temp += "="; 44 | $temp += `getAttr ($node+"."+$i)`; 45 | 46 | $list[size($list)] = $temp; 47 | } 48 | 49 | return $list; 50 | } 51 | 52 | 53 | // returns a list of all nodes of a given type in the specified XML file 54 | global proc string[] getByType(string $topNode, string $type) 55 | { 56 | string $list[]; 57 | string $all[] = `listRelatives -ad $topNode`; 58 | 59 | string $temp; 60 | 61 | for ($i in $all) 62 | { 63 | $temp = `getAttr ($i+".type")`; 64 | 65 | if ($temp == $type) 66 | { 67 | $list[size($list)] = $i; 68 | } 69 | } 70 | 71 | return $list; 72 | } 73 | 74 | // parses the specified XML file 75 | global proc string loadXML(string $fileName) 76 | { 77 | global string $currParent; 78 | int $fileID = `fopen $fileName "r"`; 79 | 80 | string $currTag[]; 81 | int $tagI = 0; 82 | 83 | string $line = `fgetline $fileID`; 84 | 85 | string $char; 86 | string $tag; 87 | string $close; 88 | int $start = 1; 89 | string $content = ""; 90 | 91 | string $topNode = makeNode("XML file",1); 92 | $currParent = $topNode; 93 | string $newNode; 94 | 95 | while ($line != "") 96 | { 97 | for ($i=1;$i"` != 0) 122 | { 123 | $tag += $char; 124 | $i++; 125 | $char = `substring $line $i $i`; 126 | } 127 | if ($start) 128 | { 129 | // make a new node 130 | makeNode($tag,0); 131 | } 132 | else 133 | { 134 | // jump up a level 135 | closeTag(); 136 | } 137 | } 138 | else 139 | { 140 | // not in a tag- must be actual data 141 | $content += $char; 142 | $i++; 143 | $char = `substring $line $i $i`; 144 | while ((`strcmp $char "<"` != 0) && ($i < size($line))) 145 | { 146 | $content += $char; 147 | $i++; 148 | $char = `substring $line $i $i`; 149 | } 150 | $i--; 151 | } 152 | 153 | } 154 | 155 | $line = `fgetline $fileID`; 156 | } 157 | 158 | fclose $fileID; 159 | 160 | select -r $topNode; 161 | 162 | print ("\n"+$content+"\n"); 163 | 164 | return $topNode; 165 | } 166 | 167 | ///////////////////////////////////////////////////////////////////////////////////////// 168 | /* 169 | Below are a number of helper procedures used by the above functions. The procedures below aren't meant to be called directly. 170 | */ 171 | 172 | // creates a node, sets its attributes, and parents it to the appropriate node 173 | global proc string makeNode(string $type,int $root) 174 | { 175 | $type = substituteAllString($type,"?",""); 176 | 177 | global string $currParent; 178 | 179 | string $buffer[]; 180 | 181 | tokenize $type " " $buffer; 182 | if (size($buffer) > 1) 183 | { 184 | $type = $buffer[0]; 185 | } 186 | 187 | int $addOn = 1; 188 | 189 | string $tempName = $type + $addOn; 190 | 191 | while (`objExists $tempName`) 192 | { 193 | $addOn++; 194 | $tempName = $type + $addOn; 195 | } 196 | 197 | $name = `group -em `; 198 | 199 | if (!$root) 200 | { 201 | string $temp[] = `parent $name $currParent`; 202 | $name = $temp[0]; 203 | } 204 | 205 | $name = `rename $name $tempName`; 206 | $currParent = $name; 207 | 208 | addAttr -ln type -dt "string" $name; 209 | setAttr -type "string" ($name+".type") $type; 210 | 211 | for ($i=1;$i 1: 255 | LOG.warn('Multiple tweenMachine data nodes found. Using {}'.format(self.node)) 256 | # If the data is in the old format (tmXML has children), convert it 257 | if mc.listRelatives(self.node, children=True): 258 | LOG.info('# tweenMachine: Old data found. Converting.') 259 | self.root = etree.XML("") 260 | self.tree = etree.ElementTree(self.root) 261 | # Create base elements 262 | buttons_element = etree.SubElement(self.root, "buttons") 263 | buttons_element.set("height", str(SETTINGS["button_height"])) 264 | groups_element = etree.SubElement(self.root, "groups") 265 | # Convert option data 266 | slider_vis_node = mc.ls("tmSliderVis*")[0] 267 | slider_vis_value = int(mc.getAttr(slider_vis_node + ".data")) 268 | button_vis_node = mc.ls("tmSliderVis*")[0] 269 | button_vis_value = int(mc.getAttr(button_vis_node + ".data")) 270 | if slider_vis_value and button_vis_value: 271 | show_mode = "both" 272 | else: 273 | if slider_vis_value: 274 | show_mode = "slider" 275 | else: 276 | show_mode = "buttons" 277 | SETTINGS["show_mode"] = show_mode 278 | # Convert button data 279 | buttons_node = mc.ls("tmButtons*")[0] 280 | for node in mc.listRelatives(buttons_node, children=True): 281 | suffix = node[-1] 282 | bcolor = str(mc.getAttr("tmButtonRGB%s.data" % suffix)) 283 | bvalue = str(mc.getAttr("tmButtonValue%s.data" % suffix)) 284 | button_element = etree.SubElement(buttons_element, "button") 285 | button_element.set("rgb", bcolor) 286 | button_element.set("value", bvalue) 287 | # Convert groups and sets 288 | group_node = mc.ls("tmGroups*")[0] 289 | for node in mc.ls(group_node + "|tmGroup*"): 290 | # Get the group name and order 291 | gname = str(mc.getAttr(node + ".id")) 292 | gorder = str(mc.getAttr(node + ".order")) 293 | group_element = etree.SubElement(groups_element, "group") 294 | group_element.set("name", gname) 295 | group_element.set("index", gorder) 296 | # Get the sets in this group 297 | for setnode in mc.listRelatives(node, children=True): 298 | setname = str(mc.getAttr(setnode + ".id")) 299 | setorder = str(mc.getAttr(setnode + ".order")) 300 | # Create a set node and add the set objects to it 301 | set_element = etree.SubElement(group_element, "set") 302 | set_element.set("name", setname) 303 | set_element.set("index", setorder) 304 | setobjs = [] 305 | for objnode in mc.listRelatives(setnode, children=True): 306 | setobjs.append(str(mc.getAttr(objnode + ".data"))) 307 | set_element.text = " ".join(setobjs) 308 | # Otherwise get the data from the node 309 | else: 310 | self.root = etree.XML(mc.getAttr(node + ".data")) 311 | self.tree = etree.ElementTree(self.root) 312 | # Otherwise start from scratch 313 | else: 314 | self.root = etree.XML(""" 315 | 316 |