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')

        # Make a control bone (copy of original).
        bone = copy_bone(self.obj, self.org_bone, self.org_name)

        # Make a deformation bone (copy of original, child of original).
        def_bone = copy_bone(self.obj, self.org_bone, make_deformer_name(self.org_name))

        # Get edit bones
        eb = self.obj.data.edit_bones
        bone_e = eb[bone]
        def_bone_e = eb[def_bone]

        # Parent
        def_bone_e.use_connect = False
        def_bone_e.parent = eb[self.org_bone]

        bpy.ops.object.mode_set(mode='OBJECT')
        pb = self.obj.pose.bones

        # Constrain the original bone.
        con = pb[self.org_bone].constraints.new('COPY_TRANSFORMS')
        con.name = "copy_loc"
        con.target = self.obj
        con.subtarget = bone

        # Create control widget
        create_bone_widget(self.obj, bone)
Example #2
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')

        # Make a control bone (copy of original).
        bone = copy_bone(self.obj, self.org_bone, self.org_name)

        # Make a deformation bone (copy of original, child of original).
        def_bone = copy_bone(self.obj, self.org_bone,
                             make_deformer_name(self.org_name))

        # Get edit bones
        eb = self.obj.data.edit_bones
        bone_e = eb[bone]
        def_bone_e = eb[def_bone]

        # Parent
        def_bone_e.use_connect = False
        def_bone_e.parent = eb[self.org_bone]

        bpy.ops.object.mode_set(mode='OBJECT')
        pb = self.obj.pose.bones

        # Constrain the original bone.
        con = pb[self.org_bone].constraints.new('COPY_TRANSFORMS')
        con.name = "copy_loc"
        con.target = self.obj
        con.subtarget = bone

        # Create control widget
        create_bone_widget(self.obj, bone)
    def create_deform(self):
        org_bones = self.org_bones

        bpy.ops.object.mode_set(mode='EDIT')

        def_bones = []
        for o in org_bones:
            def_name = make_deformer_name(strip_org(o))
            def_name = copy_bone(self.obj, o, def_name)
            def_bones.append(def_name)

        bpy.ops.object.mode_set(mode='POSE')
        # Create bbone segments
        for bone in def_bones:
            self.obj.data.bones[bone].bbone_segments = self.bbones

        if not self.SINGLE_BONE:
            self.obj.data.bones[def_bones[0]].bbone_easein = 0.0
            self.obj.data.bones[def_bones[-1]].bbone_easeout = 0.0
        else:
            self.obj.data.bones[def_bones[0]].bbone_easein = 1.0
            self.obj.data.bones[def_bones[-1]].bbone_easeout = 1.0
        bpy.ops.object.mode_set(mode='EDIT')

        conv_def = ""
        if self.params.conv_bone and self.params.conv_def:
            b = org(self.params.conv_bone)
            conv_def = make_deformer_name(strip_org(b))
            conv_def = copy_bone(self.obj, b, conv_def)

        return def_bones, conv_def
    def create_mch(self):
        bpy.ops.object.mode_set(mode='EDIT')
        edit_bones = self.obj.data.edit_bones

        main_bone_name = strip_org(self.bones['org'][0])
        mouth_lock_name = make_mechanism_name(main_bone_name + "_lock")
        mouth_lock = copy_bone(self.obj, self.main_mch, mouth_lock_name)

        self.bones['jaw_mch'] = dict()
        self.bones['jaw_mch']['mouth_lock'] = mouth_lock
        self.bones['jaw_mch']['jaw_masters'] = []

        jaw_masters_number = self.lip_len + 3

        for i in range(0, jaw_masters_number):
            jaw_m_name = make_mechanism_name("jaw_master")
            jaw_m = copy_bone(self.obj, self.main_mch, jaw_m_name)
            div_len = (edit_bones[mouth_lock].length /
                       (jaw_masters_number + 1))
            edit_bones[jaw_m].length = (jaw_masters_number - i) * div_len
            edit_bones[jaw_m].use_connect = False

            self.bones['jaw_mch']['jaw_masters'].append(jaw_m)

        # create remaining subchain mch-s
        super().create_mch()
    def create_mch(self):

        bpy.ops.object.mode_set(mode='EDIT')
        edit_bones = self.obj.data.edit_bones

        self.bones['eye_mch'] = dict()
        self.bones['eye_mch']['eyelid_top'] = []
        self.bones['eye_mch']['eyelid_bottom'] = []
        self.bones['eye_mch']['eye_master'] = ''
        self.bones['eye_mch']['eye_master_tip'] = ''

        main_bone_name = strip_org(self.bones['org'][0])
        eye_mch_name = make_mechanism_name(main_bone_name)
        eye_mch_name = copy_bone(self.obj, self.bones['org'][0], eye_mch_name)
        self.bones['eye_mch']['eye_master'] = eye_mch_name

        eye_tip_mch_name = copy_bone(self.obj, self.orientation_bone,
                                     eye_mch_name)
        self.bones['eye_mch']['eye_master_tip'] = eye_tip_mch_name
        put_bone(self.obj, eye_tip_mch_name, edit_bones[eye_mch_name].tail)
        if self.orientation_bone == self.base_bone:
            align_bone_y_axis(self.obj, eye_tip_mch_name, Vector((0, 0, 1)))
        edit_bones[
            eye_tip_mch_name].length = 0.25 * edit_bones[eye_mch_name].length

        # top lid
        top_lid_chain = self.get_chain_bones(self.lid_bones['top'][0])
        for l_b in top_lid_chain:
            lid_m_name = copy_bone(self.obj, self.bones['org'][0],
                                   eye_mch_name)
            edit_bones[lid_m_name].tail = edit_bones[l_b].tail
            self.bones['eye_mch']['eyelid_top'].append(lid_m_name)

        # bottom lid
        bottom_lid_chain = self.get_chain_bones(self.lid_bones['bottom'][0])
        for l_b in bottom_lid_chain:
            lid_m_name = copy_bone(self.obj, self.bones['org'][0],
                                   eye_mch_name)
            edit_bones[lid_m_name].tail = edit_bones[l_b].tail
            self.bones['eye_mch']['eyelid_bottom'].append(lid_m_name)

        # create mch for eye_follow driver
        if self.needs_driver:
            if self.paired_eye or self.is_clustered():
                eye_follow_mch = self.get_common_name()
            else:
                eye_follow_mch = strip_org(self.base_bone)
            eye_follow_mch = make_mechanism_name(eye_follow_mch)
            eye_follow_mch += "_parent"

            if eye_follow_mch not in edit_bones:
                parent = edit_bones[self.base_bone].parent.name
                eye_follow_mch = copy_bone(self.obj, parent, eye_follow_mch)
                edit_bones[
                    eye_follow_mch].length = 0.25 * edit_bones[parent].length
            self.bones['eye_mch']['eyefollow'] = eye_follow_mch

        super().create_mch()
Example #6
0
    def create_mch(self):
        bpy.ops.object.mode_set(mode='EDIT')
        edit_bones = self.obj.data.edit_bones

        main_bone_name = strip_org(self.bones['org'][0])
        mouth_lock_name = make_mechanism_name(main_bone_name + "_lock")
        mouth_lock = copy_bone(self.obj, self.main_mch, mouth_lock_name)

        self.bones['jaw_mch'] = dict()
        self.bones['jaw_mch']['mouth_lock'] = mouth_lock
        self.bones['jaw_mch']['jaw_masters'] = []

        jaw_masters_number = 3

        for i in range(0, jaw_masters_number):
            jaw_m_name = make_mechanism_name("jaw_master")
            jaw_m = copy_bone(self.obj, self.main_mch, jaw_m_name)
            div_len = (edit_bones[mouth_lock].length/(jaw_masters_number + 1))
            edit_bones[jaw_m].length = (jaw_masters_number - i) * div_len
            edit_bones[jaw_m].use_connect = False

            self.bones['jaw_mch']['jaw_masters'].append(jaw_m)

        self.bones['mouth_mch'] = dict()

        org_top = self.mouth_bones['top'][0]
        top_mch_name = make_mechanism_name(strip_org(org_top))
        top_mch = copy_bone(self.obj, org_top, top_mch_name)
        self.bones['mouth_mch']['top'] = [top_mch]
        edit_bones[top_mch].use_connect = False

        self.bones['mouth_mch']['corners'] = []
        for org_name in self.mouth_bones['corners']:
            mch_name = make_mechanism_name(strip_org(org_name))
            mch = copy_bone(self.obj, org_name, mch_name)
            self.bones['mouth_mch']['corners'].append(mch)
            edit_bones[mch].use_connect = False

        org_bottom = self.mouth_bones['bottom'][0]
        bottom_mch_name = make_mechanism_name(strip_org(org_bottom))
        bottom_mch = copy_bone(self.obj, org_bottom, bottom_mch_name)
        self.bones['mouth_mch']['bottom'] = [bottom_mch]
        edit_bones[bottom_mch].use_connect = False

        mbs = self.flatten(self.bones['mouth_mch'])
        mouth_center = edit_bones[mbs[0]].head
        for b in mbs[1:]:
            mouth_center = mouth_center + edit_bones[b].head
        mouth_center = mouth_center / len(mbs)

        for b in self.flatten(self.bones['mouth_mch']):
            put_bone(self.obj, b, mouth_center)

        # create remaining subchain mch-s
        super().create_mch()
Example #7
0
    def make_mch_chain(self):
        """
        Create all MCHs needed on a single chain
        :return:
        :rtype: list
        """

        if not self.active:
            return []

        bpy.ops.object.mode_set(mode='EDIT')
        edit_bones = self.obj.data.edit_bones

        chain = self._bones['org']

        self._bones['mch'] = []

        if self.chain_type == ChainType.TYPE_MCH_BASED:
            for chain_bone in chain:
                mch = make_mechanism_name(strip_org(chain_bone))
                mch = copy_bone(self.obj, chain_bone, assign_name=mch)
                edit_bones[mch].parent = None
                edit_bones[mch].use_connect = False
                edit_bones[mch].length *= self.MCH_SCALE
                self._bones['mch'].append(mch)

        return self._bones['mch']
Example #8
0
    def make_def_chain(self):
        """
        Creates all DEFs in chain
        :return:
        :rtype:list
        """

        if not self.active:
            return []

        bpy.ops.object.mode_set(mode='EDIT')
        edit_bones = self.obj.data.edit_bones

        chain = self._bones['org']

        self._bones['def'] = []

        if self.chain_type == ChainType.TYPE_MCH_BASED:
            for chain_bone in chain:
                def_bone = make_deformer_name(strip_org(chain_bone))
                def_bone = copy_bone(self.obj,
                                     chain_bone,
                                     assign_name=def_bone)
                edit_bones[def_bone].parent = None
                edit_bones[def_bone].use_connect = False
                self._bones['def'].append(def_bone)

        return self._bones['def']
    def create_mch(self):

        bpy.ops.object.mode_set(mode='EDIT')
        edit_bones = self.obj.data.edit_bones

        super().create_mch()

        self.bones['tail_mch'] = {}

        org_chain = self.get_chain_bones(self.base_bone)

        if edit_bones[org_chain[0]].parent:
            bone_to_copy = edit_bones[org_chain[0]].parent.name
        else:
            bone_to_copy = self.orientation_bone

        mch_rot_tail = make_mechanism_name('ROT-' + strip_org(self.base_bone))
        mch_rot_tail = copy_bone(self.obj,
                                 bone_to_copy,
                                 assign_name=mch_rot_tail)
        self.bones['tail_mch']['rot_tail_mch'] = mch_rot_tail
        main_chain = self.get_chain_bones(self.base_bone)
        flip_bone(self.obj, mch_rot_tail)
        edit_bones[mch_rot_tail].parent = None
        put_bone(self.obj, mch_rot_tail, edit_bones[main_chain[0]].head)
Example #10
0
    def gen_deform(self):
        """ Generate the deformation rig.

        """
        for name in self.org_bones:
            bpy.ops.object.mode_set(mode='EDIT')
            eb = self.obj.data.edit_bones

            # Create deform bone
            bone_e = eb[copy_bone(self.obj, name)]

            # Change its name
            bone_e.name = make_deformer_name(strip_org(name))
            bone_name = bone_e.name

            # Leave edit mode
            bpy.ops.object.mode_set(mode='OBJECT')

            # Get the pose bone
            bone = self.obj.pose.bones[bone_name]

            # Constrain to the original bone
            con = bone.constraints.new('COPY_TRANSFORMS')
            con.name = "copy_transforms"
            con.target = self.obj
            con.subtarget = name
    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')
        eb = self.obj.data.edit_bones

        org_delta = self.org_bones["delta"]
        org_delta_e = eb[self.org_bones["delta"]]
        org_child = self.org_bones["child"]
        org_child_e = eb[self.org_bones["child"]]

        # Calculate the matrix for achieving the delta
        child_mat = org_delta_e.matrix.invert() * org_child_e.matrix
        mat = org_delta_e.matrix * child_mat.invert()

        # Create the delta bones.
        delta_e = eb[copy_bone(self.obj, self.org_bones["delta"])]
        delta_e.name = make_mechanism_name(self.org_names[0])
        delta = delta_e.name

        # Set the delta to the matrix's transforms
        set_mat(self.obj, delta, mat)

        bpy.ops.object.mode_set(mode='OBJECT')

        # Constrain org_delta to delta
        con = self.obj.pose.bones[org_delta].constraints.new('COPY_TRANSFORMS')
        con.name = "delta"
        con.target = self.obj
        con.subtarget = delta
Example #12
0
    def gen_deform(self):
        """ Generate the deformation rig.

        """
        for name in self.org_bones:
            bpy.ops.object.mode_set(mode='EDIT')
            eb = self.obj.data.edit_bones

            # Create deform bone
            bone_e = eb[copy_bone(self.obj, name)]

            # Change its name
            bone_e.name = make_deformer_name(strip_org(name))
            bone_name = bone_e.name

            # Leave edit mode
            bpy.ops.object.mode_set(mode='OBJECT')

            # Get the pose bone
            bone = self.obj.pose.bones[bone_name]

            # Constrain to the original bone
            con = bone.constraints.new('COPY_TRANSFORMS')
            con.name = "copy_transforms"
            con.target = self.obj
            con.subtarget = name
Example #13
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')
        eb = self.obj.data.edit_bones

        org_delta = self.org_bones["delta"]
        org_delta_e = eb[self.org_bones["delta"]]
        # org_child = self.org_bones["child"]  # UNUSED
        org_child_e = eb[self.org_bones["child"]]

        # Calculate the matrix for achieving the delta
        child_mat = org_delta_e.matrix.invert() * org_child_e.matrix
        mat = org_delta_e.matrix * child_mat.invert()

        # Create the delta bones.
        delta_e = eb[copy_bone(self.obj, self.org_bones["delta"])]
        delta_e.name = make_mechanism_name(self.org_names[0])
        delta = delta_e.name

        # Set the delta to the matrix's transforms
        set_mat(self.obj, delta, mat)

        bpy.ops.object.mode_set(mode='OBJECT')

        # Constrain org_delta to delta
        con = self.obj.pose.bones[org_delta].constraints.new('COPY_TRANSFORMS')
        con.name = "delta"
        con.target = self.obj
        con.subtarget = delta
    def create_pivot(self, pivot=None):
        """ Create the pivot control and mechanism bones """

        org_bones = self.org_bones

        bpy.ops.object.mode_set(mode='EDIT')
        eb = self.obj.data.edit_bones

        if not pivot:
            pivot = int(len(org_bones) / 2)

        pivot_name = org_bones[pivot]
        if '.L' in pivot_name:
            prefix = strip_org(org_bones[pivot]).split('.')[0] + '.L'
        elif '.R' in pivot_name:
            prefix = strip_org(org_bones[pivot]).split('.')[0] + '.R'
        else:
            prefix = strip_org(org_bones[pivot]).split('.')[0]

        ctrl_name = get_bone_name(prefix, 'ctrl', 'pivot')
        ctrl_name = copy_bone(self.obj, pivot_name, ctrl_name)
        ctrl_eb = eb[ctrl_name]

        self.orient_bone(ctrl_eb, 'y', self.spine_length / 2.5)

        pivot_loc = eb[pivot_name].head + (
            (eb[pivot_name].tail - eb[pivot_name].head) /
            2) * (len(org_bones) % 2)

        put_bone(self.obj, ctrl_name, pivot_loc)

        v = eb[org_bones[-1]].tail - eb[org_bones[
            0]].head  # Create a vector from head of first ORG to tail of last
        v.normalize()
        v_proj = eb[org_bones[0]].y_axis.dot(
            v) * v  # projection of first ORG to v
        v_point = eb[org_bones[
            0]].y_axis - v_proj  # a vector co-planar to first ORG and v directed out of the chain

        if v_point.magnitude < eb[org_bones[
                0]].y_axis.magnitude * 1e-03:  # if v_point is too small it's not usable
            v_point = eb[org_bones[0]].x_axis

        if self.params.tweak_axis == 'auto':
            align_bone_y_axis(self.obj, ctrl_name, v)
            align_bone_z_axis(self.obj, ctrl_name, -v_point)
        elif self.params.tweak_axis == 'x':
            align_bone_y_axis(self.obj, ctrl_name, Vector((1, 0, 0)))
            align_bone_x_axis(self.obj, ctrl_name, Vector((0, 0, 1)))
        elif self.params.tweak_axis == 'y':
            align_bone_y_axis(self.obj, ctrl_name, Vector((0, 1, 0)))
            align_bone_x_axis(self.obj, ctrl_name, Vector((1, 0, 0)))
        elif self.params.tweak_axis == 'z':
            align_bone_y_axis(self.obj, ctrl_name, Vector((0, 0, 1)))
            align_bone_x_axis(self.obj, ctrl_name, Vector((1, 0, 0)))

        return {'ctrl': ctrl_name}
Example #15
0
    def create_controls(self):
        bpy.ops.object.mode_set(mode='EDIT')
        edit_bones = self.obj.data.edit_bones

        self.bones['jaw_ctrl'] = dict()

        jaw_ctrl_name = "jaw_master"

        jaw_ctrl = copy_bone(self.obj, self.main_mch, jaw_ctrl_name)
        self.bones['jaw_ctrl']['jaw'] = jaw_ctrl
        edit_bones[jaw_ctrl].use_connect = False

        self.bones['mouth_ctrl'] = dict()

        org_top = self.mouth_bones['top'][0]
        top_ctrl = copy_bone(self.obj, org_top, strip_org(org_top))
        self.bones['mouth_ctrl']['top'] = [top_ctrl]
        edit_bones[top_ctrl].use_connect = False

        self.bones['mouth_ctrl']['corners'] = []
        for org_name in self.mouth_bones['corners']:
            ctrl = copy_bone(self.obj, org_name, strip_org(org_name))
            self.bones['mouth_ctrl']['corners'].append(ctrl)
            edit_bones[top_ctrl].use_connect = False

        org_bottom = self.mouth_bones['bottom'][0]
        bottom_ctrl = copy_bone(self.obj, org_bottom, strip_org(org_bottom))
        self.bones['mouth_ctrl']['bottom'] = [bottom_ctrl]
        edit_bones[bottom_ctrl].use_connect = False

        mouth_center = (edit_bones[org_top].head + edit_bones[org_bottom].head) / 2

        main_mouth_ctrl = copy_bone(self.obj, org_top, "main_mouth")
        self.bones['mouth_ctrl']['main'] = main_mouth_ctrl
        edit_bones[main_mouth_ctrl].use_connect = False
        put_bone(self.obj, main_mouth_ctrl, mouth_center)

        super().create_controls()

        ctrls = self.get_all_ctrls()

        for ctrl in ctrls:
            align_bone_y_axis(self.obj, ctrl, Vector((0, 0, 1)))
