Blender V2.61 - r43446
|
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 /* *********************************************** */