Example #1
0
    def draw(self, context):
        layout = self.layout
        src = context.src
        mp = context.mp
        mpath = src.motion_path

        layout.prop(mp, 'show_frame_numbers')  # , text="Frame Numbers")
        layout.prop(mp, 'show_keyframe_highlight')  # , text="Keyframes")
        if mp.show_keyframe_highlight:
            if Is.posebone(src):
                layout.prop(mp,
                            'show_keyframe_action_all',
                            text="+ Non-Grouped Keyframes")
            layout.prop(mp, 'show_keyframe_numbers', text="Keyframe Numbers")

        layout.separator()
        if Is.posebone(src):
            layout.label(text=src.name, icon='BONE_DATA')
        else:
            layout.label(text=src.name, icon='OBJECT_DATA')
        if mpath:
            layout.prop(mpath, 'lines')  # , text="Lines")
            layout.prop(mpath, 'use_custom_color')  # , text="Custom Color")
        else:
            op = 'zpy.update_motion_paths'
            layout.label(text="Add Motion Paths")
            layout.operator(op, text="At Heads").use_tails = False
            layout.operator(op, text="At Tails").use_tails = True

        layout.separator()
        mot = utils.prefs(__package__).motion
        layout.prop(mot, 'frame_before')
        layout.prop(mot, 'frame_after')
Example #2
0
    def execute(self, context):
        do_all = (self.mode == {'loc', 'rot', 'scale'})

        selected = Get.selected(context, mirror=True)

        for src in selected:
            base = get_base(src)

            if 'loc' in self.mode:
                src.location = base.location
            if 'rot' in self.mode:
                if src.rotation_mode == 'QUATERNION':
                    src.rotation_quaternion = base.rotation_quaternion
                elif src.rotation_mode == 'AXIS_ANGLE':
                    src.rotation_axis_angle = base.rotation_axis_angle
                else:
                    src.rotation_euler = base.rotation_euler
                if Is.posebone(src):
                    src.bbone_curveinx = src.bbone_curveoutx = src.bbone_curveiny = src.bbone_curveouty = src.bbone_rollin = src.bbone_rollout = 0
            if 'scale' in self.mode:
                src.scale = base.scale
                if Is.posebone(src):
                    src.bbone_scaleinx = src.bbone_scaleinx = src.bbone_scaleiny = src.bbone_scaleoutx = src.bbone_scaleouty = 1
                    src.bbone_easein = src.bbone_easeout = 0

            utils.clean_custom(src)

        keyframe.keyingset(context, selected=selected)

        return {'FINISHED'}
Example #3
0
File: Get.py Project: Irmitya/zpy
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)
Example #4
0
 def get_bone_child(self, _bone):
     if Is.posebone(_bone):
         bone = _bone.bone
         if _bone.child:
             child = _bone.child.bone
         else:
             # No bone connected, so try to find a substitute
             child = self.get_closest_child(bone)
     else:
         bone = _bone
         child = None
         if len(bone.children) == 1:
             child = bone.children[0]
         elif bone.children:
             for bone_child in bone.children:
                 if bone_child.use_connect:
                     if (child is not None):
                         child_dist = Get.distance(child.tail, bone.tail)
                         active_dist = Get.distance(bone_child.tail,
                                                    bone.tail)
                         if (child_dist == active_dist):
                             # both children tails same distance from bone
                             # Just sort alphabetically
                             child = sorted(
                                 (b.name, b)
                                 for b in [child, bone_child])[0][1]
                             continue
                         elif (child_dist < active_dist):
                             # Previous is closes
                             continue
                     child = bone_child
             if child is None:
                 # No bone connected, so try to find a substitute
                 child = self.get_closest_child(bone)
     return (bone, child)
Example #5
0
    def execute(self, context):
        if (context.mode == 'POSE'):
            if self.selected:
                bones = context.selected_pose_bones
            else:
                bones = [context.active_pose_bone]
        else:
            if self.selected:
                bones = context.selected_bones
            else:
                bones = [context.active_bone]

        for _bone in bones:
            (bone, child) = self.get_bone_child(_bone)
            self.set_bbone(bone, child)

            if Is.posebone(_bone):
                mirror_x = (_bone.id_data.pose.use_mirror_x
                            or bone.id_data.use_mirror_x)
            else:
                mirror_x = bone.id_data.use_mirror_x

            if mirror_x:
                m_bone = Get.mirror_bone(_bone)
                if m_bone and (m_bone not in bones):
                    (mbone, mchild) = self.get_bone_child(m_bone)
                    self.set_bbone(mbone, mchild)

        return {'FINISHED'}
