diff options
-rw-r--r-- | source/blender/editors/include/ED_screen_types.h | 10 | ||||
-rw-r--r-- | source/blender/editors/screen/screen_ops.c | 29 |
2 files changed, 28 insertions, 11 deletions
diff --git a/source/blender/editors/include/ED_screen_types.h b/source/blender/editors/include/ED_screen_types.h index 06c2c3039f5..51f3eea74fa 100644 --- a/source/blender/editors/include/ED_screen_types.h +++ b/source/blender/editors/include/ED_screen_types.h @@ -34,11 +34,11 @@ extern "C" { typedef struct ScreenAnimData { ARegion *region; /* do not read from this, only for comparing if region exists */ short redraws; - short flag; /* flags for playback */ - int sfra; /* frame that playback was started from */ - int nextfra; /* next frame to go to (when ANIMPLAY_FLAG_USE_NEXT_FRAME is set) */ - double last_duration; /* used for frame dropping */ - bool from_anim_edit; /* playback was invoked from animation editor */ + short flag; /* flags for playback */ + int sfra; /* frame that playback was started from */ + int nextfra; /* next frame to go to (when ANIMPLAY_FLAG_USE_NEXT_FRAME is set) */ + double lagging_frame_count; /* used for frame dropping */ + bool from_anim_edit; /* playback was invoked from animation editor */ } ScreenAnimData; /* for animplayer */ diff --git a/source/blender/editors/screen/screen_ops.c b/source/blender/editors/screen/screen_ops.c index cb3984aa9ad..5b808206935 100644 --- a/source/blender/editors/screen/screen_ops.c +++ b/source/blender/editors/screen/screen_ops.c @@ -4437,10 +4437,29 @@ static int screen_animation_step(bContext *C, wmOperator *UNUSED(op), const wmEv } else { if (sync) { - /* note: this is very simplistic, - * its has problem that it may skip too many frames. - * however at least this gives a less jittery playback */ - const int step = max_ii(1, floor((wt->duration - sad->last_duration) * FPS)); + /* Try to keep the playback in realtime by dropping frames. */ + + /* How much time (in frames) has passed since the last frame was drawn? */ + double delta_frames = wt->delta * FPS; + + /* Add the remaining fraction from the last time step. */ + delta_frames += sad->lagging_frame_count; + + if (delta_frames < 1.0) { + /* We can render faster than the scene frame rate. However skipping or delaying frames + * here seems to in practice lead to jittery playback so just step forward a minimum of + * one frame. (Even though this can lead to too fast playback, the jitteryness is more + * annoying) + */ + delta_frames = 1.0f; + sad->lagging_frame_count = 0; + } + else { + /* Extract the delta frame fractions that will be skipped when converting to int. */ + sad->lagging_frame_count = delta_frames - (int)delta_frames; + } + + const int step = delta_frames; /* skip frames */ if (sad->flag & ANIMPLAY_FLAG_REVERSE) { @@ -4461,8 +4480,6 @@ static int screen_animation_step(bContext *C, wmOperator *UNUSED(op), const wmEv } } - sad->last_duration = wt->duration; - /* reset 'jumped' flag before checking if we need to jump... */ sad->flag &= ~ANIMPLAY_FLAG_JUMPED; |