Example #1
0
File: Get.py Project: Irmitya/zpy
def selected(context, src=None, mirror=False, mirror_x_only=True):
    """
    return selected objects or selected bones.
    If src is specified, return selected bones from it
    """

    mode = context.mode

    if mode in ('POSE', 'PAINT_WEIGHT'):
        selected = Get.selected_pose_bones(context, src)
        if mirror:
            for bone in selected:
                rig = bone.id_data
                if (rig.pose.use_mirror_x or not mirror_x_only):
                    flip = rig.pose.bones.get(utils.flip_name(bone.name))
                    if flip and (flip not in selected):
                        selected.append(flip)
    elif mode == 'EDIT_ARMATURE':
        selected = Get.selected_edit_bones(context, src)
        if mirror:
            for bone in selected:
                arm = bone.id_data
                if (arm.use_mirror_x or not mirror_x_only):
                    flip = arm.edit_bones.get(utils.flip_name(bone.name))
                    if flip and (flip not in selected):
                        selected.append(flip)
    else:
        selected = Get.selected_objects(context, True)

    return selected
def get_name(bone, bbone):
    bn = bone.name
    (prefix, replace, suffix, number) = utils.flip_name(bn, only_split=True)

    if bn == bn.title():
        bbone = bbone.title()
    elif bn == bn.upper():
        bbone = bbone.upper()

    if prefix and replace:
        return f"{prefix}.{bbone}{replace}{suffix}{number}"
    elif (suffix or number) and (bn != utils.flip_name(bn)):
        return f"{prefix}{replace}{suffix}.{bbone}{number}"
    else:
        return f"{bn}.{bbone}"
    def execute(self, context):
        obj = context.object

        in_edit = (obj.mode == 'EDIT')
        if in_edit:
            Set.mode(context, 'OBJECT')

        active = obj.active_shape_key
        vg = active.vertex_group
        index = obj.active_shape_key_index
        pin = obj.show_only_shape_key

        obj.show_only_shape_key = True
        active.vertex_group = ''
        bpy.ops.object.shape_key_add(from_mix=True)
        while obj.active_shape_key_index > (index + 1):
            bpy.ops.object.shape_key_move(type='UP')
        active.vertex_group = vg

        shape = obj.active_shape_key

        if self.mirror:
            shape.name = utils.flip_name(active.name)
            shape.vertex_group = utils.flip_name(vg)
        else:
            shape.vertex_group = vg
            shape.name = active.name

        for var in ('interpolation', 'mute', 'relative_key', 'slider_max',
                    'slider_min', 'value'):
            setattr(shape, var, getattr(active, var))
            driver = Get.driver(active, var)
            if not driver:
                continue
            newdriver = utils.copy_driver(driver, shape, var)

            if self.mirror:
                for v in newdriver.driver.variables:
                    for t in v.targets:
                        t.bone_target = utils.flip_name(t.bone_target)

        # obj.active_shape_key_index = index
        obj.show_only_shape_key = pin

        if in_edit:
            Set.mode(context, 'EDIT')

        return {'FINISHED'}
Example #4
0
File: Get.py Project: Irmitya/zpy
def mirror_bone(bone):
    name = utils.flip_name(bone.name)
    if name == bone.name:
        return

    if Is.posebone(bone):
        return bone.id_data.pose.bones.get(name)
    elif Is.editbone(bone):
        return bone.id_data.edit_bones.get(name)
    elif Is.bone(bone):
        return bone.id_data.bones.get(name)
    def description(cls, context, properties):
        txt = cls.bl_description

        if properties.mirror:
            obj = context.object
            if obj and obj.active_shape_key:
                active = obj.active_shape_key
                sk = utils.flip_name(active.name)
                vg = utils.flip_name(active.vertex_group)

                if (sk != active.name):
                    txt += f", and name it {sk}"
                    if (vg != active.vertex_group):
                        txt += f" with the vertex group [{vg}]"
                elif (vg != active.vertex_group):
                    txt += f", and switch its vertex group with [{vg}]"
            else:
                txt += ", and flip it's name and vertex group if it has a Left/Right mirroed name indicators"

        return txt
