How to use a slider value in calculations? - python

I have a piece of code which generates noise. The noise is generated inside a 0.0 to 1.0 range. As long as I set a defined number the code works. If I were to allow users to select maximum range for the number with a slider it stops working.
I have a slider which replaces the value of 1.0 inside the brightness calculation. As soon as I replace 1.0 value inside Brightness with a slider generated value called noiseAttribute the code breaks. It gives no error and technically runs but just makes the object black instead of locking the color value.
import maya.cmds as cmds
import random
import functools
colorList = cmds.ls('colorSet*')
def createUI( pWindowTitle, pNoiseVerts):
windowID = 'myWindowID'
if cmds.window( windowID, exists=True ):
cmds.deleteUI(windowID )
cmds.window( windowID, title=pWindowTitle, s=False, rtf=True )
cmds.rowColumnLayout( numberOfColumns=1, columnWidth=[(1,200)])
cmds.text(label= 'Max Value Lock')
noiseAttribute = cmds.floatSliderGrp( min=0.0, max=1.0, value=1, field=True)
cmds.button( label='Noise', command=functools.partial (addNoise) )
def cancelCallback( *pArgs ):
if cmds.window( windowID, exists=True ):
cmds.deleteUI( windowID)
cmds.button( label='Cancel', command=cancelCallback )
cmds.showWindow()
def pNoiseVerts(object, noiseAttribute):
verts = range(cmds.polyEvaluate(object, vertex=True))
random.shuffle(verts)
for vertex in verts:
cmds.select(object + '.vtx[' + str(vertex) + ']')
brightness = random.uniform(0.0, noiseAttribute)
cmds.polyColorPerVertex(rgb=(brightness, brightness, brightness))
cmds.setAttr(object + '.displayColors', True)
def addNoise(noiseAttribute, *args):
if len(colorList) > 0:
cmds.delete(colorList)
objects = cmds.ls( sl=True, long=True)
if len(objects) > 0:
setList = cmds.ls('colorSet*')
result = cmds.polyColorSet ( create=True, colorSet='colorSet#')
result = cmds.polyColorPerVertex ( rgb=[0.5,0.5,0.5])
result = cmds.polyColorSet ( create=True, colorSet='colorSet#')
for object in objects:
pNoiseVerts(object, noiseAttribute)
else:
cmds.inViewMessage (amg='Message: <hl>Please select an object first</hl>.', pos='midCenter', fade=True )
createUI( 'Config', pNoiseVerts)
As mentioned before the object turns black instead of having its max color value locked.

You dont pass any arguments with your functools
Here is one of my answer on the same topic : Need Help Making Buttons to perform for loops when you input a number
How to print the value of intField in Maya python
Maya Python - Using data from UI
You can go in my history of questions, I answered a lot about functools
import maya.cmds as cmds
import random
import functools
colorList = cmds.ls('colorSet*')
def createUI(pWindowTitle):
windowID = 'myWindowID'
if cmds.window( windowID, exists=True ):
cmds.deleteUI(windowID )
cmds.window( windowID, title=pWindowTitle, s=False, rtf=True )
cmds.rowColumnLayout( numberOfColumns=1, columnWidth=[(1,200)])
cmds.text(label= 'Max Value Lock')
noiseAttribute = cmds.floatSliderGrp( min=0.0, max=1.0, value=1, field=True)
cmds.button( label='Noise', command=functools.partial(ui_addNoise, noiseAttribute) )
def cancelCallback( *pArgs ):
if cmds.window( windowID, exists=True ):
cmds.deleteUI( windowID)
cmds.button( label='Cancel', command=cancelCallback )
cmds.showWindow()
def ui_addNoise(noiseSlider, *args):
value = cmds.floatSliderGrp(noiseSlider, q=True, value=True)
addNoise(value)
def pNoiseVerts(object, value):
verts = range(cmds.polyEvaluate(object, vertex=True))
random.shuffle(verts)
for id in verts:
# you should never select things in maya, pass it as variable :
vtx = '{}.vtx[{}]'.format(object, id)
brightness = random.uniform(0.0, value)
cmds.polyColorPerVertex(vtx, rgb=(brightness, brightness, brightness))
cmds.setAttr(object + '.displayColors', True)
def addNoise(value):
if len(colorList) > 0:
cmds.delete(colorList)
objects = cmds.ls( sl=True, long=True)
if len(objects) > 0:
setList = cmds.ls('colorSet*')
result = cmds.polyColorSet ( create=True, colorSet='colorSet#')
result = cmds.polyColorPerVertex ( rgb=[0.5,0.5,0.5])
result = cmds.polyColorSet ( create=True, colorSet='colorSet#')
for object in objects:
pNoiseVerts(object, value)
else:
cmds.inViewMessage (amg='Message: <hl>Please select an object first</hl>.', pos='midCenter', fade=True )
createUI( 'Config')

