From 723e129252f82cc81faa8834a68c79e4439ee8fa Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Wed, 2 Nov 2011 20:56:52 +0000 Subject: Depsgraph/Python: callbacks and properties to detect datablock changes * Adds two new python handlers: scene_update_pre() and scene_update_post() These run before and after Blender does a scene update on making modifications to the scene. * Datablocks now have an is_updated property. This will be set to true in the above callbacks if the datablock was tagged to be updated. This works for the most common datablocks used for rendering: object, material, world, lamsp, texture, mesh, curve. * Datablock collections also have an is_updated property. If this is set, it means one datablock of this type was added, removed or modified. It's also useful as a quick check to avoid looping over all datablocks. * RenderEngine.view_update() can also check these properties, for interactive viewport rendering. http://wiki.blender.org/index.php/Dev:2.6/Source/Render/UpdateAPI --- source/blender/blenkernel/BKE_depsgraph.h | 6 ++ source/blender/blenkernel/BKE_scene.h | 2 + source/blender/blenkernel/intern/depsgraph.c | 125 +++++++++++++++++++++++---- source/blender/blenkernel/intern/scene.c | 14 +++ 4 files changed, 132 insertions(+), 15 deletions(-) (limited to 'source/blender/blenkernel') diff --git a/source/blender/blenkernel/BKE_depsgraph.h b/source/blender/blenkernel/BKE_depsgraph.h index 59b7712a5a4..0b0637fb42a 100644 --- a/source/blender/blenkernel/BKE_depsgraph.h +++ b/source/blender/blenkernel/BKE_depsgraph.h @@ -120,6 +120,12 @@ void DAG_ids_flush_update(struct Main *bmain, int time); void DAG_id_tag_update(struct ID *id, short flag); /* flush all tagged updates */ void DAG_ids_flush_tagged(struct Main *bmain); + /* check and clear ID recalc flags */ +void DAG_ids_check_recalc(struct Main *bmain); +void DAG_ids_clear_recalc(struct Main *bmain); + /* test if any of this id type is tagged for update */ +void DAG_id_type_tag(struct Main *bmain, short idtype); +int DAG_id_type_tagged(struct Main *bmain, short idtype); /* (re)-create dependency graph for armature pose */ void DAG_pose_sort(struct Object *ob); diff --git a/source/blender/blenkernel/BKE_scene.h b/source/blender/blenkernel/BKE_scene.h index 45ee6fd4ebd..4806a288cee 100644 --- a/source/blender/blenkernel/BKE_scene.h +++ b/source/blender/blenkernel/BKE_scene.h @@ -88,6 +88,8 @@ int scene_check_setscene(struct Main *bmain, struct Scene *sce); float BKE_curframe(struct Scene *scene); void scene_update_tagged(struct Main *bmain, struct Scene *sce); +void scene_clear_tagged(struct Main *bmain, struct Scene *sce); + void scene_update_for_newframe(struct Main *bmain, struct Scene *sce, unsigned int lay); void scene_add_render_layer(struct Scene *sce); diff --git a/source/blender/blenkernel/intern/depsgraph.c b/source/blender/blenkernel/intern/depsgraph.c index c9df8a135fe..9d51571346f 100644 --- a/source/blender/blenkernel/intern/depsgraph.c +++ b/source/blender/blenkernel/intern/depsgraph.c @@ -1761,9 +1761,22 @@ void DAG_scene_sort(Main *bmain, Scene *sce) sce->recalc |= SCE_PRV_CHANGED; /* test for 3d preview */ } +static void lib_id_recalc_tag(Main *bmain, ID *id) +{ + id->flag |= LIB_ID_RECALC; + bmain->id_tag_update[id->name[0]] = 1; +} + +static void lib_id_recalc_data_tag(Main *bmain, ID *id) +{ + id->flag |= LIB_ID_RECALC_DATA; + bmain->id_tag_update[id->name[0]] = 1; +} + /* node was checked to have lasttime != curtime and is if type ID_OB */ static void flush_update_node(DagNode *node, unsigned int layer, int curtime) { + Main *bmain= G.main; DagAdjList *itA; Object *ob, *obc; int oldflag, changed=0; @@ -1789,20 +1802,24 @@ static void flush_update_node(DagNode *node, unsigned int layer, int curtime) if(itA->type & DAG_RL_OB_OB) { //printf("ob %s changes ob %s\n", ob->id.name, obc->id.name); obc->recalc |= OB_RECALC_OB; + lib_id_recalc_tag(bmain, &obc->id); } if(itA->type & DAG_RL_OB_DATA) { //printf("ob %s changes obdata %s\n", ob->id.name, obc->id.name); obc->recalc |= OB_RECALC_DATA; + lib_id_recalc_data_tag(bmain, &obc->id); } } if(ob->recalc & OB_RECALC_DATA) { if(itA->type & DAG_RL_DATA_OB) { //printf("obdata %s changes ob %s\n", ob->id.name, obc->id.name); obc->recalc |= OB_RECALC_OB; + lib_id_recalc_tag(bmain, &obc->id); } if(itA->type & DAG_RL_DATA_DATA) { //printf("obdata %s changes obdata %s\n", ob->id.name, obc->id.name); obc->recalc |= OB_RECALC_DATA; + lib_id_recalc_data_tag(bmain, &obc->id); } } if(oldflag!=obc->recalc) changed= 1; @@ -1833,6 +1850,7 @@ static void flush_update_node(DagNode *node, unsigned int layer, int curtime) if(itA->type & (DAG_RL_OB_DATA|DAG_RL_DATA_DATA)) { // printf("parent %s changes ob %s\n", ob->id.name, obc->id.name); obc->recalc |= OB_RECALC_DATA; + lib_id_recalc_data_tag(bmain, &obc->id); } } } @@ -1872,6 +1890,7 @@ static unsigned int flush_layer_node(Scene *sce, DagNode *node, int curtime) /* node was checked to have lasttime != curtime , and is of type ID_OB */ static void flush_pointcache_reset(Scene *scene, DagNode *node, int curtime, int reset) { + Main *bmain= G.main; DagAdjList *itA; Object *ob; @@ -1883,8 +1902,10 @@ static void flush_pointcache_reset(Scene *scene, DagNode *node, int curtime, int ob= (Object*)(itA->node->ob); if(reset || (ob->recalc & OB_RECALC_ALL)) { - if(BKE_ptcache_object_reset(scene, ob, PTCACHE_RESET_DEPSGRAPH)) + if(BKE_ptcache_object_reset(scene, ob, PTCACHE_RESET_DEPSGRAPH)) { ob->recalc |= OB_RECALC_DATA; + lib_id_recalc_data_tag(bmain, &ob->id); + } flush_pointcache_reset(scene, itA->node, curtime, 1); } @@ -2001,8 +2022,10 @@ void DAG_scene_flush_update(Main *bmain, Scene *sce, unsigned int lay, const sho ob= (Object*)(itA->node->ob); if(ob->recalc & OB_RECALC_ALL) { - if(BKE_ptcache_object_reset(sce, ob, PTCACHE_RESET_DEPSGRAPH)) + if(BKE_ptcache_object_reset(sce, ob, PTCACHE_RESET_DEPSGRAPH)) { ob->recalc |= OB_RECALC_DATA; + lib_id_recalc_data_tag(bmain, &ob->id); + } flush_pointcache_reset(sce, itA->node, lasttime, 1); } @@ -2204,6 +2227,12 @@ static void dag_object_time_update_flags(Object *ob) } } } + + if(ob->recalc & OB_RECALC_OB) + lib_id_recalc_tag(G.main, &ob->id); + if(ob->recalc & OB_RECALC_DATA) + lib_id_recalc_data_tag(G.main, &ob->id); + } /* flag all objects that need recalc, for changes in time for example */ /* do_time: make this optional because undo resets objects to their animated locations without this */ @@ -2362,6 +2391,9 @@ void DAG_on_visible_update(Main *bmain, const short do_time) DAG_scene_update_flags(bmain, scene, lay, do_time); scene->lay_updated |= lay; } + + /* hack to get objects updating on layer changes */ + DAG_id_type_tag(bmain, ID_OB); } static void dag_id_flush_update__isDependentTexture(void *userData, Object *UNUSED(ob), ID **idpoin) @@ -2408,6 +2440,7 @@ static void dag_id_flush_update(Scene *sce, ID *id) for(obt=bmain->object.first; obt; obt= obt->id.next) { if(!(ob && obt == ob) && obt->data == id) { obt->recalc |= OB_RECALC_DATA; + lib_id_recalc_data_tag(bmain, &obt->id); BKE_ptcache_object_reset(sce, obt, PTCACHE_RESET_DEPSGRAPH); } } @@ -2421,8 +2454,10 @@ static void dag_id_flush_update(Scene *sce, ID *id) data.is_dependent= 0; modifiers_foreachIDLink(obt, dag_id_flush_update__isDependentTexture, &data); - if (data.is_dependent) + if (data.is_dependent) { obt->recalc |= OB_RECALC_DATA; + lib_id_recalc_data_tag(bmain, &obt->id); + } /* particle settings can use the texture as well */ if(obt->particlesystem.first) { @@ -2435,7 +2470,8 @@ static void dag_id_flush_update(Scene *sce, ID *id) mtex = *mtexp; if(mtex && mtex->tex == (Tex*)id) { obt->recalc |= OB_RECALC_DATA; - + lib_id_recalc_data_tag(bmain, &obt->id); + if(mtex->mapto & PAMAP_INIT) psys->recalc |= PSYS_RECALC_RESET; if(mtex->mapto & PAMAP_CHILD) @@ -2455,6 +2491,8 @@ static void dag_id_flush_update(Scene *sce, ID *id) Key *key= ob_get_key(obt); if(!(ob && obt == ob) && ((ID *)key == id)) { obt->flag |= (OB_RECALC_OB|OB_RECALC_DATA); + lib_id_recalc_tag(bmain, &obt->id); + lib_id_recalc_data_tag(bmain, &obt->id); BKE_ptcache_object_reset(sce, obt, PTCACHE_RESET_DEPSGRAPH); } } @@ -2479,7 +2517,7 @@ void DAG_ids_flush_tagged(Main *bmain) ListBase *lbarray[MAX_LIBARRAY]; Scene *sce; unsigned int lay; - int a, have_tag = 0; + int a, do_flush = 0; dag_current_scene_layers(bmain, &sce, &lay); @@ -2497,23 +2535,64 @@ void DAG_ids_flush_tagged(Main *bmain) looping over all ID's in case there are no tags */ if(id && bmain->id_tag_update[id->name[0]]) { for(; id; id=id->next) { - if(id->flag & LIB_ID_RECALC) { + if(id->flag & (LIB_ID_RECALC|LIB_ID_RECALC_DATA)) { dag_id_flush_update(sce, id); - id->flag &= ~LIB_ID_RECALC; + do_flush = 1; } } + } + } + + /* flush changes to other objects */ + if(do_flush) + DAG_scene_flush_update(bmain, sce, lay, 0); +} + +void DAG_ids_check_recalc(Main *bmain) +{ + ListBase *lbarray[MAX_LIBARRAY]; + int a; + + /* loop over all ID types */ + a = set_listbasepointers(bmain, lbarray); + + while(a--) { + ListBase *lb = lbarray[a]; + ID *id = lb->first; - have_tag = 1; + /* we tag based on first ID type character to avoid + looping over all ID's in case there are no tags */ + if(id && bmain->id_tag_update[id->name[0]]) { + /* do editors update */ + dag_editors_update(bmain, NULL); + return; } } +} - if(have_tag) { - /* clear tags */ - memset(bmain->id_tag_update, 0, sizeof(bmain->id_tag_update)); - /* flush changes to other objects */ - DAG_scene_flush_update(bmain, sce, lay, 0); +void DAG_ids_clear_recalc(Main *bmain) +{ + ListBase *lbarray[MAX_LIBARRAY]; + int a; + + /* loop over all ID types */ + a = set_listbasepointers(bmain, lbarray); + + while(a--) { + ListBase *lb = lbarray[a]; + ID *id = lb->first; + + /* we tag based on first ID type character to avoid + looping over all ID's in case there are no tags */ + if(id && bmain->id_tag_update[id->name[0]]) { + for(; id; id=id->next) + if(id->flag & (LIB_ID_RECALC|LIB_ID_RECALC_DATA)) + id->flag &= ~(LIB_ID_RECALC|LIB_ID_RECALC_DATA); + } } + + memset(bmain->id_tag_update, 0, sizeof(bmain->id_tag_update)); } void DAG_id_tag_update(ID *id, short flag) @@ -2523,8 +2602,14 @@ void DAG_id_tag_update(ID *id, short flag) if(id==NULL) return; /* tag ID for update */ - id->flag |= LIB_ID_RECALC; - bmain->id_tag_update[id->name[0]] = 1; + if(flag) { + if(flag & OB_RECALC_OB) + lib_id_recalc_tag(bmain, id); + if(flag & (OB_RECALC_DATA|PSYS_RECALC)) + lib_id_recalc_data_tag(bmain, id); + } + else + lib_id_recalc_tag(bmain, id); /* flag is for objects and particle systems */ if(flag) { @@ -2556,6 +2641,16 @@ void DAG_id_tag_update(ID *id, short flag) } } +void DAG_id_type_tag(struct Main *bmain, short idtype) +{ + bmain->id_tag_update[((char*)&idtype)[0]] = 1; +} + +int DAG_id_type_tagged(Main *bmain, short idtype) +{ + return bmain->id_tag_update[((char*)&idtype)[0]]; +} + #if 0 // UNUSED /* recursively descends tree, each node only checked once */ /* node is checked to be of type object */ diff --git a/source/blender/blenkernel/intern/scene.c b/source/blender/blenkernel/intern/scene.c index c902bee80a8..b25120c0fff 100644 --- a/source/blender/blenkernel/intern/scene.c +++ b/source/blender/blenkernel/intern/scene.c @@ -992,6 +992,8 @@ void scene_update_tagged(Main *bmain, Scene *scene) { DAG_ids_flush_tagged(bmain); + BLI_exec_cb(bmain, &scene->id, BLI_CB_EVT_SCENE_UPDATE_PRE); + scene->physics_settings.quick_cache_step= 0; /* update all objects: drivers, matrices, displists, etc. flags set @@ -1011,10 +1013,19 @@ void scene_update_tagged(Main *bmain, Scene *scene) if (scene->physics_settings.quick_cache_step) BKE_ptcache_quick_cache_all(bmain, scene); + DAG_ids_check_recalc(bmain); + + BLI_exec_cb(bmain, &scene->id, BLI_CB_EVT_SCENE_UPDATE_POST); + /* in the future this should handle updates for all datablocks, not only objects and scenes. - brecht */ } +void scene_clear_tagged(Main *bmain, Scene *UNUSED(scene)) +{ + DAG_ids_clear_recalc(bmain); +} + /* applies changes right away, does all sets too */ void scene_update_for_newframe(Main *bmain, Scene *sce, unsigned int lay) { @@ -1039,6 +1050,8 @@ void scene_update_for_newframe(Main *bmain, Scene *sce, unsigned int lay) * so dont call within 'scene_update_tagged_recursive' */ DAG_scene_update_flags(bmain, sce, lay, TRUE); // only stuff that moves or needs display still + BLI_exec_cb(bmain, (ID *)sce, BLI_CB_EVT_SCENE_UPDATE_PRE); + /* All 'standard' (i.e. without any dependencies) animation is handled here, * with an 'local' to 'macro' order of evaluation. This should ensure that * settings stored nestled within a hierarchy (i.e. settings in a Texture block @@ -1052,6 +1065,7 @@ void scene_update_for_newframe(Main *bmain, Scene *sce, unsigned int lay) scene_update_tagged_recursive(bmain, sce, sce); /* keep this last */ + BLI_exec_cb(bmain, (ID *)sce, BLI_CB_EVT_SCENE_UPDATE_POST); BLI_exec_cb(bmain, (ID *)sce, BLI_CB_EVT_FRAME_CHANGE_POST); } -- cgit v1.2.3