Merging r46111 through r46136 from trunk into soc-2011-tomato
[blender-staging.git] / source / blender / editors / armature / poseUtils.c
index c9a803180506705932ec78d08a49f174de5a0530..3c855ff96e664694d75e228e9dff38eff7aabffa 100644 (file)
@@ -1,6 +1,4 @@
-/**
- * $Id$
- *
+/*
  * ***** BEGIN GPL LICENSE BLOCK *****
  *
  * This program is free software; you can redistribute it and/or
  * ***** END GPL LICENSE BLOCK *****
  */
 
+/** \file blender/editors/armature/poseUtils.c
+ *  \ingroup edarmature
+ */
+
+
 #include <stdlib.h>
 #include <stdio.h>
 #include <stddef.h>
 #include "BLI_blenlib.h"
 #include "BLI_dynstr.h"
 #include "BLI_dlrbTree.h"
+#include "BLI_utildefines.h"
 
 #include "DNA_anim_types.h"
 #include "DNA_armature_types.h"
 #include "DNA_object_types.h"
 #include "DNA_scene_types.h"
 
-#include "BKE_animsys.h"
 #include "BKE_action.h"
 #include "BKE_armature.h"
 #include "BKE_depsgraph.h"
-#include "BKE_fcurve.h"
-#include "BKE_object.h"
+#include "BKE_idprop.h"
 
-#include "BKE_global.h"
 #include "BKE_context.h"
-#include "BKE_report.h"
-#include "BKE_utildefines.h"
 
 #include "RNA_access.h"
 
@@ -62,7 +61,6 @@
 #include "WM_types.h"
 
 
-#include "BIF_gl.h"
 
 #include "ED_armature.h"
 #include "ED_keyframing.h"
@@ -113,31 +111,46 @@ static void fcurves_to_pchan_links_get (ListBase *pfLinks, Object *ob, bAction *
                        pchan->flag |= POSE_SIZE;
                        
                /* store current transforms */
-               // TODO: store axis-angle too?
-               VECCOPY(pfl->oldloc, pchan->loc);
-               VECCOPY(pfl->oldrot, pchan->eul);
-               VECCOPY(pfl->oldscale, pchan->size);
-               QUATCOPY(pfl->oldquat, pchan->quat);
+               copy_v3_v3(pfl->oldloc, pchan->loc);
+               copy_v3_v3(pfl->oldrot, pchan->eul);
+               copy_v3_v3(pfl->oldscale, pchan->size);
+               copy_qt_qt(pfl->oldquat, pchan->quat);
+               copy_v3_v3(pfl->oldaxis, pchan->rotAxis);
+               pfl->oldangle = pchan->rotAngle;
+               
+               /* make copy of custom properties */
+               if (pchan->prop && (transFlags & ACT_TRANS_PROP))
+                       pfl->oldprops = IDP_CopyProperty(pchan->prop);
        }
 } 
 
 
 /* get sets of F-Curves providing transforms for the bones in the Pose  */
-// TODO: separate the inner workings out to another helper func, since we need option of whether to take selected or visible bones...
-void poseAnim_mapping_get (bContext *C, ListBase *pfLinks, Object *ob, bAction *act)
+void poseAnim_mapping_get(bContext *C, ListBase *pfLinks, Object *ob, bAction *act)
 {      
        /* for each Pose-Channel which gets affected, get the F-Curves for that channel 
         * and set the relevant transform flags...
         */
-       CTX_DATA_BEGIN(C, bPoseChannel*, pchan, selected_pose_bones) 
+       CTX_DATA_BEGIN (C, bPoseChannel*, pchan, selected_pose_bones)
        {
                fcurves_to_pchan_links_get(pfLinks, ob, act, pchan);
        }
        CTX_DATA_END;
+       
+       /* if no PoseChannels were found, try a second pass, doing visible ones instead
+        * i.e. if nothing selected, do whole pose
+        */
+       if (pfLinks->first == NULL) {
+               CTX_DATA_BEGIN (C, bPoseChannel*, pchan, visible_pose_bones)
+               {
+                       fcurves_to_pchan_links_get(pfLinks, ob, act, pchan);
+               }
+               CTX_DATA_END;
+       }
 }
 
 /* free F-Curve <-> PoseChannel links  */
