[Bf-blender-cvs] [91835926982] blender2.8: Animation: Make it possible to keyframe to with copy-on-write

Sergey Sharybin noreply at git.blender.org
Thu Apr 26 18:12:02 CEST 2018


Commit: 918359269824a081c5e5819c44bc8461f59ebd37
Author: Sergey Sharybin
Date:   Wed Apr 25 17:59:08 2018 +0200
Branches: blender2.8
https://developer.blender.org/rB918359269824a081c5e5819c44bc8461f59ebd37

Animation: Make it possible to keyframe to with copy-on-write

The issue was that every object tweak was doing a full copy
of original datablock onto evaluated version, and was updating
animation. This made it impossible to tweak properties which
has keyframes.

Proposed solution is to:

- Always apply animation on frame change, and when object
  is explicitly tagged for animation update.

  This will store original DNA value of animated property
  in the f-curve.

- When applying animation in other cases, we check original
  DNA value stored in f-curve with the actual original DNA
  property. If they differ, it means user started to tweak
  animated property, and we should skip animation.

  If the value is the same, we apply animation.

This is just a first step towards proper final implementation,
but seems to be the direction we want to take.

===================================================================

M	source/blender/blenkernel/intern/anim_sys.c
M	source/blender/makesdna/DNA_anim_types.h

===================================================================

diff --git a/source/blender/blenkernel/intern/anim_sys.c b/source/blender/blenkernel/intern/anim_sys.c
index c1822bf086b..b8b585ba278 100644
--- a/source/blender/blenkernel/intern/anim_sys.c
+++ b/source/blender/blenkernel/intern/anim_sys.c
@@ -78,6 +78,8 @@
 
 #include "atomic_ops.h"
 
+#include "DEG_depsgraph_query.h"
+
 /* ***************************************** */
 /* AnimData API */
 
