Commit: 3df93d063e2d52a2c2e73cfe31801c15682bf0b4
Author: Joshua Leung
Date:   Thu Jan 22 02:08:29 2015 +1300
Branches: master
https://developer.blender.org/rB3df93d063e2d52a2c2e73cfe31801c15682bf0b4

Fix: Joining armatures loses drivers

Currently, when joining two armatures, the drivers of the armatures being merged
in are lost. This commit introduces a new AnimData API function for merging
animation data into another AnimData block.

NOTE:
* For now, this only copies the drivers over. As a result, manual effort will
  still be needed to go through and fix the drivers.

  I am working on automating that process, but it's more important that the
  drivers don't have to be created from scratch for now (since this is needed
  for the Goosberry rigging work).

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

M       source/blender/blenkernel/BKE_animsys.h
M       source/blender/blenkernel/intern/anim_sys.c
M       source/blender/editors/armature/armature_naming.c
M       source/blender/editors/armature/armature_relations.c

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

diff --git a/source/blender/blenkernel/BKE_animsys.h 
b/source/blender/blenkernel/BKE_animsys.h
index a5109ac..24abd11 100644
--- a/source/blender/blenkernel/BKE_animsys.h
+++ b/source/blender/blenkernel/BKE_animsys.h
@@ -73,6 +73,20 @@ bool BKE_copy_animdata_id(struct ID *id_to, struct ID 
*id_from, const bool do_ac
 /* Copy AnimData Actions */
 void BKE_copy_animdata_id_action(struct ID *id);
 
+/* Merge copies of data from source AnimData block */
+typedef enum eAnimData_MergeCopy_Modes {
+       /* Keep destination action */
+       ADT_MERGECOPY_KEEP_DST = 0,
+       
+       /* Use src action (make a new copy) */
+       ADT_MERGECOPY_SRC_COPY = 1,
+       
+       /* Use src action (but just reference the existing version) */
+       ADT_MERGECOPY_SRC_REF  = 2
+} eAnimData_MergeCopy_Modes;
+
+void BKE_animdata_merge_copy(struct ID *dst_id, struct ID *src_id, 
eAnimData_MergeCopy_Modes action_mode, bool fix_drivers);
+
 /* Make Local */
 void BKE_animdata_make_local(struct AnimData *adt);
 
diff --git a/source/blender/blenkernel/intern/anim_sys.c 
b/source/blender/blenkernel/intern/anim_sys.c
index 8e36449..00e5c1b 100644
--- a/source/blender/blenkernel/intern/anim_sys.c
+++ b/source/blender/blenkernel/intern/anim_sys.c
@@ -318,6 +318,77 @@ void BKE_copy_animdata_id_action(ID *id)
        }
 }
 
