doxygen: add newline after \file
[blender.git] / source / blender / editors / armature / pose_lib.c
1 /*
2  * This program is free software; you can redistribute it and/or
3  * modify it under the terms of the GNU General Public License
4  * as published by the Free Software Foundation; either version 2
5  * of the License, or (at your option) any later version.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * along with this program; if not, write to the Free Software Foundation,
14  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
15  *
16  * The Original Code is Copyright (C) 2007, Blender Foundation
17  * This is a new part of Blender
18  */
19
20 /** \file
21  * \ingroup edarmature
22  */
23
24 #include <string.h>
25 #include <math.h>
26
27 #include "MEM_guardedalloc.h"
28
29 #include "BLI_blenlib.h"
30 #include "BLI_dlrbTree.h"
31 #include "BLI_string_utils.h"
32
33 #include "BLT_translation.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_animsys.h"
42 #include "BKE_armature.h"
43 #include "BKE_idprop.h"
44 #include "BKE_library.h"
45 #include "BKE_main.h"
46 #include "BKE_object.h"
47
48 #include "BKE_context.h"
49 #include "BKE_report.h"
50
51 #include "DEG_depsgraph.h"
52
53 #include "RNA_access.h"
54 #include "RNA_define.h"
55 #include "RNA_enum_types.h"
56
57 #include "WM_api.h"
58 #include "WM_types.h"
59
60 #include "UI_interface.h"
61 #include "UI_resources.h"
62
63 #include "ED_anim_api.h"
64 #include "ED_armature.h"
65 #include "ED_keyframes_draw.h"
66 #include "ED_keyframing.h"
67 #include "ED_keyframes_edit.h"
68 #include "ED_screen.h"
69 #include "ED_object.h"
70
71 #include "armature_intern.h"
72
73 /* ******* XXX ********** */
74
75 static void action_set_activemarker(void *UNUSED(a), void *UNUSED(b), void *UNUSED(c)) {}
76
77 /* ************************************************************* */
78 /* == POSE-LIBRARY TOOL FOR BLENDER ==
79  *
80  * Overview:
81  *  This tool allows animators to store a set of frequently used poses to dump into
82  *  the active action to help in "budget" productions to quickly block out new actions.
83  *  It acts as a kind of "glorified clipboard for poses", allowing for naming of poses.
84  *
85  * Features:
86  * - PoseLibs are simply normal Actions
87  * - Each "pose" is simply a set of keyframes that occur on a particular frame
88  *   -> a set of TimeMarkers that belong to each Action, help 'label' where a 'pose' can be
89  *      found in the Action
90  * - The Scrollwheel or PageUp/Down buttons when used in a special mode or after pressing/holding
91  *   [a modifier] key, cycles through the poses available for the active pose's poselib, allowing the
92  *   animator to preview what action best suits that pose
93  */
94 /* ************************************************************* */
95
96
97 /* gets the first available frame in poselib to store a pose on
98  * - frames start from 1, and a pose should occur on every frame... 0 is error!
99  */
100 static int poselib_get_free_index(bAction *act)
101 {
102         TimeMarker *marker;
103         int low = 0, high = 0;
104         bool changed = false;
105
106         /* sanity checks */
107         if (ELEM(NULL, act, act->markers.first)) return 1;
108
109         /* As poses are not stored in chronological order, we must iterate over this list
110          * a few times until we don't make any new discoveries (mostly about the lower bound).
111          * Prevents problems with deleting then trying to add new poses [#27412]
112          */
113         do {
114                 changed = false;
115
116                 for (marker = act->markers.first; marker; marker = marker->next) {
117                         /* only increase low if value is 1 greater than low, to find "gaps" where
118                          * poses were removed from the poselib
119                          */
120                         if (marker->frame == (low + 1)) {
121                                 low++;
122                                 changed = true;
123                         }
124
125                         /* value replaces high if it is the highest value encountered yet */
126                         if (marker->frame > high) {
127                                 high = marker->frame;
128                                 changed = true;
129                         }
130                 }
131         } while (changed != 0);
132
133         /* - if low is not equal to high, then low+1 is a gap
134          * - if low is equal to high, then high+1 is the next index (add at end)
135          */
136         if (low < high)
137                 return (low + 1);
138         else
139                 return (high + 1);
140 }
141
142 /* returns the active pose for a poselib */
143 static TimeMarker *poselib_get_active_pose(bAction *act)
144 {
145         if ((act) && (act->active_marker))
146                 return BLI_findlink(&act->markers, act->active_marker - 1);
147         else
148                 return NULL;
149 }
150
151 /* Get object that Pose Lib should be found on */
152 /* XXX C can be zero */
153 static Object *get_poselib_object(bContext *C)
154 {
155         ScrArea *sa;
156
157         /* sanity check */
158         if (C == NULL)
159                 return NULL;
160
161         sa = CTX_wm_area(C);
162
163         if (sa && (sa->spacetype == SPACE_PROPERTIES))
164                 return ED_object_context(C);
165         else
166                 return BKE_object_pose_armature_get(CTX_data_active_object(C));
167 }
168
169 /* Poll callback for operators that require existing PoseLib data (with poses) to work */
170 static bool has_poselib_pose_data_poll(bContext *C)
171 {
172         Object *ob = get_poselib_object(C);
173         return (ob && ob->poselib);
174 }
175
176 /* Poll callback for operators that require existing PoseLib data (with poses)
177  * as they need to do some editing work on those poses (i.e. not on lib-linked actions)
178  */
179 static bool has_poselib_pose_data_for_editing_poll(bContext *C)
180 {
181         Object *ob = get_poselib_object(C);
182         return (ob && ob->poselib && !ID_IS_LINKED(ob->poselib));
183 }
184
185 /* ----------------------------------- */
186
187 /* Initialize a new poselib (whether it is needed or not) */
188 static bAction *poselib_init_new(Main *bmain, Object *ob)
189 {
190         /* sanity checks - only for armatures */
191         if (ELEM(NULL, ob, ob->pose))
192                 return NULL;
193
194         /* init object's poselib action (unlink old one if there) */
195         if (ob->poselib)
196                 id_us_min(&ob->poselib->id);
197
198         ob->poselib = BKE_action_add(bmain, "PoseLib");
199         ob->poselib->idroot = ID_OB;
200
201         return ob->poselib;
202 }
203
204 /* Initialize a new poselib (checks if that needs to happen) */
205 static bAction *poselib_validate(Main *bmain, Object *ob)
206 {
207         if (ELEM(NULL, ob, ob->pose))
208                 return NULL;
209         else if (ob->poselib == NULL)
210                 return poselib_init_new(bmain, ob);
211         else
212                 return ob->poselib;
213 }
214
215 /* ************************************************************* */
216 /* Pose Lib UI Operators */
217
218 static int poselib_new_exec(bContext *C, wmOperator *UNUSED(op))
219 {
220         Main *bmain = CTX_data_main(C);
221         Object *ob = get_poselib_object(C);
222
223         /* sanity checks */
224         if (ob == NULL)
225                 return OPERATOR_CANCELLED;
226
227         /* new method here deals with the rest... */
228         poselib_init_new(bmain, ob);
229
230         /* notifier here might evolve? */
231         WM_event_add_notifier(C, NC_OBJECT | ND_POSE, NULL);
232
233         return OPERATOR_FINISHED;
234 }
235
236 void POSELIB_OT_new(wmOperatorType *ot)
237 {
238         /* identifiers */
239         ot->name = "New Pose Library";
240         ot->idname = "POSELIB_OT_new";
241         ot->description = "Add New Pose Library to active Object";
242
243         /* callbacks */
244         ot->exec = poselib_new_exec;
245         ot->poll = ED_operator_posemode;
246
247         /* flags */
248         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
249 }
250
251 /* ------------------------------------------------ */
252
253 static int poselib_unlink_exec(bContext *C, wmOperator *UNUSED(op))
254 {
255         Object *ob = get_poselib_object(C);
256
257         /* sanity checks */
258         if (ELEM(NULL, ob, ob->poselib))
259                 return OPERATOR_CANCELLED;
260
261         /* there should be a poselib (we just checked above!), so just lower its user count and remove */
262         id_us_min(&ob->poselib->id);
263         ob->poselib = NULL;
264
265         /* notifier here might evolve? */
266         WM_event_add_notifier(C, NC_OBJECT | ND_POSE, NULL);
267
268         return OPERATOR_FINISHED;
269 }
270
271 void POSELIB_OT_unlink(wmOperatorType *ot)
272 {
273         /* identifiers */
274         ot->name = "Unlink Pose Library";
275         ot->idname = "POSELIB_OT_unlink";
276         ot->description = "Remove Pose Library from active Object";
277
278         /* callbacks */
279         ot->exec = poselib_unlink_exec;
280         ot->poll = has_poselib_pose_data_poll;
281
282         /* flags */
283         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
284 }
285
286 /* ************************************************************* */
287 /* Pose Editing Operators */
288
289 /* This tool automagically generates/validates poselib data so that it corresponds to the data
290  * in the action. This is for use in making existing actions usable as poselibs.
291  */
292 static int poselib_sanitize_exec(bContext *C, wmOperator *op)
293 {
294         Object *ob = get_poselib_object(C);
295         bAction *act = (ob) ? ob->poselib : NULL;
296         DLRBT_Tree keys;
297         ActKeyColumn *ak;
298         TimeMarker *marker, *markern;
299
300         /* validate action */
301         if (act == NULL) {
302                 BKE_report(op->reports, RPT_WARNING, "No action to validate");
303                 return OPERATOR_CANCELLED;
304         }
305
306         /* determine which frames have keys */
307         BLI_dlrbTree_init(&keys);
308         action_to_keylist(NULL, act, &keys, 0);
309
310         /* for each key, make sure there is a corresponding pose */
311         for (ak = keys.first; ak; ak = ak->next) {
312                 /* check if any pose matches this */
313                 /* TODO: don't go looking through the list like this every time... */
314                 for (marker = act->markers.first; marker; marker = marker->next) {
315                         if (IS_EQ((double)marker->frame, (double)ak->cfra)) {
316                                 marker->flag = -1;
317                                 break;
318                         }
319                 }
320
321                 /* add new if none found */
322                 if (marker == NULL) {
323                         /* add pose to poselib */
324                         marker = MEM_callocN(sizeof(TimeMarker), "ActionMarker");
325
326                         BLI_snprintf(marker->name, sizeof(marker->name), "F%d Pose", (int)ak->cfra);
327
328                         marker->frame = (int)ak->cfra;
329                         marker->flag = -1;
330
331                         BLI_addtail(&act->markers, marker);
332                 }
333         }
334
335         /* remove all untagged poses (unused), and remove all tags */
336         for (marker = act->markers.first; marker; marker = markern) {
337                 markern = marker->next;
338
339                 if (marker->flag != -1)
340                         BLI_freelinkN(&act->markers, marker);
341                 else
342                         marker->flag = 0;
343         }
344
345         /* free temp memory */
346         BLI_dlrbTree_free(&keys);
347
348         /* send notifiers for this - using keyframe editing notifiers, since action
349          * may be being shown in anim editors as active action
350          */
351         WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_EDITED, NULL);
352
353         return OPERATOR_FINISHED;
354 }
355
356 void POSELIB_OT_action_sanitize(wmOperatorType *ot)
357 {
358         /* identifiers */
359         ot->name = "Sanitize Pose Library Action";
360         ot->idname = "POSELIB_OT_action_sanitize";
361         ot->description = "Make action suitable for use as a Pose Library";
362
363         /* callbacks */
364         ot->exec = poselib_sanitize_exec;
365         ot->poll = has_poselib_pose_data_for_editing_poll;
366
367         /* flags */
368         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
369 }
370
371 /* ------------------------------------------ */
372
373 /* Poll callback for adding poses to a PoseLib */
374 static bool poselib_add_poll(bContext *C)
375 {
376         /* There are 2 cases we need to be careful with:
377          *  1) When this operator is invoked from a hotkey, there may be no PoseLib yet
378          *  2) If a PoseLib already exists, we can't edit the action if it is a lib-linked
379          *     actions, as data will be lost when saving the file
380          */
381         if (ED_operator_posemode(C)) {
382                 Object *ob = get_poselib_object(C);
383                 if (ob) {
384                         if ((ob->poselib == NULL) || !ID_IS_LINKED(ob->poselib)) {
385                                 return true;
386                         }
387                 }
388         }
389         return false;
390 }
391
392 static void poselib_add_menu_invoke__replacemenu(bContext *C, uiLayout *layout, void *UNUSED(arg))
393 {
394         Object *ob = get_poselib_object(C);
395         bAction *act = ob->poselib; /* never NULL */
396         TimeMarker *marker;
397
398         wmOperatorType *ot = WM_operatortype_find("POSELIB_OT_pose_add", 1);
399
400         BLI_assert(ot != NULL);
401
402         /* set the operator execution context correctly */
403         uiLayoutSetOperatorContext(layout, WM_OP_EXEC_DEFAULT);
404
405         /* add each marker to this menu */
406         for (marker = act->markers.first; marker; marker = marker->next) {
407                 PointerRNA props_ptr;
408                 uiItemFullO_ptr(
409                         layout, ot,
410                         marker->name, ICON_ARMATURE_DATA, NULL,
411                         WM_OP_EXEC_DEFAULT, 0, &props_ptr);
412                 RNA_int_set(&props_ptr, "frame", marker->frame);
413                 RNA_string_set(&props_ptr, "name", marker->name);
414         }
415 }
416
417 static int poselib_add_menu_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
418 {
419         Scene *scene = CTX_data_scene(C);
420         Object *ob = get_poselib_object(C);
421         bPose *pose = (ob) ? ob->pose : NULL;
422         uiPopupMenu *pup;
423         uiLayout *layout;
424
425         /* sanity check */
426         if (ELEM(NULL, ob, pose))
427                 return OPERATOR_CANCELLED;
428
429         /* start building */
430         pup = UI_popup_menu_begin(C, op->type->name, ICON_NONE);
431         layout = UI_popup_menu_layout(pup);
432         uiLayoutSetOperatorContext(layout, WM_OP_EXEC_DEFAULT);
433
434         /* add new (adds to the first unoccupied frame) */
435         uiItemIntO(layout, IFACE_("Add New"), ICON_NONE, "POSELIB_OT_pose_add", "frame", poselib_get_free_index(ob->poselib));
436
437         /* check if we have any choices to add a new pose in any other way */
438         if ((ob->poselib) && (ob->poselib->markers.first)) {
439                 /* add new (on current frame) */
440                 uiItemIntO(layout, IFACE_("Add New (Current Frame)"), ICON_NONE, "POSELIB_OT_pose_add", "frame", CFRA);
441
442                 /* replace existing - submenu */
443                 uiItemMenuF(layout, IFACE_("Replace Existing..."), 0, poselib_add_menu_invoke__replacemenu, NULL);
444         }
445
446         UI_popup_menu_end(C, pup);
447
448         /* this operator is only for a menu, not used further */
449         return OPERATOR_INTERFACE;
450 }
451
452
453 static int poselib_add_exec(bContext *C, wmOperator *op)
454 {
455         Main *bmain = CTX_data_main(C);
456         Object *ob = get_poselib_object(C);
457         bAction *act = poselib_validate(bmain, ob);
458         bPose *pose = (ob) ? ob->pose : NULL;
459         TimeMarker *marker;
460         KeyingSet *ks;
461         int frame = RNA_int_get(op->ptr, "frame");
462         char name[64];
463
464         /* sanity check (invoke should have checked this anyway) */
465         if (ELEM(NULL, ob, pose))
466                 return OPERATOR_CANCELLED;
467
468         /* get name to give to pose */
469         RNA_string_get(op->ptr, "name", name);
470
471         /* add pose to poselib - replaces any existing pose there
472          * - for the 'replace' option, this should end up finding the appropriate marker,
473          *   so no new one will be added
474          */
475         for (marker = act->markers.first; marker; marker = marker->next) {
476                 if (marker->frame == frame) {
477                         BLI_strncpy(marker->name, name, sizeof(marker->name));
478                         break;
479                 }
480         }
481         if (marker == NULL) {
482                 marker = MEM_callocN(sizeof(TimeMarker), "ActionMarker");
483
484                 BLI_strncpy(marker->name, name, sizeof(marker->name));
485                 marker->frame = frame;
486
487                 BLI_addtail(&act->markers, marker);
488         }
489
490         /* validate name */
491         BLI_uniquename(&act->markers, marker, DATA_("Pose"), '.', offsetof(TimeMarker, name), sizeof(marker->name));
492
493         /* use Keying Set to determine what to store for the pose */
494
495         /* this includes custom props :)*/
496         ks = ANIM_builtin_keyingset_get_named(NULL, ANIM_KS_WHOLE_CHARACTER_SELECTED_ID);
497
498         ANIM_apply_keyingset(C, NULL, act, ks, MODIFYKEY_MODE_INSERT, (float)frame);
499
500         /* store new 'active' pose number */
501         act->active_marker = BLI_listbase_count(&act->markers);
502         DEG_id_tag_update(&act->id, ID_RECALC_COPY_ON_WRITE);
503
504         /* done */
505         return OPERATOR_FINISHED;
506 }
507
508 void POSELIB_OT_pose_add(wmOperatorType *ot)
509 {
510         /* identifiers */
511         ot->name = "PoseLib Add Pose";
512         ot->idname = "POSELIB_OT_pose_add";
513         ot->description = "Add the current Pose to the active Pose Library";
514
515         /* api callbacks */
516         ot->invoke = poselib_add_menu_invoke;
517         ot->exec = poselib_add_exec;
518         ot->poll = poselib_add_poll;
519
520         /* flags */
521         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
522
523         /* properties */
524         RNA_def_int(ot->srna, "frame", 1, 0, INT_MAX, "Frame", "Frame to store pose on", 0, INT_MAX);
525         RNA_def_string(ot->srna, "name", "Pose", 64, "Pose Name", "Name of newly added Pose");
526 }
527
528 /* ----- */
529
530 /* can be called with C == NULL */
531 static const EnumPropertyItem *poselib_stored_pose_itemf(bContext *C, PointerRNA *UNUSED(ptr), PropertyRNA *UNUSED(prop), bool *r_free)
532 {
533         Object *ob = get_poselib_object(C);
534         bAction *act = (ob) ? ob->poselib : NULL;
535         TimeMarker *marker;
536         EnumPropertyItem *item = NULL, item_tmp = {0};
537         int totitem = 0;
538         int i = 0;
539
540         if (C == NULL) {
541                 return DummyRNA_NULL_items;
542         }
543
544         /* check that the action exists */
545         if (act) {
546                 /* add each marker to the list */
547                 for (marker = act->markers.first, i = 0; marker; marker = marker->next, i++) {
548                         item_tmp.identifier = item_tmp.name = marker->name;
549                         item_tmp.icon = ICON_ARMATURE_DATA;
550                         item_tmp.value = i;
551                         RNA_enum_item_add(&item, &totitem, &item_tmp);
552                 }
553         }
554
555         RNA_enum_item_end(&item, &totitem);
556         *r_free = true;
557
558         return item;
559 }
560
561 static int poselib_remove_exec(bContext *C, wmOperator *op)
562 {
563         Object *ob = get_poselib_object(C);
564         bAction *act = (ob) ? ob->poselib : NULL;
565         TimeMarker *marker;
566         int marker_index;
567         FCurve *fcu;
568         PropertyRNA *prop;
569
570         /* check if valid poselib */
571         if (act == NULL) {
572                 BKE_report(op->reports, RPT_ERROR, "Object does not have pose lib data");
573                 return OPERATOR_CANCELLED;
574         }
575
576         prop = RNA_struct_find_property(op->ptr, "pose");
577         if (RNA_property_is_set(op->ptr, prop)) {
578                 marker_index = RNA_property_enum_get(op->ptr, prop);
579         }
580         else {
581                 marker_index = act->active_marker - 1;
582         }
583
584         /* get index (and pointer) of pose to remove */
585         marker = BLI_findlink(&act->markers, marker_index);
586         if (marker == NULL) {
587                 BKE_reportf(op->reports, RPT_ERROR, "Invalid pose specified %d", marker_index);
588                 return OPERATOR_CANCELLED;
589         }
590
591         /* remove relevant keyframes */
592         for (fcu = act->curves.first; fcu; fcu = fcu->next) {
593                 BezTriple *bezt;
594                 unsigned int i;
595
596                 if (fcu->bezt) {
597                         for (i = 0, bezt = fcu->bezt; i < fcu->totvert; i++, bezt++) {
598                                 /* check if remove */
599                                 if (IS_EQF(bezt->vec[1][0], (float)marker->frame)) {
600                                         delete_fcurve_key(fcu, i, 1);
601                                         break;
602                                 }
603                         }
604                 }
605         }
606
607         /* remove poselib from list */
608         BLI_freelinkN(&act->markers, marker);
609
610         /* fix active pose number */
611         act->active_marker = 0;
612
613         /* send notifiers for this - using keyframe editing notifiers, since action
614          * may be being shown in anim editors as active action
615          */
616         WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_EDITED, NULL);
617         DEG_id_tag_update(&act->id, ID_RECALC_COPY_ON_WRITE);
618
619         /* done */
620         return OPERATOR_FINISHED;
621 }
622
623 void POSELIB_OT_pose_remove(wmOperatorType *ot)
624 {
625         PropertyRNA *prop;
626
627         /* identifiers */
628         ot->name = "PoseLib Remove Pose";
629         ot->idname = "POSELIB_OT_pose_remove";
630         ot->description = "Remove nth pose from the active Pose Library";
631
632         /* api callbacks */
633         ot->invoke = WM_menu_invoke;
634         ot->exec = poselib_remove_exec;
635         ot->poll = has_poselib_pose_data_for_editing_poll;
636
637         /* flags */
638         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
639
640         /* properties */
641         prop = RNA_def_enum(ot->srna, "pose", DummyRNA_NULL_items, 0, "Pose", "The pose to remove");
642         RNA_def_enum_funcs(prop, poselib_stored_pose_itemf);
643         RNA_def_property_flag(prop, PROP_ENUM_NO_TRANSLATE);
644         ot->prop = prop;
645 }
646
647 static int poselib_rename_invoke(bContext *C, wmOperator *op, const wmEvent *event)
648 {
649         Object *ob = get_poselib_object(C);
650         bAction *act = (ob) ? ob->poselib : NULL;
651         TimeMarker *marker;
652
653         /* check if valid poselib */
654         if (act == NULL) {
655                 BKE_report(op->reports, RPT_ERROR, "Object does not have pose lib data");
656                 return OPERATOR_CANCELLED;
657         }
658
659         /* get index (and pointer) of pose to remove */
660         marker = BLI_findlink(&act->markers, act->active_marker - 1);
661         if (marker == NULL) {
662                 BKE_report(op->reports, RPT_ERROR, "Invalid index for pose");
663                 return OPERATOR_CANCELLED;
664         }
665         else {
666                 /* use the existing name of the marker as the name, and use the active marker as the one to rename */
667                 RNA_enum_set(op->ptr, "pose", act->active_marker - 1);
668                 RNA_string_set(op->ptr, "name", marker->name);
669         }
670
671         /* part to sync with other similar operators... */
672         return WM_operator_props_popup_confirm(C, op, event);
673 }
674
675 static int poselib_rename_exec(bContext *C, wmOperator *op)
676 {
677         Object *ob = BKE_object_pose_armature_get(CTX_data_active_object(C));
678         bAction *act = (ob) ? ob->poselib : NULL;
679         TimeMarker *marker;
680         char newname[64];
681
682         /* check if valid poselib */
683         if (act == NULL) {
684                 BKE_report(op->reports, RPT_ERROR, "Object does not have pose lib data");
685                 return OPERATOR_CANCELLED;
686         }
687
688         /* get index (and pointer) of pose to remove */
689         marker = BLI_findlink(&act->markers, RNA_enum_get(op->ptr, "pose"));
690         if (marker == NULL) {
691                 BKE_report(op->reports, RPT_ERROR, "Invalid index for pose");
692                 return OPERATOR_CANCELLED;
693         }
694
695         /* get new name */
696         RNA_string_get(op->ptr, "name", newname);
697
698         /* copy name and validate it */
699         BLI_strncpy(marker->name, newname, sizeof(marker->name));
700         BLI_uniquename(&act->markers, marker, DATA_("Pose"), '.', offsetof(TimeMarker, name), sizeof(marker->name));
701
702         /* send notifiers for this - using keyframe editing notifiers, since action
703          * may be being shown in anim editors as active action
704          */
705         WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_EDITED, NULL);
706
707         /* done */
708         return OPERATOR_FINISHED;
709 }
710
711 void POSELIB_OT_pose_rename(wmOperatorType *ot)
712 {
713         PropertyRNA *prop;
714
715         /* identifiers */
716         ot->name = "PoseLib Rename Pose";
717         ot->idname = "POSELIB_OT_pose_rename";
718         ot->description = "Rename specified pose from the active Pose Library";
719
720         /* api callbacks */
721         ot->invoke = poselib_rename_invoke;
722         ot->exec = poselib_rename_exec;
723         ot->poll = has_poselib_pose_data_for_editing_poll;
724
725         /* flags */
726         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
727
728         /* properties */
729         /* NOTE: name not pose is the operator's "main" property,
730          * so that it will get activated in the popup for easy renaming */
731         ot->prop = RNA_def_string(ot->srna, "name", "RenamedPose", 64, "New Pose Name", "New name for pose");
732         prop = RNA_def_enum(ot->srna, "pose", DummyRNA_NULL_items, 0, "Pose", "The pose to rename");
733         RNA_def_enum_funcs(prop, poselib_stored_pose_itemf);
734         RNA_def_property_flag(prop, PROP_ENUM_NO_TRANSLATE);
735 }
736
737 static int poselib_move_exec(bContext *C, wmOperator *op)
738 {
739         Object *ob = get_poselib_object(C);
740         bAction *act = (ob) ? ob->poselib : NULL;
741         TimeMarker *marker;
742         int marker_index;
743         int dir;
744         PropertyRNA *prop;
745
746         /* check if valid poselib */
747         if (act == NULL) {
748                 BKE_report(op->reports, RPT_ERROR, "Object does not have pose lib data");
749                 return OPERATOR_CANCELLED;
750         }
751
752         prop = RNA_struct_find_property(op->ptr, "pose");
753         if (RNA_property_is_set(op->ptr, prop)) {
754                 marker_index = RNA_property_enum_get(op->ptr, prop);
755         }
756         else {
757                 marker_index = act->active_marker - 1;
758         }
759
760         /* get index (and pointer) of pose to remove */
761         marker = BLI_findlink(&act->markers, marker_index);
762         if (marker == NULL) {
763                 BKE_reportf(op->reports, RPT_ERROR, "Invalid pose specified %d", marker_index);
764                 return OPERATOR_CANCELLED;
765         }
766
767         dir = RNA_enum_get(op->ptr, "direction");
768
769         /* move pose */
770         if (BLI_listbase_link_move(&act->markers, marker, dir)) {
771                 act->active_marker = marker_index + dir + 1;
772
773                 /* send notifiers for this - using keyframe editing notifiers, since action
774                  * may be being shown in anim editors as active action
775                  */
776                 WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_EDITED, NULL);
777         }
778         else {
779                 return OPERATOR_CANCELLED;
780         }
781
782         /* done */
783         return OPERATOR_FINISHED;
784 }
785
786 void POSELIB_OT_pose_move(wmOperatorType *ot)
787 {
788         PropertyRNA *prop;
789         static const EnumPropertyItem pose_lib_pose_move[] = {
790                 {-1, "UP", 0, "Up", ""},
791                 {1, "DOWN", 0, "Down", ""},
792                 {0, NULL, 0, NULL, NULL},
793         };
794
795         /* identifiers */
796         ot->name = "PoseLib Move Pose";
797         ot->idname = "POSELIB_OT_pose_move";
798         ot->description = "Move the pose up or down in the active Pose Library";
799
800         /* api callbacks */
801         ot->invoke = WM_menu_invoke;
802         ot->exec = poselib_move_exec;
803         ot->poll = has_poselib_pose_data_for_editing_poll;
804
805         /* flags */
806         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
807
808         /* properties */
809         prop = RNA_def_enum(ot->srna, "pose", DummyRNA_NULL_items, 0, "Pose", "The pose to move");
810         RNA_def_enum_funcs(prop, poselib_stored_pose_itemf);
811         RNA_def_property_flag(prop, PROP_ENUM_NO_TRANSLATE);
812         ot->prop = prop;
813
814         RNA_def_enum(ot->srna, "direction", pose_lib_pose_move, 0, "Direction",
815                      "Direction to move the chosen pose towards");
816 }
817
818
819
820 /* ************************************************************* */
821 /* Pose-Lib Browsing/Previewing Operator */
822
823 /* Simple struct for storing settings/data for use during PoseLib preview */
824 typedef struct tPoseLib_PreviewData {
825         /** tPoseLib_Backup structs for restoring poses. */
826         ListBase backups;
827         /** LinkData structs storing list of poses which match the current search-string. */
828         ListBase searchp;
829
830         /** active scene. */
831         Scene *scene;
832         /** active area. */
833         ScrArea *sa;
834
835         /** RNA-Pointer to Object 'ob' .*/
836         PointerRNA rna_ptr;
837         /** object to work on. */
838         Object *ob;
839         /** object's armature data. */
840         bArmature *arm;
841         /** object's pose. */
842         bPose *pose;
843         /** poselib to use. */
844         bAction *act;
845         /** 'active' pose. */
846         TimeMarker *marker;
847
848         /** total number of elements to work on. */
849         int totcount;
850
851         /** state of main loop. */
852         short state;
853         /** redraw/update settings during main loop. */
854         short redraw;
855         /** flags for various settings. */
856         short flag;
857
858         /** position of cursor in searchstr (cursor occurs before the item at the nominated index) */
859         short search_cursor;
860         /** (Part of) Name to search for to filter poses that get shown. */
861         char searchstr[64];
862         /** Previously set searchstr (from last loop run),
863          * so that we can detected when to rebuild searchp. */
864         char searchold[64];
865
866         /** Info-text to print in header. */
867         char headerstr[UI_MAX_DRAW_STR];
868 } tPoseLib_PreviewData;
869
870 /* defines for tPoseLib_PreviewData->state values */
871 enum {
872         PL_PREVIEW_ERROR = -1,
873         PL_PREVIEW_RUNNING,
874         PL_PREVIEW_CONFIRM,
875         PL_PREVIEW_CANCEL,
876         PL_PREVIEW_RUNONCE,
877 };
878
879 /* defines for tPoseLib_PreviewData->redraw values */
880 enum {
881         PL_PREVIEW_NOREDRAW = 0,
882         PL_PREVIEW_REDRAWALL,
883         PL_PREVIEW_REDRAWHEADER,
884 };
885
886 /* defines for tPoseLib_PreviewData->flag values */
887 enum {
888         PL_PREVIEW_FIRSTTIME    = (1 << 0),
889         PL_PREVIEW_SHOWORIGINAL = (1 << 1),
890         PL_PREVIEW_ANY_BONE_SELECTED = (1 << 2),
891 };
892
893 /* ---------------------------- */
894
895 /* simple struct for storing backup info */
896 typedef struct tPoseLib_Backup {
897         struct tPoseLib_Backup *next, *prev;
898
899         bPoseChannel *pchan;        /* pose channel backups are for */
900
901         bPoseChannel olddata;       /* copy of pose channel's old data (at start) */
902         IDProperty *oldprops;       /* copy (needs freeing) of pose channel's properties (at start) */
903 } tPoseLib_Backup;
904
905 /* Makes a copy of the current pose for restoration purposes - doesn't do constraints currently */
906 static void poselib_backup_posecopy(tPoseLib_PreviewData *pld)
907 {
908         bActionGroup *agrp;
909         bPoseChannel *pchan;
910         bool selected = false;
911
912         /* determine whether any bone is selected. */
913         LISTBASE_FOREACH (bPoseChannel *, bchan, &pld->pose->chanbase) {
914                 selected = bchan->bone != NULL && bchan->bone->flag & BONE_SELECTED;
915                 if (selected) {
916                         pld->flag |= PL_PREVIEW_ANY_BONE_SELECTED;
917                         break;
918                 }
919         }
920         if (!selected) {
921                 pld->flag &= ~PL_PREVIEW_ANY_BONE_SELECTED;
922         }
923
924         /* for each posechannel that has an actionchannel in */
925         for (agrp = pld->act->groups.first; agrp; agrp = agrp->next) {
926                 /* try to find posechannel */
927                 pchan = BKE_pose_channel_find_name(pld->pose, agrp->name);
928
929                 /* backup data if available */
930                 if (pchan) {
931                         tPoseLib_Backup *plb;
932
933                         /* store backup */
934                         plb = MEM_callocN(sizeof(tPoseLib_Backup), "tPoseLib_Backup");
935
936                         plb->pchan = pchan;
937                         memcpy(&plb->olddata, plb->pchan, sizeof(bPoseChannel));
938
939                         if (pchan->prop)
940                                 plb->oldprops = IDP_CopyProperty(pchan->prop);
941
942                         BLI_addtail(&pld->backups, plb);
943
944                         /* mark as being affected */
945                         pld->totcount++;
946                 }
947         }
948 }
949
950 /* Restores original pose */
951 static void poselib_backup_restore(tPoseLib_PreviewData *pld)
952 {
953         tPoseLib_Backup *plb;
954
955         for (plb = pld->backups.first; plb; plb = plb->next) {
956                 /* copy most of data straight back */
957                 memcpy(plb->pchan, &plb->olddata, sizeof(bPoseChannel));
958
959                 /* just overwrite values of properties from the stored copies (there should be some) */
960                 if (plb->oldprops)
961                         IDP_SyncGroupValues(plb->pchan->prop, plb->oldprops);
962
963                 /* TODO: constraints settings aren't restored yet,
964                  * even though these could change (though not that likely) */
965         }
966 }
967
968 /* Free list of backups, including any side data it may use */
969 static void poselib_backup_free_data(tPoseLib_PreviewData *pld)
970 {
971         tPoseLib_Backup *plb, *plbn;
972
973         for (plb = pld->backups.first; plb; plb = plbn) {
974                 plbn = plb->next;
975
976                 /* free custom data */
977                 if (plb->oldprops) {
978                         IDP_FreeProperty(plb->oldprops);
979                         MEM_freeN(plb->oldprops);
980                 }
981
982                 /* free backup element now */
983                 BLI_freelinkN(&pld->backups, plb);
984         }
985 }
986
987 /* ---------------------------- */
988
989 /* Applies the appropriate stored pose from the pose-library to the current pose
990  * - assumes that a valid object, with a poselib has been supplied
991  * - gets the string to print in the header
992  * - this code is based on the code for extract_pose_from_action in blenkernel/action.c
993  */
994 static void poselib_apply_pose(tPoseLib_PreviewData *pld)
995 {
996         PointerRNA *ptr = &pld->rna_ptr;
997         bArmature *arm = pld->arm;
998         bPose *pose = pld->pose;
999         bPoseChannel *pchan;
1000         bAction *act = pld->act;
1001         bActionGroup *agrp;
1002
1003         KeyframeEditData ked = {{NULL}};
1004         KeyframeEditFunc group_ok_cb;
1005         int frame = 1;
1006         const bool any_bone_selected = pld->flag & PL_PREVIEW_ANY_BONE_SELECTED;
1007
1008         /* get the frame */
1009         if (pld->marker)
1010                 frame = pld->marker->frame;
1011         else
1012                 return;
1013
1014
1015         /* init settings for testing groups for keyframes */
1016         group_ok_cb = ANIM_editkeyframes_ok(BEZT_OK_FRAMERANGE);
1017         ked.f1 = ((float)frame) - 0.5f;
1018         ked.f2 = ((float)frame) + 0.5f;
1019
1020         /* start applying - only those channels which have a key at this point in time! */
1021         for (agrp = act->groups.first; agrp; agrp = agrp->next) {
1022                 /* check if group has any keyframes */
1023                 if (ANIM_animchanneldata_keyframes_loop(&ked, NULL, agrp, ALE_GROUP, NULL, group_ok_cb, NULL)) {
1024                         /* has keyframe on this frame, so try to get a PoseChannel with this name */
1025                         pchan = BKE_pose_channel_find_name(pose, agrp->name);
1026
1027                         if (pchan) {
1028                                 bool ok = 0;
1029
1030                                 /* check if this bone should get any animation applied */
1031                                 if (!any_bone_selected) {
1032                                         /* if no bones are selected, then any bone is ok */
1033                                         ok = 1;
1034                                 }
1035                                 else if (pchan->bone) {
1036                                         /* only ok if bone is visible and selected */
1037                                         if ((pchan->bone->flag & BONE_SELECTED) &&
1038                                             (pchan->bone->flag & BONE_HIDDEN_P) == 0 &&
1039                                             (pchan->bone->layer & arm->layer))
1040                                         {
1041                                                 ok = 1;
1042                                         }
1043                                 }
1044
1045                                 if (ok)
1046                                         animsys_evaluate_action_group(ptr, act, agrp, (float)frame);
1047                         }
1048                 }
1049         }
1050 }
1051
1052 /* Auto-keys/tags bones affected by the pose used from the poselib */
1053 static void poselib_keytag_pose(bContext *C, Scene *scene, tPoseLib_PreviewData *pld)
1054 {
1055         bPose *pose = pld->pose;
1056         bPoseChannel *pchan;
1057         bAction *act = pld->act;
1058         bActionGroup *agrp;
1059
1060         KeyingSet *ks = ANIM_get_keyingset_for_autokeying(scene, ANIM_KS_WHOLE_CHARACTER_ID);
1061         ListBase dsources = {NULL, NULL};
1062         bool autokey = autokeyframe_cfra_can_key(scene, &pld->ob->id);
1063         const bool any_bone_selected = pld->flag & PL_PREVIEW_ANY_BONE_SELECTED;
1064
1065         /* start tagging/keying */
1066         for (agrp = act->groups.first; agrp; agrp = agrp->next) {
1067                 /* only for selected bones unless there aren't any selected, in which case all are included  */
1068                 pchan = BKE_pose_channel_find_name(pose, agrp->name);
1069
1070                 if (pchan) {
1071                         if (!any_bone_selected || ((pchan->bone) && (pchan->bone->flag & BONE_SELECTED))) {
1072                                 if (autokey) {
1073                                         /* add datasource override for the PoseChannel, to be used later */
1074                                         ANIM_relative_keyingset_add_source(&dsources, &pld->ob->id, &RNA_PoseBone, pchan);
1075
1076                                         /* clear any unkeyed tags */
1077                                         if (pchan->bone)
1078                                                 pchan->bone->flag &= ~BONE_UNKEYED;
1079                                 }
1080                                 else {
1081                                         /* add unkeyed tags */
1082                                         if (pchan->bone)
1083                                                 pchan->bone->flag |= BONE_UNKEYED;
1084                                 }
1085                         }
1086                 }
1087         }
1088
1089         /* perform actual auto-keying now */
1090         if (autokey) {
1091                 /* insert keyframes for all relevant bones in one go */
1092                 ANIM_apply_keyingset(C, &dsources, NULL, ks, MODIFYKEY_MODE_INSERT, (float)CFRA);
1093                 BLI_freelistN(&dsources);
1094         }
1095
1096         /* send notifiers for this */
1097         WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_EDITED, NULL);
1098 }
1099
1100 /* Apply the relevant changes to the pose */
1101 static void poselib_preview_apply(bContext *C, wmOperator *op)
1102 {
1103         tPoseLib_PreviewData *pld = (tPoseLib_PreviewData *)op->customdata;
1104
1105         /* only recalc pose (and its dependencies) if pose has changed */
1106         if (pld->redraw == PL_PREVIEW_REDRAWALL) {
1107                 /* don't clear pose if firsttime */
1108                 if ((pld->flag & PL_PREVIEW_FIRSTTIME) == 0)
1109                         poselib_backup_restore(pld);
1110                 else
1111                         pld->flag &= ~PL_PREVIEW_FIRSTTIME;
1112
1113                 /* pose should be the right one to draw (unless we're temporarily not showing it) */
1114                 if ((pld->flag & PL_PREVIEW_SHOWORIGINAL) == 0) {
1115                         RNA_int_set(op->ptr, "pose_index", BLI_findindex(&pld->act->markers, pld->marker));
1116                         poselib_apply_pose(pld);
1117                 }
1118                 else
1119                         RNA_int_set(op->ptr, "pose_index", -2);  /* -2 means don't apply any pose */
1120
1121                 /* old optimize trick... this enforces to bypass the depgraph
1122                  * - note: code copied from transform_generics.c -> recalcData()
1123                  */
1124                 // FIXME: shouldn't this use the builtin stuff?
1125                 if ((pld->arm->flag & ARM_DELAYDEFORM) == 0)
1126                         DEG_id_tag_update(&pld->ob->id, ID_RECALC_GEOMETRY);  /* sets recalc flags */
1127                 else
1128                         BKE_pose_where_is(CTX_data_depsgraph(C), pld->scene, pld->ob);
1129         }
1130
1131         /* do header print - if interactively previewing */
1132         if (pld->state == PL_PREVIEW_RUNNING) {
1133                 if (pld->flag & PL_PREVIEW_SHOWORIGINAL) {
1134                         ED_area_status_text(pld->sa, IFACE_("PoseLib Previewing Pose: [Showing Original Pose]"));
1135                         ED_workspace_status_text(C, IFACE_("Use Tab to start previewing poses again"));
1136                 }
1137                 else if (pld->searchstr[0]) {
1138                         char tempstr[65];
1139                         char markern[64];
1140                         short index;
1141
1142                         /* get search-string */
1143                         index = pld->search_cursor;
1144
1145                         if (index >= 0 && index < sizeof(tempstr) - 1) {
1146                                 memcpy(&tempstr[0], &pld->searchstr[0], index);
1147                                 tempstr[index] = '|';
1148                                 memcpy(&tempstr[index + 1], &pld->searchstr[index], (sizeof(tempstr) - 1) - index);
1149                         }
1150                         else {
1151                                 BLI_strncpy(tempstr, pld->searchstr, sizeof(tempstr));
1152                         }
1153
1154                         /* get marker name */
1155                         BLI_strncpy(markern, pld->marker ? pld->marker->name : "No Matches", sizeof(markern));
1156
1157                         BLI_snprintf(pld->headerstr, sizeof(pld->headerstr),
1158                                      IFACE_("PoseLib Previewing Pose: Filter - [%s] | "
1159                                             "Current Pose - \"%s\""),
1160                                      tempstr, markern);
1161                         ED_area_status_text(pld->sa, pld->headerstr);
1162                         ED_workspace_status_text(C, IFACE_("Use ScrollWheel or PageUp/Down to change pose"));
1163                 }
1164                 else {
1165                         BLI_snprintf(pld->headerstr, sizeof(pld->headerstr),
1166                                      IFACE_("PoseLib Previewing Pose: \"%s\""),
1167                                      pld->marker->name);
1168                         ED_area_status_text(pld->sa, pld->headerstr);
1169                         ED_workspace_status_text(C, NULL);
1170                 }
1171         }
1172
1173         /* request drawing of view + clear redraw flag */
1174         WM_event_add_notifier(C, NC_OBJECT | ND_POSE, pld->ob);
1175         pld->redraw = PL_PREVIEW_NOREDRAW;
1176 }
1177
1178 /* ---------------------------- */
1179
1180 /* This helper function is called during poselib_preview_poses to find the
1181  * pose to preview next (after a change event)
1182  */
1183 static void poselib_preview_get_next(tPoseLib_PreviewData *pld, int step)
1184 {
1185         /* stop if not going anywhere, as we assume that there is a direction to move in */
1186         if (step == 0)
1187                 return;
1188
1189         /* search-string dictates a special approach */
1190         if (pld->searchstr[0]) {
1191                 TimeMarker *marker;
1192                 LinkData *ld, *ldn, *ldc;
1193
1194                 /* free and rebuild if needed (i.e. if search-str changed) */
1195                 if (!STREQ(pld->searchstr, pld->searchold)) {
1196                         /* free list of temporary search matches */
1197                         BLI_freelistN(&pld->searchp);
1198
1199                         /* generate a new list of search matches */
1200                         for (marker = pld->act->markers.first; marker; marker = marker->next) {
1201                                 /* does the name partially match?
1202                                  * - don't worry about case, to make it easier for users to quickly input a name (or
1203                                  *   part of one), which is the whole point of this feature
1204                                  */
1205                                 if (BLI_strcasestr(marker->name, pld->searchstr)) {
1206                                         /* make link-data to store reference to it */
1207                                         ld = MEM_callocN(sizeof(LinkData), "PoseMatch");
1208                                         ld->data = marker;
1209                                         BLI_addtail(&pld->searchp, ld);
1210                                 }
1211                         }
1212
1213                         /* set current marker to NULL (so that we start from first) */
1214                         pld->marker = NULL;
1215                 }
1216
1217                 /* check if any matches */
1218                 if (BLI_listbase_is_empty(&pld->searchp)) {
1219                         pld->marker = NULL;
1220                         return;
1221                 }
1222
1223                 /* find first match */
1224                 for (ldc = pld->searchp.first; ldc; ldc = ldc->next) {
1225                         if (ldc->data == pld->marker)
1226                                 break;
1227                 }
1228                 if (ldc == NULL)
1229                         ldc = pld->searchp.first;
1230
1231                 /* Loop through the matches in a cyclic fashion, incrementing/decrementing step as appropriate
1232                  * until step == 0. At this point, marker should be the correct marker.
1233                  */
1234                 if (step > 0) {
1235                         for (ld = ldc; ld && step; ld = ldn, step--)
1236                                 ldn = (ld->next) ? ld->next : pld->searchp.first;
1237                 }
1238                 else {
1239                         for (ld = ldc; ld && step; ld = ldn, step++)
1240                                 ldn = (ld->prev) ? ld->prev : pld->searchp.last;
1241                 }
1242
1243                 /* set marker */
1244                 if (ld)
1245                         pld->marker = ld->data;
1246         }
1247         else {
1248                 TimeMarker *marker, *next;
1249
1250                 /* if no marker, because we just ended searching, then set that to the start of the list */
1251                 if (pld->marker == NULL)
1252                         pld->marker = pld->act->markers.first;
1253
1254                 /* Loop through the markers in a cyclic fashion, incrementing/decrementing step as appropriate
1255                  * until step == 0. At this point, marker should be the correct marker.
1256                  */
1257                 if (step > 0) {
1258                         for (marker = pld->marker; marker && step; marker = next, step--)
1259                                 next = (marker->next) ? marker->next : pld->act->markers.first;
1260                 }
1261                 else {
1262                         for (marker = pld->marker; marker && step; marker = next, step++)
1263                                 next = (marker->prev) ? marker->prev : pld->act->markers.last;
1264                 }
1265
1266                 /* it should be fairly impossible for marker to be NULL */
1267                 if (marker)
1268                         pld->marker = marker;
1269         }
1270 }
1271
1272 /* specially handle events for searching */
1273 static void poselib_preview_handle_search(tPoseLib_PreviewData *pld, unsigned short event, char ascii)
1274 {
1275         /* try doing some form of string manipulation first */
1276         switch (event) {
1277                 case BACKSPACEKEY:
1278                         if (pld->searchstr[0] && pld->search_cursor) {
1279                                 short len = strlen(pld->searchstr);
1280                                 short index = pld->search_cursor;
1281                                 short i;
1282
1283                                 for (i = index; i <= len; i++)
1284                                         pld->searchstr[i - 1] = pld->searchstr[i];
1285
1286                                 pld->search_cursor--;
1287
1288                                 poselib_preview_get_next(pld, 1);
1289                                 pld->redraw = PL_PREVIEW_REDRAWALL;
1290                                 return;
1291                         }
1292                         break;
1293
1294                 case DELKEY:
1295                         if (pld->searchstr[0] && pld->searchstr[1]) {
1296                                 short len = strlen(pld->searchstr);
1297                                 short index = pld->search_cursor;
1298                                 int i;
1299
1300                                 if (index < len) {
1301                                         for (i = index; i < len; i++)
1302                                                 pld->searchstr[i] = pld->searchstr[i + 1];
1303
1304                                         poselib_preview_get_next(pld, 1);
1305                                         pld->redraw = PL_PREVIEW_REDRAWALL;
1306                                         return;
1307                                 }
1308                         }
1309                         break;
1310         }
1311
1312         if (ascii) {
1313                 /* character to add to the string */
1314                 short index = pld->search_cursor;
1315                 short len = (pld->searchstr[0]) ? strlen(pld->searchstr) : 0;
1316                 short i;
1317
1318                 if (len) {
1319                         for (i = len; i > index; i--)
1320                                 pld->searchstr[i] = pld->searchstr[i - 1];
1321                 }
1322                 else
1323                         pld->searchstr[1] = 0;
1324
1325                 pld->searchstr[index] = ascii;
1326                 pld->search_cursor++;
1327
1328                 poselib_preview_get_next(pld, 1);
1329                 pld->redraw = PL_PREVIEW_REDRAWALL;
1330         }
1331 }
1332
1333 /* handle events for poselib_preview_poses */
1334 static int poselib_preview_handle_event(bContext *UNUSED(C), wmOperator *op, const wmEvent *event)
1335 {
1336         tPoseLib_PreviewData *pld = op->customdata;
1337         int ret = OPERATOR_RUNNING_MODAL;
1338
1339         /* only accept 'press' event, and ignore 'release', so that we don't get double actions */
1340         if (ELEM(event->val, KM_PRESS, KM_NOTHING) == 0) {
1341                 //printf("PoseLib: skipping event with type '%s' and val %d\n", WM_key_event_string(event->type, false), event->val);
1342                 return ret;
1343         }
1344
1345         /* backup stuff that needs to occur before every operation
1346          * - make a copy of searchstr, so that we know if cache needs to be rebuilt
1347          */
1348         BLI_strncpy(pld->searchold, pld->searchstr, sizeof(pld->searchold));
1349
1350         /* if we're currently showing the original pose, only certain events are handled */
1351         if (pld->flag & PL_PREVIEW_SHOWORIGINAL) {
1352                 switch (event->type) {
1353                         /* exit - cancel */
1354                         case ESCKEY:
1355                         case RIGHTMOUSE:
1356                                 pld->state = PL_PREVIEW_CANCEL;
1357                                 break;
1358
1359                         /* exit - confirm */
1360                         case LEFTMOUSE:
1361                         case RETKEY:
1362                         case PADENTER:
1363                         case SPACEKEY:
1364                                 pld->state = PL_PREVIEW_CONFIRM;
1365                                 break;
1366
1367                         /* view manipulation */
1368                         /* we add pass through here, so that the operators responsible for these can still run,
1369                          * even though we still maintain control (as RUNNING_MODAL flag is still set too)
1370                          */
1371                         case PAD0: case PAD1: case PAD2: case PAD3: case PAD4:
1372                         case PAD5: case PAD6: case PAD7: case PAD8: case PAD9:
1373                         case PADPLUSKEY: case PADMINUS:
1374                         case MIDDLEMOUSE: case MOUSEMOVE:
1375                                 //pld->redraw = PL_PREVIEW_REDRAWHEADER;
1376                                 ret = OPERATOR_PASS_THROUGH;
1377                                 break;
1378
1379                         /* quicky compare to original */
1380                         case TABKEY:
1381                                 pld->flag &= ~PL_PREVIEW_SHOWORIGINAL;
1382                                 pld->redraw = PL_PREVIEW_REDRAWALL;
1383                                 break;
1384                 }
1385
1386                 /* EXITS HERE... */
1387                 return ret;
1388         }
1389
1390         /* NORMAL EVENT HANDLING... */
1391         /* searching takes priority over normal activity */
1392         switch (event->type) {
1393                 /* exit - cancel */
1394                 case ESCKEY:
1395                 case RIGHTMOUSE:
1396                         pld->state = PL_PREVIEW_CANCEL;
1397                         break;
1398
1399                 /* exit - confirm */
1400                 case LEFTMOUSE:
1401                 case RETKEY:
1402                 case PADENTER:
1403                 case SPACEKEY:
1404                         pld->state = PL_PREVIEW_CONFIRM;
1405                         break;
1406
1407                 /* toggle between original pose and poselib pose*/
1408                 case TABKEY:
1409                         pld->flag |= PL_PREVIEW_SHOWORIGINAL;
1410                         pld->redraw = PL_PREVIEW_REDRAWALL;
1411                         break;
1412
1413                 /* change to previous pose (cyclic) */
1414                 case PAGEUPKEY:
1415                 case WHEELUPMOUSE:
1416                         poselib_preview_get_next(pld, -1);
1417                         pld->redraw = PL_PREVIEW_REDRAWALL;
1418                         break;
1419
1420                 /* change to next pose (cyclic) */
1421                 case PAGEDOWNKEY:
1422                 case WHEELDOWNMOUSE:
1423                         poselib_preview_get_next(pld, 1);
1424                         pld->redraw = PL_PREVIEW_REDRAWALL;
1425                         break;
1426
1427                 /* jump 5 poses (cyclic, back) */
1428                 case DOWNARROWKEY:
1429                         poselib_preview_get_next(pld, -5);
1430                         pld->redraw = PL_PREVIEW_REDRAWALL;
1431                         break;
1432
1433                 /* jump 5 poses (cyclic, forward) */
1434                 case UPARROWKEY:
1435                         poselib_preview_get_next(pld, 5);
1436                         pld->redraw = PL_PREVIEW_REDRAWALL;
1437                         break;
1438
1439                 /* change to next pose or searching cursor control */
1440                 case RIGHTARROWKEY:
1441                         if (pld->searchstr[0]) {
1442                                 /* move text-cursor to the right */
1443                                 if (pld->search_cursor < strlen(pld->searchstr))
1444                                         pld->search_cursor++;
1445                                 pld->redraw = PL_PREVIEW_REDRAWHEADER;
1446                         }
1447                         else {
1448                                 /* change to next pose (cyclic) */
1449                                 poselib_preview_get_next(pld, 1);
1450                                 pld->redraw = PL_PREVIEW_REDRAWALL;
1451                         }
1452                         break;
1453
1454                 /* change to next pose or searching cursor control */
1455                 case LEFTARROWKEY:
1456                         if (pld->searchstr[0]) {
1457                                 /* move text-cursor to the left */
1458                                 if (pld->search_cursor)
1459                                         pld->search_cursor--;
1460                                 pld->redraw = PL_PREVIEW_REDRAWHEADER;
1461                         }
1462                         else {
1463                                 /* change to previous pose (cyclic) */
1464                                 poselib_preview_get_next(pld, -1);
1465                                 pld->redraw = PL_PREVIEW_REDRAWALL;
1466                         }
1467                         break;
1468
1469                 /* change to first pose or start of searching string */
1470                 case HOMEKEY:
1471                         if (pld->searchstr[0]) {
1472                                 pld->search_cursor = 0;
1473                                 pld->redraw = PL_PREVIEW_REDRAWHEADER;
1474                         }
1475                         else {
1476                                 /* change to first pose */
1477                                 pld->marker = pld->act->markers.first;
1478                                 pld->act->active_marker = 1;
1479
1480                                 pld->redraw = PL_PREVIEW_REDRAWALL;
1481                         }
1482                         break;
1483
1484                 /* change to last pose or start of searching string */
1485                 case ENDKEY:
1486                         if (pld->searchstr[0]) {
1487                                 pld->search_cursor = strlen(pld->searchstr);
1488                                 pld->redraw = PL_PREVIEW_REDRAWHEADER;
1489                         }
1490                         else {
1491                                 /* change to last pose */
1492                                 pld->marker = pld->act->markers.last;
1493                                 pld->act->active_marker = BLI_listbase_count(&pld->act->markers);
1494
1495                                 pld->redraw = PL_PREVIEW_REDRAWALL;
1496                         }
1497                         break;
1498
1499                 /* view manipulation */
1500                 /* we add pass through here, so that the operators responsible for these can still run,
1501                  * even though we still maintain control (as RUNNING_MODAL flag is still set too)
1502                  */
1503                 case MIDDLEMOUSE: case MOUSEMOVE:
1504                         //pld->redraw = PL_PREVIEW_REDRAWHEADER;
1505                         ret = OPERATOR_PASS_THROUGH;
1506                         break;
1507
1508                 /* view manipulation, or searching */
1509                 case PAD0: case PAD1: case PAD2: case PAD3: case PAD4:
1510                 case PAD5: case PAD6: case PAD7: case PAD8: case PAD9:
1511                 case PADPLUSKEY: case PADMINUS:
1512                         if (pld->searchstr[0]) {
1513                                 /* searching... */
1514                                 poselib_preview_handle_search(pld, event->type, event->ascii);
1515                         }
1516                         else {
1517                                 /* view manipulation (see above) */
1518                                 //pld->redraw = PL_PREVIEW_REDRAWHEADER;
1519                                 ret = OPERATOR_PASS_THROUGH;
1520                         }
1521                         break;
1522
1523                 /* otherwise, assume that searching might be able to handle it */
1524                 default:
1525                         poselib_preview_handle_search(pld, event->type, event->ascii);
1526                         break;
1527         }
1528
1529         return ret;
1530 }
1531
1532 /* ---------------------------- */
1533
1534 /* Init PoseLib Previewing data */
1535 static void poselib_preview_init_data(bContext *C, wmOperator *op)
1536 {
1537         tPoseLib_PreviewData *pld;
1538         Object *ob = get_poselib_object(C);
1539         int pose_index = RNA_int_get(op->ptr, "pose_index");
1540
1541         /* set up preview state info */
1542         op->customdata = pld = MEM_callocN(sizeof(tPoseLib_PreviewData), "PoseLib Preview Data");
1543
1544         /* get basic data */
1545         pld->ob = ob;
1546         pld->arm = (ob) ? (ob->data) : NULL;
1547         pld->pose = (ob) ? (ob->pose) : NULL;
1548         pld->act = (ob) ? (ob->poselib) : NULL;
1549
1550         pld->scene = CTX_data_scene(C);
1551         pld->sa = CTX_wm_area(C);
1552
1553         /* get starting pose based on RNA-props for this operator */
1554         if (pose_index == -1)
1555                 pld->marker = poselib_get_active_pose(pld->act);
1556         else if (pose_index == -2)
1557                 pld->flag |= PL_PREVIEW_SHOWORIGINAL;
1558         else
1559                 pld->marker = (pld->act) ? BLI_findlink(&pld->act->markers, pose_index) : NULL;
1560
1561         /* check if valid poselib */
1562         if (ELEM(NULL, pld->ob, pld->pose, pld->arm)) {
1563                 BKE_report(op->reports, RPT_ERROR, "Pose lib is only for armatures in pose mode");
1564                 pld->state = PL_PREVIEW_ERROR;
1565                 return;
1566         }
1567         if (pld->act == NULL) {
1568                 BKE_report(op->reports, RPT_ERROR, "Object does not have a valid pose lib");
1569                 pld->state = PL_PREVIEW_ERROR;
1570                 return;
1571         }
1572         if (pld->marker == NULL) {
1573                 if (pld->act->markers.first) {
1574                         /* just use first one then... */
1575                         pld->marker = pld->act->markers.first;
1576                         if (pose_index > -2)
1577                                 BKE_report(op->reports, RPT_WARNING, "Pose lib had no active pose");
1578                 }
1579                 else {
1580                         BKE_report(op->reports, RPT_ERROR, "Pose lib has no poses to preview/apply");
1581                         pld->state = PL_PREVIEW_ERROR;
1582                         return;
1583                 }
1584         }
1585
1586         /* get ID pointer for applying poses */
1587         RNA_id_pointer_create(&ob->id, &pld->rna_ptr);
1588
1589         /* make backups for restoring pose */
1590         poselib_backup_posecopy(pld);
1591
1592         /* set flags for running */
1593         pld->state = PL_PREVIEW_RUNNING;
1594         pld->redraw = PL_PREVIEW_REDRAWALL;
1595         pld->flag |= PL_PREVIEW_FIRSTTIME;
1596
1597         /* set depsgraph flags */
1598         /* make sure the lock is set OK, unlock can be accidentally saved? */
1599         pld->pose->flag |= POSE_LOCKED;
1600         pld->pose->flag &= ~POSE_DO_UNLOCK;
1601
1602         /* clear strings + search */
1603         pld->headerstr[0] = pld->searchstr[0] = pld->searchold[0] = '\0';
1604         pld->search_cursor = 0;
1605 }
1606
1607 /* After previewing poses */
1608 static void poselib_preview_cleanup(bContext *C, wmOperator *op)
1609 {
1610         tPoseLib_PreviewData *pld = (tPoseLib_PreviewData *)op->customdata;
1611         Scene *scene = pld->scene;
1612         Object *ob = pld->ob;
1613         bPose *pose = pld->pose;
1614         bArmature *arm = pld->arm;
1615         bAction *act = pld->act;
1616         TimeMarker *marker = pld->marker;
1617
1618         /* redraw the header so that it doesn't show any of our stuff anymore */
1619         ED_area_status_text(pld->sa, NULL);
1620         ED_workspace_status_text(C, NULL);
1621
1622         /* this signal does one recalc on pose, then unlocks, so ESC or edit will work */
1623         pose->flag |= POSE_DO_UNLOCK;
1624
1625         /* clear pose if canceled */
1626         if (pld->state == PL_PREVIEW_CANCEL) {
1627                 poselib_backup_restore(pld);
1628
1629                 /* old optimize trick... this enforces to bypass the depgraph
1630                  * - note: code copied from transform_generics.c -> recalcData()
1631                  */
1632                 if ((arm->flag & ARM_DELAYDEFORM) == 0)
1633                         DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);  /* sets recalc flags */
1634                 else
1635                         BKE_pose_where_is(CTX_data_depsgraph(C), scene, ob);
1636         }
1637         else if (pld->state == PL_PREVIEW_CONFIRM) {
1638                 /* tag poses as appropriate */
1639                 poselib_keytag_pose(C, scene, pld);
1640
1641                 /* change active pose setting */
1642                 act->active_marker = BLI_findindex(&act->markers, marker) + 1;
1643                 action_set_activemarker(act, marker, NULL);
1644
1645                 /* Update event for pose and deformation children */
1646                 DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
1647
1648                 /* updates */
1649                 if (IS_AUTOKEY_MODE(scene, NORMAL)) {
1650                         //remake_action_ipos(ob->action);
1651                 }
1652                 else
1653                         BKE_pose_where_is(CTX_data_depsgraph(C), scene, ob);
1654         }
1655
1656         /* Request final redraw of the view. */
1657         WM_event_add_notifier(C, NC_OBJECT | ND_POSE, pld->ob);
1658
1659         /* free memory used for backups and searching */
1660         poselib_backup_free_data(pld);
1661         BLI_freelistN(&pld->searchp);
1662
1663         /* free temp data for operator */
1664         MEM_freeN(pld);
1665         op->customdata = NULL;
1666 }
1667
1668 /* End previewing operation */
1669 static int poselib_preview_exit(bContext *C, wmOperator *op)
1670 {
1671         tPoseLib_PreviewData *pld = op->customdata;
1672         int exit_state = pld->state;
1673
1674         /* finish up */
1675         poselib_preview_cleanup(C, op);
1676
1677         if (ELEM(exit_state, PL_PREVIEW_CANCEL, PL_PREVIEW_ERROR))
1678                 return OPERATOR_CANCELLED;
1679         else
1680                 return OPERATOR_FINISHED;
1681 }
1682
1683 /* Cancel previewing operation (called when exiting Blender) */
1684 static void poselib_preview_cancel(bContext *C, wmOperator *op)
1685 {
1686         poselib_preview_exit(C, op);
1687 }
1688
1689 /* main modal status check */
1690 static int poselib_preview_modal(bContext *C, wmOperator *op, const wmEvent *event)
1691 {
1692         tPoseLib_PreviewData *pld = op->customdata;
1693         int ret;
1694
1695         /* 1) check state to see if we're still running */
1696         if (pld->state != PL_PREVIEW_RUNNING)
1697                 return poselib_preview_exit(C, op);
1698
1699         /* 2) handle events */
1700         ret = poselib_preview_handle_event(C, op, event);
1701
1702         /* 3) apply changes and redraw, otherwise, confirming goes wrong */
1703         if (pld->redraw)
1704                 poselib_preview_apply(C, op);
1705
1706         return ret;
1707 }
1708
1709 /* Modal Operator init */
1710 static int poselib_preview_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
1711 {
1712         tPoseLib_PreviewData *pld;
1713
1714         /* check if everything is ok, and init settings for modal operator */
1715         poselib_preview_init_data(C, op);
1716         pld = (tPoseLib_PreviewData *)op->customdata;
1717
1718         if (pld->state == PL_PREVIEW_ERROR) {
1719                 /* an error occurred, so free temp mem used */
1720                 poselib_preview_cleanup(C, op);
1721                 return OPERATOR_CANCELLED;
1722         }
1723
1724         /* do initial apply to have something to look at */
1725         poselib_preview_apply(C, op);
1726
1727         /* add temp handler if we're running as a modal operator */
1728         WM_event_add_modal_handler(C, op);
1729
1730         return OPERATOR_RUNNING_MODAL;
1731 }
1732
1733 /* Repeat operator */
1734 static int poselib_preview_exec(bContext *C, wmOperator *op)
1735 {
1736         tPoseLib_PreviewData *pld;
1737
1738         /* check if everything is ok, and init settings for modal operator */
1739         poselib_preview_init_data(C, op);
1740         pld = (tPoseLib_PreviewData *)op->customdata;
1741
1742         if (pld->state == PL_PREVIEW_ERROR) {
1743                 /* an error occurred, so free temp mem used */
1744                 poselib_preview_cleanup(C, op);
1745                 return OPERATOR_CANCELLED;
1746         }
1747
1748         /* the exec() callback is effectively a 'run-once' scenario, so set the state to that
1749          * so that everything draws correctly
1750          */
1751         pld->state = PL_PREVIEW_RUNONCE;
1752
1753         /* apply the active pose */
1754         poselib_preview_apply(C, op);
1755
1756         /* now, set the status to exit */
1757         pld->state = PL_PREVIEW_CONFIRM;
1758
1759         /* cleanup */
1760         return poselib_preview_exit(C, op);
1761 }
1762
1763 void POSELIB_OT_browse_interactive(wmOperatorType *ot)
1764 {
1765         /* identifiers */
1766         ot->name = "PoseLib Browse Poses";
1767         ot->idname = "POSELIB_OT_browse_interactive";
1768         ot->description = "Interactively browse poses in 3D-View";
1769
1770         /* callbacks */
1771         ot->invoke = poselib_preview_invoke;
1772         ot->modal = poselib_preview_modal;
1773         ot->cancel = poselib_preview_cancel;
1774         ot->exec = poselib_preview_exec;
1775         ot->poll = has_poselib_pose_data_poll;
1776
1777         /* flags */
1778         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_BLOCKING;
1779
1780         /* properties */
1781         // TODO: make the pose_index into a proper enum instead of a cryptic int...
1782         ot->prop = RNA_def_int(ot->srna, "pose_index", -1, -2, INT_MAX, "Pose", "Index of the pose to apply (-2 for no change to pose, -1 for poselib active pose)", 0, INT_MAX);
1783
1784         // XXX: percentage vs factor?
1785         /* not used yet */
1786 #if 0
1787         RNA_def_float_factor(
1788                 ot->srna, "blend_factor", 1.0f, 0.0f, 1.0f, "Blend Factor",
1789                 "Amount that the pose is applied on top of the existing poses", 0.0f, 1.0f);
1790 #endif
1791 }
1792
1793 void POSELIB_OT_apply_pose(wmOperatorType *ot)
1794 {
1795         /* identifiers */
1796         ot->name = "Apply Pose Library Pose";
1797         ot->idname = "POSELIB_OT_apply_pose";
1798         ot->description = "Apply specified Pose Library pose to the rig";
1799
1800         /* callbacks */
1801         ot->exec = poselib_preview_exec;
1802         ot->poll = has_poselib_pose_data_poll;
1803
1804         /* flags */
1805         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1806
1807         /* properties */
1808         /* TODO: make the pose_index into a proper enum instead of a cryptic int... */
1809         ot->prop = RNA_def_int(ot->srna, "pose_index", -1, -2, INT_MAX, "Pose", "Index of the pose to apply (-2 for no change to pose, -1 for poselib active pose)", 0, INT_MAX);
1810 }