def freeze(self, node, **kwargs): sel = selected() kwargs['rotate'] = kwargs.pop('r', kwargs.pop('rotate', True)) kwargs['scale'] = kwargs.pop('s', kwargs.pop('scale', True)) skip_locked = kwargs.pop('skip_locked', True) # Unparent all the joint's children to prevent any locked # attribute errors. children = dict([(c, c.listRelatives(allParents=True)) \ for c in node.getChildren(type=['transform', 'joint'])]) [c.setParent(world=True) for c in children.keys()] # Unlock any locked rotate or scale attributes, save their # values for later and set them to zero for now, so they # aren't affected by the freeze. atts = {} for rs in ('rotate', 'scale'): if not kwargs[rs]: continue for axis in 'xyz': a = node.attr(rs[0] + axis) if a.isLocked(): atts[a] = a.get() a.unlock() if skip_locked: a.set(0) # Perform the freeze. select(node) makeIdentity(apply=True, **kwargs) # Restore and lock any rotate or scale attributes that # were locked before. for a, v in atts.items(): if skip_locked: a.set(v) a.lock() # Restore children to their original parents and delete any # automatically-generated parent buffers. for c, parents in children.items(): p = c.getParent() c.setParent(parents) if p: delete(p) select(sel)
def __init__(self, root_cls=None, *args, **kwargs): """ Flags: - bone_radius: br (int, default:1) Sets all joints' bone radii. This flag only works if -vary_bone_radius is False. - nhpat (string, default:<nt>_<s><ss>_<n><ns>) Establishes a naming convention where 'nt' is the node type (drive or bind joint), 's' in the side, 'ss' is the side sequence, 'n' is the name and 'ns' is the name sequence. - long_bone_radius: lbr (float, default:2.0) Sets -vary_bone_radius' maximum range. This flag only works if -vary_bone_radius is True. - short_bone_radius: sbr (float, default:0.5) Sets -vary_bone_radius' minimum range. This flag only works if -vary_bone_radius is True. - test_bone_radius: tebr (bool, default:False) Tests the bone radius settings without continuing the rigging process. - tip_bone_radius: tbr (float, default:0.25) Sets all tip joints' bone radii. This flag only works if -vary_bone_radius is True. """ # Find the joint-chain's root joint. joints = ls(selection=True, type='joint') roots = [] for j in joints: while True: pj = j.listRelatives(parent=True, type='joint') if pj: j = pj[0] elif j not in roots: roots.append(j) break assert len(roots), 'Selection requires at least one joint.' # Vary bone radius. self._short_bone_radius = kwargs.pop('sbr', kwargs.pop('short_bone_radius', self._short_bone_radius)) self._long_bone_radius = kwargs.pop('lbr', kwargs.pop('long_bone_radius', self._long_bone_radius)) self._tip_bone_radius = kwargs.pop('tbr', kwargs.pop('tip_bone_radius', self._tip_bone_radius)) for r in roots: self.set_bone_length_range(r) self.set_bone_radii(r) test_bone_radius = kwargs.pop('tebr', kwargs.pop('test_bone_radius', False)) if test_bone_radius: return if not issubclass(root_cls, CharacterJoint): raise TypeError("%s class must be a subclass of %s." \ % (root_cls.__name__, CharacterJoint)) # NameHelper segments establish a naming convention for this character. self.name_helper = kwargs.pop('nh', kwargs.pop('name_helper', None)) if not self.name_helper: self.name_helper = NameHelper() # In order to distinguish the character's left and right sides, first we need to # define the character's front axis. self.front = kwargs.pop('front', 'z') for jdict in [self.drive_joints, self.bind_joints]: jdict[root_cls] = [] for i, root in enumerate(roots): # Clean-up the joint chain by freezing rotate and scale makeIdentity(root, apply=True, rotate=True, scale=True) # Recurse through the entire joint chain, assigning the appropriate # CharacterJoint class to each joint. self.drive_joints[root_cls].append(root_cls(root, self, jdict=self.drive_joints, *args, **kwargs)) self.bind_joints[root_cls].append(root_cls(root.duplicate()[0], self, jdict=self.bind_joints, *args, **kwargs)) # Recursion added joints to the lists backwards, so reverse it to # keep the joints in a top-down relationship. for jdict in [self.drive_joints, self.bind_joints]: [jdict[cls].reverse() for cls in jdict.keys()] # Change the name of the joints to something they would not use # to prevent any naming conflicts in the future. roots.extend(self.bind_joints[root_cls]) function_on_hierarchy(roots, rename, 'FooJoint#') # Name joints. for cls, dj_list in self.drive_joints.items(): for i, dj in enumerate(dj_list): while True: self.rename_part(dj) if len(ls(dj.nodeName())) == 1: bj = self.bind_joints[cls][i] dj.bind_joint = bj bj.drive_joint = dj bj.side_sequence = dj.side_sequence self.rename_part(bj) break dj.side_sequence += 1
def __init__(self, root_cls=None, *args, **kwargs): """ Flags: - bone_radius: br (int, default:1) Sets all joints' bone radii. This flag only works if -vary_bone_radius is False. - nhpat (string, default:<nt>_<s><ss>_<n><ns>) Establishes a naming convention where 'nt' is the node type (drive or bind joint), 's' in the side, 'ss' is the side sequence, 'n' is the name and 'ns' is the name sequence. - long_bone_radius: lbr (float, default:2.0) Sets -vary_bone_radius' maximum range. This flag only works if -vary_bone_radius is True. - short_bone_radius: sbr (float, default:0.5) Sets -vary_bone_radius' minimum range. This flag only works if -vary_bone_radius is True. - test_bone_radius: tebr (bool, default:False) Tests the bone radius settings without continuing the rigging process. - tip_bone_radius: tbr (float, default:0.25) Sets all tip joints' bone radii. This flag only works if -vary_bone_radius is True. """ # Find the joint-chain's root joint. joints = ls(selection=True, type='joint') roots = [] for j in joints: while True: pj = j.listRelatives(parent=True, type='joint') if pj: j = pj[0] elif j not in roots: roots.append(j) break assert len(roots), 'Selection requires at least one joint.' # Vary bone radius. self._short_bone_radius = kwargs.pop( 'sbr', kwargs.pop('short_bone_radius', self._short_bone_radius)) self._long_bone_radius = kwargs.pop( 'lbr', kwargs.pop('long_bone_radius', self._long_bone_radius)) self._tip_bone_radius = kwargs.pop( 'tbr', kwargs.pop('tip_bone_radius', self._tip_bone_radius)) for r in roots: self.set_bone_length_range(r) self.set_bone_radii(r) test_bone_radius = kwargs.pop('tebr', kwargs.pop('test_bone_radius', False)) if test_bone_radius: return if not issubclass(root_cls, CharacterJoint): raise TypeError("%s class must be a subclass of %s." \ % (root_cls.__name__, CharacterJoint)) # NameHelper segments establish a naming convention for this character. self.name_helper = kwargs.pop('nh', kwargs.pop('name_helper', None)) if not self.name_helper: self.name_helper = NameHelper() # In order to distinguish the character's left and right sides, first we need to # define the character's front axis. self.front = kwargs.pop('front', 'z') for jdict in [self.drive_joints, self.bind_joints]: jdict[root_cls] = [] for i, root in enumerate(roots): # Clean-up the joint chain by freezing rotate and scale makeIdentity(root, apply=True, rotate=True, scale=True) # Recurse through the entire joint chain, assigning the appropriate # CharacterJoint class to each joint. self.drive_joints[root_cls].append( root_cls(root, self, jdict=self.drive_joints, *args, **kwargs)) self.bind_joints[root_cls].append( root_cls(root.duplicate()[0], self, jdict=self.bind_joints, *args, **kwargs)) # Recursion added joints to the lists backwards, so reverse it to # keep the joints in a top-down relationship. for jdict in [self.drive_joints, self.bind_joints]: [jdict[cls].reverse() for cls in jdict.keys()] # Change the name of the joints to something they would not use # to prevent any naming conflicts in the future. roots.extend(self.bind_joints[root_cls]) function_on_hierarchy(roots, rename, 'FooJoint#') # Name joints. for cls, dj_list in self.drive_joints.items(): for i, dj in enumerate(dj_list): while True: self.rename_part(dj) if len(ls(dj.nodeName())) == 1: bj = self.bind_joints[cls][i] dj.bind_joint = bj bj.drive_joint = dj bj.side_sequence = dj.side_sequence self.rename_part(bj) break dj.side_sequence += 1