Beispiel #1
0
def sorted_bones(selected):
    "Scan through selected bones to find order of bones in a a tree"

    selected = [
        b for b in selected if (Is.posebone(b) or Is.bone(b) or Is.editbone(b))
    ]
    bones = list()

    while selected:
        for bone in list(selected):
            if (bone not in selected):
                # a previous bone was one of this bone's parents
                continue

            for parent in bone.parent_recursive:
                if parent in selected:
                    break
            else:
                bones.append(bone)
                selected.remove(bone)

                # Loop over children, which "may" result in less looping
                for child in bone.children_recursive:
                    if child in selected:
                        bones.append(child)
                        selected.remove(child)

    return bones
Beispiel #2
0
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)
Beispiel #3
0
def matrix(src, local=False, basis=False, tail=False, copy=True):
    # editbone.     matrix
    # bone.         matrix, matrix_local
    # posebone.     matrix, matrix_basis, matrix_channel
    # object.       matrix_world, matrix_basis, matrix_local, matrix_parent_inverse

    if Is.posebone(src):
        if copy:
            matrix = utils.multiply_matrix(src.id_data.matrix_world,
                                           src.matrix)
        else:
            matrix = src.matrix

        if basis:
            matrix_local = src.matrix_basis
        else:
            matrix_local = src.bone.matrix_local
    elif Is.bone(src):
        matrix = src.matrix
        matrix_local = src.matrix_basis
    elif Is.editbone(src):
        matrix = matrix_local = src.matrix
    else:
        matrix = src.matrix_world
        if basis:
            matrix_local = src.matrix_basis
        else:
            matrix_local = src.matrix_local

    if copy:
        matrix = matrix.copy()
        matrix_local = matrix_local.copy()

    # scaled = False
    # if len(set(matrix.to_scale())) == 1:
    #     matrix *= matrix.to_scale()[0]
    #     scaled = True

    if (tail and hasattr(src, 'tail')):
        # matrix.translation += (src.tail - src.head)
        matrix.translation = matrix.Translation(src.tail).translation
        matrix_local.translation = \
            matrix_local.Translation(src.tail).translation
        # for (i, t) in enumerate(matrix.translation):
        #     v = (src.tail[i] - src.head[i]) * (
        #         1 if scaled else matrix.to_scale()[i])
        #     matrix.translation[i] += v

    if (basis or local):
        return matrix_local
    else:
        return matrix
Beispiel #4
0
def tail(context, bone):
    # ------ Bones
    if any((Is.posebone(bone), Is.bone(bone), Is.editbone(bone))):
        if (Is.posebone(bone)):
            obj = bone.id_data
        else:
            obj = Get.rig(context, bone)

        if obj is None:
            return
        else:
            mat = Get.matrix(obj)
            return utils.multiply_matrix(mat, bone.tail)
Beispiel #5
0
def icon_from_type(src):
    "return an Icon id for the specified item's type"

    if Is.object(src):
        if src.type == 'LIGHT_PROBE':
            icon = 'LIGHTPROBE_' + src.data.type
        else:
            icon = src.type + '_DATA'
    elif Is.bone(src) or Is.editbone(src) or Is.posebone(src):
        icon = 'BONE_DATA'
    else:
        icon = 'ERROR'
        utils.debug("Can't find icon type for ", src, type(src))

    return icon
Beispiel #6
0
def select(target, value=True):
    """Select or Deselect an item"""

    if Is.object(target):
        target.select_set(value)
    elif Is.posebone(target):
        target.bone.select = value
    elif Is.bone(target) or Is.editbone(target):
        target.select = value
    elif target is None:
        pass
    else:
        # Give error
        assert None, (
            "Error: zpy\\Set.select() can't use the provided target \n",
            target,
        )
