Cleanup: comment line length (editors)
[blender.git] / source / blender / editors / armature / pose_transform.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) 2001-2002 by NaN Holding BV.
19  * All rights reserved.
20  *
21  * Contributor(s): Blender Foundation, 2002-2009 full recode.
22  *
23  * ***** END GPL LICENSE BLOCK *****
24  */
25
26 /** \file blender/editors/armature/pose_transform.c
27  *  \ingroup edarmature
28  */
29
30 #include "DNA_anim_types.h"
31 #include "DNA_armature_types.h"
32 #include "DNA_object_types.h"
33 #include "DNA_scene_types.h"
34
35 #include "MEM_guardedalloc.h"
36
37 #include "BLI_blenlib.h"
38 #include "BLI_math.h"
39 #include "BLI_string_utils.h"
40
41 #include "BKE_animsys.h"
42 #include "BKE_action.h"
43 #include "BKE_appdir.h"
44 #include "BKE_armature.h"
45 #include "BKE_blender_copybuffer.h"
46 #include "BKE_context.h"
47 #include "BKE_deform.h"
48 #include "BKE_depsgraph.h"
49 #include "BKE_global.h"
50 #include "BKE_idprop.h"
51 #include "BKE_main.h"
52 #include "BKE_object.h"
53 #include "BKE_report.h"
54
55 #include "RNA_access.h"
56 #include "RNA_define.h"
57
58 #include "WM_api.h"
59 #include "WM_types.h"
60
61 #include "ED_armature.h"
62 #include "ED_keyframing.h"
63 #include "ED_screen.h"
64 #include "ED_util.h"
65
66 #include "armature_intern.h"
67
68
69 /* ********************************************** */
70 /* Pose Apply */
71
72 /* helper for apply_armature_pose2bones - fixes parenting of objects that are bone-parented to armature */
73 static void applyarmature_fix_boneparents(Main *bmain, Scene *scene, Object *armob)
74 {
75         Object workob, *ob;
76
77         /* go through all objects in database */
78         for (ob = bmain->object.first; ob; ob = ob->id.next) {
79                 /* if parent is bone in this armature, apply corrections */
80                 if ((ob->parent == armob) && (ob->partype == PARBONE)) {
81                         /* apply current transform from parent (not yet destroyed),
82                          * then calculate new parent inverse matrix
83                          */
84                         BKE_object_apply_mat4(ob, ob->obmat, false, false);
85
86                         BKE_object_workob_calc_parent(scene, ob, &workob);
87                         invert_m4_m4(ob->parentinv, workob.obmat);
88                 }
89         }
90 }
91
92 /* set the current pose as the restpose */
93 static int apply_armature_pose2bones_exec(bContext *C, wmOperator *op)
94 {
95         Main *bmain = CTX_data_main(C);
96         Scene *scene = CTX_data_scene(C);
97         Object *ob = BKE_object_pose_armature_get(CTX_data_active_object(C)); // must be active object, not edit-object
98         bArmature *arm = BKE_armature_from_object(ob);
99         bPose *pose;
100         bPoseChannel *pchan;
101         EditBone *curbone;
102
103         /* don't check if editmode (should be done by caller) */
104         if (ob->type != OB_ARMATURE)
105                 return OPERATOR_CANCELLED;
106         if (BKE_object_obdata_is_libdata(ob)) {
107                 BKE_report(op->reports, RPT_ERROR, "Cannot apply pose to lib-linked armature");
108                 return OPERATOR_CANCELLED;
109         }
110
111         /* helpful warnings... */
112         /* TODO: add warnings to be careful about actions, applying deforms first, etc. */
113         if (ob->adt && ob->adt->action)
114                 BKE_report(op->reports, RPT_WARNING,
115                            "Actions on this armature will be destroyed by this new rest pose as the "
116                            "transforms stored are relative to the old rest pose");
117
118         /* Get editbones of active armature to alter */
119         ED_armature_to_edit(arm);
120
121         /* get pose of active object and move it out of posemode */
122         pose = ob->pose;
123
124         for (pchan = pose->chanbase.first; pchan; pchan = pchan->next) {
125                 curbone = ED_armature_ebone_find_name(arm->edbo, pchan->name);
126
127                 /* simply copy the head/tail values from pchan over to curbone */
128                 copy_v3_v3(curbone->head, pchan->pose_head);
129                 copy_v3_v3(curbone->tail, pchan->pose_tail);
130
131                 /* fix roll:
132                  * 1. find auto-calculated roll value for this bone now
133                  * 2. remove this from the 'visual' y-rotation
134                  */
135                 {
136                         float premat[3][3], imat[3][3], pmat[3][3], tmat[3][3];
137                         float delta[3], eul[3];
138
139                         /* obtain new auto y-rotation */
140                         sub_v3_v3v3(delta, curbone->tail, curbone->head);
141                         vec_roll_to_mat3(delta, 0.0f, premat);
142                         invert_m3_m3(imat, premat);
143
144                         /* get pchan 'visual' matrix */
145                         copy_m3_m4(pmat, pchan->pose_mat);
146
147                         /* remove auto from visual and get euler rotation */
148                         mul_m3_m3m3(tmat, imat, pmat);
149                         mat3_to_eul(eul, tmat);
150
151                         /* just use this euler-y as new roll value */
152                         curbone->roll = eul[1];
153                 }
154
155                 /* combine pose and rest values for bendy bone settings,
156                  * then clear the pchan values (so we don't get a double-up)
157                  */
158                 if (pchan->bone->segments > 1) {
159                         curbone->curveInX += pchan->curveInX;
160                         curbone->curveInY += pchan->curveInY;
161                         curbone->curveOutX += pchan->curveOutX;
162                         curbone->curveOutY += pchan->curveOutY;
163                         curbone->roll1 += pchan->roll1;
164                         curbone->roll2 += pchan->roll2;
165                         curbone->ease1 += pchan->ease1;
166                         curbone->ease2 += pchan->ease2;
167                         curbone->scaleIn *= pchan->scaleIn;
168                         curbone->scaleOut *= pchan->scaleOut;
169
170                         pchan->curveInX = pchan->curveOutX = 0.0f;
171                         pchan->curveInY = pchan->curveOutY = 0.0f;
172                         pchan->roll1 = pchan->roll2 = 0.0f;
173                         pchan->ease1 = pchan->ease2 = 0.0f;
174                         pchan->scaleIn = pchan->scaleOut = 1.0f;
175                 }
176
177                 /* clear transform values for pchan */
178                 zero_v3(pchan->loc);
179                 zero_v3(pchan->eul);
180                 unit_qt(pchan->quat);
181                 unit_axis_angle(pchan->rotAxis, &pchan->rotAngle);
182                 pchan->size[0] = pchan->size[1] = pchan->size[2] = 1.0f;
183
184                 /* set anim lock */
185                 curbone->flag |= BONE_UNKEYED;
186         }
187
188         /* convert editbones back to bones, and then free the edit-data */
189         ED_armature_from_edit(bmain, arm);
190         ED_armature_edit_free(arm);
191
192         /* flush positions of posebones */
193         BKE_pose_where_is(scene, ob);
194
195         /* fix parenting of objects which are bone-parented */
196         applyarmature_fix_boneparents(bmain, scene, ob);
197
198         /* note, notifier might evolve */
199         WM_event_add_notifier(C, NC_OBJECT | ND_POSE, ob);
200
201         return OPERATOR_FINISHED;
202 }
203
204 void POSE_OT_armature_apply(wmOperatorType *ot)
205 {
206         /* identifiers */
207         ot->name = "Apply Pose as Rest Pose";
208         ot->idname = "POSE_OT_armature_apply";
209         ot->description = "Apply the current pose as the new rest pose";
210
211         /* callbacks */
212         ot->exec = apply_armature_pose2bones_exec;
213         ot->poll = ED_operator_posemode;
214
215         /* flags */
216         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
217 }
218
219
220 /* set the current pose as the restpose */
221 static int pose_visual_transform_apply_exec(bContext *C, wmOperator *UNUSED(op))
222 {
223         Object *ob = BKE_object_pose_armature_get(CTX_data_active_object(C)); // must be active object, not edit-object
224
225         /* don't check if editmode (should be done by caller) */
226         if (ob->type != OB_ARMATURE)
227                 return OPERATOR_CANCELLED;
228
229         /* loop over all selected pchans
230          *
231          * TODO, loop over children before parents if multiple bones
232          * at once are to be predictable*/
233         CTX_DATA_BEGIN(C, bPoseChannel *, pchan, selected_pose_bones)
234         {
235                 float delta_mat[4][4];
236
237                 /* chan_mat already contains the delta transform from rest pose to pose-mode pose
238                  * as that is baked into there so that B-Bones will work. Once we've set this as the
239                  * new raw-transform components, don't recalc the poses yet, otherwise IK result will
240                  * change, thus changing the result we may be trying to record.
241                  */
242                 /* XXX For some reason, we can't use pchan->chan_mat here, gives odd rotation/offset (see T38251).
243                  *     Using pchan->pose_mat and bringing it back in bone space seems to work as expected!
244                  */
245                 BKE_armature_mat_pose_to_bone(pchan, pchan->pose_mat, delta_mat);
246
247                 BKE_pchan_apply_mat4(pchan, delta_mat, true);
248         }
249         CTX_DATA_END;
250
251         DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
252
253         /* note, notifier might evolve */
254         WM_event_add_notifier(C, NC_OBJECT | ND_POSE, ob);
255
256         return OPERATOR_FINISHED;
257 }
258
259 void POSE_OT_visual_transform_apply(wmOperatorType *ot)
260 {
261         /* identifiers */
262         ot->name = "Apply Visual Transform to Pose";
263         ot->idname = "POSE_OT_visual_transform_apply";
264         ot->description = "Apply final constrained position of pose bones to their transform";
265
266         /* callbacks */
267         ot->exec = pose_visual_transform_apply_exec;
268         ot->poll = ED_operator_posemode;
269
270         /* flags */
271         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
272 }
273
274 /* ********************************************** */
275 /* Copy/Paste */
276
277 /* This function is used to indicate that a bone is selected
278  * and needs to be included in copy buffer (used to be for inserting keys)
279  */
280 static void set_pose_keys(Object *ob)
281 {
282         bArmature *arm = ob->data;
283         bPoseChannel *chan;
284
285         if (ob->pose) {
286                 for (chan = ob->pose->chanbase.first; chan; chan = chan->next) {
287                         Bone *bone = chan->bone;
288                         if ((bone) && (bone->flag & BONE_SELECTED) && (arm->layer & bone->layer))
289                                 chan->flag |= POSE_KEY;
290                         else
291                                 chan->flag &= ~POSE_KEY;
292                 }
293         }
294 }
295
296 /**
297  * Perform paste pose, for a single bone.
298  *
299  * \param ob: Object where bone to paste to lives
300  * \param chan: Bone that pose to paste comes from
301  * \param selOnly: Only paste on selected bones
302  * \param flip: Flip on x-axis
303  * \return Whether the bone that we pasted to if we succeeded
304  */
305 static bPoseChannel *pose_bone_do_paste(Object *ob, bPoseChannel *chan, const bool selOnly, const bool flip)
306 {
307         bPoseChannel *pchan;
308         char name[MAXBONENAME];
309         short paste_ok;
310
311         /* get the name - if flipping, we must flip this first */
312         if (flip)
313                 BLI_string_flip_side_name(name, chan->name, false, sizeof(name));
314         else
315                 BLI_strncpy(name, chan->name, sizeof(name));
316
317         /* only copy when:
318          *  1) channel exists - poses are not meant to add random channels to anymore
319          *  2) if selection-masking is on, channel is selected - only selected bones get pasted on, allowing making both sides symmetrical
320          */
321         pchan = BKE_pose_channel_find_name(ob->pose, name);
322
323         if (selOnly)
324                 paste_ok = ((pchan) && (pchan->bone->flag & BONE_SELECTED));
325         else
326                 paste_ok = (pchan != NULL);
327
328         /* continue? */
329         if (paste_ok) {
330                 /* only loc rot size
331                  * - only copies transform info for the pose
332                  */
333                 copy_v3_v3(pchan->loc, chan->loc);
334                 copy_v3_v3(pchan->size, chan->size);
335                 pchan->flag = chan->flag;
336
337                 /* check if rotation modes are compatible (i.e. do they need any conversions) */
338                 if (pchan->rotmode == chan->rotmode) {
339                         /* copy the type of rotation in use */
340                         if (pchan->rotmode > 0) {
341                                 copy_v3_v3(pchan->eul, chan->eul);
342                         }
343                         else if (pchan->rotmode == ROT_MODE_AXISANGLE) {
344                                 copy_v3_v3(pchan->rotAxis, chan->rotAxis);
345                                 pchan->rotAngle = chan->rotAngle;
346                         }
347                         else {
348                                 copy_qt_qt(pchan->quat, chan->quat);
349                         }
350                 }
351                 else if (pchan->rotmode > 0) {
352                         /* quat/axis-angle to euler */
353                         if (chan->rotmode == ROT_MODE_AXISANGLE)
354                                 axis_angle_to_eulO(pchan->eul, pchan->rotmode, chan->rotAxis, chan->rotAngle);
355                         else
356                                 quat_to_eulO(pchan->eul, pchan->rotmode, chan->quat);
357                 }
358                 else if (pchan->rotmode == ROT_MODE_AXISANGLE) {
359                         /* quat/euler to axis angle */
360                         if (chan->rotmode > 0)
361                                 eulO_to_axis_angle(pchan->rotAxis, &pchan->rotAngle, chan->eul, chan->rotmode);
362                         else
363                                 quat_to_axis_angle(pchan->rotAxis, &pchan->rotAngle, chan->quat);
364                 }
365                 else {
366                         /* euler/axis-angle to quat */
367                         if (chan->rotmode > 0)
368                                 eulO_to_quat(pchan->quat, chan->eul, chan->rotmode);
369                         else
370                                 axis_angle_to_quat(pchan->quat, chan->rotAxis, pchan->rotAngle);
371                 }
372
373                 /* B-Bone posing options should also be included... */
374                 pchan->curveInX = chan->curveInX;
375                 pchan->curveInY = chan->curveInY;
376                 pchan->curveOutX = chan->curveOutX;
377                 pchan->curveOutY = chan->curveOutY;
378
379                 pchan->roll1 = chan->roll1;
380                 pchan->roll2 = chan->roll2;
381                 pchan->ease1 = chan->ease1;
382                 pchan->ease2 = chan->ease2;
383                 pchan->scaleIn = chan->scaleIn;
384                 pchan->scaleOut = chan->scaleOut;
385
386                 /* paste flipped pose? */
387                 if (flip) {
388                         pchan->loc[0] *= -1;
389
390                         pchan->curveInX *= -1;
391                         pchan->curveOutX *= -1;
392                         pchan->roll1 *= -1; // XXX?
393                         pchan->roll2 *= -1; // XXX?
394
395                         /* has to be done as eulers... */
396                         if (pchan->rotmode > 0) {
397                                 pchan->eul[1] *= -1;
398                                 pchan->eul[2] *= -1;
399                         }
400                         else if (pchan->rotmode == ROT_MODE_AXISANGLE) {
401                                 float eul[3];
402
403                                 axis_angle_to_eulO(eul, EULER_ORDER_DEFAULT, pchan->rotAxis, pchan->rotAngle);
404                                 eul[1] *= -1;
405                                 eul[2] *= -1;
406                                 eulO_to_axis_angle(pchan->rotAxis, &pchan->rotAngle, eul, EULER_ORDER_DEFAULT);
407                         }
408                         else {
409                                 float eul[3];
410
411                                 normalize_qt(pchan->quat);
412                                 quat_to_eul(eul, pchan->quat);
413                                 eul[1] *= -1;
414                                 eul[2] *= -1;
415                                 eul_to_quat(pchan->quat, eul);
416                         }
417                 }
418
419                 /* ID properties */
420                 if (chan->prop) {
421                         if (pchan->prop) {
422                                 /* if we have existing properties on a bone, just copy over the values of
423                                  * matching properties (i.e. ones which will have some impact) on to the
424                                  * target instead of just blinding replacing all [
425                                  */
426                                 IDP_SyncGroupValues(pchan->prop, chan->prop);
427                         }
428                         else {
429                                 /* no existing properties, so assume that we want copies too? */
430                                 pchan->prop = IDP_CopyProperty(chan->prop);
431                         }
432                 }
433         }
434
435         /* return whether paste went ahead */
436         return pchan;
437 }
438
439 /* ---- */
440
441 static int pose_copy_exec(bContext *C, wmOperator *op)
442 {
443         Object *ob = BKE_object_pose_armature_get(CTX_data_active_object(C));
444         char str[FILE_MAX];
445         /* Sanity checking. */
446         if (ELEM(NULL, ob, ob->pose)) {
447                 BKE_report(op->reports, RPT_ERROR, "No pose to copy");
448                 return OPERATOR_CANCELLED;
449         }
450         /* Sets chan->flag to POSE_KEY if bone selected. */
451         set_pose_keys(ob);
452         /* Construct a local bmain and only put object and it's data into it,
453          * o this way we don't expand any other objects into the copy buffer
454          * file.
455          *
456          * TODO(sergey): Find an easier way to tell copy buffer to only store
457          * data we are actually interested in. Maybe pass it a flag to skip
458          * any datablock expansion?
459          */
460         Main *temp_bmain = BKE_main_new();
461         Object ob_copy = *ob;
462         bArmature arm_copy = *((bArmature *)ob->data);
463         ob_copy.data = &arm_copy;
464         BLI_addtail(&temp_bmain->object, &ob_copy);
465         BLI_addtail(&temp_bmain->armature, &arm_copy);
466         /* begin copy buffer on a temp bmain. */
467         BKE_copybuffer_begin(temp_bmain);
468         /* Store the whole object to the copy buffer because pose can't be
469          * existing on it's own.
470          */
471         BKE_copybuffer_tag_ID(&ob_copy.id);
472         BLI_make_file_string("/", str, BKE_tempdir_base(), "copybuffer_pose.blend");
473         BKE_copybuffer_save(temp_bmain, str, op->reports);
474         /* We clear the lists so no datablocks gets freed,
475          * This is required because objects in temp bmain shares same pointers
476          * as the real ones.
477          */
478         BLI_listbase_clear(&temp_bmain->object);
479         BLI_listbase_clear(&temp_bmain->armature);
480         BKE_main_free(temp_bmain);
481         /* We are all done! */
482         BKE_report(op->reports, RPT_INFO, "Copied pose to buffer");
483         return OPERATOR_FINISHED;
484 }
485
486 void POSE_OT_copy(wmOperatorType *ot)
487 {
488         /* identifiers */
489         ot->name = "Copy Pose";
490         ot->idname = "POSE_OT_copy";
491         ot->description = "Copies the current pose of the selected bones to copy/paste buffer";
492
493         /* api callbacks */
494         ot->exec = pose_copy_exec;
495         ot->poll = ED_operator_posemode;
496
497         /* flag */
498         ot->flag = OPTYPE_REGISTER;
499 }
500
501 /* ---- */
502
503 static int pose_paste_exec(bContext *C, wmOperator *op)
504 {
505         Main *bmain = CTX_data_main(C);
506         Object *ob = BKE_object_pose_armature_get(CTX_data_active_object(C));
507         Scene *scene = CTX_data_scene(C);
508         bPoseChannel *chan;
509         const bool flip = RNA_boolean_get(op->ptr, "flipped");
510         bool selOnly = RNA_boolean_get(op->ptr, "selected_mask");
511
512         /* Get KeyingSet to use. */
513         KeyingSet *ks = ANIM_get_keyingset_for_autokeying(scene, ANIM_KS_WHOLE_CHARACTER_ID);
514
515         /* Sanity checks. */
516         if (ELEM(NULL, ob, ob->pose)) {
517                 return OPERATOR_CANCELLED;
518         }
519
520         /* Read copy buffer .blend file. */
521         char str[FILE_MAX];
522         Main *tmp_bmain = BKE_main_new();
523         BLI_make_file_string("/", str, BKE_tempdir_base(), "copybuffer_pose.blend");
524         if (!BKE_copybuffer_read(tmp_bmain, str, op->reports)) {
525                 BKE_report(op->reports, RPT_ERROR, "Copy buffer is empty");
526                 BKE_main_free(tmp_bmain);
527                 return OPERATOR_CANCELLED;
528         }
529         /* Make sure data from this file is usable for pose paste. */
530         if (BLI_listbase_count_at_most(&tmp_bmain->object, 2) != 1) {
531                 BKE_report(op->reports, RPT_ERROR, "Copy buffer is not from pose mode");
532                 BKE_main_free(tmp_bmain);
533                 return OPERATOR_CANCELLED;
534         }
535
536         Object *object_from = tmp_bmain->object.first;
537         bPose *pose_from = object_from->pose;
538         if (pose_from == NULL) {
539                 BKE_report(op->reports, RPT_ERROR, "Copy buffer has no pose");
540                 BKE_main_free(tmp_bmain);
541                 return OPERATOR_CANCELLED;
542         }
543
544         /* If selOnly option is enabled, if user hasn't selected any bones,
545          * just go back to default behavior to be more in line with other
546          * pose tools.
547          */
548         if (selOnly) {
549                 if (CTX_DATA_COUNT(C, selected_pose_bones) == 0) {
550                         selOnly = false;
551                 }
552         }
553
554         /* Safely merge all of the channels in the buffer pose into any
555          * existing pose.
556          */
557         for (chan = pose_from->chanbase.first; chan; chan = chan->next) {
558                 if (chan->flag & POSE_KEY) {
559                         /* Try to perform paste on this bone. */
560                         bPoseChannel *pchan = pose_bone_do_paste(ob, chan, selOnly, flip);
561                         if (pchan != NULL) {
562                                 /* Keyframing tagging for successful paste, */
563                                 ED_autokeyframe_pchan(C, scene, ob, pchan, ks);
564                         }
565                 }
566         }
567         BKE_main_free(tmp_bmain);
568
569         /* Update event for pose and deformation children. */
570         DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
571
572         /* Recalculate paths if any of the bones have paths... */
573         if ((ob->pose->avs.path_bakeflag & MOTIONPATH_BAKE_HAS_PATHS)) {
574                 ED_pose_recalculate_paths(bmain, scene, ob);
575         }
576
577         /* Notifiers for updates, */
578         WM_event_add_notifier(C, NC_OBJECT | ND_POSE, ob);
579
580         return OPERATOR_FINISHED;
581 }
582
583 void POSE_OT_paste(wmOperatorType *ot)
584 {
585         PropertyRNA *prop;
586
587         /* identifiers */
588         ot->name = "Paste Pose";
589         ot->idname = "POSE_OT_paste";
590         ot->description = "Paste the stored pose on to the current pose";
591
592         /* api callbacks */
593         ot->exec = pose_paste_exec;
594         ot->poll = ED_operator_posemode;
595
596         /* flag */
597         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
598
599         /* properties */
600         prop = RNA_def_boolean(ot->srna, "flipped", false, "Flipped on X-Axis", "Paste the stored pose flipped on to current pose");
601         RNA_def_property_flag(prop, PROP_SKIP_SAVE);
602
603         RNA_def_boolean(ot->srna, "selected_mask", false, "On Selected Only", "Only paste the stored pose on to selected bones in the current pose");
604 }
605
606 /* ********************************************** */
607 /* Clear Pose Transforms */
608
609 /* clear scale of pose-channel */
610 static void pchan_clear_scale(bPoseChannel *pchan)
611 {
612         if ((pchan->protectflag & OB_LOCK_SCALEX) == 0)
613                 pchan->size[0] = 1.0f;
614         if ((pchan->protectflag & OB_LOCK_SCALEY) == 0)
615                 pchan->size[1] = 1.0f;
616         if ((pchan->protectflag & OB_LOCK_SCALEZ) == 0)
617                 pchan->size[2] = 1.0f;
618
619         pchan->ease1 = 0.0f;
620         pchan->ease2 = 0.0f;
621         pchan->scaleIn = 1.0f;
622         pchan->scaleOut = 1.0f;
623 }
624
625 /* clear location of pose-channel */
626 static void pchan_clear_loc(bPoseChannel *pchan)
627 {
628         if ((pchan->protectflag & OB_LOCK_LOCX) == 0)
629                 pchan->loc[0] = 0.0f;
630         if ((pchan->protectflag & OB_LOCK_LOCY) == 0)
631                 pchan->loc[1] = 0.0f;
632         if ((pchan->protectflag & OB_LOCK_LOCZ) == 0)
633                 pchan->loc[2] = 0.0f;
634 }
635
636 /* clear rotation of pose-channel */
637 static void pchan_clear_rot(bPoseChannel *pchan)
638 {
639         if (pchan->protectflag & (OB_LOCK_ROTX | OB_LOCK_ROTY | OB_LOCK_ROTZ | OB_LOCK_ROTW)) {
640                 /* check if convert to eulers for locking... */
641                 if (pchan->protectflag & OB_LOCK_ROT4D) {
642                         /* perform clamping on a component by component basis */
643                         if (pchan->rotmode == ROT_MODE_AXISANGLE) {
644                                 if ((pchan->protectflag & OB_LOCK_ROTW) == 0)
645                                         pchan->rotAngle = 0.0f;
646                                 if ((pchan->protectflag & OB_LOCK_ROTX) == 0)
647                                         pchan->rotAxis[0] = 0.0f;
648                                 if ((pchan->protectflag & OB_LOCK_ROTY) == 0)
649                                         pchan->rotAxis[1] = 0.0f;
650                                 if ((pchan->protectflag & OB_LOCK_ROTZ) == 0)
651                                         pchan->rotAxis[2] = 0.0f;
652
653                                 /* check validity of axis - axis should never be 0,0,0 (if so, then we make it rotate about y) */
654                                 if (IS_EQF(pchan->rotAxis[0], pchan->rotAxis[1]) && IS_EQF(pchan->rotAxis[1], pchan->rotAxis[2]))
655                                         pchan->rotAxis[1] = 1.0f;
656                         }
657                         else if (pchan->rotmode == ROT_MODE_QUAT) {
658                                 if ((pchan->protectflag & OB_LOCK_ROTW) == 0)
659                                         pchan->quat[0] = 1.0f;
660                                 if ((pchan->protectflag & OB_LOCK_ROTX) == 0)
661                                         pchan->quat[1] = 0.0f;
662                                 if ((pchan->protectflag & OB_LOCK_ROTY) == 0)
663                                         pchan->quat[2] = 0.0f;
664                                 if ((pchan->protectflag & OB_LOCK_ROTZ) == 0)
665                                         pchan->quat[3] = 0.0f;
666                         }
667                         else {
668                                 /* the flag may have been set for the other modes, so just ignore the extra flag... */
669                                 if ((pchan->protectflag & OB_LOCK_ROTX) == 0)
670                                         pchan->eul[0] = 0.0f;
671                                 if ((pchan->protectflag & OB_LOCK_ROTY) == 0)
672                                         pchan->eul[1] = 0.0f;
673                                 if ((pchan->protectflag & OB_LOCK_ROTZ) == 0)
674                                         pchan->eul[2] = 0.0f;
675                         }
676                 }
677                 else {
678                         /* perform clamping using euler form (3-components) */
679                         float eul[3], oldeul[3], quat1[4] = {0};
680                         float qlen = 0.0f;
681
682                         if (pchan->rotmode == ROT_MODE_QUAT) {
683                                 qlen = normalize_qt_qt(quat1, pchan->quat);
684                                 quat_to_eul(oldeul, quat1);
685                         }
686                         else if (pchan->rotmode == ROT_MODE_AXISANGLE) {
687                                 axis_angle_to_eulO(oldeul, EULER_ORDER_DEFAULT, pchan->rotAxis, pchan->rotAngle);
688                         }
689                         else {
690                                 copy_v3_v3(oldeul, pchan->eul);
691                         }
692
693                         eul[0] = eul[1] = eul[2] = 0.0f;
694
695                         if (pchan->protectflag & OB_LOCK_ROTX)
696                                 eul[0] = oldeul[0];
697                         if (pchan->protectflag & OB_LOCK_ROTY)
698                                 eul[1] = oldeul[1];
699                         if (pchan->protectflag & OB_LOCK_ROTZ)
700                                 eul[2] = oldeul[2];
701
702                         if (pchan->rotmode == ROT_MODE_QUAT) {
703                                 eul_to_quat(pchan->quat, eul);
704
705                                 /* restore original quat size */
706                                 mul_qt_fl(pchan->quat, qlen);
707
708                                 /* quaternions flip w sign to accumulate rotations correctly */
709                                 if ((quat1[0] < 0.0f && pchan->quat[0] > 0.0f) || (quat1[0] > 0.0f && pchan->quat[0] < 0.0f)) {
710                                         mul_qt_fl(pchan->quat, -1.0f);
711                                 }
712                         }
713                         else if (pchan->rotmode == ROT_MODE_AXISANGLE) {
714                                 eulO_to_axis_angle(pchan->rotAxis, &pchan->rotAngle, eul, EULER_ORDER_DEFAULT);
715                         }
716                         else {
717                                 copy_v3_v3(pchan->eul, eul);
718                         }
719                 }
720         }       /* Duplicated in source/blender/editors/object/object_transform.c */
721         else {
722                 if (pchan->rotmode == ROT_MODE_QUAT) {
723                         unit_qt(pchan->quat);
724                 }
725                 else if (pchan->rotmode == ROT_MODE_AXISANGLE) {
726                         /* by default, make rotation of 0 radians around y-axis (roll) */
727                         unit_axis_angle(pchan->rotAxis, &pchan->rotAngle);
728                 }
729                 else {
730                         zero_v3(pchan->eul);
731                 }
732         }
733
734         /* Clear also Bendy Bone stuff - Roll is obvious,
735          * but Curve X/Y stuff is also kindof rotational in nature... */
736         pchan->roll1 = 0.0f;
737         pchan->roll2 = 0.0f;
738
739         pchan->curveInX = 0.0f;
740         pchan->curveInY = 0.0f;
741         pchan->curveOutX = 0.0f;
742         pchan->curveOutY = 0.0f;
743 }
744
745 /* clear loc/rot/scale of pose-channel */
746 static void pchan_clear_transforms(bPoseChannel *pchan)
747 {
748         pchan_clear_loc(pchan);
749         pchan_clear_rot(pchan);
750         pchan_clear_scale(pchan);
751 }
752
753 /* --------------- */
754
755 /* generic exec for clear-pose operators */
756 static int pose_clear_transform_generic_exec(bContext *C, wmOperator *op,
757                                              void (*clear_func)(bPoseChannel *), const char default_ksName[])
758 {
759         Main *bmain = CTX_data_main(C);
760         Scene *scene = CTX_data_scene(C);
761         Object *ob = BKE_object_pose_armature_get(CTX_data_active_object(C));
762         short autokey = 0;
763
764         /* sanity checks */
765         if (ELEM(NULL, clear_func, default_ksName)) {
766                 BKE_report(op->reports, RPT_ERROR, "Programming error: missing clear transform function or keying set name");
767                 return OPERATOR_CANCELLED;
768         }
769
770         /* only clear relevant transforms for selected bones */
771         CTX_DATA_BEGIN(C, bPoseChannel *, pchan, selected_pose_bones)
772         {
773                 /* run provided clearing function */
774                 clear_func(pchan);
775
776                 /* do auto-keyframing as appropriate */
777                 if (autokeyframe_cfra_can_key(scene, &ob->id)) {
778                         /* clear any unkeyed tags */
779                         if (pchan->bone)
780                                 pchan->bone->flag &= ~BONE_UNKEYED;
781
782                         /* tag for autokeying later */
783                         autokey = 1;
784                 }
785                 else {
786                         /* add unkeyed tags */
787                         if (pchan->bone)
788                                 pchan->bone->flag |= BONE_UNKEYED;
789                 }
790         }
791         CTX_DATA_END;
792
793         /* perform autokeying on the bones if needed */
794         if (autokey) {
795                 /* get KeyingSet to use */
796                 KeyingSet *ks = ANIM_get_keyingset_for_autokeying(scene, default_ksName);
797
798                 /* insert keyframes */
799                 ANIM_apply_keyingset(C, NULL, NULL, ks, MODIFYKEY_MODE_INSERT, (float)CFRA);
800
801                 /* now recalculate paths */
802                 if ((ob->pose->avs.path_bakeflag & MOTIONPATH_BAKE_HAS_PATHS))
803                         ED_pose_recalculate_paths(bmain, scene, ob);
804         }
805
806         DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
807
808         /* note, notifier might evolve */
809         WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, ob);
810
811         return OPERATOR_FINISHED;
812 }
813
814 /* --------------- */
815
816 static int pose_clear_scale_exec(bContext *C, wmOperator *op)
817 {
818         return pose_clear_transform_generic_exec(C, op, pchan_clear_scale, ANIM_KS_SCALING_ID);
819 }
820
821 void POSE_OT_scale_clear(wmOperatorType *ot)
822 {
823         /* identifiers */
824         ot->name = "Clear Pose Scale";
825         ot->idname = "POSE_OT_scale_clear";
826         ot->description = "Reset scaling of selected bones to their default values";
827
828         /* api callbacks */
829         ot->exec = pose_clear_scale_exec;
830         ot->poll = ED_operator_posemode;
831
832         /* flags */
833         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
834 }
835
836
837 static int pose_clear_rot_exec(bContext *C, wmOperator *op)
838 {
839         return pose_clear_transform_generic_exec(C, op, pchan_clear_rot, ANIM_KS_ROTATION_ID);
840 }
841
842 void POSE_OT_rot_clear(wmOperatorType *ot)
843 {
844         /* identifiers */
845         ot->name = "Clear Pose Rotation";
846         ot->idname = "POSE_OT_rot_clear";
847         ot->description = "Reset rotations of selected bones to their default values";
848
849         /* api callbacks */
850         ot->exec = pose_clear_rot_exec;
851         ot->poll = ED_operator_posemode;
852
853         /* flags */
854         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
855 }
856
857
858 static int pose_clear_loc_exec(bContext *C, wmOperator *op)
859 {
860         return pose_clear_transform_generic_exec(C, op, pchan_clear_loc, ANIM_KS_LOCATION_ID);
861 }
862
863 void POSE_OT_loc_clear(wmOperatorType *ot)
864 {
865         /* identifiers */
866         ot->name = "Clear Pose Location";
867         ot->idname = "POSE_OT_loc_clear";
868         ot->description = "Reset locations of selected bones to their default values";
869
870         /* api callbacks */
871         ot->exec = pose_clear_loc_exec;
872         ot->poll = ED_operator_posemode;
873
874         /* flags */
875         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
876 }
877
878
879 static int pose_clear_transforms_exec(bContext *C, wmOperator *op)
880 {
881         return pose_clear_transform_generic_exec(C, op, pchan_clear_transforms, ANIM_KS_LOC_ROT_SCALE_ID);
882 }
883
884 void POSE_OT_transforms_clear(wmOperatorType *ot)
885 {
886         /* identifiers */
887         ot->name = "Clear Pose Transforms";
888         ot->idname = "POSE_OT_transforms_clear";
889         ot->description = "Reset location, rotation, and scaling of selected bones to their default values";
890
891         /* api callbacks */
892         ot->exec = pose_clear_transforms_exec;
893         ot->poll = ED_operator_posemode;
894
895         /* flags */
896         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
897 }
898
899 /* ********************************************** */
900 /* Clear User Transforms */
901
902 static int pose_clear_user_transforms_exec(bContext *C, wmOperator *op)
903 {
904         Scene *scene = CTX_data_scene(C);
905         Object *ob = BKE_object_pose_armature_get(CTX_data_active_object(C));
906         float cframe = (float)CFRA;
907         const bool only_select = RNA_boolean_get(op->ptr, "only_selected");
908
909         if ((ob->adt) && (ob->adt->action)) {
910                 /* XXX: this is just like this to avoid contaminating anything else;
911                  * just pose values should change, so this should be fine
912                  */
913                 bPose *dummyPose = NULL;
914                 Object workob = {{NULL}};
915                 bPoseChannel *pchan;
916
917                 /* execute animation step for current frame using a dummy copy of the pose */
918                 BKE_pose_copy_data(&dummyPose, ob->pose, 0);
919
920                 BLI_strncpy(workob.id.name, "OB<ClearTfmWorkOb>", sizeof(workob.id.name));
921                 workob.type = OB_ARMATURE;
922                 workob.data = ob->data;
923                 workob.adt = ob->adt;
924                 workob.pose = dummyPose;
925
926                 BKE_animsys_evaluate_animdata(scene, &workob.id, workob.adt, cframe, ADT_RECALC_ANIM);
927
928                 /* copy back values, but on selected bones only  */
929                 for (pchan = dummyPose->chanbase.first; pchan; pchan = pchan->next) {
930                         pose_bone_do_paste(ob, pchan, only_select, 0);
931                 }
932
933                 /* free temp data - free manually as was copied without constraints */
934                 for (pchan = dummyPose->chanbase.first; pchan; pchan = pchan->next) {
935                         if (pchan->prop) {
936                                 IDP_FreeProperty(pchan->prop);
937                                 MEM_freeN(pchan->prop);
938                         }
939                 }
940
941                 /* was copied without constraints */
942                 BLI_freelistN(&dummyPose->chanbase);
943                 MEM_freeN(dummyPose);
944         }
945         else {
946                 /* no animation, so just reset whole pose to rest pose
947                  * (cannot just restore for selected though)
948                  */
949                 BKE_pose_rest(ob->pose);
950         }
951
952         /* notifiers and updates */
953         DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
954         WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, ob);
955
956         return OPERATOR_FINISHED;
957 }
958
959 void POSE_OT_user_transforms_clear(wmOperatorType *ot)
960 {
961         /* identifiers */
962         ot->name = "Clear User Transforms";
963         ot->idname = "POSE_OT_user_transforms_clear";
964         ot->description = "Reset pose on selected bones to keyframed state";
965
966         /* callbacks */
967         ot->exec = pose_clear_user_transforms_exec;
968         ot->poll = ED_operator_posemode;
969
970         /* flags */
971         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
972
973         /* properties */
974         RNA_def_boolean(ot->srna, "only_selected", true, "Only Selected", "Only visible/selected bones");
975 }