Merge branch 'master' into blender2.8
[blender.git] / source / blender / editors / armature / pose_utils.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/pose_utils.c
27  *  \ingroup edarmature
28  */
29
30 #include "MEM_guardedalloc.h"
31
32 #include "BLI_math.h"
33 #include "BLI_blenlib.h"
34
35 #include "DNA_anim_types.h"
36 #include "DNA_armature_types.h"
37 #include "DNA_object_types.h"
38 #include "DNA_scene_types.h"
39
40 #include "BKE_action.h"
41 #include "BKE_armature.h"
42 #include "BKE_idprop.h"
43
44 #include "BKE_context.h"
45
46 #include "DEG_depsgraph.h"
47
48 #include "RNA_access.h"
49
50 #include "WM_api.h"
51 #include "WM_types.h"
52
53 #include "ED_armature.h"
54 #include "ED_keyframing.h"
55
56 #include "armature_intern.h"
57
58 /* *********************************************** */
59 /* Contents of this File:
60  *
61  * This file contains methods shared between Pose Slide and Pose Lib;
62  * primarily the functions in question concern Animato <-> Pose
63  * convenience functions, such as applying/getting pose values
64  * and/or inserting keyframes for these.
65  */
66 /* *********************************************** */
67 /* FCurves <-> PoseChannels Links */
68
69 /* helper for poseAnim_mapping_get() -> get the relevant F-Curves per PoseChannel */
70 static void fcurves_to_pchan_links_get(ListBase *pfLinks, Object *ob, bAction *act, bPoseChannel *pchan)
71 {
72         ListBase curves = {NULL, NULL};
73         int transFlags = action_get_item_transforms(act, ob, pchan, &curves);
74
75         pchan->flag &= ~(POSE_LOC | POSE_ROT | POSE_SIZE | POSE_BBONE_SHAPE);
76
77         /* check if any transforms found... */
78         if (transFlags) {
79                 /* make new linkage data */
80                 tPChanFCurveLink *pfl = MEM_callocN(sizeof(tPChanFCurveLink), "tPChanFCurveLink");
81                 PointerRNA ptr;
82
83                 pfl->fcurves = curves;
84                 pfl->pchan = pchan;
85
86                 /* get the RNA path to this pchan - this needs to be freed! */
87                 RNA_pointer_create((ID *)ob, &RNA_PoseBone, pchan, &ptr);
88                 pfl->pchan_path = RNA_path_from_ID_to_struct(&ptr);
89
90                 /* add linkage data to operator data */
91                 BLI_addtail(pfLinks, pfl);
92
93                 /* set pchan's transform flags */
94                 if (transFlags & ACT_TRANS_LOC)
95                         pchan->flag |= POSE_LOC;
96                 if (transFlags & ACT_TRANS_ROT)
97                         pchan->flag |= POSE_ROT;
98                 if (transFlags & ACT_TRANS_SCALE)
99                         pchan->flag |= POSE_SIZE;
100                 if (transFlags & ACT_TRANS_BBONE)
101                         pchan->flag |= POSE_BBONE_SHAPE;
102
103                 /* store current transforms */
104                 copy_v3_v3(pfl->oldloc, pchan->loc);
105                 copy_v3_v3(pfl->oldrot, pchan->eul);
106                 copy_v3_v3(pfl->oldscale, pchan->size);
107                 copy_qt_qt(pfl->oldquat, pchan->quat);
108                 copy_v3_v3(pfl->oldaxis, pchan->rotAxis);
109                 pfl->oldangle = pchan->rotAngle;
110
111                 /* store current bbone values */
112                 pfl->roll1 = pchan->roll1;
113                 pfl->roll2 = pchan->roll2;
114                 pfl->curveInX = pchan->curveInX;
115                 pfl->curveInY = pchan->curveInY;
116                 pfl->curveOutX = pchan->curveOutX;
117                 pfl->curveOutY = pchan->curveOutY;
118                 pfl->ease1 = pchan->ease1;
119                 pfl->ease2 = pchan->ease2;
120                 pfl->scaleIn = pchan->scaleIn;
121                 pfl->scaleOut = pchan->scaleOut;
122
123                 /* make copy of custom properties */
124                 if (pchan->prop && (transFlags & ACT_TRANS_PROP))
125                         pfl->oldprops = IDP_CopyProperty(pchan->prop);
126         }
127 }
128
129
130 /* get sets of F-Curves providing transforms for the bones in the Pose  */
131 void poseAnim_mapping_get(bContext *C, ListBase *pfLinks, Object *ob, bAction *act)
132 {
133         /* for each Pose-Channel which gets affected, get the F-Curves for that channel
134          * and set the relevant transform flags...
135          */
136         CTX_DATA_BEGIN (C, bPoseChannel *, pchan, selected_pose_bones)
137         {
138                 fcurves_to_pchan_links_get(pfLinks, ob, act, pchan);
139         }
140         CTX_DATA_END;
141
142         /* if no PoseChannels were found, try a second pass, doing visible ones instead
143          * i.e. if nothing selected, do whole pose
144          */
145         if (BLI_listbase_is_empty(pfLinks)) {
146                 CTX_DATA_BEGIN (C, bPoseChannel *, pchan, visible_pose_bones)
147                 {
148                         fcurves_to_pchan_links_get(pfLinks, ob, act, pchan);
149                 }
150                 CTX_DATA_END;
151
152         }
153 }
154
155 /* free F-Curve <-> PoseChannel links  */
156 void poseAnim_mapping_free(ListBase *pfLinks)
157 {
158         tPChanFCurveLink *pfl, *pfln = NULL;
159
160         /* free the temp pchan links and their data */
161         for (pfl = pfLinks->first; pfl; pfl = pfln) {
162                 pfln = pfl->next;
163
164                 /* free custom properties */
165                 if (pfl->oldprops) {
166                         IDP_FreeProperty(pfl->oldprops);
167                         MEM_freeN(pfl->oldprops);
168                 }
169
170                 /* free list of F-Curve reference links */
171                 BLI_freelistN(&pfl->fcurves);
172
173                 /* free pchan RNA Path */
174                 MEM_freeN(pfl->pchan_path);
175
176                 /* free link itself */
177                 BLI_freelinkN(pfLinks, pfl);
178         }
179 }
180
181 /* ------------------------- */
182
183 /* helper for apply() / reset() - refresh the data */
184 void poseAnim_mapping_refresh(bContext *C, Scene *scene, Object *ob)
185 {
186         Depsgraph *depsgraph = CTX_data_depsgraph(C);
187         bArmature *arm = (bArmature *)ob->data;
188
189         /* old optimize trick... this enforces to bypass the depgraph
190          *      - note: code copied from transform_generics.c -> recalcData()
191          */
192         /* FIXME: shouldn't this use the builtin stuff? */
193         if ((arm->flag & ARM_DELAYDEFORM) == 0)
194                 DEG_id_tag_update(&ob->id, OB_RECALC_DATA);  /* sets recalc flags */
195         else
196                 BKE_pose_where_is(depsgraph, scene, ob);
197
198         DEG_id_tag_update(&ob->id, DEG_TAG_COPY_ON_WRITE); /* otherwise animation doesn't get updated */
199         WM_event_add_notifier(C, NC_OBJECT | ND_POSE, ob);
200 }
201
202 /* reset changes made to current pose */
203 void poseAnim_mapping_reset(ListBase *pfLinks)
204 {
205         tPChanFCurveLink *pfl;
206
207         /* iterate over each pose-channel affected, restoring all channels to their original values */
208         for (pfl = pfLinks->first; pfl; pfl = pfl->next) {
209                 bPoseChannel *pchan = pfl->pchan;
210
211                 /* just copy all the values over regardless of whether they changed or not */
212                 copy_v3_v3(pchan->loc, pfl->oldloc);
213                 copy_v3_v3(pchan->eul, pfl->oldrot);
214                 copy_v3_v3(pchan->size, pfl->oldscale);
215                 copy_qt_qt(pchan->quat, pfl->oldquat);
216                 copy_v3_v3(pchan->rotAxis, pfl->oldaxis);
217                 pchan->rotAngle = pfl->oldangle;
218
219                 /* store current bbone values */
220                 pchan->roll1 = pfl->roll1;
221                 pchan->roll2 = pfl->roll2;
222                 pchan->curveInX = pfl->curveInX;
223                 pchan->curveInY = pfl->curveInY;
224                 pchan->curveOutX = pfl->curveOutX;
225                 pchan->curveOutY = pfl->curveOutY;
226                 pchan->ease1 = pfl->ease1;
227                 pchan->ease2 = pfl->ease2;
228                 pchan->scaleIn = pfl->scaleIn;
229                 pchan->scaleOut = pfl->scaleOut;
230
231                 /* just overwrite values of properties from the stored copies (there should be some) */
232                 if (pfl->oldprops)
233                         IDP_SyncGroupValues(pfl->pchan->prop, pfl->oldprops);
234         }
235 }
236
237 /* perform autokeyframing after changes were made + confirmed */
238 void poseAnim_mapping_autoKeyframe(bContext *C, Scene *scene, Object *ob, ListBase *pfLinks, float cframe)
239 {
240         /* insert keyframes as necessary if autokeyframing */
241         if (autokeyframe_cfra_can_key(scene, &ob->id)) {
242                 KeyingSet *ks = ANIM_get_keyingset_for_autokeying(scene, ANIM_KS_WHOLE_CHARACTER_ID);
243                 ListBase dsources = {NULL, NULL};
244                 tPChanFCurveLink *pfl;
245
246                 /* iterate over each pose-channel affected, tagging bones to be keyed */
247                 /* XXX: here we already have the information about what transforms exist, though
248                  * it might be easier to just overwrite all using normal mechanisms
249                  */
250                 for (pfl = pfLinks->first; pfl; pfl = pfl->next) {
251                         bPoseChannel *pchan = pfl->pchan;
252
253                         /* add datasource override for the PoseChannel, to be used later */
254                         ANIM_relative_keyingset_add_source(&dsources, &ob->id, &RNA_PoseBone, pchan);
255
256                         /* clear any unkeyed tags */
257                         if (pchan->bone)
258                                 pchan->bone->flag &= ~BONE_UNKEYED;
259                 }
260
261                 /* insert keyframes for all relevant bones in one go */
262                 ANIM_apply_keyingset(C, &dsources, NULL, ks, MODIFYKEY_MODE_INSERT, cframe);
263                 BLI_freelistN(&dsources);
264
265                 /* do the bone paths
266                  *      - only do this if keyframes should have been added
267                  *      - do not calculate unless there are paths already to update...
268                  */
269                 if (ob->pose->avs.path_bakeflag & MOTIONPATH_BAKE_HAS_PATHS) {
270                         //ED_pose_clear_paths(C, ob); // XXX for now, don't need to clear
271                         ED_pose_recalculate_paths(C, scene, ob);
272                 }
273         }
274 }
275
276 /* ------------------------- */
277
278 /* find the next F-Curve for a PoseChannel with matching path...
279  *      - path is not just the pfl rna_path, since that path doesn't have property info yet
280  */
281 LinkData *poseAnim_mapping_getNextFCurve(ListBase *fcuLinks, LinkData *prev, const char *path)
282 {
283         LinkData *first = (prev) ? prev->next : (fcuLinks) ? fcuLinks->first : NULL;
284         LinkData *ld;
285
286         /* check each link to see if the linked F-Curve has a matching path */
287         for (ld = first; ld; ld = ld->next) {
288                 FCurve *fcu = (FCurve *)ld->data;
289
290                 /* check if paths match */
291                 if (STREQ(path, fcu->rna_path))
292                         return ld;
293         }
294
295         /* none found */
296         return NULL;
297 }
298
299 /* *********************************************** */