class Component(core.Component): """A Component that creates aimConstraints.""" constraints = fields.ArrayField('constraints', add_label_text='Add Aim Constraint') container = fields.ContainerField('constraint', parent=constraints, container_view=AimConstraintView()) drivers = fields.MayaNodeField('drivers', multi=True, help_text='The nodes to aim at.', parent=container) driven = fields.MayaNodeField('driven', help_text='The node to aim', parent=container) maintain_offset = fields.BooleanField('maintain_offset', default=True, parent=container) aim_vector = fields.VectorField('aim_vector', default=(1.0, 0.0, 0.0), parent=container) up_vector = fields.VectorField('up_vector', default=(0.0, 1.0, 0.0), parent=container) world_up_type = fields.CharField( 'world_up_type', choices=['scene', 'object', 'objectrotation', 'vector', 'none'], default='object', parent=container) world_up_vector = fields.VectorField('world_up_vector', default=(0.0, 1.0, 0.0), parent=container) world_up_object = fields.MayaNodeField('world_up_object', parent=container) skip_x = fields.BooleanField('skip_x', parent=container) skip_y = fields.BooleanField('skip_y', parent=container) skip_z = fields.BooleanField('skip_z', parent=container) @classmethod def image_path(cls): return ':/aimConstraint.png' def execute(self): for container in self.constraints: drivers = container['drivers'].value() driven = container['driven'].value() skip = [ x for x in 'xyz' if container['skip_{0}'.format(x)].value() ] cmds.aimConstraint( drivers, driven, maintainOffset=container['maintain_offset'].value(), aimVector=container['aim_vector'].value(), upVector=container['up_vector'].value(), worldUpType=container['world_up_type'].value(), worldUpVector=container['world_up_vector'].value(), worldUpObject=container['world_up_object'].value(), skip=skip)
class ContainerComponent(core.Component): spheres = fields.ArrayField('spheres') container = fields.ContainerField('sphere', parent=spheres) sphere_name = fields.CharField('sphere_name', parent=container) radius = fields.FloatField('radius', default=1.0, parent=container) def execute(self): for sphere in self.spheres: name = sphere['sphere_name'].value() radius = sphere['radius'].value() cmds.polySphere(name=name, radius=radius)
class Component(core.Component): """A Component that imports or references in a Maya file.""" import_operation = 'Import' reference_operation = 'Reference' files = fields.ArrayField('files', add_label_text='Add File', display_name=False) container = fields.ContainerField('file', parent=files, container_view=FileView()) operation = fields.CharField( 'operation', choices=[import_operation, reference_operation], default=import_operation, help_text='Whether to import or reference the file.', parent=container) file_path = fields.FilePathField('file_path', filter='Maya Files (*.ma *.mb)', help_text='The Maya file path.', parent=container) namespace = fields.CharField( 'namespace', help_text='The import or reference namespace.', parent=container) @classmethod def image_path(cls): return ':/fileOpen.png' def help_url(self): return 'https://github.com/chadmv/cmt/wiki/File-Component' def execute(self): for container in self.files: operation = container['operation'].value() file_path = container['file_path'].get_path() namespace = container['namespace'].value() flag = 'i' if operation == Component.import_operation else 'r' kwargs = { flag: True, 'type': { '.ma': 'mayaAscii', '.mb': 'mayaBinary', '.fbx': 'FBX', }[os.path.splitext(file_path.lower())[-1]] } if namespace: kwargs['namespace'] = namespace cmds.file(file_path, **kwargs)
def __init__(self, file_paths=None, **kwargs): super(Component, self).__init__(**kwargs) self.array_field = fields.ArrayField(name='File Paths', add_label_text='Add Skin File') self.add_field(self.array_field) if file_paths is None: file_paths = [''] if isinstance(file_paths, basestring): file_paths = [file_paths] for file_path in file_paths: self.array_field.add_field(fields.FilePathField( name='File Path', value=file_path, filter='Skin Files (*.skin)', help_text='The Skeleton file path.'))
def __init__(self, spheres=None, **kwargs): super(ContainerComponent, self).__init__(**kwargs) self.array_field = fields.ArrayField(name='spheres') self.add_field(self.array_field) if spheres is None: spheres = [{'sphere_name': 'sphere1'}] for sphere in spheres: container = fields.ContainerField(name='sphere') self.array_field.add_field(container) container.add_field( fields.CharField(name='Sphere Name', value=sphere['sphere_name'])) container.add_field( fields.FloatField(name='Radius', value=sphere.get('radius', 1.0)))
class Component(core.Component): """A Component that imports skin weights using skinio.""" files = fields.ArrayField('files', add_label_text='Add Skin File', display_name=False) file_path = fields.FilePathField('file_path', filter='Skin Files (*.skin)', help_text='The Skeleton file path.', parent=files) @classmethod def image_path(cls): return ':/importSmoothSkin.png' def execute(self): for file_field in self.files: file_path = file_field.get_path() skinio.import_skin(file_path)
def __init__(self, constraints=None, **kwargs): """Constructor :param constraints: A list of dictionaries describing the aimConstraints that need to be created: { 'drivers': nodes, 'driven': node, 'maintainOffset': True, 'skipTranslate': ['x', 'y', 'z'] 'skipRotate': ['x', 'y', 'z'] } """ super(Component, self).__init__(**kwargs) self.constraints = fields.ArrayField( name='Parent Constraints', add_label_text='Add Parent Constraint') self.add_field(self.constraints) if not constraints: # Create default entries if none specified constraints = [{'driven': 'node'}] # The fields will be arranged in two row containers # [[driver, driven], [name, twist, swing, invertTwist, invertSwing, twistAxis]] for constraint in constraints: self.add_constraint_data(constraint)
class Component(core.Component): """A Component that creates swingTwist nodes.""" twist_axis = { 0: 'X', 1: 'Y', 2: 'Z', } swingtwists = fields.ArrayField('swing_twists', add_label_text='Add SwingTwist', display_name=False) container = fields.ContainerField('swing_twist', parent=swingtwists, container_view=SwingTwistView()) driver = fields.MayaNodeField('driver', help_text='The node to drive the swingtwist', parent=container) driven = fields.MayaNodeField('driven', help_text='The node to be driven', parent=container) name = fields.CharField( 'name', default='swingTwist#', help_text='The name of the created swingTwist node.', parent=container) twist = fields.FloatField('twist', default=1.0, help_text='The twist amount', min_value=-1.0, max_value=1.0, parent=container) swing = fields.FloatField('swing', default=1.0, help_text='The swing amount', min_value=-1.0, max_value=1.0, parent=container) twist_axis = fields.CharField('twist_axis', default='X', choices=['X', 'Y', 'Z'], help_text='The twist axis', parent=container) @classmethod def image_path(cls): return shortcuts.get_icon_path('swingTwist') def execute(self): cmds.loadPlugin('cmt_py', qt=True) for container in self.swingtwists: driver = container['driver'].value() driven = container['driven'].value() if not cmds.objExists(driver) or not cmds.objExists(driven): logger.warning('{0} or {1} does not exist.'.format( driver, driven)) continue logger.info('Creating swingtwist on {0} from {1}'.format( driven, driver)) name = container['name'].value() twist = container['twist'].value() swing = container['swing'].value() twist_axis = 'XYZ'.index(container['twist_axis'].value()) cmds.swingTwist(driver, driven, name=name, twist=twist, swing=swing, twistAxis=twist_axis)
class Component(core.Component): """A Component that creates parentConstraints.""" constraints = fields.ArrayField('constraints', add_label_text='Add Parent Constraint') container = fields.ContainerField('constraint', parent=constraints, container_view=ParentConstraintView()) drivers = fields.MayaNodeField('drivers', multi=True, help_text='The nodes to constrain to.', parent=container) driven = fields.MayaNodeField('driven', help_text='The node to constrain.', parent=container) maintain_offset = fields.BooleanField('maintain_offset', default=True, parent=container) skip_tx = fields.BooleanField('skip_tx', verbose_name='Skip tx', parent=container) skip_ty = fields.BooleanField('skip_ty', verbose_name='Skip ty', parent=container) skip_tz = fields.BooleanField('skip_tz', verbose_name='Skip tz', parent=container) skip_rx = fields.BooleanField('skip_rx', verbose_name='Skip rx', parent=container) skip_ry = fields.BooleanField('skip_ry', verbose_name='Skip ry', parent=container) skip_rz = fields.BooleanField('skip_rz', verbose_name='Skip rz', parent=container) @classmethod def image_path(cls): return ':/parentConstraint.png' def add_constraint_data(self, constraint): container = fields.ContainerField( name='constraint', parent=self.constraints, container_view=ParentConstraintView()) fields.MayaNodeField(name='drivers', value=constraint.get('drivers', []), multi=True, help_text='The nodes to constrain to.', parent=container) fields.MayaNodeField(name='driven', value=constraint.get('driven', ''), help_text='The node to constrain.', parent=container) fields.BooleanField(name='maintain_offset', value=constraint.get('maintainOffset', True), parent=container) skip = constraint.get('skipTranslate', []) fields.BooleanField(name='skip_tx', verbose_name='Skip tx', value='x' in skip, parent=container) fields.BooleanField(name='skip_ty', verbose_name='Skip ty', value='y' in skip, parent=container) fields.BooleanField(name='skip_tz', verbose_name='Skip tz', value='z' in skip, parent=container) skip = constraint.get('skipRotate', []) fields.BooleanField(name='skip_rx', verbose_name='Skip rx', value='x' in skip, parent=container) fields.BooleanField(name='skip_ry', verbose_name='Skip ry', value='y' in skip, parent=container) fields.BooleanField(name='skip_rz', verbose_name='Skip rz', value='z' in skip, parent=container) return container def widget(self): widget = self.constraints.widget() # Add a new button to the widget button_layout to add selected constraints to the UI. button = QtWidgets.QPushButton('Add from Selected') button.released.connect( partial(self.add_from_selected, field_layout=widget.field_layout)) widget.button_layout.addWidget(button) return widget def add_from_selected(self, field_layout): # Get parentConstraints from the selected nodes sel = cmds.ls(sl=True) or [] constraints = [ x for x in sel if cmds.nodeType(x) == 'parentConstraint' ] transforms = [ x for x in sel if cmds.nodeType(x) in ['transform', 'joint'] ] for transform in transforms: constraints += (cmds.listConnections(transform, type='parentConstraint') or []) constraints = list(set(constraints)) for constraint in constraints: data = constraint_data(constraint) field = self.add_constraint_data(data) self.constraints.add_element( field, field_layout) # Update the UI with the added constraint def execute(self): for container in self.constraints: drivers = container['drivers'].value() driven = container['driven'].value() skip_translate = [ x for x in 'xyz' if container['skip_t{0}'.format(x)].value() ] skip_rotate = [ x for x in 'xyz' if container['skip_r{0}'.format(x)].value() ] cmds.parentConstraint( drivers, driven, maintainOffset=container['maintain_offset'].value(), skipTranslate=skip_translate, skipRotate=skip_rotate)
def __init__(self, constraints=None, **kwargs): """Constructor :param constraints: A list of dictionaries describing the aimConstraints that need to be created: { 'drivers': nodes, 'driven': node, 'maintainOffset': True, 'aimVector': (1.0, 0.0, 0.0), 'upVector': (0.0, 1.0, 0.0), 'worldUpType': "scene", "object", "objectrotation", "vector", or "none" 'worldUpVector': node, 'worldUpObject': node, 'skip': ['x', 'y', 'z'] } """ super(Component, self).__init__(**kwargs) self.constraints = fields.ArrayField( name='Aim Constraints', add_label_text='Add Aim Constraint') self.add_field(self.constraints) if not constraints: # Create default entries if none specified constraints = [{'driven': 'node'}] # The fields will be arranged in two row containers # [[driver, driven], [name, twist, swing, invertTwist, invertSwing, twistAxis]] for constraint in constraints: container = fields.ContainerField( name='Constraint', orientation=fields.ContainerField.vertical, stretch=True) self.constraints.add_field(container) row_container = fields.ContainerField(name='', border=False) container.add_field(row_container) row_container.add_field( fields.MayaNodeField(name='Drivers', value=constraint.get('drivers', []), multi=True, help_text='The nodes to aim at.')) row_container.add_field( fields.MayaNodeField(name='Driven', value=constraint.get('driven', ''), help_text='The node to aim')) row_container.add_field( fields.BooleanField(name='Maintain offset', value=constraint.get( 'maintainOffset', True))) row_container = fields.ContainerField(name='', border=False) container.add_field(row_container) row_container.add_field( fields.VectorField(name='Aim vector', value=constraint.get( 'aimVector', (1.0, 0.0, 0.0)))) row_container.add_field( fields.VectorField(name='Up vector', value=constraint.get( 'upVector', (0.0, 1.0, 0.0)))) row_container = fields.ContainerField(name='', border=False) container.add_field(row_container) choices = ['scene', 'object', 'objectrotation', 'vector', 'none'] row_container.add_field( fields.ChoiceField(name='World up type', choices=choices, value=constraint.get('worldUpType'))) row_container.add_field( fields.VectorField(name='World up vector', value=constraint.get( 'worldUpVector', (0.0, 1.0, 0.0)))) row_container.add_field( fields.MayaNodeField(name='World up object', value=constraint.get('worldUpObject', ''))) row_container = fields.ContainerField(name='', border=False, stretch=True) container.add_field(row_container) skip = constraint.get('skip', []) row_container.add_field( fields.BooleanField(name='Skip x', value='x' in skip)) row_container.add_field( fields.BooleanField(name='Skip y', value='y' in skip)) row_container.add_field( fields.BooleanField(name='Skip z', value='z' in skip))
def __init__(self, swing_twists=None, **kwargs): """Constructor :param swing_twists: A list of dictionaries describing the swingTwist nodes that need to be created: { 'driven': node, 'driver': nodes, 'name': name, 'twist': 1.0, 'swing': 0.2, } """ super(Component, self).__init__(**kwargs) self.swingtwists = fields.ArrayField(name='Swing Twists', add_label_text='Add SwingTwist') self.add_field(self.swingtwists) if not swing_twists: # Create default entries if none specified swing_twists = [{'name': 'swingTwist#'}] twist_axes = self.twist_axis.values() twist_axes.sort() # The fields will be arranged in two row containers # [[driver, driven], [name, twist, swing, invertTwist, invertSwing, twistAxis]] for swingtwist in swing_twists: container = fields.ContainerField( name='Swing Twist', orientation=fields.ContainerField.vertical, stretch=True) self.swingtwists.add_field(container) row_container = fields.ContainerField(name='', border=False) container.add_field(row_container) row_container.add_field( fields.MayaNodeField( name='Driver', value=swingtwist.get('driver', ''), help_text='The node to drive the swingtwist')) row_container.add_field( fields.MayaNodeField(name='Driven', value=swingtwist.get('driven', ''), help_text='The node to be driven')) row_container = fields.ContainerField(name='', border=False) container.add_field(row_container) row_container.add_field( fields.CharField( name='Name', value=swingtwist.get('name', 'swingTwist#'), help_text='The name of the created swingTwist node.')) row_container.add_field( fields.FloatField(name='Twist', value=swingtwist.get('twist', 1.0), help_text='The twist amount', min_value=-1.0, max_value=1.0)) row_container.add_field( fields.FloatField(name='Swing', value=swingtwist.get('swing', 1.0), help_text='The swing amount', min_value=-1.0, max_value=1.0)) row_container.add_field( fields.ChoiceField(name='Twist Axis', value=Component.twist_axis[swingtwist.get( 'twistAxis', 0)], choices=twist_axes, help_text='The twist axis'))