Fix T66913: undo after frame-change doesn't refresh properly
Use the ID.recalc flag to detect when updates after frame-change is needed. Since comparing the last calculated frame doesn't take undo into account (see code-comment for details). `ID_RECALC_AUDIO_SEEK` has been renamed to `ID_RECALC_FRAME_CHANGE` since this is not only related to audio however internally this flag is still categorized in `NodeType::AUDIO`. Reviewed By: sergey Ref D13942
This commit is contained in:
		@@ -2522,7 +2522,7 @@ void BKE_scene_update_sound(Depsgraph *depsgraph, Main *bmain)
 | 
			
		||||
  Scene *scene = DEG_get_evaluated_scene(depsgraph);
 | 
			
		||||
  const int recalc = scene->id.recalc;
 | 
			
		||||
  BKE_sound_ensure_scene(scene);
 | 
			
		||||
  if (recalc & ID_RECALC_AUDIO_SEEK) {
 | 
			
		||||
  if (recalc & ID_RECALC_FRAME_CHANGE) {
 | 
			
		||||
    BKE_sound_seek_scene(bmain, scene);
 | 
			
		||||
  }
 | 
			
		||||
  if (recalc & ID_RECALC_AUDIO_FPS) {
 | 
			
		||||
 
 | 
			
		||||
@@ -72,6 +72,14 @@ void DEG_evaluate_on_refresh(Depsgraph *graph)
 | 
			
		||||
    deg_graph->frame = frame;
 | 
			
		||||
    deg_graph->ctime = ctime;
 | 
			
		||||
  }
 | 
			
		||||
  else if (scene->id.recalc & ID_RECALC_FRAME_CHANGE) {
 | 
			
		||||
    /* Comparing depsgraph & scene frame fails in the case of undo,
 | 
			
		||||
     * since the undo state is stored before updates from the frame change have been applied.
 | 
			
		||||
     * In this case reading back the undo state will behave as if no updates on frame change
 | 
			
		||||
     * is needed as the #Depsgraph.ctime & frame will match the values in the input scene.
 | 
			
		||||
     * Use #ID_RECALC_FRAME_CHANGE to detect that recalculation is necessary. see: T66913. */
 | 
			
		||||
    deg_graph->tag_time_source();
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  deg_flush_updates_and_refresh(deg_graph);
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -211,7 +211,7 @@ void depsgraph_tag_to_component_opcode(const ID *id,
 | 
			
		||||
    case ID_RECALC_SEQUENCER_STRIPS:
 | 
			
		||||
      *component_type = NodeType::SEQUENCER;
 | 
			
		||||
      break;
 | 
			
		||||
    case ID_RECALC_AUDIO_SEEK:
 | 
			
		||||
    case ID_RECALC_FRAME_CHANGE:
 | 
			
		||||
    case ID_RECALC_AUDIO_FPS:
 | 
			
		||||
    case ID_RECALC_AUDIO_VOLUME:
 | 
			
		||||
    case ID_RECALC_AUDIO_MUTE:
 | 
			
		||||
@@ -737,8 +737,8 @@ const char *DEG_update_tag_as_string(IDRecalcFlag flag)
 | 
			
		||||
      return "EDITORS";
 | 
			
		||||
    case ID_RECALC_SEQUENCER_STRIPS:
 | 
			
		||||
      return "SEQUENCER_STRIPS";
 | 
			
		||||
    case ID_RECALC_AUDIO_SEEK:
 | 
			
		||||
      return "AUDIO_SEEK";
 | 
			
		||||
    case ID_RECALC_FRAME_CHANGE:
 | 
			
		||||
      return "FRAME_CHANGE";
 | 
			
		||||
    case ID_RECALC_AUDIO_FPS:
 | 
			
		||||
      return "AUDIO_FPS";
 | 
			
		||||
    case ID_RECALC_AUDIO_VOLUME:
 | 
			
		||||
 
 | 
			
		||||
@@ -169,7 +169,7 @@ static void change_frame_apply(bContext *C, wmOperator *op)
 | 
			
		||||
  FRAMENUMBER_MIN_CLAMP(CFRA);
 | 
			
		||||
 | 
			
		||||
  /* do updates */
 | 
			
		||||
  DEG_id_tag_update(&scene->id, ID_RECALC_AUDIO_SEEK);
 | 
			
		||||
  DEG_id_tag_update(&scene->id, ID_RECALC_FRAME_CHANGE);
 | 
			
		||||
  WM_event_add_notifier(C, NC_SCENE | ND_FRAME, scene);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -1662,7 +1662,7 @@ void ED_screen_animation_timer(bContext *C, int redraws, int sync, int enable)
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /* Seek audio to ensure playback in preview range with AV sync. */
 | 
			
		||||
  DEG_id_tag_update(&scene->id, ID_RECALC_AUDIO_SEEK);
 | 
			
		||||
  DEG_id_tag_update(&scene->id, ID_RECALC_FRAME_CHANGE);
 | 
			
		||||
 | 
			
		||||
  /* Notifier caught by top header, for button. */
 | 
			
		||||
  WM_event_add_notifier(C, NC_SCREEN | ND_ANIMPLAY, NULL);
 | 
			
		||||
 
 | 
			
		||||
@@ -2986,7 +2986,7 @@ static int frame_offset_exec(bContext *C, wmOperator *op)
 | 
			
		||||
 | 
			
		||||
  areas_do_frame_follow(C, false);
 | 
			
		||||
 | 
			
		||||
  DEG_id_tag_update(&scene->id, ID_RECALC_AUDIO_SEEK);
 | 
			
		||||
  DEG_id_tag_update(&scene->id, ID_RECALC_FRAME_CHANGE);
 | 
			
		||||
 | 
			
		||||
  WM_event_add_notifier(C, NC_SCENE | ND_FRAME, scene);
 | 
			
		||||
 | 
			
		||||
@@ -3047,7 +3047,7 @@ static int frame_jump_exec(bContext *C, wmOperator *op)
 | 
			
		||||
 | 
			
		||||
    areas_do_frame_follow(C, true);
 | 
			
		||||
 | 
			
		||||
    DEG_id_tag_update(&scene->id, ID_RECALC_AUDIO_SEEK);
 | 
			
		||||
    DEG_id_tag_update(&scene->id, ID_RECALC_FRAME_CHANGE);
 | 
			
		||||
 | 
			
		||||
    WM_event_add_notifier(C, NC_SCENE | ND_FRAME, scene);
 | 
			
		||||
  }
 | 
			
		||||
@@ -3161,7 +3161,7 @@ static int keyframe_jump_exec(bContext *C, wmOperator *op)
 | 
			
		||||
 | 
			
		||||
  areas_do_frame_follow(C, true);
 | 
			
		||||
 | 
			
		||||
  DEG_id_tag_update(&scene->id, ID_RECALC_AUDIO_SEEK);
 | 
			
		||||
  DEG_id_tag_update(&scene->id, ID_RECALC_FRAME_CHANGE);
 | 
			
		||||
 | 
			
		||||
  WM_event_add_notifier(C, NC_SCENE | ND_FRAME, scene);
 | 
			
		||||
 | 
			
		||||
@@ -3225,7 +3225,7 @@ static int marker_jump_exec(bContext *C, wmOperator *op)
 | 
			
		||||
 | 
			
		||||
  areas_do_frame_follow(C, true);
 | 
			
		||||
 | 
			
		||||
  DEG_id_tag_update(&scene->id, ID_RECALC_AUDIO_SEEK);
 | 
			
		||||
  DEG_id_tag_update(&scene->id, ID_RECALC_FRAME_CHANGE);
 | 
			
		||||
 | 
			
		||||
  WM_event_add_notifier(C, NC_SCENE | ND_FRAME, scene);
 | 
			
		||||
 | 
			
		||||
@@ -4626,7 +4626,7 @@ static int screen_animation_step_invoke(bContext *C, wmOperator *UNUSED(op), con
 | 
			
		||||
  if (scene_eval == NULL) {
 | 
			
		||||
    /* Happens when undo/redo system is used during playback, nothing meaningful we can do here. */
 | 
			
		||||
  }
 | 
			
		||||
  else if (scene_eval->id.recalc & ID_RECALC_AUDIO_SEEK) {
 | 
			
		||||
  else if (scene_eval->id.recalc & ID_RECALC_FRAME_CHANGE) {
 | 
			
		||||
    /* Ignore seek here, the audio will be updated to the scene frame after jump during next
 | 
			
		||||
     * dependency graph update. */
 | 
			
		||||
  }
 | 
			
		||||
@@ -4741,7 +4741,7 @@ static int screen_animation_step_invoke(bContext *C, wmOperator *UNUSED(op), con
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  if (sad->flag & ANIMPLAY_FLAG_JUMPED) {
 | 
			
		||||
    DEG_id_tag_update(&scene->id, ID_RECALC_AUDIO_SEEK);
 | 
			
		||||
    DEG_id_tag_update(&scene->id, ID_RECALC_FRAME_CHANGE);
 | 
			
		||||
#ifdef PROFILE_AUDIO_SYNCH
 | 
			
		||||
    old_frame = CFRA;
 | 
			
		||||
#endif
 | 
			
		||||
 
 | 
			
		||||
@@ -1082,7 +1082,7 @@ static void change_frame_apply(bContext *C, wmOperator *op)
 | 
			
		||||
  SUBFRA = 0.0f;
 | 
			
		||||
 | 
			
		||||
  /* do updates */
 | 
			
		||||
  DEG_id_tag_update(&scene->id, ID_RECALC_AUDIO_SEEK);
 | 
			
		||||
  DEG_id_tag_update(&scene->id, ID_RECALC_FRAME_CHANGE);
 | 
			
		||||
  WM_event_add_notifier(C, NC_SCENE | ND_FRAME, scene);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -1385,7 +1385,7 @@ static int frame_jump_exec(bContext *C, wmOperator *op)
 | 
			
		||||
 | 
			
		||||
  if (CFRA != sc->user.framenr) {
 | 
			
		||||
    CFRA = sc->user.framenr;
 | 
			
		||||
    DEG_id_tag_update(&scene->id, ID_RECALC_AUDIO_SEEK);
 | 
			
		||||
    DEG_id_tag_update(&scene->id, ID_RECALC_FRAME_CHANGE);
 | 
			
		||||
 | 
			
		||||
    WM_event_add_notifier(C, NC_SCENE | ND_FRAME, scene);
 | 
			
		||||
  }
 | 
			
		||||
 
 | 
			
		||||
@@ -103,7 +103,7 @@ static void graphview_cursor_apply(bContext *C, wmOperator *op)
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    SUBFRA = 0.0f;
 | 
			
		||||
    DEG_id_tag_update(&scene->id, ID_RECALC_AUDIO_SEEK);
 | 
			
		||||
    DEG_id_tag_update(&scene->id, ID_RECALC_FRAME_CHANGE);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /* set the cursor value */
 | 
			
		||||
 
 | 
			
		||||
@@ -3605,7 +3605,7 @@ static void change_frame_apply(bContext *C, wmOperator *op)
 | 
			
		||||
  SUBFRA = 0.0f;
 | 
			
		||||
 | 
			
		||||
  /* do updates */
 | 
			
		||||
  DEG_id_tag_update(&scene->id, ID_RECALC_AUDIO_SEEK);
 | 
			
		||||
  DEG_id_tag_update(&scene->id, ID_RECALC_FRAME_CHANGE);
 | 
			
		||||
  WM_event_add_notifier(C, NC_SCENE | ND_FRAME, scene);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -2213,7 +2213,7 @@ static int sequencer_strip_jump_exec(bContext *C, wmOperator *op)
 | 
			
		||||
    return OPERATOR_CANCELLED;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  DEG_id_tag_update(&scene->id, ID_RECALC_AUDIO_SEEK);
 | 
			
		||||
  DEG_id_tag_update(&scene->id, ID_RECALC_FRAME_CHANGE);
 | 
			
		||||
  WM_event_add_notifier(C, NC_SCENE | ND_FRAME, scene);
 | 
			
		||||
 | 
			
		||||
  return OPERATOR_FINISHED;
 | 
			
		||||
 
 | 
			
		||||
@@ -800,7 +800,9 @@ typedef enum IDRecalcFlag {
 | 
			
		||||
   * Use this tag with a scene ID which owns the sequences. */
 | 
			
		||||
  ID_RECALC_SEQUENCER_STRIPS = (1 << 14),
 | 
			
		||||
 | 
			
		||||
  ID_RECALC_AUDIO_SEEK = (1 << 15),
 | 
			
		||||
  /* Runs on frame-change (used for seeking audio too). */
 | 
			
		||||
  ID_RECALC_FRAME_CHANGE = (1 << 15),
 | 
			
		||||
 | 
			
		||||
  ID_RECALC_AUDIO_FPS = (1 << 16),
 | 
			
		||||
  ID_RECALC_AUDIO_VOLUME = (1 << 17),
 | 
			
		||||
  ID_RECALC_AUDIO_MUTE = (1 << 18),
 | 
			
		||||
 
 | 
			
		||||
@@ -1028,7 +1028,7 @@ static void rna_Scene_frame_update(Main *UNUSED(bmain),
 | 
			
		||||
                                   PointerRNA *ptr)
 | 
			
		||||
{
 | 
			
		||||
  Scene *scene = (Scene *)ptr->owner_id;
 | 
			
		||||
  DEG_id_tag_update(&scene->id, ID_RECALC_AUDIO_SEEK);
 | 
			
		||||
  DEG_id_tag_update(&scene->id, ID_RECALC_FRAME_CHANGE);
 | 
			
		||||
  WM_main_add_notifier(NC_SCENE | ND_FRAME, scene);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -3589,7 +3589,7 @@ void wm_event_do_handlers(bContext *C)
 | 
			
		||||
      if (scene_eval != NULL) {
 | 
			
		||||
        const int is_playing_sound = BKE_sound_scene_playing(scene_eval);
 | 
			
		||||
 | 
			
		||||
        if (scene_eval->id.recalc & ID_RECALC_AUDIO_SEEK) {
 | 
			
		||||
        if (scene_eval->id.recalc & ID_RECALC_FRAME_CHANGE) {
 | 
			
		||||
          /* Ignore seek here, the audio will be updated to the scene frame after jump during next
 | 
			
		||||
           * dependency graph update. */
 | 
			
		||||
        }
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user