Example #16
0
    def make_ctrl_chain(self):
        """
        Create all ctrls in chain
        :return:
        """

        if not self.active:
            return []

        bpy.ops.object.mode_set(mode='EDIT')
        edit_bones = self.obj.data.edit_bones

        chain = self._bones['org']

        self._bones['ctrl'] = []

        if self.chain_type == ChainType.TYPE_MCH_BASED:
            for chain_bone in chain:
                ctrl = strip_org(chain_bone)
                ctrl = copy_bone(self.obj,
                                 self.orientation_bone,
                                 assign_name=ctrl)
                put_bone(self.obj, ctrl, edit_bones[chain_bone].head)
                edit_bones[ctrl].length = edit_bones[
                    self.orientation_bone].length * self.CTRL_SCALE
                edit_bones[ctrl].parent = None
                edit_bones[ctrl].use_connect = False
                self._bones['ctrl'].append(ctrl)

            last_name = chain[-1]
            last_ctrl = copy_bone(self.obj,
                                  self.orientation_bone,
                                  assign_name=strip_org(last_name))
            put_bone(self.obj, last_ctrl, edit_bones[last_name].tail)
            edit_bones[last_ctrl].length = edit_bones[
                self.orientation_bone].length * self.CTRL_SCALE
            edit_bones[last_ctrl].parent = None
            edit_bones[last_ctrl].use_connect = False
            self._bones['ctrl'].append(last_ctrl)

        return self._bones['ctrl']
Example #17
0
    def create_controls(self):
        bpy.ops.object.mode_set(mode='EDIT')
        edit_bones = self.obj.data.edit_bones

        super().create_controls()

        self.bones['tongue_ctrl'] = {}

        tongue_master_name = strip_org(self.base_bone) + '_master'
        tongue_master_name = copy_bone(self.obj, self.base_bone, assign_name=tongue_master_name)
        flip_bone(self.obj, tongue_master_name)
        self.bones['tongue_ctrl']['tongue_master'] = tongue_master_name
Example #18
0
    def generate(self):
        bone_list = self.rubber_hose_limb.generate()

        # Set up toe
        bpy.ops.object.mode_set(mode='EDIT')
        toe = copy_bone(self.obj, self.org_bones[3],
                        make_deformer_name(strip_org(self.org_bones[3])))
        eb = self.obj.data.edit_bones
        eb[toe].use_connect = False
        eb[toe].parent = eb[self.org_bones[3]]

        return bone_list
    def create_controls(self):

        bpy.ops.object.mode_set(mode='EDIT')
        edit_bones = self.obj.data.edit_bones

        super().create_controls()

        self.bones['tweaks'] = {}
        self.bones['tail_ctrl'] = {}

        chain = strip_org(self.base_bone)
        ctrl_chain = self.bones['ctrl'][chain]
        self.bones['tweaks'][chain] = []
        orgs = self.get_chain_bones(org(chain))

        for org_bone, ctrl in zip(orgs, ctrl_chain):
            edit_bones[ctrl].length = edit_bones[org_bone].length
            align_bone_y_axis(self.obj, ctrl, edit_bones[org_bone].y_axis)
            tweak_name = 'tweak_' + ctrl
            tweak_name = copy_bone(self.obj, org_bone, assign_name=tweak_name)
            edit_bones[tweak_name].length = edit_bones[
                self.orientation_bone].length * self.TWEAK_SCALE
            self.bones['tweaks'][chain].append(tweak_name)

        tweak_name = 'tweak_' + ctrl_chain[-1]
        tweak_name = copy_bone(self.obj, orgs[-1], assign_name=tweak_name)
        edit_bones[tweak_name].parent = None
        put_bone(self.obj, tweak_name, edit_bones[orgs[-1]].tail)
        edit_bones[tweak_name].length = edit_bones[
            self.orientation_bone].length * self.TWEAK_SCALE
        self.bones['tweaks'][chain].append(tweak_name)

        edit_bones[ctrl_chain[-1]].head = edit_bones[orgs[0]].head
        edit_bones[ctrl_chain[-1]].tail = edit_bones[orgs[0]].tail
        tail_master = strip_org(self.base_bone) + '_master'
        edit_bones[ctrl_chain[-1]].name = tail_master
        self.bones['tail_ctrl']['tail_master'] = tail_master
        ctrl_chain[-1] = tail_master
    def create_mch(self):
        bpy.ops.object.mode_set(mode='EDIT')
        edit_bones = self.obj.data.edit_bones

        mch_bone = make_mechanism_name(strip_org(self.base_bone))
        mch_bone = copy_bone(self.obj, self.base_bone, mch_bone)
        self.bones['glue_mch'] = mch_bone

        MCH_LAYER = [n == 30 for n in range(0, 32)]
        edit_bones[mch_bone].layers = MCH_LAYER

        if self.glue_mode == 'bridge':
            self.bones['glue_mch'] = [mch_bone]
            b = self.base_bone
            put_bone(
                self.obj, mch_bone, edit_bones[b].head -
                (edit_bones[mch_bone].tail - edit_bones[mch_bone].head))

            mch_bone = make_mechanism_name(strip_org(self.base_bone))
            mch_bone = copy_bone(self.obj, self.base_bone, mch_bone)
            self.bones['glue_mch'].append(mch_bone)
            put_bone(self.obj, mch_bone, edit_bones[b].tail)
            edit_bones[mch_bone].layers = MCH_LAYER
    def create_def(self):

        bpy.ops.object.mode_set(mode='EDIT')
        edit_bones = self.obj.data.edit_bones

        self.bones['eye_def'] = dict()

        if self.params.make_deform:
            main_eye_def = make_deformer_name(strip_org(self.bones['org'][0]))
            main_eye_def = copy_bone(self.obj, self.bones['org'][0],
                                     main_eye_def)
            self.bones['eye_def']['eyeball_def'] = main_eye_def

        super().create_def()
    def create_controls(self):
        bpy.ops.object.mode_set(mode='EDIT')
        edit_bones = self.obj.data.edit_bones

        super().create_controls()

        self.bones['nose_ctrl'] = {}

        nose_master_name = strip_org(self.base_bone) + '_master'
        nose_master_name = copy_bone(self.obj,
                                     self.base_bone,
                                     assign_name=nose_master_name)
        self.bones['nose_ctrl']['nose_master'] = nose_master_name

        last_bone = self.get_chain_bones(self.base_bone)[-1]
        edit_bones[nose_master_name].tail = edit_bones[last_bone].tail
    def aggregate_ctrls(self, same_parent=True):
        """
        Aggregate controls should be called before constraining but AFTER parenting
        two ctrls are aggregated only if they are close enough and have the same parent
        or same_parent = False
        :return:
        """

        bpy.ops.object.mode_set(mode='EDIT')
        edit_bones = self.obj.data.edit_bones

        aggregates = []

        all_ctrls = self.flatten(self.bones['ctrl'])

        while 1:
            ctrl = all_ctrls[0]
            aggregate = [ctrl]
            for ctrl2 in all_ctrls[1:]:
                error = edit_bones[ctrl].length * self.POSITION_RELATIVE_ERROR
                if (edit_bones[ctrl].head - edit_bones[ctrl2].head).magnitude <= error \
                        and (not same_parent or edit_bones[ctrl].parent == edit_bones[ctrl2].parent):
                    aggregate.append(ctrl2)
            for element in aggregate:
                all_ctrls.remove(element)
            if len(aggregate) > 1:
                aggregates.append(aggregate)
            if not all_ctrls:
                break

        if aggregates:
            self.bones['ctrl']['aggregate'] = []

        for aggregate in aggregates:
            name = self.get_aggregate_name(aggregate)
            aggregate_ctrl = copy_bone(self.obj, aggregate[0], name)
            self.bones['ctrl']['aggregate'].append(aggregate_ctrl)
            for ctrl in aggregate:
                self.update_parent(ctrl, aggregate_ctrl)
                edit_bones.remove(edit_bones[ctrl])
                for chain in self.bones['ctrl']:
                    if chain == 'aggregate':
                        continue
                    if ctrl in self.bones['ctrl'][chain]:
                        i = self.bones['ctrl'][chain].index(ctrl)
                        self.bones['ctrl'][chain][i] = aggregate_ctrl
                        continue
    def create_controls(self):
        bpy.ops.object.mode_set(mode='EDIT')
        edit_bones = self.obj.data.edit_bones

        self.bones['jaw_ctrl'] = dict()

        jaw_ctrl_name = "jaw_master"

        jaw_ctrl = copy_bone(self.obj, self.main_mch, jaw_ctrl_name)
        self.bones['jaw_ctrl']['jaw'] = jaw_ctrl
        edit_bones[jaw_ctrl].use_connect = False

        super().create_controls()

        ctrls = self.get_all_ctrls()

        for ctrl in ctrls:
            align_bone_y_axis(self.obj, ctrl, Vector((0, 0, 1)))
    def create_def(self):
        """
        If add_glue_def is True adds a DEF
        :return:
        """

        if not self.params.add_glue_def:
            return

        bpy.ops.object.mode_set(mode='EDIT')
        edit_bones = self.obj.data.edit_bones

        def_bone = make_deformer_name(strip_org(self.base_bone))
        def_bone = copy_bone(self.obj, self.base_bone, def_bone)
        self.bones['glue_def'] = def_bone

        DEF_LAYER = [n == 29 for n in range(0, 32)]
        edit_bones[def_bone].layers = DEF_LAYER
        edit_bones[def_bone].use_deform = True
def create_side_org_bones(obj, org_bones, duplicate, side_suffix):
    """Copy originals with side suffix"""
    bpy.ops.object.mode_set(mode='EDIT')
    eb = obj.data.edit_bones

    side_org_bones = []
    if duplicate:
        for b in org_bones:
            side_org_bone = copy_bone(
                obj, b,
                pantin_utils.strip_LR_numbers(b) + side_suffix)
            side_org_bones.append(side_org_bone)
            eb[side_org_bone].layers = [
                False if i != 31 else True for i in range(32)
            ]
    else:
        side_org_bones = org_bones

    return side_org_bones
Example #27
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 bones
        uarm = copy_bone(self.obj, self.org_bones[0], make_mechanism_name(strip_org(insert_before_lr(self.org_bones[0], "_ik"))))
        farm = copy_bone(self.obj, self.org_bones[1], make_mechanism_name(strip_org(insert_before_lr(self.org_bones[1], "_ik"))))

        hand = copy_bone(self.obj, self.org_bones[2], strip_org(insert_before_lr(self.org_bones[2], "_ik")))
        pole = copy_bone(self.obj, self.org_bones[0], strip_org(insert_before_lr(self.org_bones[0], "_pole")))

        vishand = copy_bone(self.obj, self.org_bones[2], "VIS-" + strip_org(insert_before_lr(self.org_bones[2], "_ik")))
        vispole = copy_bone(self.obj, self.org_bones[1], "VIS-" + strip_org(insert_before_lr(self.org_bones[0], "_pole")))

        # Get edit bones
        eb = self.obj.data.edit_bones

        uarm_e = eb[uarm]
        farm_e = eb[farm]
        hand_e = eb[hand]
        pole_e = eb[pole]
        vishand_e = eb[vishand]
        vispole_e = eb[vispole]

        # Parenting
        farm_e.parent = uarm_e

        hand_e.use_connect = False
        hand_e.parent = None

        pole_e.use_connect = False

        vishand_e.use_connect = False
        vishand_e.parent = None

        vispole_e.use_connect = False
        vispole_e.parent = None

        # Misc
        hand_e.use_local_location = False

        vishand_e.hide_select = True
        vispole_e.hide_select = True

        # Positioning
        v1 = farm_e.tail - uarm_e.head
        if 'X' in self.primary_rotation_axis or 'Y' in self.primary_rotation_axis:
            v2 = v1.cross(farm_e.x_axis)
            if (v2 * farm_e.z_axis) > 0.0:
                v2 *= -1.0
        else:
            v2 = v1.cross(farm_e.z_axis)
            if (v2 * farm_e.x_axis) < 0.0:
                v2 *= -1.0
        v2.normalize()
        v2 *= v1.length

        if '-' in self.primary_rotation_axis:
            v2 *= -1

        pole_e.head = farm_e.head + v2
        pole_e.tail = pole_e.head + (Vector((0, 1, 0)) * (v1.length / 8))
        pole_e.roll = 0.0

        vishand_e.tail = vishand_e.head + Vector((0, 0, v1.length / 32))
        vispole_e.tail = vispole_e.head + Vector((0, 0, v1.length / 32))

        # Determine the pole offset value
        plane = (farm_e.tail - uarm_e.head).normalized()
        vec1 = uarm_e.x_axis.normalized()
        vec2 = (pole_e.head - uarm_e.head).normalized()
        pole_offset = angle_on_plane(plane, vec1, vec2)

        # Object mode, get pose bones
        bpy.ops.object.mode_set(mode='OBJECT')
        pb = self.obj.pose.bones

        # uarm_p = pb[uarm]  # UNUSED
        farm_p = pb[farm]
        hand_p = pb[hand]
        pole_p = pb[pole]
        vishand_p = pb[vishand]
        vispole_p = pb[vispole]

        # Set the elbow to only bend on the primary axis
        if 'X' in self.primary_rotation_axis:
            farm_p.lock_ik_y = True
            farm_p.lock_ik_z = True
        elif 'Y' in self.primary_rotation_axis:
            farm_p.lock_ik_x = True
            farm_p.lock_ik_z = True
        else:
            farm_p.lock_ik_x = True
            farm_p.lock_ik_y = True

        # Pole target only translates
        pole_p.lock_location = False, False, False
        pole_p.lock_rotation = True, True, True
        pole_p.lock_rotation_w = True
        pole_p.lock_scale = True, True, True

        # Set up custom properties
        if self.switch == True:
            prop = rna_idprop_ui_prop_get(hand_p, "ikfk_switch", create=True)
            hand_p["ikfk_switch"] = 0.0
            prop["soft_min"] = prop["min"] = 0.0
            prop["soft_max"] = prop["max"] = 1.0

        # Bend direction hint
        if self.bend_hint:
            con = farm_p.constraints.new('LIMIT_ROTATION')
            con.name = "bend_hint"
            con.owner_space = 'LOCAL'
            if self.primary_rotation_axis == 'X':
                con.use_limit_x = True
                con.min_x = pi / 10
                con.max_x = pi / 10
            elif self.primary_rotation_axis == '-X':
                con.use_limit_x = True
                con.min_x = -pi / 10
                con.max_x = -pi / 10
            elif self.primary_rotation_axis == 'Y':
                con.use_limit_y = True
                con.min_y = pi / 10
                con.max_y = pi / 10
            elif self.primary_rotation_axis == '-Y':
                con.use_limit_y = True
                con.min_y = -pi / 10
                con.max_y = -pi / 10
            elif self.primary_rotation_axis == 'Z':
                con.use_limit_z = True
                con.min_z = pi / 10
                con.max_z = pi / 10
            elif self.primary_rotation_axis == '-Z':
                con.use_limit_z = True
                con.min_z = -pi / 10
                con.max_z = -pi / 10

        # IK Constraint
        con = farm_p.constraints.new('IK')
        con.name = "ik"
        con.target = self.obj
        con.subtarget = hand
        con.pole_target = self.obj
        con.pole_subtarget = pole
        con.pole_angle = pole_offset
        con.chain_count = 2

        # Constrain org bones to controls
        con = pb[self.org_bones[0]].constraints.new('COPY_TRANSFORMS')
        con.name = "ik"
        con.target = self.obj
        con.subtarget = uarm
        if self.switch == True:
            # IK/FK switch 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 = hand_p.path_from_id() + '["ikfk_switch"]'

        con = pb[self.org_bones[1]].constraints.new('COPY_TRANSFORMS')
        con.name = "ik"
        con.target = self.obj
        con.subtarget = farm
        if self.switch == True:
            # IK/FK switch 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 = hand_p.path_from_id() + '["ikfk_switch"]'

        con = pb[self.org_bones[2]].constraints.new('COPY_TRANSFORMS')
        con.name = "ik"
        con.target = self.obj
        con.subtarget = hand
        if self.switch == True:
            # IK/FK switch 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 = hand_p.path_from_id() + '["ikfk_switch"]'

        # VIS hand constraints
        con = vishand_p.constraints.new('COPY_LOCATION')
        con.name = "copy_loc"
        con.target = self.obj
        con.subtarget = self.org_bones[2]

        con = vishand_p.constraints.new('STRETCH_TO')
        con.name = "stretch_to"
        con.target = self.obj
        con.subtarget = hand
        con.volume = 'NO_VOLUME'
        con.rest_length = vishand_p.length

        # VIS pole constraints
        con = vispole_p.constraints.new('COPY_LOCATION')
        con.name = "copy_loc"
        con.target = self.obj
        con.subtarget = self.org_bones[1]

        con = vispole_p.constraints.new('STRETCH_TO')
        con.name = "stretch_to"
        con.target = self.obj
        con.subtarget = pole
        con.volume = 'NO_VOLUME'
        con.rest_length = vispole_p.length

        # Set layers if specified
        if self.layers:
            hand_p.bone.layers = self.layers
            pole_p.bone.layers = self.layers
            vishand_p.bone.layers = self.layers
            vispole_p.bone.layers = self.layers

        # Create widgets
        create_line_widget(self.obj, vispole)
        create_line_widget(self.obj, vishand)
        create_sphere_widget(self.obj, pole)

        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, pole]