Example #6
0
File: Get.py Project: Irmitya/zpy
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
Example #7
0
File: New.py Project: Irmitya/zpy
def bone_group(rig, name='Group', color=None):
    ""

    if Is.posebone(rig):
        rig = rig.id_data
    group = rig.pose.bone_groups.new(name=name)

    if Is.string(color):
        group.color_set = color
        # DEFAULT = regular bone color (not unique)
        # THEME01 - THEME15 = Builtin color palettes
        # THEME16 - THEME20 = Black for user assigned templates
        # CUSTOM = manually set
    elif color is False:
        group.color_set = 'DEFAULT'
    elif color is True:
        from random import randrange as random
        rand = f"{random(1, 15):02}"
        group.color_set = f'THEME{rand}'
    elif color:
        group.color_set = 'CUSTOM'
        gc = group.colors
        if not Is.iterable(color):
            if Is.digit(color):
                color = [[color] * 3] * 3
            else:
                color = [color] * 3
        (gc.normal, gc.select, gc.active) = color

    return group
Example #8
0
File: Get.py Project: Irmitya/zpy
def visible_armature_layers(bone, arm):
    """List of layer indexes that is visible and the Bone is on"""

    if Is.posebone(bone):
        bone = bone.bone
    if Is.armature(arm):
        arm = arm.data

    return [i for i, j in zip(bone.layers, arm.layers) if i and j]
Example #9
0
def keyingset(context, default=True, **kargs):
    """
    Use bpy.ops to insert keyframe.
    default means to only use the keying set if the keying set button is enabled
    """

    insert_key = kargs.get('insert_key')
    if not keyframe.poll_insert(context, insert_key):
        return

    ks = context.scene.keying_sets_all.active
    if (default and not keyframe.use_keyingset(context)) or \
            ks is None:
        ks = 'LocRotScale'
    else:
        ks = ks.bl_idname

    bones = kargs.get('bones', list())
    objects = kargs.get('objects', list())
    selected = kargs.get('selected', list())

    # if bones is None: bones = Get.selected_pose_bones(context)
    # if objects is None: objects = Get.selected_objects(context)

    for src in selected:
        if Is.posebone(src):
            bones.append(src)
        elif Is.object(src):
            objects.append(src)
        else:
            assert None, ("This is not a bone or object", src)

    if kargs.get('skip_bones', False):
        # This step removes bones from badBonePrefixes
        for src in bones.copy():
            if not keyframe.poll_insert(context, insert_key, src=src):
                bones.remove(src)

    # if keyframe.use_keyingset():
    # bpy.ops.anim.keyframe_insert(type=ks, confirm_success=False)
    # # else:
    # for src in KSI.iter():
    # keyframe.all(src)

    if (bones or objects):
        try:
            return bpy.ops.anim.keyframe_insert(dict(selected_pose_bones=bones,
                                                     selected_objects=objects),
                                                type=ks,
                                                confirm_success=False)
        except Exception as ex:
            pass
    else:
        "Nothing to keyframe"
Example #10
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)
Example #11
0
File: Get.py Project: Irmitya/zpy
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
    def execute(self, context):
        selection = Get.selected(context)

        if not selection:
            selection = [Get.active(context)]

        for src in selection:
            if Is.posebone(src):
                mp = src.id_data.pose.animation_visualization.motion_path
            else:
                mp = src.animation_visualization.motion_path
            mp.type = self.type

        return {'FINISHED'}
Example #13
0
File: Get.py Project: Irmitya/zpy
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
Example #14
0
File: New.py Project: Irmitya/zpy
def hook(curve, target, index):
    mod = curve.modifiers.new("Modifier Name", 'HOOK')

    mod.object = target.id_data
    if Is.posebone(target):
        mod.subtarget = target.name

    # modifier sets indices (which are the points + their two handles)
    mod_points = (index * 3 + 0, index * 3 + 1, index * 3 + 2)
    mod.vertex_indices_set(mod_points)
    mod.matrix_inverse = Get.matrix(target).inverted_safe()
    # Set the matrix, to allow the hook to stay with the "posed" bones
    # Don't get target's matrix, because it hasn't been updated yet
    mod.show_expanded = False

    return mod
