示例#1
0
    def execute(self, context):
        if self.bones:
            bones = eval(self.bones)
        else:
            bones = Get.selected_pose_bones(context)

        if not bones:
            return {'CANCELLED'}

        wgts = readWidgets()
        if self.widget:
            widget = wgts[self.widget]
        else:
            widget = wgts[context.scene.widget_list]

        for bone in bones:
            if bone.id_data.proxy:
                continue
            slide = list(self.slide)
            rotate = list(self.rotate)
            if self.mirror:
                mirror = findMirrorObject(bone)
                if mirror and mirror in bones and bone.name.endswith(
                    ('L', 'l')):
                    slide[0] *= -1
                    rotate[1] *= -1
                    rotate[2] *= -1

            createWidget(
                context,
                bone,
                widget,
                self.relative_size,
                self.global_size,
                [*self.scale],
                slide,
                rotate,
                get_collection(context),
            )

        utils.update(context)

        pr = utils.prefs(__addon__).bone_widgets
        # pr = prefs.prefs().bone_widgets
        if pr.keep_settings:
            pr.slide = self.slide
            pr.rotate = self.rotate
            pr.relative_size = self.relative_size
            pr.global_size = self.global_size
            pr.scale = self.scale
            pr.mirror = self.mirror

        # Create new object then delete it.
        # When creating multiple widgets, if the last one tries to enter edit
        # mode before a particular update occurs, Blender will crash.
        # If the last object created (I.E. this empty) is not the widget,
        # Blender can enter edit mode without crash
        Get.objects(context, link=True).unlink(New.object(context))

        return {'FINISHED'}
示例#2
0
文件: New.py 项目: Irmitya/zpy
def object(context, name='Object', data=None, link=True):
    """
    Create a new object using the specified data.
    If no data is provided, the object will be an empty.
    """

    object = bpy.data.objects.new(name, data)
    if link: Get.objects(context, link=True).link(object)

    return object
示例#3
0
文件: Set.py 项目: Irmitya/zpy
def in_scene(context, object, value=True):
    # TODO: set this function to be able to remove an object from scene
    #       currently it ONLY uses the value for set at True

    if value:
        if Is.collection(object):
            scn = context.scene
            if not Get.collection_from_scene(object, scn.collection):
                scn.collection.children.link(object)
        elif not (Is.in_scene(context, object)
                  and Is.in_view(context, object)):
            Get.objects(context, link=True).link(object)
    def poll_parse(self, context, rig):
        null = [None] * 3

        if not Is.armature(rig):
            return null

        val = rig.get('daz_to_rigify')
        if val == 'metarig':
            meta = rig
            for rig in Get.objects(context):
                if rig.get('daz_to_rigify') == repr(meta):
                    break
            else:
                rig = meta.data.rigify_target_rig
                if rig is None:
                    return null
        elif val is None:
            if rig.data.rigify_layers:
                # Is a regular metarig
                meta = rig
            else:
                # Is a regular rig
                return null
        else:
            try:
                meta = eval(val)
                if meta is None:
                    return null
            except:
                return null
        return (meta, rig)
    def execute(self, context):
        active = Get.active(context)
        active_select = Is.selected(active)
        selected = Get.selected(context)
        is_pose = bool(context.mode == 'POSE')
        arg = dict(only_selected=bool(selected))

        if is_pose:
            clear = bpy.ops.pose.paths_clear

            # Operator only runs on active rig, so repeat for all in pose mode
            if selected:
                obs = {b.id_data for b in selected}
            else:
                obs = {ob for ob in Get.objects(context) if ob.mode == 'POSE'}

            for ob in obs:
                Set.active(context, ob)
                clear(**arg)
            else:
                Set.active(context, active)
                Set.select(active, active_select)
        elif bpy.ops.object.paths_clear.poll(context.copy()):
            bpy.ops.object.paths_clear(**arg)

        return {'FINISHED'}
