== RNA Property Updates get called by Animation System now ==
authorJoshua Leung <aligorith@gmail.com>
Sun, 24 Jul 2011 04:34:46 +0000 (04:34 +0000)
committerJoshua Leung <aligorith@gmail.com>
Sun, 24 Jul 2011 04:34:46 +0000 (04:34 +0000)
This fixes bug #26764 and several others like it, where modifier
properties (and others, but most visibly modifiers) would not do
anything when animated or driven, as modifier properties require the
RNA update calls to tag the modifiers to get recalculated.

While just adding a call to RNA_property_update() could have gotten
this working (as per the Campbell's patch attached in the report, and
also my own attempt #25881). However, on production rigs, the
performance cost of this is untenatable (on my own tests, without
these updates, I was getting ~5fps on such a rig, but only 0.9fps or
possibly even worse with the updates added).

Hence, this commit adds a property-update caching system to the RNA
level, which aims to reduce to the number of times that the update
functions end up needing to get called.

While this is much faster than without the caching, I also added an
optimisation for pose bones (which are numerous in production rigs) so
that their property updates are skipped, since they are useless to the
animsys (they only tag the depsgraph for updating). This gets things
moving at a more acceptable framerate.

15 files changed:
source/blender/blenkernel/BKE_animsys.h
source/blender/blenkernel/intern/action.c
source/blender/blenkernel/intern/anim.c
source/blender/blenkernel/intern/anim_sys.c
source/blender/blenkernel/intern/blender.c
source/blender/blenkernel/intern/key.c
source/blender/blenkernel/intern/object.c
source/blender/blenkernel/intern/particle_system.c
source/blender/blenkernel/intern/scene.c
source/blender/blenkernel/intern/sequencer.c
source/blender/editors/space_view3d/drawanimviz.c
source/blender/editors/space_view3d/drawarmature.c
source/blender/makesrna/RNA_access.h
source/blender/makesrna/intern/rna_access.c
source/blender/render/intern/source/pipeline.c

index 228a359c81de056d8bd8faea131ccb35fa660812..bf619d76e6897517716cf01af98fb7fffa5305f2 100644 (file)
@@ -140,10 +140,10 @@ void BKE_animdata_main_cb(struct Main *main, ID_AnimData_Edit_Callback func, voi
 /* In general, these ones should be called to do all animation evaluation */
 
 /* Evaluation loop for evaluating animation data  */
-void BKE_animsys_evaluate_animdata(struct ID *id, struct AnimData *adt, float ctime, short recalc);
+void BKE_animsys_evaluate_animdata(struct Scene *scene, struct ID *id, struct AnimData *adt, float ctime, short recalc);
 
 /* Evaluation of all ID-blocks with Animation Data blocks - Animation Data Only */
-void BKE_animsys_evaluate_all_animation(struct Main *main, float ctime);
+void BKE_animsys_evaluate_all_animation(struct Main *main, struct Scene *scene, float ctime);
 
 
 /* ------------ Specialised API --------------- */
index e69ff5df913a3d54040552bbd8739d31191d3a39..a6539f0060538d388338688c03b217156113728b 100644 (file)
@@ -1197,7 +1197,7 @@ void what_does_obaction (Object *ob, Object *workob, bPose *pose, bAction *act,
                adt.action= act;
                
                /* execute effects of Action on to workob (or it's PoseChannels) */
-               BKE_animsys_evaluate_animdata(&workob->id, &adt, cframe, ADT_RECALC_ANIM);
+               BKE_animsys_evaluate_animdata(NULL, &workob->id, &adt, cframe, ADT_RECALC_ANIM);
        }
 }
 
index 3300c82cae2d0c5632eabfcf315d414b9bb772ef..7ddb078ef8ec12be1dadc21b783247789ae09ce1 100644 (file)
@@ -796,7 +796,7 @@ static void frames_duplilist(ListBase *lb, Scene *scene, Object *ob, int level,
                         * and/or other objects which may affect this object's transforms are not updated either.
                         * However, this has always been the way that this worked (i.e. pre 2.5), so I guess that it'll be fine!
                         */
-                       BKE_animsys_evaluate_animdata(&ob->id, ob->adt, (float)scene->r.cfra, ADT_RECALC_ANIM); /* ob-eval will do drivers, so we don't need to do them */
+                       BKE_animsys_evaluate_animdata(scene, &ob->id, ob->adt, (float)scene->r.cfra, ADT_RECALC_ANIM); /* ob-eval will do drivers, so we don't need to do them */
                        where_is_object_time(scene, ob, (float)scene->r.cfra);
                        
                        dob= new_dupli_object(lb, ob, ob->obmat, ob->lay, scene->r.cfra, OB_DUPLIFRAMES, animated);
@@ -811,7 +811,7 @@ static void frames_duplilist(ListBase *lb, Scene *scene, Object *ob, int level,
         */
        scene->r.cfra= cfrao;
        
-       BKE_animsys_evaluate_animdata(&ob->id, ob->adt, (float)scene->r.cfra, ADT_RECALC_ANIM); /* ob-eval will do drivers, so we don't need to do them */
+       BKE_animsys_evaluate_animdata(scene, &ob->id, ob->adt, (float)scene->r.cfra, ADT_RECALC_ANIM); /* ob-eval will do drivers, so we don't need to do them */
        where_is_object_time(scene, ob, (float)scene->r.cfra);
        
        /* but, to make sure unkeyed object transforms are still sane, 
index 69458ec7401d16fe3f4d146b8f122c9ef5c5ad30..3e59accc599d70a7131555e4f4bc1a31280a82a7 100644 (file)
@@ -1116,7 +1116,7 @@ static short animsys_write_rna_setting (PointerRNA *ptr, char *path, int array_i
                {
                        int array_len= RNA_property_array_length(&new_ptr, prop);
                        
-                       if(array_len && array_index >= array_len)
+                       if (array_len && array_index >= array_len)
                        {
                                if (G.f & G_DEBUG) {
                                        printf("Animato: Invalid array index. ID = '%s',  '%s[%d]', array length is %d \n",
@@ -1154,6 +1154,23 @@ static short animsys_write_rna_setting (PointerRNA *ptr, char *path, int array_i
                                        /* nothing can be done here... so it is unsuccessful? */
                                        return 0;
                        }
+                       
+                       /* buffer property update for later flushing */
+                       if (RNA_property_update_check(prop)) {
+                               short skip_updates_hack = 0;
+                               
+                               /* optimisation hacks: skip property updates for those properties
+                                * for we know that which the updates in RNA were really just for
+                                * flushing property editing via UI/Py
+                                */
+                               if (RNA_struct_is_a(new_ptr.type, &RNA_PoseBone)) {
+                                       /* bone transforms - update pose (i.e. tag depsgraph) */
+                                       skip_updates_hack = 1;
+                               }                               
+                               
+                               if (skip_updates_hack == 0)
+                                       RNA_property_update_cache_add(&new_ptr, prop);
+                       }
                }
                
                /* successful */
@@ -2132,8 +2149,9 @@ static void animsys_evaluate_overrides (PointerRNA *ptr, AnimData *adt)
  * and that the flags for which parts of the anim-data settings need to be recalculated 
  * have been set already by the depsgraph. Now, we use the recalc 
  */
-void BKE_animsys_evaluate_animdata (ID *id, AnimData *adt, float ctime, short recalc)
+void BKE_animsys_evaluate_animdata (Scene *scene, ID *id, AnimData *adt, float ctime, short recalc)
 {
+       Main *bmain = G.main; // xxx - to get passed in!
        PointerRNA id_ptr;
        
        /* sanity checks */
@@ -2184,6 +2202,10 @@ void BKE_animsys_evaluate_animdata (ID *id, AnimData *adt, float ctime, short re
         */
        animsys_evaluate_overrides(&id_ptr, adt);
        
+       /* execute and clear all cached property update functions */
+       RNA_property_update_cache_flush(bmain, scene);
+       RNA_property_update_cache_free();
+       
        /* clear recalc flag now */
        adt->recalc= 0;
 }
@@ -2195,7 +2217,7 @@ void BKE_animsys_evaluate_animdata (ID *id, AnimData *adt, float ctime, short re
  * 'local' (i.e. belonging in the nearest ID-block that setting is related to, not a
  * standard 'root') block are overridden by a larger 'user'
  */
-void BKE_animsys_evaluate_all_animation (Main *main, float ctime)
+void BKE_animsys_evaluate_all_animation (Main *main, Scene *scene, float ctime)
 {
        ID *id;
 
@@ -2211,7 +2233,7 @@ void BKE_animsys_evaluate_all_animation (Main *main, float ctime)
        for (id= first; id; id= id->next) { \
                if (ID_REAL_USERS(id) > 0) { \
                        AnimData *adt= BKE_animdata_from_id(id); \
-                       BKE_animsys_evaluate_animdata(id, adt, ctime, aflag); \
+                       BKE_animsys_evaluate_animdata(scene, id, adt, ctime, aflag); \
                } \
        }
        /* another macro for the "embedded" nodetree cases 
@@ -2227,9 +2249,9 @@ void BKE_animsys_evaluate_all_animation (Main *main, float ctime)
                        NtId_Type *ntp= (NtId_Type *)id; \
                        if (ntp->nodetree) { \
                                AnimData *adt2= BKE_animdata_from_id((ID *)ntp->nodetree); \
-                               BKE_animsys_evaluate_animdata((ID *)ntp->nodetree, adt2, ctime, ADT_RECALC_ANIM); \
+                               BKE_animsys_evaluate_animdata(scene, (ID *)ntp->nodetree, adt2, ctime, ADT_RECALC_ANIM); \
                        } \
-                       BKE_animsys_evaluate_animdata(id, adt, ctime, aflag); \
+                       BKE_animsys_evaluate_animdata(scene, id, adt, ctime, aflag); \
                } \
        }
        
index 8b4bbbd3c834ddb203978eefb3208fb747980e6d..d573da603f66ddf7fbaf48a72f45b3c1b0834e9e 100644 (file)
@@ -90,6 +90,8 @@
 
 #include "BKE_utildefines.h"
 
+#include "RNA_access.h"
+
 #include "WM_api.h" // XXXXX BAD, very BAD dependency (bad level call) - remove asap, elubie
 
 Global G;
@@ -239,6 +241,9 @@ static void setup_app_data(bContext *C, BlendFileData *bfd, const char *filepath
 //     CTX_wm_manager_set(C, NULL);
        clear_global(); 
        
+       /* clear old property update cache, in case some old references are left dangling */
+       RNA_property_update_cache_free();
+       
        G.main= bfd->main;
 
        CTX_data_main_set(C, G.main);
index 8b0cfb1d1563eeb9dad13082dd626f11f97b4f16..50c120a3ec153290a9a21bb16e07c414ba0f4cdc 100644 (file)
@@ -1400,7 +1400,7 @@ float *do_ob_key(Scene *scene, Object *ob)
                /* do shapekey local drivers */
                float ctime= (float)scene->r.cfra; // XXX this needs to be checked
                
-               BKE_animsys_evaluate_animdata(&key->id, key->adt, ctime, ADT_RECALC_DRIVERS);
+               BKE_animsys_evaluate_animdata(scene, &key->id, key->adt, ctime, ADT_RECALC_DRIVERS);
                
                if(ob->type==OB_MESH) do_mesh_key(scene, ob, key, out, tot);
                else if(ob->type==OB_LATTICE) do_latt_key(scene, ob, key, out, tot);
index dff62b05bd35fc0a6763f17448dea71772456f19..862d583bd3412541032f96ae2ddc6d79a922bbfb 100644 (file)
@@ -2084,7 +2084,7 @@ void where_is_object_time(Scene *scene, Object *ob, float ctime)
        if(ob==NULL) return;
        
        /* execute drivers only, as animation has already been done */
-       BKE_animsys_evaluate_animdata(&ob->id, ob->adt, ctime, ADT_RECALC_DRIVERS);
+       BKE_animsys_evaluate_animdata(scene, &ob->id, ob->adt, ctime, ADT_RECALC_DRIVERS);
        
        if(ob->parent) {
                Object *par= ob->parent;
@@ -2623,7 +2623,7 @@ void object_handle_update(Scene *scene, Object *ob)
                        if(adt) {
                                /* evaluate drivers */
                                // XXX: for mesh types, should we push this to derivedmesh instead?
-                               BKE_animsys_evaluate_animdata(data_id, adt, ctime, ADT_RECALC_DRIVERS);
+                               BKE_animsys_evaluate_animdata(scene, data_id, adt, ctime, ADT_RECALC_DRIVERS);
                        }
 
                        /* includes all keys and modifiers */
index 1423f520b9534c1bc23109825250675814db1b31..f62ba2be19343872fc1460fa85b9a67370afb287 100644 (file)
@@ -1801,7 +1801,7 @@ void reset_particle(ParticleSimulationData *sim, ParticleData *pa, float dtime,
        if(part->type!=PART_HAIR && dtime > 0.f && pa->time < cfra && pa->time >= sim->psys->cfra) {
                /* we have to force RECALC_ANIM here since where_is_objec_time only does drivers */
                while(ob) {
-                       BKE_animsys_evaluate_animdata(&ob->id, ob->adt, pa->time, ADT_RECALC_ANIM);
+                       BKE_animsys_evaluate_animdata(sim->scene, &ob->id, ob->adt, pa->time, ADT_RECALC_ANIM);
                        ob = ob->parent;
                }
                ob = sim->ob;
@@ -4253,7 +4253,7 @@ void particle_system_update(Scene *scene, Object *ob, ParticleSystem *psys)
                return;
 
        /* execute drivers only, as animation has already been done */
-       BKE_animsys_evaluate_animdata(&part->id, part->adt, cfra, ADT_RECALC_DRIVERS);
+       BKE_animsys_evaluate_animdata(scene, &part->id, part->adt, cfra, ADT_RECALC_DRIVERS);
 
        if(psys->recalc & PSYS_RECALC_TYPE)
                psys_changed_type(&sim);
@@ -4291,7 +4291,7 @@ void particle_system_update(Scene *scene, Object *ob, ParticleSystem *psys)
                                for(i=0; i<=part->hair_step; i++){
                                        hcfra=100.0f*(float)i/(float)psys->part->hair_step;
                                        if((part->flag & PART_HAIR_REGROW)==0)
-                                               BKE_animsys_evaluate_animdata(&part->id, part->adt, hcfra, ADT_RECALC_ANIM);
+                                               BKE_animsys_evaluate_animdata(scene, &part->id, part->adt, hcfra, ADT_RECALC_ANIM);
                                        system_step(&sim, hcfra);
                                        psys->cfra = hcfra;
                                        psys->recalc = 0;
@@ -4369,7 +4369,7 @@ void particle_system_update(Scene *scene, Object *ob, ParticleSystem *psys)
        if(psys->cfra < cfra) {
                /* make sure emitter is left at correct time (particle emission can change this) */
                while(ob) {
-                       BKE_animsys_evaluate_animdata(&ob->id, ob->adt, cfra, ADT_RECALC_ANIM);
+                       BKE_animsys_evaluate_animdata(scene, &ob->id, ob->adt, cfra, ADT_RECALC_ANIM);
                        ob = ob->parent;
                }
                ob = sim.ob;
index e045bd0fb82cd84a431da39e44a34f9622f07ad7..42793e4b4a4ace51db7b144fdbc4935fceb26991 100644 (file)
@@ -915,7 +915,7 @@ static void scene_update_drivers(Main *UNUSED(bmain), Scene *scene)
        
        /* scene itself */
        if (scene->adt && scene->adt->drivers.first) {
-               BKE_animsys_evaluate_animdata(&scene->id, scene->adt, ctime, ADT_RECALC_DRIVERS);
+               BKE_animsys_evaluate_animdata(scene, &scene->id, scene->adt, ctime, ADT_RECALC_DRIVERS);
        }
        
        /* world */
@@ -925,7 +925,7 @@ static void scene_update_drivers(Main *UNUSED(bmain), Scene *scene)
                AnimData *adt= BKE_animdata_from_id(wid);
                
                if (adt && adt->drivers.first)
-                       BKE_animsys_evaluate_animdata(wid, adt, ctime, ADT_RECALC_DRIVERS);
+                       BKE_animsys_evaluate_animdata(scene, wid, adt, ctime, ADT_RECALC_DRIVERS);
        }
        
        /* nodes */
@@ -934,7 +934,7 @@ static void scene_update_drivers(Main *UNUSED(bmain), Scene *scene)
                AnimData *adt= BKE_animdata_from_id(nid);
                
                if (adt && adt->drivers.first)
-                       BKE_animsys_evaluate_animdata(nid, adt, ctime, ADT_RECALC_DRIVERS);
+                       BKE_animsys_evaluate_animdata(scene, nid, adt, ctime, ADT_RECALC_DRIVERS);
        }
 }
 
@@ -985,7 +985,7 @@ void scene_update_tagged(Main *bmain, Scene *scene)
                float ctime = BKE_curframe(scene);
                
                if (adt && (adt->recalc & ADT_RECALC_ANIM))
-                       BKE_animsys_evaluate_animdata(&scene->id, adt, ctime, 0);
+                       BKE_animsys_evaluate_animdata(scene, &scene->id, adt, ctime, 0);
        }
        
        if (scene->physics_settings.quick_cache_step)
@@ -1020,7 +1020,7 @@ void scene_update_for_newframe(Main *bmain, Scene *sce, unsigned int lay)
         * can be overridden by settings from Scene, which owns the Texture through a hierarchy
         * such as Scene->World->MTex/Texture) can still get correctly overridden.
         */
-       BKE_animsys_evaluate_all_animation(bmain, ctime);
+       BKE_animsys_evaluate_all_animation(bmain, sce, ctime);
        /*...done with recusrive funcs */
 
        /* object_handle_update() on all objects, groups and sets */
index 5da70f9731412b632cdda8796483eaa48ccfc3e2..9673fee0b63e372ad088142424b8606401d2e394 100644 (file)
@@ -2123,7 +2123,7 @@ static ImBuf * seq_render_strip(SeqRenderData context, Sequence * seq, float cfr
                        ibuf = seq_render_scene_strip_impl(context, seq, nr);
 
                        /* Scene strips update all animation, so we need to restore original state.*/
-                       BKE_animsys_evaluate_all_animation(context.bmain, cfra);
+                       BKE_animsys_evaluate_all_animation(context.bmain, context.scene, cfra);
 
                        copy_to_ibuf_still(context, seq, nr, ibuf);
                        break;
@@ -2200,7 +2200,7 @@ static ImBuf* seq_render_strip_stack(
        if(scene->r.cfra != cfra) {
                // XXX for prefetch and overlay offset!..., very bad!!!
                AnimData *adt= BKE_animdata_from_id(&scene->id);
-               BKE_animsys_evaluate_animdata(&scene->id, adt, cfra, ADT_RECALC_ANIM);
+               BKE_animsys_evaluate_animdata(scene, &scene->id, adt, cfra, ADT_RECALC_ANIM);
        }
 #endif
 
index aa3ba1a306214ce657a3cc07b6fbb7d9d4c6ff6b..4a51cb3be094815afb35ba7dadcde84802e1dbda 100644 (file)
@@ -393,7 +393,7 @@ static void draw_ghost_poses_range(Scene *scene, View3D *v3d, ARegion *ar, Base
                colfac = (end - (float)CFRA) / range;
                UI_ThemeColorShadeAlpha(TH_WIRE, 0, -128-(int)(120.0*sqrt(colfac)));
                
-               BKE_animsys_evaluate_animdata(&ob->id, adt, (float)CFRA, ADT_RECALC_ALL);
+               BKE_animsys_evaluate_animdata(scene, &ob->id, adt, (float)CFRA, ADT_RECALC_ALL);
                where_is_pose(scene, ob);
                draw_pose_bones(scene, v3d, ar, base, OB_WIRE);
        }
@@ -472,7 +472,7 @@ static void draw_ghost_poses_keys(Scene *scene, View3D *v3d, ARegion *ar, Base *
                
                CFRA= (int)ak->cfra;
                
-               BKE_animsys_evaluate_animdata(&ob->id, adt, (float)CFRA, ADT_RECALC_ALL);
+               BKE_animsys_evaluate_animdata(scene, &ob->id, adt, (float)CFRA, ADT_RECALC_ALL);
                where_is_pose(scene, ob);
                draw_pose_bones(scene, v3d, ar, base, OB_WIRE);
        }
@@ -542,7 +542,7 @@ static void draw_ghost_poses(Scene *scene, View3D *v3d, ARegion *ar, Base *base)
                        CFRA= (int)BKE_nla_tweakedit_remap(adt, actframe+ctime, NLATIME_CONVERT_MAP);
                        
                        if (CFRA != cfrao) {
-                               BKE_animsys_evaluate_animdata(&ob->id, adt, (float)CFRA, ADT_RECALC_ALL);
+                               BKE_animsys_evaluate_animdata(scene, &ob->id, adt, (float)CFRA, ADT_RECALC_ALL);
                                where_is_pose(scene, ob);
                                draw_pose_bones(scene, v3d, ar, base, OB_WIRE);
                        }
@@ -557,7 +557,7 @@ static void draw_ghost_poses(Scene *scene, View3D *v3d, ARegion *ar, Base *base)
                        CFRA= (int)BKE_nla_tweakedit_remap(adt, actframe-ctime, NLATIME_CONVERT_MAP);
                        
                        if (CFRA != cfrao) {
-                               BKE_animsys_evaluate_animdata(&ob->id, adt, (float)CFRA, ADT_RECALC_ALL);
+                               BKE_animsys_evaluate_animdata(scene, &ob->id, adt, (float)CFRA, ADT_RECALC_ALL);
                                where_is_pose(scene, ob);
                                draw_pose_bones(scene, v3d, ar, base, OB_WIRE);
                        }
index 1087284e2e55377ff46178b3d7cb1ea8d51c6f75..de35be13c43cf8a4d46e0fb95eecca7ef2201435 100644 (file)
@@ -2339,7 +2339,7 @@ static void draw_ghost_poses_range(Scene *scene, View3D *v3d, ARegion *ar, Base
                colfac = (end - (float)CFRA) / range;
                UI_ThemeColorShadeAlpha(TH_WIRE, 0, -128-(int)(120.0*sqrt(colfac)));
                
-               BKE_animsys_evaluate_animdata(&ob->id, adt, (float)CFRA, ADT_RECALC_ALL);
+               BKE_animsys_evaluate_animdata(scene, &ob->id, adt, (float)CFRA, ADT_RECALC_ALL);
                where_is_pose(scene, ob);
                draw_pose_bones(scene, v3d, ar, base, OB_WIRE, TRUE, FALSE);
        }
@@ -2418,7 +2418,7 @@ static void draw_ghost_poses_keys(Scene *scene, View3D *v3d, ARegion *ar, Base *
                
                CFRA= (int)ak->cfra;
                
-               BKE_animsys_evaluate_animdata(&ob->id, adt, (float)CFRA, ADT_RECALC_ALL);
+               BKE_animsys_evaluate_animdata(scene, &ob->id, adt, (float)CFRA, ADT_RECALC_ALL);
                where_is_pose(scene, ob);
                draw_pose_bones(scene, v3d, ar, base, OB_WIRE, TRUE, FALSE);
        }
@@ -2488,7 +2488,7 @@ static void draw_ghost_poses(Scene *scene, View3D *v3d, ARegion *ar, Base *base)
                        CFRA= (int)BKE_nla_tweakedit_remap(adt, actframe+ctime, NLATIME_CONVERT_MAP);
                        
                        if (CFRA != cfrao) {
-                               BKE_animsys_evaluate_animdata(&ob->id, adt, (float)CFRA, ADT_RECALC_ALL);
+                               BKE_animsys_evaluate_animdata(scene, &ob->id, adt, (float)CFRA, ADT_RECALC_ALL);
                                where_is_pose(scene, ob);
                                draw_pose_bones(scene, v3d, ar, base, OB_WIRE, TRUE, FALSE);
                        }
@@ -2503,7 +2503,7 @@ static void draw_ghost_poses(Scene *scene, View3D *v3d, ARegion *ar, Base *base)
                        CFRA= (int)BKE_nla_tweakedit_remap(adt, actframe-ctime, NLATIME_CONVERT_MAP);
                        
                        if (CFRA != cfrao) {
-                               BKE_animsys_evaluate_animdata(&ob->id, adt, (float)CFRA, ADT_RECALC_ALL);
+                               BKE_animsys_evaluate_animdata(scene, &ob->id, adt, (float)CFRA, ADT_RECALC_ALL);
                                where_is_pose(scene, ob);
                                draw_pose_bones(scene, v3d, ar, base, OB_WIRE, TRUE, FALSE);
                        }
index 49bc10a067585337d980ad2180afea663c4a270e..f5d73bddc3b8d01159643e48639df63024db99fc 100644 (file)
@@ -702,6 +702,10 @@ void RNA_property_update(struct bContext *C, PointerRNA *ptr, PropertyRNA *prop)
 void RNA_property_update_main(struct Main *bmain, struct Scene *scene, PointerRNA *ptr, PropertyRNA *prop);
 int RNA_property_update_check(struct PropertyRNA *prop);
 
+void RNA_property_update_cache_add(PointerRNA *ptr, PropertyRNA *prop);
+void RNA_property_update_cache_flush(struct Main *bmain, struct Scene *scene);
+void RNA_property_update_cache_free(void);
+
 /* Property Data */
 
 int RNA_property_boolean_get(PointerRNA *ptr, PropertyRNA *prop);
index 285e8ca39bafccf5ba0ffc5384842f1e79ad95e8..7936fc4c280d8d45763cb8f51f1886a478f6ba9b 100644 (file)
@@ -85,7 +85,9 @@ void RNA_init(void)
 void RNA_exit(void)
 {
        StructRNA *srna;
-
+       
+       RNA_property_update_cache_free();
+       
        for(srna=BLENDER_RNA.structs.first; srna; srna=srna->cont.next) {
                if(srna->cont.prophash) {
                        BLI_ghash_free(srna->cont.prophash, NULL, NULL);
@@ -1391,6 +1393,112 @@ void RNA_property_update_main(Main *bmain, Scene *scene, PointerRNA *ptr, Proper
        rna_property_update(NULL, bmain, scene, ptr, prop);
 }
 
+
+/* RNA Updates Cache ------------------------ */
+/* Overview of RNA Update cache system:
+ *
+ * RNA Update calls need to be cached in order to maintain reasonable performance
+ * of the animation system (i.e. maintaining a somewhat interactive framerate)
+ * while still allowing updates to be called (necessary in particular for modifier
+ * property updates to actually work).
+ *
+ * The cache is structured with a dual-layer structure
+ * - L1 = PointerRNA used as key; id.data is used (it should always be defined,
+ *              and most updates end up using just that anyways)
+ * - L2 = Update functions to be called on those PointerRNA's
+ */
+
+/* cache element */
+typedef struct tRnaUpdateCacheElem {
+       struct tRnaUpdateCacheElem *next, *prev;
+       
+       PointerRNA ptr;         /* L1 key - id as primary, data secondary/ignored? */
+       ListBase L2Funcs;       /* L2 functions (LinkData<RnaUpdateFuncRef>) */
+} tRnaUpdateCacheElem;
+
+/* cache global (tRnaUpdateCacheElem's) - only accessible using these API calls */
+static ListBase rna_updates_cache = {NULL, NULL};
+
+/* ........................... */
+
+void RNA_property_update_cache_add(PointerRNA *ptr, PropertyRNA *prop)
+{
+       tRnaUpdateCacheElem *uce = NULL;
+       UpdateFunc fn = NULL;
+       LinkData *ld;
+       short is_rna = (prop->magic == RNA_MAGIC);
+       
+       /* sanity check */
+       if (ELEM(NULL, ptr, prop))
+               return;
+               
+       prop= rna_ensure_property(prop);
+       
+       /* we can only handle update calls with no context args for now (makes animsys updates easier) */
+       if ((is_rna == 0) || (prop->update == NULL) || (prop->flag & PROP_CONTEXT_UPDATE))
+               return;
+       fn = prop->update;
+               
+       /* find cache element for which key matches... */
+       for (uce = rna_updates_cache.first; uce; uce = uce->next) {
+               /* just match by id only for now, since most update calls that we'll encounter only really care about this */
+               // TODO: later, the cache might need to have some nesting on L1 to cope better with these problems + some tagging to indicate we need this
+               if (uce->ptr.id.data == ptr->id.data)
+                       break;
+       }
+       if (uce == NULL) {
+               /* create new instance */
+               uce = MEM_callocN(sizeof(tRnaUpdateCacheElem), "tRnaUpdateCacheElem");
+               BLI_addtail(&rna_updates_cache, uce);
+               
+               /* copy pointer */
+               RNA_pointer_create(ptr->id.data, ptr->type, ptr->data, &uce->ptr);
+       }
+       
+       /* check on the update func */
+       for (ld = uce->L2Funcs.first; ld; ld = ld->next) {
+               /* stop on match - function already cached */
+               if (fn == ld->data)
+                       return;
+       }
+       /* else... if still here, we need to add it */
+       BLI_addtail(&uce->L2Funcs, BLI_genericNodeN(fn));
+}
+
+void RNA_property_update_cache_flush(Main *bmain, Scene *scene)
+{
+       tRnaUpdateCacheElem *uce;
+       
+       // TODO: should we check that bmain and scene are valid? The above stuff doesn't!
+       
+       /* execute the cached updates */
+       for (uce = rna_updates_cache.first; uce; uce = uce->next) {
+               LinkData *ld;
+               
+               for (ld = uce->L2Funcs.first; ld; ld = ld->next) {
+                       UpdateFunc fn = (UpdateFunc)ld->data;
+                       fn(bmain, scene, &uce->ptr);
+               }
+       }
+}
+
+void RNA_property_update_cache_free(void)
+{
+       tRnaUpdateCacheElem *uce, *ucn;
+       
+       for (uce = rna_updates_cache.first; uce; uce = ucn) {
+               ucn = uce->next;
+               
+               /* free L2 cache */
+               BLI_freelistN(&uce->L2Funcs);
+               
+               /* remove self */
+               BLI_freelinkN(&rna_updates_cache, uce);
+       }
+}
+
+/* ---------------------------------------------------------------------- */
+
 /* Property Data */
 
 int RNA_property_boolean_get(PointerRNA *ptr, PropertyRNA *prop)
index b9006b390ab24433012601de0f93e869a0bb9bd1..0afbffc5fd5650f79678b8776e1bfd8fee1e172f 100644 (file)
@@ -2525,7 +2525,7 @@ static void do_render_seq(Render * re)
 
        if(recurs_depth==0) {
                /* otherwise sequencer animation isnt updated */
-               BKE_animsys_evaluate_all_animation(re->main, (float)cfra); // XXX, was BKE_curframe(re->scene)
+               BKE_animsys_evaluate_all_animation(re->main, re->scene, (float)cfra); // XXX, was BKE_curframe(re->scene)
        }
 
        recurs_depth++;