[Bf-blender-cvs] [99a5f37] master: WIP: Attempt to get driver links remapped correctly when joining armatures

Joshua Leung noreply at git.blender.org
Thu Jan 22 14:35:58 CET 2015


Commit: 99a5f376a21099a1cacb611482d1889e9e627923
Author: Joshua Leung
Date:   Thu Jan 22 22:04:16 2015 +1300
Branches: master
https://developer.blender.org/rB99a5f376a21099a1cacb611482d1889e9e627923

WIP: Attempt to get driver links remapped correctly when joining armatures

Now, RNA Paths and driver targets get corrected, but at the expense of this
always happening (i.e. even for those affecting drivers which existed before).

===================================================================

M	source/blender/editors/armature/armature_relations.c

===================================================================

diff --git a/source/blender/editors/armature/armature_relations.c b/source/blender/editors/armature/armature_relations.c
index 38e3588..155267a 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);
 		}
 	}




More information about the Bf-blender-cvs mailing list