示例#6
0
    def get_rig_meshes(self, context):
        """
        Find the selected rigs and meshes, attached together.
        If only a rig is selected, find all the meshes that use it.
        """

        active = context.object

        if context.mode == 'PAINT_WEIGHT':
            meshes = {active}
            rig = None
            for mod in active.modifiers:
                if (mod.type == 'ARMATURE') and (mod.object in Get.objects(context)[:]):
                    rig = mod.object
                    if rig.mode == 'POSE':
                        break
            if not rig:
                self.report({'ERROR'}, "Can't find rig using the active mesh")
        else:
            rig = active
            meshes = set()
            for ob in context.selected_objects:
                if Is.mesh(ob):
                    for mod in ob.modifiers:
                        if (mod.type == 'ARMATURE') and (mod.object == rig):
                            meshes.add(ob)

            if not meshes:
                for ob in Get.objects(context):
                    if not Is.visible(context, ob):
                        continue

                    for mod in ob.modifiers:
                        if (mod.type == 'ARMATURE') and (mod.object == rig):
                            meshes.add(ob)

            if not meshes:
                self.report({'ERROR'}, "Can't find mesh using the active rig")

        return (rig, meshes)
示例#7
0
    def poll(cls, context):
        ob = context.object

        if Is.armature(ob) and ob.mode in ('POSE', 'EDIT'):
            return Get.selected(context, ob)

        if not bpy.ops.paint.weight_from_bones.poll(context.copy()):
            return

        if Is.mesh(ob) and (ob.mode == 'WEIGHT_PAINT'):
            for mod in ob.modifiers:
                if (mod.type == 'ARMATURE') and (mod.object in Get.objects(context)[:]):
                    if mod.object.mode == 'POSE':
                        return True
示例#8
0
    def poll_parse(self, context, rig):
        null = [None] * 2
        if (not Is.armature(rig)):
            return null
        if (rig.data.get('rig_id') is None):
            meta = rig
            rig = meta.data.rigify_target_rig
            if rig is None:
                return null
        else:
            for meta in Get.objects(context):
                if Is.armature(meta) and meta.data.rigify_target_rig == rig:
                    break
            else:
                return null

        return (rig, meta)
示例#9
0
文件: Set.py 项目: 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
示例#10
0
def get_selected_keys_and_extents():
    context = bpy.context
    pbones = context.selected_pose_bones
    if pbones is None:
        pbones = []
    curve_datas = []
    selected = []
    objects = []
    bones = []
    fcurves = []

    try:
        only_selected = context.space_data.dopesheet.show_only_selected
        show_hidden = context.space_data.dopesheet.show_hidden
    except:
        only_selected = True
        show_hidden = False

    def add_obj(obj):
        if show_hidden is False and not Is.visible(context, obj):
            return None
        if obj not in selected:
            selected.append(obj)

    def add_bone(b):
        if only_selected and not b.bone.select:
            return None
        add_obj(b.id_data)
        bones.append(b)

    for obj in Get.objects(context):
        if show_hidden is False and not Is.visible(context, obj):
            continue

        # Add object and bones
        if not (only_selected and not Is.selected(obj)):
            add_obj(obj)
        if obj.pose is not None:
            for (name, pbone) in obj.pose.bones.items():
                if any((only_selected is False, Is.selected(obj), pbone in pbones,)):
                    add_bone(pbone)

    # Add fcurves from objects
    for obj in selected:
        anim = obj.animation_data
        if anim and anim.action:
            fcurves.extend([(obj, fc) for fc in anim.action.fcurves])

    # Scan fcurves for keyframes
    for obj, curve in fcurves:
        if curve.hide or curve.lock or not curve.select:
            continue
        first_co = None
        points = None
        last_co = None
        path = curve.data_path

        # Read path to get target's name
        if (path.startswith('pose.bones')):
            # btype =   'BONE'
            # bpath =   path.split('"]', 1)[1]      ## Transforms and custom prop
            # if (bpath.startswith('.')):       ## constraints?
                # bpath =   bpath.split('.', 1)[1]
            bname = (path.split('["', 1)[1].split('"]', 1)[0])
            bone = obj.pose.bones.get(bname)
        elif (path.startswith('bones')):  # data.bones
            # btype = 'BONE'
            # bpath = path.split('"].', 1)[1]
            bname = (path.split('["', 1)[1].split('"]', 1)[0])
            bone = obj.bones.get(bname)
        else:
            # btype = 'OBJECT'
            # bpath = path
            bname = obj.name
            bone = obj

        if (bone is None and curve.is_valid is True) or (bone is not None and bone != obj and bone not in bones):
            # Bone not selected
            continue

        keyframes_referenced = []
        keyframes_data = []
        for keyframe in curve.keyframe_points:
            if keyframe.select_control_point:
                if first_co is None:
                    first_co = keyframe.co
                else:
                    last_co = keyframe.co
                keyframes_referenced.append(keyframe)
                keyframes_data.append({
                    'co': deepcopy(keyframe.co),
                    'handle_left': deepcopy(keyframe.handle_left),
                    'handle_right': deepcopy(keyframe.handle_right)
                })  # needs to be all three data points!
        if last_co is not None:
            curve_datas.append([keyframes_referenced, first_co, last_co, keyframes_data, curve])
    return curve_datas
