diff options
author | Bastien Montagne <montagne29@wanadoo.fr> | 2016-03-24 14:28:41 +0300 |
---|---|---|
committer | Bastien Montagne <montagne29@wanadoo.fr> | 2016-03-24 18:10:39 +0300 |
commit | c08924bf94f2dffaae7b3ef2fad3c49cb8043c89 (patch) | |
tree | ee01dfd8f137667c39be7e3ed894236a64464751 /source/blender/blenkernel | |
parent | 60cf62ff4b08e310208dca9e35bd75131833e1aa (diff) |
Rework library_query foreach looper - add optional recursivity.
This commit:
* Fixes bad handling of 'stop iteration' (by adding a status flag, so that we can actually
stop in helper functions too, and jumping to a finalize label instead of raw return, to
allow propper clean up).
* Adds optional recursion into 'ID tree' - callback can also decide to exclude current id_pp
from recursion. Note that this implies 'readonly', modifying IDs while recursing is not
something we want to support!
* Changes callback signature/expected behavior: return behavior is now handled through flags,
and 'parent' ID of id_pp is also passed (since it may not always be root id anymore).
Reviewers: sergey, campbellbarton
Differential Revision: https://developer.blender.org/D1869
Diffstat (limited to 'source/blender/blenkernel')
-rw-r--r-- | source/blender/blenkernel/BKE_library_query.h | 14 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/library.c | 4 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/library_query.c | 834 |
3 files changed, 461 insertions, 391 deletions
diff --git a/source/blender/blenkernel/BKE_library_query.h b/source/blender/blenkernel/BKE_library_query.h index f07644dc833..86628ea8b6f 100644 --- a/source/blender/blenkernel/BKE_library_query.h +++ b/source/blender/blenkernel/BKE_library_query.h @@ -50,15 +50,23 @@ enum { IDWALK_USER_ONE = (1 << 9), }; -/* Call a callback for each ID link which the given ID uses. +enum { + IDWALK_RET_NOP = 0, + IDWALK_RET_STOP_ITER = 1 << 0, /* Completly top iteration. */ + IDWALK_RET_STOP_RECURSION = 1 << 1, /* Stop recursion, that is, do not loop over ID used by current one. */ +}; + +/** + * Call a callback for each ID link which the given ID uses. * - * Return 'false' if you want to stop iteration. + * \return a set of flags to controll further iteration (0 to keep going). */ -typedef bool (*LibraryIDLinkCallback) (void *user_data, struct ID **id_pointer, int cd_flag); +typedef int (*LibraryIDLinkCallback) (void *user_data, struct ID *id_self, struct ID **id_pointer, int cd_flag); /* Flags for the foreach function itself. */ enum { IDWALK_READONLY = (1 << 0), + IDWALK_RECURSE = (1 << 1), /* Also implies IDWALK_READONLY. */ }; /* Loop over all of the ID's this datablock links to. */ diff --git a/source/blender/blenkernel/intern/library.c b/source/blender/blenkernel/intern/library.c index 72801d6f6d5..895d215ca91 100644 --- a/source/blender/blenkernel/intern/library.c +++ b/source/blender/blenkernel/intern/library.c @@ -1086,7 +1086,7 @@ void *BKE_libblock_copy(ID *id) return BKE_libblock_copy_ex(G.main, id); } -static bool id_relink_looper(void *UNUSED(user_data), ID **id_pointer, const int cd_flag) +static int id_relink_looper(void *UNUSED(user_data), ID *UNUSED(self_id), ID **id_pointer, const int cd_flag) { ID *id = *id_pointer; if (id) { @@ -1100,7 +1100,7 @@ static bool id_relink_looper(void *UNUSED(user_data), ID **id_pointer, const int BKE_libblock_relink(id); } } - return true; + return IDWALK_RET_NOP; } void BKE_libblock_relink(ID *id) diff --git a/source/blender/blenkernel/intern/library_query.c b/source/blender/blenkernel/intern/library_query.c index f5e17c07f54..73b1294ef4a 100644 --- a/source/blender/blenkernel/intern/library_query.c +++ b/source/blender/blenkernel/intern/library_query.c @@ -61,6 +61,8 @@ #include "DNA_world_types.h" #include "BLI_utildefines.h" +#include "BLI_ghash.h" +#include "BLI_linklist_stack.h" #include "BKE_animsys.h" #include "BKE_constraint.h" @@ -74,52 +76,80 @@ #include "BKE_sequencer.h" #include "BKE_tracking.h" -#define FOREACH_CALLBACK_INVOKE_ID_PP(self_id, id_pp, flag, callback, user_data, cb_flag) \ - { \ - ID *old_id = *id_pp; \ - bool keep_working = callback(user_data, id_pp, cb_flag); \ - if (flag & IDWALK_READONLY) { \ - BLI_assert(*id_pp == old_id); \ - (void)old_id; /* quiet warning */ \ + +#define FOREACH_FINALIZE _finalize +#define FOREACH_FINALIZE_VOID FOREACH_FINALIZE: (void)0 + +#define FOREACH_CALLBACK_INVOKE_ID_PP(_data, id_pp, cb_flag) \ + if (!((_data)->status & IDWALK_STOP)) { \ + const int _flag = (_data)->flag; \ + ID *old_id = *(id_pp); \ + const int callback_return = (_data)->callback((_data)->user_data, (_data)->self_id, id_pp, cb_flag); \ + if (_flag & IDWALK_READONLY) { \ + BLI_assert(*(id_pp) == old_id); \ } \ - if (keep_working == false) { \ - /* REAL DANGER! Beware of this return! */ \ - /* TODO(sergey): Make it less creepy without too much duplicated code.. */ \ - return; \ + if (_flag & IDWALK_RECURSE) { \ + if (!BLI_gset_haskey((_data)->ids_handled, old_id)) { \ + BLI_gset_add((_data)->ids_handled, old_id); \ + if (!(callback_return & IDWALK_RET_STOP_RECURSION)) { \ + BLI_LINKSTACK_PUSH((_data)->ids_todo, old_id); \ + } \ + } \ } \ + if (callback_return & IDWALK_RET_STOP_ITER) { \ + (_data)->status |= IDWALK_STOP; \ + goto FOREACH_FINALIZE; \ + } \ + } \ + else { \ + goto FOREACH_FINALIZE; \ } ((void)0) -#define FOREACH_CALLBACK_INVOKE_ID(self_id, id, flag, callback, user_data, cb_flag) \ +#define FOREACH_CALLBACK_INVOKE_ID(_data, id, cb_flag) \ { \ CHECK_TYPE_ANY(id, ID *, void *); \ - FOREACH_CALLBACK_INVOKE_ID_PP(self_id, (ID **)&(id), flag, callback, user_data, cb_flag); \ + FOREACH_CALLBACK_INVOKE_ID_PP(_data, (ID **)&(id), cb_flag); \ } ((void)0) -#define FOREACH_CALLBACK_INVOKE(self_id, id_super, flag, callback, user_data, cb_flag) \ +#define FOREACH_CALLBACK_INVOKE(_data, id_super, cb_flag) \ { \ CHECK_TYPE(&((id_super)->id), ID *); \ - FOREACH_CALLBACK_INVOKE_ID_PP(self_id, (ID **)&id_super, flag, callback, user_data, cb_flag); \ + FOREACH_CALLBACK_INVOKE_ID_PP(_data, (ID **)&(id_super), cb_flag); \ } ((void)0) +/* status */ +enum { + IDWALK_STOP = 1 << 0, +}; + typedef struct LibraryForeachIDData { ID *self_id; int flag; LibraryIDLinkCallback callback; void *user_data; + int status; + + /* To handle recursion. */ + GSet *ids_handled; /* All IDs that are either already done, or still in ids_todo stack. */ + BLI_LINKSTACK_DECLARE(ids_todo, ID *); } LibraryForeachIDData; static void library_foreach_rigidbodyworldSceneLooper( struct RigidBodyWorld *UNUSED(rbw), ID **id_pointer, void *user_data, int cd_flag) { LibraryForeachIDData *data = (LibraryForeachIDData *) user_data; - FOREACH_CALLBACK_INVOKE_ID_PP(data->self_id, id_pointer, data->flag, data->callback, data->user_data, cd_flag); + FOREACH_CALLBACK_INVOKE_ID_PP(data, id_pointer, cd_flag); + + FOREACH_FINALIZE_VOID; } static void library_foreach_modifiersForeachIDLink( void *user_data, Object *UNUSED(object), ID **id_pointer, int cd_flag) { LibraryForeachIDData *data = (LibraryForeachIDData *) user_data; - FOREACH_CALLBACK_INVOKE_ID_PP(data->self_id, id_pointer, data->flag, data->callback, data->user_data, cd_flag); + FOREACH_CALLBACK_INVOKE_ID_PP(data, id_pointer, cd_flag); + + FOREACH_FINALIZE_VOID; } static void library_foreach_constraintObjectLooper(bConstraint *UNUSED(con), ID **id_pointer, @@ -127,35 +157,45 @@ static void library_foreach_constraintObjectLooper(bConstraint *UNUSED(con), ID { LibraryForeachIDData *data = (LibraryForeachIDData *) user_data; const int cd_flag = is_reference ? IDWALK_USER : IDWALK_NOP; - FOREACH_CALLBACK_INVOKE_ID_PP(data->self_id, id_pointer, data->flag, data->callback, data->user_data, cd_flag); + FOREACH_CALLBACK_INVOKE_ID_PP(data, id_pointer, cd_flag); + + FOREACH_FINALIZE_VOID; } static void library_foreach_particlesystemsObjectLooper( ParticleSystem *UNUSED(psys), ID **id_pointer, void *user_data, int cd_flag) { LibraryForeachIDData *data = (LibraryForeachIDData *) user_data; - FOREACH_CALLBACK_INVOKE_ID_PP(data->self_id, id_pointer, data->flag, data->callback, data->user_data, cd_flag); + FOREACH_CALLBACK_INVOKE_ID_PP(data, id_pointer, cd_flag); + + FOREACH_FINALIZE_VOID; } static void library_foreach_sensorsObjectLooper( bSensor *UNUSED(sensor), ID **id_pointer, void *user_data, int cd_flag) { LibraryForeachIDData *data = (LibraryForeachIDData *) user_data; - FOREACH_CALLBACK_INVOKE_ID_PP(data->self_id, id_pointer, data->flag, data->callback, data->user_data, cd_flag); + FOREACH_CALLBACK_INVOKE_ID_PP(data, id_pointer, cd_flag); + + FOREACH_FINALIZE_VOID; } static void library_foreach_controllersObjectLooper( bController *UNUSED(controller), ID **id_pointer, void *user_data, int cd_flag) { LibraryForeachIDData *data = (LibraryForeachIDData *) user_data; - FOREACH_CALLBACK_INVOKE_ID_PP(data->self_id, id_pointer, data->flag, data->callback, data->user_data, cd_flag); + FOREACH_CALLBACK_INVOKE_ID_PP(data, id_pointer, cd_flag); + + FOREACH_FINALIZE_VOID; } static void library_foreach_actuatorsObjectLooper( bActuator *UNUSED(actuator), ID **id_pointer, void *user_data, int cd_flag) { LibraryForeachIDData *data = (LibraryForeachIDData *) user_data; - FOREACH_CALLBACK_INVOKE_ID_PP(data->self_id, id_pointer, data->flag, data->callback, data->user_data, cd_flag); + FOREACH_CALLBACK_INVOKE_ID_PP(data, id_pointer, cd_flag); + + FOREACH_FINALIZE_VOID; } static void library_foreach_animationData(LibraryForeachIDData *data, AnimData *adt) @@ -170,17 +210,21 @@ static void library_foreach_animationData(LibraryForeachIDData *data, AnimData * /* only used targets */ DRIVER_TARGETS_USED_LOOPER(dvar) { - FOREACH_CALLBACK_INVOKE_ID(data->self_id, dtar->id, data->flag, data->callback, data->user_data, IDWALK_NOP); + FOREACH_CALLBACK_INVOKE_ID(data, dtar->id, IDWALK_NOP); } DRIVER_TARGETS_LOOPER_END } } + + FOREACH_FINALIZE_VOID; } static void library_foreach_mtex(LibraryForeachIDData *data, MTex *mtex) { - FOREACH_CALLBACK_INVOKE(data->self_id, mtex->object, data->flag, data->callback, data->user_data, IDWALK_NOP); - FOREACH_CALLBACK_INVOKE(data->self_id, mtex->tex, data->flag, data->callback, data->user_data, IDWALK_USER); + FOREACH_CALLBACK_INVOKE(data, mtex->object, IDWALK_NOP); + FOREACH_CALLBACK_INVOKE(data, mtex->tex, IDWALK_USER); + + FOREACH_FINALIZE_VOID; } @@ -191,460 +235,478 @@ static void library_foreach_mtex(LibraryForeachIDData *data, MTex *mtex) */ void BKE_library_foreach_ID_link(ID *id, LibraryIDLinkCallback callback, void *user_data, int flag) { - AnimData *adt; LibraryForeachIDData data; int i; - data.self_id = id; + if (flag & IDWALK_RECURSE) { + /* For now, recusion implies read-only. */ + flag |= IDWALK_READONLY; + + data.ids_handled = BLI_gset_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp, __func__); + BLI_LINKSTACK_INIT(data.ids_todo); + } + else { + data.ids_handled = NULL; + } data.flag = flag; data.callback = callback; data.user_data = user_data; - adt = BKE_animdata_from_id(id); - if (adt) { - library_foreach_animationData(&data, adt); - } - #define CALLBACK_INVOKE_ID(check_id, cb_flag) \ - FOREACH_CALLBACK_INVOKE_ID(id, check_id, flag, callback, user_data, cb_flag) + FOREACH_CALLBACK_INVOKE_ID(&data, check_id, cb_flag) #define CALLBACK_INVOKE(check_id_super, cb_flag) \ - FOREACH_CALLBACK_INVOKE(id, check_id_super, flag, callback, user_data, cb_flag) - - switch (GS(id->name)) { - case ID_SCE: - { - Scene *scene = (Scene *) id; - ToolSettings *toolsett = scene->toolsettings; - SceneRenderLayer *srl; - Base *base; - - CALLBACK_INVOKE(scene->camera, IDWALK_NOP); - CALLBACK_INVOKE(scene->world, IDWALK_USER); - CALLBACK_INVOKE(scene->set, IDWALK_NOP); - CALLBACK_INVOKE(scene->clip, IDWALK_NOP); - CALLBACK_INVOKE(scene->nodetree, IDWALK_NOP); - /* DO NOT handle scene->basact here, it's doubling with the loop over whole scene->base later, - * since basact is just a pointer to one of those items. */ - CALLBACK_INVOKE(scene->obedit, IDWALK_NOP); - - for (srl = scene->r.layers.first; srl; srl = srl->next) { - FreestyleModuleConfig *fmc; - FreestyleLineSet *fls; - - if (srl->mat_override) { - CALLBACK_INVOKE(srl->mat_override, IDWALK_USER); - } - if (srl->light_override) { - CALLBACK_INVOKE(srl->light_override, IDWALK_USER); + FOREACH_CALLBACK_INVOKE(&data, check_id_super, cb_flag) + + do { + data.self_id = id; + + AnimData *adt = BKE_animdata_from_id(id); + if (adt) { + library_foreach_animationData(&data, adt); + } + + switch (GS(id->name)) { + case ID_SCE: + { + Scene *scene = (Scene *) id; + ToolSettings *toolsett = scene->toolsettings; + SceneRenderLayer *srl; + Base *base; + + CALLBACK_INVOKE(scene->camera, IDWALK_NOP); + CALLBACK_INVOKE(scene->world, IDWALK_USER); + CALLBACK_INVOKE(scene->set, IDWALK_NOP); + CALLBACK_INVOKE(scene->clip, IDWALK_NOP); + CALLBACK_INVOKE(scene->nodetree, IDWALK_NOP); + /* DO NOT handle scene->basact here, it's doubling with the loop over whole scene->base later, + * since basact is just a pointer to one of those items. */ + CALLBACK_INVOKE(scene->obedit, IDWALK_NOP); + + for (srl = scene->r.layers.first; srl; srl = srl->next) { + FreestyleModuleConfig *fmc; + FreestyleLineSet *fls; + + if (srl->mat_override) { + CALLBACK_INVOKE(srl->mat_override, IDWALK_USER); + } + if (srl->light_override) { + CALLBACK_INVOKE(srl->light_override, IDWALK_USER); + } + for (fmc = srl->freestyleConfig.modules.first; fmc; fmc = fmc->next) { + if (fmc->script) { + CALLBACK_INVOKE(fmc->script, IDWALK_NOP); + } + } + for (fls = srl->freestyleConfig.linesets.first; fls; fls = fls->next) { + if (fls->group) { + CALLBACK_INVOKE(fls->group, IDWALK_USER); + } + if (fls->linestyle) { + CALLBACK_INVOKE(fls->linestyle, IDWALK_USER); + } + } } - for (fmc = srl->freestyleConfig.modules.first; fmc; fmc = fmc->next) { - if (fmc->script) { - CALLBACK_INVOKE(fmc->script, IDWALK_NOP); + + if (scene->ed) { + Sequence *seq; + SEQP_BEGIN(scene->ed, seq) + { + CALLBACK_INVOKE(seq->scene, IDWALK_NOP); + CALLBACK_INVOKE(seq->scene_camera, IDWALK_NOP); + CALLBACK_INVOKE(seq->clip, IDWALK_USER); + CALLBACK_INVOKE(seq->mask, IDWALK_USER); + CALLBACK_INVOKE(seq->sound, IDWALK_USER); } + SEQ_END } - for (fls = srl->freestyleConfig.linesets.first; fls; fls = fls->next) { - if (fls->group) { - CALLBACK_INVOKE(fls->group, IDWALK_USER); + + CALLBACK_INVOKE(scene->gpd, IDWALK_USER); + + for (base = scene->base.first; base; base = base->next) { + CALLBACK_INVOKE(base->object, IDWALK_USER); + } + + if (toolsett) { + CALLBACK_INVOKE(toolsett->skgen_template, IDWALK_NOP); + CALLBACK_INVOKE(toolsett->particle.scene, IDWALK_NOP); + CALLBACK_INVOKE(toolsett->particle.object, IDWALK_NOP); + CALLBACK_INVOKE(toolsett->particle.shape_object, IDWALK_NOP); + CALLBACK_INVOKE(toolsett->imapaint.stencil, IDWALK_NOP); + CALLBACK_INVOKE(toolsett->imapaint.clone, IDWALK_NOP); + CALLBACK_INVOKE(toolsett->imapaint.canvas, IDWALK_NOP); + if (toolsett->vpaint) { + CALLBACK_INVOKE(toolsett->vpaint->paint.brush, IDWALK_NOP); + CALLBACK_INVOKE(toolsett->vpaint->paint.palette, IDWALK_NOP); } - if (fls->linestyle) { - CALLBACK_INVOKE(fls->linestyle, IDWALK_USER); + if (toolsett->wpaint) { + CALLBACK_INVOKE(toolsett->wpaint->paint.brush, IDWALK_NOP); + CALLBACK_INVOKE(toolsett->wpaint->paint.palette, IDWALK_NOP); + } + if (toolsett->sculpt) { + CALLBACK_INVOKE(toolsett->sculpt->paint.brush, IDWALK_NOP); + CALLBACK_INVOKE(toolsett->sculpt->paint.palette, IDWALK_NOP); + CALLBACK_INVOKE(toolsett->sculpt->gravity_object, IDWALK_NOP); + } + if (toolsett->uvsculpt) { + CALLBACK_INVOKE(toolsett->uvsculpt->paint.brush, IDWALK_NOP); + CALLBACK_INVOKE(toolsett->uvsculpt->paint.palette, IDWALK_NOP); } } - } - if (scene->ed) { - Sequence *seq; - SEQP_BEGIN(scene->ed, seq) - { - CALLBACK_INVOKE(seq->scene, IDWALK_NOP); - CALLBACK_INVOKE(seq->scene_camera, IDWALK_NOP); - CALLBACK_INVOKE(seq->clip, IDWALK_USER); - CALLBACK_INVOKE(seq->mask, IDWALK_USER); - CALLBACK_INVOKE(seq->sound, IDWALK_USER); + if (scene->rigidbody_world) { + BKE_rigidbody_world_id_loop(scene->rigidbody_world, library_foreach_rigidbodyworldSceneLooper, &data); } - SEQ_END - } - CALLBACK_INVOKE(scene->gpd, IDWALK_USER); + CALLBACK_INVOKE(scene->gm.dome.warptext, IDWALK_NOP); - for (base = scene->base.first; base; base = base->next) { - CALLBACK_INVOKE(base->object, IDWALK_USER); + break; } - if (toolsett) { - CALLBACK_INVOKE(toolsett->skgen_template, IDWALK_NOP); - CALLBACK_INVOKE(toolsett->particle.scene, IDWALK_NOP); - CALLBACK_INVOKE(toolsett->particle.object, IDWALK_NOP); - CALLBACK_INVOKE(toolsett->particle.shape_object, IDWALK_NOP); - CALLBACK_INVOKE(toolsett->imapaint.stencil, IDWALK_NOP); - CALLBACK_INVOKE(toolsett->imapaint.clone, IDWALK_NOP); - CALLBACK_INVOKE(toolsett->imapaint.canvas, IDWALK_NOP); - if (toolsett->vpaint) { - CALLBACK_INVOKE(toolsett->vpaint->paint.brush, IDWALK_NOP); - CALLBACK_INVOKE(toolsett->vpaint->paint.palette, IDWALK_NOP); + case ID_OB: + { + Object *object = (Object *) id; + ParticleSystem *psys; + + /* object data special case */ + if (object->type == OB_EMPTY) { + /* empty can have NULL or Image */ + CALLBACK_INVOKE_ID(object->data, IDWALK_USER); } - if (toolsett->wpaint) { - CALLBACK_INVOKE(toolsett->wpaint->paint.brush, IDWALK_NOP); - CALLBACK_INVOKE(toolsett->wpaint->paint.palette, IDWALK_NOP); + else { + /* when set, this can't be NULL */ + if (object->data) { + CALLBACK_INVOKE_ID(object->data, IDWALK_USER | IDWALK_NEVER_NULL); + } } - if (toolsett->sculpt) { - CALLBACK_INVOKE(toolsett->sculpt->paint.brush, IDWALK_NOP); - CALLBACK_INVOKE(toolsett->sculpt->paint.palette, IDWALK_NOP); - CALLBACK_INVOKE(toolsett->sculpt->gravity_object, IDWALK_NOP); + + CALLBACK_INVOKE(object->parent, IDWALK_NOP); + CALLBACK_INVOKE(object->track, IDWALK_NOP); + /* object->proxy is refcounted, but not object->proxy_group... *sigh* */ + CALLBACK_INVOKE(object->proxy, IDWALK_USER); + CALLBACK_INVOKE(object->proxy_group, IDWALK_NOP); + CALLBACK_INVOKE(object->proxy_from, IDWALK_NOP); + CALLBACK_INVOKE(object->poselib, IDWALK_USER); + for (i = 0; i < object->totcol; i++) { + CALLBACK_INVOKE(object->mat[i], IDWALK_USER); } - if (toolsett->uvsculpt) { - CALLBACK_INVOKE(toolsett->uvsculpt->paint.brush, IDWALK_NOP); - CALLBACK_INVOKE(toolsett->uvsculpt->paint.palette, IDWALK_NOP); + CALLBACK_INVOKE(object->gpd, IDWALK_USER); + CALLBACK_INVOKE(object->dup_group, IDWALK_USER); + + if (object->pd) { + CALLBACK_INVOKE(object->pd->tex, IDWALK_USER); + CALLBACK_INVOKE(object->pd->f_source, IDWALK_NOP); } - } - if (scene->rigidbody_world) { - BKE_rigidbody_world_id_loop(scene->rigidbody_world, library_foreach_rigidbodyworldSceneLooper, &data); - } + if (object->pose) { + bPoseChannel *pchan; + for (pchan = object->pose->chanbase.first; pchan; pchan = pchan->next) { + CALLBACK_INVOKE(pchan->custom, IDWALK_USER); + BKE_constraints_id_loop(&pchan->constraints, library_foreach_constraintObjectLooper, &data); + } + } - CALLBACK_INVOKE(scene->gm.dome.warptext, IDWALK_NOP); + if (object->rigidbody_constraint) { + CALLBACK_INVOKE(object->rigidbody_constraint->ob1, IDWALK_NOP); + CALLBACK_INVOKE(object->rigidbody_constraint->ob2, IDWALK_NOP); + } - break; - } + if (object->lodlevels.first) { + LodLevel *level; + for (level = object->lodlevels.first; level; level = level->next) { + CALLBACK_INVOKE(level->source, IDWALK_NOP); + } + } - case ID_OB: - { - Object *object = (Object *) id; - ParticleSystem *psys; + modifiers_foreachIDLink(object, library_foreach_modifiersForeachIDLink, &data); + BKE_constraints_id_loop(&object->constraints, library_foreach_constraintObjectLooper, &data); - /* object data special case */ - if (object->type == OB_EMPTY) { - /* empty can have NULL or Image */ - CALLBACK_INVOKE_ID(object->data, IDWALK_USER); - } - else { - /* when set, this can't be NULL */ - if (object->data) { - CALLBACK_INVOKE_ID(object->data, IDWALK_USER | IDWALK_NEVER_NULL); + for (psys = object->particlesystem.first; psys; psys = psys->next) { + BKE_particlesystem_id_loop(psys, library_foreach_particlesystemsObjectLooper, &data); } - } - CALLBACK_INVOKE(object->parent, IDWALK_NOP); - CALLBACK_INVOKE(object->track, IDWALK_NOP); - /* object->proxy is refcounted, but not object->proxy_group... *sigh* */ - CALLBACK_INVOKE(object->proxy, IDWALK_USER); - CALLBACK_INVOKE(object->proxy_group, IDWALK_NOP); - CALLBACK_INVOKE(object->proxy_from, IDWALK_NOP); - CALLBACK_INVOKE(object->poselib, IDWALK_USER); - for (i = 0; i < object->totcol; i++) { - CALLBACK_INVOKE(object->mat[i], IDWALK_USER); + BKE_sca_sensors_id_loop(&object->sensors, library_foreach_sensorsObjectLooper, &data); + BKE_sca_controllers_id_loop(&object->controllers, library_foreach_controllersObjectLooper, &data); + BKE_sca_actuators_id_loop(&object->actuators, library_foreach_actuatorsObjectLooper, &data); + break; } - CALLBACK_INVOKE(object->gpd, IDWALK_USER); - CALLBACK_INVOKE(object->dup_group, IDWALK_USER); - if (object->pd) { - CALLBACK_INVOKE(object->pd->tex, IDWALK_USER); - CALLBACK_INVOKE(object->pd->f_source, IDWALK_NOP); + case ID_ME: + { + Mesh *mesh = (Mesh *) id; + CALLBACK_INVOKE(mesh->texcomesh, IDWALK_USER); + CALLBACK_INVOKE(mesh->key, IDWALK_USER); + for (i = 0; i < mesh->totcol; i++) { + CALLBACK_INVOKE(mesh->mat[i], IDWALK_USER); + } + break; } - if (object->pose) { - bPoseChannel *pchan; - for (pchan = object->pose->chanbase.first; pchan; pchan = pchan->next) { - CALLBACK_INVOKE(pchan->custom, IDWALK_USER); - BKE_constraints_id_loop(&pchan->constraints, library_foreach_constraintObjectLooper, &data); + case ID_CU: + { + Curve *curve = (Curve *) id; + CALLBACK_INVOKE(curve->bevobj, IDWALK_NOP); + CALLBACK_INVOKE(curve->taperobj, IDWALK_NOP); + CALLBACK_INVOKE(curve->textoncurve, IDWALK_NOP); + CALLBACK_INVOKE(curve->key, IDWALK_USER); + for (i = 0; i < curve->totcol; i++) { + CALLBACK_INVOKE(curve->mat[i], IDWALK_USER); } + CALLBACK_INVOKE(curve->vfont, IDWALK_USER); + CALLBACK_INVOKE(curve->vfontb, IDWALK_USER); + CALLBACK_INVOKE(curve->vfonti, IDWALK_USER); + CALLBACK_INVOKE(curve->vfontbi, IDWALK_USER); + break; } - if (object->rigidbody_constraint) { - CALLBACK_INVOKE(object->rigidbody_constraint->ob1, IDWALK_NOP); - CALLBACK_INVOKE(object->rigidbody_constraint->ob2, IDWALK_NOP); + case ID_MB: + { + MetaBall *metaball = (MetaBall *) id; + for (i = 0; i < metaball->totcol; i++) { + CALLBACK_INVOKE(metaball->mat[i], IDWALK_USER); + } + break; } - if (object->lodlevels.first) { - LodLevel *level; - for (level = object->lodlevels.first; level; level = level->next) { - CALLBACK_INVOKE(level->source, IDWALK_NOP); + case ID_MA: + { + Material *material = (Material *) id; + for (i = 0; i < MAX_MTEX; i++) { + if (material->mtex[i]) { + library_foreach_mtex(&data, material->mtex[i]); + } } + CALLBACK_INVOKE(material->nodetree, IDWALK_NOP); + CALLBACK_INVOKE(material->group, IDWALK_USER); + break; } - modifiers_foreachIDLink(object, library_foreach_modifiersForeachIDLink, &data); - BKE_constraints_id_loop(&object->constraints, library_foreach_constraintObjectLooper, &data); - - for (psys = object->particlesystem.first; psys; psys = psys->next) { - BKE_particlesystem_id_loop(psys, library_foreach_particlesystemsObjectLooper, &data); + case ID_TE: + { + Tex *texture = (Tex *) id; + CALLBACK_INVOKE(texture->nodetree, IDWALK_NOP); + CALLBACK_INVOKE(texture->ima, IDWALK_USER); + if (texture->env) { + CALLBACK_INVOKE(texture->env->object, IDWALK_NOP); + CALLBACK_INVOKE(texture->env->ima, IDWALK_USER); + } + if (texture->pd) + CALLBACK_INVOKE(texture->pd->object, IDWALK_NOP); + if (texture->vd) + CALLBACK_INVOKE(texture->vd->object, IDWALK_NOP); + if (texture->ot) + CALLBACK_INVOKE(texture->ot->object, IDWALK_NOP); + break; } - BKE_sca_sensors_id_loop(&object->sensors, library_foreach_sensorsObjectLooper, &data); - BKE_sca_controllers_id_loop(&object->controllers, library_foreach_controllersObjectLooper, &data); - BKE_sca_actuators_id_loop(&object->actuators, library_foreach_actuatorsObjectLooper, &data); - break; - } - - case ID_ME: - { - Mesh *mesh = (Mesh *) id; - CALLBACK_INVOKE(mesh->texcomesh, IDWALK_USER); - CALLBACK_INVOKE(mesh->key, IDWALK_USER); - for (i = 0; i < mesh->totcol; i++) { - CALLBACK_INVOKE(mesh->mat[i], IDWALK_USER); + case ID_LT: + { + Lattice *lattice = (Lattice *) id; + CALLBACK_INVOKE(lattice->key, IDWALK_USER); + break; } - break; - } - case ID_CU: - { - Curve *curve = (Curve *) id; - CALLBACK_INVOKE(curve->bevobj, IDWALK_NOP); - CALLBACK_INVOKE(curve->taperobj, IDWALK_NOP); - CALLBACK_INVOKE(curve->textoncurve, IDWALK_NOP); - CALLBACK_INVOKE(curve->key, IDWALK_USER); - for (i = 0; i < curve->totcol; i++) { - CALLBACK_INVOKE(curve->mat[i], IDWALK_USER); + case ID_LA: + { + Lamp *lamp = (Lamp *) id; + for (i = 0; i < MAX_MTEX; i++) { + if (lamp->mtex[i]) { + library_foreach_mtex(&data, lamp->mtex[i]); + } + } + CALLBACK_INVOKE(lamp->nodetree, IDWALK_NOP); + break; } - CALLBACK_INVOKE(curve->vfont, IDWALK_USER); - CALLBACK_INVOKE(curve->vfontb, IDWALK_USER); - CALLBACK_INVOKE(curve->vfonti, IDWALK_USER); - CALLBACK_INVOKE(curve->vfontbi, IDWALK_USER); - break; - } - case ID_MB: - { - MetaBall *metaball = (MetaBall *) id; - for (i = 0; i < metaball->totcol; i++) { - CALLBACK_INVOKE(metaball->mat[i], IDWALK_USER); + case ID_CA: + { + Camera *camera = (Camera *) id; + CALLBACK_INVOKE(camera->dof_ob, IDWALK_NOP); + break; } - break; - } - case ID_MA: - { - Material *material = (Material *) id; - for (i = 0; i < MAX_MTEX; i++) { - if (material->mtex[i]) { - library_foreach_mtex(&data, material->mtex[i]); - } + case ID_KE: + { + Key *key = (Key *) id; + CALLBACK_INVOKE_ID(key->from, IDWALK_NOP); + break; } - CALLBACK_INVOKE(material->nodetree, IDWALK_NOP); - CALLBACK_INVOKE(material->group, IDWALK_USER); - break; - } - case ID_TE: - { - Tex *texture = (Tex *) id; - CALLBACK_INVOKE(texture->nodetree, IDWALK_NOP); - CALLBACK_INVOKE(texture->ima, IDWALK_USER); - if (texture->env) { - CALLBACK_INVOKE(texture->env->object, IDWALK_NOP); - CALLBACK_INVOKE(texture->env->ima, IDWALK_USER); + case ID_SCR: + { + bScreen *screen = (bScreen *) id; + CALLBACK_INVOKE(screen->scene, IDWALK_USER_ONE); + break; } - if (texture->pd) - CALLBACK_INVOKE(texture->pd->object, IDWALK_NOP); - if (texture->vd) - CALLBACK_INVOKE(texture->vd->object, IDWALK_NOP); - if (texture->ot) - CALLBACK_INVOKE(texture->ot->object, IDWALK_NOP); - break; - } - case ID_LT: - { - Lattice *lattice = (Lattice *) id; - CALLBACK_INVOKE(lattice->key, IDWALK_USER); - break; - } - - case ID_LA: - { - Lamp *lamp = (Lamp *) id; - for (i = 0; i < MAX_MTEX; i++) { - if (lamp->mtex[i]) { - library_foreach_mtex(&data, lamp->mtex[i]); + case ID_WO: + { + World *world = (World *) id; + for (i = 0; i < MAX_MTEX; i++) { + if (world->mtex[i]) { + library_foreach_mtex(&data, world->mtex[i]); + } } + CALLBACK_INVOKE(world->nodetree, IDWALK_NOP); + break; } - CALLBACK_INVOKE(lamp->nodetree, IDWALK_NOP); - break; - } - - case ID_CA: - { - Camera *camera = (Camera *) id; - CALLBACK_INVOKE(camera->dof_ob, IDWALK_NOP); - break; - } - - case ID_KE: - { - Key *key = (Key *) id; - CALLBACK_INVOKE_ID(key->from, IDWALK_NOP); - break; - } - case ID_SCR: - { - bScreen *screen = (bScreen *) id; - CALLBACK_INVOKE(screen->scene, IDWALK_USER_ONE); - break; - } + case ID_SPK: + { + Speaker *speaker = (Speaker *) id; + CALLBACK_INVOKE(speaker->sound, IDWALK_USER); + break; + } - case ID_WO: - { - World *world = (World *) id; - for (i = 0; i < MAX_MTEX; i++) { - if (world->mtex[i]) { - library_foreach_mtex(&data, world->mtex[i]); + case ID_GR: + { + Group *group = (Group *) id; + GroupObject *gob; + for (gob = group->gobject.first; gob; gob = gob->next) { + CALLBACK_INVOKE(gob->ob, IDWALK_USER_ONE); } + break; } - CALLBACK_INVOKE(world->nodetree, IDWALK_NOP); - break; - } - - case ID_SPK: - { - Speaker *speaker = (Speaker *) id; - CALLBACK_INVOKE(speaker->sound, IDWALK_USER); - break; - } - case ID_GR: - { - Group *group = (Group *) id; - GroupObject *gob; - for (gob = group->gobject.first; gob; gob = gob->next) { - CALLBACK_INVOKE(gob->ob, IDWALK_USER_ONE); + case ID_NT: + { + bNodeTree *ntree = (bNodeTree *) id; + bNode *node; + CALLBACK_INVOKE(ntree->gpd, IDWALK_USER); + for (node = ntree->nodes.first; node; node = node->next) { + CALLBACK_INVOKE_ID(node->id, IDWALK_USER); + } + break; } - break; - } - case ID_NT: - { - bNodeTree *ntree = (bNodeTree *) id; - bNode *node; - CALLBACK_INVOKE(ntree->gpd, IDWALK_USER); - for (node = ntree->nodes.first; node; node = node->next) { - CALLBACK_INVOKE_ID(node->id, IDWALK_USER); + case ID_BR: + { + Brush *brush = (Brush *) id; + CALLBACK_INVOKE(brush->toggle_brush, IDWALK_NOP); + CALLBACK_INVOKE(brush->clone.image, IDWALK_NOP); + CALLBACK_INVOKE(brush->paint_curve, IDWALK_USER); + library_foreach_mtex(&data, &brush->mtex); + library_foreach_mtex(&data, &brush->mask_mtex); + break; } - break; - } - case ID_BR: - { - Brush *brush = (Brush *) id; - CALLBACK_INVOKE(brush->toggle_brush, IDWALK_NOP); - CALLBACK_INVOKE(brush->clone.image, IDWALK_NOP); - CALLBACK_INVOKE(brush->paint_curve, IDWALK_USER); - library_foreach_mtex(&data, &brush->mtex); - library_foreach_mtex(&data, &brush->mask_mtex); - break; - } - - case ID_PA: - { - ParticleSettings *psett = (ParticleSettings *) id; - CALLBACK_INVOKE(psett->dup_group, IDWALK_NOP); - CALLBACK_INVOKE(psett->dup_ob, IDWALK_NOP); - CALLBACK_INVOKE(psett->bb_ob, IDWALK_NOP); - - for (i = 0; i < MAX_MTEX; i++) { - if (psett->mtex[i]) { - library_foreach_mtex(&data, psett->mtex[i]); + case ID_PA: + { + ParticleSettings *psett = (ParticleSettings *) id; + CALLBACK_INVOKE(psett->dup_group, IDWALK_NOP); + CALLBACK_INVOKE(psett->dup_ob, IDWALK_NOP); + CALLBACK_INVOKE(psett->bb_ob, IDWALK_NOP); + + for (i = 0; i < MAX_MTEX; i++) { + if (psett->mtex[i]) { + library_foreach_mtex(&data, psett->mtex[i]); + } } - } - - if (psett->effector_weights) { - CALLBACK_INVOKE(psett->effector_weights->group, IDWALK_NOP); - } - if (psett->boids) { - BoidState *state; - BoidRule *rule; + if (psett->effector_weights) { + CALLBACK_INVOKE(psett->effector_weights->group, IDWALK_NOP); + } - for (state = psett->boids->states.first; state; state = state->next) { - for (rule = state->rules.first; rule; rule = rule->next) { - if (rule->type == eBoidRuleType_Avoid) { - BoidRuleGoalAvoid *gabr = (BoidRuleGoalAvoid *)rule; - CALLBACK_INVOKE(gabr->ob, IDWALK_NOP); - } - else if (rule->type == eBoidRuleType_FollowLeader) { - BoidRuleFollowLeader *flbr = (BoidRuleFollowLeader *)rule; - CALLBACK_INVOKE(flbr->ob, IDWALK_NOP); + if (psett->boids) { + BoidState *state; + BoidRule *rule; + + for (state = psett->boids->states.first; state; state = state->next) { + for (rule = state->rules.first; rule; rule = rule->next) { + if (rule->type == eBoidRuleType_Avoid) { + BoidRuleGoalAvoid *gabr = (BoidRuleGoalAvoid *)rule; + CALLBACK_INVOKE(gabr->ob, IDWALK_NOP); + } + else if (rule->type == eBoidRuleType_FollowLeader) { + BoidRuleFollowLeader *flbr = (BoidRuleFollowLeader *)rule; + CALLBACK_INVOKE(flbr->ob, IDWALK_NOP); + } } } } - } - break; - } + break; + } - case ID_MC: - { - MovieClip *clip = (MovieClip *) id; - MovieTracking *tracking = &clip->tracking; - MovieTrackingObject *object; + case ID_MC: + { + MovieClip *clip = (MovieClip *) id; + MovieTracking *tracking = &clip->tracking; + MovieTrackingObject *object; - CALLBACK_INVOKE(clip->gpd, IDWALK_USER); - for (object = tracking->objects.first; object; object = object->next) { - ListBase *tracksbase = BKE_tracking_object_get_tracks(tracking, object); - MovieTrackingTrack *track; + CALLBACK_INVOKE(clip->gpd, IDWALK_USER); + for (object = tracking->objects.first; object; object = object->next) { + ListBase *tracksbase = BKE_tracking_object_get_tracks(tracking, object); + MovieTrackingTrack *track; - for (track = tracksbase->first; track; track = track->next) { - CALLBACK_INVOKE(track->gpd, IDWALK_USER); + for (track = tracksbase->first; track; track = track->next) { + CALLBACK_INVOKE(track->gpd, IDWALK_USER); + } } + break; } - break; - } - case ID_MSK: - { - Mask *mask = (Mask *) id; - MaskLayer *mask_layer; - for (mask_layer = mask->masklayers.first; mask_layer; mask_layer = mask_layer->next) { - MaskSpline *mask_spline; - - for (mask_spline = mask_layer->splines.first; mask_spline; mask_spline = mask_spline->next) { - for (i = 0; i < mask_spline->tot_point; i++) { - MaskSplinePoint *point = &mask_spline->points[i]; - CALLBACK_INVOKE_ID(point->parent.id, IDWALK_USER); + case ID_MSK: + { + Mask *mask = (Mask *) id; + MaskLayer *mask_layer; + for (mask_layer = mask->masklayers.first; mask_layer; mask_layer = mask_layer->next) { + MaskSpline *mask_spline; + + for (mask_spline = mask_layer->splines.first; mask_spline; mask_spline = mask_spline->next) { + for (i = 0; i < mask_spline->tot_point; i++) { + MaskSplinePoint *point = &mask_spline->points[i]; + CALLBACK_INVOKE_ID(point->parent.id, IDWALK_USER); + } } } + break; } - break; - } - case ID_LS: - { - FreestyleLineStyle *linestyle = (FreestyleLineStyle *) id; - LineStyleModifier *lsm; - for (i = 0; i < MAX_MTEX; i++) { - if (linestyle->mtex[i]) { - library_foreach_mtex(&data, linestyle->mtex[i]); + case ID_LS: + { + FreestyleLineStyle *linestyle = (FreestyleLineStyle *) id; + LineStyleModifier *lsm; + for (i = 0; i < MAX_MTEX; i++) { + if (linestyle->mtex[i]) { + library_foreach_mtex(&data, linestyle->mtex[i]); + } } - } - CALLBACK_INVOKE(linestyle->nodetree, IDWALK_NOP); + CALLBACK_INVOKE(linestyle->nodetree, IDWALK_NOP); - for (lsm = linestyle->color_modifiers.first; lsm; lsm = lsm->next) { - if (lsm->type == LS_MODIFIER_DISTANCE_FROM_OBJECT) { - LineStyleColorModifier_DistanceFromObject *p = (LineStyleColorModifier_DistanceFromObject *)lsm; - if (p->target) { - CALLBACK_INVOKE(p->target, IDWALK_NOP); + for (lsm = linestyle->color_modifiers.first; lsm; lsm = lsm->next) { + if (lsm->type == LS_MODIFIER_DISTANCE_FROM_OBJECT) { + LineStyleColorModifier_DistanceFromObject *p = (LineStyleColorModifier_DistanceFromObject *)lsm; + if (p->target) { + CALLBACK_INVOKE(p->target, IDWALK_NOP); + } } } - } - for (lsm = linestyle->alpha_modifiers.first; lsm; lsm = lsm->next) { - if (lsm->type == LS_MODIFIER_DISTANCE_FROM_OBJECT) { - LineStyleAlphaModifier_DistanceFromObject *p = (LineStyleAlphaModifier_DistanceFromObject *)lsm; - if (p->target) { - CALLBACK_INVOKE(p->target, IDWALK_NOP); + for (lsm = linestyle->alpha_modifiers.first; lsm; lsm = lsm->next) { + if (lsm->type == LS_MODIFIER_DISTANCE_FROM_OBJECT) { + LineStyleAlphaModifier_DistanceFromObject *p = (LineStyleAlphaModifier_DistanceFromObject *)lsm; + if (p->target) { + CALLBACK_INVOKE(p->target, IDWALK_NOP); + } } } - } - for (lsm = linestyle->thickness_modifiers.first; lsm; lsm = lsm->next) { - if (lsm->type == LS_MODIFIER_DISTANCE_FROM_OBJECT) { - LineStyleThicknessModifier_DistanceFromObject *p = (LineStyleThicknessModifier_DistanceFromObject *)lsm; - if (p->target) { - CALLBACK_INVOKE(p->target, IDWALK_NOP); + for (lsm = linestyle->thickness_modifiers.first; lsm; lsm = lsm->next) { + if (lsm->type == LS_MODIFIER_DISTANCE_FROM_OBJECT) { + LineStyleThicknessModifier_DistanceFromObject *p = (LineStyleThicknessModifier_DistanceFromObject *)lsm; + if (p->target) { + CALLBACK_INVOKE(p->target, IDWALK_NOP); + } } } + break; } - break; } + } while ((id = (flag & IDWALK_RECURSE) ? BLI_LINKSTACK_POP(data.ids_todo) : NULL)); + +FOREACH_FINALIZE: + if (data.ids_handled) { + BLI_gset_free(data.ids_handled, NULL); + BLI_LINKSTACK_FREE(data.ids_todo); } #undef CALLBACK_INVOKE_ID @@ -679,7 +741,7 @@ typedef struct IDUsersIter { int count; /* Set by callback. */ } IDUsersIter; -static bool foreach_libblock_id_users_callback(void *user_data, ID **id_p, int UNUSED(cb_flag)) +static int foreach_libblock_id_users_callback(void *user_data, ID *UNUSED(self_id), ID **id_p, int UNUSED(cb_flag)) { IDUsersIter *iter = user_data; @@ -687,7 +749,7 @@ static bool foreach_libblock_id_users_callback(void *user_data, ID **id_p, int U iter->count++; } - return true; + return IDWALK_RET_NOP; } /** |