Related

Embedding visvis figure in a wx application

The code bellow try to embed visvis figure in a wx application to make a movie with 3D data. The problem is that everytime I rum the code, I get the error
"./src/unix/glx11.cpp(86): assert "xid" failed in SetCurrent(): window
must be shown" right after calling Figure = app.GetFigureClass()
self.fig = Figure(self)
I spent some time researching this error, but none of the answers suited me. Does anyone knows how to fix it?
import wx
import h5py
import numpy as np
import visvis as vv
app = vv.use('wx')
class CPlot3D (wx.Frame) :
"""
Class for plotting 3D Dirac
"""
def data_for_plotting (self, frame_number) :
"""
Load the data to be plotted for the frame with the frame_number
"""
frame = str(self.frame_names[frame_number])
return self.f[frame][...]
def draw_curent_frame (self, event=None) :
"""
Display the current frame
"""
# Load data
data = self.data_for_plotting (self.frame_number.GetValue())
try :
self.volume_plot.SetData (data)
except AttributeError :
vv.clf()
self.volume_plot = vv.volshow (data, clim=(self.global_min, self.global_max), renderStyle='mip', cm=vv.CM_JET)
a = vv.gca()
vv.ColormapEditor(a)
def GetTicks (axis_num, min_val, max_val, label_format="%.2f") :
size = data.shape[axis_num]
# Number of ticks
nticks = int(np.ceil(np.log2(size)))
nticks += 1 - nticks % 2 # Make <nticks> odd
ticks_position = np.linspace(0, size-1, nticks)
ticks_label = map( lambda x : label_format % x, np.linspace(min_val, max_val, nticks) )
return dict( zip(ticks_position, ticks_label) )
a.axis.xTicks = GetTicks(0, self.x_min, self.x_max)
a.axis.xLabel = "x (rel. units)"
a.axis.yTicks = GetTicks(1, self.y_min, self.y_max)
a.axis.yLabel = "y (rel. units)"
a.axis.zTicks = GetTicks(2, self.z_min, self.z_max)
a.axis.zLabel = "z (rel. units)"
self.fig.Draw()
def __init__ (self, parent, file_name, title="Plot Dirac 3D") :
# Open files
self.f = h5py.File (file_name, 'r')
# Extract the dimension
self.x_gridDIM = int(self.f['x_gridDIM'][...])
self.y_gridDIM = int(self.f['y_gridDIM'][...])
self.z_gridDIM = int(self.f['z_gridDIM'][...])
self.dx = self.f['dx'][...]
self.x_min = self.f['x_min'][...]
self.x_max = self.x_min + self.x_gridDIM * self.dx
self.y_min = self.f['y_min'][...]
self.y_max = self.y_min + self.y_gridDIM * self.dx
self.z_min = self.f['z_min'][...]
self.z_max = self.z_min + self.z_gridDIM * self.dx
# Collect the frame names
self.frame_names = []
for key in self.f.keys () :
try : self.frame_names.append (int(key))
except ValueError: pass
self.frame_names.sort ()
print "\nGet global maximum and minimum..."
# Find the min and max values in all the frames
for frame_number in range(len(self.frame_names)) :
data = self.data_for_plotting (frame_number)
try :
self.global_min = min( self.global_min, data.min() )
self.global_max = max( self.global_max, data.max() )
except AttributeError :
self.global_min = data.min()
self.global_max = data.max()
print "\nStart animation..."
# Create GUI
dw, dh = wx.DisplaySize()
wx.Frame.__init__ (self, parent, title=title, size=(0.4*dw, 0.6*dh) )
self.ConstructGUI ()
self.Center()
self.Show ()
wx.EVT_CLOSE(self, self.on_close)
self.On_animation_button ()
def on_close (self, event) :
try : self.animation_timer.Stop()
except AttributeError : pass
self.Destroy()
def ConstructGUI (self) :
"""
Make a GUI
"""
######################### Navigation bar ##############################
panel = wx.Panel(self)
boxsizer = wx.BoxSizer (wx.HORIZONTAL)
# Frame number indicator
boxsizer.Add (wx.StaticText(panel, label="Frame Number:"))
self.frame_number = wx.SpinCtrl (panel, value="0", min=0, max=len(self.frame_names)-1)
self.frame_number.Bind (wx.EVT_SPINCTRL, self.draw_curent_frame )
boxsizer.Add (self.frame_number)
# Go to the beginning button
self.go_beginnign_button = wx.Button (panel, label="<<")
self.Bind (wx.EVT_BUTTON, self.go_to_beginning, self.go_beginnign_button)
boxsizer.Add (self.go_beginnign_button)
# Animation button
self.animation_button_start_label = "Play animation "
self.animation_button_stop_label = "STOP animation"
self.animation_button = wx.Button (panel, label=self.animation_button_start_label)
self.Bind (wx.EVT_BUTTON, self.On_animation_button, self.animation_button)
boxsizer.Add (self.animation_button)
# Go to the end button
self.go_end_button = wx.Button (panel, label=">>")
self.Bind (wx.EVT_BUTTON, self.go_to_end, self.go_end_button)
boxsizer.Add (self.go_end_button)
panel.SetSizer (boxsizer)
############################# Setting up visvis binding #######################################
Figure = app.GetFigureClass()
self.fig = Figure(self)
################################### Layout #####################################################
sizer = wx.BoxSizer (wx.VERTICAL)
sizer.Add (panel, flag=wx.CENTER)
sizer.Add(self.fig._widget, 1, flag=wx.EXPAND)
self.SetSizer(sizer)
self.SetAutoLayout(True)
self.Layout()
def On_animation_button (self, event=None) :
"""
<self.animation_button> was clicked
"""
if self.animation_button.GetLabel() == self.animation_button_start_label :
# Begin playing animation
# Set up timer for animation
timer_id = wx.NewId ()
self.animation_timer = wx.Timer (self, timer_id)
self.animation_timer.Start (200)
def on_animation_timer (event) :
self.draw_curent_frame()
position = self.frame_number.GetValue()
if position > len(self.frame_names)-2 : self.On_animation_button ()
else : self.frame_number.SetValue (position+1)
wx.EVT_TIMER (self, timer_id, on_animation_timer)
# Channing the button's label
self.animation_button.SetLabel(self.animation_button_stop_label)
else : # Stop playing animation
self.animation_timer.Stop ()
del self.animation_timer
# Channing the button's label
self.animation_button.SetLabel(self.animation_button_start_label)
def go_to_beginning (self, event) :
"""
<self.go_beginnign_button> was clicked
"""
self.frame_number.SetValue (0)
self.draw_curent_frame()
def go_to_end (self, event) :
"""
<self.go_end_button> was clicked
"""
self.frame_number.SetValue (len(self.frame_names)-1)
self.draw_curent_frame()
if __name__ == '__main__' :
import sys
app.Create()
# Loading files
if len(sys.argv) <> 2 :
openFileDialog = wx.FileDialog(None, "Open HDF5 file to load 3D Dirac", "", "",
"HDF5 files (*.hdf5)|*.hdf5", wx.FD_OPEN | wx.FD_FILE_MUST_EXIST | wx.FD_CHANGE_DIR)
# Check whether user canceled
if openFileDialog.ShowModal() == wx.ID_CANCEL:
print "Error: file name is needed as argument"
exit()
else : filename = openFileDialog.GetPath()
else : filename = sys.argv[1]
CPlot3D (None, filename)
app.Run ()
When you call On_animation_button() manually, your frame is not actually shown yet, even though you had called Show() on it because, at least with X11, showing happens asynchronously. So you need to delay calling it until later. This can be done by e.g. binding a lambda doing this to EVT_SIZE event (because by the time you get it, the window is already initialized) or just by using CallAfter().