示例#11
0
    def get_keys(self, context):
        scn_frame = context.scene.frame_current_final
        fcurves = dict()
        quats = dict()
        updates = dict()

        break_sync = False
        if hasattr(context.scene, 'sync'):
            break_sync = context.scene.sync.sync_3d and context.scene.sync.sync_between_3d

        if context.mode == 'POSE':
            # objects = [o for o in Get.objects(context) if o.mode == 'POSE']
            objects = list()

            for ob in Get.objects(context):
                if ob.mode != 'POSE':
                    continue
                bones = tuple([f"pose.bones[\"{b.name}\"]"
                    for b in Get.selected_pose_bones(context, ob)])
                if bones:
                    objects.append((ob, bones))

            if not objects:
                for ob in Get.objects(context):
                    if ob.mode != 'POSE':
                        continue
                    bones = tuple([f"pose.bones[\"{b.name}\"]"
                        for b in ob.pose.bones if Is.visible(context, b)])
                    if bones:
                        objects.append((ob, bones))
        else:
            objects = [(o, list()) for o in Get.selected_objects(context)]

        for (ob, bones) in objects:
            for anim in Get.animation_datas(ob):
                action = anim.action
                if not action:
                    continue

                if anim.use_tweak_mode:
                    frame = Get.frame_to_strip(context, anim, scn_frame)
                    for s in Get.strips(anim.id_data):
                        if s.action == action:
                            strip = s
                            if s.active: break
                    blend = strip.blend_type
                else:
                    frame = scn_frame
                    blend = anim.action_blend_type

                offset = abs(frame - scn_frame)
                if (scn_frame < frame):
                    offset *= -1

                for fc in anim.action.fcurves:
                    path = fc.data_path
                    index = fc.array_index

                    if len(fc.keyframe_points) < 2:
                        continue
                    if bones:
                        src = None
                        for bone in bones:
                            if path.startswith(bone):
                                try:
                                    eval(repr(ob) + '.' + path)  # Validate path
                                    src = eval(repr(ob) + '.' + bone)
                                    attr = path.replace(bone, '', 1)
                                    if attr.startswith('.'):
                                        attr = attr.replace('.', '', 1)
                                        is_custom = False
                                    else:
                                        is_custom = True
                                except:
                                    # curve points to a removed bone or something
                                    src = None
                                break
                        else:
                            # Pose mode but bone not selected
                            continue
                        if src is None:
                            # Missing bone
                            continue
                    else:
                        attr = path
                        src = ob

                        if attr in transforms:
                            is_custom = False
                        elif attr.startswith('["'):
                            is_custom = True
                        else:
                            # if attr.startswith(('pose.bones', 'bones')):
                            continue

                    # Find the property to be able to manipulate, and its current value
                    if is_custom:
                        prop = src
                        split = attr.rsplit('"]["', 1)
                        if len(split) == 2:
                            prop = eval(repr(src) + split[0] + '"]')
                            attr = '["' + split[1]
                        prop_value = getattr(prop, attr)
                    elif hasattr(src, attr):
                        prop = getattr(src, attr)
                        if Is.iterable(prop):
                            # elif attr in transforms:
                                # prop = src.path_resolve(attr)
                            prop_value = prop[index]
                        else:
                            prop = src
                            prop_value = getattr(prop, attr)
                    else:
                        # maybe a constraint:
                            # pose.bones[bone.name].constraints[con.name].influence
                        continue

                    # Function to apply values to the bone/object, later
                    if Is.iterable(prop):
                        def apply(self, val):
                            "Function to apply values to (array) in bone/object, later"
                            self.prop[self.index] = val

                        prop = src.path_resolve(attr)
                        prop_value = prop[index]
                        is_array = True
                    else:
                        def apply(self, val):
                            setattr(self.prop, self.attr, val)
                        is_array = False

                    cache = dict(
                        attr=attr,
                        apply=apply,
                        index=index,
                        is_array=is_array,
                        key=None,
                        quat=None,
                        prop=prop,
                        src=src,
                        value=fc.evaluate(frame),
                    )
                    left = type('', (), cache)
                    current = type('', (), cache)
                    current.found = False
                    right = type('', (), cache)

                    pre_key = None

                    # Find the current keyframe, and keys left and right
                    if break_sync:
                        # types = context.scene.keyframe_navigation_types
                        types = ('KEYFRAME', 'MOVING_HOLD')
                        for key in fc.keyframe_points:
                            if key.co.x < frame:
                                if (left.key is None) or (key.type in types):
                                    left.key = key
                                    left.value = key.co.y
                                    right.key = key
                                    right.value = key.co.y
                            elif key.co.x == frame:
                                if left.key is None:
                                    left.key = key
                                    left.value = key.co.y
                                current.key = key
                                current.found = True
                                right.key = key
                                right.value = key.co.y
                            elif key.co.x > frame:
                                if left.key is None:
                                    left.key = key
                                    left.value = key.co.y
                                if (key.type in types) or key == fc.keyframe_points[-1]:
                                    right.key = key
                                    right.value = key.co.y
                                    break

                    if not (left.key and right.key):
                        for key in fc.keyframe_points:
                            if key.co.x < frame:
                                left.key = key
                                left.value = key.co.y
                                right.key = key
                                right.value = key.co.y
                            elif key.co.x == frame:
                                if left.key is None:
                                    left.key = key
                                    left.value = key.co.y
                                current.key = key
                                current.found = True
                                right.key = key
                                right.value = key.co.y
                            elif key.co.x > frame:
                                if left.key is None:
                                    left.key = key
                                    left.value = key.co.y
                                right.key = key
                                right.value = key.co.y
                                break

                    if not (left.key and right.key):
                        # Nothing to tween
                        continue

                    # Get info for current keyframe's defaults

                    sVal = left.key.co.x + offset
                    eVal = right.key.co.x + offset

                    current.w1 = frame - sVal
                    current.w2 = eVal - frame

                    left.frame = left.key.co.x
                    current.frame = frame
                    right.frame = right.key.co.x

                    current.in_range = False
                    if frame < left.frame:
                        left.value = prop_value
                    elif right.frame < frame:
                        right.value = prop_value
                    else:
                        current.in_range = True

                    if blend == 'REPLACE':
                        current.value = prop_value
                    else:
                        if not self.has_additive:
                            self.has_additive = True

                        if current.key:
                            value = current.key.co.y
                        else:
                            value = fc.evaluate(frame)

                        left.value = prop_value + (left.value - value)
                        current.value = prop_value  # + (value - value)
                        right.value = prop_value + (right.value - value)

                        if tween.update:
                            if sVal not in updates:
                                updates[sVal] = list()
                            if eVal not in updates:
                                updates[eVal] = list()
                            updates[sVal].append(left)
                            updates[eVal].append(right)

                    # Add classes to memory
                    fcurves[fc] = [left, current, right]

                    if attr == 'rotation_quaternion':
                        # Do math for quaternions
                        if (action, path) not in quats:
                            quats[(action, path)] = dict()

                        if (src.lock_rotations_4d or not src.lock_rotation_w) \
                            and True not in src.lock_rotation[:]:
                            quats[(action, path)][index] = (left, current, right)

        if updates:
            for frame in updates:
                context.scene.frame_set(frame)

                for (cls) in updates[frame]:
                    if Is.iterable(prop):
                        cls.value = cls.prop[cls.index]
                    else:
                        cls.value = getattr(cls.prop, cls.attr)

            context.scene.frame_set(scn_frame)

        for (action, path) in quats:
            if len(quats[action, path]) < 4:
                continue
            (w_left, w_current, w_right) = quats[action, path][0]
            (x_left, x_current, x_right) = quats[action, path][1]
            (y_left, y_current, y_right) = quats[action, path][2]
            (z_left, z_current, z_right) = quats[action, path][3]

            left_quat = [x.value for x in (w_left, x_left, y_left, z_left)]
            current_quat = [x.value for x in (w_current, x_current, y_current, z_current)]
            right_quat = [x.value for x in (w_right, x_right, y_right, z_right)]

            cpp.normalize_qt(left_quat)
            cpp.normalize_qt(current_quat)
            cpp.normalize_qt(right_quat)

            for x in (w_left, x_left, y_left, z_left):
                x.quat = left_quat
            for x in (w_current, x_current, y_current, z_current):
                x.quat = current_quat
            for x in (w_right, x_right, y_right, z_right):
                x.quat = right_quat

        return fcurves
