From 3946ae56ac585121bcec8871393f0dae3a57a56b Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Fri, 29 Jan 2010 21:16:21 +0000 Subject: [PATCH] deleting objects which were driver targets would crash blender. added a utility function BKE_animdata_main_cb which loops over all AnimData's of all ID's --- source/blender/blenkernel/BKE_animsys.h | 2 + source/blender/blenkernel/intern/anim_sys.c | 41 +++++++++++++++++++++ source/blender/blenkernel/intern/library.c | 32 +++++++++++++++- 3 files changed, 73 insertions(+), 2 deletions(-) diff --git a/source/blender/blenkernel/BKE_animsys.h b/source/blender/blenkernel/BKE_animsys.h index a36845b38a2..68dd62af179 100644 --- a/source/blender/blenkernel/BKE_animsys.h +++ b/source/blender/blenkernel/BKE_animsys.h @@ -94,6 +94,8 @@ void BKE_animdata_fix_paths_rename(struct ID *owner_id, struct AnimData *adt, ch /* Fix all the paths for the entire database... */ void BKE_all_animdata_fix_paths_rename(char *prefix, char *oldName, char *newName); +void BKE_animdata_main_cb(struct Main *main, void (*func)(struct ID *, struct AnimData *, void *), void *user_data); + /* ************************************* */ // TODO: overrides, remapping, and path-finding api's diff --git a/source/blender/blenkernel/intern/anim_sys.c b/source/blender/blenkernel/intern/anim_sys.c index e6a429e4b5f..81871828af2 100644 --- a/source/blender/blenkernel/intern/anim_sys.c +++ b/source/blender/blenkernel/intern/anim_sys.c @@ -422,10 +422,51 @@ void BKE_animdata_fix_paths_rename (ID *owner_id, AnimData *adt, char *prefix, c MEM_freeN(newN); } +void BKE_animdata_main_cb(Main *main, void (*func)(ID *, AnimData *, void *), void *user_data) +{ + ID *id; + +#define ANIMDATA_IDS_CB(first) \ + for (id= first; id; id= id->next) { \ + AnimData *adt= BKE_animdata_from_id(id); \ + if(adt) func(id, adt, user_data); \ + } + + ANIMDATA_IDS_CB(main->nodetree.first); /* nodes */ + ANIMDATA_IDS_CB(main->tex.first); /* textures */ + ANIMDATA_IDS_CB(main->lamp.first); /* lamps */ + ANIMDATA_IDS_CB(main->mat.first); /* materials */ + ANIMDATA_IDS_CB(main->camera.first); /* cameras */ + ANIMDATA_IDS_CB(main->key.first); /* shapekeys */ + ANIMDATA_IDS_CB(main->mball.first); /* metaballs */ + ANIMDATA_IDS_CB(main->curve.first); /* curves */ + ANIMDATA_IDS_CB(main->armature.first); /* armatures */ + ANIMDATA_IDS_CB(main->mesh.first); /* meshes */ + ANIMDATA_IDS_CB(main->particle.first); /* particles */ + ANIMDATA_IDS_CB(main->object.first); /* objects */ + ANIMDATA_IDS_CB(main->world.first); /* worlds */ + + /* scenes */ + for (id= main->scene.first; id; id= id->next) { + AnimData *adt= BKE_animdata_from_id(id); + Scene *scene= (Scene *)id; + + /* do compositing nodes first (since these aren't included in main tree) */ + if (scene->nodetree) { + AnimData *adt2= BKE_animdata_from_id((ID *)scene->nodetree); + if(adt2) func(id, adt2, user_data); + } + + /* now fix scene animation data as per normal */ + if(adt) func((ID *)id, adt, user_data); + } +} + /* Fix all RNA-Paths throughout the database (directly access the Global.main version) * NOTE: it is assumed that the structure we're replacing is <["><"]> * i.e. pose.bones["Bone"] */ +/* TODO: use BKE_animdata_main_cb for looping over all data */ void BKE_all_animdata_fix_paths_rename (char *prefix, char *oldName, char *newName) { Main *mainptr= G.main; diff --git a/source/blender/blenkernel/intern/library.c b/source/blender/blenkernel/intern/library.c index 4b6257b8b18..8512b6315e1 100644 --- a/source/blender/blenkernel/intern/library.c +++ b/source/blender/blenkernel/intern/library.c @@ -698,6 +698,30 @@ void set_free_windowmanager_cb(void (*func)(bContext *C, wmWindowManager *) ) free_windowmanager_cb= func; } +void animdata_dtar_clear_cb(ID *id, AnimData *adt, void *userdata) +{ + ChannelDriver *driver; + FCurve *fcu; + + /* find the driver this belongs to and update it */ + for (fcu=adt->drivers.first; fcu; fcu=fcu->next) { + driver= fcu->driver; + + if (driver) { + DriverVar *dvar; + for (dvar= driver->variables.first; dvar; dvar= dvar->next) { + DriverTarget *dtar= &dvar->targets[0]; + int tarIndex= 0; + for (; tarIndex < MAX_DRIVER_TARGETS; tarIndex++, dtar++) { + if(dtar->id == userdata) + dtar->id= NULL; + } + } + } + } +} + + /* used in headerbuttons.c image.c mesh.c screen.c sound.c and library.c */ void free_libblock(ListBase *lb, void *idv) { @@ -798,9 +822,13 @@ void free_libblock(ListBase *lb, void *idv) IDP_FreeProperty(id->properties); MEM_freeN(id->properties); } - BLI_remlink(lb, id); - MEM_freeN(id); + BLI_remlink(lb, id); + + /* this ID may be a driver target! */ + BKE_animdata_main_cb(G.main, animdata_dtar_clear_cb, (void *)id); + + MEM_freeN(id); } void free_libblock_us(ListBase *lb, void *idv) /* test users */