How to keep locator at the centre of parents when deleting parent constraint in python

import maya.cmds as cmds
sel = cmds.ls(sl = True)
cmds.spaceLocator(n = 'driver')
for i in sel:
cmds.parentConstraint(i, 'driver', n = 'delPs', mo = False)
#until this line, the 'driver' keeps its position at the centre of i
cmds.delete('delPs')
#after this line, the 'driver' moves to the pivot point of the last item on the selection.
I'm trying to keep locator(driver) at the centre of the selected objects after delete constraint node.Can I get some advise?
im not sure to understand your problem but here is some solutions, hope one will help you, im using math instead of constraint
from __future__ import division
import maya.cmds as cmds
# =========================
#just to illustrate an exemple selection of 10 sphere combined
import random
psph = [cmds.polySphere()[0] for i in range(4)]
for i in psph:
cmds.setAttr(i+'.t', random.uniform(0.0, 10), random.uniform(0.0, 10), random.uniform(0.0, 10))
# sph_comb = cmds.polyUnite(psph)
cmds.delete(psph , ch=True)
# ===============================
def getCentroid(sel):
obj = cmds.ls(sel, o=True)
sel = cmds.polyListComponentConversion(sel, tv=True)
sel = cmds.ls(sel, flatten=1)
if len(obj) > 1:
pos = []
for s in sel:
p = cmds.xform(s, q=1, t=1, ws=1)
pos += p
else:
pos = cmds.xform(sel, q=1, t=1, ws=1)
nb = len(sel)
myCenter = sum(pos[0::3]) / nb, sum(pos[1::3]) / nb, sum(pos[2::3]) / nb
return myCenter
# example for each sphere
sel= cmds.ls(psph)
for i in sel:
loc = cmds.spaceLocator(n = 'driver')[0]
coord = getCentroid(i)
cmds.setAttr(loc+'.t', *coord)
# for only one at the center of all sphres
sel= cmds.ls(psph)
coord = getCentroid(sel)
loc = cmds.spaceLocator()[0]
cmds.setAttr(loc+'.t', *coord)
EDIT : fix some code issue on my function getCentroid because xform can get multiple object

