Merged 15170:15635 from trunk (no conflicts or even merges)
[blender.git] / source / blender / src / poselib.c
1 /**
2  * $Id$
3  *
4  * ***** BEGIN GPL LICENSE BLOCK *****
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * as published by the Free Software Foundation; either version 2
9  * of the License, or (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software Foundation,
18  * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
19  *
20  * The Original Code is Copyright (C) 2007, Blender Foundation
21  * This is a new part of Blender
22  *
23  * Contributor(s): Joshua Leung
24  *
25  * ***** END GPL LICENSE BLOCK *****
26  */
27  
28 #include <stdlib.h>
29 #include <stdio.h>
30 #include <stddef.h>
31 #include <string.h>
32 #include <math.h>
33
34 #ifdef HAVE_CONFIG_H
35 #include <config.h>
36 #endif
37
38 #include "MEM_guardedalloc.h"
39
40 #include "BLI_arithb.h"
41 #include "BLI_blenlib.h"
42 #include "BLI_dynstr.h"
43
44 #include "DNA_listBase.h"
45 #include "DNA_action_types.h"
46 #include "DNA_armature_types.h"
47 #include "DNA_curve_types.h"
48 #include "DNA_ipo_types.h"
49 #include "DNA_object_types.h"
50 #include "DNA_object_force.h"
51 #include "DNA_scene_types.h"
52 #include "DNA_userdef_types.h"
53
54 #include "BKE_action.h"
55 #include "BKE_armature.h"
56 #include "BKE_depsgraph.h"
57 #include "BKE_ipo.h"
58 #include "BKE_modifier.h"
59 #include "BKE_object.h"
60
61 #include "BKE_global.h"
62 #include "BKE_utildefines.h"
63
64 //#include "BIF_keyframing.h"
65 #include "BSE_editipo.h"
66
67 #include "BDR_drawaction.h"
68 #include "BSE_time.h"
69
70 #include "BIF_poselib.h"
71 #include "BIF_interface.h"
72 #include "BIF_editaction.h"
73 #include "BIF_space.h"
74 #include "BIF_screen.h"
75 #include "BIF_toets.h"
76 #include "BIF_toolbox.h"
77
78
79 #include "blendef.h"
80
81 #include "PIL_time.h"                   /* sleep                                */
82 #include "mydevice.h"
83
84 /* ************************************************************* */
85 /* == POSE-LIBRARY TOOL FOR BLENDER == 
86  *      
87  * Overview: 
88  *      This tool allows animators to store a set of frequently used poses to dump into
89  *      the active action to help in "budget" productions to quickly block out new actions.
90  *      It acts as a kind of "glorified clipboard for poses", allowing for naming of poses.
91  *
92  * Features:
93  *      - PoseLibs are simply normal Actions
94  *      - Each "pose" is simply a set of keyframes that occur on a particular frame
95  *              -> a set of TimeMarkers that belong to each Action, help 'label' where a 'pose' can be
96  *                 found in the Action
97  *      - The Scrollwheel or PageUp/Down buttons when used in a special mode or after pressing/holding
98  *        [a modifier] key, cycles through the poses available for the active pose's poselib, allowing the
99  *        animator to preview what action best suits that pose
100  */
101 /* ************************************************************* */
102
103 /* gets list of poses in poselib as a string usable for pupmenu() */
104 char *poselib_build_poses_menu (bAction *act, char title[])
105 {
106         DynStr *pupds= BLI_dynstr_new();
107         TimeMarker *marker;
108         char *str;
109         char buf[64];
110         int i;
111         
112         /* add title first */
113         sprintf(buf, "%s%%t|", title);
114         BLI_dynstr_append(pupds, buf);
115         
116         /* loop through markers, adding them */
117         for (marker=act->markers.first, i=1; marker; marker=marker->next, i++) {
118                 BLI_dynstr_append(pupds, marker->name);
119                 
120                 sprintf(buf, "%%x%d", i);
121                 BLI_dynstr_append(pupds, buf);
122                 
123                 if (marker->next)
124                         BLI_dynstr_append(pupds, "|");
125         }
126         
127         /* convert to normal MEM_malloc'd string */
128         str= BLI_dynstr_get_cstring(pupds);
129         BLI_dynstr_free(pupds);
130         
131         return str;
132 }
133
134 /* gets the first available frame in poselib to store a pose on 
135  *      - frames start from 1, and a pose should occur on every frame... 0 is error!
136  */
137 int poselib_get_free_index (bAction *act)
138 {
139         TimeMarker *marker;
140         int low=0, high=0;
141         
142         /* sanity checks */
143         if (ELEM(NULL, act, act->markers.first)) return 1;
144         
145         /* loop over poses finding various values (poses are not stored in chronological order) */
146         for (marker= act->markers.first; marker; marker= marker->next) {
147                 /* only increase low if value is 1 greater than low, to find "gaps" where
148                  * poses were removed from the poselib
149                  */
150                 if (marker->frame == (low + 1)) 
151                         low++;
152                 
153                 /* value replaces high if it is the highest value encountered yet */
154                 if (marker->frame > high) 
155                         high= marker->frame;
156         }
157         
158         /* - if low is not equal to high, then low+1 is a gap 
159          * - if low is equal to high, then high+1 is the next index (add at end) 
160          */
161         if (low < high) 
162                 return (low + 1);
163         else 
164                 return (high + 1);
165 }
166
167 /* returns the active pose for a poselib */
168 TimeMarker *poselib_get_active_pose (bAction *act)
169 {       
170         if ((act) && (act->active_marker))
171                 return BLI_findlink(&act->markers, act->active_marker-1);
172         else
173                 return NULL;
174 }
175
176 /* ************************************************************* */
177
178 /* Initialise a new poselib (whether it is needed or not) */
179 bAction *poselib_init_new (Object *ob)
180 {
181         /* sanity checks - only for armatures */
182         if (ELEM(NULL, ob, ob->pose))
183                 return NULL;
184         
185         /* init object's poselib action (unlink old one if there) */
186         if (ob->poselib)
187                 ob->poselib->id.us--;
188         ob->poselib= add_empty_action("PoseLib");
189         
190         return ob->poselib;
191 }
192
193 /* Initialise a new poselib (checks if that needs to happen) */
194 bAction *poselib_validate (Object *ob)
195 {
196         if (ELEM(NULL, ob, ob->pose))
197                 return NULL;
198         else if (ob->poselib == NULL)
199                 return poselib_init_new(ob);
200         else
201                 return ob->poselib;
202 }
203
204
205 /* This tool automagically generates/validates poselib data so that it corresponds to the data 
206  * in the action. This is for use in making existing actions usable as poselibs.
207  */
208 void poselib_validate_act (bAction *act)
209 {
210         ListBase keys = {NULL, NULL};
211         ActKeyColumn *ak;
212         TimeMarker *marker, *markern;
213         
214         /* validate action and poselib */
215         if (act == NULL)  {
216                 error("No Action to validate");
217                 return;
218         }
219         
220         /* determine which frames have keys */
221         action_to_keylist(act, &keys, NULL, NULL);
222         
223         /* for each key, make sure there is a correspnding pose */
224         for (ak= keys.first; ak; ak= ak->next) {
225                 /* check if any pose matches this */
226                 for (marker= act->markers.first; marker; marker= marker->next) {
227                         if (IS_EQ(marker->frame, ak->cfra)) {
228                                 marker->flag = -1;
229                                 break;
230                         }
231                 }
232                 
233                 /* add new if none found */
234                 if (marker == NULL) {
235                         char name[64];
236                         
237                         /* add pose to poselib */
238                         marker= MEM_callocN(sizeof(TimeMarker), "ActionMarker");
239                         
240                         strcpy(name, "Pose");
241                         BLI_strncpy(marker->name, name, sizeof(marker->name));
242                         
243                         marker->frame= (int)ak->cfra;
244                         marker->flag= -1;
245                         
246                         BLI_addtail(&act->markers, marker);
247                 }
248         }
249         
250         /* remove all untagged poses (unused), and remove all tags */
251         for (marker= act->markers.first; marker; marker= markern) {
252                 markern= marker->next;
253                 
254                 if (marker->flag != -1)
255                         BLI_freelinkN(&act->markers, marker);
256                 else
257                         marker->flag = 0;
258         }
259         
260         /* free temp memory */
261         BLI_freelistN(&keys);
262         
263         BIF_undo_push("PoseLib Validate Action");
264 }
265
266 /* ************************************************************* */
267
268 /* This function adds an ipo-curve of the right type where it's needed */
269 static IpoCurve *poselib_verify_icu (Ipo *ipo, int adrcode)
270 {
271         IpoCurve *icu;
272         
273         for (icu= ipo->curve.first; icu; icu= icu->next) {
274                 if (icu->adrcode==adrcode) break;
275         }
276         if (icu==NULL) {
277                 icu= MEM_callocN(sizeof(IpoCurve), "ipocurve");
278                 
279                 icu->flag |= IPO_VISIBLE|IPO_AUTO_HORIZ;
280                 if (ipo->curve.first==NULL) icu->flag |= IPO_ACTIVE;    /* first one added active */
281                 
282                 icu->blocktype= ID_PO;
283                 icu->adrcode= adrcode;
284                 
285                 set_icu_vars(icu);
286                 
287                 BLI_addtail(&ipo->curve, icu);
288         }
289         
290         return icu;
291 }
292
293 /* This tool adds the current pose to the poselib 
294  *      Note: Standard insertkey cannot be used for this due to its limitations
295  */
296 void poselib_add_current_pose (Object *ob, int val)
297 {
298         bArmature *arm= (ob) ? ob->data : NULL;
299         bPose *pose= (ob) ? ob->pose : NULL;
300         bPoseChannel *pchan;
301         TimeMarker *marker;
302         bAction *act;
303         bActionChannel *achan;
304         IpoCurve *icu;
305         int frame;
306         char name[64];
307         
308         /* sanity check */
309         if (ELEM3(NULL, ob, arm, pose)) 
310                 return;
311         
312         /* mode - add new or replace existing */
313         if (val == 0) {
314                 if ((ob->poselib) && (ob->poselib->markers.first)) {
315                         val= pupmenu("PoseLib Add Current Pose%t|Add New%x1|Replace Existing%x2");
316                         if (val <= 0) return;
317                 }
318                 else 
319                         val= 1;
320         }
321         
322         if ((ob->poselib) && (val == 2)) {
323                 char *menustr;
324                 
325                 /* get poselib */
326                 act= ob->poselib;
327                 
328                 /* get the pose to replace */
329                 menustr= poselib_build_poses_menu(act, "Replace PoseLib Pose");
330                 val= pupmenu_col(menustr, 20);
331                 if (menustr) MEM_freeN(menustr);
332                 
333                 if (val <= 0) return;
334                 marker= BLI_findlink(&act->markers, val-1);
335                 if (marker == NULL) return;
336                 
337                 /* get the frame from the poselib */
338                 frame= marker->frame;
339         }
340         else {
341                 /* get name of pose */
342                 sprintf(name, "Pose");
343                 if (sbutton(name, 0, sizeof(name)-1, "Name: ") == 0)
344                         return;
345                         
346                 /* get/initialise poselib */
347                 act= poselib_validate(ob);
348                 
349                 /* get frame */
350                 frame= poselib_get_free_index(act);
351                 
352                 /* add pose to poselib - replaces any existing pose there */
353                 for (marker= act->markers.first; marker; marker= marker->next) {
354                         if (marker->frame == frame) {
355                                 BLI_strncpy(marker->name, name, sizeof(marker->name));
356                                 break;
357                         }
358                 }
359                 if (marker == NULL) {
360                         marker= MEM_callocN(sizeof(TimeMarker), "ActionMarker");
361                         
362                         BLI_strncpy(marker->name, name, sizeof(marker->name));
363                         marker->frame= frame;
364                         
365                         BLI_addtail(&act->markers, marker);
366                 }
367                 
368                 /* validate name */
369                 BLI_uniquename(&act->markers, marker, "Pose", offsetof(TimeMarker, name), 64);
370         }       
371         
372         /* loop through selected posechannels, keying their pose to the action */
373         for (pchan= pose->chanbase.first; pchan; pchan= pchan->next) {
374                 /* check if available */
375                 if ((pchan->bone) && (arm->layer & pchan->bone->layer)) {
376                         if (pchan->bone->flag & (BONE_SELECTED|BONE_ACTIVE)) {
377                                 /* make action-channel if needed (action groups are also created) */
378                                 achan= verify_action_channel(act, pchan->name);
379                                 verify_pchan2achan_grouping(act, pose, pchan->name);
380                                 
381                                 /* make ipo if needed... */
382                                 if (achan->ipo == NULL)
383                                         achan->ipo= add_ipo(achan->name, ID_PO);
384                                         
385                                 /* add missing ipo-curves and insert keys */
386                                 #define INSERT_KEY_ICU(adrcode, data) {\
387                                                 icu= poselib_verify_icu(achan->ipo, adrcode); \
388                                                 insert_vert_icu(icu, frame, data, 1); \
389                                         }
390                                         
391                                 INSERT_KEY_ICU(AC_LOC_X, pchan->loc[0])
392                                 INSERT_KEY_ICU(AC_LOC_Y, pchan->loc[1])
393                                 INSERT_KEY_ICU(AC_LOC_Z, pchan->loc[2])
394                                 INSERT_KEY_ICU(AC_SIZE_X, pchan->size[0])
395                                 INSERT_KEY_ICU(AC_SIZE_Y, pchan->size[1])
396                                 INSERT_KEY_ICU(AC_SIZE_Z, pchan->size[2])
397                                 INSERT_KEY_ICU(AC_QUAT_W, pchan->quat[0])
398                                 INSERT_KEY_ICU(AC_QUAT_X, pchan->quat[1])
399                                 INSERT_KEY_ICU(AC_QUAT_Y, pchan->quat[2])
400                                 INSERT_KEY_ICU(AC_QUAT_Z, pchan->quat[3])
401                         }
402                 }
403         }
404         
405         /* store new 'active' pose number */
406         act->active_marker= BLI_countlist(&act->markers);
407         
408         BIF_undo_push("PoseLib Add Pose");
409         allqueue(REDRAWBUTSEDIT, 0);
410 }
411
412
413 /* This tool removes the pose that the user selected from the poselib (or the provided pose) */
414 void poselib_remove_pose (Object *ob, TimeMarker *marker)
415 {
416         bPose *pose= (ob) ? ob->pose : NULL;
417         bAction *act= (ob) ? ob->poselib : NULL;
418         bActionChannel *achan;
419         char *menustr;
420         int val;
421         
422         /* check if valid poselib */
423         if (ELEM(NULL, ob, pose)) {
424                 error("PoseLib is only for Armatures in PoseMode");
425                 return;
426         }
427         if (act == NULL) {
428                 error("Object doesn't have PoseLib data");
429                 return;
430         }
431         
432         /* get index (and pointer) of pose to remove */
433         if (marker == NULL) {
434                 menustr= poselib_build_poses_menu(act, "Remove PoseLib Pose");
435                 val= pupmenu_col(menustr, 20);
436                 if (menustr) MEM_freeN(menustr);
437                 
438                 if (val <= 0) return;
439                 marker= BLI_findlink(&act->markers, val-1);
440                 if (marker == NULL) return;
441         }
442         else {
443                 /* only continue if pose belongs to poselib */
444                 if (BLI_findindex(&act->markers, marker) == -1) 
445                         return;
446         }
447         
448         /* remove relevant keyframes */
449         for (achan= act->chanbase.first; achan; achan= achan->next) {
450                 Ipo *ipo= achan->ipo;
451                 IpoCurve *icu;
452                 BezTriple *bezt;
453                 int i;
454                 
455                 for (icu= ipo->curve.first; icu; icu= icu->next) {
456                         for (i=0, bezt=icu->bezt; i < icu->totvert; i++, bezt++) {
457                                 /* check if remove... */
458                                 if (IS_EQ(bezt->vec[1][0], marker->frame)) {
459                                         delete_icu_key(icu, i, 1);
460                                         break;
461                                 }
462                         }       
463                 }
464         }
465         
466         /* remove poselib from list */
467         BLI_freelinkN(&act->markers, marker);
468         
469         /* fix active pose number */
470         act->active_marker= 0;
471         
472         /* undo + redraw */
473         BIF_undo_push("PoseLib Remove Pose");
474         allqueue(REDRAWBUTSEDIT, 0);
475         allqueue(REDRAWACTION, 0);
476 }
477
478
479 /* This tool renames the pose that the user selected from the poselib */
480 void poselib_rename_pose (Object *ob)
481 {
482         bPose *pose= (ob) ? ob->pose : NULL;
483         bAction *act= (ob) ? ob->poselib : NULL;
484         TimeMarker *marker;
485         char *menustr, name[64];
486         int val;
487         
488         /* check if valid poselib */
489         if (ELEM(NULL, ob, pose)) {
490                 error("PoseLib is only for Armatures in PoseMode");
491                 return;
492         }
493         if (act == NULL) {
494                 error("Object doesn't have a valid PoseLib");
495                 return;
496         }
497         
498         /* get index of pose to remove */
499         menustr= poselib_build_poses_menu(act, "Rename PoseLib Pose");
500         val= pupmenu_col(menustr, 20);
501         if (menustr) MEM_freeN(menustr);
502         
503         if (val <= 0) return;
504         marker= BLI_findlink(&act->markers, val-1);
505         if (marker == NULL) return;
506         
507         /* get name of pose */
508         sprintf(name, marker->name);
509         if (sbutton(name, 0, sizeof(name)-1, "Name: ") == 0)
510                 return;
511         
512         /* copy name and validate it */
513         BLI_strncpy(marker->name, name, sizeof(marker->name));
514         BLI_uniquename(&act->markers, marker, "Pose", offsetof(TimeMarker, name), 64);
515         
516         /* undo and update */
517         BIF_undo_push("PoseLib Rename Pose");
518         allqueue(REDRAWBUTSEDIT, 0);
519         allqueue(REDRAWACTION, 0);
520 }
521
522
523 /* ************************************************************* */
524
525 /* Simple struct for storing settings/data for use during PoseLib preview */
526 typedef struct tPoseLib_PreviewData {
527         ListBase backups;               /* tPoseLib_Backup structs for restoring poses */
528         ListBase searchp;               /* LinkData structs storing list of poses which match the current search-string */
529         
530         Object *ob;                             /* object to work on */
531         bArmature *arm;                 /* object's armature data */
532         bPose *pose;                    /* object's pose */
533         bAction *act;                   /* poselib to use */
534         TimeMarker *marker;             /* 'active' pose */
535         
536         short state;                    /* state of main loop */
537         short redraw;                   /* redraw/update settings during main loop */
538         short flag;                             /* flags for various settings */
539         
540         int selcount;                   /* number of selected elements to work on */
541         int totcount;                   /* total number of elements to work on */
542         
543         char headerstr[200];    /* Info-text to print in header */
544         
545         char searchstr[64];             /* (Part of) Name to search for to filter poses that get shown */
546         char searchold[64];             /* Previously set searchstr (from last loop run), so that we can detected when to rebuild searchp */
547         short search_cursor;    /* position of cursor in searchstr (cursor occurs before the item at the nominated index) */
548 } tPoseLib_PreviewData;
549
550 /* defines for tPoseLib_PreviewData->state values */
551 enum {
552         PL_PREVIEW_ERROR = -1,
553         PL_PREVIEW_RUNNING,
554         PL_PREVIEW_CONFIRM,
555         PL_PREVIEW_CANCEL,
556         PL_PREVIEW_RUNONCE 
557 };
558
559 /* defines for tPoseLib_PreviewData->redraw values */
560 enum {
561         PL_PREVIEW_NOREDRAW = 0,
562         PL_PREVIEW_REDRAWALL,
563         PL_PREVIEW_REDRAWHEADER,
564 };
565
566 /* defines for tPoseLib_PreviewData->flag values */
567 enum {
568         PL_PREVIEW_FIRSTTIME    = (1<<0),
569         PL_PREVIEW_SHOWORIGINAL = (1<<1)
570 };
571
572 /* ---------------------------- */
573
574 /* simple struct for storing backup info */
575 typedef struct tPoseLib_Backup {
576         struct tPoseLib_Backup *next, *prev;
577         
578         bPoseChannel *pchan;
579         bPoseChannel olddata;
580 } tPoseLib_Backup;
581
582 /* Makes a copy of the current pose for restoration purposes - doesn't do constraints currently */
583 static void poselib_backup_posecopy (tPoseLib_PreviewData *pld)
584 {
585         bActionChannel *achan;
586         bPoseChannel *pchan;
587         
588         /* for each posechannel that has an actionchannel in */
589         for (achan= pld->act->chanbase.first; achan; achan= achan->next) {
590                 /* try to find posechannel */
591                 pchan= get_pose_channel(pld->pose, achan->name);
592                 
593                 /* backup data if available */
594                 if (pchan) {
595                         tPoseLib_Backup *plb;
596                         
597                         /* store backup */
598                         plb= MEM_callocN(sizeof(tPoseLib_Backup), "tPoseLib_Backup");
599                         
600                         plb->pchan= pchan;
601                         memcpy(&plb->olddata, plb->pchan, sizeof(bPoseChannel));
602                         
603                         BLI_addtail(&pld->backups, plb);
604                         
605                         /* mark as being affected */
606                         if ((pchan->bone) && (pchan->bone->flag & BONE_SELECTED))
607                                 pld->selcount++;
608                         pld->totcount++;
609                 }
610         }
611 }
612
613 /* Restores original pose - doesn't do constraints currently */
614 static void poselib_backup_restore (tPoseLib_PreviewData *pld)
615 {
616         tPoseLib_Backup *plb;
617         
618         for (plb= pld->backups.first; plb; plb= plb->next) {
619                 memcpy(plb->pchan, &plb->olddata, sizeof(bPoseChannel));
620         }
621 }
622
623 /* ---------------------------- */
624
625 /* Applies the appropriate stored pose from the pose-library to the current pose
626  *      - assumes that a valid object, with a poselib has been supplied
627  *      - gets the string to print in the header
628  *      - this code is based on the code for extract_pose_from_action in blenkernel/action.c
629  */
630 static void poselib_apply_pose (tPoseLib_PreviewData *pld)
631 {
632         bPose *pose= pld->pose;
633         bPoseChannel *pchan;
634         bAction *act= pld->act;
635         bActionChannel *achan;
636         IpoCurve *icu;
637         int frame;
638         
639         if (pld->marker)
640                 frame= pld->marker->frame;
641         else
642                 return; 
643         
644         /* start applying - only those channels which have a key at this point in time! */
645         for (achan= act->chanbase.first; achan; achan= achan->next) {
646                 short found= 0;
647                 
648                 /* apply this achan? */
649                 if (achan->ipo) {
650                         /* find a keyframe at this frame - users may not have defined the pose on every channel, so this is necessary */
651                         // TODO: this may be bad for user-defined poses...
652                         for (icu= achan->ipo->curve.first; icu; icu= icu->next) {
653                                 BezTriple *bezt;
654                                 int i;
655                                 
656                                 for (i=0, bezt=icu->bezt; i < icu->totvert; i++, bezt++) {
657                                         if (IN_RANGE(bezt->vec[1][0], (frame-0.5f), (frame+0.5f))) {
658                                                 found= 1;
659                                                 break;
660                                         }
661                                 }
662                                 
663                                 if (found) break;
664                         }
665                         
666                         /* apply pose - only if posechannel selected? */
667                         if (found) {
668                                 pchan= get_pose_channel(pose, achan->name);
669                                 
670                                 if (pchan) {    
671                                         short ok= 0;
672                                         
673                                         if (pchan->bone) {
674                                                 if ( (pchan->bone->flag & (BONE_SELECTED|BONE_ACTIVE)) &&
675                                                          (pchan->bone->flag & BONE_HIDDEN_P)==0 )
676                                                         ok = 1;
677                                                 else if (pld->selcount == 0)
678                                                         ok= 1;
679                                         }
680                                         else if (pld->selcount == 0)
681                                                 ok= 1;
682                                         
683                                         if (ok) {
684                                                 /* Evaluates and sets the internal ipo values   */
685                                                 calc_ipo(achan->ipo, frame);
686                                                 /* This call also sets the pchan flags */
687                                                 execute_action_ipo(achan, pchan);
688                                         }
689                                 }
690                         }
691                 }
692                 
693                 /* tag achan as having been used or not... */
694                 if (found)
695                         achan->flag |= ACHAN_SELECTED;
696                 else
697                         achan->flag &= ~ACHAN_SELECTED;
698         }
699 }
700
701 /* Auto-keys/tags bones affected by the pose used from the poselib */
702 static void poselib_keytag_pose (tPoseLib_PreviewData *pld)
703 {
704         bPose *pose= pld->pose;
705         bPoseChannel *pchan;
706         bAction *act= pld->act;
707         bActionChannel *achan;
708         
709         /* start tagging/keying */
710         for (achan= act->chanbase.first; achan; achan= achan->next) {
711                 /* only for selected action channels */
712                 if (achan->flag & ACHAN_SELECTED) {
713                         pchan= get_pose_channel(pose, achan->name);
714                         
715                         if (pchan) {
716                                 // TODO: use a standard autokeying function in future (to allow autokeying-editkeys to work)
717                                 if (IS_AUTOKEY_MODE(NORMAL)) {
718                                         ID *id= &pld->ob->id;
719                                         
720                                         /* Set keys on pose */
721                                         if (pchan->flag & POSE_ROT) {
722                                                 insertkey(id, ID_PO, pchan->name, NULL, AC_QUAT_X, 0);
723                                                 insertkey(id, ID_PO, pchan->name, NULL, AC_QUAT_Y, 0);
724                                                 insertkey(id, ID_PO, pchan->name, NULL, AC_QUAT_Z, 0);
725                                                 insertkey(id, ID_PO, pchan->name, NULL, AC_QUAT_W, 0);
726                                         }
727                                         if (pchan->flag & POSE_SIZE) {
728                                                 insertkey(id, ID_PO, pchan->name, NULL, AC_SIZE_X, 0);
729                                                 insertkey(id, ID_PO, pchan->name, NULL, AC_SIZE_Y, 0);
730                                                 insertkey(id, ID_PO, pchan->name, NULL, AC_SIZE_Z, 0);
731                                         }
732                                         if (pchan->flag & POSE_LOC) {
733                                                 insertkey(id, ID_PO, pchan->name, NULL, AC_LOC_X, 0);
734                                                 insertkey(id, ID_PO, pchan->name, NULL, AC_LOC_Y, 0);
735                                                 insertkey(id, ID_PO, pchan->name, NULL, AC_LOC_Z, 0);
736                                         }
737                                         
738                                         /* clear any unkeyed tags */
739                                         if (pchan->bone)
740                                                 pchan->bone->flag &= ~BONE_UNKEYED;
741                                 }
742                                 else {
743                                         /* add unkeyed tags */
744                                         if (pchan->bone)
745                                                 pchan->bone->flag |= BONE_UNKEYED;
746                                 }
747                         }
748                 }
749         }
750 }
751
752 /* ---------------------------- */
753
754 /* This helper function is called during poselib_preview_poses to find the 
755  * pose to preview next (after a change event)
756  */
757 static void poselib_preview_get_next (tPoseLib_PreviewData *pld, int step)
758 {
759         /* check if we no longer have search-string, but don't have any marker */
760         if (pld->marker == NULL) {
761                 if ((step) && (pld->searchstr[0] == 0))
762                         pld->marker= pld->act->markers.first;
763         }       
764         
765         /* the following operations assume that there is a starting point and direction */
766         if ((pld->marker) && (step)) {
767                 /* search-string dictates a special approach */
768                 if (pld->searchstr[0]) {
769                         TimeMarker *marker;
770                         LinkData *ld, *ldn, *ldc;
771                         
772                         /* free and rebuild if needed (i.e. if search-str changed) */
773                         if (strcmp(pld->searchstr, pld->searchold)) {
774                                 /* free list of temporary search matches */
775                                 BLI_freelistN(&pld->searchp);
776                                 
777                                 /* generate a new list of search matches */
778                                 for (marker= pld->act->markers.first; marker; marker= marker->next) {
779                                         /* does the name partially match? 
780                                          *      - don't worry about case, to make it easier for users to quickly input a name (or 
781                                          *        part of one), which is the whole point of this feature
782                                          */
783                                         if (BLI_strcasestr(marker->name, pld->searchstr)) {
784                                                 /* make link-data to store reference to it */
785                                                 ld= MEM_callocN(sizeof(LinkData), "PoseMatch");
786                                                 ld->data= marker;
787                                                 BLI_addtail(&pld->searchp, ld);
788                                         }
789                                 }
790                                 
791                                 /* set current marker to NULL (so that we start from first) */
792                                 pld->marker= NULL;
793                         }
794                         
795                         /* check if any matches */
796                         if (pld->searchp.first == NULL) { 
797                                 pld->marker= NULL;
798                                 return;
799                         }
800                         
801                         /* find first match */
802                         for (ldc= pld->searchp.first; ldc; ldc= ldc->next) {
803                                 if (ldc->data == pld->marker)
804                                         break;
805                         }
806                         if (ldc == NULL)
807                                 ldc= pld->searchp.first;
808                                 
809                         /* Loop through the matches in a cyclic fashion, incrementing/decrementing step as appropriate 
810                          * until step == 0. At this point, marker should be the correct marker.
811                          */
812                         if (step > 0) {
813                                 for (ld=ldc; ld && step; ld=ldn, step--)
814                                         ldn= (ld->next) ? ld->next : pld->searchp.first;
815                         }
816                         else {
817                                 for (ld=ldc; ld && step; ld=ldn, step++)
818                                         ldn= (ld->prev) ? ld->prev : pld->searchp.last;
819                         }
820                         
821                         /* set marker */
822                         if (ld)
823                                 pld->marker= ld->data;
824                 }
825                 else {
826                         TimeMarker *marker, *next;
827                         
828                         /* Loop through the markers in a cyclic fashion, incrementing/decrementing step as appropriate 
829                          * until step == 0. At this point, marker should be the correct marker.
830                          */
831                         if (step > 0) {
832                                 for (marker=pld->marker; marker && step; marker=next, step--)
833                                         next= (marker->next) ? marker->next : pld->act->markers.first;
834                         }
835                         else {
836                                 for (marker=pld->marker; marker && step; marker=next, step++)
837                                         next= (marker->prev) ? marker->prev : pld->act->markers.last;
838                         }
839                         
840                         /* it should be fairly impossible for marker to be NULL */
841                         if (marker)
842                                 pld->marker= marker;
843                 }
844         }
845 }
846
847 /* specially handle events for searching */
848 static void poselib_preview_handle_search (tPoseLib_PreviewData *pld, unsigned short event, char ascii)
849 {
850         if (ascii) {
851                 /* character to add to the string */
852                 short index= pld->search_cursor;
853                 short len= (pld->searchstr[0]) ? strlen(pld->searchstr) : 0;
854                 short i;
855                 
856                 if (len) {
857                         for (i = len; i > index; i--)  
858                                 pld->searchstr[i]= pld->searchstr[i-1];
859                 }
860                 else
861                         pld->searchstr[1]= 0;
862                         
863                 pld->searchstr[index]= ascii;
864                 pld->search_cursor++;
865                 
866                 poselib_preview_get_next(pld, 1);
867                 pld->redraw = PL_PREVIEW_REDRAWALL;
868         }
869         else {
870                 /* some form of string manipulation */
871                 switch (event) {
872                         case BACKSPACEKEY:
873                                 if (pld->searchstr[0] && pld->search_cursor) {
874                                         short len= strlen(pld->searchstr);
875                                         short index= pld->search_cursor;
876                                         short i;
877                                         
878                                         for (i = index; i <= len; i++) 
879                                                 pld->searchstr[i-1] = pld->searchstr[i];
880                                         
881                                         pld->search_cursor--;
882                                         
883                                         poselib_preview_get_next(pld, 1);
884                                         pld->redraw = PL_PREVIEW_REDRAWALL;
885                                 }       
886                                 break;
887                                 
888                         case DELKEY:
889                                 if (pld->searchstr[0] && pld->searchstr[1]) {
890                                         short len= strlen(pld->searchstr);
891                                         short index= pld->search_cursor;
892                                         int i;
893                                         
894                                         if (index < len) {
895                                                 for (i = index; i < len; i++) 
896                                                         pld->searchstr[i] = pld->searchstr[i+1];
897                                                         
898                                                 poselib_preview_get_next(pld, 1);
899                                                 pld->redraw = PL_PREVIEW_REDRAWALL;
900                                         }
901                                 }
902                                 break;
903                 }
904         }
905 }
906
907 /* handle events for poselib_preview_poses */
908 static void poselib_preview_handle_event (tPoseLib_PreviewData *pld, unsigned short event, char ascii)
909 {
910         /* backup stuff that needs to occur before every operation
911          *      - make a copy of searchstr, so that we know if cache needs to be rebuilt
912          */
913         strcpy(pld->searchold, pld->searchstr);
914         
915         /* if we're currently showing the original pose, only certain events are handled */
916         if (pld->flag & PL_PREVIEW_SHOWORIGINAL) {
917                 switch (event) {
918                         /* exit - cancel */
919                         case ESCKEY:
920                         case RIGHTMOUSE:
921                                 pld->state= PL_PREVIEW_CANCEL;
922                                 break;
923                                 
924                         /* exit - confirm */
925                         case LEFTMOUSE:
926                         case RETKEY:
927                         case PADENTER:
928                         case SPACEKEY:
929                                 pld->state= PL_PREVIEW_CONFIRM;
930                                 break;
931                         
932                         /* view manipulation */
933                         case MIDDLEMOUSE:
934                                 // there's a little bug here that causes the normal header to get drawn while view is manipulated 
935                                 handle_view_middlemouse();
936                                 pld->redraw= PL_PREVIEW_REDRAWHEADER;
937                                 break;
938                                 
939                         /* view manipulation, or searching */
940                         case PAD0: case PAD1: case PAD2: case PAD3: case PAD4:
941                         case PAD5: case PAD6: case PAD7: case PAD8: case PAD9:
942                         case PADPLUSKEY: case PADMINUS:
943                                 persptoetsen(event);
944                                 pld->redraw= PL_PREVIEW_REDRAWHEADER;
945                                 break;
946                                 
947                         case TABKEY:
948                                 pld->flag &= ~PL_PREVIEW_SHOWORIGINAL;
949                                 pld->redraw= PL_PREVIEW_REDRAWALL;
950                                 break;
951                 }
952                 
953                 /* EXITS HERE... */
954                 return;
955         }
956         
957         /* NORMAL EVENT HANDLING... */
958         /* searching takes priority over normal activity */
959         switch (event) {
960                 /* exit - cancel */
961                 case ESCKEY:
962                 case RIGHTMOUSE:
963                         pld->state= PL_PREVIEW_CANCEL;
964                         break;
965                         
966                 /* exit - confirm */
967                 case LEFTMOUSE:
968                 case RETKEY:
969                 case PADENTER:
970                 case SPACEKEY:
971                         pld->state= PL_PREVIEW_CONFIRM;
972                         break;
973                         
974                 /* toggle between original pose and poselib pose*/
975                 case TABKEY:
976                         pld->flag |= PL_PREVIEW_SHOWORIGINAL;
977                         pld->redraw= PL_PREVIEW_REDRAWALL;
978                         break;
979                 
980                 /* change to previous pose (cyclic) */
981                 case PAGEUPKEY:
982                 case WHEELUPMOUSE:
983                         poselib_preview_get_next(pld, -1);
984                         pld->redraw= PL_PREVIEW_REDRAWALL;
985                         break;
986                 
987                 /* change to next pose (cyclic) */
988                 case PAGEDOWNKEY:
989                 case WHEELDOWNMOUSE:
990                         poselib_preview_get_next(pld, 1);
991                         pld->redraw= PL_PREVIEW_REDRAWALL;
992                         break;
993                 
994                 /* jump 5 poses (cyclic, back) */
995                 case DOWNARROWKEY:
996                         poselib_preview_get_next(pld, -5);
997                         pld->redraw= PL_PREVIEW_REDRAWALL;
998                         break;
999                 
1000                 /* jump 5 poses (cyclic, forward) */
1001                 case UPARROWKEY:
1002                         poselib_preview_get_next(pld, 5);
1003                         pld->redraw= PL_PREVIEW_REDRAWALL;
1004                         break;
1005                 
1006                 /* change to next pose or searching cursor control */
1007                 case RIGHTARROWKEY:
1008                         if (pld->searchstr[0]) {
1009                                 /* move text-cursor to the right */
1010                                 if (pld->search_cursor < strlen(pld->searchstr))
1011                                         pld->search_cursor++;
1012                                 pld->redraw= PL_PREVIEW_REDRAWHEADER;
1013                         }
1014                         else {
1015                                 /* change to next pose (cyclic) */
1016                                 poselib_preview_get_next(pld, 1);
1017                                 pld->redraw= PL_PREVIEW_REDRAWALL;
1018                         }
1019                         break;
1020                         
1021                 /* change to next pose or searching cursor control */
1022                 case LEFTARROWKEY:
1023                         if (pld->searchstr[0]) {
1024                                 /* move text-cursor to the left */
1025                                 if (pld->search_cursor)
1026                                         pld->search_cursor--;
1027                                 pld->redraw= PL_PREVIEW_REDRAWHEADER;
1028                         }
1029                         else {
1030                                 /* change to previous pose (cyclic) */
1031                                 poselib_preview_get_next(pld, -1);
1032                                 pld->redraw= PL_PREVIEW_REDRAWALL;
1033                         }
1034                         break;
1035                         
1036                 /* change to first pose or start of searching string */
1037                 case HOMEKEY:
1038                         if (pld->searchstr[0]) {
1039                                 pld->search_cursor= 0;
1040                                 pld->redraw= PL_PREVIEW_REDRAWHEADER;
1041                         }
1042                         else {
1043                                 /* change to first pose */
1044                                 pld->marker= pld->act->markers.first;
1045                                 pld->act->active_marker= 1;
1046                                 
1047                                 pld->redraw= PL_PREVIEW_REDRAWALL;
1048                         }
1049                         break;
1050                         
1051                 /* change to last pose or start of searching string */
1052                 case ENDKEY:
1053                         if (pld->searchstr[0]) {
1054                                 pld->search_cursor= strlen(pld->searchstr);
1055                                 pld->redraw= PL_PREVIEW_REDRAWHEADER;
1056                         }
1057                         else {
1058                                 /* change to last pose */
1059                                 pld->marker= pld->act->markers.last;
1060                                 pld->act->active_marker= BLI_countlist(&pld->act->markers);
1061                                 
1062                                 pld->redraw= PL_PREVIEW_REDRAWALL;
1063                         }
1064                         break;
1065                         
1066                 /* view manipulation */
1067                 case MIDDLEMOUSE:
1068                         // there's a little bug here that causes the normal header to get drawn while view is manipulated 
1069                         handle_view_middlemouse();
1070                         pld->redraw= PL_PREVIEW_REDRAWHEADER;
1071                         break;
1072                         
1073                 /* view manipulation, or searching */
1074                 case PAD0: case PAD1: case PAD2: case PAD3: case PAD4:
1075                 case PAD5: case PAD6: case PAD7: case PAD8: case PAD9:
1076                 case PADPLUSKEY: case PADMINUS:
1077                         if (pld->searchstr[0]) {
1078                                 poselib_preview_handle_search(pld, event, ascii);
1079                         }
1080                         else {
1081                                 persptoetsen(event);
1082                                 pld->redraw= PL_PREVIEW_REDRAWHEADER;
1083                         }
1084                         break;
1085                         
1086                 /* otherwise, assume that searching might be able to handle it */
1087                 default:
1088                         poselib_preview_handle_search(pld, event, ascii);
1089                         break;
1090         }
1091 }
1092
1093 /* ---------------------------- */
1094
1095 /* Init PoseLib Previewing data */
1096 static void poselib_preview_init_data (tPoseLib_PreviewData *pld, Object *ob, short apply_active)
1097 {
1098         /* clear pld first as it resides on the stack */
1099         memset(pld, 0, sizeof(tPoseLib_PreviewData));
1100         
1101         /* get basic data */
1102         pld->ob= ob;
1103         pld->arm= (ob) ? (ob->data) : NULL;
1104         pld->pose= (ob) ? (ob->pose) : NULL;
1105         pld->act= (ob) ? (ob->poselib) : NULL;
1106         pld->marker= poselib_get_active_pose(pld->act);
1107         
1108         /* check if valid poselib */
1109         if (ELEM3(NULL, pld->ob, pld->pose, pld->arm)) {
1110                 error("PoseLib is only for Armatures in PoseMode");
1111                 pld->state= PL_PREVIEW_ERROR;
1112                 return;
1113         }
1114         if (pld->act == NULL) {
1115                 error("Object doesn't have a valid PoseLib");
1116                 pld->state= PL_PREVIEW_ERROR;
1117                 return;
1118         }
1119         if (pld->marker == NULL) {
1120                 if ((apply_active==0) && (pld->act->markers.first)) {
1121                         /* just use first one then... */
1122                         pld->marker= pld->act->markers.first;
1123                         printf("PoseLib had no active pose\n");
1124                 }
1125                 else {
1126                         error("PoseLib has no poses to preview/apply");
1127                         pld->state= PL_PREVIEW_ERROR;
1128                         return;
1129                 }
1130         }
1131         
1132         /* make backups for restoring pose */
1133         poselib_backup_posecopy(pld);
1134         
1135         /* set flags for running */
1136         pld->state= (apply_active) ? PL_PREVIEW_RUNONCE : PL_PREVIEW_RUNNING;
1137         pld->redraw= PL_PREVIEW_REDRAWALL;
1138         pld->flag= PL_PREVIEW_FIRSTTIME;
1139         
1140         /* set depsgraph flags */
1141                 /* make sure the lock is set OK, unlock can be accidentally saved? */
1142         pld->pose->flag |= POSE_LOCKED;
1143         pld->pose->flag &= ~POSE_DO_UNLOCK;
1144         
1145         /* clear strings + search */
1146         strcpy(pld->headerstr, "");
1147         strcpy(pld->searchstr, "");
1148         strcpy(pld->searchold, "");
1149         pld->search_cursor= 0;
1150 }
1151
1152 /* After previewing poses */
1153 static void poselib_preview_cleanup (tPoseLib_PreviewData *pld)
1154 {
1155         Object *ob= pld->ob;
1156         bPose *pose= pld->pose;
1157         bArmature *arm= pld->arm;
1158         bAction *act= pld->act;
1159         TimeMarker *marker= pld->marker;
1160         
1161         /* this signal does one recalc on pose, then unlocks, so ESC or edit will work */
1162         pose->flag |= POSE_DO_UNLOCK;
1163         
1164         /* clear pose if cancelled */
1165         if (pld->state == PL_PREVIEW_CANCEL) {
1166                 poselib_backup_restore(pld);
1167                 
1168                 /* old optimize trick... this enforces to bypass the depgraph 
1169                  *      - note: code copied from transform_generics.c -> recalcData()
1170                  */
1171                 if ((arm->flag & ARM_DELAYDEFORM)==0)
1172                         DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA);  /* sets recalc flags */
1173                 else
1174                         where_is_pose(ob);
1175                 
1176                 allqueue(REDRAWVIEW3D, 0);
1177                 allqueue(REDRAWBUTSEDIT, 0);
1178         }
1179         else if (pld->state == PL_PREVIEW_CONFIRM) {
1180                 /* tag poses as appropriate */
1181                 poselib_keytag_pose(pld);
1182                 
1183                 /* change active pose setting */
1184                 act->active_marker= BLI_findindex(&act->markers, marker) + 1;
1185                 action_set_activemarker(act, marker, 0);
1186                 
1187                 /* Update event for pose and deformation children */
1188                 DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA);
1189                 
1190                 /* updates */
1191                 if (IS_AUTOKEY_MODE(NORMAL)) {
1192                         remake_action_ipos(ob->action);
1193                         
1194                         allqueue(REDRAWIPO, 0);
1195                         allqueue(REDRAWVIEW3D, 0);
1196                         allqueue(REDRAWBUTSEDIT, 0);
1197                         allqueue(REDRAWACTION, 0);              
1198                         allqueue(REDRAWNLA, 0);
1199                 }
1200                 else {
1201                         /* need to trick depgraph, action is not allowed to execute on pose */
1202                         where_is_pose(ob);
1203                         ob->recalc= 0;
1204                         
1205                         allqueue(REDRAWVIEW3D, 0);
1206                         allqueue(REDRAWBUTSEDIT, 0);
1207                 }
1208         }
1209         
1210         /* free memory used for backups */
1211         BLI_freelistN(&pld->backups);
1212         BLI_freelistN(&pld->searchp);
1213 }
1214
1215
1216
1217 /* This tool allows users to preview the pose from the pose-lib using the mouse-scrollwheel/pageupdown
1218  * It is also used to apply the active poselib pose only
1219  */
1220 void poselib_preview_poses (Object *ob, short apply_active)
1221 {
1222         tPoseLib_PreviewData pld;
1223         
1224         unsigned short event;
1225         short val=0;
1226         char ascii;
1227         
1228         /* check if valid poselib */
1229         poselib_preview_init_data(&pld, ob, apply_active);
1230         if (pld.state == PL_PREVIEW_ERROR)
1231                 return;
1232                 
1233         /* start preview loop */
1234         while (ELEM(pld.state, PL_PREVIEW_RUNNING, PL_PREVIEW_RUNONCE)) {
1235                 /* preview a pose */
1236                 if (pld.redraw) {
1237                         /* only recalc pose (and its dependencies) if pose has changed */
1238                         if (pld.redraw == PL_PREVIEW_REDRAWALL) {
1239                                 /* don't clear pose if firsttime */
1240                                 if ((pld.flag & PL_PREVIEW_FIRSTTIME)==0)
1241                                         poselib_backup_restore(&pld);
1242                                 else
1243                                         pld.flag &= ~PL_PREVIEW_FIRSTTIME;
1244                                         
1245                                 /* pose should be the right one to draw (unless we're temporarily not showing it) */
1246                                 if ((pld.flag & PL_PREVIEW_SHOWORIGINAL)==0)
1247                                         poselib_apply_pose(&pld);
1248                                 
1249                                 /* old optimize trick... this enforces to bypass the depgraph 
1250                                  *      - note: code copied from transform_generics.c -> recalcData()
1251                                  */
1252                                 if ((pld.arm->flag & ARM_DELAYDEFORM)==0)
1253                                         DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA);  /* sets recalc flags */
1254                                 else
1255                                         where_is_pose(ob);
1256                         }
1257                         
1258                         /* do header print - if interactively previewing */
1259                         if (pld.state == PL_PREVIEW_RUNNING) {
1260                                 if (pld.flag & PL_PREVIEW_SHOWORIGINAL) {
1261                                         sprintf(pld.headerstr, "PoseLib Previewing Pose: [Showing Original Pose] | Use Tab to start previewing poses again");
1262                                         headerprint(pld.headerstr);
1263                                 }
1264                                 else if (pld.searchstr[0]) {
1265                                         char tempstr[65];
1266                                         char markern[64];
1267                                         short index;
1268                                         
1269                                         /* get search-string */
1270                                         index= pld.search_cursor;
1271                                         
1272                                         if (IN_RANGE(index, 0, 64)) {
1273                                                 memcpy(&tempstr[0], &pld.searchstr[0], index);
1274                                                 tempstr[index]= '|';
1275                                                 memcpy(&tempstr[index+1], &pld.searchstr[index], 64-index);
1276                                         }
1277                                         else {
1278                                                 strncpy(tempstr, pld.searchstr, 64);
1279                                         }
1280                                         
1281                                         /* get marker name */
1282                                         if (pld.marker)
1283                                                 strcpy(markern, pld.marker->name);
1284                                         else
1285                                                 strcpy(markern, "No Matches");
1286                                         
1287                                         sprintf(pld.headerstr, "PoseLib Previewing Pose: Filter - [%s] | Current Pose - \"%s\"  | Use ScrollWheel or PageUp/Down to change", tempstr, markern);
1288                                         headerprint(pld.headerstr);
1289                                 }
1290                                 else {
1291                                         sprintf(pld.headerstr, "PoseLib Previewing Pose: \"%s\"  | Use ScrollWheel or PageUp/Down to change", pld.marker->name);
1292                                         headerprint(pld.headerstr);
1293                                 }
1294                         }
1295                         
1296                         /* force drawing of view + clear redraw flag */
1297                         force_draw(0);
1298                         pld.redraw= PL_PREVIEW_NOREDRAW;
1299                 }
1300                 
1301                 /* stop now if only running once */
1302                 if (pld.state == PL_PREVIEW_RUNONCE) {
1303                         pld.state = PL_PREVIEW_CONFIRM;
1304                         break;
1305                 }
1306                 
1307                 /* essential for idling subloop */
1308                 if (qtest() == 0) 
1309                         PIL_sleep_ms(2);
1310                 
1311                 /* emptying queue and reading events */
1312                 while ( qtest() ) {
1313                         event= extern_qread_ext(&val, &ascii);
1314                         
1315                         /* event processing */
1316                         if (val) {
1317                                 poselib_preview_handle_event(&pld, event, ascii);
1318                         }
1319                 }
1320         }
1321         
1322         /* finish up */
1323         poselib_preview_cleanup(&pld);
1324         
1325         BIF_undo_push("PoseLib Apply Pose");
1326 }