def generate(self): """ Generate the rig. Do NOT modify any of the original bones, except for adding constraints. The main armature should be selected and active before this is called. """ bpy.ops.object.mode_set(mode='EDIT') # Create the control bones uarm = copy_bone(self.obj, self.org_bones[0], strip_org(self.org_bones[0])) farm = copy_bone(self.obj, self.org_bones[1], strip_org(self.org_bones[1])) hand = copy_bone(self.obj, self.org_bones[2], strip_org(self.org_bones[2])) # Create the hinge bones if self.org_parent != None: hinge = copy_bone(self.obj, self.org_parent, make_mechanism_name(uarm + ".hinge")) socket1 = copy_bone(self.obj, uarm, make_mechanism_name(uarm + ".socket1")) socket2 = copy_bone(self.obj, uarm, make_mechanism_name(uarm + ".socket2")) # Get edit bones eb = self.obj.data.edit_bones uarm_e = eb[uarm] farm_e = eb[farm] hand_e = eb[hand] if self.org_parent != None: hinge_e = eb[hinge] socket1_e = eb[socket1] socket2_e = eb[socket2] # Parenting farm_e.parent = uarm_e hand_e.parent = farm_e if self.org_parent != None: hinge_e.use_connect = False socket1_e.use_connect = False socket2_e.use_connect = False uarm_e.parent = hinge_e hinge_e.parent = socket2_e socket2_e.parent = None # Positioning if self.org_parent != None: center = (hinge_e.head + hinge_e.tail) / 2 hinge_e.head = center socket1_e.length /= 4 socket2_e.length /= 3 # Object mode, get pose bones bpy.ops.object.mode_set(mode='OBJECT') pb = self.obj.pose.bones uarm_p = pb[uarm] farm_p = pb[farm] hand_p = pb[hand] if self.org_parent != None: hinge_p = pb[hinge] if self.org_parent != None: # socket1_p = pb[socket1] # UNUSED socket2_p = pb[socket2] # Set the elbow to only bend on the x-axis. farm_p.rotation_mode = 'XYZ' if 'X' in self.primary_rotation_axis: farm_p.lock_rotation = (False, True, True) elif 'Y' in self.primary_rotation_axis: farm_p.lock_rotation = (True, False, True) else: farm_p.lock_rotation = (True, True, False) # Hinge transforms are locked, for auto-ik if self.org_parent != None: hinge_p.lock_location = True, True, True hinge_p.lock_rotation = True, True, True hinge_p.lock_rotation_w = True hinge_p.lock_scale = True, True, True # Set up custom properties if self.org_parent != None: prop = rna_idprop_ui_prop_get(uarm_p, "isolate", create=True) uarm_p["isolate"] = 0.0 prop["soft_min"] = prop["min"] = 0.0 prop["soft_max"] = prop["max"] = 1.0 # Hinge constraints / drivers if self.org_parent != None: con = socket2_p.constraints.new('COPY_LOCATION') con.name = "copy_location" con.target = self.obj con.subtarget = socket1 con = socket2_p.constraints.new('COPY_TRANSFORMS') con.name = "isolate_off" con.target = self.obj con.subtarget = socket1 # Driver fcurve = con.driver_add("influence") driver = fcurve.driver var = driver.variables.new() driver.type = 'AVERAGE' var.name = "var" var.targets[0].id_type = 'OBJECT' var.targets[0].id = self.obj var.targets[0].data_path = uarm_p.path_from_id() + '["isolate"]' mod = fcurve.modifiers[0] mod.poly_order = 1 mod.coefficients[0] = 1.0 mod.coefficients[1] = -1.0 # Constrain org bones to controls con = pb[self.org_bones[0]].constraints.new('COPY_TRANSFORMS') con.name = "fk" con.target = self.obj con.subtarget = uarm con = pb[self.org_bones[1]].constraints.new('COPY_TRANSFORMS') con.name = "fk" con.target = self.obj con.subtarget = farm con = pb[self.org_bones[2]].constraints.new('COPY_TRANSFORMS') con.name = "fk" con.target = self.obj con.subtarget = hand # Set layers if specified if self.layers: uarm_p.bone.layers = self.layers farm_p.bone.layers = self.layers hand_p.bone.layers = self.layers # Create control widgets create_limb_widget(self.obj, uarm) create_limb_widget(self.obj, farm) ob = create_widget(self.obj, hand) if ob != None: verts = [(0.7, 1.5, 0.0), (0.7, -0.25, 0.0), (-0.7, -0.25, 0.0), (-0.7, 1.5, 0.0), (0.7, 0.723, 0.0), (-0.7, 0.723, 0.0), (0.7, 0.0, 0.0), (-0.7, 0.0, 0.0)] edges = [(1, 2), (0, 3), (0, 4), (3, 5), (4, 6), (1, 6), (5, 7), (2, 7)] mesh = ob.data mesh.from_pydata(verts, edges, []) mesh.update() mod = ob.modifiers.new("subsurf", 'SUBSURF') mod.levels = 2 return [uarm, farm, hand]
def control(self): """ Generate the control rig. """ bpy.ops.object.mode_set(mode='EDIT') # Figure out the name for the control bone (remove the last .##) ctrl_name = re.sub("([0-9]+\.)", "", strip_org(self.org_bones[0])[::-1], count=1)[::-1] # Create the bones ctrl = copy_bone(self.obj, self.org_bones[0], ctrl_name) helpers = [] bones = [] for bone in self.org_bones: bones += [copy_bone(self.obj, bone, strip_org(bone))] helpers += [ copy_bone(self.obj, bone, make_mechanism_name(strip_org(bone))) ] # Position bones eb = self.obj.data.edit_bones length = 0.0 for bone in helpers: length += eb[bone].length eb[bone].length /= 2 eb[ctrl].length = length * 1.5 # Parent bones prev = eb[self.org_bones[0]].parent for (b, h) in zip(bones, helpers): b_e = eb[b] h_e = eb[h] b_e.use_connect = False h_e.use_connect = False b_e.parent = h_e h_e.parent = prev prev = b_e # Transform locks and rotation mode bpy.ops.object.mode_set(mode='OBJECT') pb = self.obj.pose.bones for bone in bones[1:]: pb[bone].lock_location = True, True, True if pb[self.org_bones[0]].bone.use_connect is True: pb[bones[0]].lock_location = True, True, True pb[ctrl].lock_scale = True, False, True for bone in helpers: pb[bone].rotation_mode = 'XYZ' # Drivers i = 1 val = 1.2 / (len(self.org_bones) - 1) for bone in helpers: # Add custom prop prop_name = "bend_%02d" % i prop = rna_idprop_ui_prop_get(pb[ctrl], prop_name, create=True) prop["min"] = 0.0 prop["max"] = 1.0 prop["soft_min"] = 0.0 prop["soft_max"] = 1.0 if i == 1: pb[ctrl][prop_name] = 0.0 else: pb[ctrl][prop_name] = val # Add driver if 'X' in self.primary_rotation_axis: fcurve = pb[bone].driver_add("rotation_euler", 0) elif 'Y' in self.primary_rotation_axis: fcurve = pb[bone].driver_add("rotation_euler", 1) else: fcurve = pb[bone].driver_add("rotation_euler", 2) driver = fcurve.driver driver.type = 'SCRIPTED' var = driver.variables.new() var.name = "ctrl_y" var.targets[0].id_type = 'OBJECT' var.targets[0].id = self.obj var.targets[0].data_path = pb[ctrl].path_from_id() + '.scale[1]' var = driver.variables.new() var.name = "bend" var.targets[0].id_type = 'OBJECT' var.targets[0].id = self.obj var.targets[0].data_path = pb[ctrl].path_from_id( ) + '["' + prop_name + '"]' if '-' in self.primary_rotation_axis: driver.expression = "-(1.0-ctrl_y) * bend * 3.14159 * 2" else: driver.expression = "(1.0-ctrl_y) * bend * 3.14159 * 2" i += 1 # Constraints con = pb[helpers[0]].constraints.new('COPY_LOCATION') con.name = "copy_location" con.target = self.obj con.subtarget = ctrl con = pb[helpers[0]].constraints.new('COPY_ROTATION') con.name = "copy_rotation" con.target = self.obj con.subtarget = ctrl # Constrain org bones to the control bones for (bone, org) in zip(bones, self.org_bones): con = pb[org].constraints.new('COPY_TRANSFORMS') con.name = "copy_transforms" con.target = self.obj con.subtarget = bone # Set layers for extra control bones if self.ex_layers: for bone in bones: pb[bone].bone.layers = self.ex_layers # Create control widgets w = create_widget(self.obj, ctrl) if w is not None: mesh = w.data verts = [(0, 0, 0), (0, 1, 0), (0.05, 1, 0), (0.05, 1.1, 0), (-0.05, 1.1, 0), (-0.05, 1, 0)] if 'Z' in self.primary_rotation_axis: # Flip x/z coordinates temp = [] for v in verts: temp += [(v[2], v[1], v[0])] verts = temp edges = [(0, 1), (1, 2), (2, 3), (3, 4), (4, 5), (5, 1)] mesh.from_pydata(verts, edges, []) mesh.update() for bone in bones: create_limb_widget(self.obj, bone)
def control(self): """ Generate the control rig. """ bpy.ops.object.mode_set(mode="EDIT") # Figure out the name for the control bone (remove the last .##) ctrl_name = re.sub("([0-9]+\.)", "", strip_org(self.org_bones[0])[::-1], count=1)[::-1] # Create the bones ctrl = copy_bone(self.obj, self.org_bones[0], ctrl_name) helpers = [] bones = [] for bone in self.org_bones: bones += [copy_bone(self.obj, bone, strip_org(bone))] helpers += [copy_bone(self.obj, bone, make_mechanism_name(strip_org(bone)))] # Position bones eb = self.obj.data.edit_bones length = 0.0 for bone in helpers: length += eb[bone].length eb[bone].length /= 2 eb[ctrl].length = length * 1.5 # Parent bones prev = eb[self.org_bones[0]].parent for (b, h) in zip(bones, helpers): b_e = eb[b] h_e = eb[h] b_e.use_connect = False h_e.use_connect = False b_e.parent = h_e h_e.parent = prev prev = b_e # Transform locks and rotation mode bpy.ops.object.mode_set(mode="OBJECT") pb = self.obj.pose.bones for bone in bones[1:]: pb[bone].lock_location = True, True, True if pb[self.org_bones[0]].bone.use_connect == True: pb[bones[0]].lock_location = True, True, True pb[ctrl].lock_scale = True, False, True for bone in helpers: pb[bone].rotation_mode = "XYZ" # Drivers i = 1 val = 1.2 / (len(self.org_bones) - 1) for bone in helpers: # Add custom prop prop_name = "bend_%02d" % i prop = rna_idprop_ui_prop_get(pb[ctrl], prop_name, create=True) prop["min"] = 0.0 prop["max"] = 1.0 prop["soft_min"] = 0.0 prop["soft_max"] = 1.0 if i == 1: pb[ctrl][prop_name] = 0.0 else: pb[ctrl][prop_name] = val # Add driver if "X" in self.primary_rotation_axis: fcurve = pb[bone].driver_add("rotation_euler", 0) elif "Y" in self.primary_rotation_axis: fcurve = pb[bone].driver_add("rotation_euler", 1) else: fcurve = pb[bone].driver_add("rotation_euler", 2) driver = fcurve.driver driver.type = "SCRIPTED" var = driver.variables.new() var.name = "ctrl_y" var.targets[0].id_type = "OBJECT" var.targets[0].id = self.obj var.targets[0].data_path = pb[ctrl].path_from_id() + ".scale[1]" var = driver.variables.new() var.name = "bend" var.targets[0].id_type = "OBJECT" var.targets[0].id = self.obj var.targets[0].data_path = pb[ctrl].path_from_id() + '["' + prop_name + '"]' if "-" in self.primary_rotation_axis: driver.expression = "-(1.0-ctrl_y) * bend * 3.14159 * 2" else: driver.expression = "(1.0-ctrl_y) * bend * 3.14159 * 2" i += 1 # Constraints con = pb[helpers[0]].constraints.new("COPY_LOCATION") con.name = "copy_location" con.target = self.obj con.subtarget = ctrl con = pb[helpers[0]].constraints.new("COPY_ROTATION") con.name = "copy_rotation" con.target = self.obj con.subtarget = ctrl # Constrain org bones to the control bones for (bone, org) in zip(bones, self.org_bones): con = pb[org].constraints.new("COPY_TRANSFORMS") con.name = "copy_transforms" con.target = self.obj con.subtarget = bone # Set layers for extra control bones if self.ex_layers: for bone in bones: pb[bone].bone.layers = self.ex_layers # Create control widgets w = create_widget(self.obj, ctrl) if w != None: mesh = w.data verts = [(0, 0, 0), (0, 1, 0), (0.05, 1, 0), (0.05, 1.1, 0), (-0.05, 1.1, 0), (-0.05, 1, 0)] if "Z" in self.primary_rotation_axis: # Flip x/z coordinates temp = [] for v in verts: temp += [(v[2], v[1], v[0])] verts = temp edges = [(0, 1), (1, 2), (2, 3), (3, 4), (4, 5), (5, 1)] mesh.from_pydata(verts, edges, []) mesh.update() for bone in bones: create_limb_widget(self.obj, bone)