Python OGR: Finding bad spot in source code for code displacement

I've tried to adapt a python ogr script which displaces points too near to each other (originally from http://wiki.gis-lab.info/w/Displacement_of_points_with_same_coordinates,_ShiftPoints/OGR for python2) to Python3. I've also changed the GDAL driver from Shapefile to GeoJSON:
#!/usr/bin/env python
import sys
import math
from itertools import cycle
from optparse import OptionParser
try:
from osgeo import ogr
except ImportError:
import ogr
driverName = "GeoJSON"
class progressBar( object ):
'''Class to display progress bar
'''
def __init__( self, maximum, barLength ):
'''Init progressbar instance.
#param maximum maximum progress value
#param barLength length of the bar in characters
'''
self.maxValue = maximum
self.barLength = barLength
self.spin = cycle(r'-\|/').__next__
self.lastLength = 0
self.tmpl = '%-' + str( barLength ) + 's ] %c %5.1f%%'
sys.stdout.write( '[ ' )
sys.stdout.flush()
def update( self, value ):
'''Update progressbar.
#param value Input new progress value
'''
# Remove last state.
sys.stdout.write( '\b' * self.lastLength )
percent = value * 100.0 / self.maxValue
# Generate new state
width = int( percent / 100.0 * self.barLength )
output = self.tmpl % ( '-' * width, self.spin(), percent )
# Show the new state and store its length.
sys.stdout.write( output )
sys.stdout.flush()
self.lastLength = len( output )
def __log( msg, abort = True, exitCode = 1 ):
''' display log message and abort execution
#param msg message to display
#param abort abort program execution or no. Default: True
#param exitCode exit code passed to sys.exit. Default: 1
'''
print(msg)
if abort:
sys.exit( exitCode )
def doDisplacement( src, dst, radius, rotate, logFile = None, logField = None ):
''' read source file and write displacement result to output file
#param src source shapefile
#param dst destination shapefile
#param radius displacement radius
#param rotate flag indicates rotate points or no
'''
# try to open source shapefile
inShape = ogr.Open( src, False )
if inShape is None:
__log( "Unable to open source shapefile " + src )
print(inShape)
inLayer = inShape.GetLayer( 0 )
print(inLayer)
print(inLayer.GetGeomType())
if inLayer.GetGeomType() not in [ ogr.wkbPoint, ogr.wkbPoint25D ]:
__log( "Input layer should be point layer." )
print(inLayer.GetFeatureCount())
if inLayer.GetFeatureCount() == 0:
__log( "There are no points in given shapefile." )
drv = ogr.GetDriverByName( driverName )
if drv is None:
__log( "%s driver not available." % driverName )
crs = inLayer.GetSpatialRef()
# initialize output shapefile
outShape = drv.CreateDataSource( dst )
if outShape is None:
__log( "Creation of output file %s failed." % dst )
outLayer = outShape.CreateLayer( "point", crs, ogr.wkbPoint )
if outLayer is None:
__log( "Layer creation failed." )
# create fields in output layer
logIndex = 0
featDef = inLayer.GetLayerDefn()
for i in range( featDef.GetFieldCount() ):
fieldDef = featDef.GetFieldDefn( i )
if logField and logField.lower() == fieldDef.GetNameRHef().lower():
logIndex = i
if outLayer.CreateField ( fieldDef ) != 0:
__log( "Creating %s field failed." % fieldDef.GetNameRef() )
__log( "Search for overlapped features", abort = False )
cn = 0
pb = progressBar( inLayer.GetFeatureCount(), 65 )
# find overlapped points
displacement = dict()
inLayer.ResetReading()
inFeat = inLayer.GetNextFeature()
while inFeat is not None:
wkt = inFeat.GetGeometryRef().ExportToWkt()
print(wkt)
if wkt not in displacement:
lst = [ inFeat.GetFID() ]
displacement[ wkt ] = lst
else:
lst = displacement[ wkt ]
j = [ inFeat.GetFID() ]
j.extend( lst )
displacement[ wkt ] = j
cn += 1
pb.update( cn )
inFeat = inLayer.GetNextFeature()
__log( "\nDisplace overlapped features", abort = False )
cn = 0
pb = progressBar( len( displacement ), 65 )
lineIds = []
lineValues = []
lines = []
pc = 0
# move overlapped features and write them to output file
for k, v in displacement.items():
featNum = len( v )
if featNum == 1:
f = inLayer.GetFeature( v[ 0 ] )
if outLayer.CreateFeature( f ) != 0:
__log( "Failed to create feature in output shapefile." )
else:
pc += featNum
fullPerimeter = 2 * math.pi
angleStep = fullPerimeter / featNum
if featNum == 2 and rotate:
currentAngle = math.pi / 2
else:
currentAngle = 0
for i in v:
sinusCurrentAngle = math.sin( currentAngle )
cosinusCurrentAngle = math.cos( currentAngle )
dx = radius * sinusCurrentAngle
dy = radius * cosinusCurrentAngle
ft = inLayer.GetFeature( i )
lineIds.append( str( ft.GetFID() ) )
lineValues.append( ft.GetFieldAsString( logIndex ) )
geom = ft.GetGeometryRef()
x = geom.GetX()
y = geom.GetY()
pt = ogr.Geometry( ogr.wkbPoint )
pt.SetPoint_2D( 0, x + dx, y + dy )
f = ogr.Feature( outLayer.GetLayerDefn() )
f.SetFrom( ft )
f.SetGeometry( pt )
if outLayer.CreateFeature( f ) != 0:
__log( "Failed to create feature in output shapefile." )
f.Destroy()
currentAngle += angleStep
# store logged info
lines.append( ";".join( lineIds ) + "(" + ";".join( lineValues ) + ")\n" )
lineIds = []
lineValues = []
cn += 1
pb.update( cn )
# cleanup
print("\nPoints displaced: %d\n" % pc)
inShape = None
outShape = None
# write log
if logFile:
fl = open( logFile, "w" )
fl.writelines( lines )
fl.close()
if __name__ == '__main__':
parser = OptionParser( usage = "displacement.py [OPTIONS] INPUT OUTPUT",
version = "%prog v0.1",
description = "Shift overlapped points so all of them becomes visible",
epilog = "Experimental version. Use at own risk." )
parser.add_option( "-d", "--distance", action="store", dest="radius",
default=0.015, metavar="DISTANCE", type="float",
help="displacement distanse [default: %default]" )
parser.add_option( "-r", "--rotate", action="store_true", dest="rotate",
default=False, help="place points horizontaly, if count = 2 [default: %default]" )
parser.add_option( "-l", "--log", action="store", dest="logFile",
metavar="FILE",
help="log overlapped points to file [default: %default]. Makes no sense without '-f' option" )
parser.add_option( "-f", "--field", action="store", dest="logField",
metavar="FIELD",
help="Shape field that will be logged to file. Makes no sense without '-l' option" )
( opts, args ) = parser.parse_args()
if len( args ) != 2:
parser.error( "incorrect number of arguments" )
if opts.logFile and opts.logField:
doDisplacement( args[ 0 ], args[ 1 ], opts.radius, opts.rotate, opts.logFile, opts.logField )
else:
doDisplacement( args[ 0 ], args[ 1 ], opts.radius, opts.rotate )
The script
finds displacement candidates by drawing a circle around each point
calculates the angle depending on the number of points to displace (e.g. 2 - 0 & 180)
moves the points
I'm using this input file. Executing python displacement.py input.geojson output.geojson -d 100 should displace all points, but there are always 0 points displaced.
May you please help me finding out the cause?
There is not bad spot in this code, it does exactly what it says it does.
It only displaces points which have the exact same coordinates. Your file has different coordinates. I tried it with a shapefile with the same coordinates, and it worked fine.
I guess you'll have to look for another solution.

