├── .gitignore ├── .pre-commit-config.yaml ├── LICENSE ├── README.md ├── pyproject.toml ├── setup.sh └── src ├── boScripts.mod └── boScripts └── scripts ├── abPointLoft.py ├── boBatchFileMaker.py ├── boBatchFileProcessor.mel ├── boBlendShapes.mel ├── boCurveSlider.py ├── boRandomizer.mel ├── boRenderStats.mel ├── boScriptJobs.mel ├── boSliders.mel ├── boSmear.py ├── boTSMTools.mel ├── boTimers.mel ├── boTimers.py ├── boTimingCharts.mel ├── boTriggers.mel ├── boUVSnapshot.py ├── boUtilities.mel └── boZDepthShader.mel /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store* 2 | Thumbs.db 3 | /.project 4 | *.pyc 5 | /bin 6 | /dist 7 | /parts 8 | /eggs 9 | /downloads 10 | /build 11 | /develop-eggs 12 | *.egg-info 13 | -------------------------------------------------------------------------------- /.pre-commit-config.yaml: -------------------------------------------------------------------------------- 1 | # exclude vendored packages, images, maya files, generated ui files 2 | exclude: "vendor|\/.*png|\/.*svg|\/.*ma|gen\/.*py$" 3 | repos: 4 | - repo: https://github.com/pre-commit/pre-commit-hooks 5 | rev: v4.3.0 6 | hooks: 7 | - id: check-ast 8 | language_version: python3 9 | - id: check-yaml 10 | - id: check-case-conflict 11 | - id: check-executables-have-shebangs 12 | - id: check-merge-conflict 13 | - id: end-of-file-fixer 14 | - id: requirements-txt-fixer 15 | - id: trailing-whitespace 16 | - repo: https://github.com/ambv/black 17 | rev: 22.10.0 18 | hooks: 19 | - id: black 20 | language_version: python3 21 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2023 Bohdon Sayre 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 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bohdon/boScripts/49dc6cc2558608a6ff88f87039482f2ba4dbadee/README.md -------------------------------------------------------------------------------- /pyproject.toml: -------------------------------------------------------------------------------- 1 | [tool.black] 2 | line-length = 120 3 | -------------------------------------------------------------------------------- /setup.sh: -------------------------------------------------------------------------------- 1 | #! /bin/bash 2 | 3 | PROJECT_NAME="boScripts" 4 | PACKAGE_NAME="boScripts" 5 | 6 | 7 | if [[ ! "$MAYA_MODULES_INSTALL_PATH" ]]; then 8 | if [[ "$(uname)" == "Darwin" ]]; then 9 | MAYA_MODULES_INSTALL_PATH="$HOME/Library/Preferences/Autodesk/maya/modules" 10 | elif [[ "$(expr substr $(uname -s) 1 5)" == "Linux" ]]; then 11 | MAYA_MODULES_INSTALL_PATH="/usr/autodesk/userconfig/maya/modules" 12 | elif [[ "$(expr substr $(uname -s) 1 5)" == "MINGW" ]]; then 13 | IS_WINDOWS=1 14 | MAYA_MODULES_INSTALL_PATH="$HOME/Documents/maya/modules" 15 | fi 16 | fi 17 | 18 | 19 | 20 | build() { 21 | echo "Building..." 22 | mkdir -p build 23 | cp -R src/$PACKAGE_NAME build/ 24 | cp src/$PACKAGE_NAME.mod build/ 25 | cp LICENSE build/$PACKAGE_NAME 26 | } 27 | 28 | clean() { 29 | echo "Cleaning..." 30 | rm -Rf build 31 | } 32 | 33 | dev() { 34 | uninstall 35 | clean 36 | echo "Installing for development..." 37 | link `pwd`/src/$PACKAGE_NAME.mod $MAYA_MODULES_INSTALL_PATH/$PACKAGE_NAME.mod 38 | link `pwd`/src/$PACKAGE_NAME $MAYA_MODULES_INSTALL_PATH/$PACKAGE_NAME 39 | } 40 | 41 | test() { 42 | if ! [[ "$1" ]]; then 43 | echo "usage: setup.sh test [MAYAVERSION] ..." 44 | return 45 | fi 46 | 47 | build 48 | echo "Running tests..." 49 | echo "Be sure to run 'setup.sh dev' first." 50 | 51 | for version in "$@" 52 | do 53 | # find mayapy 54 | mayapy="$PROGRAMFILES/Autodesk/Maya${version}/bin/mayapy.exe" 55 | # log maya version 56 | py_version=`"$mayapy" -V` 57 | printf "\n> Maya ${version} (${py_version})\n" 58 | # run tests 59 | "$mayapy" tests build/$PACKAGE_NAME 60 | done 61 | } 62 | 63 | install() { 64 | uninstall 65 | clean 66 | build 67 | echo "Installing..." 68 | cp -v build/$PACKAGE_NAME.mod $MAYA_MODULES_INSTALL_PATH/$PACKAGE_NAME.mod 69 | cp -Rv build/$PACKAGE_NAME $MAYA_MODULES_INSTALL_PATH/$PACKAGE_NAME 70 | } 71 | 72 | uninstall() { 73 | echo "Uninstalling..." 74 | rm -v $MAYA_MODULES_INSTALL_PATH/$PACKAGE_NAME.mod || true 75 | rm -Rv $MAYA_MODULES_INSTALL_PATH/$PACKAGE_NAME || true 76 | } 77 | 78 | 79 | ALL_COMMANDS="build, clean, dev, test, install, uninstall" 80 | 81 | 82 | 83 | # Template setup.sh utils 84 | # ----------------------- 85 | 86 | 87 | # simple cross-platform symlink util 88 | link() { 89 | # use mklink if on windows 90 | if [[ -n "$WINDIR" ]]; then 91 | # determine if the link is a directory 92 | # also convert '/' to '\' 93 | if [[ -d "$1" ]]; then 94 | cmd <<< "mklink /D \"`cygpath -w \"$2\"`\" \"`cygpath -w \"$1\"`\"" > /dev/null 95 | else 96 | cmd <<< "mklink \"`cygpath -w \"$2\"`\" \"`cygpath -w \"$1\"`\"" > /dev/null 97 | fi 98 | else 99 | ln -sf "$1" "$2" 100 | fi 101 | } 102 | 103 | # run command by name 104 | if [[ "$1" ]]; then 105 | cd $(dirname "$0") 106 | $1 "${@:2}" 107 | else 108 | echo -e "usage: setup.sh [COMMAND]\n $ALL_COMMANDS" 109 | fi 110 | -------------------------------------------------------------------------------- /src/boScripts.mod: -------------------------------------------------------------------------------- 1 | + boScripts 1.0 ./boScripts -------------------------------------------------------------------------------- /src/boScripts/scripts/abPointLoft.py: -------------------------------------------------------------------------------- 1 | """ 2 | A tool for snapping points to a surface. 3 | Similar effect as using a live surface, except 4 | movement of the points is limited to a single axis. 5 | """ 6 | 7 | __version__ = "1.0" 8 | __author__ = "Ahdom and Bohdon Sayre" 9 | 10 | import logging 11 | 12 | import pymel.core as pm 13 | 14 | logger = logging.getLogger("Point Loft") 15 | logger.setLevel(logging.DEBUG) 16 | 17 | 18 | def doIt(): 19 | selList = pm.ls(sl=True, fl=True) 20 | myPointLoft = PointLoft() 21 | myPointLoft.surf = selList[-1] # get the last selected object (the surface) 22 | myPointLoft.pts = selList[:-1] # get all but the last selected objects (the verts) 23 | myPointLoft.run() 24 | 25 | 26 | class Gui(object): 27 | """ 28 | The GUI Class for Point Loft 29 | Contains three sections for collection points, 30 | the surface, and the axis to perform movement on 31 | 32 | >>> import abPointLoft 33 | >>> abPointLoft.Gui() 34 | """ 35 | 36 | title = "Point Loft %s" % __version__ 37 | winName = "abPointLoftWin" 38 | win = None 39 | ui = {} 40 | pts = [] 41 | surf = None 42 | axis = 0 43 | useNormal = False 44 | 45 | def __init__(self): 46 | self.create() 47 | 48 | def create(self): 49 | if pm.window(self.winName, exists=True): 50 | pm.deleteUI(self.winName) 51 | 52 | with pm.window(self.winName, t=self.title, mxb=False) as self.win: 53 | template = pm.uiTemplate("abPointLoftTemplate", force=True) 54 | template.define(pm.button, w=40, h=20, bgc=[1.4 * v for v in [0.18, 0.21, 0.25]]) 55 | template.define(pm.columnLayout, rs=12, adj=True) 56 | template.define(pm.formLayout, nd=100) 57 | template.define(pm.frameLayout, mw=4, mh=4, bs="out", bgc=[0.18, 0.21, 0.25]) 58 | with template: 59 | with pm.formLayout() as mainForm: 60 | with pm.columnLayout() as mainCol: 61 | with pm.frameLayout(l="Points (0)") as ptsFrame: 62 | with pm.formLayout() as form1: 63 | ptsField = pm.textField(ed=False) 64 | ptsBtn = pm.button(l="Get", c=pm.Callback(self.getPts)) 65 | pm.popupMenu(p=ptsBtn) 66 | pm.menuItem(l="Select Points", c=pm.Callback(self.selectPts)) 67 | with pm.frameLayout(l="Surface") as surfFrame: 68 | with pm.formLayout() as form2: 69 | surfField = pm.textField(ed=False) 70 | surfBtn = pm.button(l="Get", c=pm.Callback(self.getSurf)) 71 | with pm.frameLayout(l="Axis") as axisFrame: 72 | with pm.formLayout() as form3: 73 | axisRadioGrp = pm.radioButtonGrp( 74 | nrb=4, 75 | cc=pm.Callback(self.axisChange), 76 | sl=2, 77 | l1="X", 78 | l2="Y", 79 | l3="Z", 80 | l4="N", 81 | cw4=[30, 30, 30, 30], 82 | ) 83 | runBtn = pm.button(l="Run", h=30, c=pm.Callback(self.run)) 84 | 85 | pm.formLayout( 86 | form1, e=True, af=[(ptsField, "left", 0), (ptsBtn, "right", 0)], ac=[(ptsField, "right", 4, ptsBtn)] 87 | ) 88 | pm.formLayout( 89 | form2, 90 | e=True, 91 | af=[(surfField, "left", 0), (surfBtn, "right", 0)], 92 | ac=[(surfField, "right", 4, surfBtn)], 93 | ) 94 | pm.formLayout(form3, e=True, ap=[(axisRadioGrp, "left", -70, 50)]) 95 | pm.formLayout( 96 | mainForm, 97 | e=True, 98 | af=[ 99 | (mainCol, "top", 6), 100 | (mainCol, "left", 6), 101 | (mainCol, "right", 6), 102 | (runBtn, "left", 6), 103 | (runBtn, "right", 6), 104 | (runBtn, "bottom", 6), 105 | ], 106 | ) 107 | # store ui elements 108 | self.ui["mainForm"] = mainForm 109 | self.ui["mainCol"] = mainCol 110 | self.ui["ptsFrame"] = ptsFrame 111 | self.ui["ptsField"] = ptsField 112 | self.ui["ptsBtn"] = ptsBtn 113 | self.ui["surfFrame"] = surfFrame 114 | self.ui["surfField"] = surfField 115 | self.ui["surfBtn"] = surfBtn 116 | self.ui["axisFrame"] = axisFrame 117 | self.ui["axisRadioGrp"] = axisRadioGrp 118 | self.ui["runBtn"] = runBtn 119 | self.axisChange() 120 | 121 | def getPts(self): 122 | self.pts = pm.ls(sl=True, fl=True) 123 | ptsDisplayList = [str(vert.name()) for vert in self.pts] 124 | self.ui["ptsField"].setText(str(ptsDisplayList)) 125 | self.ui["ptsFrame"].setLabel("Points (%d)" % len(self.pts)) 126 | 127 | def selectPts(self): 128 | pm.select(self.pts) 129 | 130 | def getSurf(self): 131 | self.surf = pm.ls(sl=True)[0] 132 | self.ui["surfField"].setText(self.surf) 133 | 134 | def axisChange(self): 135 | self.axis = self.ui["axisRadioGrp"].getSelect() - 1 136 | if self.axis == 3: 137 | self.axis = 0 138 | self.useNormal = True 139 | else: 140 | self.useNormal = False 141 | 142 | def run(self): 143 | if self.pts == [] or self.surf == []: 144 | logger.error("Not enough information was provided") 145 | return 146 | 147 | print(self.surf, self.axis, self.useNormal, self.pts) 148 | 149 | pl = PointLoft() 150 | pl.pts = self.pts 151 | pl.surf = self.surf 152 | pl.axis = self.axis 153 | pl.useNormal = self.useNormal 154 | pl.run() 155 | 156 | 157 | class PointLoft(object): 158 | """The Main Point Loft class 159 | Takes a list of points, a surface, and an axis and moves 160 | the points to the surface""" 161 | 162 | def __init__(self, surf=[], pts=[], axis=1, useNormal=False): 163 | """The runner class for Point Loft""" 164 | self.surf = surf 165 | self.pts = pts 166 | self.axis = axis 167 | self.useNormal = useNormal 168 | self.axisVectors = [[1, 0, 0], [0, 1, 0], [0, 0, 1], []] 169 | self.ptDeltas = [[0, 1, 0], [0, 0, 1], [1, 0, 0], [1, 2, 3]] 170 | 171 | def run(self): 172 | if self.surf == [] or self.pts == []: 173 | logger.error("Not enough information was provided") 174 | return 175 | 176 | ptDelta = self.ptDeltas[self.axis] 177 | axis = self.axisVectors[self.axis] 178 | 179 | print("axis %s" % axis) 180 | print("ptDelta %s" % ptDelta) 181 | 182 | moveCount = 0 183 | failCount = 0 184 | for pt in self.pts: 185 | ptPos = pm.pointPosition(pt) 186 | ptPos2 = ptPos - ptDelta 187 | c = pm.curve(d=1, p=[ptPos2, ptPos], k=[0, 1]) 188 | if self.useNormal: 189 | proj = pm.projectCurve(c, self.surf, un=True) 190 | else: 191 | proj = pm.projectCurve(c, self.surf, d=axis) 192 | projC = proj[0].listConnections()[1] 193 | if pm.objExists("%s.cv[0]" % projC): 194 | goalPt = pm.pointPosition("%s.cv[0]" % projC) 195 | pm.move(pt, goalPt, a=True, ws=True) 196 | moveCount += 1 197 | else: 198 | failCount += 1 199 | pm.delete(c, proj) 200 | 201 | logger.info("%d point(s) were moved successfully" % moveCount) 202 | if failCount > 0: 203 | logger.warning("%d point(s) could not be moved" % failCount) 204 | -------------------------------------------------------------------------------- /src/boScripts/scripts/boBatchFileMaker.py: -------------------------------------------------------------------------------- 1 | """ 2 | Batch File Maker 3 | 0.2.2 4 | 5 | Copyright (c) 2010 Bohdon Sayre 6 | All Rights Reserved. 7 | bsayre@c.ringling.edu 8 | 9 | Description: 10 | Generates batch files easily for command line rendering with Maya. 11 | 12 | Instructions: 13 | >>> import boBatchFileMaker 14 | >>> boBatchFileMaker.doIt() 15 | 16 | Version 0.2.2: 17 | > Rough 2011 compatibility 18 | > Render Settings display maintained between window sessions 19 | > File List maintained between window sessions 20 | > Right click menu for adding/removing batch file and render settings options 21 | 22 | Feel free to email me with any bugs, comments, or requests! 23 | """ 24 | 25 | import glob 26 | import os 27 | import re 28 | 29 | import maya.cmds as cmds 30 | import maya.mel as mel 31 | 32 | 33 | def doIt(): 34 | win = BatchFileMakerWindow() 35 | win.show() 36 | del win 37 | 38 | 39 | def pyError(errorString): 40 | """print an error message""" 41 | import maya.mel as mel 42 | 43 | try: 44 | mel.eval(r'error "%s"' % errorString) 45 | except: 46 | pass 47 | 48 | 49 | def pyWarning(warningString): 50 | """print a warning message""" 51 | import maya.mel as mel 52 | 53 | try: 54 | mel.eval(r'warning "%s"' % warningString) 55 | except: 56 | pass 57 | 58 | 59 | def getMAFrameRange(maFile): 60 | # check ext 61 | if not os.path.exists(maFile): 62 | print("file not found: %s" % maFile) 63 | return 64 | root, ext = os.path.splitext(maFile) 65 | if ext != ".ma": 66 | print("filetype is not mayaAscii: %s" % maFile) 67 | return 68 | 69 | startFrame, endFrame = None, None 70 | 71 | fsock = open(maFile, "r") 72 | try: 73 | lines = fsock.readlines() 74 | for line in lines: 75 | if re.search('setAttr ".fs"', line): 76 | split = line.split(" ") 77 | try: 78 | startFrame = int(re.match("[0-9]*", split[2]).group()) 79 | except: 80 | pass 81 | if re.search('setAttr ".ef"', line): 82 | split = line.split(" ") 83 | try: 84 | endFrame = int(re.match("[0-9]*", split[2]).group()) 85 | except: 86 | pass 87 | except: 88 | pass 89 | finally: 90 | fsock.close() 91 | 92 | return [startFrame, endFrame] 93 | 94 | 95 | class BatchFileMakerError(Exception): 96 | def __init__(self, value): 97 | self.value = value 98 | 99 | def __str__(self): 100 | return repr(self.value) 101 | 102 | 103 | class BatchFileMakerWindow: 104 | _name = "bbfmWin" 105 | _title = "Batch File Maker 0.2.1" 106 | 107 | # GUI element names 108 | _mainForm = "bbfmWin_MainForm" 109 | _winWidth = 640 110 | _winHeight = 600 111 | _frameHeights = 308 112 | _fl_form = "bbfmWin_FileListForm" 113 | _fl_list = "bbfmWin_FileList" 114 | _fl_addBtn = "bbfmWin_AddFileBtn" 115 | _fl_remBtn = "bbfmWin_RemoveFileBtn" 116 | _fl_clearBtn = "bbfmWin_ClearListBtn" 117 | _fl_loadBtn = "bbfmWin_LoadFolderBtn" 118 | _rs_centerLine = -32 119 | _rs_frame = "bbfmWin_RenderSettingsFrame" 120 | _rs_form = "bbfmWin_RenderSettingsForm" 121 | _rs_popup = "bbfmWin_RenderSettingsPopup" 122 | _rs_mm_range = "bbfmWin_RSMM_FrameRangeItem" 123 | _rs_mm_pad = "bbfmWin_RSMM_PaddingItem" 124 | _rs_mm_res = "bbfmWin_RSMM_ResolutionItem" 125 | _rs_mm_fnc = "bbfmWin_RSMM_FileNameFormatItem" 126 | _rs_mm_of = "bbfmWin_RSMM_OutputFormatItem" 127 | _rs_mm_r = "bbfmWin_RSMM_RendererItem" 128 | _rs_mm_pd = "bbfmWin_RSMM_ProjectItem" 129 | _rs_mm_rd = "bbfmWin_RSMM_RenderDirectoryItem" 130 | _rs_noOptsText = "bbfmWin_RenderSettingsNoOptionsText" 131 | _rs_rangeText1 = "bbfmWin_FrameRangeText1" 132 | _rs_start = "bbfmWin_FrameRangeStartField" 133 | _rs_rangeText2 = "bbfmWin_FrameRangeText2" 134 | _rs_end = "bbfmWin_FrameRangeEndField" 135 | _rs_getRangeText = "bbfmWin_GetFrameRangeText" 136 | _rs_getRangeBtn = "bbfmWin_GetFrameRangeBtn" 137 | _rs_padText = "bbfmWin_PaddingText" 138 | _rs_pad = "bbfmWin_PaddingField" 139 | _rs_resText = "bbfmWin_ResText" 140 | _rs_resW = "bbfmWin_ResWidthField" 141 | _rs_resH = "bbfmWin_ResHeightField" 142 | _rs_fncText = "bbfmWin_FileNamingText" 143 | _rs_fncOpt = "bbfmWin_FileNamingOption" 144 | _rs_ofText = "bbfmWin_OutputFormatText" 145 | _rs_ofOpt = "bbfmWin_OutputFormatOption" 146 | _rs_pdText = "bbfmWin_ProjectText" 147 | _rs_pdField = "bbfmWin_ProjectField" 148 | _rs_pdBtn = "bbfmWin_ProjectBtn" 149 | _rs_rdText = "bbfmWin_RenderDirectoryText" 150 | _rs_rdField = "bbfmWin_RenderDirectoryField" 151 | _rs_rdBtn = "bbfmWin_RenderDirectoryBtn" 152 | _rs_rText = "bbfnWin_RendererText" 153 | _rs_rOpt = "bbfmWin_RendererOption" 154 | _bfs_centerLine = -32 155 | _bfs_frame = "bbfmWin_BatchFileSettingsFrame" 156 | _bfs_form = "bbfmWin_BatchFileSettingsForm" 157 | _bfs_popup = "bbfmWin_BatchFileSettingsPopup" 158 | _bfs_nameText = "bbfmWin_NamingConventionText" 159 | _bfs_prefixText = "bbfmWin_Naming_PrefixText" 160 | _bfs_prefixField = "bbfmWin_Naming_PrefixField" 161 | _bfs_sceneCheck = "bbfmWin_Naming_SceneNameCheck" 162 | _bfs_rangeCheck = "bbfmWin_Naming_FrameRangeCheck" 163 | _bfs_numberedCheck = "bbfmWin_Naming_NumberedCheck" 164 | _bfs_previewText = "bbfmWin_Naming_previewText" 165 | _bfs_sep1 = "bbfmWin_RS_Sep1" 166 | _bfs_divText = "bbfmWin_FrameRangeDivisionsText" 167 | _bfs_divField = "bbfmWin_FrameRangeDivisionsField" 168 | _bfs_divText2 = "bbfmWin_FrameRangeDivisionsText2" 169 | _bfs_sep2 = "bbfmWin_RS_Sep2" 170 | _bfs_saveText = "bbfmWin_SaveLocationText" 171 | _bfs_saveField = "bbfmWin_SaveLocationField" 172 | _bfs_saveBtn = "bbfmWin_SaveLocationBtn" 173 | 174 | _makeBtn = "bbfmWin_MakeBatchFilesBtn" 175 | 176 | mel.eval("global string $bbfmWin_fileList[];") 177 | mel.eval("global int $bbfmWin_renderSettingsCheck[];") 178 | mel.eval("global int $bbfmWin_renderSettingsInts[];") 179 | mel.eval("global string $bbfmWin_renderSettingsStrings[];") 180 | 181 | def sendToMel(self, value, var): 182 | """Sends a python variable to mel""" 183 | cmd = "$%s = %s" % (var, value) 184 | mel.eval(cmd) 185 | 186 | def getFromMel(self, var, tempVar="temp"): 187 | """Returns the value of a mel veriable""" 188 | cmd = "$%s = $%s;" % (tempVar, var) 189 | return mel.eval(cmd) 190 | 191 | def show(self): 192 | if cmds.window(self._name, exists=True): 193 | cmds.deleteUI(self._name) 194 | 195 | cmds.window(self._name, s=True, mb=True, rtf=False, t=self._title) 196 | 197 | if cmds.menu(l="Edit"): 198 | cmds.menuItem(l="Reset All Settings", c=self.resetSettings) 199 | if cmds.menu(l="Help"): 200 | cmds.menuItem(l="Help on Batch File Maker", en=False) 201 | 202 | if cmds.formLayout(self._mainForm, nd=100): 203 | # file list form 204 | if cmds.formLayout(self._fl_form, nd=100): 205 | fileList = self.getFromMel("bbfmWin_fileList", "tempArray") 206 | cmds.textScrollList(self._fl_list, ams=True, sc=self.fl_listSelectCommand, append=fileList) 207 | cmds.button(self._fl_addBtn, l="Add Files...", c=self.fl_addFiles) 208 | cmds.button(self._fl_loadBtn, l="Add Folder...", c=self.fl_addFolder) 209 | cmds.button(self._fl_remBtn, l="Remove Selected Files", c=self.fl_remSelFiles) 210 | cmds.button(self._fl_clearBtn, l="Clear List", c=self.fl_clearFiles) 211 | cmds.setParent(self._mainForm) 212 | del fileList 213 | cmds.formLayout( 214 | self._fl_form, 215 | e=True, 216 | af=[(self._fl_list, "left", 0), (self._fl_list, "right", 0), (self._fl_list, "top", 0)], 217 | ac=[(self._fl_list, "bottom", 2, self._fl_addBtn)], 218 | ) 219 | cmds.formLayout( 220 | self._fl_form, 221 | e=True, 222 | af=[ 223 | (self._fl_addBtn, "bottom", 8), 224 | (self._fl_loadBtn, "bottom", 8), 225 | (self._fl_remBtn, "bottom", 8), 226 | (self._fl_clearBtn, "bottom", 8), 227 | ], 228 | ) 229 | cmds.formLayout( 230 | self._fl_form, e=True, ap=[(self._fl_addBtn, "left", 4, 0), (self._fl_addBtn, "right", 2, 25)] 231 | ) 232 | cmds.formLayout( 233 | self._fl_form, e=True, ap=[(self._fl_loadBtn, "left", 4, 25), (self._fl_loadBtn, "right", 2, 50)] 234 | ) 235 | cmds.formLayout( 236 | self._fl_form, e=True, ap=[(self._fl_remBtn, "left", 4, 50), (self._fl_remBtn, "right", 2, 75)] 237 | ) 238 | cmds.formLayout( 239 | self._fl_form, e=True, ap=[(self._fl_clearBtn, "left", 4, 75), (self._fl_clearBtn, "right", 2, 100)] 240 | ) 241 | 242 | # render settings frame/form 243 | if cmds.frameLayout(self._rs_frame, l="Render Settings", bs="etchedOut", li=10, height=self._frameHeights): 244 | if cmds.popupMenu(self._rs_popup, mm=True): 245 | checkList = self.getFromMel("bbfmWin_renderSettingsCheck", "tempIntArray") 246 | if len(checkList) != 8: 247 | checkList = [0, 0, 0, 0, 0, 0, 0, 0] 248 | cmds.menuItem( 249 | self._rs_mm_range, l="Frame Range", cb=checkList[0], c=self.rs_updateRenderSettingsDisplay 250 | ) 251 | cmds.menuItem(self._rs_mm_pad, l="Padding", cb=checkList[1], c=self.rs_updateRenderSettingsDisplay) 252 | cmds.menuItem( 253 | self._rs_mm_res, l="Resolution", cb=checkList[2], c=self.rs_updateRenderSettingsDisplay 254 | ) 255 | cmds.menuItem( 256 | self._rs_mm_fnc, l="File Naming Format", cb=checkList[3], c=self.rs_updateRenderSettingsDisplay 257 | ) 258 | cmds.menuItem( 259 | self._rs_mm_of, l="Output Format", cb=checkList[4], c=self.rs_updateRenderSettingsDisplay 260 | ) 261 | cmds.menuItem(self._rs_mm_r, l="Renderer", cb=checkList[5], c=self.rs_updateRenderSettingsDisplay) 262 | cmds.menuItem(self._rs_mm_pd, l="Project", cb=checkList[6], c=self.rs_updateRenderSettingsDisplay) 263 | cmds.menuItem( 264 | self._rs_mm_rd, l="Render Directory", cb=checkList[7], c=self.rs_updateRenderSettingsDisplay 265 | ) 266 | cmds.menuItem(d=True) 267 | cmds.menuItem(l="Add All", c=self.rs_addRenderSettingsAll) 268 | cmds.menuItem(l="Remove All", c=self.rs_removeRenderSettingsAll) 269 | del checkList 270 | if cmds.formLayout(self._rs_form, nd=100): 271 | # renderSettingInts = 272 | cmds.text(self._rs_noOptsText, l="Right Click to Add Settings...", al="center") 273 | cmds.text(self._rs_rangeText1, l="Frame Range") 274 | cmds.intField(self._rs_start, v=1, w=60) 275 | cmds.text(self._rs_rangeText2, l="-") 276 | cmds.intField(self._rs_end, v=10, w=60) 277 | cmds.button(self._rs_getRangeBtn, l="get range from file", c=self.rs_getRangeBtnCommand) 278 | cmds.text(self._rs_getRangeText, l="(requires .ma)", en=False) 279 | cmds.text(self._rs_padText, l="Padding") 280 | cmds.intField(self._rs_pad, v=4, w=60) 281 | cmds.text(self._rs_resText, l="Resolution") 282 | cmds.intField(self._rs_resW, v=853, w=60) 283 | if cmds.popupMenu(mm=True): 284 | cmds.menuItem(l="853x480", c=self.rs_setResPreset480) 285 | cmds.menuItem(l="1280x720", c=self.rs_setResPreset720) 286 | cmds.menuItem(l="1920x1080", c=self.rs_setResPreset1080) 287 | cmds.intField(self._rs_resH, v=480, w=60) 288 | if cmds.popupMenu(mm=True): 289 | cmds.menuItem(l="853x480", c=self.rs_setResPreset480) 290 | cmds.menuItem(l="1280x720", c=self.rs_setResPreset720) 291 | cmds.menuItem(l="1920x1080", c=self.rs_setResPreset1080) 292 | cmds.text(self._rs_fncText, l="File Naming Format") 293 | if cmds.optionMenu(self._rs_fncOpt): 294 | cmds.menuItem(l="name") 295 | cmds.menuItem(l="name.ext") 296 | cmds.menuItem(l="name.#.ext") 297 | cmds.menuItem(l="name.ext.#") 298 | cmds.menuItem(l="name.#") 299 | cmds.menuItem(l="name#.ext") 300 | cmds.menuItem(l="name_#.ext") 301 | cmds.optionMenu(self._rs_fncOpt, e=True, sl=3) 302 | cmds.text(self._rs_ofText, l="Output Format") 303 | if cmds.optionMenu(self._rs_ofOpt): 304 | cmds.menuItem(l="Targa") 305 | cmds.menuItem(l="Tiff8") 306 | cmds.menuItem(l="Tiff16") 307 | cmds.menuItem(l="Tiff32") 308 | cmds.menuItem(l="OpenEXR") 309 | cmds.menuItem(l="MayaIFF") 310 | cmds.text(self._rs_rText, l="Renderer") 311 | if cmds.optionMenu(self._rs_rOpt): 312 | cmds.menuItem(l="RenderMan") 313 | cmds.menuItem(l="Maya Software") 314 | cmds.menuItem(l="Mental Ray") 315 | cmds.text(self._rs_pdText, l="Project Directory") 316 | cmds.textField(self._rs_pdField, width=210, cc=self.rs_pdFieldChange) 317 | if cmds.popupMenu(mm=True): 318 | cmds.menuItem(l="Add to favorites (coming soon)", en=False) 319 | cmds.menuItem(l="Manage project directory favorites...", en=False) 320 | cmds.button(self._rs_pdBtn, l="browse...", c=self.rs_pdBrowse) 321 | cmds.text(self._rs_rdText, l="Render Directory") 322 | cmds.textField(self._rs_rdField, width=210, cc=self.rs_rdFieldChange) 323 | if cmds.popupMenu(mm=True): 324 | cmds.menuItem(l="Add to favorites (coming soon)", en=False) 325 | cmds.menuItem(l="Manage render directory favorites...", en=False) 326 | cmds.button(self._rs_rdBtn, l="browse...", c=self.rs_rdBrowse) 327 | 328 | # no opts text 329 | cmds.formLayout( 330 | self._rs_form, 331 | e=True, 332 | ap=[(self._rs_noOptsText, "left", -75, 50), (self._rs_noOptsText, "top", -20, 50)], 333 | ) 334 | # frame range 335 | cmds.formLayout(self._rs_form, e=True, ap=[(self._rs_start, "left", self._rs_centerLine, 50)]) 336 | cmds.formLayout( 337 | self._rs_form, 338 | e=True, 339 | ac=[ 340 | (self._rs_rangeText1, "right", 2, self._rs_start), 341 | (self._rs_rangeText2, "left", 2, self._rs_start), 342 | (self._rs_end, "left", 2, self._rs_rangeText2), 343 | ], 344 | ) 345 | cmds.formLayout( 346 | self._rs_form, 347 | e=True, 348 | ap=[ 349 | (self._rs_rangeText1, "top", 8, 0), 350 | (self._rs_start, "top", 6, 0), 351 | (self._rs_rangeText2, "top", 8, 0), 352 | (self._rs_end, "top", 6, 0), 353 | ], 354 | ) 355 | # get frame range 356 | cmds.formLayout(self._rs_form, e=True, ap=[(self._rs_getRangeBtn, "left", self._rs_centerLine, 50)]) 357 | cmds.formLayout( 358 | self._rs_form, e=True, ac=[(self._rs_getRangeText, "left", 4, self._rs_getRangeBtn)] 359 | ) 360 | cmds.formLayout( 361 | self._rs_form, 362 | e=True, 363 | ac=[ 364 | (self._rs_getRangeText, "top", 5, self._rs_start), 365 | (self._rs_getRangeBtn, "top", 2, self._rs_start), 366 | ], 367 | ) 368 | # padding 369 | cmds.formLayout(self._rs_form, e=True, ap=[(self._rs_pad, "left", self._rs_centerLine, 50)]) 370 | cmds.formLayout(self._rs_form, e=True, ac=[(self._rs_padText, "right", 2, self._rs_pad)]) 371 | cmds.formLayout( 372 | self._rs_form, 373 | e=True, 374 | ac=[ 375 | (self._rs_padText, "top", 8, self._rs_getRangeBtn), 376 | (self._rs_pad, "top", 6, self._rs_getRangeBtn), 377 | ], 378 | ) 379 | # resolution 380 | cmds.formLayout(self._rs_form, e=True, ap=[(self._rs_resW, "left", self._rs_centerLine, 50)]) 381 | cmds.formLayout( 382 | self._rs_form, 383 | e=True, 384 | ac=[(self._rs_resText, "right", 2, self._rs_resW), (self._rs_resH, "left", 2, self._rs_resW)], 385 | ) 386 | cmds.formLayout( 387 | self._rs_form, 388 | e=True, 389 | ac=[ 390 | (self._rs_resText, "top", 8, self._rs_pad), 391 | (self._rs_resW, "top", 6, self._rs_pad), 392 | (self._rs_resH, "top", 6, self._rs_pad), 393 | ], 394 | ) 395 | # file naming convention 396 | cmds.formLayout(self._rs_form, e=True, ap=[(self._rs_fncOpt, "left", self._rs_centerLine, 50)]) 397 | cmds.formLayout(self._rs_form, e=True, ac=[(self._rs_fncText, "right", 2, self._rs_resW)]) 398 | cmds.formLayout( 399 | self._rs_form, 400 | e=True, 401 | ac=[(self._rs_fncOpt, "top", 6, self._rs_resW), (self._rs_fncText, "top", 8, self._rs_resW)], 402 | ) 403 | # output format 404 | cmds.formLayout(self._rs_form, e=True, ap=[(self._rs_ofOpt, "left", self._rs_centerLine, 50)]) 405 | cmds.formLayout(self._rs_form, e=True, ac=[(self._rs_ofText, "right", 2, self._rs_ofOpt)]) 406 | cmds.formLayout( 407 | self._rs_form, 408 | e=True, 409 | ac=[(self._rs_ofOpt, "top", 6, self._rs_fncOpt), (self._rs_ofText, "top", 8, self._rs_fncOpt)], 410 | ) 411 | # renderer 412 | cmds.formLayout(self._rs_form, e=True, ap=[(self._rs_rOpt, "left", self._rs_centerLine, 50)]) 413 | cmds.formLayout(self._rs_form, e=True, ac=[(self._rs_rText, "right", 2, self._rs_rOpt)]) 414 | cmds.formLayout( 415 | self._rs_form, 416 | e=True, 417 | ac=[(self._rs_rOpt, "top", 6, self._rs_ofOpt), (self._rs_rText, "top", 8, self._rs_ofOpt)], 418 | ) 419 | # project text 420 | cmds.formLayout(self._rs_form, e=True, ap=[(self._rs_pdText, "left", 12, 0)]) 421 | cmds.formLayout(self._rs_form, e=True, ac=[(self._rs_pdText, "bottom", 2, self._rs_pdField)]) 422 | # project directory field 423 | cmds.formLayout( 424 | self._rs_form, 425 | e=True, 426 | ap=[(self._rs_pdField, "left", 4, 0)], 427 | ac=[(self._rs_pdField, "right", 2, self._rs_pdBtn)], 428 | ) 429 | cmds.formLayout(self._rs_form, e=True, af=[(self._rs_pdBtn, "right", 6)]) 430 | cmds.formLayout( 431 | self._rs_form, 432 | e=True, 433 | ac=[ 434 | (self._rs_pdField, "bottom", 3, self._rs_rdText), 435 | (self._rs_pdBtn, "bottom", 3, self._rs_rdText), 436 | ], 437 | ) 438 | # render directory text 439 | cmds.formLayout(self._rs_form, e=True, ap=[(self._rs_rdText, "left", 12, 0)]) 440 | cmds.formLayout(self._rs_form, e=True, ac=[(self._rs_rdText, "bottom", 2, self._rs_rdField)]) 441 | # render directory field 442 | cmds.formLayout( 443 | self._rs_form, 444 | e=True, 445 | ap=[(self._rs_rdField, "left", 4, 0)], 446 | ac=[(self._rs_rdField, "right", 2, self._rs_rdBtn)], 447 | ) 448 | cmds.formLayout(self._rs_form, e=True, af=[(self._rs_rdBtn, "right", 6)]) 449 | cmds.formLayout( 450 | self._rs_form, 451 | e=True, 452 | ap=[(self._rs_rdField, "bottom", 4, 100), (self._rs_rdBtn, "bottom", 4, 100)], 453 | ) 454 | 455 | cmds.setParent(self._mainForm) 456 | 457 | # batch file settings frame/form 458 | if cmds.frameLayout( 459 | self._bfs_frame, l="Batch File Settings", bs="etchedOut", li=10, height=self._frameHeights 460 | ): 461 | if cmds.formLayout(self._bfs_form, nd=100): 462 | cmds.text(self._bfs_nameText, l="Naming Convention") 463 | cmds.text(self._bfs_prefixText, l="Prefix") 464 | cmds.textField(self._bfs_prefixField, cc=self.bfs_namingConventionUpdate) 465 | cmds.checkBox(self._bfs_sceneCheck, l="Scene Name", v=True, cc=self.bfs_namingConventionUpdate) 466 | cmds.checkBox(self._bfs_rangeCheck, l="Frame Range", v=True, cc=self.bfs_namingConventionUpdate) 467 | cmds.checkBox(self._bfs_numberedCheck, l="Numbered", v=False, cc=self.bfs_namingConventionUpdate) 468 | cmds.text(self._bfs_previewText, l="preview: prefix_sceneFile_1-100_[1].bat", al="center", en=False) 469 | cmds.separator(self._bfs_sep1, st="in") 470 | cmds.text(self._bfs_divText, l="Divide frame range into segments:") 471 | cmds.intField(self._bfs_divField, min=1, max=10000, v=1, cc=self.bfs_divFieldChange) 472 | cmds.text(self._bfs_divText2, l="Ex, 1-100 with 2 segments: 1-50, 51-100", al="center", en=False) 473 | cmds.separator(self._bfs_sep2, st="in") 474 | cmds.text(self._bfs_saveText, l="Save Location (existing .bat files will be overwritten)") 475 | cmds.textField(self._bfs_saveField, cc=self.bfs_saveFieldChange) 476 | if cmds.popupMenu(mm=True): 477 | cmds.menuItem(l="Add to favorites (coming soon)", en=False) 478 | cmds.menuItem(l="Manage save location favorites..", en=False) 479 | cmds.menuItem(d=True) 480 | cmds.menuItem(l="Open Folder", c=self.bfs_saveLocationOpen) 481 | cmds.button(self._bfs_saveBtn, l="browse...", c=self.bfs_saveBrowse) 482 | 483 | # naming text 484 | cmds.formLayout( 485 | self._bfs_form, 486 | e=True, 487 | ap=[(self._bfs_nameText, "left", 8, 0), (self._bfs_nameText, "top", 8, 0)], 488 | ) 489 | # prefix 490 | cmds.formLayout(self._bfs_form, e=True, ap=[(self._bfs_prefixText, "left", 12, 0)]) 491 | cmds.formLayout( 492 | self._bfs_form, 493 | e=True, 494 | ac=[(self._bfs_prefixField, "left", 6, self._bfs_prefixText)], 495 | ap=[(self._bfs_prefixField, "right", 12, 100)], 496 | ) 497 | cmds.formLayout( 498 | self._bfs_form, 499 | e=True, 500 | ac=[ 501 | (self._bfs_prefixText, "top", 8, self._bfs_nameText), 502 | (self._bfs_prefixField, "top", 6, self._bfs_nameText), 503 | ], 504 | ) 505 | # scene 506 | cmds.formLayout(self._bfs_form, e=True, ap=[(self._bfs_sceneCheck, "left", -130, 50)]) 507 | cmds.formLayout( 508 | self._bfs_form, 509 | e=True, 510 | ac=[ 511 | (self._bfs_rangeCheck, "left", 3, self._bfs_sceneCheck), 512 | (self._bfs_numberedCheck, "left", 3, self._bfs_rangeCheck), 513 | ], 514 | ) 515 | cmds.formLayout( 516 | self._bfs_form, 517 | e=True, 518 | ac=[ 519 | (self._bfs_sceneCheck, "top", 4, self._bfs_prefixField), 520 | (self._bfs_rangeCheck, "top", 4, self._bfs_prefixField), 521 | (self._bfs_numberedCheck, "top", 4, self._bfs_prefixField), 522 | ], 523 | ) 524 | # preview 525 | cmds.formLayout( 526 | self._bfs_form, 527 | e=True, 528 | ap=[(self._bfs_previewText, "left", 12, 0), (self._bfs_previewText, "right", 12, 100)], 529 | ac=[(self._bfs_previewText, "top", 6, self._bfs_numberedCheck)], 530 | ) 531 | # sep1 532 | cmds.formLayout( 533 | self._bfs_form, 534 | e=True, 535 | ap=[(self._bfs_sep1, "left", 12, 0), (self._bfs_sep1, "right", 12, 100)], 536 | ac=[(self._bfs_sep1, "top", 8, self._bfs_previewText)], 537 | ) 538 | # divisions 539 | cmds.formLayout(self._bfs_form, e=True, ap=[(self._bfs_divText, "left", -115, 50)]) 540 | cmds.formLayout(self._bfs_form, e=True, ac=[(self._bfs_divField, "left", 3, self._bfs_divText)]) 541 | cmds.formLayout( 542 | self._bfs_form, 543 | e=True, 544 | ac=[ 545 | (self._bfs_divText, "top", 8, self._bfs_sep1), 546 | (self._bfs_divField, "top", 6, self._bfs_sep1), 547 | ], 548 | ) 549 | # divisions help 550 | cmds.formLayout( 551 | self._bfs_form, 552 | e=True, 553 | ap=[(self._bfs_divText2, "left", -105, 50)], 554 | ac=[(self._bfs_divText2, "top", 3, self._bfs_divField)], 555 | ) 556 | # sep2 557 | cmds.formLayout( 558 | self._bfs_form, 559 | e=True, 560 | ap=[(self._bfs_sep2, "left", 12, 0), (self._bfs_sep2, "right", 12, 100)], 561 | ac=[(self._bfs_sep2, "top", 8, self._bfs_previewText)], 562 | ) 563 | # save location text 564 | cmds.formLayout( 565 | self._bfs_form, 566 | e=True, 567 | ap=[(self._bfs_saveText, "left", 8, 0)], 568 | ac=[(self._bfs_saveText, "bottom", 3, self._bfs_saveField)], 569 | ) 570 | # save location field 571 | cmds.formLayout( 572 | self._bfs_form, 573 | e=True, 574 | ap=[(self._bfs_saveField, "left", 4, 0)], 575 | ac=[(self._bfs_saveField, "right", 2, self._bfs_saveBtn)], 576 | ) 577 | cmds.formLayout(self._bfs_form, e=True, af=[(self._bfs_saveBtn, "right", 6)]) 578 | cmds.formLayout( 579 | self._bfs_form, 580 | e=True, 581 | ap=[(self._bfs_saveField, "bottom", 4, 100), (self._bfs_saveBtn, "bottom", 4, 100)], 582 | ) 583 | 584 | cmds.setParent(self._mainForm) 585 | 586 | cmds.button(self._makeBtn, l="Make Batch File (no files selected)", en=False, h=25, c=self.makeButtonCommand) 587 | 588 | cmds.formLayout( 589 | self._mainForm, 590 | e=True, 591 | af=[(self._fl_form, "left", 4), (self._fl_form, "right", 4), (self._fl_form, "top", 4)], 592 | ac=[(self._fl_form, "bottom", 6, self._bfs_frame)], 593 | ) 594 | cmds.formLayout( 595 | self._mainForm, 596 | e=True, 597 | af=[(self._rs_frame, "left", 4)], 598 | ap=[(self._rs_frame, "right", 2, 50)], 599 | ac=[(self._rs_frame, "bottom", 4, self._makeBtn)], 600 | ) 601 | cmds.formLayout( 602 | self._mainForm, 603 | e=True, 604 | af=[(self._bfs_frame, "right", 4)], 605 | ap=[(self._bfs_frame, "left", 2, 50)], 606 | ac=[(self._bfs_frame, "bottom", 4, self._makeBtn)], 607 | ) 608 | cmds.formLayout( 609 | self._mainForm, 610 | e=True, 611 | af=[(self._makeBtn, "left", 4), (self._makeBtn, "right", 4), (self._makeBtn, "bottom", 4)], 612 | ) 613 | 614 | self.rs_updateRenderSettingsDisplay() 615 | cmds.showWindow(self._name) 616 | 617 | def resetSettings(self, *args): 618 | cmds.window(self._name, e=True, width=self._winWidth, height=self._winHeight) 619 | 620 | def fl_addFiles(self, *args): 621 | cmds.fileBrowserDialog(m=0, fc=self.fl_addFilesHandler, an="Choose...", om="Import") 622 | 623 | def fl_addFilesHandler(self, fileName, fileType): 624 | self.fl_addFileToList(fileName) 625 | 626 | def fl_addFolder(self, *args): 627 | cmds.fileBrowserDialog(m=4, fc=self.fl_addFolderHandler, an="Select a folder...", om="Import") 628 | 629 | def fl_addFolderHandler(self, folderName, fileType): 630 | # get all the ma/mb files from the folder and add them 631 | if os.path.exists(folderName) and os.path.isdir(folderName): 632 | fileList = glob.glob("%s/*.m[a|b]" % folderName) 633 | fileList.sort() 634 | for f in fileList: 635 | self.fl_addFileToList(f) 636 | 637 | def fl_addFileToList(self, fileName): 638 | root, ext = os.path.splitext(fileName) 639 | if ext == ".ma" or ext == ".mb": 640 | curList = cmds.textScrollList(self._fl_list, q=True, ai=True) 641 | if curList: 642 | if fileName in curList: 643 | return 644 | cmds.textScrollList(self._fl_list, e=True, append=fileName) 645 | 646 | self.fl_updateGlobalVar() 647 | 648 | def fl_updateGlobalVar(self): 649 | # update global var 650 | curList = cmds.textScrollList(self._fl_list, q=True, ai=True) 651 | if curList == None: 652 | value = "{}" 653 | else: 654 | value = '{"%s"}' % '", "'.join(curList) 655 | self.sendToMel(var="bbfmWin_fileList", value=value) 656 | 657 | def fl_remSelFiles(self, *args): 658 | selFiles = cmds.textScrollList(self._fl_list, q=True, si=True) 659 | if selFiles: 660 | for f in selFiles: 661 | cmds.textScrollList(self._fl_list, e=True, ri=f) 662 | 663 | self.fl_updateGlobalVar() 664 | 665 | def fl_clearFiles(self, *args): 666 | cmds.textScrollList(self._fl_list, e=True, ra=True) 667 | self.fl_updateGlobalVar() 668 | 669 | def fl_listSelectCommand(self, *args): 670 | self.updateMakeButton() 671 | 672 | def rs_addRenderSettingsAll(self, *args): 673 | self.rs_setRenderSettingsDisplay([1, 1, 1, 1, 1, 1, 1, 1]) 674 | 675 | def rs_removeRenderSettingsAll(self, *args): 676 | self.rs_setRenderSettingsDisplay([0, 0, 0, 0, 0, 0, 0, 0]) 677 | 678 | def rs_setRenderSettingsDisplay(self, settings): 679 | cmds.menuItem(self._rs_mm_range, e=True, cb=settings[0]) 680 | cmds.menuItem(self._rs_mm_pad, e=True, cb=settings[1]) 681 | cmds.menuItem(self._rs_mm_res, e=True, cb=settings[2]) 682 | cmds.menuItem(self._rs_mm_fnc, e=True, cb=settings[3]) 683 | cmds.menuItem(self._rs_mm_of, e=True, cb=settings[4]) 684 | cmds.menuItem(self._rs_mm_r, e=True, cb=settings[5]) 685 | cmds.menuItem(self._rs_mm_pd, e=True, cb=settings[6]) 686 | cmds.menuItem(self._rs_mm_rd, e=True, cb=settings[7]) 687 | self.rs_updateRenderSettingsDisplay() 688 | 689 | def rs_updateRenderSettingsDisplay(self, *args): 690 | """Checks the render settings menu and sets control visibilities accordingly""" 691 | fr = cmds.menuItem(self._rs_mm_range, q=True, cb=True) 692 | pad = cmds.menuItem(self._rs_mm_pad, q=True, cb=True) 693 | res = cmds.menuItem(self._rs_mm_res, q=True, cb=True) 694 | fnc = cmds.menuItem(self._rs_mm_fnc, q=True, cb=True) 695 | of = cmds.menuItem(self._rs_mm_of, q=True, cb=True) 696 | r = cmds.menuItem(self._rs_mm_r, q=True, cb=True) 697 | pd = cmds.menuItem(self._rs_mm_pd, q=True, cb=True) 698 | rd = cmds.menuItem(self._rs_mm_rd, q=True, cb=True) 699 | # range 700 | cmds.text(self._rs_rangeText1, e=True, vis=fr) 701 | cmds.intField(self._rs_start, e=True, vis=fr) 702 | cmds.text(self._rs_rangeText2, e=True, vis=fr) 703 | cmds.intField(self._rs_end, e=True, vis=fr) 704 | cmds.button(self._rs_getRangeBtn, e=True, vis=fr) 705 | cmds.text(self._rs_getRangeText, e=True, vis=fr) 706 | # padding 707 | cmds.text(self._rs_padText, e=True, vis=pad) 708 | cmds.intField(self._rs_pad, e=True, vis=pad) 709 | # res 710 | cmds.text(self._rs_resText, e=True, vis=res) 711 | cmds.intField(self._rs_resW, e=True, vis=res) 712 | cmds.intField(self._rs_resH, e=True, vis=res) 713 | # fnc 714 | cmds.text(self._rs_fncText, e=True, vis=fnc) 715 | cmds.optionMenu(self._rs_fncOpt, e=True, vis=fnc) 716 | # of 717 | cmds.text(self._rs_ofText, e=True, vis=of) 718 | cmds.optionMenu(self._rs_ofOpt, e=True, vis=of) 719 | # renderer 720 | cmds.text(self._rs_rText, e=True, vis=r) 721 | cmds.optionMenu(self._rs_rOpt, e=True, vis=r) 722 | # pd 723 | cmds.text(self._rs_pdText, e=True, vis=pd) 724 | cmds.textField(self._rs_pdField, e=True, vis=pd) 725 | cmds.button(self._rs_pdBtn, e=True, vis=pd) 726 | # rd 727 | cmds.text(self._rs_rdText, e=True, vis=rd) 728 | cmds.textField(self._rs_rdField, e=True, vis=rd) 729 | cmds.button(self._rs_rdBtn, e=True, vis=rd) 730 | # no options text visibility 731 | if fr or pad or res or fnc or of or r or pd or rd: 732 | cmds.text(self._rs_noOptsText, e=True, vis=False) 733 | else: 734 | cmds.text(self._rs_noOptsText, e=True, vis=True) 735 | 736 | self.bfs_namingConventionUpdate() 737 | cmds.frameLayout(self._rs_frame, e=True, h=self._frameHeights) 738 | 739 | self.rs_updateGlobalVar([fr, pad, res, fnc, of, r, pd, rd]) 740 | 741 | def rs_updateGlobalVar(self, settings=None): 742 | # update global var 743 | for i in range(len(settings)): 744 | if settings[i] is False or settings[i] is True: 745 | settings[i] = int(settings[i]) 746 | if settings == None: 747 | value = "{}" 748 | else: 749 | value = "{%s}" % ", ".join([str(num) for num in settings]) 750 | self.sendToMel(var="bbfmWin_renderSettingsCheck", value=value) 751 | 752 | def rs_getRangeBtnCommand(self, *args): 753 | sel = cmds.textScrollList(self._fl_list, q=True, si=True)[-1] 754 | if sel: 755 | fr = getMAFrameRange(sel) 756 | if fr[0]: 757 | cmds.intField(self._rs_start, e=True, v=fr[0]) 758 | if fr[1]: 759 | cmds.intField(self._rs_end, e=True, v=fr[1]) 760 | 761 | def rs_setResPreset480(self, *args): 762 | self.rs_setResPreset([853, 480]) 763 | 764 | def rs_setResPreset720(self, *args): 765 | self.rs_setResPreset([1280, 720]) 766 | 767 | def rs_setResPreset1080(self, *args): 768 | self.rs_setResPreset([1920, 1080]) 769 | 770 | def rs_setResPreset(self, res): 771 | cmds.intField(self._rs_resW, e=True, v=res[0]) 772 | cmds.intField(self._rs_resH, e=True, v=res[1]) 773 | 774 | def rs_pdBrowse(self, *args): 775 | cmds.fileBrowserDialog(m=4, fc=self.rs_pdBrowseHandler, an="Select a folder...", om="Import") 776 | 777 | def rs_pdBrowseHandler(self, folderName, fileType): 778 | if os.path.exists(folderName) and os.path.isdir(folderName): 779 | cmds.textField(self._rs_pdField, e=True, tx=folderName) 780 | 781 | def rs_pdFieldChange(self, *args): 782 | val = cmds.textField(self._rs_pdField, q=True, tx=True) 783 | if val != "": 784 | val = os.path.abspath(val).replace("\\", "/") 785 | cmds.textField(self._rs_pdField, e=True, tx=val) 786 | 787 | def rs_rdBrowse(self, *args): 788 | cmds.fileBrowserDialog(m=4, fc=self.rs_rdBrowseHandler, an="Select a folder...", om="Import") 789 | 790 | def rs_rdBrowseHandler(self, folderName, fileType): 791 | if os.path.exists(folderName) and os.path.isdir(folderName): 792 | cmds.textField(self._rs_rdField, e=True, tx=folderName) 793 | 794 | def rs_rdFieldChange(self, *args): 795 | val = cmds.textField(self._rs_rdField, q=True, tx=True) 796 | if val != "": 797 | val = os.path.abspath(val).replace("\\", "/") 798 | cmds.textField(self._rs_rdField, e=True, tx=val) 799 | 800 | def bfs_namingConventionUpdate(self, *args): 801 | """Checks the check boxes and prefix and updates the preview text""" 802 | rs_fr = cmds.menuItem(self._rs_mm_range, q=True, cb=True) 803 | cmds.checkBox(self._bfs_rangeCheck, e=True, en=rs_fr) 804 | cmds.intField(self._bfs_divField, e=True, en=rs_fr) 805 | 806 | prefix = cmds.textField(self._bfs_prefixField, q=True, tx=True) 807 | scene = cmds.checkBox(self._bfs_sceneCheck, q=True, v=True) 808 | fr = cmds.checkBox(self._bfs_rangeCheck, q=True, v=True) 809 | num = cmds.checkBox(self._bfs_numberedCheck, q=True, v=True) 810 | 811 | prevElems = [] 812 | if prefix: 813 | prevElems.append(prefix) 814 | if scene: 815 | prevElems.append("myMayaFile") 816 | if fr and rs_fr: 817 | prevElems.append("1-100") 818 | if num: 819 | prevElems.append("[1]") 820 | prevStr = "_".join(prevElems) + ".bat" 821 | 822 | cmds.text(self._bfs_previewText, e=True, l=prevStr) 823 | 824 | def bfs_divFieldChange(self, *args): 825 | self.updateMakeButton() 826 | 827 | def bfs_saveBrowse(self, *args): 828 | cmds.fileBrowserDialog(m=4, fc=self.bfs_saveBrowseHandler, an="Select a folder...", om="Import") 829 | 830 | def bfs_saveBrowseHandler(self, folderName, fileType): 831 | if os.path.exists(folderName) and os.path.isdir(folderName): 832 | cmds.textField(self._bfs_saveField, e=True, tx=folderName) 833 | 834 | def bfs_saveFieldChange(self, *args): 835 | val = cmds.textField(self._bfs_saveField, q=True, tx=True) 836 | if val != "": 837 | val = os.path.abspath(val).replace("\\", "/") 838 | cmds.textField(self._bfs_saveField, e=True, tx=val) 839 | 840 | def bfs_saveLocationOpen(self, *args): 841 | path = os.path.abspath(cmds.textField(self._bfs_saveField, q=True, tx=True)).replace("\\", "/") 842 | cmd = r'system("load "+encodeString("%s")+"");' % path 843 | mel.eval(cmd) 844 | 845 | def updateMakeButton(self): 846 | selList = cmds.textScrollList(self._fl_list, q=True, si=True) 847 | if selList: 848 | count = len(selList) 849 | countPlural = count > 1 and "s" or "" 850 | cmds.button( 851 | self._makeBtn, 852 | e=True, 853 | l="Make Batch File%s (%d file%s selected)" % (countPlural, count, countPlural), 854 | en=True, 855 | ) 856 | else: 857 | cmds.button(self._makeBtn, e=True, l="Make Batch Files (no files selected)", en=False) 858 | 859 | def getRenderSettings(self): 860 | # get render settings 861 | frCheck = cmds.menuItem(self._rs_mm_range, q=True, cb=True) 862 | padCheck = cmds.menuItem(self._rs_mm_pad, q=True, cb=True) 863 | resCheck = cmds.menuItem(self._rs_mm_res, q=True, cb=True) 864 | fncCheck = cmds.menuItem(self._rs_mm_fnc, q=True, cb=True) 865 | ofCheck = cmds.menuItem(self._rs_mm_of, q=True, cb=True) 866 | rCheck = cmds.menuItem(self._rs_mm_r, q=True, cb=True) 867 | pdCheck = cmds.menuItem(self._rs_mm_pd, q=True, cb=True) 868 | rdCheck = cmds.menuItem(self._rs_mm_rd, q=True, cb=True) 869 | fr, pad, res, fnc, of, r, pd, rd = None, None, None, None, None, None, None, None 870 | renderers = ["default", "rman", "sw", "mr"] 871 | if frCheck: 872 | fr = [cmds.intField(self._rs_start, q=True, v=True), cmds.intField(self._rs_end, q=True, v=True)] 873 | if padCheck: 874 | pad = cmds.intField(self._rs_pad, q=True, v=True) 875 | if resCheck: 876 | res = [cmds.intField(self._rs_resW, q=True, v=True), cmds.intField(self._rs_resH, q=True, v=True)] 877 | if fncCheck: 878 | fnc = cmds.optionMenu(self._rs_fncOpt, q=True, v=True) 879 | if ofCheck: 880 | of = cmds.optionMenu(self._rs_ofOpt, q=True, v=True) 881 | if rCheck: 882 | r = renderers[cmds.optionMenu(self._rs_rOpt, q=True, sl=True)] 883 | if pdCheck: 884 | pd = cmds.textField(self._rs_pdField, q=True, tx=True) 885 | if rdCheck: 886 | rd = cmds.textField(self._rs_rdField, q=True, tx=True) 887 | 888 | return {"range": fr, "pad": pad, "res": res, "fnc": fnc, "of": of, "r": r, "pd": pd, "rd": rd} 889 | 890 | def getBatchFileSettings(self): 891 | # get batch file settings 892 | prefix = cmds.textField(self._bfs_prefixField, q=True, tx=True) 893 | sceneCheck = cmds.checkBox(self._bfs_sceneCheck, q=True, v=True) 894 | frCheck = cmds.checkBox(self._bfs_rangeCheck, q=True, v=True) 895 | numCheck = cmds.checkBox(self._bfs_numberedCheck, q=True, v=True) 896 | div = cmds.intField(self._bfs_divField, q=True, v=True) 897 | save = cmds.textField(self._bfs_saveField, q=True, tx=True) 898 | return { 899 | "prefix": prefix, 900 | "includeScene": sceneCheck, 901 | "includeRange": frCheck, 902 | "includeNum": numCheck, 903 | "div": div, 904 | "sd": save, 905 | } 906 | 907 | def makeButtonCommand(self, *args): 908 | """Gathers the necessary information, then creates and runs a BatchFileMaker object""" 909 | # get file list 910 | fileList = cmds.textScrollList(self._fl_list, q=True, si=True) 911 | rs = self.getRenderSettings() 912 | bfs = self.getBatchFileSettings() 913 | 914 | bfm = BatchFileMaker(fileList, rs, bfs) 915 | bfm.run() 916 | 917 | 918 | class BatchFileMaker(object): 919 | def __init__(self, fileList, rs, bfs): 920 | self.fileList = fileList 921 | self.rs = rs 922 | self.bfs = bfs 923 | self.rangeList = None 924 | self.flags = None 925 | self.batCmds = None 926 | 927 | def run(self): 928 | # check file list 929 | if not self.fileList: 930 | pyError("no files were specified") 931 | return 932 | # check paths 933 | self.checkPaths() 934 | # generate flags that are the same for every .bat 935 | self.buildStaticFlags() 936 | # get the divided frame ranges, if any 937 | self.buildRangeDivs() 938 | # build the bat commands, 1 per file per range 939 | self.buildBatCmds() 940 | # write the bats to files 941 | self.writeBatCmds() 942 | 943 | def checkPaths(self): 944 | """Checks/creates destination folders if necessary""" 945 | if self.bfs["sd"]: 946 | if not os.path.exists(self.bfs["sd"]): 947 | result = cmds.confirmDialog( 948 | t="Creating Directory...", 949 | m="The specified Save Location does not exist, create?\n%s" % self.bfs["sd"], 950 | b=["Yes", "No"], 951 | db="Ok", 952 | cb="No", 953 | ) 954 | if result == "Yes": 955 | os.makedirs(self.bfs["sd"]) 956 | print("save directory has been created: %s" % self.bfs["sd"]) 957 | else: 958 | result = cmds.confirmDialog( 959 | t="Save Location", 960 | ma="center", 961 | m="No save location was specified for the batch files.\nThey will be saved to the last working directory.\nDo you want to continue?", 962 | b=["Yes", "No"], 963 | db="Ok", 964 | cb="No", 965 | ) 966 | if result == "Yes": 967 | pyWarning( 968 | "no save location specified: batch files will be saved to the last working directory, check script editor for details" 969 | ) 970 | else: 971 | raise BatchFileMakerError("cancelled by request") 972 | 973 | if self.rs["pd"]: 974 | if not os.path.exists(self.rs["pd"]): 975 | result = cmds.confirmDialog( 976 | t="Creating Directory...", 977 | m="The specified Project Directory does not exist, create?\n%s" % self.rs["pd"], 978 | b=["Yes", "No"], 979 | db="Ok", 980 | cb="No", 981 | ) 982 | if result == "Yes": 983 | os.makedirs(self.rs["pd"]) 984 | print("project directory has been created: %s" % self.rs["pd"]) 985 | 986 | if self.rs["rd"]: 987 | if not os.path.exists(self.rs["rd"]): 988 | result = cmds.confirmDialog( 989 | t="Creating Directory...", 990 | m="The specified Render Directory does not exist, create?\n%s" % self.rs["rd"], 991 | b=["Yes", "No"], 992 | db="Ok", 993 | cb="No", 994 | ) 995 | if result == "Yes": 996 | os.makedirs(self.rs["rd"]) 997 | print("render directory has been created: %s" % self.rs["rd"]) 998 | 999 | def buildStaticFlags(self): 1000 | """Creates the flags that will be the same for every .bat""" 1001 | self.flags = [] 1002 | if self.rs["r"]: 1003 | self.flags.append("-r %s" % self.rs["r"]) 1004 | if self.rs["pad"]: 1005 | self.flags.append("-pad %d" % self.rs["pad"]) 1006 | if self.rs["res"]: 1007 | self.flags.append("-res %d %d" % (self.rs["res"][0], self.rs["res"][1])) 1008 | if self.rs["fnc"]: 1009 | self.flags.append("-fnc %s" % self.rs["fnc"]) 1010 | if self.rs["of"]: 1011 | self.flags.append("-of %s" % self.rs["of"]) 1012 | if self.rs["pd"]: 1013 | self.flags.append("-proj %s" % self.rs["pd"]) 1014 | if self.rs["rd"]: 1015 | self.flags.append("-rd %s" % self.rs["rd"]) 1016 | 1017 | def buildRangeDivs(self): 1018 | if self.rs["range"]: 1019 | if self.bfs["div"]: 1020 | fr = self.rs["range"] 1021 | div = self.bfs["div"] 1022 | rangeLen = fr[1] - fr[0] + 1 1023 | if div > rangeLen: 1024 | div = rangeLen 1025 | unit = rangeLen / div 1026 | ex = (rangeLen) - (div * unit) 1027 | unit -= 1 1028 | st = fr[0] 1029 | frList = [] 1030 | for i in range(0, div): 1031 | end = st + unit 1032 | if ex > 0: 1033 | end += 1 1034 | ex -= 1 1035 | frList.append([st, end]) 1036 | st = end + 1 1037 | self.rangeList = frList 1038 | 1039 | def buildBatCmds(self): 1040 | self.batCmds = {} 1041 | for f in self.fileList: 1042 | if self.rangeList: 1043 | i = 1 1044 | for r in self.rangeList: 1045 | curFlags = list(self.flags) 1046 | curFlags.append("-s %s" % r[0]) 1047 | curFlags.append("-e %s" % r[1]) 1048 | batCmd = "render^\n %s^\n %s\npause" % ("^\n ".join(curFlags), f) 1049 | batName = self.getBatName(f, r, i) 1050 | self.batCmds[batName] = batCmd 1051 | i += 1 1052 | else: 1053 | sep = len(self.flags) > 0 and "^\n " or "" 1054 | batCmd = "render^\n %s%s %s" % ("^\n ".join(self.flags), sep, f) 1055 | batName = self.getBatName(f, None, None) 1056 | self.batCmds[batName] = batCmd 1057 | 1058 | def getBatName(self, scene, fr, num): 1059 | elems = [] 1060 | if self.bfs["prefix"]: 1061 | elems.append(self.bfs["prefix"]) 1062 | if self.bfs["includeScene"]: 1063 | sceneRoot = os.path.basename(scene) 1064 | sceneRoot, ext = os.path.splitext(sceneRoot) 1065 | elems.append(sceneRoot) 1066 | if self.bfs["includeRange"] and fr: 1067 | rangeStr = "%d-%d" % (fr[0], fr[1]) 1068 | elems.append(rangeStr) 1069 | if self.bfs["includeNum"] and num: 1070 | numStr = "[%d]" % num 1071 | elems.append(numStr) 1072 | 1073 | returnStr = "_".join(elems) 1074 | return returnStr 1075 | 1076 | def writeBatCmds(self): 1077 | files = self.batCmds.keys() 1078 | for f in files: 1079 | filePath = os.path.abspath(os.path.join(self.bfs["sd"], "%s.bat" % f)) 1080 | self.writeFile(filePath, self.batCmds[f]) 1081 | 1082 | def writeFile(self, fileName, data): 1083 | try: 1084 | fsock = open(fileName, "w") 1085 | try: 1086 | fsock.write(data + "\n") 1087 | print("// wrote batch file successfully: %s" % fileName) 1088 | finally: 1089 | fsock.close() 1090 | except IOError: 1091 | pyWarning(r"// could not open file %s" % fileName) 1092 | -------------------------------------------------------------------------------- /src/boScripts/scripts/boBatchFileProcessor.mel: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bohdon/boScripts/49dc6cc2558608a6ff88f87039482f2ba4dbadee/src/boScripts/scripts/boBatchFileProcessor.mel -------------------------------------------------------------------------------- /src/boScripts/scripts/boBlendShapes.mel: -------------------------------------------------------------------------------- 1 | /* 2 | Blend Shapes 3 | 2.1 4 | 5 | Copyright (c) 2010 Bohdon Sayre 6 | All Rights Reserved. 7 | bo@bohdon.com 8 | 9 | unique prefix: bbs 10 | 11 | Description: 12 | This script contains the multi blend slider 13 | as well as a new inbetweener for blendshapes. 14 | 15 | Instructions: 16 | source boBlendShapes then run... 17 | bbsMultiBlendSlider; //opens the multi blend slider window 18 | bbsAddInbetween; //shows the inbetweener window 19 | bbsAddInbetweenAuto; //adds an inbetween automatically based on selection 20 | 21 | Version 2.1: 22 | > multi blend slider now handles mulitple blend shape bases being selected 23 | > multi blend slider is now a window, multiBlendHUDSlider has been removed 24 | > inbetweener window for auto or manual adding 25 | > multi blend tools include a slider and preset buttons 26 | 27 | Feel free to email me with any bugs, comments, or requests! 28 | */ 29 | 30 | //==================================================================================================== 31 | //MULTI BLEND SLIDER 32 | global proc bbsMultiBlendSlider() { 33 | //window name 34 | $win = "bbsMultiBlendSliderWin"; 35 | 36 | //check for pre-existing window 37 | if (`window -ex $win`) deleteUI -wnd $win; 38 | 39 | //create window 40 | window -w 100 -h 100 -rtf 1 -s 0 -tlb 1 -mb 1 -mxb 0 -t "Multi Blend Slider 2.1" -mnc ("window -e -t \"Multi Blend Slider 2.1\" "+$win+";") $win; 41 | 42 | //main layout 43 | formLayout -nd 100 bbsMultiBlendSliderForm; 44 | floatSliderGrp -field 1 -step .001 -minValue 0 -maxValue 1 -cw2 50 200 45 | -dc "bbsMultiBlendSlide(0)" 46 | -cc "bbsMultiBlendSlide(1)" 47 | bbsMultiBlendSliderSlider; 48 | $btn1 = `button -l "0" -al "center" -c "bbsMultiBlendSet(0, 1, 0)"`; 49 | $btn2 = `button -l ".333" -al "center" -c "bbsMultiBlendSet(.333333, 1, 0)"`; 50 | $btn3 = `button -l ".5" -al "center" -c "bbsMultiBlendSet(.5, 1, 0)"`; 51 | $btn4 = `button -l ".666" -al "center" -c "bbsMultiBlendSet(.666666, 1, 0)"`; 52 | $btn5 = `button -l "1" -al "center" -c "bbsMultiBlendSet(1, 1, 0)"`; 53 | 54 | formLayout -e 55 | -ap bbsMultiBlendSliderSlider "top" 1 0 56 | -ap bbsMultiBlendSliderSlider "left" 1 0 57 | -ap bbsMultiBlendSliderSlider "right" 1 100 58 | 59 | -ac $btn1 "top" 1 bbsMultiBlendSliderSlider -ap $btn1 "left" 1 0 -ap $btn1 "right" 1 20 60 | -ac $btn2 "top" 1 bbsMultiBlendSliderSlider -ap $btn2 "left" 1 20 -ap $btn2 "right" 1 40 61 | -ac $btn3 "top" 1 bbsMultiBlendSliderSlider -ap $btn3 "left" 1 40 -ap $btn3 "right" 1 60 62 | -ac $btn4 "top" 1 bbsMultiBlendSliderSlider -ap $btn4 "left" 1 60 -ap $btn4 "right" 1 80 63 | -ac $btn5 "top" 1 bbsMultiBlendSliderSlider -ap $btn5 "left" 1 80 -ap $btn5 "right" 1 100 64 | bbsMultiBlendSliderForm; 65 | 66 | window -e -w 215 -h 72 $win; 67 | showWindow $win; 68 | } 69 | global proc bbsMultiBlendSlide(int $undo) { 70 | //gets the value of the slider and uses bbsMultiBlendSet 71 | 72 | float $val = `floatSliderGrp -q -v bbsMultiBlendSliderSlider`; 73 | bbsMultiBlendSet($val, $undo, 1); 74 | } 75 | 76 | global proc bbsMultiBlendSet(float $val, int $undo, int $fromSlider) { 77 | 78 | if (!$fromSlider) { 79 | //if the value came from the slider, we don't want to do this 80 | floatSliderGrp -e -v $val bbsMultiBlendSliderSlider; 81 | } 82 | 83 | string $selList[] = `ls -sl`; 84 | if (!size($selList)) 85 | return; 86 | 87 | undoInfo -swf $undo; 88 | 89 | for ($obj in $selList) { 90 | 91 | //check if they're targets 92 | $objBS = `bbsGetTargetBlend $obj`; 93 | if (`objExists($objBS+"."+$obj)`) { 94 | if ($undo) { 95 | evalEcho("setAttr "+$objBS+"."+$obj+" "+$val); 96 | } else { 97 | setAttr ($objBS+"."+$obj) $val; 98 | } 99 | //found that it was a target, so go to the next loop 100 | continue; 101 | } 102 | 103 | //check if they're base heads 104 | string $blendShapes[] = `bbsGetBlendShapes $obj`; 105 | if (!size($blendShapes)) { 106 | if (`nodeType $obj` == "blendShape") { 107 | $blendShapes[0] = $obj; 108 | } 109 | } 110 | 111 | //one way or another, if a base or blendshape is selected, the list size will be > 0 112 | if (size($blendShapes)) { 113 | string $bs = $blendShapes[0]; 114 | string $blendAttrs[] = `bbsGetBlendAttrs $bs`; 115 | for ($attr in $blendAttrs) { 116 | if ($undo) { 117 | evalEcho("setAttr "+$bs+"."+$attr+" "+$val); 118 | } else { 119 | setAttr ($bs+"."+$attr) $val; 120 | } 121 | } 122 | } 123 | } 124 | 125 | undoInfo -swf $undo; 126 | } 127 | 128 | 129 | global proc bbsMultiBlendKey() { 130 | //keys the blendshape values of the selected objects 131 | 132 | //undo should only be enabled on release, otherwise the queue will be flooded 133 | string $selList[] = `ls -sl`; 134 | if (!size($selList)) return ; 135 | 136 | for ($obj in $selList) { 137 | $objBS = `bbsGetTargetBlend $obj`; 138 | 139 | if (!`objExists($objBS+"."+$obj)`) continue ; 140 | evalEcho("setKeyframe "+$objBS+"."+$obj); 141 | } 142 | } 143 | //==================================================================================================== 144 | 145 | 146 | 147 | 148 | //==================================================================================================== 149 | //ADD INBETWEEN WINDOW 150 | global proc bbsAddInbetween() { 151 | string $bbsAIWin = "bbsAIWin"; 152 | if (`window -exists $bbsAIWin`) deleteUI -wnd $bbsAIWin; 153 | 154 | //create window 155 | window -w 100 -h 100 -rtf 1 -mb 1 -mnc "window -e -t \"Add Blend Shape Inbetween Target\" bbsAIWin;" -t "Add Blend Shape Inbetween Target" bbsAIWin; 156 | 157 | menu -l "Refresh" bbsAIEditMenu; 158 | menuItem -l "All" -c "bbsAIGetBlends; bbsAIGetBlendTargets;" bbsAIRefreshItem; 159 | 160 | formLayout -nd 100 bbsAIFormMain; 161 | 162 | //main forms column 163 | columnLayout -adj 1 bbsAIColumnMain; 164 | columnLayout -w 500 -h 70 bbsAIColumnBlendShape; 165 | rowLayout -nc 2 -cw2 160 300 -cl2 "right" "left"; 166 | text -w 160 -l "BlendShape node: "; 167 | columnLayout ; 168 | checkBox -v 1 -l "Automatic" 169 | -cc ("if (!`checkBox -q -v bbsAIBlendShapeCheck`) {\ 170 | checkBox -e -en 1 bbsAITargetCheck;\ 171 | optionMenu -e -vis 1 bbsAIBlendShapeOptionMenu;\ 172 | } else {\ 173 | checkBox -e -en 0 -v 1 bbsAITargetCheck;\ 174 | optionMenu -e -vis 0 bbsAIBlendShapeOptionMenu;\ 175 | optionMenu -e -vis (`checkBox -q -v bbsAITargetCheck` ? 0 : 1) bbsAITargetOptionMenu;\ 176 | textField -e -vis (`checkBox -q -v bbsAITargetCheck` ? 0 : 1) bbsAITargetField;\ 177 | text -e -l \"Select inbetweens, then the target...\" bbsAITipText;\ 178 | } bbsAIGetBlends;") 179 | bbsAIBlendShapeCheck; 180 | optionMenu -vis 0 -cc "bbsAIGetBlendTargets" bbsAIBlendShapeOptionMenu; 181 | setParent bbsAIColumnMain; 182 | 183 | separator -h 8; 184 | columnLayout -w 500 -h 70 bbsAIColumnTarget; 185 | rowLayout -nc 3 -cw3 160 80 220 -cl3 "right" "left" "left"; 186 | text -w 160 -l "Target name: "; 187 | columnLayout ; 188 | checkBox -en 0 -v 1 -l "Automatic" 189 | -cc "optionMenu -e -vis (`checkBox -q -v bbsAITargetCheck` ? 0 : 1) bbsAITargetOptionMenu;\ 190 | textField -e -vis (`checkBox -q -v bbsAITargetCheck` ? 0 : 1) bbsAITargetField;\ 191 | bbsAIGetBlendTargets;\ 192 | if (`checkBox -q -v bbsAITargetCheck`) {\ 193 | text -e -l \"Select inbetweens, then the target...\" bbsAITipText;\ 194 | } else {\ 195 | text -e -l \"Select inbetweens only...\" bbsAITipText;\ 196 | }" 197 | bbsAITargetCheck; 198 | textField -vis 0 -w 280 bbsAITargetField; 199 | optionMenu -vis 0 -acc -cc "bbsAISetBlendTarget" bbsAITargetOptionMenu; 200 | setParent bbsAIColumnMain; 201 | 202 | separator -h 8; 203 | columnLayout -w 500 -h 70 bbsAIColumnWeights; 204 | rowLayout -nc 3 -cw3 160 80 220 -cl3 "right" "left" "left"; 205 | text -w 160 -l "Inbetween weights: "; 206 | columnLayout ; 207 | checkBox -v 1 -l "Automatic" -cc "floatSliderGrp -e -vis (`checkBox -q -v bbsAIInbetweenCheck` ? 0 : 1) bbsAIInbetweenSlider;" bbsAIInbetweenCheck; 208 | floatSliderGrp -vis 0 -field 1 -min 0 -max 1 -v .5 -step .01 -cw2 40 300 bbsAIInbetweenSlider; 209 | setParent -top; 210 | 211 | //status text 212 | text -w 500 -al "left" -fn "boldLabelFont" -l "Select inbetweens, then the target..." bbsAITipText; 213 | 214 | //buttons 215 | button -h 26 -l "Apply and Close" -c "bbsAIApply(0); deleteUI -wnd bbsAIWin" bbsAIApplyAndCloseBtn; 216 | button -h 26 -l "Apply" -c "bbsAIApply(0)" bbsAIApplyBtn; 217 | button -h 26 -l "Close" -c "deleteUI -wnd bbsAIWin" bbsAICloseBtn; 218 | 219 | formLayout -edit 220 | -af bbsAIColumnMain "top" 5 221 | -af bbsAIColumnMain "left" 5 222 | -af bbsAIColumnMain "right" 5 223 | 224 | -af bbsAIApplyAndCloseBtn "bottom" 5 225 | -ap bbsAIApplyAndCloseBtn "left" 5 0 226 | -ap bbsAIApplyAndCloseBtn "right" 2 33 227 | 228 | -af bbsAIApplyBtn "bottom" 5 229 | -ap bbsAIApplyBtn "left" 2 33 230 | -ap bbsAIApplyBtn "right" 2 66 231 | 232 | -af bbsAITipText "bottom" 36 233 | -af bbsAITipText "left" 5 234 | 235 | -af bbsAICloseBtn "bottom" 5 236 | -ap bbsAICloseBtn "left" 2 66 237 | -ap bbsAICloseBtn "right" 5 100 238 | bbsAIFormMain; 239 | 240 | 241 | window -e -w 548 -h 384 $bbsAIWin; 242 | showWindow $bbsAIWin; 243 | } 244 | global proc bbsAIGetBlends() { 245 | //get blend shapes 246 | string $curItems[] = `optionMenu -q -ill bbsAIBlendShapeOptionMenu`; 247 | for ($i = size($curItems)-1; $i >= 0; $i--) { 248 | deleteUI -mi $curItems[$i]; 249 | } 250 | 251 | $blends = `ls -type blendShape`; 252 | if (size($blends) > 0) { 253 | for ($bs in `ls -typ blendShape`) { 254 | menuItem -p bbsAIBlendShapeOptionMenu -l $bs; 255 | } 256 | } 257 | 258 | bbsAIGetBlendTargets; 259 | } 260 | global proc bbsAIGetBlendTargets() { 261 | //get blend shape targets 262 | string $curItems[] = `optionMenu -q -ill bbsAITargetOptionMenu`; 263 | for ($i = size($curItems)-1; $i >= 0; $i--) { 264 | deleteUI -mi $curItems[$i]; 265 | } 266 | 267 | if (`optionMenu -q -ni bbsAIBlendShapeOptionMenu` > 0) { 268 | string $blendShape = `optionMenu -q -v bbsAIBlendShapeOptionMenu`; 269 | $blendAttrs = `bbsGetBlendAttrs($blendShape)`; 270 | $blendAttrs = `sort $blendAttrs`; 271 | for ($attr in $blendAttrs) { 272 | menuItem -p bbsAITargetOptionMenu -l $attr; 273 | } 274 | } 275 | bbsAISetBlendTarget; 276 | } 277 | global proc bbsAISetBlendTarget() { 278 | textField -e -tx "" bbsAITargetField; 279 | 280 | if (!`optionMenu -q -ni bbsAITargetOptionMenu`) return ; 281 | string $name = `optionMenu -q -v bbsAITargetOptionMenu`; 282 | textField -e -tx $name bbsAITargetField; 283 | } 284 | 285 | 286 | 287 | //quick proc for all-auto (don't need window!) 288 | global proc bbsAddInbetweenAuto() { 289 | bbsAIApply(1); 290 | } 291 | global proc bbsAIApply(int $allAuto) { 292 | //get information 293 | int $blendAuto = 1; 294 | int $targetAuto = 1; 295 | int $weightsAuto = 1; 296 | 297 | if (!$allAuto && `window -ex bbsAIWin`) { 298 | $blendAuto = `checkBox -q -v bbsAIBlendShapeCheck`; 299 | $targetAuto = `checkBox -q -v bbsAITargetCheck`; 300 | $weightsAuto = `checkBox -q -v bbsAIInbetweenCheck`; 301 | } 302 | 303 | string $blendShape[], $blendInbs[], $blendBase, $blendTarget; 304 | int $index; 305 | float $weights; 306 | string $selList[] = `ls -sl`; 307 | if (!size($selList)) { 308 | error "nothing selected"; 309 | return; 310 | } 311 | 312 | if ($targetAuto) { 313 | $blendTarget = $selList[size($selList)-1]; 314 | $blendInbs = $selList; 315 | $blendInbs = stringArrayRemove ({$blendTarget}, $blendInbs); 316 | } else { 317 | $blendTarget = `textField -q -tx bbsAITargetField`; 318 | $blendInbs = $selList; 319 | } 320 | 321 | //blendshape 322 | if ($blendAuto) { 323 | string $objShape[] = `listRelatives -c -s $blendTarget`; 324 | $blendShape = `listConnections -t blendShape -s 0 $objShape[0]`; 325 | } else { 326 | if (`optionMenu -q -ni bbsAIBlendShapeOptionMenu` == 0) { 327 | error ("No blend shape specified"); 328 | return ; 329 | } 330 | $blendShape[0] = `optionMenu -q -v bbsAIBlendShapeOptionMenu`; 331 | } 332 | 333 | //do some error checking 334 | if ($blendShape[0] == "" && $blendAuto) { 335 | error ("target '"+$blendTarget+"' is not hooked up to a blendshape"); 336 | return ; 337 | } 338 | if ($blendTarget == "") { 339 | error ("No target specified"); 340 | return ; 341 | } 342 | if (!`objExists $blendTarget`) { 343 | error ("target '"+$blendTarget+"' does not exist"); 344 | return ; 345 | } 346 | 347 | //get base 348 | $connections = `blendShape -q -g $blendShape[0]`; 349 | $connections = `listRelatives -p -f $connections[0]`; 350 | $blendBase = $connections[0]; 351 | 352 | //get the target index 353 | $index = `bbsGetBlendTargetIndex $blendShape[0] $blendTarget`; 354 | if ($index == -1) { 355 | error ("target '"+$blendTarget+"' is not hooked up to '"+$blendShape[0]+"'"); 356 | return ; 357 | } 358 | 359 | //get weights 360 | if ($weightsAuto) { 361 | $weights = (float)1/(size($blendInbs)+1); 362 | } else { 363 | $weights = `floatSliderGrp -q -v bbsAIInbetweenSlider`; 364 | } 365 | 366 | string $command = "blendShape -e -ib "; 367 | for ($i = 0; $i < size($blendInbs); $i++) { 368 | float $thisWeight = floor(($weights * ($i+1))*1000)/(float)1000; 369 | $command += ("-t "+$blendBase+" "+$index+" "+$blendInbs[$i]+" "+$thisWeight+" "); 370 | } 371 | $command += (""+$blendShape[0]); 372 | 373 | evalEcho ($command); 374 | } 375 | //==================================================================================================== 376 | 377 | 378 | 379 | 380 | //==================================================================================================== 381 | //HELPER PROCEDURES FOR ALL BLENDSHAPE STUFF 382 | 383 | 384 | global proc bbsRec_buildShape(string $base, float $pointArray[], string $compArray[]) { 385 | //rebuilds a shape off of an original shape and a pointArray-compArray combination 386 | 387 | if (!`objExists $base`) 388 | error "bbsRec_buildShape: no base shape was passed. cannot recreate blend shape"; 389 | if (!size($pointArray)) 390 | error "bbsRec_buildShape: no point array was passed. cannot recreate blend shape"; 391 | if (!size($compArray)) 392 | error "bbsRec_buildShape: no component array was passed. cannot recreate blend shape"; 393 | 394 | //get the base shape 395 | string $baseShape; 396 | if (1) { 397 | string $buffer[] = `listConnections -c -s $base`; 398 | if (!size($buffer)) 399 | return; 400 | $baseShape = $buffer[0]; 401 | } 402 | 403 | //evaluate if the base shape is mesh 404 | if (`nodeType $baseShape` != "mesh") 405 | error "bbsRec_buildShape: the base shape was not of type mesh"; 406 | 407 | //get the mel command by using python to evaluate each vertices movement 408 | python("import boBlendShapes"); 409 | python("reload(boBlendShapes)"); 410 | 411 | } 412 | 413 | global proc string[] bbsGetBlendShapes( string $base) { 414 | //get all blendshape nodes attached to a base (transform) 415 | 416 | if (!`objExists $base`) return {}; 417 | string $baseShape[] = `listRelatives -s -c $base`; 418 | if (!size($baseShape)) return {}; 419 | 420 | string $blendShapes[] = `listConnections -d 0 ($baseShape[0]+".inMesh")`; 421 | if (!size($blendShapes)) return {}; 422 | $blendShapes = {$blendShapes[0]}; 423 | 424 | $hasConnect = 1; 425 | while($hasConnect) { 426 | string $tempCon[] = `listConnections -d 0 $blendShapes[size($blendShapes)-1]`; 427 | if (!size($tempCon)) { 428 | $hasConnect = 0; 429 | } else { 430 | $blendShapes[size($blendShapes)] = $tempCon[0]; 431 | } 432 | } 433 | for ($i = size($blendShapes)-1; $i >=0; $i--) { 434 | string $type[] = `ls -st $blendShapes[$i]`; 435 | if ($type[1] != "blendShape") { 436 | $blendShapes = stringArrayRemove({$blendShapes[$i]}, $blendShapes); 437 | } 438 | } 439 | 440 | return $blendShapes; 441 | } 442 | 443 | global proc string[] bbsGetBlendAttrs(string $blendShape) { 444 | //get all blendshape attributes of a certain blendshape node 445 | 446 | if (!`objExists $blendShape`) return {}; 447 | string $weights[] = `listAttr -m ($blendShape+".w")`; 448 | return $weights; 449 | } 450 | 451 | global proc float[] bbsGetBlendValues(string $blendShape, int $index) { 452 | //get all blendshape values of a blendshape attribute 453 | 454 | if (!`objExists $blendShape`) return {}; 455 | string $valuesStr[] = `listAttr -m ($blendShape+".inputTarget[0].inputTargetGroup["+$index+"]")`; 456 | stringArrayRemoveAtIndex(0, $valuesStr); 457 | int $valueLen = size($valuesStr); 458 | float $values[] = {}; 459 | //remove and isolate number 460 | for($i = ($valueLen-1); $i >= 0; $i--) { 461 | if (($i%4) != 0) { 462 | stringArrayRemoveAtIndex($i, $valuesStr); 463 | } else { 464 | $valuesStr[$i] = `substring $valuesStr[$i] (size($valuesStr[$i])-4) (size($valuesStr[$i])-1)`; 465 | $valuesStr[$i] = (float($valuesStr[$i])-5000)/1000; 466 | } 467 | } 468 | for ($i = 0; $i < size($valuesStr); $i++) { 469 | $values[$i] = float($valuesStr[$i]); 470 | } 471 | return $values; 472 | } 473 | 474 | global proc string bbsGetBlendTarget(string $blendShape, int $index, float $weight) { 475 | //get the object in the scene that corresponds to a blendshape attribute at a certain weight 476 | 477 | if (!`objExists $blendShape`) return ""; 478 | string $inAttr = ($blendShape+".inputTarget[0].inputTargetGroup["+$index+"].inputTargetItem["+($weight*1000+5000)+"].inputGeomTarget"); 479 | string $blendTargets[] = `listConnections -t shape -d 0 $inAttr`; 480 | 481 | return $blendTargets[0]; 482 | } 483 | 484 | global proc int bbsGetBlendTargetIndex(string $blendShape, string $target) { 485 | //get the targets index 486 | 487 | if (!`objExists $blendShape`) return -1; 488 | string $weights[] = `listAttr -m ($blendShape+".w")`; 489 | for ($i = 0; $i < size($weights); $i++) { 490 | if ($target == `bbsGetBlendTarget $blendShape $i 1`) { 491 | return $i; 492 | } 493 | } 494 | return -1; 495 | } 496 | 497 | 498 | global proc string bbsGetTargetBlend(string $target) { 499 | //get the blendshape that corresponds to a target shape 500 | 501 | string $targetShape[] = `listRelatives -c -s $target`; 502 | if (!size($targetShape)) return "" ; 503 | string $targetBS[] = `listConnections -t blendShape -s 0 $targetShape[0]`; 504 | //$targetBS[0] is the blendshape node 505 | if (!size($targetBS)) return "" ; 506 | 507 | return $targetBS[0]; 508 | } 509 | //==================================================================================================== 510 | -------------------------------------------------------------------------------- /src/boScripts/scripts/boCurveSlider.py: -------------------------------------------------------------------------------- 1 | import pymel.core as pm 2 | 3 | 4 | def doIt(): 5 | CurveSlider() 6 | 7 | 8 | class CurveSlider(object): 9 | def __init__(self): 10 | self.create() 11 | 12 | def create(self): 13 | if pm.window("slideWin", q=True, ex=True): 14 | pm.deleteUI("slideWin") 15 | with pm.window("slideWin", tlb=True, mxb=False, t="Slide Curves"): 16 | with pm.formLayout(nd=100) as form: 17 | self.slider = pm.intSliderGrp(field=True, v=1, min=1, max=20) 18 | btn1 = pm.button(l="<", c=pm.Callback(self.slideCurvesGUI, 1)) 19 | btn2 = pm.button(l=">", c=pm.Callback(self.slideCurvesGUI, -1)) 20 | pm.formLayout( 21 | form, 22 | e=True, 23 | af=[(btn1, "left", 2), (btn2, "right", 2), (self.slider, "left", 2), (self.slider, "right", 2)], 24 | ap=[(btn1, "right", 1, 50), (btn2, "left", 1, 50)], 25 | ac=[(self.slider, "top", 2, btn1)], 26 | ) 27 | 28 | def slideCurvesGUI(self, d=1): 29 | self.slideCurves(pm.intSliderGrp(self.slider, q=True, v=True) * d) 30 | 31 | def slideCurves(self, d=1): 32 | selList = pm.ls(sl=True) 33 | for obj in selList: 34 | nodes = pm.keyframe(obj, query=True, name=True) 35 | for node in nodes: 36 | keyTimes = pm.keyframe(node, q=True, tc=True) 37 | # query values at delta 38 | newValues = [] 39 | for time in keyTimes: 40 | newValues.append(pm.keyframe(node, t=int(time + d), q=True, ev=True)) 41 | # assign new values 42 | for i in range(0, len(keyTimes)): 43 | pm.keyframe(node, e=True, t=int(keyTimes[i]), vc=newValues[i][0]) 44 | -------------------------------------------------------------------------------- /src/boScripts/scripts/boRandomizer.mel: -------------------------------------------------------------------------------- 1 | /* 2 | Randomizer 3 | 1.1 4 | 5 | Copyright (c) 2010 Bohdon Sayre 6 | All Rights Reserved. 7 | bo@bohdon.com 8 | 9 | unique prefix: brnd 10 | 11 | Description: 12 | Provides a GUI for efficiently randomizing objects, 13 | components, or attributes with several options 14 | 15 | Instructions: 16 | boRandomizer; 17 | 18 | Version 1.1: 19 | > Channel randomizer now grabs attributes from main object, shape, history, and and outputs 20 | > Channel Randomization via channelBox selection 21 | > Echoing transformation commands to the script editor is optional 22 | > Custom seeding for repeated randomizations 23 | > Round values option 24 | > Absolute or Relative transformations 25 | > Translate and Rotate Space options including Object, World, Local, and Gimbal 26 | > Axis isolation and uniform scaling options 27 | > Object and Component randomization through "move" "rotate" and "scale" commands 28 | 29 | 30 | Feel free to email me with any bugs, comments, or requests! 31 | */ 32 | 33 | global proc boRandomizer() { 34 | //window name 35 | $win = "brndWin"; 36 | 37 | //check for pre-existing window 38 | if (`window -ex $win`) deleteUI -wnd $win; 39 | 40 | //create window 41 | window -rtf 1 -mb 1 -mxb 0 -t "Bo Randomizer 1.1" -mnc ("window -e -t \"Bo Randomizer 1.1\" "+$win+";") $win; 42 | 43 | //menu bar 44 | menu -l "Options" brndWin_Menu; 45 | menuItem -l "Echo Commands" -cb 0 brndWin_Menu_Echo; 46 | menuItem -d 1; 47 | menuItem -l "Reset All Settings" -c "boRandomizer"; 48 | 49 | //main layout 50 | columnLayout -adj 1 -rs 4; 51 | //Object frame layout 52 | frameLayout -l "Object / Component" -li 4 -bs "etchedOut" -mw 4 -mh 4; 53 | formLayout -nd 100 brndObjForm; 54 | floatField -pre 3 -v -1.0 brndWin_ObjTransMinFloat; 55 | floatField -pre 3 -v 1.0 brndWin_ObjTransMaxFloat; 56 | intField -vis 0 -v 2 brndWin_ObjTransSpaceInt; 57 | button -l "Translate" 58 | -c "brndObjRandomize 1 0 0;" 59 | brndWin_ObjTransBtn; 60 | 61 | floatField -pre 1 -v -180.0 brndWin_ObjRotMinFloat; 62 | floatField -pre 1 -v 180.0 brndWin_ObjRotMaxFloat; 63 | intField -vis 0 -v 2 brndWin_ObjRotSpaceInt; 64 | button -l "Rotate" 65 | -c "brndObjRandomize 0 1 0;" 66 | brndWin_ObjRotBtn; 67 | 68 | floatField -pre 3 -v 0.5 brndWin_ObjScaleMinFloat; 69 | floatField -pre 3 -v 2.0 brndWin_ObjScaleMaxFloat; 70 | button -l "Scale" 71 | -c "brndObjRandomize 0 0 1;" 72 | brndWin_ObjScaleBtn; 73 | 74 | button -l "All" 75 | -c "brndObjRandomize 1 1 1;" 76 | brndWin_ObjAllBtn; 77 | 78 | checkBox -l "Sync multiple objects" brndWin_ObjSyncObjsCheck; 79 | setParent..; 80 | 81 | formLayout -e 82 | -ap brndWin_ObjTransMinFloat "top" 0 0 83 | -ap brndWin_ObjTransMinFloat "left" 2 0 84 | -ap brndWin_ObjTransMinFloat "right" 2 25 85 | -ap brndWin_ObjTransMaxFloat "top" 0 0 86 | -ap brndWin_ObjTransMaxFloat "left" 2 25 87 | -ap brndWin_ObjTransMaxFloat "right" 2 50 88 | -ap brndWin_ObjTransBtn "top" 0 0 89 | -ap brndWin_ObjTransBtn "left" 2 50 90 | -ap brndWin_ObjTransBtn "right" 2 75 91 | -aoc brndWin_ObjTransBtn "bottom" 0 brndWin_ObjTransMinFloat 92 | 93 | 94 | -ac brndWin_ObjRotMinFloat "top" 2 brndWin_ObjTransMinFloat 95 | -ap brndWin_ObjRotMinFloat "left" 2 0 96 | -ap brndWin_ObjRotMinFloat "right" 2 25 97 | -ac brndWin_ObjRotMaxFloat "top" 2 brndWin_ObjTransMinFloat 98 | -ap brndWin_ObjRotMaxFloat "left" 2 25 99 | -ap brndWin_ObjRotMaxFloat "right" 2 50 100 | -ac brndWin_ObjRotBtn "top" 2 brndWin_ObjTransMinFloat 101 | -ap brndWin_ObjRotBtn "left" 2 50 102 | -ap brndWin_ObjRotBtn "right" 2 75 103 | -aoc brndWin_ObjRotBtn "bottom" 0 brndWin_ObjRotMinFloat 104 | 105 | 106 | -ac brndWin_ObjScaleMinFloat "top" 2 brndWin_ObjRotMinFloat 107 | -ap brndWin_ObjScaleMinFloat "left" 2 0 108 | -ap brndWin_ObjScaleMinFloat "right" 2 25 109 | -ac brndWin_ObjScaleMaxFloat "top" 2 brndWin_ObjRotMinFloat 110 | -ap brndWin_ObjScaleMaxFloat "left" 2 25 111 | -ap brndWin_ObjScaleMaxFloat "right" 2 50 112 | -ac brndWin_ObjScaleBtn "top" 2 brndWin_ObjRotMinFloat 113 | -ap brndWin_ObjScaleBtn "left" 2 50 114 | -ap brndWin_ObjScaleBtn "right" 2 75 115 | -aoc brndWin_ObjScaleBtn "bottom" 0 brndWin_ObjScaleMinFloat 116 | 117 | -ap brndWin_ObjAllBtn "top" 0 0 118 | -ap brndWin_ObjAllBtn "left" 2 75 119 | -ap brndWin_ObjAllBtn "right" 2 100 120 | -aoc brndWin_ObjAllBtn "bottom" 0 brndWin_ObjScaleMinFloat 121 | 122 | -ac brndWin_ObjSyncObjsCheck "top" 2 brndWin_ObjScaleMinFloat 123 | -ap brndWin_ObjSyncObjsCheck "left" 2 0 124 | 125 | brndObjForm; 126 | 127 | //marking menus 128 | popupMenu -mm 1 -b 3 -p brndWin_ObjTransBtn; 129 | menuItem -rp "S" -l "Relative" -cb 1 130 | -c "menuItem -e -cb 1 brndWin_ObjTransMM_Relative; menuItem -e -cb 0 brndWin_ObjTransMM_Absolute;" 131 | brndWin_ObjTransMM_Relative; 132 | menuItem -rp "N" -l "Absolute" -cb 0 133 | -c "menuItem -e -cb 0 brndWin_ObjTransMM_Relative; menuItem -e -cb 1 brndWin_ObjTransMM_Absolute;" 134 | brndWin_ObjTransMM_Absolute; 135 | menuItem -rp "NW" -l "Object" -cb 0 136 | -c "intField -e -v 1 brndWin_ObjTransSpaceInt; menuItem -e -cb 1 brndWin_ObjTransMM_Object; menuItem -e -cb 0 brndWin_ObjTransMM_World; menuItem -e -cb 0 brndWin_ObjTransMM_Local;" 137 | brndWin_ObjTransMM_Object; 138 | menuItem -rp "W" -l "World" -cb 1 139 | -c "intField -e -v 2 brndWin_ObjTransSpaceInt; menuItem -e -cb 0 brndWin_ObjTransMM_Object; menuItem -e -cb 1 brndWin_ObjTransMM_World; menuItem -e -cb 0 brndWin_ObjTransMM_Local;" 140 | brndWin_ObjTransMM_World; 141 | menuItem -rp "SW" -l "Local" -cb 0 142 | -c "intField -e -v 3 brndWin_ObjTransSpaceInt; menuItem -e -cb 0 brndWin_ObjTransMM_Object; menuItem -e -cb 0 brndWin_ObjTransMM_World; menuItem -e -cb 1 brndWin_ObjTransMM_Local;" 143 | brndWin_ObjTransMM_Local; 144 | menuItem -rp "NE" -l "X" -cb 1 brndWin_ObjTransMM_X; 145 | menuItem -rp "E" -l "Y" -cb 1 brndWin_ObjTransMM_Y; 146 | menuItem -rp "SE" -l "Z" -cb 1 brndWin_ObjTransMM_Z; 147 | menuItem -l "Round Values" -cb 0 brndWin_ObjTransMM_Round; 148 | popupMenu -mm 1 -b 3 -p brndWin_ObjRotBtn; 149 | menuItem -rp "S" -l "Relative" -cb 0 150 | -c "menuItem -e -cb 1 brndWin_ObjRotMM_Relative; menuItem -e -cb 0 brndWin_ObjRotMM_Absolute;" 151 | brndWin_ObjRotMM_Relative; 152 | menuItem -rp "N" -l "Absolute" -cb 1 153 | -c "menuItem -e -cb 0 brndWin_ObjRotMM_Relative; menuItem -e -cb 1 brndWin_ObjRotMM_Absolute;" 154 | brndWin_ObjRotMM_Absolute; 155 | menuItem -rp "NW" -l "Gimbal" -cb 0 156 | -c "intField -e -v 1 brndWin_ObjRotSpaceInt; menuItem -e -cb 1 brndWin_ObjRotMM_Gimbal; menuItem -e -cb 0 brndWin_ObjRotMM_World; menuItem -e -cb 0 brndWin_ObjRotMM_Local;" 157 | brndWin_ObjRotMM_Gimbal; 158 | menuItem -rp "W" -l "World" -cb 1 159 | -c "intField -e -v 2 brndWin_ObjRotSpaceInt; menuItem -e -cb 0 brndWin_ObjRotMM_Gimbal; menuItem -e -cb 1 brndWin_ObjRotMM_World; menuItem -e -cb 0 brndWin_ObjRotMM_Local;" 160 | brndWin_ObjRotMM_World; 161 | menuItem -rp "SW" -l "Local" -cb 0 162 | -c "intField -e -v 3 brndWin_ObjRotSpaceInt; menuItem -e -cb 0 brndWin_ObjRotMM_Gimbal; menuItem -e -cb 0 brndWin_ObjRotMM_World; menuItem -e -cb 1 brndWin_ObjRotMM_Local;" 163 | brndWin_ObjRotMM_Local; 164 | menuItem -rp "NE" -l "X" -cb 1 brndWin_ObjRotMM_X; 165 | menuItem -rp "E" -l "Y" -cb 1 brndWin_ObjRotMM_Y; 166 | menuItem -rp "SE" -l "Z" -cb 1 brndWin_ObjRotMM_Z; 167 | menuItem -l "Round Values" -cb 0 brndWin_ObjRotMM_Round; 168 | popupMenu -mm 1 -b 3 -p brndWin_ObjScaleBtn; 169 | menuItem -rp "S" -l "Relative" -cb 0 170 | -c "menuItem -e -cb 1 brndWin_ObjScaleMM_Relative; menuItem -e -cb 0 brndWin_ObjScaleMM_Absolute;" 171 | brndWin_ObjScaleMM_Relative; 172 | menuItem -rp "N" -l "Absolute" -cb 1 173 | -c "menuItem -e -cb 0 brndWin_ObjScaleMM_Relative; menuItem -e -cb 1 brndWin_ObjScaleMM_Absolute;" 174 | brndWin_ObjScaleMM_Absolute; 175 | menuItem -rp "NE" -l "X" -cb 1 brndWin_ObjScaleMM_X; 176 | menuItem -rp "E" -l "Y" -cb 1 brndWin_ObjScaleMM_Y; 177 | menuItem -rp "SE" -l "Z" -cb 1 brndWin_ObjScaleMM_Z; 178 | menuItem -l "Round Values" -cb 0 brndWin_ObjScaleMM_Round; 179 | menuItem -l "Uniform Scale" -cb 1 brndWin_ObjScaleMM_Uniform; 180 | 181 | setParent ..; 182 | 183 | //Channel frame layout 184 | frameLayout -l "Channel" -li 4 -bs "etchedOut" -mw 4 -mh 4; 185 | formLayout -nd 100 brndChanForm; 186 | floatField -pre 3 -v 0.0 brndWin_ChanMinFloat; 187 | floatField -pre 3 -v 1.0 brndWin_ChanMaxFloat; 188 | button -l "Randomize" 189 | -c "brndChan_Randomize" 190 | brndWin_ChanRandBtn; 191 | 192 | checkBox -l "Sync multiple objects" brndWin_ChanSyncObjsCheck; 193 | checkBox -l "Sync multiple channels" brndWin_ChanSyncChansCheck; 194 | 195 | setParent ..; 196 | 197 | formLayout -e 198 | -ap brndWin_ChanMinFloat "left" 2 0 199 | -ap brndWin_ChanMinFloat "right" 2 25 200 | -ap brndWin_ChanMaxFloat "left" 2 25 201 | -ap brndWin_ChanMaxFloat "right" 2 50 202 | -ap brndWin_ChanRandBtn "top" 0 0 203 | -ap brndWin_ChanRandBtn "left" 2 50 204 | -ap brndWin_ChanRandBtn "right" 2 100 205 | -aoc brndWin_ChanRandBtn "bottom" 0 brndWin_ChanMaxFloat 206 | 207 | -ac brndWin_ChanSyncObjsCheck "top" 6 brndWin_ChanMinFloat 208 | -ac brndWin_ChanSyncChansCheck "top" 2 brndWin_ChanSyncObjsCheck 209 | 210 | brndChanForm; 211 | 212 | //marking menus 213 | popupMenu -mm 1 -b 3 -p brndWin_ChanRandBtn; 214 | menuItem -rp "S" -l "Round Values" -cb 0 brndWin_ChanRandMM_Round; 215 | 216 | setParent ..; 217 | 218 | //Options frame layout 219 | frameLayout -l "Custom Seeding" -li 4 -bs "etchedOut" -mw 4 -mh 4; 220 | formLayout -nd 100 brndOptForm; 221 | checkBox -l "Use Custom Seed" brndWin_OptSeedCheck; 222 | intField -v 0 brndWin_OptSeedInt; 223 | button -l "random seed" -c ("intField -e -v ((int)rand(10000)) brndWin_OptSeedInt") brndWin_OptSeedRandBtn; 224 | 225 | setParent ..; 226 | 227 | formLayout -e 228 | -ap brndWin_OptSeedCheck "top" 0 0 229 | -ap brndWin_OptSeedCheck "left" 2 0 230 | -ac brndWin_OptSeedInt "top" 2 brndWin_OptSeedCheck 231 | -ap brndWin_OptSeedInt "left" 26 0 232 | -ac brndWin_OptSeedRandBtn "top" 2 brndWin_OptSeedCheck 233 | -ac brndWin_OptSeedRandBtn "left" 10 brndWin_OptSeedInt 234 | -aoc brndWin_OptSeedRandBtn "bottom" 0 brndWin_OptSeedInt 235 | 236 | brndOptForm; 237 | 238 | setParent ..; 239 | 240 | 241 | window -e -w 276 -h 325 $win; 242 | showWindow $win; 243 | 244 | }; 245 | //==================================================================================================== 246 | 247 | 248 | //==================================================================================================== 249 | global proc brndObjRandomize(int $trans, int $rot, int $scale) { 250 | //randomizes the selected objects/components in the specified transformational types 251 | 252 | //get the selection 253 | string $selList[] = `ls -r 1 -fl -sl`; 254 | if (!size($selList)) 255 | return; 256 | 257 | //create the important variables 258 | int $syncObjs, $useSeed, $round; 259 | float $customSeed, $tOpts[], $rOpts[], $sOpts[]; 260 | 261 | $syncObjs = `checkBox -q -v brndWin_ObjSyncObjsCheck`; 262 | $useSeed = `checkBox -q -v brndWin_OptSeedCheck`; 263 | $customSeed = `intField -q -v brndWin_OptSeedInt`; 264 | $echoCommand = `menuItem -q -cb brndWin_Menu_Echo`; 265 | 266 | //all transformations will be written to one final command string, and exectuted at once 267 | string $finalCmd = ""; 268 | string $flags[]; 269 | float $values[]; 270 | 271 | if ($useSeed) { 272 | seed($customSeed); 273 | } else { 274 | //millisecond based seeding 275 | int $time = (int)(`timerX` * 100); 276 | seed($time); 277 | } 278 | 279 | //get the options of menu items and checkboxes for any of the transform types 280 | if ($trans) { 281 | $tOpts = brndObj_GetOptions("Trans"); 282 | } 283 | if ($rot) { 284 | $rOpts = brndObj_GetOptions("Rot"); 285 | } 286 | if ($scale) { 287 | $sOpts = brndObj_GetOptions("Scale"); 288 | } 289 | //disable a transform type if none of the axes are checked 290 | if ($tOpts[2]!=1 && $tOpts[3]!=1 && $tOpts[4]!=1) 291 | $trans = 0; 292 | if ($rOpts[2]!=1 && $rOpts[3]!=1 && $rOpts[4]!=1) 293 | $rot = 0; 294 | if ($sOpts[2]!=1 && $sOpts[3]!=1 && $sOpts[4]!=1) 295 | $scale = 0; 296 | 297 | //cancel the whole thing if none of the types are now checked 298 | if ($trans!=1 && $rot!=1 && $scale!=1) { 299 | warning "none of the axes were checked for the selected transform types"; 300 | return; 301 | } 302 | 303 | //build the finalCmd 304 | if ($syncObjs) { 305 | //generate only 1 set of rand values (all objects will receive the same command) 306 | 307 | if ($trans) { 308 | $flags = `brndObj_BuildFlags "trans" $tOpts`; 309 | $values = `brndObj_BuildValues "trans" $tOpts`; 310 | $round = $tOpts[6]; 311 | $finalCmd += `brndObj_BuildCmd "move" $flags $values $round ""`; 312 | } 313 | if ($rot) { 314 | $flags = `brndObj_BuildFlags "rot" $rOpts`; 315 | $values = `brndObj_BuildValues "rot" $rOpts`; 316 | $round = $rOpts[6]; 317 | $finalCmd += `brndObj_BuildCmd "rotate" $flags $values $round ""`; 318 | } 319 | if ($scale) { 320 | $flags = `brndObj_BuildFlags "scale" $sOpts`; 321 | $values = `brndObj_BuildValues "scale" $sOpts`; 322 | $round = $sOpts[6]; 323 | $finalCmd += `brndObj_BuildCmd "scale" $flags $values $round ""`; 324 | } 325 | } else { 326 | //loop through each object and generate a set of commands 327 | 328 | for ($obj in $selList) { 329 | if ($trans) { 330 | $flags = `brndObj_BuildFlags "trans" $tOpts`; 331 | $values = `brndObj_BuildValues "trans" $tOpts`; 332 | $round = $tOpts[6]; 333 | $finalCmd += `brndObj_BuildCmd "move" $flags $values $round $obj`; 334 | } 335 | if ($rot) { 336 | $flags = `brndObj_BuildFlags "rot" $rOpts`; 337 | $values = `brndObj_BuildValues "rot" $rOpts`; 338 | $round = $rOpts[6]; 339 | $finalCmd += `brndObj_BuildCmd "rotate" $flags $values $round $obj`; 340 | } 341 | if ($scale) { 342 | $flags = `brndObj_BuildFlags "scale" $sOpts`; 343 | $values = `brndObj_BuildValues "scale" $sOpts`; 344 | $round = $sOpts[6]; 345 | $finalCmd += `brndObj_BuildCmd "scale" $flags $values $round $obj`; 346 | } 347 | } 348 | } 349 | 350 | //execute the command 351 | if ($echoCommand) { 352 | evalEcho($finalCmd); 353 | } else { 354 | eval($finalCmd); 355 | } 356 | } 357 | global proc float[] brndObj_GetOptions(string $type) { 358 | //returns an array of options based on $type 359 | //$type should be "Trans", "Rot", or "Scale" 360 | //0 - min value 361 | //1 - max value 362 | //2 - use X axis 363 | //3 - use Y axis 364 | //4 - use Z axis 365 | //5 - relative transform 366 | //6 - round the values 367 | //7 - transform space (only for trans or rotate) 368 | //8 - uniform scale (only for scale) 369 | 370 | if ($type != "Trans" && $type != "Rot" && $type != "Scale") 371 | return {}; 372 | 373 | float $opts[]; 374 | 375 | $opts[0] = `floatField -q -v ("brndWin_Obj"+$type+"MinFloat")`; 376 | $opts[1] = `floatField -q -v ("brndWin_Obj"+$type+"MaxFloat")`; 377 | $opts[2] = `menuItem -q -cb ("brndWin_Obj"+$type+"MM_X")`; 378 | $opts[3] = `menuItem -q -cb ("brndWin_Obj"+$type+"MM_Y")`; 379 | $opts[4] = `menuItem -q -cb ("brndWin_Obj"+$type+"MM_Z")`; 380 | $opts[5] = `menuItem -q -cb ("brndWin_Obj"+$type+"MM_Relative")`; 381 | $opts[6] = `menuItem -q -cb ("brndWin_Obj"+$type+"MM_Round")`; 382 | if ($type != "Scale") { 383 | $opts[7] = `intField -q -v ("brndWin_Obj"+$type+"SpaceInt")`; 384 | $opts[8] = 0; 385 | } else { 386 | $opts[7] = 0; 387 | $opts[8] = `menuItem -q -cb ("brndWin_Obj"+$type+"MM_Uniform")`; 388 | } 389 | 390 | return $opts; 391 | } 392 | global proc string[] brndObj_BuildFlags(string $type, float $opts[]) { 393 | //returns the flags based on the type and the options 394 | 395 | string $flags[]; 396 | 397 | // $flags[0] : relative/absolute 398 | $flags[0] = ($opts[5] == 1 ? "-r" : "-a"); 399 | 400 | // $flags[1] : space (only for trans and rot) 401 | if ($type == "trans") { 402 | if ($opts[7] == 1) { 403 | $flags[1] = "-os"; 404 | } else if ($opts[7] == 2) { 405 | $flags[1] = "-ws"; 406 | } else if ($opts[7] == 3) { 407 | $flags[1] = "-ls"; 408 | } 409 | } else if ($type == "rot") { 410 | if ($opts[7] == 1) { 411 | $flags[1] = "-eu"; 412 | } else if ($opts[7] == 2) { 413 | $flags[1] = "-ws"; 414 | } else if ($opts[7] == 3) { 415 | $flags[1] = "-os"; 416 | } 417 | } else { 418 | $flags[1] = ""; 419 | } 420 | 421 | // $flags[2] : axis flag (-x -xy -xyz -xz -y -yz or -z) 422 | string $axisFlag = "-"; 423 | if ($opts[2]) { 424 | $axisFlag += "x"; 425 | } 426 | if ($opts[3]) { 427 | $axisFlag += "y"; 428 | } 429 | if ($opts[4]) { 430 | $axisFlag += "z"; 431 | } 432 | $flags[2] = $axisFlag; 433 | 434 | //return the array 435 | return $flags; 436 | } 437 | global proc float[] brndObj_BuildValues(string $type, float $opts[]) { 438 | //returns an array of 1, 2, or 3 values based on the tyep and the options 439 | 440 | float $values[]; 441 | 442 | if ($opts[8] == 1) { 443 | //uniform is checked (could also work for trans and rot in the future) 444 | float $value = `brndRandRange $opts[0] $opts[1]`; 445 | $values = {$value, $value, $value}; 446 | } else { 447 | if ($opts[2]) { 448 | $values[size($values)] = `brndRandRange $opts[0] $opts[1]`; 449 | } 450 | if ($opts[3]) { 451 | $values[size($values)] = `brndRandRange $opts[0] $opts[1]`; 452 | } 453 | if ($opts[4]) { 454 | $values[size($values)] = `brndRandRange $opts[0] $opts[1]`; 455 | } 456 | } 457 | 458 | return $values; 459 | } 460 | global proc string brndObj_BuildCmd(string $mainCmd, string $flags[], float $values[], int $round, string $obj) { 461 | //returns a command based on a mainCmd (move, rotate, or scale), flags, and values 462 | 463 | string $cmd = ($mainCmd + " "); 464 | for ($flag in $flags) { 465 | if ($flag != "") { 466 | $cmd += ($flag + " "); 467 | } 468 | } 469 | for ($value in $values) { 470 | if ($round) { 471 | $value = floor($value + 0.5); 472 | } 473 | $cmd += ($value + " "); 474 | } 475 | 476 | //when using objects in the command, there must always be three values 477 | //even if a two or one value flag is used (like -x or -xy) 478 | if (size($values) == 1) { 479 | $cmd += "0 0 "; 480 | } else if (size($values) == 2) { 481 | $cmd += "0 "; 482 | } 483 | 484 | //$obj isn't used if object sync is on 485 | if ($obj != "") { 486 | $cmd += $obj; 487 | } 488 | 489 | $cmd += ";\n"; 490 | 491 | return $cmd; 492 | } 493 | //==================================================================================================== 494 | 495 | 496 | 497 | //==================================================================================================== 498 | global proc brndChan_Randomize() { 499 | //randomizes the selected channels in the channel box for the selected objects 500 | 501 | //get the selections 502 | string $selList[] = `ls -r 1 -fl -sl`; 503 | if (!size($selList)) 504 | return; 505 | 506 | string $attrList[], $mainAttrs[], $outAttrs[], $histAttrs[], $shapeAttrs[]; 507 | $mainAttrs = `channelBox -q -sma mainChannelBox`; 508 | $outAttrs = `channelBox -q -soa mainChannelBox`; 509 | $histAttrs = `channelBox -q -sha mainChannelBox`; 510 | $shapeAttrs = `channelBox -q -ssa mainChannelBox`; 511 | $attrList = stringArrayCatenate($mainAttrs, $outAttrs); 512 | $attrList = stringArrayCatenate($attrList, $histAttrs); 513 | $attrList = stringArrayCatenate($attrList, $shapeAttrs); 514 | 515 | if(!size($attrList)) 516 | return ; 517 | 518 | //create the important variables 519 | int $syncObjs, $syncChans, $useSeed, $round; 520 | float $customSeed, $optMin, $optMax; 521 | 522 | $syncObjs = `checkBox -q -v brndWin_ChanSyncObjsCheck`; 523 | $syncChans = `checkBox -q -v brndWin_ChanSyncChansCheck`; 524 | $round = `menuItem -q -cb brndWin_ChanRandMM_Round`; 525 | $useSeed = `checkBox -q -v brndWin_OptSeedCheck`; 526 | $customSeed = `intField -q -v brndWin_OptSeedInt`; 527 | $echoCommand = `menuItem -q -cb brndWin_Menu_Echo`; 528 | 529 | $optMin = `floatField -q -v brndWin_ChanMinFloat`; 530 | $optMax = `floatField -q -v brndWin_ChanMaxFloat`; 531 | 532 | if ($useSeed) { 533 | seed($customSeed); 534 | } else { 535 | //millisecond based seeding 536 | int $time = (int)(`timerX` * 100); 537 | seed($time); 538 | } 539 | 540 | 541 | string $finalCmd = ""; 542 | 543 | if ($syncChans) { 544 | if ($syncObjs) { 545 | //only need one set of random values for the whole thing 546 | float $val = brndRandRange($optMin, $optMax); 547 | if ($round) $val = floor($val+0.5); 548 | for ($obj in $selList) { 549 | for ($attr in $attrList) { 550 | if (`objExists ($obj+"."+$attr)`) 551 | $finalCmd += "setAttr "+$obj+"."+$attr+" "+$val+";\n"; 552 | } 553 | } 554 | } else { 555 | //only need one set of random values for each object 556 | for ($obj in $selList) { 557 | float $val = brndRandRange($optMin, $optMax); 558 | if ($round) $val = floor($val+0.5); 559 | for ($attr in $attrList) { 560 | if (`objExists ($obj+"."+$attr)`) 561 | $finalCmd += "setAttr "+$obj+"."+$attr+" "+$val+";\n"; 562 | } 563 | } 564 | } 565 | } else { 566 | if ($syncObjs) { 567 | //need only one set of random channel values (1 for each channel) 568 | for ($attr in $attrList) { 569 | float $val = brndRandRange($optMin, $optMax); 570 | if ($round) $val = floor($val+0.5); 571 | for ($obj in $selList) { 572 | if (`objExists ($obj+"."+$attr)`) 573 | $finalCmd += "setAttr "+$obj+"."+$attr+" "+$val+";\n"; 574 | } 575 | } 576 | } else { 577 | //need a random value for every channel for every object 578 | for ($attr in $attrList) { 579 | for ($obj in $selList) { 580 | float $val = brndRandRange($optMin, $optMax); 581 | if ($round) $val = floor($val+0.5); 582 | if (`objExists ($obj+"."+$attr)`) 583 | $finalCmd += "setAttr "+$obj+"."+$attr+" "+$val+";\n"; 584 | } 585 | } 586 | } 587 | } 588 | 589 | //execute the command 590 | if ($echoCommand) { 591 | evalEcho($finalCmd); 592 | } else { 593 | eval($finalCmd); 594 | } 595 | } 596 | 597 | 598 | //==================================================================================================== 599 | global proc float brndRandRange(float $min, float $max) { 600 | //returns a random number in the specified range 601 | 602 | float $dist = $max - $min; 603 | float $rand = rand($dist); 604 | $rand += $min; 605 | return $rand; 606 | } 607 | //==================================================================================================== 608 | -------------------------------------------------------------------------------- /src/boScripts/scripts/boRenderStats.mel: -------------------------------------------------------------------------------- 1 | /* 2 | Render Stats 3 | 0.8 4 | 5 | Copyright (c) 2010 Bohdon Sayre 6 | All Rights Reserved. 7 | bo@bohdon.com 8 | 9 | unique prefix: brnst 10 | 11 | Description: 12 | A GUI for quickly setting render stats on multiple objects. 13 | 14 | Instructions: 15 | boRenderStats; 16 | 17 | Version 0.8: 18 | > Select/Deselect a checkBox column to select/deselect the attribute on all objects 19 | > Horizontal checkBox rows for every selected item 20 | 21 | Feel free to email me with any bugs, comments, or requests! 22 | */ 23 | 24 | 25 | global proc boRenderStats() { 26 | /** 27 | * Main procedure. Creates the GUI and sets up the main script job. 28 | **/ 29 | //window name 30 | string $win = "brnstWin"; 31 | 32 | //check for pre-existing window 33 | if (`window -exists $win`) deleteUI -window $win; 34 | 35 | //create window 36 | window -w 200 -s 1 -tlb 1 -t "Render Stats" $win; 37 | 38 | 39 | //build variables 40 | string $titles[] = { "Cast", "Receive", "Blur", "Vis", "Smooth", "Reflect", "Refract", "Double", "Opposite" }; 41 | string $attrs[] = brnstGetAttrs(); 42 | 43 | string $form = `formLayout -nd 100`; 44 | string $scroll = `scrollLayout`; 45 | columnLayout -adj 1 brnstScrollColumn; 46 | 47 | //Header Column 48 | columnLayout -rs 4 brnstHeaderColumn; 49 | int $firstColWidth = 140; 50 | int $colWidth = 45; 51 | 52 | //titles row 53 | string $titlesRow = `rowLayout -nc (size($titles) + 1)`; 54 | rowLayout -e -cal 1 "center" -cw 1 $firstColWidth $titlesRow; 55 | text -w $firstColWidth -fn "boldLabelFont" -l "Object"; 56 | 57 | for ($i = 1; $i < size($titles) + 1; $i++) { 58 | rowLayout -e -cal ($i+1) "center" -cw ($i+1) $colWidth $titlesRow; 59 | text -w $colWidth -l $titles[$i-1] ("brnstMainCheck_" + $titles[$i-1]); 60 | }; 61 | setParent ..; 62 | 63 | //checkboxes row 64 | string $boxesRow = `rowLayout -nc (size($titles) + 1)`; 65 | rowLayout -e -cw 1 ($firstColWidth + $colWidth/2 - 5) $boxesRow; 66 | text -l ""; 67 | for ($i = 1; $i < size($titles) + 1; $i++) { 68 | rowLayout -e -cal ($i+1) "center" -cw ($i+1) $colWidth $boxesRow; 69 | checkBox -l "" -cc ("brnstCheckAll(\"" + $titles[$i-1] + "\",\"" + $attrs[$i-1] + "\", #1);"); 70 | }; 71 | setParent ..; 72 | 73 | 74 | setParent ..; 75 | separator -st "single"; 76 | columnLayout -rs 4 brnstMainColumn; 77 | setParent ..; 78 | setParent ..; 79 | setParent ..; 80 | 81 | formLayout -e 82 | -ap $scroll "left" 0 0 83 | -ap $scroll "right" 0 100 84 | -ap $scroll "top" 0 0 85 | -ap $scroll "bottom" 0 100 86 | $form; 87 | 88 | window -e -w 580 -h 220 $win; 89 | showWindow $win; 90 | 91 | //setup script job 92 | brnstSetupScriptjob($win); 93 | brnstRefresh(); 94 | 95 | } 96 | 97 | global proc brnstAddObject(string $obj) { 98 | /** 99 | * Adds an object to the list in the window. 100 | **/ 101 | string $layout = brnstGetLayout(); 102 | string $titles[] = { "Cast", "Receive", "Blur", "Vis", "Smooth", "Reflect", "Refract", "Double", "Opposite" }; 103 | string $attrs[] = brnstGetAttrs(); 104 | int $firstColWidth = 140; 105 | int $colWidth = 45; 106 | 107 | setParent $layout; 108 | //checkboxes row 109 | string $row = `rowLayout -nc (size($attrs) + 1)`; 110 | rowLayout -e -cw 1 ($firstColWidth + $colWidth/2 - 5) $row; 111 | text -l $obj; 112 | for ($i = 1; $i < size($attrs) + 1; $i++) { 113 | rowLayout -e -cal ($i+1) "center" -cw ($i+1) $colWidth $row; 114 | 115 | string $checkBox = ("brnstCheck_"+$obj+"_"+$titles[$i-1]); 116 | int $val = `getAttr ($obj+"."+$attrs[$i-1])`; 117 | 118 | checkBox -l "" -v $val -cc ("brnstSetAttr(\"" + $obj + "\", \"" + ($attrs[$i-1]) + "\", #1);") $checkBox; 119 | } 120 | } 121 | 122 | 123 | global proc string brnstGetLayout() { 124 | /** 125 | * Retrieves the layout for adding items to the window. This 126 | * is a columnLayout, so that objects can be added easily in a descending order. 127 | **/ 128 | return "brnstMainColumn"; 129 | } 130 | 131 | 132 | global proc string[] brnstGetAttrs() { 133 | /** 134 | * Returns the current list of render stat attributes. They are listed in the 135 | * same order as they appear in the Attribute Editor. 136 | **/ 137 | return { "castsShadows", "receiveShadows", "motionBlur", "primaryVisibility", "smoothShading", "visibleInReflections", "visibleInRefractions", "doubleSided", "opposite" }; 138 | } 139 | 140 | 141 | 142 | global proc brnstSetupScriptjob(string $parent) { 143 | /** 144 | * Creates a script job tied to the window. Checks for selection 145 | * changes and refreshes the window as necessary. 146 | **/ 147 | scriptJob -p $parent -cu 1 -e "SelectionChanged" "brnstRefresh"; 148 | } 149 | 150 | 151 | 152 | 153 | global proc brnstRefresh() { 154 | /** 155 | * Called on selection change by the script job. 156 | * Checks the selection and updates the window contents. 157 | **/ 158 | //clear the layout; 159 | string $layout = brnstGetLayout(); 160 | string $children[] = `columnLayout -q -ca $layout`; 161 | if (size($children)) { 162 | for ($i = 0; $i < size($children); $i++) { 163 | deleteUI -lay $children[$i]; 164 | } 165 | } 166 | 167 | string $selList[] = `ls -r 1 -sl`; 168 | if (!size($selList)) 169 | return; 170 | 171 | for ($i = 0; $i < size($selList); $i++) { 172 | brnstAddObject($selList[$i]); 173 | } 174 | } 175 | 176 | 177 | 178 | global proc brnstSetAttr(string $obj, string $attr, int $val) { 179 | /** Sets a render attribute on the specified object **/ 180 | if (`objExists ($obj+"."+$attr)`) { 181 | setAttr ($obj+"."+$attr) $val; 182 | } 183 | } 184 | 185 | global proc brnstUpdateObjs(string $title, string $attr) { 186 | /** Retrieves checkBox values, and sets render stats. This is necessary because changeCommand isn't triggered when checkBoxes are edited **/ 187 | string $selList[] = `ls -r 1 -sl`; 188 | if (!size($selList)) 189 | return; 190 | 191 | for ($i = 0; $i < size($selList); $i++) { 192 | string $checkBox = ("brnstCheck_"+$selList[$i]+"_"+$title); 193 | int $val = `checkBox -q -v $checkBox`; 194 | setAttr ($selList[$i]+"."+$attr) $val; 195 | } 196 | } 197 | 198 | global proc brnstCheckAll(string $title, string $attr, int $val) { 199 | /** Checks all checkboxes of the column indicated by the title **/ 200 | //go through current selection and call the checkboxes by prefix and title suffix, and set their values 201 | string $selList[] = `ls -r 1 -sl`; 202 | if (!size($selList)) 203 | return; 204 | 205 | for ($i = 0; $i < size($selList); $i++) { 206 | string $checkBox = ("brnstCheck_"+$selList[$i]+"_"+$title); 207 | checkBox -e -v $val $checkBox; 208 | } 209 | 210 | brnstUpdateObjs($title, $attr); 211 | } 212 | -------------------------------------------------------------------------------- /src/boScripts/scripts/boScriptJobs.mel: -------------------------------------------------------------------------------- 1 | /* 2 | Script Jobs 3 | 1.0 4 | 5 | Copyright (c) 2010 Bohdon Sayre 6 | All Rights Reserved. 7 | bo@bohdon.com 8 | 9 | unique prefix: bsj 10 | 11 | Description: 12 | Provides a manager and helpful procedures 13 | for handling script jobs 14 | 15 | Instructions: 16 | boScriptJobs; 17 | 18 | Version 1.0: 19 | > Window manager for deleting jobs 20 | 21 | Feel free to email me with any bugs, comments, or requests! 22 | */ 23 | 24 | 25 | global proc boScriptJobs() { 26 | //main window procedure 27 | 28 | //window name 29 | $win = "bsjWin"; 30 | 31 | //check for pre-existing window 32 | if (`window -ex $win`) deleteUI -wnd $win; 33 | 34 | //create window 35 | window -rtf 1 -mb 1 -mxb 0 -t "Bo Script Job Manager" -mnc ("window -e -t \"Bo Script Job Manager\" "+$win+";") $win; 36 | 37 | //main layout 38 | frameLayout -lv 0 -bv 0 -mw 4 -mh 4; 39 | formLayout -nd 10 bsjMgrForm; 40 | button -l "List Jobs" -c "bsjMgrRefresh" bsjMgrRefreshBtn; 41 | //main job list 42 | textScrollList -h 200 -ams 1 bsjMgrList; 43 | //list popup menu 44 | popupMenu -mm 1 -aob 1; 45 | menuItem -rp "S" -l "Delete" -c "bsjMgrDeleteSelected"; 46 | 47 | formLayout -e 48 | -ap bsjMgrRefreshBtn "left" 0 0 49 | -ap bsjMgrRefreshBtn "right" 0 10 50 | -ac bsjMgrList "top" 4 bsjMgrRefreshBtn 51 | -ap bsjMgrList "left" 0 0 52 | -ap bsjMgrList "right" 0 10 53 | -ap bsjMgrList "bottom" 0 10 54 | bsjMgrForm; 55 | 56 | window -e -w 300 -h 550 $win; 57 | showWindow $win; 58 | } 59 | 60 | global proc bsjMgrRefresh() { 61 | string $scriptJobList[] = `scriptJob -lj`; 62 | 63 | //string newlines 64 | $scriptJobList = `bsjMgrStripNewlines $scriptJobList`; 65 | 66 | textScrollList -e -ra bsjMgrList; 67 | for ($scriptJob in $scriptJobList) { 68 | textScrollList -e -a $scriptJob bsjMgrList; 69 | } 70 | } 71 | global proc bsjMgrDeleteSelected() { 72 | string $jobsToDelete[] = `textScrollList -q -si bsjMgrList`; 73 | if (!size($jobsToDelete)) 74 | return; 75 | 76 | int $sjNums[] = `bsjMgrExtractNums $jobsToDelete`; 77 | 78 | print ("\n"); 79 | 80 | int $succeed = 0; 81 | for ($num in $sjNums) { 82 | if ($num > 27) { 83 | if (catch( `scriptJob -kill $num`)) { 84 | $succeed = 0; 85 | } else { 86 | $succeed = 1; 87 | } 88 | if ($succeed) { 89 | print ("// deleted scriptJob "+$num+"\n"); 90 | } else { 91 | print("// could not delete scriptJob "+$num+"\n"); 92 | } 93 | } else { 94 | print ("// please attempt manual deletion of scriptJob "+$num+"\n"); 95 | } 96 | } 97 | 98 | //refresh 99 | textScrollList -e -da bsjMgrList; 100 | bsjMgrRefresh(); 101 | 102 | } 103 | 104 | 105 | global proc string[] bsjMgrStripNewlines(string $scriptJobList[]) { 106 | //removes newline characters from the end of each line 107 | 108 | string $sjLines[]; 109 | for ($line in $scriptJobList) { 110 | $sjLines[size($sjLines)] = `substitute "\n" $line ""`; 111 | } 112 | return $sjLines; 113 | } 114 | 115 | //match operation procedures 116 | global proc int[] bsjMgrExtractNums(string $scriptJobList[]) { 117 | int $sjNums[]; 118 | for ($line in $scriptJobList) { 119 | $sjNums[size($sjNums)] = (int)`match "^[0-9]*[^:]*" $line`; 120 | } 121 | return $sjNums; 122 | } 123 | -------------------------------------------------------------------------------- /src/boScripts/scripts/boSliders.mel: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bohdon/boScripts/49dc6cc2558608a6ff88f87039482f2ba4dbadee/src/boScripts/scripts/boSliders.mel -------------------------------------------------------------------------------- /src/boScripts/scripts/boSmear.py: -------------------------------------------------------------------------------- 1 | """ 2 | Smear 3 | 4 | Copyright (c) 2011 Bohdon Sayre 5 | All Rights Reserved. 6 | bohdon@gmail.com 7 | 8 | Description: 9 | Allows you to create a "2D" mesh warp on specified objects, 10 | controlled relative to a camera. This allows the creation of 11 | "smearing" effects seen in traditional animations. 12 | 13 | Features: 14 | > Instant setup 15 | > Huge speed improvement by using much simpler connections from the mesh control 16 | > Easy to use control window for managing all smear meshes 17 | > More mesh controls (soften, weight, etc) 18 | 19 | Feel free to email me with any bugs, comments, or requests! 20 | """ 21 | 22 | # TODO: 23 | # finish smear create lockup 24 | # make smear control GUI 25 | # improve resolution system 26 | # perhaps have a way to determine how many edge lattice points, and maybe create a falloff 27 | # overscan? also might be a helpful trick 28 | # multiple smears on a single object 29 | 30 | import logging 31 | 32 | import pymel.core as pm 33 | 34 | __version__ = "3.0.0b" 35 | 36 | LOG = logging.getLogger(__name__) 37 | 38 | 39 | class SmearError(Exception): 40 | pass 41 | 42 | 43 | class Gui(object): 44 | camera_ann = "The camera on which to apply the smear. This can be changed later." 45 | target_ann = "The object to fix the center of the smear deformer to." 46 | res_ann = "The resolution of the smear mesh" 47 | 48 | def __init__(self): 49 | self.buildUI() 50 | self.loadInfo() 51 | 52 | def buildUI(self): 53 | if pm.window("bsmWin", ex=True): 54 | pm.deleteUI("bsmWin") 55 | 56 | with pm.window("bsmWin", t="Smear {0}".format(__version__)): 57 | with pm.frameLayout(lv=False, bv=False, mw=10, mh=10): 58 | with pm.formLayout(nd=100) as mainForm: 59 | with pm.frameLayout(l="Settings", bs="etchedIn", mw=4, mh=4, bgc=(0.2, 0.2, 0.2)) as stngsFrame: 60 | with pm.formLayout(nd=100) as tmpForm: 61 | tw = 60 62 | camTxt = pm.text(l="Camera ", al="right", w=tw) 63 | camMenu = self.uiCamMenu = pm.optionMenu() 64 | btn1 = pm.button(l="Refresh", h=20, w=54, c=pm.Callback(self.loadInfo)) 65 | targetTxt = pm.text(l="Target ", al="right", w=tw) 66 | targetField = self.uiTargetField = pm.textField() 67 | btn2 = pm.button(l="<<", h=20, w=30, c=pm.Callback(self.getTarget)) 68 | resTxt = pm.text(l="Resolution ", al="right", w=tw) 69 | resX = self.uiResXField = pm.intField(v=18, min=1, max=100, w=30) 70 | resDivTxt = pm.text(l="x") 71 | resY = self.uiResYField = pm.intField(v=12, min=1, max=100, w=30) 72 | pm.formLayout( 73 | tmpForm, 74 | e=True, 75 | af=[ 76 | (camTxt, "left", 0), 77 | (camTxt, "top", 3), 78 | (camMenu, "top", 0), 79 | (btn1, "right", 0), 80 | (resTxt, "left", 0), 81 | (targetTxt, "left", 0), 82 | (btn2, "right", 0), 83 | ], 84 | ac=[ 85 | (camMenu, "left", 4, camTxt), 86 | (camMenu, "right", 2, btn1), 87 | (targetTxt, "top", 7, camMenu), 88 | (targetField, "top", 4, camMenu), 89 | (btn2, "top", 4, camMenu), 90 | (targetField, "left", 4, targetTxt), 91 | (targetField, "right", 2, btn2), 92 | (resTxt, "top", 7, targetField), 93 | (resX, "top", 4, targetField), 94 | (resDivTxt, "top", 7, targetField), 95 | (resY, "top", 4, targetField), 96 | (resX, "left", 4, resTxt), 97 | (resDivTxt, "left", 4, resX), 98 | (resY, "left", 4, resDivTxt), 99 | ], 100 | ) 101 | with pm.frameLayout(l="Geometry", bs="etchedIn", mw=4, mh=4, bgc=(0.2, 0.2, 0.2)) as geoFrame: 102 | with pm.formLayout() as tmpForm: 103 | geoList = self.uiGeoList = pm.textScrollList(ams=True) 104 | btn1 = pm.button(l="+", w=30, c=pm.Callback(self.addGeo)) 105 | btn2 = pm.button(l="-", w=30, c=pm.Callback(self.delGeo)) 106 | pm.formLayout( 107 | tmpForm, 108 | e=True, 109 | af=[ 110 | (geoList, "top", 0), 111 | (geoList, "left", 0), 112 | (geoList, "bottom", 0), 113 | (btn1, "top", 0), 114 | (btn1, "right", 0), 115 | (btn2, "right", 0), 116 | ], 117 | ac=[(geoList, "right", 2, btn1), (btn2, "top", 0, btn1)], 118 | ) 119 | btn1 = pm.button(l="Create Smear", h=30, bgc=(0.75, 0.75, 0.75), c=pm.Callback(self.create)) 120 | btn2 = pm.button(l="Control Window", h=30, w=100, c=pm.Callback(ControlGui)) 121 | pm.formLayout( 122 | mainForm, 123 | e=True, 124 | af=[ 125 | (stngsFrame, "top", 0), 126 | (stngsFrame, "left", 0), 127 | (stngsFrame, "right", 0), 128 | (geoFrame, "left", 0), 129 | (geoFrame, "right", 0), 130 | (btn1, "left", 12), 131 | (btn1, "bottom", 0), 132 | (btn2, "right", 12), 133 | (btn2, "bottom", 0), 134 | ], 135 | ac=[ 136 | (geoFrame, "top", 10, stngsFrame), 137 | (geoFrame, "bottom", 8, btn1), 138 | (btn1, "right", 10, btn2), 139 | ], 140 | ) 141 | 142 | def loadInfo(self): 143 | """Populate the camera list with all perspective cams in the scene""" 144 | cams = [c.getParent() for c in pm.ls(type="camera") if not c.isOrtho()] 145 | curVal = self.uiCamMenu.getValue() 146 | self.uiCamMenu.clear() 147 | self.uiCamMenu.addItems(cams) 148 | if curVal in cams: 149 | self.uiCamMenu.setValue(curVal) 150 | 151 | def getTarget(self): 152 | """Set the target object to the selected node""" 153 | obj = pm.selected() 154 | if obj != []: 155 | self.uiTargetField.setText(str(obj[0])) 156 | else: 157 | self.uiTargetField.setText("") 158 | 159 | def addGeo(self): 160 | """Add the selected geometry to the geometry list""" 161 | items = self.uiGeoList.getAllItems() 162 | items.extend([str(i) for i in pm.selected() if self.isGeo(i)]) 163 | new = sorted(list(set(items))) 164 | print(new) 165 | self.uiGeoList.removeAll() 166 | self.uiGeoList.append(new) 167 | 168 | def isGeo(self, obj): 169 | """ 170 | Return true if the object is the shape or 171 | transform of a deformable geometry 172 | """ 173 | shapes = [obj] 174 | if obj.type() == "transform": 175 | shapes = obj.getShapes() 176 | for shape in shapes: 177 | if "deformableShape" in shape.type(i=True): 178 | return True 179 | 180 | def delGeo(self): 181 | """Deleted the selected geometry from the list""" 182 | items = self.uiGeoList.getSelectItem() 183 | for item in items: 184 | self.uiGeoList.removeItem(item) 185 | 186 | def create(self): 187 | cam = pm.PyNode(self.uiCamMenu.getValue()) 188 | target = pm.PyNode(self.uiTargetField.getText()) 189 | res = [self.uiResXField.getValue(), self.uiResYField.getValue()] 190 | geo = [pm.PyNode(x) for x in self.uiGeoList.getAllItems()] 191 | s = Smear(cam, target, res, geo) 192 | s.create() 193 | s.addGeometry(geo) 194 | 195 | 196 | class ControlGui(object): 197 | def __init__(self): 198 | if pm.window("bsmControlWin", ex=True): 199 | pm.deleteUI("bsmControlWin") 200 | 201 | with pm.window("bsmControlWin", t="Smear Control {0}".format(__version__)): 202 | pass 203 | 204 | 205 | class Smear(object): 206 | def __init__(self, cam, target, res, geo=None): 207 | """ 208 | ``cam`` -- the camera to attach the smear mesh to 209 | ``target`` -- the node to attach the center of the deformer to 210 | ``res`` -- the resolution of the smear mesh ie. (18, 12) 211 | ``geo`` -- a list of all geometry to be affected by the smear 212 | """ 213 | self.cam = cam 214 | self.target = target 215 | self.res = res 216 | self.geo = geo 217 | # initialize blank properties 218 | props = [ 219 | "mainGrp", 220 | "camChild", 221 | "meshOffset", 222 | "meshScale", 223 | "latticeFollow", 224 | "latticeScale", 225 | "ffd", 226 | "lattice", 227 | "latticeGrp", 228 | "sX", 229 | "sY", 230 | "depthGuide", 231 | "mesh", 232 | "mesh_mtl", 233 | "mesh_sg", 234 | "meshScale", 235 | ] 236 | for prop in props: 237 | setattr(self, prop, None) 238 | 239 | def create(self): 240 | self._validateObjs() 241 | self._createHierarchy() 242 | self._createLattice() 243 | self._createDepthGuide() 244 | self._createMesh() 245 | self._connectMeshToLattice() 246 | self._createConstraints() 247 | self._lockup() 248 | 249 | def addGeometry(self, geo): 250 | """Add the given geometry to the smear mesh""" 251 | if hasattr(self, "ffd"): 252 | pm.lattice(self.ffd, e=True, g=geo) 253 | else: 254 | LOG.warning("lattice ffd has not been defined for {0}".format(self)) 255 | 256 | def removeGeometry(self, geo): 257 | """Remove the given geometry from the smear mesh""" 258 | if hasattr(self, "ffd"): 259 | curGeo = pm.lattice(self.ffd, q=True, g=True) 260 | remGeo = [] 261 | for g in geo: 262 | if g in curGeo: 263 | remGeo.append(g) 264 | pm.lattice(self.ffd, e=True, rm=True, g=remGeo) 265 | else: 266 | LOG.warning("lattice ffd has not been defined for {0}".format(self)) 267 | 268 | def _validateObjs(self): 269 | pass 270 | 271 | def _createHierarchy(self): 272 | self.mainGrp = pm.group(em=True, n="smear_grp#") 273 | self.camChild = pm.group(em=True, n="smear_camChild", p=self.mainGrp) 274 | self.meshOffset = pm.group(em=True, n="smear_mesh_offset", p=self.camChild) 275 | self.meshScale = pm.group(em=True, n="smear_mesh_scale", p=self.meshOffset) 276 | self.latticeFollow = pm.group(em=True, n="smear_lattice_follow", p=self.camChild) 277 | self.latticeScale = pm.group(em=True, n="smear_lattice_scale", p=self.latticeFollow) 278 | 279 | def _createLattice(self): 280 | resX, resY = self.res 281 | self.ffd, self.lattice, base = pm.lattice( 282 | ignoreSelected=True, 283 | dv=[resX + 2, resY + 2, 2], 284 | ldv=(4, 4, 4), 285 | cp=True, 286 | s=(1, 1, 1), 287 | n="smear#", 288 | pos=(0, 0, 0), 289 | ) 290 | self.latticeGrp = self.lattice.getParent() 291 | # when a lattice is made, the vertex points are absolute, if a deformer 292 | # (such as a cluster) is applied a latticeShapeOrig is created which 293 | # maintains the absolute positions. the deformer could then be deleted 294 | # and the lattice points would remain zeroed. this is necessary for us 295 | # to connect them to the mesh points which will also be zeroed 296 | pm.select(self.lattice.pt[0][0][0]) 297 | newC = pm.cluster(relative=True, envelope=1) 298 | pm.delete(newC) 299 | # move into hierarchy 300 | pm.parent(self.latticeGrp, self.latticeScale) 301 | self.sX = 1.0275 * float(resX + 2) / resX 302 | self.sY = 0.58 * float(resY + 2) / resY 303 | self.latticeGrp.scaleX.set(self.sX) 304 | self.latticeGrp.scaleY.set(self.sY) 305 | self.latticeGrp.visibility.set(False) 306 | 307 | def _createDepthGuide(self): 308 | # create a cube using a single curve 309 | p = 0.5 310 | points = [ 311 | (-p, -p, p), 312 | (p, -p, p), 313 | (p, -p, -p), 314 | (-p, -p, -p), 315 | (-p, -p, p), 316 | (-p, p, p), 317 | (p, p, p), 318 | (p, p, -p), 319 | (-p, p, -p), 320 | (-p, p, p), 321 | (p, p, p), 322 | (p, -p, p), 323 | (p, -p, -p), 324 | (p, p, -p), 325 | (-p, p, -p), 326 | (-p, -p, -p), 327 | ] 328 | self.depthGuide = pm.curve(d=1, n="smearDepthBox", p=points, k=range(16)) 329 | pm.parent(self.depthGuide, self.latticeScale) 330 | self.depthGuide.scaleX.set(self.sX) 331 | self.depthGuide.scaleY.set(self.sY) 332 | self.depthGuide.overrideEnabled.set(True) 333 | self.depthGuide.overrideDisplayType.set(1) 334 | 335 | def _createMesh(self): 336 | """Create the smear mesh""" 337 | resX, resY = self.res 338 | self.mesh = pm.polyPlane(w=1, h=1, sx=resX - 1, sy=resY - 1, ax=(0, 0, 1), cuv=2, ch=True, n="smearMesh")[0] 339 | pm.select(self.mesh) 340 | pm.mel.HighQualityDisplay() 341 | # scale and freeze 342 | sx, sy, sz = float(resX) / (resX + 2), float(resY) / (resY + 2), 1 343 | pm.scale(self.mesh, [sx, sy, sz], a=True, xyz=True) 344 | pm.makeIdentity(apply=True, t=True, r=True, s=True, n=1) 345 | # delete history 346 | pm.delete(self.mesh, ch=True) 347 | pm.parent(self.mesh, self.meshScale) 348 | self.meshShape = self.mesh.getShape() 349 | # turn off render stats 350 | attrs = [ 351 | "castsShadows", 352 | "receiveShadows", 353 | "motionBlur", 354 | "primaryVisibility", 355 | "smoothShading", 356 | "visibleInReflections", 357 | "visibleInRefractions", 358 | "doubleSided", 359 | ] 360 | for attr in attrs: 361 | getattr(self.meshShape, attr).set(False) 362 | # apply material 363 | self.mesh_mtl = pm.shadingNode("blinn", asShader=True, n="smear_mtl#") 364 | self.mesh_sg = pm.sets(renderable=True, noSurfaceShader=True, empty=True, n="smear_sg#") 365 | self.mesh_mtl.outColor >> self.mesh_sg.surfaceShader 366 | self.mesh_mtl.color.set((0.85, 0.85, 0.85)) 367 | self.mesh_mtl.transparency.set((0.9, 0.9, 0.9)) 368 | self.mesh_mtl.reflectivity.set(0) 369 | pm.sets(self.mesh_sg, e=True, fe=self.mesh) 370 | # add attributes 371 | self.mesh.addAttr("weight", at="double", min=0, max=1, dv=1, k=True) 372 | self.mesh.addAttr("soften", at="long", min=2, max=12, dv=4, k=True) 373 | self.mesh.addAttr("depthScale", at="double", dv=12, k=True) 374 | self.mesh.addAttr("displayDepthGuide", at="long", min=0, max=1, dv=0, k=True) 375 | self.mesh.addAttr("meshTransparency", at="double", min=0, max=1, dv=0.9, k=True) 376 | # connect attrs 377 | self.mesh.weight >> self.ffd.envelope 378 | self.mesh.soften >> self.ffd.localInfluenceS 379 | self.mesh.soften >> self.ffd.localInfluenceT 380 | self.mesh.soften >> self.ffd.localInfluenceU 381 | self.mesh.depthScale >> self.latticeScale.scaleZ 382 | self.mesh.displayDepthGuide >> self.depthGuide.visibility 383 | self.mesh.meshTransparency >> self.mesh_mtl.transparencyR 384 | self.mesh.meshTransparency >> self.mesh_mtl.transparencyG 385 | self.mesh.meshTransparency >> self.mesh_mtl.transparencyB 386 | 387 | def _connectMeshToLattice(self): 388 | """Connect all points of the smear mesh to the corresponding lattice points""" 389 | i = 0 390 | for y in range(self.res[1]): 391 | for x in range(self.res[0]): 392 | for z in range(2): 393 | self.meshShape.pnts[i] >> self.lattice.pt[x + 1][y + 1][z] 394 | i += 1 395 | 396 | def _createConstraints(self): 397 | self.camShape = self.cam.getShape() 398 | filmAp = self.camShape.hfa.get() 399 | self.meshScale.scaleX.set(1.2 * self.sX * (filmAp / 1.4173)) 400 | self.meshScale.scaleY.set(1.2 * self.sY * (filmAp / 1.4173)) 401 | # constrain lattice z-depth to target 402 | pm.pointConstraint(self.target, self.latticeFollow, skip=["x", "y"], w=1) 403 | # constrain cam child group to camera 404 | pm.parentConstraint(self.cam, self.camChild, w=1) 405 | # create expression for the smear mesh to follow focal depths 406 | scaleEq = "35/{cam}.focalLength * - {lf}.translateZ".format(cam=self.cam, lf=self.latticeFollow) 407 | latticeExp = "{ls}.scaleX = {se};\r\n{ls}.scaleY = {se};".format(ls=self.latticeScale, se=scaleEq) 408 | meshExp = "{mo}.translateZ = ({cam}.focalLength)/-29;".format(cam=self.cam, mo=self.meshOffset) 409 | pm.expression(s=latticeExp, o=self.latticeScale, ae=True, uc="all") 410 | pm.expression(s=meshExp, o=self.meshOffset, ae=True, uc="all") 411 | 412 | def _lockup(self): 413 | pass 414 | -------------------------------------------------------------------------------- /src/boScripts/scripts/boTSMTools.mel: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bohdon/boScripts/49dc6cc2558608a6ff88f87039482f2ba4dbadee/src/boScripts/scripts/boTSMTools.mel -------------------------------------------------------------------------------- /src/boScripts/scripts/boTimers.mel: -------------------------------------------------------------------------------- 1 | /* 2 | Bo Timers Mel 3 | 1.0 4 | 5 | created by Bohdon Sayre 6 | bsayre@c.ringling.edu 7 | 8 | Description: 9 | Provides the boTimersStart and boTimersCancel procedures 10 | for using the boTimers.py module 11 | 12 | Version 1.0: 13 | > boTimerCancel runs the kill() function, then deletes the variabls 14 | > boTimerStart creates a boTimer python class instance, but doesn't clear the variable when it's finished... 15 | 16 | */ 17 | 18 | global proc boTimerStart(string $timerPyName, float $dur, string $cmd) { 19 | python("from boTimers import *"); 20 | python($timerPyName+"=boTimerStart("+$dur+", \""+encodeString($cmd)+"\")"); 21 | } 22 | global proc boTimerCancel(string $timerPyName) { 23 | python("from boTimers import *"); 24 | python($timerPyName+".kill()\ndel "+$timerPyName); 25 | } 26 | 27 | global proc btcPythonAppendScriptsPath() { 28 | string $env = `getenv "MAYA_SCRIPT_PATH"`; 29 | string $dirs[] = stringToStringArray($env, ";"); 30 | string $goalPath; 31 | 32 | for ($dir in $dirs) { 33 | if (size(`match "/2008/scripts$" $dir`)) 34 | $goalPath = $dir; 35 | } 36 | while(size(`match "/" $goalPath`)) 37 | $goalPath = `substitute "/" $goalPath "\\\\"`; 38 | 39 | python("import sys"); 40 | string $curPaths[] = `python "sys.path"`; 41 | for ($path in $curPaths) { 42 | if (size(`match "\\\\2008\\\\scripts" $path`)) { 43 | //print ("path found: "+$path+"\n"); //pv 44 | return; 45 | } 46 | } 47 | 48 | //append it 49 | string $cmd; 50 | $cmd = ("sys.path.append(\""+$goalPath+"\")"); 51 | python($cmd); 52 | 53 | $curPaths = `python "sys.path"`; 54 | //print("new python sys paths:\n"); 55 | //print $curPaths; 56 | //print "\n"; 57 | 58 | } 59 | 60 | btcPythonAppendScriptsPath(); 61 | python("from boTimers import *"); 62 | -------------------------------------------------------------------------------- /src/boScripts/scripts/boTimers.py: -------------------------------------------------------------------------------- 1 | """ 2 | Bo Timing Charts and other scripts uses some procedures that need to be timed, or automatic... 3 | 4 | # This python script contains a timer function to enable threaded timing 5 | # It also uses the executeDeferred procedure to make sure the mel doesn't return anything before the python script is done 6 | 7 | # The timer also needs to be interruptable, so we use a boTimerActive variable 8 | # to find out if the command should still be run once the timer ends 9 | """ 10 | 11 | import threading 12 | import time 13 | 14 | import maya.cmds as cmds 15 | import maya.mel as mel 16 | import maya.utils as utils 17 | 18 | 19 | def boCmdEncode(cmd): 20 | return cmds.encodeString(cmd).replace('\\"', '"') 21 | 22 | 23 | def boTimerStart(dur, cmd): 24 | newBoTimer = boTimer(dur, cmd) 25 | newBoTimer.start() 26 | return newBoTimer 27 | 28 | 29 | class boTimer(threading.Thread): 30 | def __init__(self, dur, cmd): 31 | self.dur = dur 32 | self.cmd = cmd 33 | self.cancel = 0 34 | threading.Thread.__init__(self) 35 | 36 | def run(self): 37 | time.sleep(self.dur) 38 | if self.cancel == 0: 39 | utils.executeDeferred(mel.eval, boCmdEncode(self.cmd)) 40 | 41 | def kill(self): 42 | self.cancel = 1 43 | -------------------------------------------------------------------------------- /src/boScripts/scripts/boTimingCharts.mel: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bohdon/boScripts/49dc6cc2558608a6ff88f87039482f2ba4dbadee/src/boScripts/scripts/boTimingCharts.mel -------------------------------------------------------------------------------- /src/boScripts/scripts/boUVSnapshot.py: -------------------------------------------------------------------------------- 1 | """ 2 | UV Snapshot Tool 3 | 4 | Copyright (c) 2011 Bohdon Sayre 5 | All Rights Reserved. 6 | bo@bohdon.com 7 | Credit to Nick Matthews, Marcus Ng, Chanelle de Nysschen for the idea! 8 | 9 | Description: 10 | A GUI for outputting uv snapshots of multiple objects at once. 11 | Simple and efficient options for size and format. 12 | 13 | Feel free to email me with any bugs, comments, or requests! 14 | """ 15 | 16 | __version__ = "1.0" 17 | 18 | import os 19 | import subprocess 20 | import sys 21 | 22 | import pymel.core as pm 23 | 24 | 25 | class GUI(object): 26 | def __init__(self): 27 | self.winName = "boBatchUVWin" 28 | self.build() 29 | 30 | def build(self): 31 | if pm.window(self.winName, ex=True): 32 | pm.deleteUI(self.winName, wnd=True) 33 | 34 | if not pm.windowPref(self.winName, ex=True): 35 | pm.windowPref(self.winName, tlc=(200, 200)) 36 | pm.windowPref(self.winName, e=True, w=240, h=180) 37 | 38 | with pm.window(self.winName, rtf=True, mb=False, mxb=False, t="UV Snapshot") as self.win: 39 | with pm.formLayout(nd=100) as form: 40 | sizeTxt = pm.text(l="Size") 41 | self.sizeField = pm.intField(v=1024, w=50) 42 | self.sizeSlider = pm.intSlider(w=100, min=4, max=13, v=10, s=1, dc=pm.Callback(self.updateSizeField)) 43 | 44 | sep1 = pm.separator(h=4, st="in") 45 | typeTxt = pm.text(l="File Type") 46 | self.fmtOpts = pm.optionMenu(w=60) 47 | for x in ["iff", "jpg", "png", "tga", "tif"]: 48 | pm.menuItem(l=x) 49 | self.fmtOpts.setValue("tif") 50 | 51 | self.antiAliasCheck = pm.checkBox(l="Anti-Alias Lines", v=True, al="left") 52 | 53 | sep2 = pm.separator(h=4, st="in") 54 | self.dstOpts = pm.optionMenu(l="Destination", w=175) 55 | for x in ["sourceimages", "images"]: 56 | pm.menuItem(l=x) 57 | pm.popupMenu(p=self.dstOpts, mm=True, b=3) 58 | pm.menuItem("Open", c=pm.Callback(self.openDir)) 59 | 60 | infoTxt1 = pm.text(en=False, al="center", l="files will be saved as uvOut_objectName.ext") 61 | 62 | runBtn = pm.button( 63 | l="Output UVs", 64 | ann="Select multiple objects, then click Output UVs", 65 | c=pm.Callback(self.snapshot), 66 | h=26, 67 | ) 68 | 69 | pm.formLayout( 70 | form, 71 | e=True, 72 | af=[ 73 | (sizeTxt, "top", 12), 74 | (self.sizeField, "top", 10), 75 | (self.sizeSlider, "top", 12), 76 | (sep1, "left", 8), 77 | (sep1, "right", 8), 78 | (sep2, "left", 8), 79 | (sep2, "right", 8), 80 | (infoTxt1, "left", 0), 81 | (infoTxt1, "right", 0), 82 | (runBtn, "bottom", 8), 83 | (runBtn, "left", 8), 84 | (runBtn, "right", 8), 85 | ], 86 | ap=[ 87 | (sizeTxt, "left", -88, 50), 88 | (typeTxt, "left", -100, 50), 89 | ], 90 | ac=[ 91 | (self.sizeField, "left", 8, sizeTxt), 92 | (self.sizeSlider, "left", 5, self.sizeField), 93 | (sep1, "top", 9, sizeTxt), 94 | (typeTxt, "top", 9, sep1), 95 | (self.fmtOpts, "top", 6, sep1), 96 | (self.fmtOpts, "left", 5, typeTxt), 97 | (self.antiAliasCheck, "top", 8, sep1), 98 | (self.antiAliasCheck, "left", 8, self.fmtOpts), 99 | (sep2, "top", 6, self.fmtOpts), 100 | (self.dstOpts, "top", 10, sep2), 101 | (infoTxt1, "bottom", 8, runBtn), 102 | (self.dstOpts, "left", -25, typeTxt), 103 | ], 104 | ) 105 | 106 | def updateSizeField(self): 107 | self.sizeField.setValue(pow(2, self.sizeSlider.getValue())) 108 | 109 | def openDir(self): 110 | dst = self.dstOpts.getValue() 111 | projDir = pm.workspace(q=True, fn=True) 112 | outDir = os.path.join(projDir, dst) 113 | if os.path.isdir(outDir): 114 | if sys.platform == "win32": 115 | subprocess.Popen(["explorer.exe", os.path.normpath(outDir)]) 116 | 117 | def snapshot(self): 118 | sel = pm.selected() 119 | dst = self.dstOpts.getValue() 120 | fmt = self.fmtOpts.getValue() 121 | size = self.sizeField.getValue() 122 | aa = self.antiAliasCheck.getValue() 123 | snapshot(sel, dst, fmt, size, aa) 124 | 125 | 126 | def snapshot(objs, dst, fmt, size, aa): 127 | """ 128 | Snapshot the given objects. Returns the exported images. 129 | 130 | `dst` -- destination directory for the images 131 | `fmt` -- the file format 132 | `size` -- the image resolution. should be a factor of 2 133 | `aa` -- whether to anti-alias the lines or not 134 | """ 135 | # validate params 136 | if not isinstance(objs, list): 137 | objs = [objs] 138 | if len(objs) == 0: 139 | raise ValueError("No valid objects were given") 140 | if size > 8192: 141 | raise ValueError("Size is too large ({0}). Limit is 8192".format(size)) 142 | # save sel 143 | prevSel = pm.selected() 144 | result = [] 145 | projDir = pm.workspace(q=True, fn=True) 146 | outDir = os.path.join(projDir, dst) 147 | for obj in objs: 148 | pm.select(obj) 149 | outName = "uvOut_{0}.{1}".format(obj.shortName().replace(":", "_"), fmt) 150 | outPath = os.path.join(outDir, outName) 151 | pm.refresh() 152 | pm.uvSnapshot(o=True, aa=aa, ff=fmt, xr=size, yr=size, n=outPath) 153 | result.append(outPath) 154 | # reselect 155 | pm.select(prevSel) 156 | # print results 157 | if len(result) == 0: 158 | print("no uv snapshots were output..") 159 | else: 160 | print("output {0} uv snapshot(s) to /{1} successfully!".format(len(result), dst)) 161 | -------------------------------------------------------------------------------- /src/boScripts/scripts/boUtilities.mel: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bohdon/boScripts/49dc6cc2558608a6ff88f87039482f2ba4dbadee/src/boScripts/scripts/boUtilities.mel -------------------------------------------------------------------------------- /src/boScripts/scripts/boZDepthShader.mel: -------------------------------------------------------------------------------- 1 | /* 2 | Z Depth Shader 3 | 0.8 4 | 5 | Copyright (c) 2010 Bohdon Sayre 6 | All Rights Reserved. 7 | bo@bohdon.com 8 | 9 | unique prefix: bzdsh 10 | 11 | Description: 12 | Creates a Z Depth Shader for all existing shaders in the scene. 13 | The shader uses samplerInfo nodes, making it Software, Mental Ray, and Renderman compatible. 14 | Preserves displacement and alpha connections for any materials that require it. 15 | Does not support fur, particles, volume, or any other special shaders. 16 | 17 | Version 0.8: 18 | > Invert Black and White option 19 | > Distance range sliders that provide instant feedback when modelviews are in texture mode 20 | > Delete Lights Option 21 | > Delete Unused Nodes option 22 | 23 | Feel free to email me with any bugs, comments, or requests! 24 | */ 25 | 26 | 27 | global proc boZDepthShader() { 28 | string $win = "bzdshWin"; 29 | if (`window -ex $win`) deleteUI -wnd $win; 30 | 31 | window -w 100 -s 1 -mxb 1 -t "Z Depth Shader 0.8" $win; 32 | 33 | string $form = `formLayout -nd 100`; 34 | checkBox -v 1 -l "Delete Unused Nodes" bzdshWin_DeleteUnusedCheck; 35 | checkBox -v 1 -l "Delete Lights" bzdshWin_DeleteLightsCheck; 36 | string $btn = `button -w 190 -h 30 -l "Create Z Shaders" -c bzdshWinCreate`; 37 | string $sep = `separator -w 190 -h 3 -st "in"`; 38 | string $txt2 = `text -l "Distance Range:"`; 39 | 40 | //check for existing setRange node 41 | float $curMinVal = 0; 42 | float $curMaxVal = 100; 43 | string $setRange = bzdshGetSetRange(); 44 | if (size($setRange)) { 45 | $curMinVal = `getAttr ($setRange+".oldMinX")`; 46 | $curMaxVal = `getAttr ($setRange+".oldMaxX")`; 47 | print ("curMinVal: "+ $curMinVal + "\n"); //pv 48 | print ("curMaxVal: "+ $curMaxVal + "\n"); //pv 49 | 50 | } 51 | floatSliderGrp -f 1 -pre 0 -min 0 -max 1000 -ss 2 -fmn -5000 -fmx 1000000 -v $curMinVal -cw2 50 10 52 | -cc "undoInfo -swf 1; bzdshSetRangeMin(#1)" 53 | -dc "undoInfo -swf 0; bzdshSetRangeMin(#1)" 54 | bzdshWin_zMinFloat; 55 | floatSliderGrp -f 1 -pre 0 -min 1 -max 1000 -ss 2 -fmn -5000 -fmx 1000000 -v $curMaxVal -cw2 50 130 56 | -cc "undoInfo -swf 1; bzdshSetRangeMax(#1)" 57 | -dc "undoInfo -swf 0; bzdshSetRangeMax(#1)" 58 | bzdshWin_zMaxFloat; 59 | checkBox -l "Invert Black and White" -cc "bzdshInvert(#1)" bzdshWin_InvertBWCheck; 60 | string $txt = `text -en 0 -al "center" -l "Disable raytracing and all passes\nbefore rendering to save render time\n(point clouds, brickmaps, etc)"`; 61 | 62 | 63 | 64 | formLayout -e 65 | -ap bzdshWin_DeleteUnusedCheck "top" 10 0 66 | -ap bzdshWin_DeleteUnusedCheck "left" -64 50 67 | 68 | -ac bzdshWin_DeleteLightsCheck "top" 6 bzdshWin_DeleteUnusedCheck 69 | -ap bzdshWin_DeleteLightsCheck "left" -64 50 70 | 71 | -ac $btn "top" 10 bzdshWin_DeleteLightsCheck 72 | -ap $btn "left" -95 50 73 | 74 | -ac $sep "top" 10 $btn 75 | -ap $sep "left" -95 50 76 | 77 | -ac $txt2 "top" 12 $sep 78 | -ap $txt2 "left" -98 50 79 | 80 | -ac bzdshWin_zMinFloat "top" 10 $txt2 81 | -ap bzdshWin_zMinFloat "left" -103 50 82 | 83 | -ac bzdshWin_zMaxFloat "top" 10 bzdshWin_zMinFloat 84 | -ap bzdshWin_zMaxFloat "left" -103 50 85 | 86 | -ac bzdshWin_InvertBWCheck "top" 6 bzdshWin_zMaxFloat 87 | -ap bzdshWin_InvertBWCheck "left" -70 50 88 | 89 | -ac $txt "top" 8 bzdshWin_InvertBWCheck 90 | -ap $txt "left" -86 50 91 | $form; 92 | 93 | window -e -w 238 -h 310 $win; 94 | showWindow $win; 95 | } 96 | 97 | 98 | /** 99 | * Retrieves the GUI settings and runs bzdshCreate 100 | **/ 101 | global proc bzdshWinCreate() { 102 | int $delUnused = `checkBox -q -v bzdshWin_DeleteUnusedCheck`; 103 | int $delLights = `checkBox -q -v bzdshWin_DeleteLightsCheck`; 104 | int $zMin = `floatSliderGrp -q -v bzdshWin_zMinFloat`; 105 | int $zMax = `floatSliderGrp -q -v bzdshWin_zMaxFloat`; 106 | int $invert = `checkBox -q -v bzdshWin_InvertBWCheck`; 107 | string $msg; 108 | 109 | $msg = bzdshCreate(); 110 | bzdshInvert($invert); 111 | bzdshSetRange($zMin, $zMax); 112 | 113 | int $delUnusedCount; 114 | if ($delUnused) { 115 | print ("// Deleting unused nodes...\n"); 116 | $delUnusedCount = MLdeleteUnused(); 117 | print "\n"; 118 | if ($delUnusedCount) { 119 | $msg += ("\\n"+$delUnusedCount+" unused node(s) deleted\\n"); 120 | } 121 | } 122 | 123 | int $delLightCount = 0; 124 | if ($delLights) { 125 | print ("// Deleting all Lights...\n"); 126 | string $lights[] = `listTransforms -lights`; 127 | if (size($lights)) { 128 | for ($light in $lights) { 129 | if (catch(`delete $light`)) { 130 | } else { 131 | $delLightCount++; 132 | }; 133 | } 134 | } 135 | if (catchQuiet(`ls -typ "RenderManEnvLightShape"`)) { 136 | print "// RenderMan plug-in not available. Skipping RenderManEnvLightShape nodes."; 137 | } else { 138 | string $lights[] = `ls -typ "RenderManEnvLightShape"`; 139 | if (size($lights)) { 140 | for ($light in $lights) { 141 | if (catch(`delete $light`)) { 142 | } else { 143 | $delLightCount++; 144 | }; 145 | } 146 | } 147 | } 148 | print "\n"; 149 | 150 | if ($delLightCount) { 151 | $msg += ("\\n"+$delLightCount+" light(s) deleted\\n"); 152 | } 153 | } 154 | 155 | 156 | string $title = "Z Depth Shaders Created"; 157 | string $btn = "Ok"; 158 | 159 | evalDeferred("confirmDialog -b \""+$btn+"\" -db \""+$btn+"\" -cb \""+$btn+"\" -m \""+$msg+"\" -t \""+$title+"\""); 160 | } 161 | 162 | 163 | /** 164 | * Creates a shader for rendering z depth passes. 165 | * 1. Find all shading groups in the scene 166 | * 2. Find shading groups whose materials have no alpha values or displacement shaders 167 | * 4. Assign the default zShader material to those objects 168 | * 5. For the remaining materials/shading groups, create a material for each material, 169 | * and transfer the belonging objects. Alpha values/displacement shaders must be 170 | * transferred. 171 | * 6. Delete unused nodes. 172 | * 173 | * Renderman specific: 174 | * 7. Check for env lights, and rman passes and ask to disable them 175 | **/ 176 | 177 | global proc string bzdshCreate() { 178 | //get all shading groups, then filter the lists 179 | string $sgs[] = bzdshGetSGs(); 180 | $sgs = bzdshRemoveEmptySGs($sgs); 181 | string $plainSGs[] = bzdshGetCleanSGs($sgs); 182 | 183 | 184 | //create default zShader 185 | string $zShader[] = bzdshCreateDefaultZShader(); 186 | for ($sg in $plainSGs) { 187 | string $objs[] = bzdshGetMembers($sg); 188 | for ($obj in $objs) 189 | catch(`sets -e -fe $zShader[1] $obj`); 190 | } 191 | 192 | 193 | //get the outplug of the last node in the zShader chain, for reuse 194 | string $out = bzdshGetFinalOut(); 195 | //create materials for all special mats 196 | string $specialSGs[] = stringArrayRemove($plainSGs, $sgs); 197 | string $dispSGs[]; 198 | string $transSGs[]; 199 | for ($sg in $specialSGs) { 200 | //create the shader 201 | string $newShader[] = bzdshCreateSpecialShader($sg, $out); 202 | if ($newShader[2]) 203 | $dispSGs[size($dispSGs)] = $newShader[0]; 204 | if ($newShader[3]) 205 | $transSGs[size($transSGs)] = $newShader[0]; 206 | //move all objects to the new shading group 207 | string $objs[] = bzdshGetMembers($sg); 208 | for ($obj in $objs) 209 | sets -e -fe $newShader[1] $obj; 210 | } 211 | 212 | //returns a message formatted for a confirmDialog 213 | int $shaderCount = size($specialSGs) + 1; 214 | string $msg = (""+$shaderCount+" Z Depth shader(s) created successfully.\\n"); 215 | if (size($dispSGs)) { 216 | $msg += ("\\n"+(size($dispSGs))+" displacement shaders preserved:\\n"); 217 | for ($sg in $dispSGs) 218 | $msg += (" "+$sg+"\\n"); 219 | } 220 | if (size($transSGs)) { 221 | $msg += ("\\n"+(size($transSGs))+" transparent shaders preserved:\\n"); 222 | for ($sg in $transSGs) 223 | $msg += (" "+$sg+"\\n"); 224 | } 225 | return $msg; 226 | } 227 | 228 | 229 | 230 | /** Create the default bzdsh material and shading group **/ 231 | global proc string[] bzdshCreateDefaultZShader() { 232 | string $mat = "zShader_mat"; 233 | string $sg = "zShader_SG"; 234 | 235 | //check if the default z shader has already been created. 236 | if (size(`ls "*.bzdshShaderMat"`)) { 237 | if (size(`ls "*.bzdshShaderEngine"`)) { 238 | print ("// The Default zShader already exists.\n"); 239 | return {$mat, $sg}; 240 | } 241 | } 242 | 243 | //create material and shading group 244 | $mat = `shadingNode -asShader surfaceShader -n $mat`; 245 | addAttr -ln "bzdshShaderMat" -at long $mat; 246 | $sg = `sets -renderable true -noSurfaceShader true -empty -name $sg`; 247 | addAttr -ln "bzdshShaderEngine" -at long $sg; 248 | connectAttr -f ($mat+".outColor") ($sg+".surfaceShader"); 249 | 250 | //create samplerInfo > mult > setRange > remap > blend 251 | string $sampler = `shadingNode -asUtility samplerInfo -n "zSamplerInfo"`; 252 | string $mult = `shadingNode -asUtility multiplyDivide -n "zMultiply"`; 253 | string $setRange = `shadingNode -asUtility setRange -n "zSetRange"`; 254 | string $remap = `shadingNode -asUtility remapValue -n "zRemapValue"`; 255 | string $blend = `shadingNode -asUtility blendColors -n "zBlendColors"`; 256 | addAttr -ln "bzdshSamplerInfo" -at long $sampler; 257 | addAttr -ln "bzdshMultiply" -at long $mult; 258 | addAttr -ln "bzdshSetRange" -at long $setRange; 259 | addAttr -ln "bzdshRemapValue" -at long $remap; 260 | addAttr -ln "bzdshBlendColors" -at long $blend; 261 | 262 | setAttr ($mult+".operation") 1; 263 | setAttr ($mult+".input2X") -1; 264 | setAttr ($setRange+".maxX") 1; 265 | setAttr ($blend+".color1") -type double3 0 0 0; 266 | setAttr ($blend+".color2") -type double3 1 1 1; 267 | 268 | connectAttr -f ($sampler+".pointCameraZ") ($mult+".input1X"); 269 | connectAttr -f ($mult+".outputX") ($setRange+".valueX"); 270 | connectAttr -f ($setRange+".outValue.outValueX") ($remap+".inputValue"); 271 | connectAttr -f ($remap+".outValue") ($blend+".blender"); 272 | connectAttr ($blend+".outputR") ($mat+".outColorR"); 273 | connectAttr ($blend+".outputR") ($mat+".outColorG"); 274 | connectAttr ($blend+".outputR") ($mat+".outColorB"); 275 | connectAttr ($blend+".outputR") ($mat+".bzdshShaderMat"); 276 | 277 | return {$mat, $sg}; 278 | } 279 | 280 | global proc string[] bzdshCreateSpecialShader(string $ssg, string $out) { 281 | 282 | string $smat = bzdshGetMat($ssg); 283 | int $hasDisp, $hasTrans; 284 | 285 | string $matSuffix = `substitute "^z_" $smat ""`; 286 | $matSuffix = boValidateObjectName($matSuffix); 287 | string $sgSuffix = `substitute "^z_" $ssg ""`; 288 | $sgSuffix = boValidateObjectName($sgSuffix); 289 | 290 | string $mat = "z_"+$matSuffix; 291 | $mat = `shadingNode -asShader lambert -n $mat`; 292 | string $sg = "z_"+$sgSuffix; 293 | $sg = `sets -renderable true -noSurfaceShader true -empty -name $sg`; 294 | connectAttr -f ($mat+".outColor") ($sg+".surfaceShader"); 295 | setAttr ($mat+".color") -type "double3" 0 0 0; 296 | setAttr ($mat+".diffuse") 0; 297 | connectAttr -f $out ($mat+".incandescenceR"); 298 | connectAttr -f $out ($mat+".incandescenceG"); 299 | connectAttr -f $out ($mat+".incandescenceB"); 300 | 301 | //connect displ shaders if any 302 | string $displs[] = `listConnections($ssg+".displacementShader")`; 303 | if (size($displs)) { 304 | print ("// copying displacement shader from "+$ssg+" to "+$sg+"\n"); 305 | connectAttr -f ($displs[0]+".displacement") ($sg+".displacementShader"); 306 | $hasDisp = 1; 307 | } 308 | 309 | //check for transparency value and connections 310 | string $attrs[] = {"transparency", "transparencyR", "transparencyG", "transparencyB"}; 311 | if (!attributeExists ($attrs[0], $smat)) 312 | $attrs = {"outTransparency", "outTransparencyR", "outTransparencyG", "outTransparencyB"}; 313 | if (!attributeExists($attrs[0], $smat)) 314 | $attrs = {}; 315 | 316 | 317 | string $attrs2[] = {"transparency", "transparencyR", "transparencyG", "transparencyB"}; 318 | for ($i = 0; $i < size($attrs); $i++) { 319 | string $plugs[] = `listConnections -p 1 -s 1 -d 0 ($smat+"."+$attrs[$i])`; 320 | if (size($plugs)) { 321 | //create a reverse and a ramp, plug into the reverse, which color gains the ramp, 322 | //then plug the ramp into the incandescence 323 | string $ramp = `shadingNode -asTexture ramp`; 324 | removeMultiInstance -break true ($ramp+".colorEntryList[1]"); 325 | removeMultiInstance -break true ($ramp+".colorEntryList[2]"); 326 | connectAttr -force $out ($ramp+".colorEntryList[0].colorR"); 327 | connectAttr -force $out ($ramp+".colorEntryList[0].colorG"); 328 | connectAttr -force $out ($ramp+".colorEntryList[0].colorB"); 329 | 330 | string $reverse = `shadingNode -asUtility reverse`; 331 | connectAttr -f ($plugs[0]) ($reverse+".input"); 332 | connectAttr -f ($reverse+".output") ($ramp+".colorGain"); 333 | disconnectAttr ($out) ($mat+".incandescenceR"); 334 | disconnectAttr ($out) ($mat+".incandescenceG"); 335 | disconnectAttr ($out) ($mat+".incandescenceB"); 336 | connectAttr -f ($ramp+".outColor") ($mat+".incandescence"); 337 | 338 | connectAttr -f ($plugs[0]) ($mat+".transparency"); 339 | $hasTrans = 1; 340 | } 341 | } 342 | 343 | if (size($attrs) > 1) { 344 | for ($i = 1; $i < size($attrs); $i++) { 345 | float $trans = `getAttr ($smat+"."+$attrs[$i])`; 346 | if ($trans != 0 && `getAttr -se ($smat+"."+$attrs[$i])`) { 347 | setAttr ($mat+"."+$attrs2[$i]) $trans; 348 | $hasTrans = 1; 349 | } 350 | } 351 | } else if (size($attrs) == 1) { 352 | print ("1: "); 353 | print $attrs; 354 | float $trans = `getAttr ($smat+"."+$attrs[0])`; 355 | if ($trans != 0 && `getAttr -se ($smat+"."+$attrs[0])`) { 356 | setAttr ($mat+"."+$attrs2[0]) $trans; 357 | setAttr ($mat+"."+$attrs2[1]) $trans; 358 | setAttr ($mat+"."+$attrs2[2]) $trans; 359 | $hasTrans = 1; 360 | } 361 | } 362 | 363 | return {$mat, $sg, $hasDisp, $hasTrans}; 364 | } 365 | 366 | 367 | /** Sets the min and max distance of the z depth shader **/ 368 | global proc bzdshSetRange(float $min, float $max) { 369 | string $setRange = bzdshGetSetRange(); 370 | if (size($setRange)) { 371 | setAttr ($setRange+".oldMinX") $min; 372 | setAttr ($setRange+".oldMaxX") $max; 373 | } 374 | } 375 | global proc bzdshSetRangeMin(float $min) { 376 | string $setRange = bzdshGetSetRange(); 377 | if (size($setRange)) { 378 | setAttr ($setRange+".oldMinX") $min; 379 | } 380 | } 381 | global proc bzdshSetRangeMax(float $max) { 382 | string $setRange = bzdshGetSetRange(); 383 | if (size($setRange)) { 384 | setAttr ($setRange+".oldMaxX") $max; 385 | } 386 | } 387 | /** sets the color 1 and 2 of the blendColors node for an easy invert **/ 388 | global proc bzdshInvert(int $invert) { 389 | string $blend = bzdshGetBlend(); 390 | if (size($blend)) { 391 | setAttr ($blend+".color1") -type double3 $invert $invert $invert; 392 | setAttr ($blend+".color2") -type double3 (!$invert) (!$invert) (!$invert); 393 | } 394 | } 395 | 396 | 397 | 398 | 399 | /** Returns the out plug of the last node in the zShader tree **/ 400 | global proc string bzdshGetFinalOut() { 401 | string $mat[] = `ls "*.bzdshShaderMat"`; 402 | if (!size($mat)) 403 | return "-1"; 404 | string $plugs[] = `listConnections -p 1 -s 1 -d 0 $mat[0]`; 405 | if (!size($plugs)) 406 | return "-2"; 407 | 408 | return $plugs[0]; 409 | } 410 | /** Finds the zSetRange node, if it exists **/ 411 | global proc string bzdshGetSetRange() { 412 | string $ls[] = `ls "*.bzdshSetRange"`; 413 | if (!size($ls)) 414 | return ""; 415 | string $setRange = `match "^[^\.]*" $ls[0]`; 416 | return $setRange; 417 | } 418 | /** Finds the blend node, if it exists **/ 419 | global proc string bzdshGetBlend() { 420 | string $ls[] = `ls "*.bzdshBlendColors"`; 421 | if (!size($ls)) 422 | return ""; 423 | string $blend = `match "^[^\.]*" $ls[0]`; 424 | return $blend; 425 | } 426 | 427 | 428 | 429 | /** 430 | * Returns a list of shading engines in the scene 431 | * Only finds shaders that have set members 432 | **/ 433 | global proc string[] bzdshGetSGs() { 434 | string $sgs[] = `ls -typ "shadingEngine"`; 435 | 436 | string $invalidMatTypes[] = {"displacementShader", "particleCloud", "shaderGlow", "RenderManVolume", "envFog", "lightFog", "volumeFog", "volumeShader", "fluidShape"}; 437 | 438 | for ($i = size($sgs)-1; $i >= 0; $i--) { 439 | string $mat = bzdshGetMat($sgs[$i]); 440 | string $nodeType = `nodeType $mat`; 441 | 442 | if (stringArrayContains($nodeType, $invalidMatTypes)) 443 | $sgs = stringArrayRemove({$sgs[$i]}, $sgs); 444 | } 445 | 446 | return $sgs; 447 | } 448 | 449 | /** Returns a list of sgs of which empty sets have been removed **/ 450 | global proc string[] bzdshRemoveEmptySGs(string $sgs[]) { 451 | string $cleanSGs[]; 452 | for ($sg in $sgs) { 453 | //check for empty shading group 454 | string $objs[] = bzdshGetMembers($sg); 455 | if (size($objs)) { 456 | $cleanSGs[size($cleanSGs)] = $sg; 457 | } 458 | } 459 | return $cleanSGs; 460 | } 461 | 462 | /** Returns a list of mats who have no displacement shaders or alpha maps **/ 463 | global proc string[] bzdshGetCleanSGs(string $sgs[]) { 464 | string $cleanSGs[]; 465 | 466 | for ($sg in $sgs) { 467 | //check for displacement shader 468 | if (size(`listConnections($sg+".displacementShader")`)) { 469 | continue; 470 | } 471 | 472 | //check for transparency value and connections 473 | string $mat = bzdshGetMat($sg); 474 | string $attrs[] = {"transparency", "transparencyR", "transparencyG", "transparencyB"}; 475 | if (!attributeExists ($attrs[0], $mat)) 476 | $attrs = {"outTransparency", "outTransparencyR", "outTransparencyG", "outTransparencyB"}; 477 | if (!attributeExists($attrs[0], $mat)) 478 | $attrs = {}; 479 | 480 | if (size($attrs) > 1) { 481 | float $trans[] = `getAttr ($mat+"."+$attrs[0])`; 482 | if ($trans[0] != 0 || $trans[1] != 0 || $trans[2] != 0) { 483 | continue; 484 | } 485 | 486 | if (size(`listConnections($mat+"."+$attrs[0])`)) 487 | continue; 488 | if (size(`listConnections($mat+"."+$attrs[1])`)) 489 | continue; 490 | if (size(`listConnections($mat+"."+$attrs[2])`)) 491 | continue; 492 | } else if (size($attrs)) { 493 | float $trans = `getAttr ($mat+"."+$attrs[0])`; 494 | if ($trans != 0) 495 | continue; 496 | 497 | if (size(`listConnections($mat+"."+$attrs[0])`)) 498 | continue; 499 | } 500 | 501 | $cleanSGs[size($cleanSGs)] = $sg; 502 | } 503 | 504 | return $cleanSGs; 505 | } 506 | 507 | /** Given a shading engine, returns the corresponding material, if it exists **/ 508 | global proc string bzdshGetMat(string $sg) { 509 | string $connects[] = `listConnections ($sg+".surfaceShader")`; 510 | if (size($connects)) 511 | return $connects[0]; 512 | else 513 | return ""; 514 | } 515 | 516 | /** Given a shading engine, finds the members **/ 517 | global proc string[] bzdshGetMembers(string $sg) { 518 | string $objs[] = `listConnections -sh 1 -s 1 -d 0 ($sg+".dagSetMembers")`; 519 | return $objs; 520 | } 521 | 522 | 523 | 524 | global proc string boValidateObjectName(string $name) { 525 | string $pattern = "[^1-9a-zA-Z_]"; 526 | int $i = 0; 527 | while(size(`match $pattern $name`) > 0) { 528 | $name = `substitute $pattern $name "_"`; 529 | $i++; if ($i > 1000) break; 530 | } 531 | 532 | return $name; 533 | } 534 | --------------------------------------------------------------------------------