style cleanup: format 'for' loop macros the same as for loops, some renaming to BLI_a...
[blender-staging.git] / source / blender / editors / armature / poseUtils.c
1 /*
2  * ***** BEGIN GPL LICENSE BLOCK *****
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software Foundation,
16  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17  *
18  * The Original Code is Copyright (C) 2009, Blender Foundation, Joshua Leung
19  * This is a new part of Blender
20  *
21  * Contributor(s): Joshua Leung
22  *
23  * ***** END GPL LICENSE BLOCK *****
24  */
25
26 /** \file blender/editors/armature/poseUtils.c
27  *  \ingroup edarmature
28  */
29
30
31 #include <stdlib.h>
32 #include <stdio.h>
33 #include <stddef.h>
34 #include <string.h>
35 #include <math.h>
36 #include <float.h>
37
38 #include "MEM_guardedalloc.h"
39
40 #include "BLI_math.h"
41 #include "BLI_blenlib.h"
42 #include "BLI_dynstr.h"
43 #include "BLI_dlrbTree.h"
44 #include "BLI_utildefines.h"
45
46 #include "DNA_anim_types.h"
47 #include "DNA_armature_types.h"
48 #include "DNA_object_types.h"
49 #include "DNA_scene_types.h"
50
51 #include "BKE_action.h"
52 #include "BKE_armature.h"
53 #include "BKE_depsgraph.h"
54 #include "BKE_idprop.h"
55
56 #include "BKE_context.h"
57
58 #include "RNA_access.h"
59
60 #include "WM_api.h"
61 #include "WM_types.h"
62
63
64
65 #include "ED_armature.h"
66 #include "ED_keyframing.h"
67
68 #include "armature_intern.h"
69
70 /* *********************************************** */
71 /* Contents of this File:
72  *
73  * This file contains methods shared between Pose Slide and Pose Lib;
74  * primarily the functions in question concern Animato <-> Pose 
75  * convenience functions, such as applying/getting pose values
76  * and/or inserting keyframes for these.
77  */
78 /* *********************************************** */ 
79 /* FCurves <-> PoseChannels Links */
80
81 /* helper for poseAnim_mapping_get() -> get the relevant F-Curves per PoseChannel */
82 static void fcurves_to_pchan_links_get (ListBase *pfLinks, Object *ob, bAction *act, bPoseChannel *pchan)
83 {
84         ListBase curves = {NULL, NULL};
85         int transFlags = action_get_item_transforms(act, ob, pchan, &curves);
86         
87         pchan->flag &= ~(POSE_LOC|POSE_ROT|POSE_SIZE);
88         
89         /* check if any transforms found... */
90         if (transFlags) {
91                 /* make new linkage data */
92                 tPChanFCurveLink *pfl= MEM_callocN(sizeof(tPChanFCurveLink), "tPChanFCurveLink");
93                 PointerRNA ptr;
94                 
95                 pfl->fcurves= curves;
96                 pfl->pchan= pchan;
97                 
98                 /* get the RNA path to this pchan - this needs to be freed! */
99                 RNA_pointer_create((ID *)ob, &RNA_PoseBone, pchan, &ptr);
100                 pfl->pchan_path= RNA_path_from_ID_to_struct(&ptr);
101                 
102                 /* add linkage data to operator data */
103                 BLI_addtail(pfLinks, pfl);
104                 
105                 /* set pchan's transform flags */
106                 if (transFlags & ACT_TRANS_LOC)
107                         pchan->flag |= POSE_LOC;
108                 if (transFlags & ACT_TRANS_ROT)
109                         pchan->flag |= POSE_ROT;
110                 if (transFlags & ACT_TRANS_SCALE)
111                         pchan->flag |= POSE_SIZE;
112                         
113                 /* store current transforms */
114                 copy_v3_v3(pfl->oldloc, pchan->loc);
115                 copy_v3_v3(pfl->oldrot, pchan->eul);
116                 copy_v3_v3(pfl->oldscale, pchan->size);
117                 copy_qt_qt(pfl->oldquat, pchan->quat);
118                 copy_v3_v3(pfl->oldaxis, pchan->rotAxis);
119                 pfl->oldangle = pchan->rotAngle;
120                 
121                 /* make copy of custom properties */
122                 if (pchan->prop && (transFlags & ACT_TRANS_PROP))
123                         pfl->oldprops = IDP_CopyProperty(pchan->prop);
124         }
125
126
127
128 /* get sets of F-Curves providing transforms for the bones in the Pose  */
129 void poseAnim_mapping_get (bContext *C, ListBase *pfLinks, Object *ob, bAction *act)
130 {       
131         /* for each Pose-Channel which gets affected, get the F-Curves for that channel 
132          * and set the relevant transform flags...
133          */
134         CTX_DATA_BEGIN (C, bPoseChannel*, pchan, selected_pose_bones) {
135                 fcurves_to_pchan_links_get(pfLinks, ob, act, pchan);
136         }
137         CTX_DATA_END;
138         
139         /* if no PoseChannels were found, try a second pass, doing visible ones instead
140          * i.e. if nothing selected, do whole pose
141          */
142         if (pfLinks->first == NULL) {
143                 CTX_DATA_BEGIN (C, bPoseChannel*, pchan, visible_pose_bones) {
144                         fcurves_to_pchan_links_get(pfLinks, ob, act, pchan);
145                 }
146                 CTX_DATA_END;
147         }
148 }
149
150 /* free F-Curve <-> PoseChannel links  */
151 void poseAnim_mapping_free (ListBase *pfLinks)
152 {
153         tPChanFCurveLink *pfl, *pfln=NULL;
154                 
155         /* free the temp pchan links and their data */
156         for (pfl= pfLinks->first; pfl; pfl= pfln) {
157                 pfln= pfl->next;
158                 
159                 /* free custom properties */
160                 if (pfl->oldprops) {
161                         IDP_FreeProperty(pfl->oldprops);
162                         MEM_freeN(pfl->oldprops);
163                 }
164                 
165                 /* free list of F-Curve reference links */
166                 BLI_freelistN(&pfl->fcurves);
167                 
168                 /* free pchan RNA Path */
169                 MEM_freeN(pfl->pchan_path);
170                 
171                 /* free link itself */
172                 BLI_freelinkN(pfLinks, pfl);
173         }
174 }
175
176 /* ------------------------- */
177
178 /* helper for apply() / reset() - refresh the data */
179 void poseAnim_mapping_refresh (bContext *C, Scene *scene, Object *ob)
180 {
181         bArmature *arm= (bArmature *)ob->data;
182         
183         /* old optimize trick... this enforces to bypass the depgraph 
184          *      - note: code copied from transform_generics.c -> recalcData()
185          */
186         // FIXME: shouldn't this use the builtin stuff?
187         if ((arm->flag & ARM_DELAYDEFORM)==0)
188                 DAG_id_tag_update(&ob->id, OB_RECALC_DATA);  /* sets recalc flags */
189         else
190                 where_is_pose(scene, ob);
191         
192         /* note, notifier might evolve */
193         WM_event_add_notifier(C, NC_OBJECT|ND_POSE, ob);
194 }
195
196 /* reset changes made to current pose */
197 void poseAnim_mapping_reset (ListBase *pfLinks)
198 {
199         tPChanFCurveLink *pfl;
200         
201         /* iterate over each pose-channel affected, restoring all channels to their original values */
202         for (pfl= pfLinks->first; pfl; pfl= pfl->next) {
203                 bPoseChannel *pchan= pfl->pchan;
204                 
205                 /* just copy all the values over regardless of whether they changed or not */
206                 copy_v3_v3(pchan->loc, pfl->oldloc);
207                 copy_v3_v3(pchan->eul, pfl->oldrot);
208                 copy_v3_v3(pchan->size, pfl->oldscale);
209                 copy_qt_qt(pchan->quat, pfl->oldquat);
210                 copy_v3_v3(pchan->rotAxis, pfl->oldaxis);
211                 pchan->rotAngle = pfl->oldangle;
212                 
213                 /* just overwrite values of properties from the stored copies (there should be some) */
214                 if (pfl->oldprops)
215                         IDP_SyncGroupValues(pfl->pchan->prop, pfl->oldprops);
216         }
217 }
218
219 /* perform autokeyframing after changes were made + confirmed */
220 void poseAnim_mapping_autoKeyframe (bContext *C, Scene *scene, Object *ob, ListBase *pfLinks, float cframe)
221 {
222         /* insert keyframes as necessary if autokeyframing */
223         if (autokeyframe_cfra_can_key(scene, &ob->id)) {
224                 KeyingSet *ks = ANIM_get_keyingset_for_autokeying(scene, ANIM_KS_WHOLE_CHARACTER_ID);
225                 ListBase dsources = {NULL, NULL};
226                 tPChanFCurveLink *pfl;
227                 
228                 /* iterate over each pose-channel affected, tagging bones to be keyed */
229                 /* XXX: here we already have the information about what transforms exist, though 
230                  * it might be easier to just overwrite all using normal mechanisms
231                  */
232                 for (pfl= pfLinks->first; pfl; pfl= pfl->next) {
233                         bPoseChannel *pchan= pfl->pchan;
234                         
235                         /* add datasource override for the PoseChannel, to be used later */
236                         ANIM_relative_keyingset_add_source(&dsources, &ob->id, &RNA_PoseBone, pchan); 
237                         
238                         /* clear any unkeyed tags */
239                         if (pchan->bone)
240                                 pchan->bone->flag &= ~BONE_UNKEYED;
241                 }
242                 
243                 /* insert keyframes for all relevant bones in one go */
244                 ANIM_apply_keyingset(C, &dsources, NULL, ks, MODIFYKEY_MODE_INSERT, cframe);
245                 BLI_freelistN(&dsources);
246                 
247                 /* do the bone paths
248                  *      - only do this if keyframes should have been added
249                  *      - do not calculate unless there are paths already to update...
250                  */
251                 if (C && (ob->pose->avs.path_bakeflag & MOTIONPATH_BAKE_HAS_PATHS)) {
252                         //ED_pose_clear_paths(C, ob); // XXX for now, don't need to clear
253                         ED_pose_recalculate_paths(scene, ob);
254                 }
255         }
256 }
257
258 /* ------------------------- */
259
260 /* find the next F-Curve for a PoseChannel with matching path... 
261  *      - path is not just the pfl rna_path, since that path doesn't have property info yet
262  */
263 LinkData *poseAnim_mapping_getNextFCurve (ListBase *fcuLinks, LinkData *prev, const char *path)
264 {
265         LinkData *first= (prev)? prev->next : (fcuLinks)? fcuLinks->first : NULL;
266         LinkData *ld;
267         
268         /* check each link to see if the linked F-Curve has a matching path */
269         for (ld= first; ld; ld= ld->next) {
270                 FCurve *fcu= (FCurve *)ld->data;
271                 
272                 /* check if paths match */
273                 if (strcmp(path, fcu->rna_path) == 0)
274                         return ld;
275         }       
276         
277         /* none found */
278         return NULL;
279 }
280
281 /* *********************************************** */