+/* Merge copies of the data from the src AnimData into the destination 
AnimData */
+void BKE_animdata_merge_copy(ID *dst_id, ID *src_id, eAnimData_MergeCopy_Modes 
action_mode, bool fix_drivers)
+{
+       AnimData *src = BKE_animdata_from_id(src_id);
+       AnimData *dst = BKE_animdata_from_id(dst_id);
+       
+       /* sanity checks */
+       if (ELEM(NULL, dst, src))
+               return;
+               
+       // TODO: we must unset all "tweakmode" flags
+       if ((src->flag & ADT_NLA_EDIT_ON) || (dst->flag & ADT_NLA_EDIT_ON)) {
+               printf("ERROR: Merging AnimData blocks while editing NLA is 
dangerous as it may cause data corruption\n");
+               return;
+       }
+       
+       /* handle actions... */
+       if (action_mode == ADT_MERGECOPY_SRC_COPY) {
+               /* make a copy of the actions */
+               dst->action = BKE_action_copy(src->action);
+               dst->tmpact = BKE_action_copy(src->tmpact);
+       }
+       else if (action_mode == ADT_MERGECOPY_SRC_REF) {
+               /* make a reference to it */
+               dst->action = src->action;
+               id_us_plus((ID *)dst->action);
+               
+               dst->tmpact = src->tmpact;
+               id_us_plus((ID *)dst->tmpact);
+       }
+       
+       /* duplicate NLA data */
+       if (src->nla_tracks.first) {
+               ListBase tracks = {NULL, NULL};
+               
+               copy_nladata(&tracks, &src->nla_tracks);
+               BLI_movelisttolist(&dst->nla_tracks, &tracks);
+       }
+       
+       /* duplicate drivers (F-Curves) */
+       if (src->drivers.first) {
+               ListBase drivers = {NULL, NULL};
+               
+               copy_fcurves(&drivers, &src->drivers);
+               
+               /* Fix up all driver targets using the old target id
+                * - This assumes that the src ID is being merged into the dst 
ID
+                */
+               if (fix_drivers) {
+                       FCurve *fcu;
+                       
+                       for (fcu = drivers.first; fcu; fcu = fcu->next) {
+                               ChannelDriver *driver = fcu->driver;
+                               DriverVar *dvar;
+                               
+                               for (dvar = driver->variables.first; dvar; dvar 
= dvar->next) {
+                                       DRIVER_TARGETS_USED_LOOPER(dvar)
+                                       {
+                                               if (dtar->id == src_id) {
+                                                       dtar->id = dst_id;
+                                               }
+                                       }
+                                       DRIVER_TARGETS_LOOPER_END
+                               }
+                       }
+               }
+               
+               BLI_movelisttolist(&dst->drivers, &drivers);
+       }
+}
+
 /* Make Local -------------------------------------------- */
 
 static void make_local_strips(ListBase *strips)
diff --git a/source/blender/editors/armature/armature_naming.c 
b/source/blender/editors/armature/armature_naming.c
index 9afc459..f984bf0 100644
--- a/source/blender/editors/armature/armature_naming.c
+++ b/source/blender/editors/armature/armature_naming.c
@@ -267,6 +267,7 @@ void ED_armature_bone_rename(bArmature *arm, const char 
*oldnamep, const char *n
                /* Fix all animdata that may refer to this bone - we can't just 
do the ones attached to objects, since
                 * other ID-blocks may have drivers referring to this bone 
[#29822]
                 */
+               // XXX: the ID here is for armatures, but most bone drivers are 
actually on the object instead...
                {
                        
                        BKE_all_animdata_fix_paths_rename(&arm->id, 
"pose.bones", oldname, newname);
diff --git a/source/blender/editors/armature/armature_relations.c 
b/source/blender/editors/armature/armature_relations.c
index 3e226c3..2a19d7a 100644
--- a/source/blender/editors/armature/armature_relations.c
+++ b/source/blender/editors/armature/armature_relations.c
@@ -40,6 +40,7 @@
 #include "BLF_translation.h"
 
 #include "BKE_action.h"
+#include "BKE_animsys.h"
 #include "BKE_constraint.h"
 #include "BKE_context.h"
 #include "BKE_depsgraph.h"
@@ -200,6 +201,33 @@ int join_armature_exec(bContext *C, wmOperator *op)
                if ((base->object->type == OB_ARMATURE) && (base->object != 
ob)) {
                        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);
+                       
+                       /* copy over animdata first, so that the link fixing 
can access and fix the links */
+                       if (base->object->adt) {
+                               if (ob->adt == NULL) {
+                                       /* no animdata, so just use a copy of 
the whole thing */
+                                       ob->adt = 
BKE_copy_animdata(base->object->adt, false);
+                               }
+                               else {
+                                       /* merge in data - we'll fix the 
drivers manually */
+                                       BKE_animdata_merge_copy(&ob->id, 
&base->object->id, ADT_MERGECOPY_KEEP_DST, false);
+                               }
+                       }
+                       
+                       if (curarm->adt) {
+                               if (arm->adt == NULL) {
+                                       /* no animdata, so just use a copy of 
the whole thing */
+                                       arm->adt = 
BKE_copy_animdata(curarm->adt, false);
+                               }
+                               else {
+                                       /* merge in data - we'll fix the 
drivers manually */
+                                       BKE_animdata_merge_copy(&arm->id, 
&curarm->id, ADT_MERGECOPY_KEEP_DST, false);
+                               }
+                       }
+                       
+                       
                        /* Make a list of editbones in current armature */
                        ED_armature_to_edit(base->object->data);

_______________________________________________
Bf-blender-cvs mailing list
Bf-blender-cvs@blender.org
http://lists.blender.org/mailman/listinfo/bf-blender-cvs

Reply via email to