示例#12
0
    def update_pose(self, context):
        # for region in context.area.regions:
        # if region.type == 'WINDOW':
        # break
        # else:
        # return self.cancel(context)
        region = context.region
        rv3d = context.space_data.region_3d

        gp = context.annotation_data

        stroke = gp.layers.active.frames[0].strokes[0]

        for chain in Get.sorted_chains(context.selected_pose_bones):
            bone_chain = list()

            for bone in reversed(chain):
                bone_chain.insert(0, bone)
                if bone == chain[0]:
                    # Do location
                    pass
                    # continue  # or break; should do the same
                else:
                    pass

                    while bone.parent not in chain:
                        # Do unselected in betweens
                        bone = bone.parent
                        if not Is.visible(context, bone):
                            # Don't rotate hidden bones
                            continue

                        bone_chain.insert(0, bone)

            bcount = len(bone_chain) - 1
            gcount = len(stroke.points) - 1

            # if bcount:
            # while gcount > bcount * 3:
            # # Split point count in half
            # index = 0
            # while index < len(stroke.points) - 1:
            #     stroke.points.pop(index=index + 1)
            #     index += 1
            # print(bcount, gcount, '\t', index, len(stroke.points))

            # gcount = len(stroke.points) - 1

            bone_mats = list()
            con_tmp = list()

            index = 0
            for bone in bone_chain:
                if index > bcount:
                    index = bcount

                point_index = utils.scale_range(index, 0, bcount, 0, gcount)
                point = stroke.points[int(point_index)]

                if index == 0:
                    if not (bone.parent):
                        bone = bone_chain[0]
                        point = stroke.points[0]

                        to_2d = location_3d_to_region_2d(
                            region, rv3d, point.co)  # get 2d space of stroke
                        if to_2d:
                            to_3d = region_2d_to_location_3d(
                                region, rv3d, to_2d,
                                bone.head)  # keep depth of bone

                            empty = New.object(context, bone.name)
                            empty.empty_display_size = 0.25
                            empty.location = to_3d

                            con = bone.constraints.new('COPY_LOCATION')
                            con.target = empty
                            con_tmp.append((bone, con, empty))

                    if bcount == 0:
                        point = stroke.points[-1]
                    else:
                        # index += 1
                        point_index = utils.scale_range(
                            0.5, 0, bcount, 0, gcount)
                        point = stroke.points[int(point_index)]

                to_2d = location_3d_to_region_2d(
                    region, rv3d, point.co)  # get 2d space of stroke
                if to_2d:
                    to_3d = region_2d_to_location_3d(
                        region, rv3d, to_2d, bone.tail)  # keep depth of bone

                    empty = New.object(context, bone.name)
                    empty.empty_display_size = 0.1
                    empty.location = to_3d

                    con = bone.constraints.new('DAMPED_TRACK')
                    con.target = empty
                    con_tmp.append((bone, con, empty))

                index += 1

            utils.update(context)
            for (bone, con, empty) in reversed(con_tmp):
                mat = Get.matrix_constraints(context, bone)
                # mat = Get.matrix(bone)
                bone_mats.append((bone, mat))

                bone.constraints.remove(con)
                Get.objects(context, link=True).unlink(empty)

            for (bone, mat) in bone_mats:
                Set.matrix(bone, mat)
                keyframe.keyingset(context, selected=[bone], skip_bones=True)

        self.remove_annotation(context)

        return {'FINISHED'}