Example #15
0
File: Get.py Project: Irmitya/zpy
def bone_group(src, name=""):
    """
    Returns a named group inside rig.
    if src is a posebone, will return the bone's group instead.
        If the bone doesn't have a group, will try to return the named group instead.
    """

    group = None

    if Is.posebone(src):
        group = src.bone_group

    if not group:
        group = src.id_data.pose.bone_groups.get(name)

    return group
Example #16
0
File: Get.py Project: Irmitya/zpy
def matrix_local(src, mat=None):
    """Get and convert a matrix to local space for later re-use"""
    if mat is None:
        mat = Get.matrix(src)

    if Is.posebone(src):
        # from zpy import Set
        # Set.matrix(src, Get.matrix(src))
        # mat = Get.matrix(src, basis=True)

        # Setting the matrix updates it to the visual pose
        # Basis gets the applied pose

        # This would do that as well, without needing "apply":
        mat = src.id_data.convert_space(pose_bone=src,
                                        matrix=mat,
                                        from_space='POSE',
                                        to_space='LOCAL')
        "or so my notes said"
        # From Baker:

        # if visual keying:
        #     # Get the final transform of the bone in its own local space...
        #     matrix[name] = obj.convert_space(
        #         pose_bone=bone, matrix=bone.matrix,
        #         from_space=self.bone_matrix, to_space='LOCAL')
        # else:
        #     matrix = bone.matrix_basis.copy()
    else:
        mat = src.id_data.convert_space(pose_bone=None,
                                        matrix=mat,
                                        from_space='WORLD',
                                        to_space='LOCAL')

        # From Baker:
        # If deleting object parents, do matrix world

        # if (Global.do_parents_clear):
        #     trans['matrix'] = obj.matrix_world.copy()
        # else:
        #     parent = obj.parent
        #     matrix = obj.matrix_world
        #     trans['matrix'] = multiply_matrix(
        #         parent.matrix_world.inverted_safe(), matrix
        #         ) if parent else matrix.copy()

    return mat
Example #17
0
File: Set.py Project: Irmitya/zpy
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,
        )
Example #18
0
File: Get.py Project: Irmitya/zpy
def name(src):

    # orig = Constraint.get.original(src)
    # if orig:
    #     src = orig

    if Is.posebone(src):
        name = f"{src.id_data.name}.{src.name}"
    else:
        name = f"{src.name}"

    # if src.constraints_relative.is_new:
    #     name = name.rsplit('-', 1)[0]
    #     if name.endswith('-'):
    #         name = name.rsplit('-', 1)[0]

    return name
Example #19
0
File: Get.py Project: Irmitya/zpy
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)
Example #20
0
File: Set.py Project: Irmitya/zpy
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
Example #21
0
File: Get.py Project: Irmitya/zpy
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
Example #22
0
File: Get.py Project: Irmitya/zpy
def ik_chain(bone, constraint=None):
    "return list of parent bones connected to the bone through an IK chain"

    parents = list()

    if not (Is.posebone(bone) and bone.parent):
        return parents

    maxlen = len(bone.parent_recursive)

    def scan(constraint):
        if (constraint.type in ('IK', 'SPLINE_IK')):
            count = constraint.chain_count
            if (count == 0 or count > maxlen):
                parents.extend(bone.parent_recursive)
            else:
                if getattr(constraint, 'use_tail', True):
                    # Spline IK starts count from the bone with the constraint
                    chain_range = count - 1
                else:
                    chain_range = count
                for chain in range(chain_range):
                    parents.append(bone.parent_recursive[chain])

    if constraint is None:
        for constraint in bone.constraints:
            scan(constraint)
    else:
        scan(constraint)

    parents_sorted = list()
    if parents:
        for parent in bone.parent_recursive:
            if parent in parents:
                parents_sorted.append(parent)

    return parents_sorted
