Blender V2.61 - r43446

poseUtils.c

Go to the documentation of this file.
00001 /*
00002  * ***** BEGIN GPL LICENSE BLOCK *****
00003  *
00004  * This program is free software; you can redistribute it and/or
00005  * modify it under the terms of the GNU General Public License
00006  * as published by the Free Software Foundation; either version 2
00007  * of the License, or (at your option) any later version.
00008  *
00009  * This program is distributed in the hope that it will be useful,
00010  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00011  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012  * GNU General Public License for more details.
00013  *
00014  * You should have received a copy of the GNU General Public License
00015  * along with this program; if not, write to the Free Software Foundation,
00016  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
00017  *
00018  * The Original Code is Copyright (C) 2009, Blender Foundation, Joshua Leung
00019  * This is a new part of Blender
00020  *
00021  * Contributor(s): Joshua Leung
00022  *
00023  * ***** END GPL LICENSE BLOCK *****
00024  */
00025 
00031 #include <stdlib.h>
00032 #include <stdio.h>
00033 #include <stddef.h>
00034 #include <string.h>
00035 #include <math.h>
00036 #include <float.h>
00037 
00038 #include "MEM_guardedalloc.h"
00039 
00040 #include "BLI_math.h"
00041 #include "BLI_blenlib.h"
00042 #include "BLI_dynstr.h"
00043 #include "BLI_dlrbTree.h"
00044 #include "BLI_utildefines.h"
00045 
00046 #include "DNA_anim_types.h"
00047 #include "DNA_armature_types.h"
00048 #include "DNA_object_types.h"
00049 #include "DNA_scene_types.h"
00050 
00051 #include "BKE_action.h"
00052 #include "BKE_armature.h"
00053 #include "BKE_depsgraph.h"
00054 #include "BKE_idprop.h"
00055 
00056 #include "BKE_context.h"
00057 
00058 #include "RNA_access.h"
00059 
00060 #include "WM_api.h"
00061 #include "WM_types.h"
00062 
00063 
00064 
00065 #include "ED_armature.h"
00066 #include "ED_keyframing.h"
00067 
00068 #include "armature_intern.h"
00069 
00070 /* *********************************************** */
00071 /* Contents of this File:
00072  *
00073  * This file contains methods shared between Pose Slide and Pose Lib;
00074  * primarily the functions in question concern Animato <-> Pose 
00075  * convenience functions, such as applying/getting pose values
00076  * and/or inserting keyframes for these.
00077  */
00078 /* *********************************************** */ 
00079 /* FCurves <-> PoseChannels Links */
00080 
00081 /* helper for poseAnim_mapping_get() -> get the relevant F-Curves per PoseChannel */
00082 static void fcurves_to_pchan_links_get (ListBase *pfLinks, Object *ob, bAction *act, bPoseChannel *pchan)
00083 {
00084     ListBase curves = {NULL, NULL};
00085     int transFlags = action_get_item_transforms(act, ob, pchan, &curves);
00086     
00087     pchan->flag &= ~(POSE_LOC|POSE_ROT|POSE_SIZE);
00088     
00089     /* check if any transforms found... */
00090     if (transFlags) {
00091         /* make new linkage data */
00092         tPChanFCurveLink *pfl= MEM_callocN(sizeof(tPChanFCurveLink), "tPChanFCurveLink");
00093         PointerRNA ptr;
00094         
00095         pfl->fcurves= curves;
00096         pfl->pchan= pchan;
00097         
00098         /* get the RNA path to this pchan - this needs to be freed! */
00099         RNA_pointer_create((ID *)ob, &RNA_PoseBone, pchan, &ptr);
00100         pfl->pchan_path= RNA_path_from_ID_to_struct(&ptr);
00101         
00102         /* add linkage data to operator data */
00103         BLI_addtail(pfLinks, pfl);
00104         
00105         /* set pchan's transform flags */
00106         if (transFlags & ACT_TRANS_LOC)
00107             pchan->flag |= POSE_LOC;
00108         if (transFlags & ACT_TRANS_ROT)
00109             pchan->flag |= POSE_ROT;
00110         if (transFlags & ACT_TRANS_SCALE)
00111             pchan->flag |= POSE_SIZE;
00112             
00113         /* store current transforms */
00114         copy_v3_v3(pfl->oldloc, pchan->loc);
00115         copy_v3_v3(pfl->oldrot, pchan->eul);
00116         copy_v3_v3(pfl->oldscale, pchan->size);
00117         copy_qt_qt(pfl->oldquat, pchan->quat);
00118         copy_v3_v3(pfl->oldaxis, pchan->rotAxis);
00119         pfl->oldangle = pchan->rotAngle;
00120         
00121         /* make copy of custom properties */
00122         if (pchan->prop && (transFlags & ACT_TRANS_PROP))
00123             pfl->oldprops = IDP_CopyProperty(pchan->prop);
00124     }
00125 } 
00126 
00127 
00128 /* get sets of F-Curves providing transforms for the bones in the Pose  */
00129 void poseAnim_mapping_get (bContext *C, ListBase *pfLinks, Object *ob, bAction *act)
00130 {   
00131     /* for each Pose-Channel which gets affected, get the F-Curves for that channel 
00132      * and set the relevant transform flags...
00133      */
00134     CTX_DATA_BEGIN(C, bPoseChannel*, pchan, selected_pose_bones) 
00135     {
00136         fcurves_to_pchan_links_get(pfLinks, ob, act, pchan);
00137     }
00138     CTX_DATA_END;
00139     
00140     /* if no PoseChannels were found, try a second pass, doing visible ones instead
00141      * i.e. if nothing selected, do whole pose
00142      */
00143     if (pfLinks->first == NULL) {
00144         CTX_DATA_BEGIN(C, bPoseChannel*, pchan, visible_pose_bones)
00145         {
00146             fcurves_to_pchan_links_get(pfLinks, ob, act, pchan);
00147         }
00148         CTX_DATA_END;
00149     }
00150 }
00151 
00152 /* free F-Curve <-> PoseChannel links  */
00153 void poseAnim_mapping_free (ListBase *pfLinks)
00154 {
00155     tPChanFCurveLink *pfl, *pfln=NULL;
00156         
00157     /* free the temp pchan links and their data */
00158     for (pfl= pfLinks->first; pfl; pfl= pfln) {
00159         pfln= pfl->next;
00160         
00161         /* free custom properties */
00162         if (pfl->oldprops) {
00163             IDP_FreeProperty(pfl->oldprops);
00164             MEM_freeN(pfl->oldprops);
00165         }
00166         
00167         /* free list of F-Curve reference links */
00168         BLI_freelistN(&pfl->fcurves);
00169         
00170         /* free pchan RNA Path */
00171         MEM_freeN(pfl->pchan_path);
00172         
00173         /* free link itself */
00174         BLI_freelinkN(pfLinks, pfl);
00175     }
00176 }
00177 
00178 /* ------------------------- */
00179 
00180 /* helper for apply() / reset() - refresh the data */
00181 void poseAnim_mapping_refresh (bContext *C, Scene *scene, Object *ob)
00182 {
00183     bArmature *arm= (bArmature *)ob->data;
00184     
00185     /* old optimize trick... this enforces to bypass the depgraph 
00186      *  - note: code copied from transform_generics.c -> recalcData()
00187      */
00188     // FIXME: shouldn't this use the builtin stuff?
00189     if ((arm->flag & ARM_DELAYDEFORM)==0)
00190         DAG_id_tag_update(&ob->id, OB_RECALC_DATA);  /* sets recalc flags */
00191     else
00192         where_is_pose(scene, ob);
00193     
00194     /* note, notifier might evolve */
00195     WM_event_add_notifier(C, NC_OBJECT|ND_POSE, ob);
00196 }
00197 
00198 /* reset changes made to current pose */
00199 void poseAnim_mapping_reset (ListBase *pfLinks)
00200 {
00201     tPChanFCurveLink *pfl;
00202     
00203     /* iterate over each pose-channel affected, restoring all channels to their original values */
00204     for (pfl= pfLinks->first; pfl; pfl= pfl->next) {
00205         bPoseChannel *pchan= pfl->pchan;
00206         
00207         /* just copy all the values over regardless of whether they changed or not */
00208         copy_v3_v3(pchan->loc, pfl->oldloc);
00209         copy_v3_v3(pchan->eul, pfl->oldrot);
00210         copy_v3_v3(pchan->size, pfl->oldscale);
00211         copy_qt_qt(pchan->quat, pfl->oldquat);
00212         copy_v3_v3(pchan->rotAxis, pfl->oldaxis);
00213         pchan->rotAngle = pfl->oldangle;
00214         
00215         /* just overwrite values of properties from the stored copies (there should be some) */
00216         if (pfl->oldprops)
00217             IDP_SyncGroupValues(pfl->pchan->prop, pfl->oldprops);
00218     }
00219 }
00220 
00221 /* perform autokeyframing after changes were made + confirmed */
00222 void poseAnim_mapping_autoKeyframe (bContext *C, Scene *scene, Object *ob, ListBase *pfLinks, float cframe)
00223 {
00224     /* insert keyframes as necessary if autokeyframing */
00225     if (autokeyframe_cfra_can_key(scene, &ob->id)) {
00226         KeyingSet *ks = ANIM_get_keyingset_for_autokeying(scene, ANIM_KS_WHOLE_CHARACTER_ID);
00227         ListBase dsources = {NULL, NULL};
00228         tPChanFCurveLink *pfl;
00229         
00230         /* iterate over each pose-channel affected, tagging bones to be keyed */
00231         /* XXX: here we already have the information about what transforms exist, though 
00232          * it might be easier to just overwrite all using normal mechanisms
00233          */
00234         for (pfl= pfLinks->first; pfl; pfl= pfl->next) {
00235             bPoseChannel *pchan= pfl->pchan;
00236             
00237             /* add datasource override for the PoseChannel, to be used later */
00238             ANIM_relative_keyingset_add_source(&dsources, &ob->id, &RNA_PoseBone, pchan); 
00239             
00240             /* clear any unkeyed tags */
00241             if (pchan->bone)
00242                 pchan->bone->flag &= ~BONE_UNKEYED;
00243         }
00244         
00245         /* insert keyframes for all relevant bones in one go */
00246         ANIM_apply_keyingset(C, &dsources, NULL, ks, MODIFYKEY_MODE_INSERT, cframe);
00247         BLI_freelistN(&dsources);
00248         
00249         /* do the bone paths
00250          *  - only do this if keyframes should have been added
00251          *  - do not calculate unless there are paths already to update...
00252          */
00253         if (C && (ob->pose->avs.path_bakeflag & MOTIONPATH_BAKE_HAS_PATHS)) {
00254             //ED_pose_clear_paths(C, ob); // XXX for now, don't need to clear
00255             ED_pose_recalculate_paths(scene, ob);
00256         }
00257     }
00258 }
00259 
00260 /* ------------------------- */
00261 
00262 /* find the next F-Curve for a PoseChannel with matching path... 
00263  *  - path is not just the pfl rna_path, since that path doesn't have property info yet
00264  */
00265 LinkData *poseAnim_mapping_getNextFCurve (ListBase *fcuLinks, LinkData *prev, const char *path)
00266 {
00267     LinkData *first= (prev)? prev->next : (fcuLinks)? fcuLinks->first : NULL;
00268     LinkData *ld;
00269     
00270     /* check each link to see if the linked F-Curve has a matching path */
00271     for (ld= first; ld; ld= ld->next) {
00272         FCurve *fcu= (FCurve *)ld->data;
00273         
00274         /* check if paths match */
00275         if (strcmp(path, fcu->rna_path) == 0)
00276             return ld;
00277     }   
00278     
00279     /* none found */
00280     return NULL;
00281 }
00282 
00283 /* *********************************************** */