# =====================================
# Force Deformation Order - BETA v.1.0
# =====================================
import maya.cmds as mc
# ==============
# Window
# ==============
# If window already exists, it will be replaced by new window
FDOName = "forceDOrder_UI"
if mc.window("forceDOrder_UI", exists=True):
mc.deleteUI("forceDOrder_UI", window=True)
def FDO_UI():
# QuiCam UI
FDOWin = mc.window(FDOName, title="Force Deformation Order", menuBar=True)
parentLayout = mc.columnLayout(adj=True)
instructionMenu = mc.menu(label="Instructions")
mc.menuItem(label="Open Instruction Window", parent=instructionMenu, command="forceDeformationOrder.instructionsWindow()")
mc.setParent("..")
mc.separator(parent=parentLayout, height=10, style="in")
mc.button(parent=parentLayout, label="Load List", width=100, height=30, command="forceDeformationOrder.loadList()")
mc.separator(parent=parentLayout, height=10, style="in")
childLayout = mc.rowLayout(parent=parentLayout, numberOfColumns=2, adjustableColumn=True)
mc.textScrollList("textBox")
mc.columnLayout(parent=childLayout, adj=True)
mc.button(label="Move Up", width=100, height=40, command="forceDeformationOrder.moveUp()")
mc.button(label="Move Down", width=100, height=40, command="forceDeformationOrder.moveDown()")
mc.columnLayout(parent=parentLayout, adj=True)
mc.separator(height=10, style="in")
mc.button(label="Remove All", width=100, height=30, command="forceDeformationOrder.removeAllList()")
mc.separator(height=10, style="in")
mc.separator(height=10, style="in")
mc.button(label="Force Deformation Order", width=100, height=30, backgroundColor=[1, 0.2, 0.2], command="forceDeformationOrder.forceOrder()")
mc.showWindow(FDOWin)
# Instructions Window
def instructionsWindow():
# If window already exists, it will be replaced by new window
instructionsName = "instructWin_UI"
if mc.window("instructWin_UI", exists=True):
mc.deleteUI("instructWin_UI", window=True)
# Instructions
instructionsWin = mc.window(instructionsName, title=" FDO - Instructions")
mc.columnLayout(adj=True, width=500)
mc.text(wordWrap=True, al="center", label="1.) Select one piece of geometry to rearrange your object's deformation order.")
mc.text(wordWrap=True, al="center", label="2.) When you have made your selection, load your list and specify the order of your inputs.")
mc.text(wordWrap=True, al="center", label="3.) Once you are satisfied with the order of your list, click 'Force Deformation Order'.")
mc.text(wordWrap=True, al="center", font="boldLabelFont", label="Note: Make sure your geometry is selected before running any commands.")
mc.separator(height=10, style="in")
mc.separator(height=10, style="in")
mc.text(wordWrap=True, al="center", font="boldLabelFont", backgroundColor=[0.8, 0.35, 0.35], label="Suggestions or Comments - http://b-animated.blogspot.com/")
mc.showWindow(instructionsWin)
# ==========
# Commands
# ==========
# Load List
def loadList():
# Store geo variable for selection...
selectedGeo = mc.ls(sl=True)
# Query geometry - obtain deformer inputs
queryGeo = mc.deformer(query=True, geometry=True)
for i in queryGeo:
geoShape = i
listDeforms = mc.listSets(type=2, object=geoShape)
mc.select(listDeforms, replace=True, noExpand=True) # needs 'noExpand' for sets
masterList = []
# Check for "skinCluster" nodes...
for everySkin in listDeforms:
listConnects = mc.listConnections(everySkin, type="skinCluster")
masterList.append(listConnects)
# Check for "blendShape" nodes...
for everyBS in listDeforms:
listConnects = mc.listConnections(everyBS, type="blendShape")
masterList.append(listConnects)
# Check for "tweak" nodes...
for everyTweak in listDeforms:
listConnects = mc.listConnections(everyTweak, type="tweak")
masterList.append(listConnects)
# Delete "None" objects..
for everyNone in masterList:
masterList.remove(None) # ... run twice to make sure
masterList.remove(None)
# Add to list
mc.textScrollList("textBox", query=True, allItems=True)
for everyInput in masterList:
mc.textScrollList("textBox", edit=True, append=everyInput)
listCount = len(masterList)
mc.select(selectedGeo, replace=True) # select geo before spitting warning
mc.warning(listCount, " Deformer(s) Added To List.")
# Remove all from list
def removeAllList():
mc.textScrollList("textBox", query=True, allItems=True)
mc.textScrollList("textBox", edit=True, removeAll=True)
mc.warning("All Items Removed From List.")
# List Control
def moveUp():
# Set up index to move item up
currentIndex = mc.textScrollList("textBox", query=True, selectIndexedItem=True) # current index
selInt = currentIndex.pop() - 1 # pop 'list' out of brackets - now 'int'
# Set up string to specify which item to move up
selStr = mc.textScrollList("textBox", query=True, selectItem=True) # shape node for selected item
moveItem = [selInt] + selStr # new list
# Move item up
mc.textScrollList("textBox", edit=True, appendPosition=moveItem) # ...requires one integer value and one string
# Delete selected item to aviod duplicates
removeDup = mc.textScrollList("textBox", query=True, selectIndexedItem=True) # produce index
mc.textScrollList("textBox", edit=True, removeIndexedItem=removeDup) # remove duplicate from list
mc.textScrollList("textBox", edit=True, selectIndexedItem=selInt) # select new list item
def moveDown():
# Set up index to move item up
currentIndex = mc.textScrollList("textBox", query=True, selectIndexedItem=True) # current index
selInt = currentIndex.pop() + 2 # pop 'list' out of brackets - now 'int'
# Set up string to specify which item to move up
selStr = mc.textScrollList("textBox", query=True, selectItem=True) # shape node for selected item
moveItem = [selInt] + selStr # new list
# Move item up
mc.textScrollList("textBox", edit=True, appendPosition=moveItem) # ...requires one integer value and one string
# Delete selected item to aviod duplicates
removeDup = mc.textScrollList("textBox", query=True, selectIndexedItem=True) # produce index
mc.textScrollList("textBox", edit=True, removeIndexedItem=removeDup) # remove duplicate from list
mc.textScrollList("textBox", edit=True, selectIndexedItem=selInt -1) # select new list item
# Force order based on list
def forceOrder():
# Store geo variable for selection...
selectedGeo = mc.ls(sl=True, long=True) # GEO (long name)
# Compare new list to old defomation order
listShapes = mc.textScrollList("textBox", query=True, allItems=True) # LIST
# Convert shape nodes to transform nodes
listAll = [] # empty list
for everyItem in listShapes:
wrapQuotes = everyItem.__str__() # wrap in quotes
listAll.append(wrapQuotes) # toss everything into empty list
# Slice itemsi in 'listAll' so we are only dealing with two items at a time (needed for reorderDeformers)
splitTwo = -2 # set to -2 to set up sliceCount
for i in listAll:
splitTwo += 1 # add 1 for every iteration
sliceCount = listAll.__getslice__(splitTwo, splitTwo +2) # slice tuple
sliceTotal = len(sliceCount) # gather length
if sliceTotal == 2: # if there are 2 values returned... move forward
RDList = sliceCount.__getslice__(0,2) # isolate deformer's list - shape nodes
RDFinals = RDList[0], RDList[1], selectedGeo[0].__str__() # convert...
# *** For every tuple, run reorderDeformers command ***
RDMaster = map(str, RDFinals) # covert type tuple to list...
mc.reorderDeformers(RDMaster[0], RDMaster[1], RDMaster[2]) # * REORDER DEFORMERS *
# three values (Dform1, Dform2, geo affected) - Dform2 placed over 1
# Once order has been changed, we'll reselect geo to refresh input list
mc.select(clear=True)
mc.select(selectedGeo, replace=True)
mc.warning("Deformation Order has been rearranged.") # final warning
# Script by Bryan Godoy
# http://b-animated.blogspot.com/
# https://twitter.com/b_animates