Is there a way to imitate Maya's Enable Stepped Preview playback mode?

I was watching an animation tutorial that used Maya and discovered that Maya has a feature called Enable Stepped Preview.

Basically, when this feature is turned on in Maya, it changes every keyframe in the project to be the equivalent of Blender’s “Constant” interpolation type. When you turn this feature off, all of the keyframes go back to using their original interpolation type.

I looked around in Blender to see if there was an equivalent feature, and it doesn’t appear that it exists.

Other than selecting all of the keyframes in an animation and changing the interpolation type to “Constant”, is there a way to do this sort of thing? I’m wondering if someone has done this via an add-on or a Python script.

(The trick, of course, is not to just treat all of the keyframes as having a Constant interpolation type, but to be able to turn this feature off and have all of the keyframes go back to using their original interpolation type.)

1 Like

Never mind – I think I figured it out, though it would take a bit of work to set up. I would need to set up the Stepped modifier in the Graph Editor for every channel where I want to apply this:

I suppose it would be possible to create a script that would set up a stepped modifier for every channel that doesn’t have it and toggle it on/off, but I’m not sure I want to go through the trouble of doing that.

3 Likes

I’ve been wanting to do exactly that for quite a while too, so I’ll try to find some time. No promises but this looks like a simple enough exercise for a beginner like me (I’ve done a similar tool to batch-toggle constraints so… it should be somewhat similar).

1 Like

I think I was incorrect with my assumption that the Stepped f-curve modifier did the equivalent of Maya’s Enable Stepped Preview playback. I messed around with this a bit more (I even started writing a script that would automatically add this modifier to everything in a scene) and realized that’s not what the Stepped f-curve modifier does.

The Stepped f-curve modifier’s Step Size is how “chunky” you want the motion to be. So if you have two keyframes 10 frames apart, setting Step Size to 2 would change the motion every two frames. If you set the Step Size to something ridiculous – like 1000 – it won’t change your keyframe to act like it had all of its keyframes set to constant interpolation; it’ll just hold the last keyframe value until 1000 frames have passed.

So…no, I don’t have an answer for this. Maybe there’s some creative solution that could simulate this feature among the f-curve modifiers, but I went through all of them and didn’t see an obvious way to virtually change all of the keyframes so they act as if they had constant interpolation. If there is a way to do that, though, it would probably be relatively simple to write a script to switch this mode on and off.

OK, I wrote a script that sort of does what I wanted; the only issue is that it’s kind of destructive – it changes ALL of the keyframes in your scene to constant, linear, Bézier, or whatever.

It’s probably not a big deal if all of your curves are Bézier, because I believe Blender will remember the original curve shapes if you switch it to one of the other types and then back to Bézier. But if you have a combination of different kind of curves, you’re essentially going to wipe that out in your scene with this script…though Undo should work.

Since I wanted to use this most when in the early stages of animating, it’s probably not going to be a big deal that this script is destructive. It’s definitely not as good as Maya’s Stepped Preview playback – I would still like to find a way to do that without being destructive.

I have tried this script with cameras, meshes, armatures, and armature bones and it appears to work as expected. I did not try this with any NLA Editor animation, so I don’t know what it would do there.

Just change set_all_frames_interpolation to the type of interpolation you want to use, and put the object types to change in the objects_type_to_affect array.

import bpy

set_all_frames_interpolation = 'CONSTANT'
#set_all_frames_interpolation = 'LINEAR'

object_types_to_affect = ['MESH', 'CAMERA', 'ARMATURE']


if len(bpy.context.scene.objects) > 0:
    for obj in bpy.context.scene.objects:
        if obj.type in object_types_to_affect:            
            if obj.animation_data:
                if obj.animation_data.action:
                    for curve in obj.animation_data.action.fcurves:                    
                        for keyframe in curve.keyframe_points:
                            keyframe.interpolation=set_all_frames_interpolation                                                

EDIT: Fixed a bug where it wasn’t checking if obj.animation_data was non-null.

1 Like

Hot damn, you’re absolutely right - I never realized this wasn’t like Maya’s stepped preview. Well, such a thing would have to be built-in I imagine, unless you went through the trouble of storing each and every keyframe type before switching it to constant, heheh.

Thanks a lot for sharing your script. I spent a few minutes yesterday trying to make sense of where fcurve modifiers were stored… never got past that pseudocode !

# initialize user step value

# if active bone's active fcurve has no stepped modifier
    # add one with user step value
# else set user step value

# set the toggle type (step or unstep) according to this

# for each selected bone
    # for each fcurve
        # check whether it has a stepped modifier
            # if it does check the toggle - if set to step
                # mute = False
                # else mute = True
                    # if different from user value
                        # set to user value
                    # else pass
            # else add stepped modifier with user step value

or you know something like that

On the flipside, the way it works in Blender is kinda neat too - I know I turn my fcurves into splines early on, and sometimes clients want to see something choppy, because they know it means it’s WIP.

Now this probably would make a nice RCS proposal.

By the way you can just use

if bpy.context.scene.objects:

in place of

if len(bpy.context.scene.objects) > 0:

I did something like this (I don’t have the original code anymore, sorry – this is partially copied and pasted from somewhere):

if bpy.context.scene.objects:
    for obj in bpy.context.scene.objects:
            
    # Get all the fcurves related to the z rotation
    fcurves = [f for f in obj.animation_data.action.fcurves if f.data_path == 'rotation_euler' and f.array_index == 2]

    for each curve in fcurves:
            # Add the modifier
            mod = curve.modifiers.new(type='STEPPED')

            # Edit some modifier settings
            #mod.cycles_before = 1
            #mod.cycles_after = 5
1 Like

By the way you can just use

if bpy.context.scene.objects:

in place of

if len(bpy.context.scene.objects) > 0:

Good catch!

Thanks !!!

Feature submitted here: https://blender.community/c/rightclickselect/WVdbbc/