Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--source/blender/editors/armature/armature_relations.c73
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);
}
}