Пример #1
0
    def preview_nla(self, context):
        scn = context.scene
        start = end = None

        # Set preview range using snapping (from frame_step operator)
        prefs = scn.step_frames
        stepped = prefs.on_steps
        frame_step = prefs.frame_step

        strips_nla = Get.strips_nla(context)

        for (obj, strips) in strips_nla:
            for item in strips:
                strip = item.strip

                # Scale update start value
                frame_start = int(strip.frame_start)
                if stepped:
                    while (frame_start % frame_step):
                        frame_start -= 1
                if (start is None) or (frame_start < start):
                    start = frame_start

            # Get used frame range from repeat
            # if (strip.repeat != 1.0):
            #     fs = strip.frame_start
            #     fe = strip.frame_end
            #     fe2 = scale_range(fe, fs, fe, 0, abs(fs - fe))
            #     frame_end = int((1 / strip.repeat) * fe2 + fs)
            # else:
            #     frame_end = int(strip.frame_end)
                if self.repeat:
                    afe = strip.action_frame_end
                    frame_end = Get.frame_from_strip(context, strip, afe)
                else:
                    frame_end = strip.frame_end
                frame_end = round(frame_end, 4)

                # Update end value
                if stepped:
                    while (frame_end % frame_step):
                        frame_end += 1
                if (strip.repeat > 1.0) and self.repeat:
                    # Don't let loops end on the first frame
                    frame_end -= 1
                if (end is None) or (end < frame_end):
                    end = frame_end

        if (None not in {start, end}):
            scn.use_preview_range = True
            scn.frame_preview_end = end
            scn.frame_preview_start = start
            return {'FINISHED'}
        else:
            if strips_nla:
                self.report({'WARNING'}, "Couldn't set preview; using default")
            return bpy.ops.nla.previewrange_set()
Пример #2
0
def scan_strips(context, sub, selected):
    frames = list()
    for obj in Get.objects_nla(context):
        data = getattr(obj, 'data', None)
        shapes = getattr(data, 'shape_keys', None)

        # Poll object
        if pose(context):
            if not pose(obj):
                continue
            elif selected:
                if not Get.selected_pose_bones(context, src=obj):
                    continue
        else:
            if (selected and obj not in selected):
                continue

        for src in (obj, data, shapes):
            frames_fcurve = list()
            frames_strip = list()
            for item in Get.strip_tracks(src, selected=False):
                strip = item.strip

                if strip.mute and not strip.select:
                    continue

                for fc in strip.fcurves:
                    if fc.hide:
                        continue
                    scan_fcurve(context, sub, fc, frames_fcurve)

                if frames_fcurve:
                    # Don't scan strip boxes if have animation keyframes
                    continue

                (fs, fe) = (strip.frame_start, strip.frame_end)
                if not sub:
                    (fs, fe) = (smooth(fs), smooth(fe))
                frames_strip.append(fs)
                frames_strip.append(fe)

                # Get loop ends
                if (strip.action) and (strip.repeat != 1.0):
                    afe = strip.action_frame_end
                    fel = fer = Get.frame_from_strip(context, strip, afe)
                    while fel < strip.frame_end:
                        frames_strip.append([smooth(fel), fel][sub])
                        fel += (fer - strip.frame_start)

            if frames_fcurve:
                frames.extend(frames_fcurve)
            else:
                frames.extend(frames_strip)

    return sorted(set(frames))
Пример #3
0
def scan_fcurve(context, sub, fcurve, frames=list(), strip=None):
    scn = context.scene
    fc = (int(scn.frame_current_final), scn.frame_current_final)[sub]
    if not fcurve.keyframe_points:
        return frames

    types = scn.keyframe_navigation_types
    (first_key, last_key) = (fcurve.keyframe_points[0],
                             fcurve.keyframe_points[-1])

    if ('HIDDEN' not in types) and fcurve.hide:
        return frames

    keyframes = list()
    for key in fcurve.keyframe_points:
        if (key.type not in types):  # and key not in (first_key, last_key):
            continue
        co = key.co[0]
        # cycos = list()
        if strip:
            co = Get.frame_from_strip(context, strip, frame=co)
            # for (x, loco) in enumerate(cycle):
            #     cyco = co + x * loco
            #     cycos.append(cyco)
            # if cycle and (strip.repeat % 1):  # has decimal
            #     cycos.append(cyco + loco)

        keyframes.append(co)

        # for cyco in cycos:
        #     if not sub: cyco = smooth(cyco)
        #     frames.append(cyco)

    for co in keyframes:
        if not sub: co = smooth(co)
        frames.append(co)

    use_cycles = scn.tool_settings.use_keyframe_cycle_aware
    for mod in fcurve.modifiers:
        if (mod.type == 'CYCLES') and use_cycles:
            (fs, fe) = (keyframes[0], keyframes[-1])
            if abs(fs - fe) < 1:
                continue
            cycos = list()

            offset = (fe - fs)

            loops = list()
            if fe <= fc:
                fel = fe
                while fel <= fc:
                    loops.append(1)
                    fel += offset
            elif fc <= fs:
                fsl = fs
                while fc <= fsl:
                    loops.append(-1)
                    fsl -= offset

            for (x, fl) in enumerate(loops):
                for co in keyframes:
                    co += ((x + 1) * (offset * fl))

                    if not sub: co = smooth(co)
                    frames.append(co)

    return frames
Пример #4
0
def scan_actions(context, sub, selected):
    scn = context.scene
    fc = (int(scn.frame_current_final), scn.frame_current_final)[sub]
    frames = list()

    for obj in selected:
        if Is.gpencil(obj):
            for layer in obj.data.layers:
                for frame in layer.frames:
                    frames.append(frame.frame_number)

    for obj in Get.objects_nla(context):
        # Poll object
        if pose(context):
            if not pose(obj):
                continue
            elif selected:
                bones = [
                    f'pose.bones[\"{b.name}\"]'
                    for b in Get.selected_pose_bones(context, src=obj)
                ]
                if not bones:
                    continue
            else:
                bones = list()
        else:
            if (selected and obj not in selected):
                continue
            else:
                bones = list()

        for anim in Get.animation_datas(obj):
            if (not anim.action):
                continue
            if anim.use_tweak_mode:
                for s in Get.strips(anim.id_data):
                    if s.action == anim.action:
                        strip = s
                        if s.active: break

                # Get loop ends
                cycle = list()
                afe = strip.action_frame_end
                fel = fer = Get.frame_from_strip(context, strip, afe)
                while fel < strip.frame_end:
                    offset = (fer - strip.frame_start)
                    cycle.append(offset)
                    fel += abs(offset)
                    # If offset becomes negative, it "should" create an infinite loop
                    # abs() forces positive, which "should" prevent loop
            else:
                strip = None

            for fcurve in anim.action.fcurves:
                path = fcurve.data_path
                if bones:
                    # Bones are selected, so verify this fcurve if for one of them
                    for bpath in bones:
                        if path.startswith(bpath):
                            break
                    else:
                        continue
                elif path.startswith('pose.bones[\"'):
                    try:
                        eval(repr(obj) + '.' + path)  # Validate path
                        bpath = path.split('\"]', 1)[0] + '\"]'
                        bone = eval(repr(obj) + '.' + bpath)
                        if not Is.visible(context, bone):
                            continue
                    except:
                        # curve points to a removed bone or something
                        continue

                scan_fcurve(context, sub, fcurve, frames, strip=strip)

    return sorted(set(frames))