Example #28
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 #29
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')

        make_rocker = False
        if self.org_bones[5] is not None:
            make_rocker = True

        # Create the bones
        thigh = copy_bone(self.obj, self.org_bones[0], make_mechanism_name(strip_org(insert_before_lr(self.org_bones[0], "_ik"))))
        shin = copy_bone(self.obj, self.org_bones[1], make_mechanism_name(strip_org(insert_before_lr(self.org_bones[1], "_ik"))))

        foot = copy_bone(self.obj, self.org_bones[2], strip_org(insert_before_lr(self.org_bones[2], "_ik")))
        foot_ik_target = copy_bone(self.obj, self.org_bones[2], make_mechanism_name(strip_org(insert_before_lr(self.org_bones[2], "_ik_target"))))
        pole = copy_bone(self.obj, self.org_bones[0], strip_org(insert_before_lr(self.org_bones[0], "_pole")))

        toe = copy_bone(self.obj, self.org_bones[3], strip_org(self.org_bones[3]))
        toe_parent = copy_bone(self.obj, self.org_bones[2], make_mechanism_name(strip_org(self.org_bones[3] + ".parent")))
        toe_parent_socket1 = copy_bone(self.obj, self.org_bones[2], make_mechanism_name(strip_org(self.org_bones[3] + ".socket1")))
        toe_parent_socket2 = copy_bone(self.obj, self.org_bones[2], make_mechanism_name(strip_org(self.org_bones[3] + ".socket2")))

        foot_roll = copy_bone(self.obj, self.org_bones[4], strip_org(insert_before_lr(self.org_bones[2], "_roll")))
        roll1 = copy_bone(self.obj, self.org_bones[4], make_mechanism_name(strip_org(self.org_bones[2] + ".roll.01")))
        roll2 = copy_bone(self.obj, self.org_bones[4], make_mechanism_name(strip_org(self.org_bones[2] + ".roll.02")))

        if make_rocker:
            rocker1 = copy_bone(self.obj, self.org_bones[5], make_mechanism_name(strip_org(self.org_bones[2] + ".rocker.01")))
            rocker2 = copy_bone(self.obj, self.org_bones[5], make_mechanism_name(strip_org(self.org_bones[2] + ".rocker.02")))

        visfoot = copy_bone(self.obj, self.org_bones[2], "VIS-" + strip_org(insert_before_lr(self.org_bones[2], "_ik")))
        vispole = copy_bone(self.obj, self.org_bones[1], "VIS-" + strip_org(insert_before_lr(self.org_bones[0], "_pole")))

        # Get edit bones
        eb = self.obj.data.edit_bones

        org_foot_e = eb[self.org_bones[2]]
        thigh_e = eb[thigh]
        shin_e = eb[shin]
        foot_e = eb[foot]
        foot_ik_target_e = eb[foot_ik_target]
        pole_e = eb[pole]
        toe_e = eb[toe]
        toe_parent_e = eb[toe_parent]
        toe_parent_socket1_e = eb[toe_parent_socket1]
        toe_parent_socket2_e = eb[toe_parent_socket2]
        foot_roll_e = eb[foot_roll]
        roll1_e = eb[roll1]
        roll2_e = eb[roll2]
        if make_rocker:
            rocker1_e = eb[rocker1]
            rocker2_e = eb[rocker2]
        visfoot_e = eb[visfoot]
        vispole_e = eb[vispole]

        # Parenting
        shin_e.parent = thigh_e

        foot_e.use_connect = False
        foot_e.parent = None
        foot_ik_target_e.use_connect = False
        foot_ik_target_e.parent = roll2_e

        pole_e.use_connect = False
        pole_e.parent = foot_e

        toe_e.parent = toe_parent_e
        toe_parent_e.use_connect = False
        toe_parent_e.parent = toe_parent_socket1_e
        toe_parent_socket1_e.use_connect = False
        toe_parent_socket1_e.parent = roll1_e
        toe_parent_socket2_e.use_connect = False
        toe_parent_socket2_e.parent = eb[self.org_bones[2]]

        foot_roll_e.use_connect = False
        foot_roll_e.parent = foot_e

        roll1_e.use_connect = False
        roll1_e.parent = foot_e

        roll2_e.use_connect = False
        roll2_e.parent = roll1_e

        visfoot_e.use_connect = False
        visfoot_e.parent = None

        vispole_e.use_connect = False
        vispole_e.parent = None

        if make_rocker:
            rocker1_e.use_connect = False
            rocker2_e.use_connect = False

            roll1_e.parent = rocker2_e
            rocker2_e.parent = rocker1_e
            rocker1_e.parent = foot_e

        # Misc
        foot_e.use_local_location = False

        visfoot_e.hide_select = True
        vispole_e.hide_select = True

        # Positioning
        vec = Vector(toe_e.vector)
        vec.normalize()
        foot_e.tail = foot_e.head + (vec * foot_e.length)
        foot_e.roll = toe_e.roll

        v1 = shin_e.tail - thigh_e.head

        if 'X' in self.primary_rotation_axis or 'Y' in self.primary_rotation_axis:
            v2 = v1.cross(shin_e.x_axis)
            if (v2 * shin_e.z_axis) > 0.0:
                v2 *= -1.0
        else:
            v2 = v1.cross(shin_e.z_axis)
            if (v2 * shin_e.x_axis) < 0.0:
                v2 *= -1.0
        v2.normalize()
        v2 *= v1.length

        if '-' in self.primary_rotation_axis:
            v2 *= -1

        pole_e.head = shin_e.head + v2
        pole_e.tail = pole_e.head + (Vector((0, 1, 0)) * (v1.length / 8))
        pole_e.roll = 0.0

        flip_bone(self.obj, toe_parent_socket1)
        flip_bone(self.obj, toe_parent_socket2)
        toe_parent_socket1_e.head = Vector(org_foot_e.tail)
        toe_parent_socket2_e.head = Vector(org_foot_e.tail)
        toe_parent_socket1_e.tail = Vector(org_foot_e.tail) + (Vector((0, 0, 1)) * foot_e.length / 2)
        toe_parent_socket2_e.tail = Vector(org_foot_e.tail) + (Vector((0, 0, 1)) * foot_e.length / 3)
        toe_parent_socket2_e.roll = toe_parent_socket1_e.roll

        tail = Vector(roll1_e.tail)
        roll1_e.tail = Vector(org_foot_e.tail)
        roll1_e.tail = Vector(org_foot_e.tail)
        roll1_e.head = tail
        roll2_e.head = Vector(org_foot_e.tail)
        foot_roll_e.head = Vector(org_foot_e.tail)
        put_bone(self.obj, foot_roll, roll1_e.head)
        foot_roll_e.length /= 2

        roll_axis = roll1_e.vector.cross(org_foot_e.vector)
        align_x_axis(self.obj, roll1, roll_axis)
        align_x_axis(self.obj, roll2, roll_axis)
        foot_roll_e.roll = roll2_e.roll

        visfoot_e.tail = visfoot_e.head + Vector((0, 0, v1.length / 32))
        vispole_e.tail = vispole_e.head + Vector((0, 0, v1.length / 32))

        if make_rocker:
            d = toe_e.y_axis.dot(rocker1_e.x_axis)
            if d >= 0.0:
                flip_bone(self.obj, rocker2)
            else:
                flip_bone(self.obj, rocker1)

        # Weird alignment issues.  Fix.
        toe_parent_e.head = Vector(org_foot_e.head)
        toe_parent_e.tail = Vector(org_foot_e.tail)
        toe_parent_e.roll = org_foot_e.roll

        foot_e.head = Vector(org_foot_e.head)

        foot_ik_target_e.head = Vector(org_foot_e.head)
        foot_ik_target_e.tail = Vector(org_foot_e.tail)

        # Determine the pole offset value
        plane = (shin_e.tail - thigh_e.head).normalized()
        vec1 = thigh_e.x_axis.normalized()
        vec2 = (pole_e.head - thigh_e.head).normalized()
        pole_offset = angle_on_plane(plane, vec1, vec2)

        # Object mode, get pose bones
        bpy.ops.object.mode_set(mode='OBJECT')
        pb = self.obj.pose.bones

        # thigh_p = pb[thigh]  # UNUSED
        shin_p = pb[shin]
        foot_p = pb[foot]
        pole_p = pb[pole]
        foot_roll_p = pb[foot_roll]
        roll1_p = pb[roll1]
        roll2_p = pb[roll2]
        if make_rocker:
            rocker1_p = pb[rocker1]
            rocker2_p = pb[rocker2]
        toe_p = pb[toe]
        toe_parent_p = pb[toe_parent]
        toe_parent_socket1_p = pb[toe_parent_socket1]
        visfoot_p = pb[visfoot]
        vispole_p = pb[vispole]

        # Set the knee to only bend on the primary axis.
        if 'X' in self.primary_rotation_axis:
            shin_p.lock_ik_y = True
            shin_p.lock_ik_z = True
        elif 'Y' in self.primary_rotation_axis:
            shin_p.lock_ik_x = True
            shin_p.lock_ik_z = True
        else:
            shin_p.lock_ik_x = True
            shin_p.lock_ik_y = True

        # Foot roll control only rotates on x-axis, or x and y if rocker.
        foot_roll_p.rotation_mode = 'XYZ'
        if make_rocker:
            foot_roll_p.lock_rotation = False, False, True
        else:
            foot_roll_p.lock_rotation = False, True, True
        foot_roll_p.lock_location = True, True, True
        foot_roll_p.lock_scale = True, True, True

        # roll and rocker bones set to euler rotation
        roll1_p.rotation_mode = 'XYZ'
        roll2_p.rotation_mode = 'XYZ'
        if make_rocker:
            rocker1_p.rotation_mode = 'XYZ'
            rocker2_p.rotation_mode = 'XYZ'

        # Pole target only translates
        pole_p.lock_location = False, False, False
        pole_p.lock_rotation = True, True, True
        pole_p.lock_rotation_w = True
        pole_p.lock_scale = True, True, True

        # Set up custom properties
        if self.switch == True:
            prop = rna_idprop_ui_prop_get(foot_p, "ikfk_switch", create=True)
            foot_p["ikfk_switch"] = 0.0
            prop["soft_min"] = prop["min"] = 0.0
            prop["soft_max"] = prop["max"] = 1.0

        # Bend direction hint
        if self.bend_hint:
            con = shin_p.constraints.new('LIMIT_ROTATION')
            con.name = "bend_hint"
            con.owner_space = 'LOCAL'
            if self.primary_rotation_axis == 'X':
                con.use_limit_x = True
                con.min_x = pi / 10
                con.max_x = pi / 10
            elif self.primary_rotation_axis == '-X':
                con.use_limit_x = True
                con.min_x = -pi / 10
                con.max_x = -pi / 10
            elif self.primary_rotation_axis == 'Y':
                con.use_limit_y = True
                con.min_y = pi / 10
                con.max_y = pi / 10
            elif self.primary_rotation_axis == '-Y':
                con.use_limit_y = True
                con.min_y = -pi / 10
                con.max_y = -pi / 10
            elif self.primary_rotation_axis == 'Z':
                con.use_limit_z = True
                con.min_z = pi / 10
                con.max_z = pi / 10
            elif self.primary_rotation_axis == '-Z':
                con.use_limit_z = True
                con.min_z = -pi / 10
                con.max_z = -pi / 10

        # IK Constraint
        con = shin_p.constraints.new('IK')
        con.name = "ik"
        con.target = self.obj
        con.subtarget = foot_ik_target
        con.pole_target = self.obj
        con.pole_subtarget = pole
        con.pole_angle = pole_offset
        con.chain_count = 2

        # toe_parent constraint
        con = toe_parent_socket1_p.constraints.new('COPY_LOCATION')
        con.name = "copy_location"
        con.target = self.obj
        con.subtarget = toe_parent_socket2

        con = toe_parent_socket1_p.constraints.new('COPY_SCALE')
        con.name = "copy_scale"
        con.target = self.obj
        con.subtarget = toe_parent_socket2

        con = toe_parent_socket1_p.constraints.new('COPY_TRANSFORMS')  # drive with IK switch
        con.name = "fk"
        con.target = self.obj
        con.subtarget = toe_parent_socket2

        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 = foot_p.path_from_id() + '["ikfk_switch"]'
        mod = fcurve.modifiers[0]
        mod.poly_order = 1
        mod.coefficients[0] = 1.0
        mod.coefficients[1] = -1.0

        # Foot roll drivers
        fcurve = roll1_p.driver_add("rotation_euler", 0)
        driver = fcurve.driver
        var = driver.variables.new()
        driver.type = 'SCRIPTED'
        driver.expression = "min(0,var)"
        var.name = "var"
        var.targets[0].id_type = 'OBJECT'
        var.targets[0].id = self.obj
        var.targets[0].data_path = foot_roll_p.path_from_id() + '.rotation_euler[0]'

        fcurve = roll2_p.driver_add("rotation_euler", 0)
        driver = fcurve.driver
        var = driver.variables.new()
        driver.type = 'SCRIPTED'
        driver.expression = "max(0,var)"
        var.name = "var"
        var.targets[0].id_type = 'OBJECT'
        var.targets[0].id = self.obj
        var.targets[0].data_path = foot_roll_p.path_from_id() + '.rotation_euler[0]'

        if make_rocker:
            fcurve = rocker1_p.driver_add("rotation_euler", 0)
            driver = fcurve.driver
            var = driver.variables.new()
            driver.type = 'SCRIPTED'
            driver.expression = "max(0,-var)"
            var.name = "var"
            var.targets[0].id_type = 'OBJECT'
            var.targets[0].id = self.obj
            var.targets[0].data_path = foot_roll_p.path_from_id() + '.rotation_euler[1]'

            fcurve = rocker2_p.driver_add("rotation_euler", 0)
            driver = fcurve.driver
            var = driver.variables.new()
            driver.type = 'SCRIPTED'
            driver.expression = "max(0,var)"
            var.name = "var"
            var.targets[0].id_type = 'OBJECT'
            var.targets[0].id = self.obj
            var.targets[0].data_path = foot_roll_p.path_from_id() + '.rotation_euler[1]'

        # Constrain org bones to controls
        con = pb[self.org_bones[0]].constraints.new('COPY_TRANSFORMS')
        con.name = "ik"
        con.target = self.obj
        con.subtarget = thigh
        if self.switch == True:
            # IK/FK switch 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 = foot_p.path_from_id() + '["ikfk_switch"]'

        con = pb[self.org_bones[1]].constraints.new('COPY_TRANSFORMS')
        con.name = "ik"
        con.target = self.obj
        con.subtarget = shin
        if self.switch == True:
            # IK/FK switch 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 = foot_p.path_from_id() + '["ikfk_switch"]'

        con = pb[self.org_bones[2]].constraints.new('COPY_TRANSFORMS')
        con.name = "ik"
        con.target = self.obj
        con.subtarget = foot_ik_target
        if self.switch == True:
            # IK/FK switch 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 = foot_p.path_from_id() + '["ikfk_switch"]'

        con = pb[self.org_bones[3]].constraints.new('COPY_TRANSFORMS')
        con.name = "copy_transforms"
        con.target = self.obj
        con.subtarget = toe

        # VIS foot constraints
        con = visfoot_p.constraints.new('COPY_LOCATION')
        con.name = "copy_loc"
        con.target = self.obj
        con.subtarget = self.org_bones[2]

        con = visfoot_p.constraints.new('STRETCH_TO')
        con.name = "stretch_to"
        con.target = self.obj
        con.subtarget = foot
        con.volume = 'NO_VOLUME'
        con.rest_length = visfoot_p.length

        # VIS pole constraints
        con = vispole_p.constraints.new('COPY_LOCATION')
        con.name = "copy_loc"
        con.target = self.obj
        con.subtarget = self.org_bones[1]

        con = vispole_p.constraints.new('STRETCH_TO')
        con.name = "stretch_to"
        con.target = self.obj
        con.subtarget = pole
        con.volume = 'NO_VOLUME'
        con.rest_length = vispole_p.length

        # Set layers if specified
        if self.layers:
            foot_p.bone.layers = self.layers
            pole_p.bone.layers = self.layers
            foot_roll_p.bone.layers = self.layers
            visfoot_p.bone.layers = self.layers
            vispole_p.bone.layers = self.layers

            toe_p.bone.layers = [(i[0] or i[1]) for i in zip(toe_p.bone.layers, self.layers)]  # Both FK and IK layers

        # Create widgets
        create_line_widget(self.obj, vispole)
        create_line_widget(self.obj, visfoot)
        create_sphere_widget(self.obj, pole)
        create_circle_widget(self.obj, toe, radius=0.7, head_tail=0.5)

        ob = create_widget(self.obj, foot)
        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

        ob = create_widget(self.obj, foot_roll)
        if ob != None:
            verts = [(0.3999999761581421, 0.766044557094574, 0.6427875757217407), (0.17668449878692627, 3.823702598992895e-08, 3.2084670920085046e-08), (-0.17668461799621582, 9.874240447516058e-08, 8.285470443070153e-08), (-0.39999961853027344, 0.7660449147224426, 0.6427879333496094), (0.3562471270561218, 0.6159579753875732, 0.5168500542640686), (-0.35624682903289795, 0.6159582138061523, 0.5168502926826477), (0.20492683351039886, 0.09688037633895874, 0.0812922865152359), (-0.20492687821388245, 0.0968804731965065, 0.08129236847162247)]
            edges = [(1, 2), (0, 3), (0, 4), (3, 5), (1, 6), (4, 6), (2, 7), (5, 7)]
            mesh = ob.data
            mesh.from_pydata(verts, edges, [])
            mesh.update()

            mod = ob.modifiers.new("subsurf", 'SUBSURF')
            mod.levels = 2

        return [thigh, shin, foot, pole, foot_roll, foot_ik_target]