Beispiel #7
0
def rig(context, src):
    """
    bone/editbone don't directly link to objects, just the armature.\\
    So, try to find an object by using their armature instead
    """

    is_armature = isinstance(src, bpy.types.Armature)

    if Is.posebone(src) or Is.armature(src.id_data):
        return src.id_data
    elif (is_armature, Is.bone(src) or Is.editbone(src)):
        for object in Get.objects(context):
            if (object.data == src.id_data):
                break
        else:
            object = None
        return object
    else:
        assert None, ("Could not find rig for", src)
Beispiel #8
0
def active(context, target):
    """Set target as active scene object or bone"""

    objects = Get.objects(context)

    # Remember previous active
    previous = Get.active(context)
    selected = Is.selected(target)

    # Set the active
    if Is.object(target):
        obj = target
    elif Is.posebone(target):
        obj = target.id_data
        obj.data.bones.active = obj.data.bones.get(target.name)
    elif isinstance(target, bpy.types.Armature):
        obj = Get.rig(context, target)
    elif Is.bone(target):
        obj = Get.rig(context, target)
        bones = target.id_data.bones
        bones.active = bones.get(target.name)
    elif Is.editbone(target):
        obj = Get.rig(context, target)

        if obj: in_edit = (obj.mode == 'EDIT')
        else: in_edit = (context.mode == 'EDIT_ARMATURE')

        if in_edit:
            bones = target.id_data.edit_bones
            bones.active = bones.get(target.name)
    elif target is None:
        obj = None
        # debug("Set.active() has None as the target")
    else:
        assert None, ("Set.active() can't use the provided target", target)

    if (target and Is.selected(target) != selected):
        # When setting a bone as active in a rig, it gets selected as well.
        Set.select(target, selected)
    objects.active = obj

    return previous
Beispiel #9
0
def sorted_chains(selected):
    "Scan through selected bones to find order of bones for spline_ik chains"

    chains = []
    for bone in selected:
        if not any((Is.posebone(bone), Is.bone(bone), Is.editbone(bone))):
            continue
        chain = []
        end = True
        for child in bone.children_recursive:
            if child in selected:
                end = False
                continue
        if end:
            for par in reversed(bone.parent_recursive):
                if par in selected:
                    chain.append(par)
            chain.append(bone)
            chains.append(chain)

    return chains
Beispiel #10
0
def matrix(src, matrix, local=False, basis=False):
    """
    Set the visual transforms for a bone or object
    The parameters vary, so the input matrix should too:
        editbone.     matrix
        bone.         matrix, matrix_local
        posebone.     matrix, matrix_basis, matrix_channel
        object.       matrix_world, matrix_basis, matrix_local, matrix_parent_inverse
    """

    if Is.object(src):
        if basis:
            src.matrix_basis = matrix
        elif local:
            src.matrix_local = matrix
        else:
            src.matrix_world = matrix
    else:
        if basis or local:
            if Is.posebone(src): src.matrix_basis = matrix
            elif Is.bone(src): src.matrix_local = matrix
            else: src.matrix = matrix
        else:
            src.matrix = matrix
