Example #1
0
    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]
Example #2
0
    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)
Example #3
0
    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]
Example #4
0
    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)