-void poseAnim_mapping_free (ListBase *pfLinks)
+void poseAnim_mapping_free(ListBase *pfLinks)
 {
        tPChanFCurveLink *pfl, *pfln=NULL;
                
@@ -145,6 +158,12 @@ void poseAnim_mapping_free (ListBase *pfLinks)
        for (pfl= pfLinks->first; pfl; pfl= pfln) {
                pfln= pfl->next;
                
+               /* free custom properties */
+               if (pfl->oldprops) {
+                       IDP_FreeProperty(pfl->oldprops);
+                       MEM_freeN(pfl->oldprops);
+               }
+               
                /* free list of F-Curve reference links */
                BLI_freelistN(&pfl->fcurves);
                
@@ -159,7 +178,7 @@ void poseAnim_mapping_free (ListBase *pfLinks)
 /* ------------------------- */
 
 /* helper for apply() / reset() - refresh the data */
-void poseAnim_mapping_refresh (bContext *C, Scene *scene, Object *ob)
+void poseAnim_mapping_refresh(bContext *C, Scene *scene, Object *ob)
 {
        bArmature *arm= (bArmature *)ob->data;
        
@@ -168,7 +187,7 @@ void poseAnim_mapping_refresh (bContext *C, Scene *scene, Object *ob)
         */
        // FIXME: shouldn't this use the builtin stuff?
        if ((arm->flag & ARM_DELAYDEFORM)==0)
-               DAG_id_flush_update(&ob->id, OB_RECALC_DATA);  /* sets recalc flags */
+               DAG_id_tag_update(&ob->id, OB_RECALC_DATA);  /* sets recalc flags */
        else
                where_is_pose(scene, ob);
        
@@ -177,7 +196,7 @@ void poseAnim_mapping_refresh (bContext *C, Scene *scene, Object *ob)
 }
 
 /* reset changes made to current pose */
-void poseAnim_mapping_reset (ListBase *pfLinks)
+void poseAnim_mapping_reset(ListBase *pfLinks)
 {
        tPChanFCurveLink *pfl;
        
@@ -186,58 +205,54 @@ void poseAnim_mapping_reset (ListBase *pfLinks)
                bPoseChannel *pchan= pfl->pchan;
                
                /* just copy all the values over regardless of whether they changed or not */
-               // TODO; include axis-angle here too?
-               VECCOPY(pchan->loc, pfl->oldloc);
-               VECCOPY(pchan->eul, pfl->oldrot);
-               VECCOPY(pchan->size, pfl->oldscale);
-               QUATCOPY(pchan->quat, pfl->oldquat);
+               copy_v3_v3(pchan->loc, pfl->oldloc);
+               copy_v3_v3(pchan->eul, pfl->oldrot);
+               copy_v3_v3(pchan->size, pfl->oldscale);
+               copy_qt_qt(pchan->quat, pfl->oldquat);
+               copy_v3_v3(pchan->rotAxis, pfl->oldaxis);
+               pchan->rotAngle = pfl->oldangle;
+               
+               /* just overwrite values of properties from the stored copies (there should be some) */
+               if (pfl->oldprops)
+                       IDP_SyncGroupValues(pfl->pchan->prop, pfl->oldprops);
        }
 }
 
 /* perform autokeyframing after changes were made + confirmed */
-void poseAnim_mapping_autoKeyframe (bContext *C, Scene *scene, Object *ob, ListBase *pfLinks, float cframe)
+void poseAnim_mapping_autoKeyframe(bContext *C, Scene *scene, Object *ob, ListBase *pfLinks, float cframe)
 {
-       static short keyingsets_need_init = 1;
-       static KeyingSet *ks_loc = NULL;
-       static KeyingSet *ks_rot = NULL;
-       static KeyingSet *ks_scale = NULL;
-       
-       /* get keyingsets the first time this is run? 
-        * NOTE: it should be safe to store these static, since they're currently builtin ones
-        * but maybe later this may change, in which case this code needs to be revised!
-        */
-       if (keyingsets_need_init) {
-               ks_loc= ANIM_builtin_keyingset_get_named(NULL, "Location");
-               ks_rot= ANIM_builtin_keyingset_get_named(NULL, "Rotation");
-               ks_scale= ANIM_builtin_keyingset_get_named(NULL, "Scaling");
-               
-               keyingsets_need_init = 0;
-       }
-       
        /* insert keyframes as necessary if autokeyframing */
        if (autokeyframe_cfra_can_key(scene, &ob->id)) {
+               KeyingSet *ks = ANIM_get_keyingset_for_autokeying(scene, ANIM_KS_WHOLE_CHARACTER_ID);
+               ListBase dsources = {NULL, NULL};
                tPChanFCurveLink *pfl;
                
-               /* iterate over each pose-channel affected, applying the changes */
+               /* iterate over each pose-channel affected, tagging bones to be keyed */
+               /* XXX: here we already have the information about what transforms exist, though 
+                * it might be easier to just overwrite all using normal mechanisms
+                */
                for (pfl= pfLinks->first; pfl; pfl= pfl->next) {
-                       ListBase dsources = {NULL, NULL};
                        bPoseChannel *pchan= pfl->pchan;
                        
-                       /* add datasource override for the PoseChannel so KeyingSet will do right thing */
+                       /* add datasource override for the PoseChannel, to be used later */
                        ANIM_relative_keyingset_add_source(&dsources, &ob->id, &RNA_PoseBone, pchan); 
                        
-                       /* insert keyframes 
-                        *      - these keyingsets here use dsources, since we need to specify exactly which keyframes get affected
-                        */
-                       if (pchan->flag & POSE_LOC)
-                               ANIM_apply_keyingset(C, &dsources, NULL, ks_loc, MODIFYKEY_MODE_INSERT, cframe);
-                       if (pchan->flag & POSE_ROT)
-                               ANIM_apply_keyingset(C, &dsources, NULL, ks_rot, MODIFYKEY_MODE_INSERT, cframe);
-                       if (pchan->flag & POSE_SIZE)
-                               ANIM_apply_keyingset(C, &dsources, NULL, ks_scale, MODIFYKEY_MODE_INSERT, cframe);
-                               
-                       /* free the temp info */
-                       BLI_freelistN(&dsources);
+                       /* clear any unkeyed tags */
+                       if (pchan->bone)
+                               pchan->bone->flag &= ~BONE_UNKEYED;
+               }
+               
+               /* insert keyframes for all relevant bones in one go */
+               ANIM_apply_keyingset(C, &dsources, NULL, ks, MODIFYKEY_MODE_INSERT, cframe);
+               BLI_freelistN(&dsources);
+               
+               /* do the bone paths
+                *      - only do this if keyframes should have been added
+                *      - do not calculate unless there are paths already to update...
+                */
+               if (C && (ob->pose->avs.path_bakeflag & MOTIONPATH_BAKE_HAS_PATHS)) {
+                       //ED_pose_clear_paths(C, ob); // XXX for now, don't need to clear
+                       ED_pose_recalculate_paths(scene, ob);
                }
        }
 }
@@ -247,7 +262,7 @@ void poseAnim_mapping_autoKeyframe (bContext *C, Scene *scene, Object *ob, ListB
 /* find the next F-Curve for a PoseChannel with matching path... 
  *     - path is not just the pfl rna_path, since that path doesn't have property info yet
  */
-LinkData *poseAnim_mapping_getNextFCurve (ListBase *fcuLinks, LinkData *prev, char *path)
+LinkData *poseAnim_mapping_getNextFCurve (ListBase *fcuLinks, LinkData *prev, const char *path)
 {
        LinkData *first= (prev)? prev->next : (fcuLinks)? fcuLinks->first : NULL;
        LinkData *ld;