Beispiel #11
0
def driver(src, path, **kargs):
    driver_type = kargs.get('driver_type', None)
    # 'AVERAGE', 'Sum Values', 'SCRIPTED', 'Minimum Value', 'Maximum Value
    expression = kargs.get('expression', None)
    frames = kargs.get('frames', list())  # keyframe.co for the driver's fcurve
    name = kargs.get('name', "var")  # Name of the variable added to the driver
    overwrite = kargs.get('overwrite', False)  # Delete the existing driver
    rotation_mode = kargs.get('rotation_mode', 'AUTO')
    target = kargs.get('target', None)
    target_path = kargs.get('target_path', '')
    transform_space = kargs.get('transform_space', 'LOCAL_SPACE')
    transform_type = kargs.get('transform_type', 'LOC_X')
    var_type = kargs.get('var_type', None)
    # 'SINGLE_PROP', 'TRANSFORMS', 'Rotational Difference', 'Distance'
    if var_type is None:
        if target and (not target_path):
            var_type = 'TRANSFORMS'
        else:
            var_type = 'SINGLE_PROP'

    Driver = Get.driver(src, path)

    if not Driver:
        Driver = src.driver_add(path)
        overwrite = True

    if overwrite:
        while Driver.keyframe_points:
            Driver.keyframe_points.remove(Driver.keyframe_points[0])

    if frames:
        if overwrite:
            Driver.extrapolation = 'LINEAR'
            while Driver.modifiers:
                Driver.modifiers.remove(Driver.modifiers[0])
        Driver.keyframe_points.add(len(frames))
        for key, co in zip(Driver.keyframe_points[:], frames):
            key.interpolation = 'LINEAR'
            key.co = co

    driver = Driver.driver

    if overwrite:
        if (expression is None):
            if (driver_type is None):
                driver_type = 'AVERAGE'
            elif (driver.type == 'SCRIPTED'):
                driver.expression = name

        while driver.variables:
            driver.variables.remove(driver.variables[0])

    if expression is not None:
        driver.expression = expression
    if driver_type:
        driver.type = driver_type

    var = driver.variables.new()
    var.name = name
    var.type = var_type
    var_target = var.targets[0]

    if target:
        is_pose = Is.posebone(target)
        is_bone = Is.bone(target) or Is.editbone(target)
        is_obj = Is.object(target)

        if is_obj:
            var_target.id = target
        elif (is_pose or is_bone):
            var_target.id = target.id_data
            var_target.bone_target = target.name
            if target_path and (not target_path.startswith(
                ('pose.bones', 'bones'))):
                if is_pose:
                    text = f'pose.bones["{target.name}"]'
                else:
                    text = f'bones["{target.name}"]'

                if (target_path[0] != '['):
                    text += '.'

                target_path = text + target_path
        else:
            try:
                var_target.id = target
            except:
                var_target.id = target.id_data

    var_target.data_path = target_path
    var_target.rotation_mode = rotation_mode
    var_target.transform_space = transform_space
    var_target.transform_type = transform_type

    return Driver
Beispiel #12
0
def visible(context, object, value=True, **kargs):
    """
    Set an object's (or bone's object's) visibility to the specified value
    """

    scn = context.scene

    if not Is.object(object):
        if isinstance(object, bpy.types.Collection):
            found = False

            def loop(root, tree=list()):
                nonlocal found

                if root.collection == object:
                    return True

                for child in root.children:
                    if loop(child, tree):
                        found = True
                        tree.append(child)
                        break

                if found:
                    return tree

            view_layer = kargs.get('view_layer', False)

            if not view_layer:
                object.hide_viewport = not value
            if value or view_layer:
                # Only enables the collection for the view layer once
                tree = loop(context.view_layer.layer_collection)
                for col in tree:
                    if (col.exclude == value) and (col.name == object.name):
                        # When a collection is enabled in the view layer,
                        # all of its child collections are as well.
                        col.exclude = not value
                    if value and col.collection.hide_viewport:
                        col.collection.hide_viewport = False
        elif Is.posebone(object):
            return Set.visible(context, object.id_data, value)
        elif Is.bone(object) or Is.editbone(object):
            return Set.visible(context, Get.rig(context, object), value)
        else:
            assert None, (
                "Set.visible() does not work with the specified item",
                object,
            )
        return

    Set.in_scene(context, object)

    is_visible = Is.visible(context, object)
    object_visible = not object.hide_viewport

    # if Is.visible(context, object) is value:
    # return visible

    while (Is.visible(context, object) is not value):
        "If object isn't in the desired visiblity, loop until it is"

        if (object.hide_viewport is value):
            object.hide_viewport = not value
            continue

        is_visible = object_visible
        view = None

        for collection in object.users_collection:
            view = context.view_layer.layer_collection.children.get(
                collection.name)
            if not view:
                # collection isn't in scene or whatever
                continue
            if view.hide_viewport is value:
                view.hide_viewport = not value
            break

        if view is None:
            assert None, (
                "Set.visible(): Object[", object,
                "] \nis hidden from viewport and I don't know how to change it"
            )
            # collection.hide_viewport = value

        break

    return is_visible