Example #23
0
File: Set.py Project: Irmitya/zpy
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
Example #24
0
File: Set.py Project: Irmitya/zpy
def active_select(context, target, isolate=True):  # , isolate_mode=False):
    """
    Set target as active scene object or bone, and select it\\
    # isolate_mode would set all other selected objects to Object mode
    """

    # def deselect(src):
    # if isolate_mode and src.id_data.mode != 'OBJECT':
    #     Set.mode(context, 'OBJECT', src)
    # Set.select(src, False)

    if isolate:
        objects = Get.selected_objects(context)
        bones = Get.selected_pose_bones(context)

        for src in [*objects, *bones]:
            # deselect(src)
            Set.select(src, False)

    Set.visible(context, target, True)
    Set.active(context, target)
    Set.select(target, True)
    if Is.posebone(target):
        Set.mode(context, 'POSE', target)
Example #25
0
File: Get.py Project: Irmitya/zpy
def action_fcurves(src, actions=None, raw_action=True):
    "Find actions used by a bone/object and return it's action + fcurves"

    fcurves = list()

    if actions is None:
        rig = src.id_data
        strips = Get.strips(rig, selected=False)
        anim = rig.animation_data
        an_act = getattr(anim, 'action', None) if raw_action else None
        actions = {an_act, *(s.action for s in strips)}

    for action in actions:
        if not action:
            continue
        for fc in action.fcurves:
            if any((
                    Is.object(src),
                    Is.posebone(src)
                    and fc.data_path.find(f'bones[\"{src.name}\"]') != -1,
            )):
                fcurves.append((action, fc))

    return fcurves
Example #26
0
File: Get.py Project: Irmitya/zpy
def matrix_constraints(context, src, mat=None, force_constraints=[]):
    """Convert matrix so that it doesn't offset with the item's constraints"""

    from mathutils import Matrix

    mats_cons = list()

    mat_new = Get.matrix(src)
    if mat is None:
        mat = mat_new

    if Is.posebone(src):
        inv = src.id_data.matrix_world.inverted()
        mat = utils.multiply_matrix(inv, mat)
        mat_new = utils.multiply_matrix(inv, mat_new)

    for con in src.constraints:
        if not getattr(con, 'target', None) or \
                con.mute or \
                (con.influence == 0.0 and con not in force_constraints):
            continue
        else:
            pose = con.target.pose
            bone = None
            if pose and getattr(con, 'subtarget', None):
                bone = pose.bones.get(con.subtarget)

        if hasattr(con, 'inverse_matrix'):
            im = con.inverse_matrix
            imi = im.inverted()
            mat0 = utils.multiply_matrix(imi, mat)
            # The constraint with cleared inverse
            mat1 = mat.copy()
            # The goal pose without constraint
            con.inverse_matrix == utils.multiply_matrix(mat1, mat0.inverted())
            # The value set initially for the constraint

            mat_tar = con.target.matrix_world.inverted()
            if bone:
                mat_tar = utils.multiply_matrix(mat_tar,
                                                bone.matrix.inverted())

            mat_value = utils.multiply_matrix(imi, mat_tar)

            # # TODO: This get's the standard Child of, but it doesn't get
            # # a constraint without all 3 Rotation enabled

            # This is meant to give a list of matrices to cycle through
            # to try to find the correct mixture. What's wrong appears to
            # be that the target matrix from above needs to be altered,
            # and the current math is already valid
            # mat0 and mat
            # mats = (
            #     Matrix(),               # 0

            #     mat0,                   # 1
            #     mat1,                   # 2
            #     mat_new,                # 3
            #     mat_tar,                # 4
            #     im,                     # 5

            #     mat0.inverted(),        # 6
            #     mat1.inverted(),        # 7
            #     mat_new.inverted(),     # 8
            #     mat_tar.inverted(),     # 9
            #     imi,                    # 10
            # )
            # ac = [' ' + a for a in ['a', 'b', 'c', 'd', 'e', 'f', 'g']]
            # for a in ac:
            #     if src.get(a) is None:
            #         src[a] = 0

            # mat_value = multiply_matrix(
            #     *(
            #         mats[src[a]] for a in ac
            #     ),
            # )

            # Set influence of the result from constraint
            mat_influce = Matrix().lerp(mat_value, con.influence)
            mats_cons.append(mat_influce)
        elif getattr(con, 'use_offset', False):
            mats_cons.append(Matrix().lerp(
                utils.multiply_matrix(mat, mat_new.inverted()), con.influence))

    return utils.multiply_matrix(*mats_cons, mat)