How to select new generated node using Python in Maya?

I am trying to create an automation to copy a shape by wrapping a polygon face to another polygon shape
# This script wrap a polygon face to the targeted terrain
import maya.cmds as cmds
# select terrain first, then the face
cmds.select( 'terrain', r = True )
cmds.select( 'face', add = True )
# wrapping a polygon face to the terrain
cmds.transferAttributes( transferPositions = 1 )
# NEW Node transferAttributes1 is created, change its attribute searchMethod to 1.
cmds.setAttr( 'transferAttributes1.searchMethod' , 1 )
# transferAttributes1 is generated after execution of
# cmds.transferAttributes( transferPositions = 1 ).
# The name might be different, such as transferAttributes2, transferAttributes3, etc.
# and cmds.setAttr( 'transferAttributes1.searchMethod' , 1 ) might give errors.
My question: Is there any way to select the new transferAttributes node and pass it to cmds.setAttr()?
PS: transferAttributes*.searchMethod might work, but it will select all transferAttributes nodes.
cmds.transferAttributes will return the name of the node it creates:
cmds.select( 'terrain', r=True )
cmds.select( 'face', add=True )
new_node = cmds.transferAttributes( transferPositions=1 )[0]
cmds.setAttr( new_node +'.searchMethod' , 1 )
import maya.cmds as cmds
cmds.select( 'terrain1', r=True )
cmds.select( 'face1', add=True )
cmds.transferAttributes( transferPositions=1 )
#select every transferAttributes Node and store them in a list.
selection = cmds.ls('transferAttributes*');
#sort the list.
selection.sort()
#select the last element from the list, thus the most recent node
key = selection[-1]
cmds.setAttr( key+'.searchMethod' , 1 )