Example #6
0
    def add_bones_dupli(self, context, rig):
        # Add bones then set their defaults
        root = self.get_root(rig)
        prev_bones = self.get_prev_bones(rig)
        pose_bones = []
        flip_bones = []

        def add_bone(bone_name):
            prev = rig.data.edit_bones[bone_name]

            bone = rig.data.edit_bones.new(prev.name)
            pose_bones.append([bone.name, prev.name])
            self.reset(bone, prev)

            bone.parent = prev.parent
            bone.use_deform = prev.use_deform

        for bone_name in prev_bones:
            add_bone(bone_name)

            if rig.pose.use_mirror_x:
                flip = utils.flip_name(bone_name)
                if (flip in rig.data.edit_bones) and (flip not in (
                        *prev_bones, *(p for (b, p) in pose_bones))):
                    # Mirrored bone exists but not selected
                    add_bone(flip)
                    flip_bones.append(flip)

        # Switch back to Pose mode and setup pose bones
        Set.mode(context, 'POSE', rig)

        for (bone, prev) in pose_bones:
            bone = rig.pose.bones[bone]
            prev = rig.pose.bones[prev]
            if (prev.name not in flip_bones):
                rig.data.bones.active = bone.bone
            bone.custom_shape = prev.custom_shape
            bone.custom_shape_transform = prev.custom_shape_transform
            bone.bone.show_wire = prev.bone.show_wire
            bone.matrix = prev.matrix
            bone.bone_group = prev.bone_group
            for lock in [
                    'location', 'rotations_4d', 'rotation_w', 'rotation',
                    'scale'
            ]:
                setattr(bone, 'lock_' + lock, getattr(prev, 'lock_' + lock))
    def pose_func(self, context, bone):
        rig = bone.id_data
        bones = rig.pose.bones
        bbones = ('bbone', 'bbone_start', 'bbone_end', 'bbone_head',
                  'bbone_in', 'bbone_out')

        def parse(bbone):
            self.bones[bbone] = rig

            # Prep the widget for removal
            wgt = bbone.custom_shape
            if wgt:
                self.widgets.add(wgt)

            # Remove stretch constraints
            for con in list(bone.constraints):
                if (getattr(con, 'target', None) == rig) and (con.subtarget
                                                              == bbone.name):
                    bone.constraints.remove(con)

            # Remove Custom Handle
            if bone.bbone_custom_handle_start == bbone:
                bone.bone.bbone_custom_handle_start = None
                bone.bone.bbone_handle_type_start = 'AUTO'
            if bone.bbone_custom_handle_end == bbone:
                bone.bone.bbone_custom_handle_end = None
                bone.bone.bbone_handle_type_end = 'AUTO'

        for bbone_name in bbones:
            bbone = bones.get(get_name(bone, bbone_name))
            if not bbone:
                continue

            parse(bbone)

            if bbone_name in ('bbone_start',
                              'bbone_end') and Get.mirror_bone(bbone):
                (prefix, replace, suffix,
                 number) = utils.flip_name(bone.name, only_split=True)
                center_name = prefix + suffix + number
                center = bones.get(center_name)
                if center:
                    parse(center)

            # Remove BBone drivers
            if bbone_name in ('bbone_in', 'bbone_out'):
                in_out = bbone_name.split('_')[1]
                in_outs = (
                    f'bbone_curve{in_out}x',
                    f'bbone_curve{in_out}y',
                    f'bbone_roll{in_out}',
                    f'bbone_scale{in_out}x',
                    f'bbone_scale{in_out}y',
                    f'bbone_ease{in_out}',
                )
                for bbone_in_out in in_outs:
                    Driver = Get.driver(bone, bbone_in_out)
                    try:
                        target = Driver.driver.variables[0].targets[0]
                    except:
                        continue
                    if (target.bone_target == bbone.name) and (target.id
                                                               == rig):
                        bone.driver_remove(bbone_in_out)
    def edit_mirror_center(self, context):
        def get_bones(rig, bbone):
            ebones = rig.data.edit_bones
            ebone = ebones.get(get_name(bone, bbone))
            mebone = Get.mirror_bone(ebone)
            return (ebone, mebone)

        found = []
        for (bone, rig) in self.selected:
            if not (rig.pose.use_mirror_x or rig.data.use_mirror_x):
                continue
            mbone = Get.mirror_bone(bone)
            if mbone in found:
                continue
            else:
                found.append(bone)

            (ebone, mebone) = get_bones(rig, 'bbone_start')
            if not (ebone and mebone):
                continue

            if (ebone.parent == mebone.parent):
                # Connect heads
                if Is.connected(bone):
                    # The parent will already handle the symmetry
                    continue
                parent = ebone.parent
            else:
                (ebone, mebone) = get_bones(rig, 'bbone_end')
                if not (ebone and mebone):
                    continue

                # Find a mutual parent between the two bones
                parent = [
                    *(x for x in ebone.parent_recursive
                      if x in mebone.parent_recursive), None
                ][0]

            distance = abs(sum(ebone.head) - sum(mebone.head)) / 2
            margin = utils.lerp(bone.bone.length, mbone.bone.length,
                                0.5) / bone.bone.bbone_segments
            if distance >= margin:
                # Bones too far apart
                continue

            (prefix, replace, suffix,
             number) = utils.flip_name(bone.name, only_split=True)
            center_name = prefix + suffix + number
            center = New.bone(context, rig, name=center_name, overwrite=True)

            attributes = [
                'head',
                'head_radius',
                'tail',
                'tail_radius',
                'roll',
                'matrix',
                'layers',
                'bbone_x',
                'bbone_z',
            ]
            for atr in attributes:
                if hasattr(center, atr):
                    setattr(
                        center, atr,
                        utils.lerp(getattr(ebone, atr), getattr(mebone, atr),
                                   0.5))
            center.use_deform = False
            center.inherit_scale = 'NONE'
            center.parent = parent
            center.hide = True

            ebone.parent = mebone.parent = center
            self.hide_bones[rig].extend((ebone.name, mebone.name))
            self.center_bones[rig].append(center.name)