Example #27
0
File: Set.py Project: Irmitya/zpy
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
Example #28
0
File: New.py Project: Irmitya/zpy
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
    def execute(self, context):
        scn = context.scene
        active = Get.active(context)
        selected = Get.selected(context)
        is_pose = bool(context.mode == 'POSE')

        if not is_pose:
            self.use_tails = False
        mode = ('HEADS', 'TAILS')[self.use_tails]

        # Use the line thickness of the active item, across the selection
        if getattr(active, 'motion_path', None):
            line = active.motion_path.line_thickness
        else:
            line = 1

        colors = dict()
        types = dict()
        for src in Get.selected(context):
            mp = src.motion_path
            if not mp:
                continue

            if mp.use_custom_color:
                colors[src] = mp.color

            if Is.posebone(src):
                display = src.id_data.pose.animation_visualization.motion_path
            else:
                display = src.animation_visualization.motion_path

            types[src] = display.type

        # Get the frame range to bake motion paths in
        motion = utils.prefs(__package__).motion

        if self.use_start_end:
            start = self.start_frame
            end = self.end_frame
        elif (motion.use_relative_range) or (scn.use_preview_range):
            start = scn.frame_preview_start
            end = scn.frame_preview_end
            fc = scn.frame_current
            fb = motion.frame_before
            fa = motion.frame_after

            if not (scn.use_preview_range) or (abs(end - start) > 100 >
                                               (fb + fa)):
                # If the preview range is too high, just default to nearby
                start = fc - fb
                end = fc + fa
        else:
            # if (active):
            # # Use the active object's motion path's in_range distance
            # if (Is.posebone(active)):
            #     mp = active.id_data.pose.animation_visualization.motion_path
            # else:
            #     mp = active.animation_visualization.motion_path
            # fb = mp.frame_before
            # fa = mp.frame_after
            # if (fb < 25): fb = 25
            # if (fa < 25): fa = 25

            # start = scn.frame_current - fb
            # end = scn.frame_current + fa
            start = scn.frame_start
            end = scn.frame_end
            fc = scn.frame_current
            if 150 < abs(end - start):
                start = fc - 50
                end = fc + 50

        # Create the motion paths
        args = dict(start_frame=start, end_frame=end + 1)
        if is_pose:
            op = bpy.ops.pose
            args['bake_location'] = mode

            # Operator only runs on active rig, so repeat for all in pose mode
            obs = {b.id_data for b in selected}

            for ob in obs:
                Set.active(context, ob)
                op.paths_clear(only_selected=True)
                op.paths_calculate(**args)
            else:
                Set.active(context, active)
        else:
            op = bpy.ops.object
            op.paths_clear(only_selected=True)
            op.paths_calculate(**args)

        for src in selected:
            mp = src.motion_path
            if not mp: continue

            mp.line_thickness = line
            color = colors.get(src)
            if color:
                mp.color = color

            if Is.posebone(src):
                display = src.id_data.pose.animation_visualization.motion_path
            else:
                display = src.animation_visualization.motion_path
            display.type = types.get(src, 'CURRENT_FRAME')

        # Set to use the frame hider instead of ever displaying all points
        # if is_pose:
        #     src.id_data.pose.animation_visualization. \
        #         motion_path.type = 'CURRENT_FRAME'
        # else:
        #     src.animation_visualization. \
        #         motion_path.type = 'CURRENT_FRAME'
        # scn.frame_set(scn.frame_current)

        return {'FINISHED'}