Renaming and Locators positioning on Joints

I am trying to get this renaming working as the locators are being duplicated and moved to the position of the joints.
For example, if I have a thigh_jnt, knee_jnt, ankle_jnt, the created locators will be named loc_thigh_jnt, loc_knee_jnt etc
However it is not working for me, as I am getting errors such as # ValueError: No object matches name: loc_0 #
Needless to say, the locator may be created but it is not at the position of the joint.
Also, can I ask if it is possible to create the locator for all the joint? Currently it is only creating for the thigh and knee but not the ankle
import maya.cmds as cmds
def createLoc():
cmds.select( cmds.listRelatives( type = 'joint', fullPath = True, allDescendents = True ) )
cmds.select( cmds.listRelatives( parent = True, fullPath = True ) )
sel = cmds.ls ( selection = True, type = 'joint' )
if not sel :
cmds.warning( "Please select a joint / No joints in selection " )
return
locGrp = cmds.group(n="loc_Grp_#", em=True)
cmds.addAttr ( locGrp, attributeType = 'double' , longName = 'locScale' , defaultValue = 1.0 , keyable = 1 )
masterLoc = cmds.spaceLocator(n="loc_0")[0]
cmds.parent( masterLoc, locGrp )
for attr in ["scaleZ", "scaleY", "scaleX"]:
cmds.connectAttr ( locGrp + ".locScale" , "%s.%s" % ( masterLoc, attr ) )
for jnt in sel:
print jnt
coords = cmds.xform ( jnt, query = True, worldSpace = True, pivots = True )[0:3]
cmds.select( masterLoc, replace = True )
cmds.duplicate( returnRootsOnly = True , inputConnections = True )
# This is where the errors starts
#cmds.rename(str(masterLoc), ("loc_" + str(sel)))
cmds.move( coords[0], coords[1], coords[2], rotatePivotRelative = True )
Here is your code snippet with some modifications and corrections to make it work.
import maya.cmds as cmds
def createLoc():
cmds.select( cmds.listRelatives( type='joint', fullPath=True, allDescendents=True ), add=True )
cmds.select( cmds.listRelatives( parent=True, fullPath=True ), add=True )
sel = cmds.ls ( selection = True, type = 'joint' )
if not sel :
cmds.warning( "Please select a joint / No joints in selection " )
return
locGrp = cmds.group(n="loc_Grp_#", em=True)
cmds.addAttr ( locGrp, attributeType='double' , longName='locScale' , defaultValue=1.0 , keyable=1 )
masterLoc = cmds.spaceLocator(n="loc_0")[0]
cmds.parent( masterLoc, locGrp )
for attr in ["scaleZ", "scaleY", "scaleX"]:
cmds.connectAttr ( locGrp + ".locScale" , "%s.%s" % ( masterLoc, attr ) )
is_root_loop = True
loc_to_rename = masterLoc
for jnt in sel:
print jnt
coords = cmds.xform ( jnt, query=True, worldSpace=True, pivots=True )[0:3]
cmds.select( masterLoc, replace=True )
if not is_root_loop:
loc_to_rename = cmds.duplicate( returnRootsOnly=True , inputConnections=True )[0]
# No more errors!
renamed_loc = cmds.rename(str(loc_to_rename), ("loc_" + str(jnt)))
if is_root_loop:
masterLoc = renamed_loc
cmds.move( coords[0], coords[1], coords[2], rotatePivotRelative=True )
is_root_loop = False
In the first two cmds.select() calls, I added add=True flag. Without that flag, cmds.select() will assume replace=True by default. That is why your root joint was being ignored after this call.
In the for loop, the masterLoc was being duplicated N times, where N is the number of joints, thus resulting in N+1 locators (including the masterLoc). So I added the is_root_loop flag to check if the loop is running for the first time. During this run, we manipulate the masterLoc itself (without duplicating it), rename the masterLoc and store the name. From the second iteration of this loop, we use this masterLoc to duplicate and rename the duplicated locators as you had previously written.
Another change I did was storing the name of the duplicated locator
loc_to_rename = cmds.duplicate( returnRootsOnly=True , inputConnections=True )[0]
And used this to rename. That is where you were getting the errors because you were trying to rename masterLoc in every iteration.
Also, it is always important to catch the return results of commands like cmds.duplicate and cmds.rename, as the name they assign may not always be as expected, as Maya will append a number or increment the number at the end of the new name if a name clash occurs with something else in the scene.
I hope this helped!

Categories