Example #30
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')

        # Figure out the name for the control bone (remove the last .##)
        last_bone = self.org_bones[-1:][0]
        ctrl_name = re.sub("([0-9]+\.)", "", strip_org(last_bone)[::-1], count=1)[::-1]

        # Make control bone
        ctrl = copy_bone(self.obj, last_bone, ctrl_name)

        # Make deformation bones
        def_bones = []
        for bone in self.org_bones:
            b = copy_bone(self.obj, bone, deformer(strip_org(bone)))
            def_bones += [b]

        # Parenting
        eb = self.obj.data.edit_bones

        for d, b in zip(def_bones, self.org_bones):
            eb[d].use_connect = False
            eb[d].parent = eb[b]

        # Constraints
        bpy.ops.object.mode_set(mode='OBJECT')
        pb = self.obj.pose.bones

        i = 0
        div = len(self.org_bones) - 1
        for b in self.org_bones:
            con = pb[b].constraints.new('COPY_TRANSFORMS')
            con.name = "copy_transforms"
            con.target = self.obj
            con.subtarget = ctrl
            con.target_space = 'LOCAL'
            con.owner_space = 'LOCAL'
            con.influence = i / div

            con = pb[b].constraints.new('COPY_ROTATION')
            con.name = "copy_rotation"
            con.target = self.obj
            con.subtarget = ctrl
            con.target_space = 'LOCAL'
            con.owner_space = 'LOCAL'
            if 'X' in self.palm_rotation_axis:
                con.invert_x = True
                con.use_x = True
                con.use_z = False
            else:
                con.invert_z = True
                con.use_x = False
                con.use_z = True
            con.use_y = False

            con.influence = (i / div) - (1 - cos((i * pi / 2) / div))

            i += 1

        # Create control widget
        w = create_widget(self.obj, ctrl)
        if w is not None:
            mesh = w.data
            verts = [(0.15780271589756012, 2.086162567138672e-07, -0.30000004172325134), (0.15780259668827057, 1.0, -0.2000001072883606), (-0.15780280530452728, 0.9999999403953552, -0.20000004768371582), (-0.15780259668827057, -2.086162567138672e-07, -0.29999998211860657), (-0.15780256688594818, -2.7089754439657554e-07, 0.30000004172325134), (-0.1578027755022049, 0.9999998807907104, 0.19999995827674866), (0.15780262649059296, 0.9999999403953552, 0.19999989867210388), (0.1578027456998825, 1.4633496903115883e-07, 0.29999998211860657), (0.15780268609523773, 0.2500001788139343, -0.27500003576278687), (-0.15780264139175415, 0.24999985098838806, -0.2749999761581421), (0.15780262649059296, 0.7500000596046448, -0.22500008344650269), (-0.1578027606010437, 0.7499998807907104, -0.2250000238418579), (0.15780265629291534, 0.75, 0.22499991953372955), (0.15780271589756012, 0.2500000596046448, 0.2749999761581421), (-0.15780261158943176, 0.2499997615814209, 0.27500003576278687), (-0.1578027307987213, 0.7499998807907104, 0.22499997913837433)]
            if 'Z' in self.palm_rotation_axis:
                # Flip x/z coordinates
                temp = []
                for v in verts:
                    temp += [(v[2], v[1], v[0])]
                verts = temp
            edges = [(1, 2), (0, 3), (4, 7), (5, 6), (8, 0), (9, 3), (10, 1), (11, 2), (12, 6), (13, 7), (4, 14), (15, 5), (10, 8), (11, 9), (15, 14), (12, 13)]
            mesh.from_pydata(verts, edges, [])
            mesh.update()

            mod = w.modifiers.new("subsurf", 'SUBSURF')
            mod.levels = 2