Example #30
0
File: Get.py Project: Irmitya/zpy
def value_from_nla_strips(context,
                          src,
                          path,
                          index=-1,
                          frame=None,
                          selected=False,
                          tweak=False):
    # Tries to actually read the strips
    # but it doesn't work with COMBINE quaternions

    anim = getattr(src.id_data, 'animation_data', None)
    if not anim:
        return

    if frame is None:
        frame = context.scene.frame_current_final

    if Is.posebone(src) and not path.startswith('pose.bones'):
        kpath = (f'pose.bones[\"{src.name}\"].' + path)
    else:
        kpath = path

    # Establish default
    if any((
            'default' is 1,
            path.endswith('scale'),
            path.endswith('rotation_quaternion') and index == 0,
            path.endswith('rotation_axis_angle') and index == 2,
    )):
        default = 1.0
    else:
        default = 0.0
    value = default

    default_quat = Quaternion()
    value_quat = default_quat

    first_strip = True
    for track in anim.nla_tracks:
        if track.mute:
            continue
        if tweak and anim.use_tweak_mode:
            for strip in track.strips:
                if strip.active:
                    break
            else:
                strip = Get.strip_in_track(track, frame=frame)
        else:
            strip = Get.strip_in_track(track, frame=frame)

        action = getattr(strip, 'action', None)
        if not action or strip.mute:
            # Either no strip evaluated or strip is meta strips (TODO)
            continue

        # Try to find property in fcurve
        if index == -1:
            fc = action.fcurves.get(kpath)
        else:
            for fc in action.fcurves:
                if fc.data_path == kpath and fc.array_index == index:
                    break
            else:
                fc = None
        if fc is None:
            if path.endswith('rotation_quaternion') and action.fcurves.get(
                    kpath):
                pass
            else:
                continue

        if frame < strip.frame_start:
            frame_strip = strip.frame_start
        elif (frame > strip.frame_end):
            frame_strip = strip.frame_end
        else:
            frame_strip = frame

        if tweak and strip.active:
            ff = frame
            inf = 1.0
        else:
            ff = frame_strip
            inf = Get.strip_influence(context, strip, frame=frame_strip)

        next_quat = Quaternion()

        if path.endswith('rotation_quaternion'):
            for i in range(4):
                # Don't research curves for the already found curve
                if fc and i == index:
                    next = fc.evaluate(Get.frame_to_strip(strip, ff))
                    next_quat[i] = next
                    continue
                for afc in action.fcurves:
                    if afc.data_path == kpath and afc.array_index == i:
                        next = afc.evaluate(Get.frame_to_strip(strip, ff))
                        next_quat[i] = next
                        break
                else:
                    next_quat[i] = default_quat[i]

        if fc:
            next = fc.evaluate(Get.frame_to_strip(context, strip, ff))
        else:
            next = None

        if (first_strip):
            value = next
            value_quat = next_quat
            first_strip = False
        elif (strip.blend_type == 'COMBINE'):
            if (path.endswith('rotation_axis_angle') and index == 2):
                result = value + (next * inf)
            elif (path.endswith('rotation_quaternion') and index == 0):
                result = value + ((default - next) * inf)
                # result = value * pow(next, inf)
            elif path.endswith('scale'):
                result = value * (next * inf)
            else:
                # result = value - ((default - next) * inf)
                result = value + (next - default) * inf
            # utils.debug(f"{path}[{index}]\t{strip.name}")
            # utils.debug(f"\tValue\t{value}")
            # utils.debug(f"\tNext\t{next}")
            # utils.debug(f"\tResult\t{result}")
            # utils.debug(f'\tGoal\t{getattr(src, path)[index]}')
            value = result

            # "Quaternion blending is deferred until all sub-channel values are known."

            #     # next_val = abs(next - default) * (-1 if next < default else 1)
            #     # value += utils.lerp(0.0, next_val, inf)

            # if path.endswith('rotation_quaternion'):
            #     mix_mode = 'QUATERNION'  # return old value
            #     mix_mode = 'AXIS_ANGLE'  # return old_value + (value - base_value) * inf
            #     # value = nla_combine_value(mix_mode, default, value, next, inf)
            #     # nla_invert_combine_quaternion(value_quat, next_quat, inf, value_quat)
            #     nla_combine_quaternion(value_quat, next_quat, inf, value_quat)
            #     value = value_quat[index]
            # else:
            #     # mix_mode = 'ADD'  # pass
            #     mix_mode = 'AXIS_ANGLE'  # return old_value + (value - base_value) * inf
            #     # mix_mode = 'MULTIPLY'  # return old_value * pow(value / base_value, inf)

            #     value = nla_combine_value(mix_mode, default, value, next, inf)
        else:
            value = nla_blend_value(strip.blend_type, value, next, inf)
            # nla_combine_quaternion(value_quat, next_quat, inf, value_quat)

    return value