diff options
-rw-r--r-- | source/blender/editors/armature/armature_relations.c | 73 |
1 files changed, 70 insertions, 3 deletions
diff --git a/source/blender/editors/armature/armature_relations.c b/source/blender/editors/armature/armature_relations.c index 38e3588f267..155267af370 100644 --- a/source/blender/editors/armature/armature_relations.c +++ b/source/blender/editors/armature/armature_relations.c @@ -29,6 +29,8 @@ * \ingroup edarmature */ +#include "MEM_guardedalloc.h" + #include "DNA_anim_types.h" #include "DNA_armature_types.h" #include "DNA_constraint_types.h" @@ -36,6 +38,7 @@ #include "DNA_scene_types.h" #include "BLI_blenlib.h" +#include "BLI_ghash.h" #include "BLI_math.h" #include "BLF_translation.h" @@ -45,6 +48,7 @@ #include "BKE_constraint.h" #include "BKE_context.h" #include "BKE_depsgraph.h" +#include "BKE_fcurve.h" #include "BKE_global.h" #include "BKE_main.h" #include "BKE_report.h" @@ -111,15 +115,66 @@ static void joined_armature_fix_links_constraints( } } +/* userdata for joined_armature_fix_animdata_cb() */ +typedef struct tJoinArmature_AdtFixData { + Object *srcArm; + Object *tarArm; + + GHash *names_map; +} tJoinArmature_AdtFixData; + +/* Callback to pass to void BKE_animdata_main_cb() for fixing driver ID's to point to the new ID */ +static void joined_armature_fix_animdata_cb(ID *id, AnimData *adt, void *user_data) +{ + tJoinArmature_AdtFixData *afd = (tJoinArmature_AdtFixData *)user_data; + ID *src_id = &afd->srcArm->id; + ID *dst_id = &afd->tarArm->id; + + GHashIterator gh_iter; + FCurve *fcu; + + /* Fix paths - Unless we duplicate the logic, we're going to have to do it this way */ + // FIXME: this is too crude... it just does everything! + GHASH_ITER(gh_iter, afd->names_map) { + const char *old_name = BLI_ghashIterator_getKey(&gh_iter); + const char *new_name = BLI_ghashIterator_getValue(&gh_iter); + + /* only remap if changed; this still means there will be some waste if there aren't many drivers/keys */ + if (strcmp(old_name, new_name)) { + // XXX: ref_id == ??? (the point of this seems really vague) + BKE_animdata_fix_paths_rename(id, adt, src_id, "pose.bones", old_name, new_name, 0, 0, false); + } + } + + /* Drivers */ + for (fcu = adt->drivers.first; fcu; fcu = fcu->next) { + ChannelDriver *driver = fcu->driver; + DriverVar *dvar; + + /* fix driver references to invalid ID's */ + for (dvar = driver->variables.first; dvar; dvar = dvar->next) { + /* only change the used targets, since the others will need fixing manually anyway */ + DRIVER_TARGETS_USED_LOOPER(dvar) + { + /* change the ID's used... */ + if (dtar->id == src_id) { + dtar->id = dst_id; + } + } + DRIVER_TARGETS_LOOPER_END + } + } +} + /* Helper function for armature joining - link fixing */ -static void joined_armature_fix_links(Object *tarArm, Object *srcArm, bPoseChannel *pchan, EditBone *curbone) +static void joined_armature_fix_links(Main *bmain, Object *tarArm, Object *srcArm, bPoseChannel *pchan, EditBone *curbone) { Object *ob; bPose *pose; bPoseChannel *pchant; /* let's go through all objects in database */ - for (ob = G.main->object.first; ob; ob = ob->id.next) { + for (ob = bmain->object.first; ob; ob = ob->id.next) { /* do some object-type specific things */ if (ob->type == OB_ARMATURE) { pose = ob->pose; @@ -193,11 +248,17 @@ int join_armature_exec(bContext *C, wmOperator *op) CTX_DATA_BEGIN(C, Base *, base, selected_editable_bases) { if ((base->object->type == OB_ARMATURE) && (base->object != ob)) { + tJoinArmature_AdtFixData afd = {NULL}; bArmature *curarm = base->object->data; /* we assume that each armature datablock is only used in a single place */ BLI_assert(ob->data != base->object->data); + /* init callback data for fixing up AnimData links later */ + afd.srcArm = base->object; + afd.tarArm = ob; + afd.names_map = BLI_ghash_str_new("join_armature_adt_fix"); + /* copy over animdata first, so that the link fixing can access and fix the links */ if (base->object->adt) { if (ob->adt == NULL) { @@ -241,6 +302,7 @@ int join_armature_exec(bContext *C, wmOperator *op) /* Get new name */ unique_editbone_name(arm->edbo, curbone->name, NULL); + BLI_ghash_insert(afd.names_map, BLI_strdup(pchan->name), curbone->name); /* Transform the bone */ { @@ -271,7 +333,7 @@ int join_armature_exec(bContext *C, wmOperator *op) } /* Fix Constraints and Other Links to this Bone and Armature */ - joined_armature_fix_links(ob, base->object, pchan, curbone); + joined_armature_fix_links(bmain, ob, base->object, pchan, curbone); /* Rename pchan */ BLI_strncpy(pchan->name, curbone->name, sizeof(pchan->name)); @@ -286,6 +348,11 @@ int join_armature_exec(bContext *C, wmOperator *op) BKE_pose_channels_hash_free(pose); } + /* Fix all the drivers (and animation data) */ + BKE_animdata_main_cb(bmain, joined_armature_fix_animdata_cb, &afd); + BLI_ghash_free(afd.names_map, MEM_freeN, NULL); + + /* Free the old object data */ ED_base_object_free_and_unlink(bmain, scene, base); } } |