Example #31
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.
        """
        # Generate base IK limb
        bone_list = self.ik_limb.generate()
        thigh = bone_list[0]
        shin = bone_list[1]
        foot = bone_list[2]
        foot_mch = bone_list[3]
        pole = bone_list[4]
        # vispole = bone_list[5]
        # visfoot = bone_list[6]

        # Build IK foot rig
        bpy.ops.object.mode_set(mode='EDIT')
        make_rocker = False
        if self.org_bones[5] is not None:
            make_rocker = True

        # Create the bones
        toe = copy_bone(self.obj, self.org_bones[3],
                        strip_org(self.org_bones[3]))
        toe_parent = copy_bone(
            self.obj, self.org_bones[2],
            make_mechanism_name(strip_org(self.org_bones[3] + ".parent")))
        toe_parent_socket1 = copy_bone(
            self.obj, self.org_bones[2],
            make_mechanism_name(strip_org(self.org_bones[3] + ".socket1")))
        toe_parent_socket2 = copy_bone(
            self.obj, self.org_bones[2],
            make_mechanism_name(strip_org(self.org_bones[3] + ".socket2")))

        foot_roll = copy_bone(
            self.obj, self.org_bones[4],
            strip_org(insert_before_lr(self.org_bones[2], "_roll.ik")))
        roll1 = copy_bone(
            self.obj, self.org_bones[4],
            make_mechanism_name(strip_org(self.org_bones[2] + ".roll.01")))
        roll2 = copy_bone(
            self.obj, self.org_bones[4],
            make_mechanism_name(strip_org(self.org_bones[2] + ".roll.02")))

        if make_rocker:
            rocker1 = copy_bone(
                self.obj, self.org_bones[5],
                make_mechanism_name(strip_org(self.org_bones[2] +
                                              ".rocker.01")))
            rocker2 = copy_bone(
                self.obj, self.org_bones[5],
                make_mechanism_name(strip_org(self.org_bones[2] +
                                              ".rocker.02")))

        # Get edit bones
        eb = self.obj.data.edit_bones

        org_foot_e = eb[self.org_bones[2]]
        foot_e = eb[foot]
        foot_ik_target_e = eb[foot_mch]
        toe_e = eb[toe]
        toe_parent_e = eb[toe_parent]
        toe_parent_socket1_e = eb[toe_parent_socket1]
        toe_parent_socket2_e = eb[toe_parent_socket2]
        foot_roll_e = eb[foot_roll]
        roll1_e = eb[roll1]
        roll2_e = eb[roll2]
        if make_rocker:
            rocker1_e = eb[rocker1]
            rocker2_e = eb[rocker2]

        # Parenting
        foot_ik_target_e.use_connect = False
        foot_ik_target_e.parent = roll2_e

        toe_e.parent = toe_parent_e
        toe_parent_e.use_connect = False
        toe_parent_e.parent = toe_parent_socket1_e
        toe_parent_socket1_e.use_connect = False
        toe_parent_socket1_e.parent = roll1_e
        toe_parent_socket2_e.use_connect = False
        toe_parent_socket2_e.parent = eb[self.org_bones[2]]

        foot_roll_e.use_connect = False
        foot_roll_e.parent = foot_e

        roll1_e.use_connect = False
        roll1_e.parent = foot_e

        roll2_e.use_connect = False
        roll2_e.parent = roll1_e

        if make_rocker:
            rocker1_e.use_connect = False
            rocker2_e.use_connect = False

            roll1_e.parent = rocker2_e
            rocker2_e.parent = rocker1_e
            rocker1_e.parent = foot_e

        # Positioning
        vec = Vector(toe_e.vector)
        vec.normalize()
        foot_e.tail = foot_e.head + (vec * foot_e.length)
        foot_e.roll = toe_e.roll

        flip_bone(self.obj, toe_parent_socket1)
        flip_bone(self.obj, toe_parent_socket2)
        toe_parent_socket1_e.head = Vector(org_foot_e.tail)
        toe_parent_socket2_e.head = Vector(org_foot_e.tail)
        toe_parent_socket1_e.tail = Vector(org_foot_e.tail) + (Vector(
            (0, 0, 1)) * foot_e.length / 2)
        toe_parent_socket2_e.tail = Vector(org_foot_e.tail) + (Vector(
            (0, 0, 1)) * foot_e.length / 3)
        toe_parent_socket2_e.roll = toe_parent_socket1_e.roll

        tail = Vector(roll1_e.tail)
        roll1_e.tail = Vector(org_foot_e.tail)
        roll1_e.tail = Vector(org_foot_e.tail)
        roll1_e.head = tail
        roll2_e.head = Vector(org_foot_e.tail)
        foot_roll_e.head = Vector(org_foot_e.tail)
        put_bone(self.obj, foot_roll, roll1_e.head)
        foot_roll_e.length /= 2

        roll_axis = roll1_e.vector.cross(org_foot_e.vector)
        align_bone_x_axis(self.obj, roll1, roll_axis)
        align_bone_x_axis(self.obj, roll2, roll_axis)
        foot_roll_e.roll = roll2_e.roll

        if make_rocker:
            d = toe_e.y_axis.dot(rocker1_e.x_axis)
            if d >= 0.0:
                flip_bone(self.obj, rocker2)
            else:
                flip_bone(self.obj, rocker1)

        # Object mode, get pose bones
        bpy.ops.object.mode_set(mode='OBJECT')
        pb = self.obj.pose.bones

        foot_p = pb[foot]
        foot_roll_p = pb[foot_roll]
        roll1_p = pb[roll1]
        roll2_p = pb[roll2]
        if make_rocker:
            rocker1_p = pb[rocker1]
            rocker2_p = pb[rocker2]
        toe_p = pb[toe]
        # toe_parent_p = pb[toe_parent]
        toe_parent_socket1_p = pb[toe_parent_socket1]

        # Foot roll control only rotates on x-axis, or x and y if rocker.
        foot_roll_p.rotation_mode = 'XYZ'
        if make_rocker:
            foot_roll_p.lock_rotation = False, False, True
        else:
            foot_roll_p.lock_rotation = False, True, True
        foot_roll_p.lock_location = True, True, True
        foot_roll_p.lock_scale = True, True, True

        # roll and rocker bones set to euler rotation
        roll1_p.rotation_mode = 'XYZ'
        roll2_p.rotation_mode = 'XYZ'
        if make_rocker:
            rocker1_p.rotation_mode = 'XYZ'
            rocker2_p.rotation_mode = 'XYZ'

        # toe_parent constraint
        con = toe_parent_socket1_p.constraints.new('COPY_LOCATION')
        con.name = "copy_location"
        con.target = self.obj
        con.subtarget = toe_parent_socket2

        con = toe_parent_socket1_p.constraints.new('COPY_SCALE')
        con.name = "copy_scale"
        con.target = self.obj
        con.subtarget = toe_parent_socket2

        con = toe_parent_socket1_p.constraints.new(
            'COPY_TRANSFORMS')  # drive with IK switch
        con.name = "fk"
        con.target = self.obj
        con.subtarget = toe_parent_socket2

        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 = foot_p.path_from_id() + '["ikfk_switch"]'
        mod = fcurve.modifiers[0]
        mod.poly_order = 1
        mod.coefficients[0] = 1.0
        mod.coefficients[1] = -1.0

        # Foot roll drivers
        fcurve = roll1_p.driver_add("rotation_euler", 0)
        driver = fcurve.driver
        var = driver.variables.new()
        driver.type = 'SCRIPTED'
        driver.expression = "min(0,var)"
        var.name = "var"
        var.targets[0].id_type = 'OBJECT'
        var.targets[0].id = self.obj
        var.targets[0].data_path = foot_roll_p.path_from_id(
        ) + '.rotation_euler[0]'

        fcurve = roll2_p.driver_add("rotation_euler", 0)
        driver = fcurve.driver
        var = driver.variables.new()
        driver.type = 'SCRIPTED'
        driver.expression = "max(0,var)"
        var.name = "var"
        var.targets[0].id_type = 'OBJECT'
        var.targets[0].id = self.obj
        var.targets[0].data_path = foot_roll_p.path_from_id(
        ) + '.rotation_euler[0]'

        if make_rocker:
            fcurve = rocker1_p.driver_add("rotation_euler", 0)
            driver = fcurve.driver
            var = driver.variables.new()
            driver.type = 'SCRIPTED'
            driver.expression = "max(0,-var)"
            var.name = "var"
            var.targets[0].id_type = 'OBJECT'
            var.targets[0].id = self.obj
            var.targets[0].data_path = foot_roll_p.path_from_id(
            ) + '.rotation_euler[1]'

            fcurve = rocker2_p.driver_add("rotation_euler", 0)
            driver = fcurve.driver
            var = driver.variables.new()
            driver.type = 'SCRIPTED'
            driver.expression = "max(0,var)"
            var.name = "var"
            var.targets[0].id_type = 'OBJECT'
            var.targets[0].id = self.obj
            var.targets[0].data_path = foot_roll_p.path_from_id(
            ) + '.rotation_euler[1]'

        # Constrain toe bone to toe control
        con = pb[self.org_bones[3]].constraints.new('COPY_TRANSFORMS')
        con.name = "copy_transforms"
        con.target = self.obj
        con.subtarget = toe

        # Set layers if specified
        if self.layers:
            foot_roll_p.bone.layers = self.layers
            toe_p.bone.layers = [
                (i[0] or i[1]) for i in zip(toe_p.bone.layers, self.layers)
            ]  # Both FK and IK layers

        # Create widgets
        create_circle_widget(self.obj, toe, radius=0.7, head_tail=0.5)

        ob = create_widget(self.obj, foot_roll)
        if ob is not None:
            verts = [
                (0.3999999761581421, 0.766044557094574, 0.6427875757217407),
                (0.17668449878692627, 3.823702598992895e-08,
                 3.2084670920085046e-08),
                (-0.17668461799621582, 9.874240447516058e-08,
                 8.285470443070153e-08),
                (-0.39999961853027344, 0.7660449147224426, 0.6427879333496094),
                (0.3562471270561218, 0.6159579753875732, 0.5168500542640686),
                (-0.35624682903289795, 0.6159582138061523, 0.5168502926826477),
                (0.20492683351039886, 0.09688037633895874, 0.0812922865152359),
                (-0.20492687821388245, 0.0968804731965065, 0.08129236847162247)
            ]
            edges = [(1, 2), (0, 3), (0, 4), (3, 5), (1, 6), (4, 6), (2, 7),
                     (5, 7)]
            mesh = ob.data
            mesh.from_pydata(verts, edges, [])
            mesh.update()

            mod = ob.modifiers.new("subsurf", 'SUBSURF')
            mod.levels = 2

        ob = create_widget(self.obj, foot)
        if ob is not 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 [thigh, shin, foot, pole, foot_roll, foot_mch]
Example #32
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 upper arm bones
        if self.use_thigh_twist:
            thigh1 = copy_bone(
                self.obj, self.org_bones[0],
                make_deformer_name(strip_org(self.org_bones[0] + ".01")))
            thigh2 = copy_bone(
                self.obj, self.org_bones[0],
                make_deformer_name(strip_org(self.org_bones[0] + ".02")))
            utip = copy_bone(
                self.obj, self.org_bones[0],
                make_mechanism_name(strip_org(self.org_bones[0] + ".tip")))
        else:
            thigh = copy_bone(self.obj, self.org_bones[0],
                              make_deformer_name(strip_org(self.org_bones[0])))

        # Create forearm bones
        if self.use_shin_twist:
            shin1 = copy_bone(
                self.obj, self.org_bones[1],
                make_deformer_name(strip_org(self.org_bones[1] + ".01")))
            shin2 = copy_bone(
                self.obj, self.org_bones[1],
                make_deformer_name(strip_org(self.org_bones[1] + ".02")))
            stip = copy_bone(
                self.obj, self.org_bones[1],
                make_mechanism_name(strip_org(self.org_bones[1] + ".tip")))
        else:
            shin = copy_bone(self.obj, self.org_bones[1],
                             make_deformer_name(strip_org(self.org_bones[1])))

        # Create foot bone
        foot = copy_bone(self.obj, self.org_bones[2],
                         make_deformer_name(strip_org(self.org_bones[2])))

        # Create toe bone
        toe = copy_bone(self.obj, self.org_bones[3],
                        make_deformer_name(strip_org(self.org_bones[3])))

        # Get edit bones
        eb = self.obj.data.edit_bones

        org_thigh_e = eb[self.org_bones[0]]
        if self.use_thigh_twist:
            thigh1_e = eb[thigh1]
            thigh2_e = eb[thigh2]
            utip_e = eb[utip]
        else:
            thigh_e = eb[thigh]

        org_shin_e = eb[self.org_bones[1]]
        if self.use_shin_twist:
            shin1_e = eb[shin1]
            shin2_e = eb[shin2]
            stip_e = eb[stip]
        else:
            shin_e = eb[shin]

        org_foot_e = eb[self.org_bones[2]]
        foot_e = eb[foot]

        org_toe_e = eb[self.org_bones[3]]
        toe_e = eb[toe]

        # Parent and position thigh bones
        if self.use_thigh_twist:
            thigh1_e.use_connect = False
            thigh2_e.use_connect = False
            utip_e.use_connect = False

            thigh1_e.parent = org_thigh_e.parent
            thigh2_e.parent = org_thigh_e
            utip_e.parent = org_thigh_e

            center = Vector((org_thigh_e.head + org_thigh_e.tail) / 2)

            thigh1_e.tail = center
            thigh2_e.head = center
            put_bone(self.obj, utip, org_thigh_e.tail)
            utip_e.length = org_thigh_e.length / 8
        else:
            thigh_e.use_connect = False
            thigh_e.parent = org_thigh_e

        # Parent and position shin bones
        if self.use_shin_twist:
            shin1_e.use_connect = False
            shin2_e.use_connect = False
            stip_e.use_connect = False

            shin1_e.parent = org_shin_e
            shin2_e.parent = org_shin_e
            stip_e.parent = org_shin_e

            center = Vector((org_shin_e.head + org_shin_e.tail) / 2)

            shin1_e.tail = center
            shin2_e.head = center
            put_bone(self.obj, stip, org_shin_e.tail)
            stip_e.length = org_shin_e.length / 8

            # Align roll of shin2 with foot
            align_roll(self.obj, shin2, foot)
        else:
            shin_e.use_connect = False
            shin_e.parent = org_shin_e

        # Parent foot
        foot_e.use_connect = False
        foot_e.parent = org_foot_e

        # Parent toe
        toe_e.use_connect = False
        toe_e.parent = org_toe_e

        # Object mode, get pose bones
        bpy.ops.object.mode_set(mode='OBJECT')
        pb = self.obj.pose.bones

        if self.use_thigh_twist:
            thigh1_p = pb[thigh1]
        if self.use_shin_twist:
            shin2_p = pb[shin2]
        foot_p = pb[foot]

        # Thigh constraints
        if self.use_thigh_twist:
            con = thigh1_p.constraints.new('COPY_LOCATION')
            con.name = "copy_location"
            con.target = self.obj
            con.subtarget = self.org_bones[0]

            con = thigh1_p.constraints.new('COPY_SCALE')
            con.name = "copy_scale"
            con.target = self.obj
            con.subtarget = self.org_bones[0]

            con = thigh1_p.constraints.new('DAMPED_TRACK')
            con.name = "track_to"
            con.target = self.obj
            con.subtarget = utip

        # Shin constraints
        if self.use_shin_twist:
            con = shin2_p.constraints.new('COPY_ROTATION')
            con.name = "copy_rotation"
            con.target = self.obj
            con.subtarget = foot

            con = shin2_p.constraints.new('DAMPED_TRACK')
            con.name = "track_to"
            con.target = self.obj
            con.subtarget = stip
Example #33
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]
    def gen_control(self):
        """ Generate the control rig.

        """
        #---------------------------------
        # Create the hip and rib controls
        bpy.ops.object.mode_set(mode='EDIT')

        # Copy org bones
        hip_control = copy_bone(self.obj, self.org_bones[0],
                                strip_org(self.org_bones[0]))
        rib_control = copy_bone(self.obj, self.org_bones[-1],
                                strip_org(self.org_bones[-1]))
        rib_mch = copy_bone(
            self.obj, self.org_bones[-1],
            make_mechanism_name(strip_org(self.org_bones[-1] + ".follow")))
        hinge = copy_bone(
            self.obj, self.org_bones[0],
            make_mechanism_name(strip_org(self.org_bones[-1]) + ".hinge"))

        eb = self.obj.data.edit_bones

        hip_control_e = eb[hip_control]
        rib_control_e = eb[rib_control]
        rib_mch_e = eb[rib_mch]
        hinge_e = eb[hinge]

        # Parenting
        hip_control_e.use_connect = False
        rib_control_e.use_connect = False
        rib_mch_e.use_connect = False
        hinge_e.use_connect = False

        hinge_e.parent = None
        rib_control_e.parent = hinge_e
        rib_mch_e.parent = rib_control_e

        # Position
        flip_bone(self.obj, hip_control)
        flip_bone(self.obj, hinge)

        hinge_e.length /= 2
        rib_mch_e.length /= 2

        put_bone(self.obj, rib_control, hip_control_e.head)
        put_bone(self.obj, rib_mch, hip_control_e.head)

        bpy.ops.object.mode_set(mode='POSE')
        bpy.ops.object.mode_set(mode='EDIT')
        eb = self.obj.data.edit_bones

        # Switch to object mode
        bpy.ops.object.mode_set(mode='OBJECT')
        pb = self.obj.pose.bones
        hip_control_p = pb[hip_control]
        rib_control_p = pb[rib_control]
        hinge_p = pb[hinge]

        # No translation on rib control
        rib_control_p.lock_location = [True, True, True]

        # Hip does not use local location
        hip_control_p.bone.use_local_location = False

        # Custom hinge property
        prop = rna_idprop_ui_prop_get(rib_control_p, "isolate", create=True)
        rib_control_p["isolate"] = 1.0
        prop["soft_min"] = prop["min"] = 0.0
        prop["soft_max"] = prop["max"] = 1.0

        # Constraints
        con = hinge_p.constraints.new('COPY_LOCATION')
        con.name = "copy_location"
        con.target = self.obj
        con.subtarget = hip_control

        con1 = hinge_p.constraints.new('COPY_ROTATION')
        con1.name = "isolate_off.01"
        con1.target = self.obj
        con1.subtarget = hip_control

        con2 = rib_control_p.constraints.new('COPY_SCALE')
        con2.name = "isolate_off.02"
        con2.target = self.obj
        con2.subtarget = hip_control
        con2.use_offset = True
        con2.target_space = 'LOCAL'
        con2.owner_space = 'LOCAL'

        # Drivers for "isolate_off"
        fcurve = con1.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 = rib_control_p.path_from_id() + '["isolate"]'
        mod = fcurve.modifiers[0]
        mod.poly_order = 1
        mod.coefficients[0] = 1.0
        mod.coefficients[1] = -1.0

        fcurve = con2.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 = rib_control_p.path_from_id() + '["isolate"]'
        mod = fcurve.modifiers[0]
        mod.poly_order = 1
        mod.coefficients[0] = 1.0
        mod.coefficients[1] = -1.0

        # Appearence
        hip_control_p.custom_shape_transform = pb[self.org_bones[0]]
        rib_control_p.custom_shape_transform = pb[self.org_bones[-1]]

        #-------------------------
        # Create flex spine chain

        # Create bones/parenting/positiong
        bpy.ops.object.mode_set(mode='EDIT')
        flex_bones = []
        flex_helpers = []
        prev_bone = None
        for b in self.org_bones:
            # Create bones
            bone = copy_bone(self.obj, b,
                             make_mechanism_name(strip_org(b) + ".flex"))
            helper = copy_bone(self.obj, rib_mch,
                               make_mechanism_name(strip_org(b) + ".flex_h"))
            flex_bones += [bone]
            flex_helpers += [helper]

            eb = self.obj.data.edit_bones
            bone_e = eb[bone]
            helper_e = eb[helper]

            # Parenting
            bone_e.use_connect = False
            helper_e.use_connect = False
            if prev_bone == None:
                helper_e.parent = eb[hip_control]
            bone_e.parent = helper_e

            # Position
            put_bone(self.obj, helper, bone_e.head)
            helper_e.length /= 4

            prev_bone = bone

        # Constraints
        bpy.ops.object.mode_set(mode='OBJECT')
        pb = self.obj.pose.bones
        rib_control_p = pb[rib_control]
        rib_mch_p = pb[rib_mch]

        inc = 1.0 / (len(flex_helpers) - 1)
        inf = 1.0 / (len(flex_helpers) - 1)
        for b in zip(flex_helpers[1:], flex_bones[:-1], self.org_bones[1:]):
            bone_p = pb[b[0]]

            # Scale constraints
            con = bone_p.constraints.new('COPY_SCALE')
            con.name = "copy_scale1"
            con.target = self.obj
            con.subtarget = flex_helpers[0]
            con.influence = 1.0

            con = bone_p.constraints.new('COPY_SCALE')
            con.name = "copy_scale2"
            con.target = self.obj
            con.subtarget = rib_mch
            con.influence = inf

            # Bend constraints
            con = bone_p.constraints.new('COPY_ROTATION')
            con.name = "bend1"
            con.target = self.obj
            con.subtarget = flex_helpers[0]
            con.influence = 1.0

            con = bone_p.constraints.new('COPY_ROTATION')
            con.name = "bend2"
            con.target = self.obj
            con.subtarget = rib_mch
            con.influence = inf

            # If not the rib control
            if b[0] != flex_helpers[-1]:
                # Custom bend property
                prop_name = "bend_" + strip_org(b[2])
                prop = rna_idprop_ui_prop_get(rib_control_p,
                                              prop_name,
                                              create=True)
                rib_control_p[prop_name] = inf
                prop["min"] = 0.0
                prop["max"] = 1.0
                prop["soft_min"] = 0.0
                prop["soft_max"] = 1.0

                # Bend driver
                fcurve = con.driver_add("influence")
                driver = fcurve.driver
                var = driver.variables.new()
                driver.type = 'AVERAGE'
                var.name = prop_name
                var.targets[0].id_type = 'OBJECT'
                var.targets[0].id = self.obj
                var.targets[0].data_path = rib_control_p.path_from_id(
                ) + '["' + prop_name + '"]'

            # Location constraint
            con = bone_p.constraints.new('COPY_LOCATION')
            con.name = "copy_location"
            con.target = self.obj
            con.subtarget = b[1]
            con.head_tail = 1.0

            inf += inc

        #----------------------------
        # Create reverse spine chain

        # Create bones/parenting/positioning
        bpy.ops.object.mode_set(mode='EDIT')
        rev_bones = []
        prev_bone = None
        for b in zip(flex_bones, self.org_bones):
            # Create bones
            bone = copy_bone(self.obj, b[1],
                             make_mechanism_name(strip_org(b[1]) + ".reverse"))
            rev_bones += [bone]
            eb = self.obj.data.edit_bones
            bone_e = eb[bone]

            # Parenting
            bone_e.use_connect = False
            bone_e.parent = eb[b[0]]

            # Position
            flip_bone(self.obj, bone)
            bone_e.tail = Vector(eb[b[0]].head)
            #bone_e.head = Vector(eb[b[0]].tail)
            if prev_bone == None:
                pass  # Position base bone wherever you want, for now do nothing (i.e. position at hips)
            else:
                put_bone(self.obj, bone, eb[prev_bone].tail)

            prev_bone = bone

        # Constraints
        bpy.ops.object.mode_set(mode='OBJECT')
        pb = self.obj.pose.bones
        prev_bone = None
        for bone in rev_bones:
            bone_p = pb[bone]

            con = bone_p.constraints.new('COPY_LOCATION')
            con.name = "copy_location"
            con.target = self.obj
            if prev_bone == None:
                con.subtarget = hip_control  # Position base bone wherever you want, for now hips
            else:
                con.subtarget = prev_bone
                con.head_tail = 1.0
            prev_bone = bone

        #---------------------------------------------
        # Constrain org bones to flex bone's rotation
        pb = self.obj.pose.bones
        for b in zip(self.org_bones, flex_bones):
            con = pb[b[0]].constraints.new('COPY_TRANSFORMS')
            con.name = "copy_rotation"
            con.target = self.obj
            con.subtarget = b[1]

        #---------------------------
        # Create pivot slide system
        pb = self.obj.pose.bones
        bone_p = pb[self.org_bones[0]]
        rib_control_p = pb[rib_control]

        # Custom pivot_slide property
        prop = rna_idprop_ui_prop_get(rib_control_p,
                                      "pivot_slide",
                                      create=True)
        rib_control_p["pivot_slide"] = 1.0 / len(self.org_bones)
        prop["min"] = 0.0
        prop["max"] = 1.0
        prop["soft_min"] = 1.0 / len(self.org_bones)
        prop["soft_max"] = 1.0 - (1.0 / len(self.org_bones))

        # Anchor constraint
        con = bone_p.constraints.new('COPY_LOCATION')
        con.name = "copy_location"
        con.target = self.obj
        con.subtarget = rev_bones[0]

        # Slide constraints
        i = 1
        tot = len(rev_bones)
        for rb in rev_bones:
            con = bone_p.constraints.new('COPY_LOCATION')
            con.name = "slide." + str(i)
            con.target = self.obj
            con.subtarget = rb
            con.head_tail = 1.0

            # Driver
            fcurve = con.driver_add("influence")
            driver = fcurve.driver
            var = driver.variables.new()
            driver.type = 'AVERAGE'
            var.name = "slide"
            var.targets[0].id_type = 'OBJECT'
            var.targets[0].id = self.obj
            var.targets[0].data_path = rib_control_p.path_from_id(
            ) + '["pivot_slide"]'
            mod = fcurve.modifiers[0]
            mod.poly_order = 1
            mod.coefficients[0] = 1 - i
            mod.coefficients[1] = tot

            i += 1

        # Create control widgets
        w1 = create_circle_widget(self.obj,
                                  hip_control,
                                  radius=1.0,
                                  head_tail=1.0)
        w2 = create_circle_widget(self.obj,
                                  rib_control,
                                  radius=1.0,
                                  head_tail=0.0)

        if w1 != None:
            obj_to_bone(w1, self.obj, self.org_bones[0])
        if w2 != None:
            obj_to_bone(w2, self.obj, self.org_bones[-1])

        # Return control names
        return hip_control, rib_control
    def generate(self):
        bpy.ops.object.mode_set(mode='EDIT')

        eb = self.obj.data.edit_bones

        # Create the control bones
        ulimb_ik = copy_bone(
            self.obj, self.org_bones[0],
            pantin_utils.strip_LR_numbers(strip_org(self.org_bones[0])) +
            '.IK' + self.side_suffix)
        flimb_ik = copy_bone(
            self.obj, self.org_bones[1],
            make_mechanism_name(
                pantin_utils.strip_LR_numbers(strip_org(self.org_bones[1])) +
                '.IK' + self.side_suffix))
        elimb_ik = copy_bone(
            self.obj, self.org_bones[2],
            pantin_utils.strip_LR_numbers(strip_org(self.org_bones[2])) +
            '.IK' + self.side_suffix)

        ulimb_str = copy_bone(
            self.obj, self.org_bones[0],
            make_mechanism_name(
                pantin_utils.strip_LR_numbers(strip_org(self.org_bones[0])) +
                ".stretch.ik" + self.side_suffix))
        flimb_str = copy_bone(
            self.obj, self.org_bones[1],
            make_mechanism_name(
                pantin_utils.strip_LR_numbers(strip_org(self.org_bones[1])) +
                ".stretch.ik" + self.side_suffix))
        elimb_str = copy_bone(
            self.obj, self.org_bones[2],
            make_mechanism_name(
                pantin_utils.strip_LR_numbers(strip_org(self.org_bones[2])) +
                ".stretch.ik" + self.side_suffix))

        joint_str = new_bone(
            self.obj,
            pantin_utils.strip_LR_numbers(strip_org(self.org_bones[1])) +
            '.IK' + self.side_suffix)
        eb[joint_str].head = eb[flimb_str].head
        eb[joint_str].tail = (eb[flimb_str].head + Vector(
            (0, 0, 1)) * eb[flimb_str].length / 2)
        align_bone_x_axis(self.obj, joint_str, Vector((-1, 0, 0)))
        # put_bone(self.obj, joint_str, Vector(eb[flimb_str].head))

        # Pelvis follow
        elimb_ik_root = copy_bone(
            self.obj, self.org_bones[2],
            make_mechanism_name(
                pantin_utils.strip_LR_numbers(strip_org(self.org_bones[2])) +
                ".ik_root" + self.side_suffix))
        elimb_ik_parent = copy_bone(
            self.obj, self.org_bones[2],
            make_mechanism_name(
                pantin_utils.strip_LR_numbers(strip_org(self.org_bones[2])) +
                ".ik_parent" + self.side_suffix))
        elimb_ik_socket = copy_bone(
            self.obj, self.org_bones[2],
            make_mechanism_name(
                pantin_utils.strip_LR_numbers(strip_org(self.org_bones[2])) +
                ".ik_socket" + self.side_suffix))

        # Get edit bones
        ulimb_ik_e = eb[ulimb_ik]
        flimb_ik_e = eb[flimb_ik]
        elimb_ik_e = eb[elimb_ik]

        ulimb_str_e = eb[ulimb_str]
        flimb_str_e = eb[flimb_str]
        elimb_str_e = eb[elimb_str]

        joint_str_e = eb[joint_str]

        elimb_ik_root_e = eb[elimb_ik_root]
        elimb_ik_parent_e = eb[elimb_ik_parent]
        elimb_ik_socket_e = eb[elimb_ik_socket]

        # Parenting

        # Side org chain
        for b, o_b in zip(self.side_org_bones[1:], self.org_bones[1:]):
            eb[b].parent = eb[
                pantin_utils.strip_LR_numbers(eb[o_b].parent.name) +
                self.side_suffix]

        if self.org_parent is not None:
            ulimb_ik_e.use_connect = False
            ulimb_ik_e.parent = eb[self.org_parent]

        flimb_ik_e.use_connect = False
        flimb_ik_e.parent = ulimb_ik_e

        elimb_ik_root_e.use_connect = False
        elimb_ik_root_e.parent = None
        elimb_ik_parent_e.use_connect = False
        elimb_ik_parent_e.parent = eb[self.side_org_bones[0]].parent
        elimb_ik_socket_e.use_connect = False
        elimb_ik_socket_e.parent = None
        elimb_ik_e.use_connect = False
        elimb_ik_e.parent = elimb_ik_socket_e

        if self.org_parent is not None:
            ulimb_str_e.use_connect = False
            ulimb_str_e.parent = eb[self.org_parent]

        flimb_str_e.use_connect = False
        flimb_str_e.parent = joint_str_e

        elimb_str_e.use_connect = True
        elimb_str_e.parent = flimb_ik_e

        joint_str_e.use_connect = False
        joint_str_e.parent = ulimb_ik_e

        # Layers
        joint_str_e.layers = elimb_str_e.layers
        # Object mode, get pose bones
        bpy.ops.object.mode_set(mode='OBJECT')
        pb = self.obj.pose.bones

        ulimb_ik_p = pb[ulimb_ik]
        flimb_ik_p = pb[flimb_ik]
        elimb_ik_p = pb[elimb_ik]

        ulimb_str_p = pb[ulimb_str]
        flimb_str_p = pb[flimb_str]
        elimb_str_p = pb[elimb_str]

        joint_str_p = pb[joint_str]

        joint_str_p.lock_location = (False, False, True)
        joint_str_p.lock_rotation = (True, True, False)
        joint_str_p.lock_rotation_w = False
        joint_str_p.lock_scale = (False, False, False)
        joint_str_p.rotation_mode = 'XZY'

        # Set up custom properties
        prop = rna_idprop_ui_prop_get(elimb_ik_p, "pelvis_follow", create=True)
        elimb_ik_p["pelvis_follow"] = int(self.pelvis_follow)
        prop["soft_min"] = 0
        prop["soft_max"] = 1
        prop["min"] = 0
        prop["max"] = 1

        prop = rna_idprop_ui_prop_get(elimb_ik_p, "IK_FK", create=True)
        elimb_ik_p["IK_FK"] = 0
        prop["soft_min"] = 0
        prop["soft_max"] = 1
        prop["min"] = 0
        prop["max"] = 1

        # Constraints
        # Bend hint, ripped off from Rigify' biped
        con = flimb_ik_p.constraints.new('LIMIT_ROTATION')
        con.name = "bend_hint"
        con.use_limit_z = True
        con.min_z = radians(45)
        con.max_z = radians(45)
        con.owner_space = 'LOCAL'

        con = flimb_ik_p.constraints.new('IK')
        con.name = "ik"
        con.target = self.obj
        con.subtarget = elimb_ik
        con.chain_count = 2

        con = ulimb_str_p.constraints.new('COPY_LOCATION')
        con.name = "anchor"
        con.target = self.obj
        con.subtarget = ulimb_ik
        con.target_space = 'LOCAL'
        con.owner_space = 'LOCAL'

        con = elimb_str_p.constraints.new('COPY_ROTATION')
        con.name = "copy rotation"
        con.target = self.obj
        con.subtarget = elimb_ik
        con.target_space = 'POSE'
        con.owner_space = 'POSE'

        con = ulimb_str_p.constraints.new('STRETCH_TO')
        con.name = "stretch to"
        con.target = self.obj
        con.subtarget = joint_str
        con.volume = 'NO_VOLUME'
        con.rest_length = ulimb_str_p.length
        con.keep_axis = 'PLANE_Z'

        con = flimb_str_p.constraints.new('STRETCH_TO')
        con.name = "stretch to"
        con.target = self.obj
        con.subtarget = elimb_str
        con.volume = 'NO_VOLUME'
        con.rest_length = flimb_str_p.length
        con.keep_axis = 'PLANE_Z'

        # Pelvis follow
        con = pb[elimb_ik_socket].constraints.new('COPY_TRANSFORMS')
        con.name = "copy root"
        con.target = self.obj
        con.subtarget = elimb_ik_root

        con = pb[elimb_ik_socket].constraints.new('COPY_TRANSFORMS')
        con.name = "copy socket"
        con.target = self.obj
        con.subtarget = elimb_ik_parent

        # Drivers
        driver = self.obj.driver_add(con.path_from_id("influence"))
        driver.driver.expression = 'pelvis_follow'
        var = driver.driver.variables.new()

        var.type = 'SINGLE_PROP'
        var.name = 'pelvis_follow'
        var.targets[0].id_type = 'OBJECT'
        var.targets[0].id = self.obj
        var.targets[0].data_path = (pb[elimb_ik].path_from_id() +
                                    '["pelvis_follow"]')

        # IK Limits
        ulimb_ik_p.lock_ik_x = True
        ulimb_ik_p.lock_ik_y = True

        flimb_ik_p.lock_ik_x = True
        flimb_ik_p.lock_ik_y = True
        flimb_ik_p.use_ik_limit_z = True
        flimb_ik_p.ik_min_z = radians(self.ik_limits[0])  # 0.0
        flimb_ik_p.ik_max_z = radians(self.ik_limits[1])  # radians(160.0)

        # Arm ik angle fix
        limb_angle = ulimb_ik_p.vector.xz.angle_signed(flimb_ik_p.vector.xz)
        if self.ik_limits[0] < 0:  # folds counterclockwise (arms)
            # has to be slightly less than the original angle
            flimb_ik_p.ik_max_z = -limb_angle - .02
        else:
            # has to be slightly more than the original angle
            flimb_ik_p.ik_min_z = -limb_angle + .02

        return [
            ulimb_ik, ulimb_str, flimb_ik, flimb_str, joint_str, elimb_ik,
            elimb_str
        ]
Example #36
0
    def deform(self):
        """ Generate the deformation rig.
            Just a copy of the original bones, except the first digit which is a twist bone.
        """
        bpy.ops.object.mode_set(mode="EDIT")

        # Create the bones
        # First bone is a twist bone
        if self.use_digit_twist:
            b1a = copy_bone(self.obj, self.org_bones[0], make_deformer_name(strip_org(self.org_bones[0] + ".01")))
            b1b = copy_bone(self.obj, self.org_bones[0], make_deformer_name(strip_org(self.org_bones[0] + ".02")))
            b1tip = copy_bone(self.obj, self.org_bones[0], make_mechanism_name(strip_org(self.org_bones[0] + ".tip")))
        else:
            b1 = copy_bone(self.obj, self.org_bones[0], make_deformer_name(strip_org(self.org_bones[0])))

        # The rest are normal
        bones = []
        for bone in self.org_bones[1:]:
            bones += [copy_bone(self.obj, bone, make_deformer_name(strip_org(bone)))]

        # Position bones
        eb = self.obj.data.edit_bones
        if self.use_digit_twist:
            b1a_e = eb[b1a]
            b1b_e = eb[b1b]
            b1tip_e = eb[b1tip]

            b1tip_e.use_connect = False
            b1tip_e.tail += Vector((0.1, 0, 0))
            b1tip_e.head = b1b_e.tail
            b1tip_e.length = b1a_e.length / 4

            center = (b1a_e.head + b1a_e.tail) / 2
            b1a_e.tail = center
            b1b_e.use_connect = False
            b1b_e.head = center

        # Parenting
        if self.use_digit_twist:
            b1b_e.parent = eb[self.org_bones[0]]
            b1tip_e.parent = eb[self.org_bones[0]]
        else:
            eb[b1].use_connect = False
            eb[b1].parent = eb[self.org_bones[0]]

        for (ba, bb) in zip(bones, self.org_bones[1:]):
            eb[ba].use_connect = False
            eb[ba].parent = eb[bb]

        # Constraints
        if self.use_digit_twist:
            bpy.ops.object.mode_set(mode="OBJECT")
            pb = self.obj.pose.bones

            b1a_p = pb[b1a]

            con = b1a_p.constraints.new("COPY_LOCATION")
            con.name = "copy_location"
            con.target = self.obj
            con.subtarget = self.org_bones[0]

            con = b1a_p.constraints.new("COPY_SCALE")
            con.name = "copy_scale"
            con.target = self.obj
            con.subtarget = self.org_bones[0]

            con = b1a_p.constraints.new("DAMPED_TRACK")
            con.name = "track_to"
            con.target = self.obj
            con.subtarget = b1tip
Example #37
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)
Example #38
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')

        # Figure out the name for the control bone (remove the last .##)
        last_bone = self.org_bones[-1:][0]
        ctrl_name = re.sub("([0-9]+\.)", "", strip_org(last_bone)[::-1], count=1)[::-1]

        # Make control bone
        ctrl = copy_bone(self.obj, last_bone, ctrl_name)

        # Make deformation bones
        def_bones = []
        for bone in self.org_bones:
            b = copy_bone(self.obj, bone, deformer(strip_org(bone)))
            def_bones += [b]

        # Parenting
        eb = self.obj.data.edit_bones

        for d, b in zip(def_bones, self.org_bones):
            eb[d].use_connect = False
            eb[d].parent = eb[b]

        # Constraints
        bpy.ops.object.mode_set(mode='OBJECT')
        pb = self.obj.pose.bones

        i = 0
        div = len(self.org_bones) - 1
        for b in self.org_bones:
            con = pb[b].constraints.new('COPY_TRANSFORMS')
            con.name = "copy_transforms"
            con.target = self.obj
            con.subtarget = ctrl
            con.target_space = 'LOCAL'
            con.owner_space = 'LOCAL'
            con.influence = i / div

            con = pb[b].constraints.new('COPY_ROTATION')
            con.name = "copy_rotation"
            con.target = self.obj
            con.subtarget = ctrl
            con.target_space = 'LOCAL'
            con.owner_space = 'LOCAL'
            if 'X' in self.palm_rotation_axis:
                con.invert_x = True
                con.use_x = True
                con.use_z = False
            else:
                con.invert_z = True
                con.use_x = False
                con.use_z = True
            con.use_y = False

            con.influence = (i / div) - (1 - cos((i * pi / 2) / div))

            i += 1

        # Create control widget
        w = create_widget(self.obj, ctrl)
        if w != None:
            mesh = w.data
            verts = [(0.15780271589756012, 2.086162567138672e-07, -0.30000004172325134), (0.15780259668827057, 1.0, -0.2000001072883606), (-0.15780280530452728, 0.9999999403953552, -0.20000004768371582), (-0.15780259668827057, -2.086162567138672e-07, -0.29999998211860657), (-0.15780256688594818, -2.7089754439657554e-07, 0.30000004172325134), (-0.1578027755022049, 0.9999998807907104, 0.19999995827674866), (0.15780262649059296, 0.9999999403953552, 0.19999989867210388), (0.1578027456998825, 1.4633496903115883e-07, 0.29999998211860657), (0.15780268609523773, 0.2500001788139343, -0.27500003576278687), (-0.15780264139175415, 0.24999985098838806, -0.2749999761581421), (0.15780262649059296, 0.7500000596046448, -0.22500008344650269), (-0.1578027606010437, 0.7499998807907104, -0.2250000238418579), (0.15780265629291534, 0.75, 0.22499991953372955), (0.15780271589756012, 0.2500000596046448, 0.2749999761581421), (-0.15780261158943176, 0.2499997615814209, 0.27500003576278687), (-0.1578027307987213, 0.7499998807907104, 0.22499997913837433)]
            if 'Z' in self.palm_rotation_axis:
                # Flip x/z coordinates
                temp = []
                for v in verts:
                    temp += [(v[2], v[1], v[0])]
                verts = temp
            edges = [(1, 2), (0, 3), (4, 7), (5, 6), (8, 0), (9, 3), (10, 1), (11, 2), (12, 6), (13, 7), (4, 14), (15, 5), (10, 8), (11, 9), (15, 14), (12, 13)]
            mesh.from_pydata(verts, edges, [])
            mesh.update()

            mod = w.modifiers.new("subsurf", 'SUBSURF')
            mod.levels = 2
Example #39
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 upper arm bones
        if self.use_thigh_twist:
            thigh1 = copy_bone(self.obj, self.org_bones[0], make_deformer_name(strip_org(self.org_bones[0] + ".01")))
            thigh2 = copy_bone(self.obj, self.org_bones[0], make_deformer_name(strip_org(self.org_bones[0] + ".02")))
            utip = copy_bone(self.obj, self.org_bones[0], make_mechanism_name(strip_org(self.org_bones[0] + ".tip")))
        else:
            thigh = copy_bone(self.obj, self.org_bones[0], make_deformer_name(strip_org(self.org_bones[0])))

        # Create forearm bones
        if self.use_shin_twist:
            shin1 = copy_bone(self.obj, self.org_bones[1], make_deformer_name(strip_org(self.org_bones[1] + ".01")))
            shin2 = copy_bone(self.obj, self.org_bones[1], make_deformer_name(strip_org(self.org_bones[1] + ".02")))
            stip = copy_bone(self.obj, self.org_bones[1], make_mechanism_name(strip_org(self.org_bones[1] + ".tip")))
        else:
            shin = copy_bone(self.obj, self.org_bones[1], make_deformer_name(strip_org(self.org_bones[1])))

        # Create foot bone
        foot = copy_bone(self.obj, self.org_bones[2], make_deformer_name(strip_org(self.org_bones[2])))

        # Create toe bone
        toe = copy_bone(self.obj, self.org_bones[3], make_deformer_name(strip_org(self.org_bones[3])))

        # Get edit bones
        eb = self.obj.data.edit_bones

        org_thigh_e = eb[self.org_bones[0]]
        if self.use_thigh_twist:
            thigh1_e = eb[thigh1]
            thigh2_e = eb[thigh2]
            utip_e = eb[utip]
        else:
            thigh_e = eb[thigh]

        org_shin_e = eb[self.org_bones[1]]
        if self.use_shin_twist:
            shin1_e = eb[shin1]
            shin2_e = eb[shin2]
            stip_e = eb[stip]
        else:
            shin_e = eb[shin]

        org_foot_e = eb[self.org_bones[2]]
        foot_e = eb[foot]

        org_toe_e = eb[self.org_bones[3]]
        toe_e = eb[toe]

        # Parent and position thigh bones
        if self.use_thigh_twist:
            thigh1_e.use_connect = False
            thigh2_e.use_connect = False
            utip_e.use_connect = False

            thigh1_e.parent = org_thigh_e.parent
            thigh2_e.parent = org_thigh_e
            utip_e.parent = org_thigh_e

            center = Vector((org_thigh_e.head + org_thigh_e.tail) / 2)

            thigh1_e.tail = center
            thigh2_e.head = center
            put_bone(self.obj, utip, org_thigh_e.tail)
            utip_e.length = org_thigh_e.length / 8
        else:
            thigh_e.use_connect = False
            thigh_e.parent = org_thigh_e

        # Parent and position shin bones
        if self.use_shin_twist:
            shin1_e.use_connect = False
            shin2_e.use_connect = False
            stip_e.use_connect = False

            shin1_e.parent = org_shin_e
            shin2_e.parent = org_shin_e
            stip_e.parent = org_shin_e

            center = Vector((org_shin_e.head + org_shin_e.tail) / 2)

            shin1_e.tail = center
            shin2_e.head = center
            put_bone(self.obj, stip, org_shin_e.tail)
            stip_e.length = org_shin_e.length / 8

            # Align roll of shin2 with foot
            align_roll(self.obj, shin2, foot)
        else:
            shin_e.use_connect = False
            shin_e.parent = org_shin_e

        # Parent foot
        foot_e.use_connect = False
        foot_e.parent = org_foot_e

        # Parent toe
        toe_e.use_connect = False
        toe_e.parent = org_toe_e

        # Object mode, get pose bones
        bpy.ops.object.mode_set(mode='OBJECT')
        pb = self.obj.pose.bones

        if self.use_thigh_twist:
            thigh1_p = pb[thigh1]
        if self.use_shin_twist:
            shin2_p = pb[shin2]
        # foot_p = pb[foot]  # UNUSED

        # Thigh constraints
        if self.use_thigh_twist:
            con = thigh1_p.constraints.new('COPY_LOCATION')
            con.name = "copy_location"
            con.target = self.obj
            con.subtarget = self.org_bones[0]

            con = thigh1_p.constraints.new('COPY_SCALE')
            con.name = "copy_scale"
            con.target = self.obj
            con.subtarget = self.org_bones[0]

            con = thigh1_p.constraints.new('DAMPED_TRACK')
            con.name = "track_to"
            con.target = self.obj
            con.subtarget = utip

        # Shin constraints
        if self.use_shin_twist:
            con = shin2_p.constraints.new('COPY_ROTATION')
            con.name = "copy_rotation"
            con.target = self.obj
            con.subtarget = foot

            con = shin2_p.constraints.new('DAMPED_TRACK')
            con.name = "track_to"
            con.target = self.obj
            con.subtarget = stip
Example #40
0
    def gen_control(self):
        """ Generate the control rig.

        """
        #---------------------------------
        # Create the neck and head controls
        bpy.ops.object.mode_set(mode='EDIT')

        # Create bones
        neck_ctrl = copy_bone(self.obj, self.org_bones[0], strip_org(self.org_bones[0]))
        neck_follow = copy_bone(self.obj, self.org_bones[-1], make_mechanism_name(strip_org(self.org_bones[0] + ".follow")))
        neck_child = new_bone(self.obj, make_mechanism_name(strip_org(self.org_bones[0] + ".child")))

        head_ctrl = copy_bone(self.obj, self.org_bones[-1], strip_org(self.org_bones[-1]))
        head_mch = new_bone(self.obj, make_mechanism_name(strip_org(self.org_bones[-1])))
        if self.isolate:
            head_socket1 = copy_bone(self.obj, self.org_bones[-1], make_mechanism_name(strip_org(self.org_bones[-1] + ".socket1")))
            head_socket2 = copy_bone(self.obj, self.org_bones[-1], make_mechanism_name(strip_org(self.org_bones[-1] + ".socket2")))

        # Create neck chain bones
        neck = []
        helpers = []
        for name in self.org_bones:
            neck += [copy_bone(self.obj, name, make_mechanism_name(strip_org(name)))]
            helpers += [copy_bone(self.obj, neck_child, make_mechanism_name(strip_org(name + ".02")))]

        # Fetch edit bones
        eb = self.obj.data.edit_bones

        neck_ctrl_e = eb[neck_ctrl]
        neck_follow_e = eb[neck_follow]
        neck_child_e = eb[neck_child]
        head_ctrl_e = eb[head_ctrl]
        head_mch_e = eb[head_mch]
        if self.isolate:
            head_socket1_e = eb[head_socket1]
            head_socket2_e = eb[head_socket2]

        # Parenting
        head_ctrl_e.use_connect = False
        head_ctrl_e.parent = neck_ctrl_e.parent
        head_mch_e.use_connect = False
        head_mch_e.parent = head_ctrl_e

        if self.isolate:
            head_socket1_e.use_connect = False
            head_socket1_e.parent = neck_ctrl_e.parent

            head_socket2_e.use_connect = False
            head_socket2_e.parent = None

            head_ctrl_e.parent = head_socket2_e

        for (name1, name2) in zip(neck, helpers):
            eb[name1].use_connect = False
            eb[name1].parent = eb[name2]
            eb[name2].use_connect = False
            eb[name2].parent = neck_ctrl_e.parent

        neck_follow_e.use_connect = False
        neck_follow_e.parent = neck_ctrl_e.parent
        neck_child_e.use_connect = False
        neck_child_e.parent = neck_ctrl_e
        neck_ctrl_e.parent = neck_follow_e

        # Position
        put_bone(self.obj, neck_follow, neck_ctrl_e.head)
        put_bone(self.obj, neck_child, neck_ctrl_e.head)
        put_bone(self.obj, head_ctrl, neck_ctrl_e.head)
        put_bone(self.obj, head_mch, neck_ctrl_e.head)
        head_mch_e.length = head_ctrl_e.length / 2
        neck_child_e.length = neck_ctrl_e.length / 2

        if self.isolate:
            put_bone(self.obj, head_socket1, neck_ctrl_e.head)
            head_mch_e.length /= 2

            put_bone(self.obj, head_socket2, neck_ctrl_e.head)
            head_mch_e.length /= 3

        for (name1, name2) in zip(neck, helpers):
            put_bone(self.obj, name2, eb[name1].head)
            eb[name2].length = eb[name1].length / 2

        # Switch to object mode
        bpy.ops.object.mode_set(mode='OBJECT')
        pb = self.obj.pose.bones
        neck_ctrl_p = pb[neck_ctrl]
        neck_follow_p = pb[neck_follow]
        # neck_child_p = pb[neck_child]  # UNUSED
        head_ctrl_p = pb[head_ctrl]
        if self.isolate:
            # head_socket1_p = pb[head_socket1]  # UNUSED
            head_socket2_p = pb[head_socket2]

        # Custom bone appearance
        neck_ctrl_p.custom_shape_transform = pb[self.org_bones[(len(self.org_bones) - 1) // 2]]
        head_ctrl_p.custom_shape_transform = pb[self.org_bones[-1]]

        # Custom properties
        prop = rna_idprop_ui_prop_get(head_ctrl_p, "inf_extent", create=True)
        head_ctrl_p["inf_extent"] = 0.5
        prop["min"] = 0.0
        prop["max"] = 1.0
        prop["soft_min"] = 0.0
        prop["soft_max"] = 1.0

        prop = rna_idprop_ui_prop_get(head_ctrl_p, "neck_follow", create=True)
        head_ctrl_p["neck_follow"] = 1.0
        prop["min"] = 0.0
        prop["max"] = 2.0
        prop["soft_min"] = 0.0
        prop["soft_max"] = 1.0

        if self.isolate:
            prop = rna_idprop_ui_prop_get(head_ctrl_p, "isolate", create=True)
            head_ctrl_p["isolate"] = 0.0
            prop["min"] = 0.0
            prop["max"] = 1.0
            prop["soft_min"] = 0.0
            prop["soft_max"] = 1.0

        # Constraints

        # Neck follow
        con = neck_follow_p.constraints.new('COPY_ROTATION')
        con.name = "copy_rotation"
        con.target = self.obj
        con.subtarget = head_ctrl

        fcurve = con.driver_add("influence")
        driver = fcurve.driver
        var = driver.variables.new()
        driver.type = 'SCRIPTED'
        var.name = "follow"
        var.targets[0].id_type = 'OBJECT'
        var.targets[0].id = self.obj
        var.targets[0].data_path = head_ctrl_p.path_from_id() + '["neck_follow"]'
        driver.expression = "follow / 2"

        # Isolate
        if self.isolate:
            con = head_socket2_p.constraints.new('COPY_LOCATION')
            con.name = "copy_location"
            con.target = self.obj
            con.subtarget = head_socket1

            con = head_socket2_p.constraints.new('COPY_TRANSFORMS')
            con.name = "copy_transforms"
            con.target = self.obj
            con.subtarget = head_socket1

            fcurve = con.driver_add("influence")
            driver = fcurve.driver
            var = driver.variables.new()
            driver.type = 'SCRIPTED'
            var.name = "isolate"
            var.targets[0].id_type = 'OBJECT'
            var.targets[0].id = self.obj
            var.targets[0].data_path = head_ctrl_p.path_from_id() + '["isolate"]'
            driver.expression = "1.0 - isolate"

        # Neck chain
        first = True
        prev = None
        i = 0
        l = len(neck)
        for (name1, name2, org_name) in zip(neck, helpers, self.org_bones):
            con = pb[org_name].constraints.new('COPY_TRANSFORMS')
            con.name = "copy_transforms"
            con.target = self.obj
            con.subtarget = name1

            n_con = pb[name2].constraints.new('COPY_TRANSFORMS')
            n_con.name = "neck"
            n_con.target = self.obj
            n_con.subtarget = neck_child

            h_con = pb[name2].constraints.new('COPY_TRANSFORMS')
            h_con.name = "head"
            h_con.target = self.obj
            h_con.subtarget = head_mch

            con = pb[name2].constraints.new('COPY_LOCATION')
            con.name = "anchor"
            con.target = self.obj
            if first:
                con.subtarget = neck_ctrl
            else:
                con.subtarget = prev
                con.head_tail = 1.0

            # Drivers
            n = (i + 1) / l

            # Neck influence
            fcurve = n_con.driver_add("influence")
            driver = fcurve.driver
            var = driver.variables.new()
            driver.type = 'SCRIPTED'
            var.name = "ext"
            var.targets[0].id_type = 'OBJECT'
            var.targets[0].id = self.obj
            var.targets[0].data_path = head_ctrl_p.path_from_id() + '["inf_extent"]'
            driver.expression = "1.0 if (%.4f > (1.0-ext) or (1.0-ext) == 0.0) else (%.4f / (1.0-ext))" % (n, n)

            # Head influence
            if (i + 1) == l:
                h_con.influence = 1.0
            else:
                fcurve = h_con.driver_add("influence")
                driver = fcurve.driver
                var = driver.variables.new()
                driver.type = 'SCRIPTED'
                var.name = "ext"
                var.targets[0].id_type = 'OBJECT'
                var.targets[0].id = self.obj
                var.targets[0].data_path = head_ctrl_p.path_from_id() + '["inf_extent"]'
                driver.expression = "0.0 if (%.4f <= (1.0-ext)) else ((%.4f - (1.0-ext)) / ext)" % (n, n)

            first = False
            prev = name1
            i += 1

        # Create control widgets
        w1 = create_circle_widget(self.obj, neck_ctrl, radius=1.0, head_tail=0.5)
        w2 = create_circle_widget(self.obj, head_ctrl, radius=1.0, head_tail=0.5)

        if w1 != None:
            obj_to_bone(w1, self.obj, self.org_bones[(len(self.org_bones) - 1) // 2])
        if w2 != None:
            obj_to_bone(w2, self.obj, self.org_bones[-1])

        # Return control bones
        return (head_ctrl, neck_ctrl)
Example #41
0
    def gen_control(self):
        """ Generate the control rig.

        """
        bpy.ops.object.mode_set(mode='EDIT')
        eb = self.obj.data.edit_bones
        #-------------------------
        # Get rest slide position
        a = self.pivot_rest * len(self.org_bones)
        i = floor(a)
        a -= i
        if i == len(self.org_bones):
            i -= 1
            a = 1.0

        pivot_rest_pos = eb[self.org_bones[i]].head.copy()
        pivot_rest_pos += eb[self.org_bones[i]].vector * a

        #----------------------
        # Create controls

        # Create control bones
        controls = []
        for i in self.control_indices:
            name = copy_bone(self.obj, self.org_bones[i],
                             strip_org(self.org_bones[i]))
            controls += [name]

        # Create control parents
        control_parents = []
        for i in self.control_indices[1:-1]:
            name = new_bone(
                self.obj,
                make_mechanism_name("par_" + strip_org(self.org_bones[i])))
            control_parents += [name]

        # Create sub-control bones
        subcontrols = []
        for i in self.control_indices:
            name = new_bone(
                self.obj,
                make_mechanism_name("sub_" + strip_org(self.org_bones[i])))
            subcontrols += [name]

        # Create main control bone
        main_control = new_bone(self.obj, self.params.spine_main_control_name)

        # Create main control WGT bones
        main_wgt1 = new_bone(
            self.obj,
            make_mechanism_name(self.params.spine_main_control_name + ".01"))
        main_wgt2 = new_bone(
            self.obj,
            make_mechanism_name(self.params.spine_main_control_name + ".02"))

        eb = self.obj.data.edit_bones

        # Parent the main control
        eb[main_control].use_connect = False
        eb[main_control].parent = eb[self.org_bones[0]].parent

        # Parent the main WGTs
        eb[main_wgt1].use_connect = False
        eb[main_wgt1].parent = eb[main_control]
        eb[main_wgt2].use_connect = False
        eb[main_wgt2].parent = eb[main_wgt1]

        # Parent the controls and sub-controls
        for name, subname in zip(controls, subcontrols):
            eb[name].use_connect = False
            eb[name].parent = eb[main_control]
            eb[subname].use_connect = False
            eb[subname].parent = eb[name]

        # Parent the control parents
        for name, par_name in zip(controls[1:-1], control_parents):
            eb[par_name].use_connect = False
            eb[par_name].parent = eb[main_control]
            eb[name].parent = eb[par_name]

        # Position the main bone
        put_bone(self.obj, main_control, pivot_rest_pos)
        eb[main_control].length = sum([eb[b].length
                                       for b in self.org_bones]) / 2

        # Position the main WGTs
        eb[main_wgt1].tail = (0.0, 0.0,
                              sum([eb[b].length for b in self.org_bones]) / 4)
        eb[main_wgt2].length = sum([eb[b].length for b in self.org_bones]) / 4
        put_bone(self.obj, main_wgt1, pivot_rest_pos)
        put_bone(self.obj, main_wgt2, pivot_rest_pos)

        # Position the controls and sub-controls
        pos = eb[controls[0]].head.copy()
        for name, subname in zip(controls, subcontrols):
            put_bone(self.obj, name, pivot_rest_pos)
            put_bone(self.obj, subname, pivot_rest_pos)
            eb[subname].length = eb[name].length / 3

        # Position the control parents
        for name, par_name in zip(controls[1:-1], control_parents):
            put_bone(self.obj, par_name, pivot_rest_pos)
            eb[par_name].length = eb[name].length / 2

        #-----------------------------------------
        # Control bone constraints and properties
        bpy.ops.object.mode_set(mode='OBJECT')
        pb = self.obj.pose.bones

        # Lock control locations
        for name in controls:
            bone = pb[name]
            bone.lock_location = True, True, True

        # Main control doesn't use local location
        pb[main_control].bone.use_local_location = False

        # Intermediate controls follow hips and spine
        for name, par_name, i in zip(controls[1:-1], control_parents,
                                     self.control_indices[1:-1]):
            bone = pb[par_name]

            # Custom bend_alpha property
            prop = rna_idprop_ui_prop_get(pb[name], "bend_alpha", create=True)
            pb[name]["bend_alpha"] = i / (len(self.org_bones) - 1
                                          )  # set bend alpha
            prop["min"] = 0.0
            prop["max"] = 1.0
            prop["soft_min"] = 0.0
            prop["soft_max"] = 1.0

            # Custom auto_rotate
            prop = rna_idprop_ui_prop_get(pb[name], "auto_rotate", create=True)
            pb[name]["auto_rotate"] = 1.0
            prop["min"] = 0.0
            prop["max"] = 1.0
            prop["soft_min"] = 0.0
            prop["soft_max"] = 1.0

            # Constraints
            con1 = bone.constraints.new('COPY_TRANSFORMS')
            con1.name = "copy_transforms"
            con1.target = self.obj
            con1.subtarget = subcontrols[0]

            con2 = bone.constraints.new('COPY_TRANSFORMS')
            con2.name = "copy_transforms"
            con2.target = self.obj
            con2.subtarget = subcontrols[-1]

            # Drivers
            fcurve = con1.driver_add("influence")
            driver = fcurve.driver
            driver.type = 'AVERAGE'
            var = driver.variables.new()
            var.name = "auto"
            var.targets[0].id_type = 'OBJECT'
            var.targets[0].id = self.obj
            var.targets[0].data_path = pb[name].path_from_id(
            ) + '["auto_rotate"]'

            fcurve = con2.driver_add("influence")
            driver = fcurve.driver
            driver.type = 'SCRIPTED'
            driver.expression = "alpha * auto"
            var = driver.variables.new()
            var.name = "alpha"
            var.targets[0].id_type = 'OBJECT'
            var.targets[0].id = self.obj
            var.targets[0].data_path = pb[name].path_from_id(
            ) + '["bend_alpha"]'
            var = driver.variables.new()
            var.name = "auto"
            var.targets[0].id_type = 'OBJECT'
            var.targets[0].id = self.obj
            var.targets[0].data_path = pb[name].path_from_id(
            ) + '["auto_rotate"]'

        #-------------------------
        # Create flex spine chain
        bpy.ops.object.mode_set(mode='EDIT')
        flex_bones = []
        flex_subs = []
        prev_bone = None
        for b in self.org_bones:
            # Create bones
            bone = copy_bone(self.obj, b,
                             make_mechanism_name(strip_org(b) + ".flex"))
            sub = new_bone(self.obj,
                           make_mechanism_name(strip_org(b) + ".flex_s"))
            flex_bones += [bone]
            flex_subs += [sub]

            eb = self.obj.data.edit_bones
            bone_e = eb[bone]
            sub_e = eb[sub]

            # Parenting
            bone_e.use_connect = False
            sub_e.use_connect = False
            if prev_bone is None:
                sub_e.parent = eb[controls[0]]
            else:
                sub_e.parent = eb[prev_bone]
            bone_e.parent = sub_e

            # Position
            put_bone(self.obj, sub, bone_e.head)
            sub_e.length = bone_e.length / 4
            if prev_bone is not None:
                sub_e.use_connect = True

            prev_bone = bone

        #----------------------------
        # Create reverse spine chain

        # Create bones/parenting/positioning
        bpy.ops.object.mode_set(mode='EDIT')
        rev_bones = []
        prev_bone = None
        for b in zip(flex_bones, self.org_bones):
            # Create bones
            bone = copy_bone(self.obj, b[1],
                             make_mechanism_name(strip_org(b[1]) + ".reverse"))
            rev_bones += [bone]
            eb = self.obj.data.edit_bones
            bone_e = eb[bone]

            # Parenting
            bone_e.use_connect = False
            bone_e.parent = eb[b[0]]

            # Position
            flip_bone(self.obj, bone)
            bone_e.tail = Vector(eb[b[0]].head)
            #bone_e.head = Vector(eb[b[0]].tail)
            if prev_bone is None:
                put_bone(self.obj, bone, pivot_rest_pos)
            else:
                put_bone(self.obj, bone, eb[prev_bone].tail)

            prev_bone = bone

        # Constraints
        bpy.ops.object.mode_set(mode='OBJECT')
        pb = self.obj.pose.bones
        prev_bone = None
        for bone in rev_bones:
            bone_p = pb[bone]

            con = bone_p.constraints.new('COPY_LOCATION')
            con.name = "copy_location"
            con.target = self.obj
            if prev_bone is None:
                con.subtarget = main_control
            else:
                con.subtarget = prev_bone
                con.head_tail = 1.0
            prev_bone = bone

        #----------------------------------------
        # Constrain original bones to flex spine
        bpy.ops.object.mode_set(mode='OBJECT')
        pb = self.obj.pose.bones

        for obone, fbone in zip(self.org_bones, flex_bones):
            con = pb[obone].constraints.new('COPY_TRANSFORMS')
            con.name = "copy_transforms"
            con.target = self.obj
            con.subtarget = fbone

        #---------------------------
        # Create pivot slide system
        pb = self.obj.pose.bones
        bone_p = pb[self.org_bones[0]]
        main_control_p = pb[main_control]

        # Custom pivot_slide property
        prop = rna_idprop_ui_prop_get(main_control_p,
                                      "pivot_slide",
                                      create=True)
        main_control_p["pivot_slide"] = self.pivot_rest
        prop["min"] = 0.0
        prop["max"] = 1.0
        prop["soft_min"] = 1.0 / len(self.org_bones)
        prop["soft_max"] = 1.0 - (1.0 / len(self.org_bones))

        # Anchor constraints
        con = bone_p.constraints.new('COPY_LOCATION')
        con.name = "copy_location"
        con.target = self.obj
        con.subtarget = rev_bones[0]

        con = pb[main_wgt1].constraints.new('COPY_ROTATION')
        con.name = "copy_rotation"
        con.target = self.obj
        con.subtarget = rev_bones[0]

        # Slide constraints
        i = 1
        tot = len(rev_bones)
        for rb in rev_bones:
            con = bone_p.constraints.new('COPY_LOCATION')
            con.name = "slide." + str(i)
            con.target = self.obj
            con.subtarget = rb
            con.head_tail = 1.0

            # Driver
            fcurve = con.driver_add("influence")
            driver = fcurve.driver
            var = driver.variables.new()
            driver.type = 'AVERAGE'
            var.name = "slide"
            var.targets[0].id_type = 'OBJECT'
            var.targets[0].id = self.obj
            var.targets[0].data_path = main_control_p.path_from_id(
            ) + '["pivot_slide"]'
            mod = fcurve.modifiers[0]
            mod.poly_order = 1
            mod.coefficients[0] = 1 - i
            mod.coefficients[1] = tot

            # Main WGT
            con = pb[main_wgt1].constraints.new('COPY_ROTATION')
            con.name = "slide." + str(i)
            con.target = self.obj
            con.subtarget = rb

            # Driver
            fcurve = con.driver_add("influence")
            driver = fcurve.driver
            var = driver.variables.new()
            driver.type = 'AVERAGE'
            var.name = "slide"
            var.targets[0].id_type = 'OBJECT'
            var.targets[0].id = self.obj
            var.targets[0].data_path = main_control_p.path_from_id(
            ) + '["pivot_slide"]'
            mod = fcurve.modifiers[0]
            mod.poly_order = 1
            mod.coefficients[0] = 1.5 - i
            mod.coefficients[1] = tot

            i += 1

        #----------------------------------
        # Constrain flex spine to controls
        bpy.ops.object.mode_set(mode='OBJECT')
        pb = self.obj.pose.bones

        # Constrain the bones that correspond exactly to the controls
        for i, name in zip(self.control_indices, subcontrols):
            con = pb[flex_subs[i]].constraints.new('COPY_TRANSFORMS')
            con.name = "copy_transforms"
            con.target = self.obj
            con.subtarget = name

        # Constrain the bones in-between the controls
        for i, j, name1, name2 in zip(self.control_indices,
                                      self.control_indices[1:], subcontrols,
                                      subcontrols[1:]):
            if (i + 1) < j:
                for n in range(i + 1, j):
                    bone = pb[flex_subs[n]]
                    # Custom bend_alpha property
                    prop = rna_idprop_ui_prop_get(bone,
                                                  "bend_alpha",
                                                  create=True)
                    bone["bend_alpha"] = (n - i) / (j - i)  # set bend alpha
                    prop["min"] = 0.0
                    prop["max"] = 1.0
                    prop["soft_min"] = 0.0
                    prop["soft_max"] = 1.0

                    con = bone.constraints.new('COPY_TRANSFORMS')
                    con.name = "copy_transforms"
                    con.target = self.obj
                    con.subtarget = name1

                    con = bone.constraints.new('COPY_TRANSFORMS')
                    con.name = "copy_transforms"
                    con.target = self.obj
                    con.subtarget = name2

                    # Driver
                    fcurve = con.driver_add("influence")
                    driver = fcurve.driver
                    var = driver.variables.new()
                    driver.type = 'AVERAGE'
                    var.name = "alpha"
                    var.targets[0].id_type = 'OBJECT'
                    var.targets[0].id = self.obj
                    var.targets[0].data_path = bone.path_from_id(
                    ) + '["bend_alpha"]'

        #-------------
        # Final stuff
        bpy.ops.object.mode_set(mode='OBJECT')
        pb = self.obj.pose.bones

        # Control appearance
        # Main
        pb[main_control].custom_shape_transform = pb[main_wgt2]
        w = create_compass_widget(self.obj, main_control)
        if w != None:
            obj_to_bone(w, self.obj, main_wgt2)

        # Spines
        for name, i in zip(controls[1:-1], self.control_indices[1:-1]):
            pb[name].custom_shape_transform = pb[self.org_bones[i]]
            # Create control widgets
            w = create_circle_widget(self.obj,
                                     name,
                                     radius=1.0,
                                     head_tail=0.5,
                                     with_line=True)
            if w != None:
                obj_to_bone(w, self.obj, self.org_bones[i])
        # Hips
        pb[controls[0]].custom_shape_transform = pb[self.org_bones[0]]
        # Create control widgets
        w = create_circle_widget(self.obj,
                                 controls[0],
                                 radius=1.0,
                                 head_tail=0.5,
                                 with_line=True)
        if w != None:
            obj_to_bone(w, self.obj, self.org_bones[0])

        # Ribs
        pb[controls[-1]].custom_shape_transform = pb[self.org_bones[-1]]
        # Create control widgets
        w = create_circle_widget(self.obj,
                                 controls[-1],
                                 radius=1.0,
                                 head_tail=0.5,
                                 with_line=True)
        if w != None:
            obj_to_bone(w, self.obj, self.org_bones[-1])

        # Layers
        pb[main_control].bone.layers = pb[self.org_bones[0]].bone.layers

        return [main_control] + controls
Example #42
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 deformation and control bone chains.
        # Just copies of the original chain.
        def_chain = []
        ctrl_chain = []
        for i in range(len(self.org_bones)):
            name = self.org_bones[i]

            # Control bone
            if self.make_controls:
                # Copy
                ctrl_bone = copy_bone(self.obj, name)
                eb = self.obj.data.edit_bones
                ctrl_bone_e = eb[ctrl_bone]
                # Name
                ctrl_bone_e.name = strip_org(name)
                # Parenting
                if i == 0:
                    # First bone
                    ctrl_bone_e.parent = eb[self.org_bones[0]].parent
                else:
                    # The rest
                    ctrl_bone_e.parent = eb[ctrl_chain[-1]]
                # Add to list
                ctrl_chain += [ctrl_bone_e.name]
            else:
                ctrl_chain += [None]

            # Deformation bone
            if self.make_deforms:
                # Copy
                def_bone = copy_bone(self.obj, name)
                eb = self.obj.data.edit_bones
                def_bone_e = eb[def_bone]
                # Name
                def_bone_e.name = make_deformer_name(strip_org(name))
                # Parenting
                if i == 0:
                    # First bone
                    def_bone_e.parent = eb[self.org_bones[0]].parent
                else:
                    # The rest
                    def_bone_e.parent = eb[def_chain[-1]]
                # Add to list
                def_chain += [def_bone_e.name]
            else:
                def_chain += [None]

        bpy.ops.object.mode_set(mode='OBJECT')
        pb = self.obj.pose.bones

        # Constraints for org and def
        for org, ctrl, defrm in zip(self.org_bones, ctrl_chain, def_chain):
            if self.make_controls:
                con = pb[org].constraints.new('COPY_TRANSFORMS')
                con.name = "copy_transforms"
                con.target = self.obj
                con.subtarget = ctrl

            if self.make_deforms:
                con = pb[defrm].constraints.new('COPY_TRANSFORMS')
                con.name = "copy_transforms"
                con.target = self.obj
                con.subtarget = org

        # Create control widgets
        if self.make_controls:
            for bone in ctrl_chain:
                create_bone_widget(self.obj, bone)
Example #43
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 upper arm bones
        if self.use_upper_arm_twist:
            uarm1 = copy_bone(self.obj, self.org_bones[0], make_deformer_name(strip_org(self.org_bones[0] + ".01")))
            uarm2 = copy_bone(self.obj, self.org_bones[0], make_deformer_name(strip_org(self.org_bones[0] + ".02")))
            utip = copy_bone(self.obj, self.org_bones[0], make_mechanism_name(strip_org(self.org_bones[0] + ".tip")))
        else:
            uarm = copy_bone(self.obj, self.org_bones[0], make_deformer_name(strip_org(self.org_bones[0])))

        # Create forearm bones
        if self.use_forearm_twist:
            farm1 = copy_bone(self.obj, self.org_bones[1], make_deformer_name(strip_org(self.org_bones[1] + ".01")))
            farm2 = copy_bone(self.obj, self.org_bones[1], make_deformer_name(strip_org(self.org_bones[1] + ".02")))
            ftip = copy_bone(self.obj, self.org_bones[1], make_mechanism_name(strip_org(self.org_bones[1] + ".tip")))
        else:
            farm = copy_bone(self.obj, self.org_bones[1], make_deformer_name(strip_org(self.org_bones[1])))

        # Create hand bone
        hand = copy_bone(self.obj, self.org_bones[2], make_deformer_name(strip_org(self.org_bones[2])))

        # Get edit bones
        eb = self.obj.data.edit_bones

        org_uarm_e = eb[self.org_bones[0]]
        if self.use_upper_arm_twist:
            uarm1_e = eb[uarm1]
            uarm2_e = eb[uarm2]
            utip_e = eb[utip]
        else:
            uarm_e = eb[uarm]

        org_farm_e = eb[self.org_bones[1]]
        if self.use_forearm_twist:
            farm1_e = eb[farm1]
            farm2_e = eb[farm2]
            ftip_e = eb[ftip]
        else:
            farm_e = eb[farm]

        org_hand_e = eb[self.org_bones[2]]
        hand_e = eb[hand]

        # Parent and position upper arm bones
        if self.use_upper_arm_twist:
            uarm1_e.use_connect = False
            uarm2_e.use_connect = False
            utip_e.use_connect = False

            uarm1_e.parent = org_uarm_e.parent
            uarm2_e.parent = org_uarm_e
            utip_e.parent = org_uarm_e

            center = Vector((org_uarm_e.head + org_uarm_e.tail) / 2)

            uarm1_e.tail = center
            uarm2_e.head = center
            put_bone(self.obj, utip, org_uarm_e.tail)
            utip_e.length = org_uarm_e.length / 8
        else:
            uarm_e.use_connect = False
            uarm_e.parent = org_uarm_e

        # Parent and position forearm bones
        if self.use_forearm_twist:
            farm1_e.use_connect = False
            farm2_e.use_connect = False
            ftip_e.use_connect = False

            farm1_e.parent = org_farm_e
            farm2_e.parent = org_farm_e
            ftip_e.parent = org_farm_e

            center = Vector((org_farm_e.head + org_farm_e.tail) / 2)

            farm1_e.tail = center
            farm2_e.head = center
            put_bone(self.obj, ftip, org_farm_e.tail)
            ftip_e.length = org_farm_e.length / 8

            # Align roll of farm2 with hand
            align_roll(self.obj, farm2, hand)
        else:
            farm_e.use_connect = False
            farm_e.parent = org_farm_e

        # Parent hand
        hand_e.use_connect = False
        hand_e.parent = org_hand_e

        # Object mode, get pose bones
        bpy.ops.object.mode_set(mode='OBJECT')
        pb = self.obj.pose.bones

        if self.use_upper_arm_twist:
            uarm1_p = pb[uarm1]
        if self.use_forearm_twist:
            farm2_p = pb[farm2]
        # hand_p = pb[hand]  # UNUSED

        # Upper arm constraints
        if self.use_upper_arm_twist:
            con = uarm1_p.constraints.new('COPY_LOCATION')
            con.name = "copy_location"
            con.target = self.obj
            con.subtarget = self.org_bones[0]

            con = uarm1_p.constraints.new('COPY_SCALE')
            con.name = "copy_scale"
            con.target = self.obj
            con.subtarget = self.org_bones[0]

            con = uarm1_p.constraints.new('DAMPED_TRACK')
            con.name = "track_to"
            con.target = self.obj
            con.subtarget = utip

        # Forearm constraints
        if self.use_forearm_twist:
            con = farm2_p.constraints.new('COPY_ROTATION')
            con.name = "copy_rotation"
            con.target = self.obj
            con.subtarget = hand

            con = farm2_p.constraints.new('DAMPED_TRACK')
            con.name = "track_to"
            con.target = self.obj
            con.subtarget = ftip
Example #44
0
    def gen_control(self):
        """ Generate the control rig.

        """
        bpy.ops.object.mode_set(mode='EDIT')
        eb = self.obj.data.edit_bones
        #-------------------------
        # Get rest slide position
        a = self.pivot_rest * len(self.org_bones)
        i = floor(a)
        a -= i
        if i == len(self.org_bones):
            i -= 1
            a = 1.0

        pivot_rest_pos = eb[self.org_bones[i]].head.copy()
        pivot_rest_pos += eb[self.org_bones[i]].vector * a

        #----------------------
        # Create controls

        # Create control bones
        controls = []
        for i in self.control_indices:
            name = copy_bone(self.obj, self.org_bones[i], strip_org(self.org_bones[i]))
            controls += [name]

        # Create control parents
        control_parents = []
        for i in self.control_indices[1:-1]:
            name = new_bone(self.obj, make_mechanism_name("par_" + strip_org(self.org_bones[i])))
            control_parents += [name]

        # Create sub-control bones
        subcontrols = []
        for i in self.control_indices:
            name = new_bone(self.obj, make_mechanism_name("sub_" + strip_org(self.org_bones[i])))
            subcontrols += [name]

        # Create main control bone
        main_control = new_bone(self.obj, self.params.spine_main_control_name)

        # Create main control WGT bones
        main_wgt1 = new_bone(self.obj, make_mechanism_name(self.params.spine_main_control_name + ".01"))
        main_wgt2 = new_bone(self.obj, make_mechanism_name(self.params.spine_main_control_name + ".02"))

        eb = self.obj.data.edit_bones

        # Parent the main control
        eb[main_control].use_connect = False
        eb[main_control].parent = eb[self.org_bones[0]].parent

        # Parent the main WGTs
        eb[main_wgt1].use_connect = False
        eb[main_wgt1].parent = eb[main_control]
        eb[main_wgt2].use_connect = False
        eb[main_wgt2].parent = eb[main_wgt1]

        # Parent the controls and sub-controls
        for name, subname in zip(controls, subcontrols):
            eb[name].use_connect = False
            eb[name].parent = eb[main_control]
            eb[subname].use_connect = False
            eb[subname].parent = eb[name]

        # Parent the control parents
        for name, par_name in zip(controls[1:-1], control_parents):
            eb[par_name].use_connect = False
            eb[par_name].parent = eb[main_control]
            eb[name].parent = eb[par_name]

        # Position the main bone
        put_bone(self.obj, main_control, pivot_rest_pos)
        eb[main_control].length = sum([eb[b].length for b in self.org_bones]) / 2

        # Position the main WGTs
        eb[main_wgt1].tail = (0.0, 0.0, sum([eb[b].length for b in self.org_bones]) / 4)
        eb[main_wgt2].length = sum([eb[b].length for b in self.org_bones]) / 4
        put_bone(self.obj, main_wgt1, pivot_rest_pos)
        put_bone(self.obj, main_wgt2, pivot_rest_pos)

        # Position the controls and sub-controls
        pos = eb[controls[0]].head.copy()
        for name, subname in zip(controls, subcontrols):
            put_bone(self.obj, name, pivot_rest_pos)
            put_bone(self.obj, subname, pivot_rest_pos)
            eb[subname].length = eb[name].length / 3

        # Position the control parents
        for name, par_name in zip(controls[1:-1], control_parents):
            put_bone(self.obj, par_name, pivot_rest_pos)
            eb[par_name].length = eb[name].length / 2

        #-----------------------------------------
        # Control bone constraints and properties
        bpy.ops.object.mode_set(mode='OBJECT')
        pb = self.obj.pose.bones

        # Lock control locations
        for name in controls:
            bone = pb[name]
            bone.lock_location = True, True, True

        # Main control doesn't use local location
        pb[main_control].bone.use_local_location = False

        # Intermediate controls follow hips and spine
        for name, par_name, i in zip(controls[1:-1], control_parents, self.control_indices[1:-1]):
            bone = pb[par_name]

            # Custom bend_alpha property
            prop = rna_idprop_ui_prop_get(pb[name], "bend_alpha", create=True)
            pb[name]["bend_alpha"] = i / (len(self.org_bones) - 1)  # set bend alpha
            prop["min"] = 0.0
            prop["max"] = 1.0
            prop["soft_min"] = 0.0
            prop["soft_max"] = 1.0

            # Custom auto_rotate
            prop = rna_idprop_ui_prop_get(pb[name], "auto_rotate", create=True)
            pb[name]["auto_rotate"] = 1.0
            prop["min"] = 0.0
            prop["max"] = 1.0
            prop["soft_min"] = 0.0
            prop["soft_max"] = 1.0

            # Constraints
            con1 = bone.constraints.new('COPY_TRANSFORMS')
            con1.name = "copy_transforms"
            con1.target = self.obj
            con1.subtarget = subcontrols[0]

            con2 = bone.constraints.new('COPY_TRANSFORMS')
            con2.name = "copy_transforms"
            con2.target = self.obj
            con2.subtarget = subcontrols[-1]

            # Drivers
            fcurve = con1.driver_add("influence")
            driver = fcurve.driver
            driver.type = 'AVERAGE'
            var = driver.variables.new()
            var.name = "auto"
            var.targets[0].id_type = 'OBJECT'
            var.targets[0].id = self.obj
            var.targets[0].data_path = pb[name].path_from_id() + '["auto_rotate"]'

            fcurve = con2.driver_add("influence")
            driver = fcurve.driver
            driver.type = 'SCRIPTED'
            driver.expression = "alpha * auto"
            var = driver.variables.new()
            var.name = "alpha"
            var.targets[0].id_type = 'OBJECT'
            var.targets[0].id = self.obj
            var.targets[0].data_path = pb[name].path_from_id() + '["bend_alpha"]'
            var = driver.variables.new()
            var.name = "auto"
            var.targets[0].id_type = 'OBJECT'
            var.targets[0].id = self.obj
            var.targets[0].data_path = pb[name].path_from_id() + '["auto_rotate"]'

        #-------------------------
        # Create flex spine chain
        bpy.ops.object.mode_set(mode='EDIT')
        flex_bones = []
        flex_subs = []
        prev_bone = None
        for b in self.org_bones:
            # Create bones
            bone = copy_bone(self.obj, b, make_mechanism_name(strip_org(b) + ".flex"))
            sub = new_bone(self.obj, make_mechanism_name(strip_org(b) + ".flex_s"))
            flex_bones += [bone]
            flex_subs += [sub]

            eb = self.obj.data.edit_bones
            bone_e = eb[bone]
            sub_e = eb[sub]

            # Parenting
            bone_e.use_connect = False
            sub_e.use_connect = False
            if prev_bone is None:
                sub_e.parent = eb[controls[0]]
            else:
                sub_e.parent = eb[prev_bone]
            bone_e.parent = sub_e

            # Position
            put_bone(self.obj, sub, bone_e.head)
            sub_e.length = bone_e.length / 4
            if prev_bone is not None:
                sub_e.use_connect = True

            prev_bone = bone

        #----------------------------
        # Create reverse spine chain

        # Create bones/parenting/positioning
        bpy.ops.object.mode_set(mode='EDIT')
        rev_bones = []
        prev_bone = None
        for b in zip(flex_bones, self.org_bones):
            # Create bones
            bone = copy_bone(self.obj, b[1], make_mechanism_name(strip_org(b[1]) + ".reverse"))
            rev_bones += [bone]
            eb = self.obj.data.edit_bones
            bone_e = eb[bone]

            # Parenting
            bone_e.use_connect = False
            bone_e.parent = eb[b[0]]

            # Position
            flip_bone(self.obj, bone)
            bone_e.tail = Vector(eb[b[0]].head)
            #bone_e.head = Vector(eb[b[0]].tail)
            if prev_bone is None:
                put_bone(self.obj, bone, pivot_rest_pos)
            else:
                put_bone(self.obj, bone, eb[prev_bone].tail)

            prev_bone = bone

        # Constraints
        bpy.ops.object.mode_set(mode='OBJECT')
        pb = self.obj.pose.bones
        prev_bone = None
        for bone in rev_bones:
            bone_p = pb[bone]

            con = bone_p.constraints.new('COPY_LOCATION')
            con.name = "copy_location"
            con.target = self.obj
            if prev_bone is None:
                con.subtarget = main_control
            else:
                con.subtarget = prev_bone
                con.head_tail = 1.0
            prev_bone = bone

        #----------------------------------------
        # Constrain original bones to flex spine
        bpy.ops.object.mode_set(mode='OBJECT')
        pb = self.obj.pose.bones

        for obone, fbone in zip(self.org_bones, flex_bones):
            con = pb[obone].constraints.new('COPY_TRANSFORMS')
            con.name = "copy_transforms"
            con.target = self.obj
            con.subtarget = fbone

        #---------------------------
        # Create pivot slide system
        pb = self.obj.pose.bones
        bone_p = pb[self.org_bones[0]]
        main_control_p = pb[main_control]

        # Custom pivot_slide property
        prop = rna_idprop_ui_prop_get(main_control_p, "pivot_slide", create=True)
        main_control_p["pivot_slide"] = self.pivot_rest
        prop["min"] = 0.0
        prop["max"] = 1.0
        prop["soft_min"] = 1.0 / len(self.org_bones)
        prop["soft_max"] = 1.0 - (1.0 / len(self.org_bones))

        # Anchor constraints
        con = bone_p.constraints.new('COPY_LOCATION')
        con.name = "copy_location"
        con.target = self.obj
        con.subtarget = rev_bones[0]

        con = pb[main_wgt1].constraints.new('COPY_ROTATION')
        con.name = "copy_rotation"
        con.target = self.obj
        con.subtarget = rev_bones[0]

        # Slide constraints
        i = 1
        tot = len(rev_bones)
        for rb in rev_bones:
            con = bone_p.constraints.new('COPY_LOCATION')
            con.name = "slide." + str(i)
            con.target = self.obj
            con.subtarget = rb
            con.head_tail = 1.0

            # Driver
            fcurve = con.driver_add("influence")
            driver = fcurve.driver
            var = driver.variables.new()
            driver.type = 'AVERAGE'
            var.name = "slide"
            var.targets[0].id_type = 'OBJECT'
            var.targets[0].id = self.obj
            var.targets[0].data_path = main_control_p.path_from_id() + '["pivot_slide"]'
            mod = fcurve.modifiers[0]
            mod.poly_order = 1
            mod.coefficients[0] = 1 - i
            mod.coefficients[1] = tot

            # Main WGT
            con = pb[main_wgt1].constraints.new('COPY_ROTATION')
            con.name = "slide." + str(i)
            con.target = self.obj
            con.subtarget = rb

            # Driver
            fcurve = con.driver_add("influence")
            driver = fcurve.driver
            var = driver.variables.new()
            driver.type = 'AVERAGE'
            var.name = "slide"
            var.targets[0].id_type = 'OBJECT'
            var.targets[0].id = self.obj
            var.targets[0].data_path = main_control_p.path_from_id() + '["pivot_slide"]'
            mod = fcurve.modifiers[0]
            mod.poly_order = 1
            mod.coefficients[0] = 1.5 - i
            mod.coefficients[1] = tot

            i += 1

        #----------------------------------
        # Constrain flex spine to controls
        bpy.ops.object.mode_set(mode='OBJECT')
        pb = self.obj.pose.bones

        # Constrain the bones that correspond exactly to the controls
        for i, name in zip(self.control_indices, subcontrols):
            con = pb[flex_subs[i]].constraints.new('COPY_TRANSFORMS')
            con.name = "copy_transforms"
            con.target = self.obj
            con.subtarget = name

        # Constrain the bones in-between the controls
        for i, j, name1, name2 in zip(self.control_indices, self.control_indices[1:], subcontrols, subcontrols[1:]):
            if (i + 1) < j:
                for n in range(i + 1, j):
                    bone = pb[flex_subs[n]]
                    # Custom bend_alpha property
                    prop = rna_idprop_ui_prop_get(bone, "bend_alpha", create=True)
                    bone["bend_alpha"] = (n - i) / (j - i)  # set bend alpha
                    prop["min"] = 0.0
                    prop["max"] = 1.0
                    prop["soft_min"] = 0.0
                    prop["soft_max"] = 1.0

                    con = bone.constraints.new('COPY_TRANSFORMS')
                    con.name = "copy_transforms"
                    con.target = self.obj
                    con.subtarget = name1

                    con = bone.constraints.new('COPY_TRANSFORMS')
                    con.name = "copy_transforms"
                    con.target = self.obj
                    con.subtarget = name2

                    # Driver
                    fcurve = con.driver_add("influence")
                    driver = fcurve.driver
                    var = driver.variables.new()
                    driver.type = 'AVERAGE'
                    var.name = "alpha"
                    var.targets[0].id_type = 'OBJECT'
                    var.targets[0].id = self.obj
                    var.targets[0].data_path = bone.path_from_id() + '["bend_alpha"]'

        #-------------
        # Final stuff
        bpy.ops.object.mode_set(mode='OBJECT')
        pb = self.obj.pose.bones

        # Control appearance
        # Main
        pb[main_control].custom_shape_transform = pb[main_wgt2]
        w = create_compass_widget(self.obj, main_control)
        if w != None:
            obj_to_bone(w, self.obj, main_wgt2)

        # Spines
        for name, i in zip(controls[1:-1], self.control_indices[1:-1]):
            pb[name].custom_shape_transform = pb[self.org_bones[i]]
            # Create control widgets
            w = create_circle_widget(self.obj, name, radius=1.0, head_tail=0.5, with_line=True)
            if w != None:
                obj_to_bone(w, self.obj, self.org_bones[i])
        # Hips
        pb[controls[0]].custom_shape_transform = pb[self.org_bones[0]]
        # Create control widgets
        w = create_circle_widget(self.obj, controls[0], radius=1.0, head_tail=0.5, with_line=True)
        if w != None:
            obj_to_bone(w, self.obj, self.org_bones[0])

        # Ribs
        pb[controls[-1]].custom_shape_transform = pb[self.org_bones[-1]]
        # Create control widgets
        w = create_circle_widget(self.obj, controls[-1], radius=1.0, head_tail=0.5, with_line=True)
        if w != None:
            obj_to_bone(w, self.obj, self.org_bones[-1])

        # Layers
        pb[main_control].bone.layers = pb[self.org_bones[0]].bone.layers

        return [main_control] + controls