@@ -1701,10 +1703,15 @@ bool BKE_animsys_execute_fcurve(PointerRNA *ptr, AnimMapper *remap, FCurve *fcu,
 /* Evaluate all the F-Curves in the given list 
  * This performs a set of standard checks. If extra checks are required, separate code should be used
  */
-static void animsys_evaluate_fcurves(PointerRNA *ptr, ListBase *list, AnimMapper *remap, float ctime)
+static void animsys_evaluate_fcurves(PointerRNA *ptr, ListBase *list, AnimMapper *remap, float ctime, short recalc)
 {
 	FCurve *fcu;
-	
+
+	/* Pointer is expected to be an ID pointer, if it's not -- we are doomed. */
+	PointerRNA orig_ptr = *ptr;
+	orig_ptr.id.data = ((ID*)orig_ptr.id.data)->orig_id;
+	orig_ptr.data = orig_ptr.id.data;
+
 	/* calculate then execute each curve */
 	for (fcu = list->first; fcu; fcu = fcu->next) {
 		/* check if this F-Curve doesn't belong to a muted group */
@@ -1712,9 +1719,28 @@ static void animsys_evaluate_fcurves(PointerRNA *ptr, ListBase *list, AnimMapper
 			/* check if this curve should be skipped */
 			if ((fcu->flag & (FCURVE_MUTED | FCURVE_DISABLED)) == 0) {
 				PathResolvedRNA anim_rna;
+				/* Read current value from original datablock. */
+				float dna_val;
+				if (animsys_store_rna_setting(&orig_ptr, remap, fcu->rna_path, fcu->array_index, &anim_rna)) {
+					if (!animsys_read_rna_setting(&anim_rna, &dna_val)) {
+						continue;
+					}
+				}
+				else {
+					continue;
+				}
 				if (animsys_store_rna_setting(ptr, remap, fcu->rna_path, fcu->array_index, &anim_rna)) {
+					const bool check_orig_dna = ((recalc & ADT_RECALC_CHECK_ORIG_DNA) != 0);
+					/* If we are tweaking DNA without changing frame, we don't write f-curves,
+					 * since otherwise we will not be able to change properties which has animation.
+					 */
+					if (check_orig_dna && fcu->orig_dna_val != dna_val) {
+						continue;
+					}
 					const float curval = calculate_fcurve(&anim_rna, fcu, ctime);
 					animsys_write_rna_setting(&anim_rna, curval);
+					/* Store original DNA value f-curve was written for. */
+					fcu->orig_dna_val = dna_val;
 				}
 			}
 		}
@@ -1827,7 +1853,7 @@ void animsys_evaluate_action_group(PointerRNA *ptr, bAction *act, bActionGroup *
 }
 
 /* Evaluate Action (F-Curve Bag) */
-void animsys_evaluate_action(PointerRNA *ptr, bAction *act, AnimMapper *remap, float ctime)
+static void animsys_evaluate_action_ex(PointerRNA *ptr, bAction *act, AnimMapper *remap, float ctime, short recalc)
 {
 	/* check if mapper is appropriate for use here (we set to NULL if it's inappropriate) */
 	if (act == NULL) return;
@@ -1836,7 +1862,12 @@ void animsys_evaluate_action(PointerRNA *ptr, bAction *act, AnimMapper *remap, f
 	action_idcode_patch_check(ptr->id.data, act);
 	
 	/* calculate then execute each curve */
-	animsys_evaluate_fcurves(ptr, &act->curves, remap, ctime);
+	animsys_evaluate_fcurves(ptr, &act->curves, remap, ctime, recalc);
+}
+
+void animsys_evaluate_action(PointerRNA *ptr, bAction *act, AnimMapper *remap, float ctime)
+{
+	animsys_evaluate_action_ex(ptr, act, remap, ctime, 0);
 }
 
 /* ***************************************** */
@@ -1875,7 +1906,7 @@ static void nlastrip_evaluate_controls(NlaStrip *strip, float ctime)
 		RNA_pointer_create(NULL, &RNA_NlaStrip, strip, &strip_ptr);
 		
 		/* execute these settings as per normal */
-		animsys_evaluate_fcurves(&strip_ptr, &strip->fcurves, NULL, ctime);
+		animsys_evaluate_fcurves(&strip_ptr, &strip->fcurves, NULL, ctime, 0);
 	}
 	
 	/* analytically generate values for influence and time (if applicable)
@@ -2742,7 +2773,7 @@ void BKE_animsys_evaluate_animdata(Scene *scene, ID *id, AnimData *adt, float ct
 		}
 		/* evaluate Active Action only */
 		else if (adt->action)
-			animsys_evaluate_action(&id_ptr, adt->action, adt->remap, ctime);
+			animsys_evaluate_action_ex(&id_ptr, adt->action, adt->remap, ctime, recalc);
 		
 		/* reset tag */
 		adt->recalc &= ~ADT_RECALC_ANIM;
@@ -2921,7 +2952,15 @@ void BKE_animsys_eval_animdata(Depsgraph *depsgraph, ID *id)
 	                      * which should get handled as part of the dependency graph instead...
 	                      */
 	DEG_debug_print_eval_time(__func__, id->name, id, ctime);
-	BKE_animsys_evaluate_animdata(scene, id, adt, ctime, ADT_RECALC_ANIM);
+	short recalc = ADT_RECALC_ANIM;
+	const Scene *scene_eval = DEG_get_evaluated_scene(depsgraph);
+	/* If animation component is directly tagged for update, we always apply f-curves. */
+	if (((scene_eval->id.recalc & ID_RECALC_TIME) == 0) &&
+	    (id->recalc & ID_RECALC_TIME) == 0)
+	{
+		recalc |= ADT_RECALC_CHECK_ORIG_DNA;
+	}
+	BKE_animsys_evaluate_animdata(scene, id, adt, ctime, recalc);
 }
 
 /* TODO(sergey): This is slow lookup of driver from CoW datablock.
diff --git a/source/blender/makesdna/DNA_anim_types.h b/source/blender/makesdna/DNA_anim_types.h
index cea1a1cf40f..13656c543ce 100644
--- a/source/blender/makesdna/DNA_anim_types.h
+++ b/source/blender/makesdna/DNA_anim_types.h
@@ -488,11 +488,13 @@ typedef struct FCurve {
 	
 		/* value cache + settings */
 	float curval;			/* value stored from last time curve was evaluated (not threadsafe, debug display only!) */
+	/* Value which comes from original DNA ddatablock at a time f-curve was evaluated. */
+	float orig_dna_val;
 	short flag;				/* user-editable settings for this curve */
 	short extend;			/* value-extending mode for this curve (does not cover  */
 	char auto_smoothing;	/* auto-handle smoothing mode */
 	
-	char pad[7];
+	char pad[3];
 
 		/* RNA - data link */
 	int array_index;		/* if applicable, the index of the RNA-array item to get */
@@ -960,6 +962,8 @@ typedef enum eAnimData_Flag {
 typedef enum eAnimData_Recalc {
 	ADT_RECALC_DRIVERS      = (1 << 0),
 	ADT_RECALC_ANIM         = (1 << 1),
+	/* Only apply f-curve value if its original DNA value matches current DNA value. */
+	ADT_RECALC_CHECK_ORIG_DNA = (1 << 2),
 	ADT_RECALC_ALL          = (ADT_RECALC_DRIVERS | ADT_RECALC_ANIM)
 } eAnimData_Recalc;



More information about the Bf-blender-cvs mailing list