Two bugfixes:
[blender.git] / source / blender / src / editaction.c
1 /**
2  * $Id$
3  *
4  * ***** BEGIN GPL/BL DUAL 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. The Blender
10  * Foundation also sells licenses for use in proprietary software under
11  * the Blender License.  See http://www.blender.org/BL/ for information
12  * about this.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software Foundation,
21  * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
22  *
23  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
24  * All rights reserved.
25  *
26  * The Original Code is: all of this file.
27  *
28  * Contributor(s): 2007, Joshua Leung (major rewrite of Action Editor)
29  *
30  * ***** END GPL/BL DUAL LICENSE BLOCK *****
31  */
32
33 #include <string.h>
34 #include <stddef.h>
35 #include <math.h>
36
37 #include "MEM_guardedalloc.h"
38
39 #include "PIL_time.h"
40
41 #include "BLI_blenlib.h"
42 #include "BLI_arithb.h"
43
44 #include "DNA_action_types.h"
45 #include "DNA_armature_types.h"
46 #include "DNA_curve_types.h"
47 #include "DNA_ipo_types.h"
48 #include "DNA_object_types.h"
49 #include "DNA_scene_types.h"
50 #include "DNA_screen_types.h"
51 #include "DNA_space_types.h"
52 #include "DNA_userdef_types.h"
53 #include "DNA_constraint_types.h"
54 #include "DNA_key_types.h"
55 #include "DNA_mesh_types.h"
56 #include "DNA_nla_types.h"
57 #include "DNA_lattice_types.h"
58
59 #include "BKE_action.h"
60 #include "BKE_armature.h"
61 #include "BKE_constraint.h"
62 #include "BKE_curve.h"
63 #include "BKE_depsgraph.h"
64 #include "BKE_global.h"
65 #include "BKE_ipo.h"
66 #include "BKE_key.h"
67 #include "BKE_library.h"
68 #include "BKE_main.h"
69 #include "BKE_utildefines.h"
70 #include "BKE_object.h" /* for where_is_object in obanim -> action baking */
71
72 #include "BIF_butspace.h"
73 #include "BIF_editaction.h"
74 #include "BIF_editarmature.h"
75 #include "BIF_editnla.h"
76 #include "BIF_editview.h"
77 #include "BIF_gl.h"
78 #include "BIF_interface.h"
79 #include "BIF_mywindow.h"
80 #include "BIF_poseobject.h"
81 #include "BIF_screen.h"
82 #include "BIF_space.h"
83 #include "BIF_toolbox.h"
84 #include "BIF_transform.h"
85
86 #include "BSE_edit.h"
87 #include "BSE_drawipo.h"
88 #include "BSE_headerbuttons.h"
89 #include "BSE_editaction_types.h"
90 #include "BSE_editipo.h"
91 #include "BSE_time.h"
92 #include "BSE_trans_types.h"
93
94 #include "BDR_drawaction.h"
95 #include "BDR_editobject.h"
96
97 #include "mydevice.h"
98 #include "blendef.h"
99 #include "nla.h"
100
101 /* **************************************************** */
102 /* ACTION API */
103
104 /* this function adds a new Action block */
105 bAction *add_empty_action (char *name)
106 {
107         bAction *act;
108         
109         act= alloc_libblock(&G.main->action, ID_AC, name);
110         act->id.flag |= LIB_FAKEUSER;
111         act->id.us++;
112         
113         return act;
114 }
115
116 /* generic get current action call, for action window context */
117 bAction *ob_get_action (Object *ob)
118 {
119         bActionStrip *strip;
120         
121         if(ob->action)
122                 return ob->action;
123         
124         for (strip=ob->nlastrips.first; strip; strip=strip->next) {
125                 if (strip->flag & ACTSTRIP_SELECT)
126                         return strip->act;
127         }
128         return NULL;
129 }
130
131 /* used by ipo, outliner, buttons to find the active channel */
132 bActionChannel *get_hilighted_action_channel (bAction *action)
133 {
134         bActionChannel *achan;
135
136         if (!action)
137                 return NULL;
138
139         for (achan= action->chanbase.first; achan; achan= achan->next) {
140                 if (VISIBLE_ACHAN(achan)) {
141                         if (SEL_ACHAN(achan) && (achan->flag & ACHAN_HILIGHTED))
142                                 return achan;
143                 }
144         }
145
146         return NULL;
147 }
148
149 /* ----------------------------------------- */
150
151 void remake_action_ipos (bAction *act)
152 {
153         bActionChannel *achan;
154         bConstraintChannel *conchan;
155         IpoCurve *icu;
156
157         for (achan= act->chanbase.first; achan; achan= achan->next) {
158                 if (achan->ipo) {
159                         for (icu = achan->ipo->curve.first; icu; icu=icu->next) {
160                                 sort_time_ipocurve(icu);
161                                 testhandles_ipocurve(icu);
162                         }
163                 }
164                 for (conchan=achan->constraintChannels.first; conchan; conchan=conchan->next) {
165                         if (conchan->ipo) {
166                                 for (icu = conchan->ipo->curve.first; icu; icu=icu->next) {
167                                         sort_time_ipocurve(icu);
168                                         testhandles_ipocurve(icu);
169                                 }
170                         }
171                 }
172         }
173         
174         synchronize_action_strips();
175 }
176
177 /* **************************************************** */
178 /* FILTER->EDIT STRUCTURES */
179 /* 
180  * This method involves generating a list of edit structures which enable
181  * tools to naively perform the actions they require without all the boiler-plate
182  * associated with loops within loops and checking for cases to ignore. 
183  */
184
185 /* this function allocates memory for a new bActListElem struct for the 
186  * provided action channel-data. 
187  */
188 bActListElem *make_new_actlistelem (void *data, short datatype, void *owner, short ownertype)
189 {
190         bActListElem *ale= NULL;
191         
192         /* only allocate memory if there is data to convert */
193         if (data) {
194                 /* allocate and set generic data */
195                 ale= MEM_callocN(sizeof(bActListElem), "bActListElem");
196                 
197                 ale->data= data;
198                 ale->type= datatype;
199                 ale->owner= owner;
200                 ale->ownertype= ownertype;
201                 
202                 if ((owner) && (ownertype == ACTTYPE_ACHAN)) {
203                         bActionChannel *ochan= (bActionChannel *)owner;
204                         ale->grp= ochan->grp;
205                 }
206                 else 
207                         ale->grp= NULL;
208                 
209                 /* do specifics */
210                 switch (datatype) {
211                         case ACTTYPE_GROUP:
212                         {
213                                 bActionGroup *agrp= (bActionGroup *)data;
214                                 
215                                 ale->flag= agrp->flag;
216                                 
217                                 ale->key_data= NULL;
218                                 ale->datatype= ALE_GROUP;
219                         }
220                                 break;
221                         case ACTTYPE_ACHAN:
222                         {
223                                 bActionChannel *achan= (bActionChannel *)data;
224                                 
225                                 ale->flag= achan->flag;
226                                 
227                                 if (achan->ipo) {
228                                         ale->key_data= achan->ipo;
229                                         ale->datatype= ALE_IPO;
230                                 }
231                                 else {
232                                         ale->key_data= NULL;
233                                         ale->datatype= ALE_NONE;
234                                 }
235                         }       
236                                 break;
237                         case ACTTYPE_CONCHAN:
238                         {
239                                 bConstraintChannel *conchan= (bConstraintChannel *)data;
240                                 
241                                 ale->flag= conchan->flag;
242                                 
243                                 if (conchan->ipo && conchan->ipo->curve.first) {
244                                         /* we assume that constraint ipo blocks only have 1 curve:
245                                          * INFLUENCE, so we pretend that a constraint channel is 
246                                          * really just a Ipo-Curve channel instead.
247                                          */
248                                         ale->key_data= conchan->ipo->curve.first;
249                                         ale->datatype= ALE_ICU;
250                                 }
251                                 else {
252                                         ale->key_data= NULL;
253                                         ale->datatype= ALE_NONE;
254                                 }
255                         }
256                                 break;
257                         case ACTTYPE_ICU:
258                         {
259                                 IpoCurve *icu= (IpoCurve *)data;
260                                 
261                                 ale->flag= icu->flag;
262                                 ale->key_data= icu;
263                                 ale->datatype= ALE_ICU;
264                         }
265                                 break;
266                                 
267                         case ACTTYPE_FILLIPO:
268                         case ACTTYPE_FILLCON:
269                         {
270                                 bActionChannel *achan= (bActionChannel *)data;
271                                 
272                                 if (datatype == ACTTYPE_FILLIPO)
273                                         ale->flag= FILTER_IPO_ACHAN(achan);
274                                 else
275                                         ale->flag= FILTER_CON_ACHAN(achan);
276                                         
277                                 ale->key_data= NULL;
278                                 ale->datatype= ALE_NONE;
279                         }
280                                 break;
281                         case ACTTYPE_IPO:
282                         {
283                                 ale->flag= 0;
284                                 ale->key_data= data;
285                                 ale->datatype= ALE_IPO;
286                         }
287                                 break;
288                 }
289         }
290         
291         /* return created datatype */
292         return ale;
293 }
294  
295 /* ----------------------------------------- */
296  
297 static void actdata_filter_actionchannel (ListBase *act_data, bActionChannel *achan, int filter_mode)
298 {
299         bActListElem *ale;
300         bConstraintChannel *conchan;
301         IpoCurve *icu;
302         
303         /* only work with this channel and its subchannels if it is visible */
304         if (!(filter_mode & ACTFILTER_VISIBLE) || VISIBLE_ACHAN(achan)) {
305                 /* only work with this channel and its subchannels if it is editable */
306                 if (!(filter_mode & ACTFILTER_FOREDIT) || EDITABLE_ACHAN(achan)) {
307                         /* check if this achan should only be included if it is selected */
308                         if (!(filter_mode & ACTFILTER_SEL) || SEL_ACHAN(achan)) {
309                                 /* are we only interested in the ipo-curves? */
310                                 if ((filter_mode & ACTFILTER_ONLYICU)==0) {
311                                         ale= make_new_actlistelem(achan, ACTTYPE_ACHAN, achan, ACTTYPE_ACHAN);
312                                         if (ale) BLI_addtail(act_data, ale);
313                                 }
314                         }
315                         else {
316                                 /* only consider selected channels - achan not selected */
317                                 return;
318                         }       
319                         
320                         /* check if expanded - if not, continue on to next action channel */
321                         if (EXPANDED_ACHAN(achan) == 0 && (filter_mode & ACTFILTER_ONLYICU)==0) 
322                                 return;
323                                 
324                         /* ipo channels */
325                         if (achan->ipo) {
326                                 /* include ipo-expand widget? */
327                                 if ((filter_mode & ACTFILTER_CHANNELS) && (filter_mode & ACTFILTER_ONLYICU)==0) {
328                                         ale= make_new_actlistelem(achan, ACTTYPE_FILLIPO, achan, ACTTYPE_ACHAN);
329                                         if (ale) BLI_addtail(act_data, ale);
330                                 }
331                                 
332                                 /* add ipo-curve channels? */
333                                 if (FILTER_IPO_ACHAN(achan) || (filter_mode & ACTFILTER_ONLYICU)) {
334                                         /* loop through ipo-curve channels, adding them */
335                                         for (icu= achan->ipo->curve.first; icu; icu=icu->next) {
336                                                 ale= make_new_actlistelem(icu, ACTTYPE_ICU, achan, ACTTYPE_ACHAN);
337                                                 if (ale) BLI_addtail(act_data, ale); 
338                                         }
339                                 }
340                         }
341                         
342                         /* constraint channels */
343                         if (achan->constraintChannels.first) {
344                                 /* include constraint-expand widget? */
345                                 if ((filter_mode & ACTFILTER_CHANNELS) && (filter_mode & ACTFILTER_ONLYICU)==0) {
346                                         ale= make_new_actlistelem(achan, ACTTYPE_FILLCON, achan, ACTTYPE_ACHAN);
347                                         if (ale) BLI_addtail(act_data, ale);
348                                 }
349                                 
350                                 /* add constaint channels? */
351                                 if (FILTER_CON_ACHAN(achan)) {
352                                         /* loop through constraint channels, checking and adding them */
353                                         for (conchan=achan->constraintChannels.first; conchan; conchan=conchan->next) {
354                                                 /* only work with this channel and its subchannels if it is editable */
355                                                 if (!(filter_mode & ACTFILTER_FOREDIT) || EDITABLE_CONCHAN(conchan)) {
356                                                         /* check if this conchan should only be included if it is selected */
357                                                         if (!(filter_mode & ACTFILTER_SEL) || SEL_CONCHAN(conchan)) {
358                                                                 if ((filter_mode & ACTFILTER_ONLYICU)==0) {
359                                                                         ale= make_new_actlistelem(conchan, ACTTYPE_CONCHAN, achan, ACTTYPE_ACHAN);
360                                                                         if (ale) BLI_addtail(act_data, ale); 
361                                                                 }
362                                                         }
363                                                 }
364                                         }
365                                 }
366                         }
367                 }               
368         }
369 }
370
371 static void actdata_filter_action (ListBase *act_data, bAction *act, int filter_mode)
372 {
373         bActListElem *ale;
374         bActionGroup *agrp;
375         bActionChannel *achan, *lastchan=NULL;
376         
377         /* loop over groups */
378         for (agrp= act->groups.first; agrp; agrp= agrp->next) {
379                 /* add this group as a channel first */
380                 if (!(filter_mode & ACTFILTER_ONLYICU) && !(filter_mode & ACTFILTER_IPOKEYS)) {
381                         ale= make_new_actlistelem(agrp, ACTTYPE_GROUP, NULL, ACTTYPE_NONE);
382                         if (ale) BLI_addtail(act_data, ale);
383                 }
384                 
385                 /* store reference to last channel of group */
386                 if (agrp->channels.last) 
387                         lastchan= agrp->channels.last;
388                 
389                 /* filters here are a bit convulted...
390                  *      - groups show a "summary" of keyframes beside their name which must accessable for tools which handle keyframes
391                  *      - groups can be collapsed (and those tools which are only interested in channels rely on knowing that group is closed)
392                  */
393                 if (!(filter_mode & ACTFILTER_VISIBLE) || EXPANDED_AGRP(agrp) || 
394                         (filter_mode & (ACTFILTER_IPOKEYS|ACTFILTER_ONLYICU))) 
395                 {
396                         if (!(filter_mode & ACTFILTER_FOREDIT) || EDITABLE_AGRP(agrp)) {                                        
397                                 for (achan= agrp->channels.first; achan && achan->grp==agrp; achan= achan->next) {
398                                         actdata_filter_actionchannel(act_data, achan, filter_mode);
399                                 }
400                         }
401                 }
402         }
403         
404         /* loop over action channels */
405         for (achan=(lastchan)?lastchan->next:act->chanbase.first; achan; achan=achan->next) {
406                 actdata_filter_actionchannel(act_data, achan, filter_mode);
407         }
408 }
409
410 static void actdata_filter_shapekey (ListBase *act_data, Key *key, int filter_mode)
411 {
412         bActListElem *ale;
413         KeyBlock *kb;
414         IpoCurve *icu;
415         int i;
416         
417         /* are we filtering for display or editing */
418         if (filter_mode & ACTFILTER_FORDRAWING) {
419                 /* for display - loop over shapekeys, adding ipo-curve references where needed */
420                 kb= key->block.first;
421                 
422                 /* loop through possible shapekeys, manually creating entries */
423                 for (i= 1; i < key->totkey; i++) {
424                         ale= MEM_callocN(sizeof(bActListElem), "bActListElem");
425                         kb = kb->next;
426                         
427                         ale->data= kb;
428                         ale->type= ACTTYPE_SHAPEKEY; /* 'abused' usage of this type */
429                         ale->owner= key;
430                         ale->ownertype= ACTTYPE_SHAPEKEY;
431                         ale->datatype= ALE_NONE;
432                         ale->index = i;
433                         
434                         if (key->ipo) {
435                                 for (icu= key->ipo->curve.first; icu; icu=icu->next) {
436                                         if (icu->adrcode == i) {
437                                                 ale->key_data= icu;
438                                                 ale->datatype= ALE_ICU;
439                                                 break;
440                                         }
441                                 }
442                         }
443                         
444                         BLI_addtail(act_data, ale);
445                 }
446         }
447         else {
448                 /* loop over ipo curves if present - for editing */
449                 if (key->ipo) {
450                         if (filter_mode & ACTFILTER_IPOKEYS) {
451                                 ale= make_new_actlistelem(key->ipo, ACTTYPE_IPO, key, ACTTYPE_SHAPEKEY);
452                                 if (ale) BLI_addtail(act_data, ale);
453                         }
454                         else {
455                                 for (icu= key->ipo->curve.first; icu; icu=icu->next) {
456                                         ale= make_new_actlistelem(icu, ACTTYPE_ICU, key, ACTTYPE_SHAPEKEY);
457                                         if (ale) BLI_addtail(act_data, ale);
458                                 }
459                         }
460                 }
461         }
462 }
463  
464 /* This function filters the active data source to leave only the desired
465  * data types. 'Public' api call.
466  *      *act_data: is a pointer to a ListBase, to which the filtered action data 
467  *              will be placed for use.
468  *      filter_mode: how should the data be filtered - bitmapping accessed flags
469  */
470 void actdata_filter (ListBase *act_data, int filter_mode, void *data, short datatype)
471 {
472         /* only filter data if there's somewhere to put it */
473         if (data && act_data) {
474                 bActListElem *ale, *next;
475                 
476                 /* firstly filter the data */
477                 switch (datatype) {
478                         case ACTCONT_ACTION:
479                                 actdata_filter_action(act_data, data, filter_mode);
480                                 break;
481                         case ACTCONT_SHAPEKEY:
482                                 actdata_filter_shapekey(act_data, data, filter_mode);
483                                 break;
484                 }
485                         
486                 /* remove any weedy entries */
487                 for (ale= act_data->first; ale; ale= next) {
488                         next= ale->next;
489                         
490                         if (ale->type == ACTTYPE_NONE)
491                                 BLI_freelinkN(act_data, ale);
492                         
493                         if (filter_mode & ACTFILTER_IPOKEYS) {
494                                 if (ale->datatype != ALE_IPO)
495                                         BLI_freelinkN(act_data, ale);
496                                 else if (ale->key_data == NULL)
497                                         BLI_freelinkN(act_data, ale);
498                         }
499                 }
500         }
501 }
502
503 /* **************************************************** */
504 /* GENERAL ACTION TOOLS */
505
506 /* gets the key data from the currently selected
507  * mesh/lattice. If a mesh is not selected, or does not have
508  * key data, then we return NULL (currently only
509  * returns key data for RVK type meshes). If there
510  * is an action that is pinned, return null
511  */
512 /* Note: there's a similar function in key.c (ob_get_key) */
513 Key *get_action_mesh_key(void) 
514 {
515     Object *ob;
516     Key    *key;
517
518     ob = OBACT;
519     if (ob == NULL) 
520                 return NULL;
521
522         if (G.saction->pin) return NULL;
523
524     if (ob->type==OB_MESH) 
525                 key = ((Mesh *)ob->data)->key;
526         else if (ob->type==OB_LATTICE) 
527                 key = ((Lattice *)ob->data)->key;
528         else 
529                 return NULL;
530
531         if (key) {
532                 if (key->type == KEY_RELATIVE)
533                         return key;
534         }
535
536     return NULL;
537 }
538
539 /* TODO: kill this! */
540 int get_nearest_key_num (Key *key, short *mval, float *x) 
541 {
542         /* returns the key num that cooresponds to the
543          * y value of the mouse click. Does not check
544          * if this is a valid keynum. Also gives the Ipo
545          * x coordinate.
546          */
547     int num;
548     float y;
549
550     areamouseco_to_ipoco(G.v2d, mval, x, &y);
551     num = (int) ((CHANNELHEIGHT/2 - y) / (CHANNELHEIGHT+CHANNELSKIP));
552
553     return (num + 1);
554 }
555
556 /* this function is used to get a pointer to an action or shapekey 
557  * datablock, thus simplying that process.
558  */
559 /* this function is intended for use */
560 void *get_nearest_act_channel (short mval[], short *ret_type)
561 {
562         ListBase act_data = {NULL, NULL};
563         bActListElem *ale;
564         void *data;
565         short datatype;
566         int filter;
567         
568         int clickmin, clickmax;
569         float x,y;
570         
571         /* determine what type of data we are operating on */
572         data = get_action_context(&datatype);
573         if (data == NULL) {
574                 *ret_type= ACTTYPE_NONE;
575                 return NULL;
576         }
577         
578     areamouseco_to_ipoco(G.v2d, mval, &x, &y);
579         clickmin = (int) (((CHANNELHEIGHT/2) - y) / (CHANNELHEIGHT+CHANNELSKIP));
580         clickmax = clickmin;
581         
582         if (clickmax < 0) {
583                 *ret_type= ACTTYPE_NONE;
584                 return NULL;
585         }
586         
587         /* filter data */
588         filter= (ACTFILTER_FORDRAWING | ACTFILTER_VISIBLE | ACTFILTER_CHANNELS);
589         actdata_filter(&act_data, filter, data, datatype);
590         
591         for (ale= act_data.first; ale; ale= ale->next) {
592                 if (clickmax < 0) 
593                         break;
594                 if (clickmin <= 0) {
595                         /* found match */
596                         *ret_type= ale->type;
597                         data= ale->data;
598                         
599                         BLI_freelistN(&act_data);
600                         
601                         return data;
602                 }
603                 --clickmin;
604                 --clickmax;
605         }
606         
607         /* cleanup */
608         BLI_freelistN(&act_data);
609         
610         *ret_type= ACTTYPE_NONE;
611         return NULL;
612 }
613
614 /* used only by mouse_action. It is used to find the location of the nearest 
615  * keyframe to where the mouse clicked, 
616  */
617 static void *get_nearest_action_key (float *selx, short *sel, short *ret_type, bActionChannel **par)
618 {
619         ListBase act_data = {NULL, NULL};
620         ListBase act_keys = {NULL, NULL};
621         bActListElem *ale;
622         ActKeyColumn *ak;
623         void *data;
624         short datatype;
625         int filter;
626         
627         rctf rectf;
628         float xmin, xmax, x, y;
629         int clickmin, clickmax;
630         short mval[2];
631         short found = 0;
632                 
633         getmouseco_areawin (mval);
634
635         /* action-channel */
636         *par= NULL;
637         
638         /* determine what type of data we are operating on */
639         data = get_action_context(&datatype);
640         if (data == NULL) {
641                 *ret_type= ACTTYPE_NONE;
642                 return NULL;
643         }
644
645     areamouseco_to_ipoco(G.v2d, mval, &x, &y);
646     clickmin = (int) (((CHANNELHEIGHT/2) - y) / (CHANNELHEIGHT+CHANNELSKIP));
647         clickmax = clickmin;
648         
649         mval[0]-=7;
650         areamouseco_to_ipoco(G.v2d, mval, &rectf.xmin, &rectf.ymin);
651         mval[0]+=14;
652         areamouseco_to_ipoco(G.v2d, mval, &rectf.xmax, &rectf.ymax);
653
654         /* if action is mapped in NLA, it returns a correction */
655         if (NLA_ACTION_SCALED && datatype==ACTCONT_ACTION) {
656                 xmin= get_action_frame(OBACT, rectf.xmin);
657                 xmax= get_action_frame(OBACT, rectf.xmax);
658         }
659         else {
660                 xmin= rectf.xmin;
661                 xmax= rectf.xmax;
662         }
663         
664         if (clickmax < 0) {
665                 *ret_type= ACTTYPE_NONE;
666                 return NULL;
667         }
668                 
669         /* filter data */
670         filter= (ACTFILTER_FORDRAWING | ACTFILTER_VISIBLE | ACTFILTER_CHANNELS);
671         actdata_filter(&act_data, filter, data, datatype);
672         
673         for (ale= act_data.first; ale; ale= ale->next) {
674                 if (clickmax < 0) 
675                         break;
676                 if (clickmin <= 0) {
677                         /* found match */
678                         
679                         /* make list of keyframes */
680                         if (ale->key_data) {
681                                 switch (ale->datatype) {
682                                         case ALE_IPO:
683                                         {
684                                                 Ipo *ipo= (Ipo *)ale->key_data;
685                                                 ipo_to_keylist(ipo, &act_keys, NULL);
686                                         }
687                                                 break;
688                                         case ALE_ICU:
689                                         {
690                                                 IpoCurve *icu= (IpoCurve *)ale->key_data;
691                                                 icu_to_keylist(icu, &act_keys, NULL);
692                                         }
693                                                 break;
694                                 }
695                         }
696                         else if (ale->type == ACTTYPE_GROUP) {
697                                 bActionGroup *agrp= (bActionGroup *)ale->data;
698                                 agroup_to_keylist(agrp, &act_keys, NULL);
699                         }
700                         
701                         /* loop through keyframes, finding one that was clicked on */
702                         for (ak= act_keys.first; ak; ak= ak->next) {
703                                 if (IN_RANGE(ak->cfra, xmin, xmax)) {
704                                         *selx= ak->cfra;
705                                         found= 1;
706                                         break;
707                                 }
708                         }
709                         /* no matching keyframe found - set to mean frame value so it doesn't actually select anything */
710                         if (found == 0)
711                                 *selx= ((xmax+xmin) / 2);
712                         
713                         /* figure out what to return */
714                         if (datatype == ACTCONT_ACTION) {
715                                 *par= ale->owner; /* assume that this is an action channel */
716                                 *ret_type= ale->type;
717                                 data = ale->data;
718                         }
719                         else if (datatype == ACTCONT_SHAPEKEY) {
720                                 data = ale->key_data;
721                                 *ret_type= ACTTYPE_ICU;
722                         }
723                         
724                         /* cleanup tempolary lists */
725                         BLI_freelistN(&act_keys);
726                         act_keys.first = act_keys.last = NULL;
727                         
728                         BLI_freelistN(&act_data);
729                         
730                         return data;
731                 }
732                 --clickmin;
733                 --clickmax;
734         }
735         
736         /* cleanup */
737         BLI_freelistN(&act_data);
738         
739         *ret_type= ACTTYPE_NONE;
740         return NULL;
741 }
742
743 void *get_action_context (short *datatype)
744 {
745         bAction *act;
746         Key *key;
747         
748         /* get pointers to active action/shapekey blocks */
749         act = (G.saction)? G.saction->action: NULL;
750         key = get_action_mesh_key();
751         
752         if (act) {
753                 *datatype= ACTCONT_ACTION;
754                 return act;
755         }
756         else if (key) {
757                 *datatype= ACTCONT_SHAPEKEY;
758                 return key;
759         }
760         else {
761                 *datatype= ACTCONT_NONE;
762                 return NULL;
763         }
764 }
765
766 /* **************************************************** */
767 /* ACTION CHANNEL GROUPS */
768
769 /* Get the active action-group for an Action */
770 bActionGroup *get_active_actiongroup (bAction *act)
771 {
772         bActionGroup *agrp= NULL;
773         
774         if (act && act->groups.first) { 
775                 for (agrp= act->groups.first; agrp; agrp= agrp->next) {
776                         if (agrp->flag & AGRP_ACTIVE)
777                                 break;
778                 }
779         }
780         
781         return agrp;
782 }
783
784 /* Make the given Action-Group the active one */
785 void set_active_actiongroup (bAction *act, bActionGroup *agrp, short select)
786 {
787         bActionGroup *grp;
788         
789         /* sanity checks */
790         if (act == NULL)
791                 return;
792         
793         /* Deactive all others */
794         for (grp= act->groups.first; grp; grp= grp->next) {
795                 if ((grp==agrp) && (select))
796                         grp->flag |= AGRP_ACTIVE;
797                 else    
798                         grp->flag &= ~AGRP_ACTIVE;
799         }
800 }
801
802 /* Add given channel into (active) group 
803  *      - assumes that channel is not linked to anything anymore
804  *      - always adds at the end of the group 
805  */
806 static void action_groups_addachan (bAction *act, bActionGroup *agrp, bActionChannel *achan)
807 {
808         bActionChannel *chan;
809         short done=0;
810         
811         /* sanity checks */
812         if (ELEM3(NULL, act, agrp, achan))
813                 return;
814         
815         /* if no channels, just add to two lists at the same time */
816         if (act->chanbase.first == NULL) {
817                 achan->next = achan->prev = NULL;
818                 
819                 agrp->channels.first = agrp->channels.last = achan;
820                 act->chanbase.first = act->chanbase.last = achan;
821                 
822                 achan->grp= agrp;
823                 return;
824         }
825         
826         /* try to find a channel to slot this in before/after */
827         for (chan= act->chanbase.first; chan; chan= chan->next) {
828                 /* if channel has no group, then we have ungrouped channels, which should always occur after groups */
829                 if (chan->grp == NULL) {
830                         BLI_insertlinkbefore(&act->chanbase, chan, achan);
831                         
832                         if (agrp->channels.first == NULL)
833                                 agrp->channels.first= achan;
834                         agrp->channels.last= achan;
835                         
836                         done= 1;
837                         break;
838                 }
839                 
840                 /* if channel has group after current, we can now insert (otherwise we have gone too far) */
841                 else if (chan->grp == agrp->next) {
842                         BLI_insertlinkbefore(&act->chanbase, chan, achan);
843                         
844                         if (agrp->channels.first == NULL)
845                                 agrp->channels.first= achan;
846                         agrp->channels.last= achan;
847                         
848                         done= 1;
849                         break;
850                 }
851                 
852                 /* if channel has group we're targeting, check whether it is the last one of these */
853                 else if (chan->grp == agrp) {
854                         if ((chan->next) && (chan->next->grp != agrp)) {
855                                 BLI_insertlinkafter(&act->chanbase, chan, achan);
856                                 agrp->channels.last= achan;
857                                 done= 1;
858                                 break;
859                         }
860                         else if (chan->next == NULL) {
861                                 BLI_addtail(&act->chanbase, achan);
862                                 agrp->channels.last= achan;
863                                 done= 1;
864                                 break;
865                         }
866                 }
867                 
868                 /* if channel has group before target, check whether the next one is something after target */
869                 else if (chan->grp == agrp->prev) {
870                         if (chan->next) {
871                                 if ((chan->next->grp != chan->grp) && (chan->next->grp != agrp)) {
872                                         BLI_insertlinkafter(&act->chanbase, chan, achan);
873                                         
874                                         agrp->channels.first= achan;
875                                         agrp->channels.last= achan;
876                                         
877                                         done= 1;
878                                         break;
879                                 }
880                         }
881                         else {
882                                 BLI_insertlinkafter(&act->chanbase, chan, achan);
883                                         
884                                 agrp->channels.first= achan;
885                                 agrp->channels.last= achan;
886                                 
887                                 done= 1;
888                                 break;
889                         }
890                 }
891         }
892         
893         /* only if added, set channel as belonging to this group */
894         if (done) {
895                 achan->grp= agrp;
896         }
897         else 
898                 printf("Error: ActionChannel: '%s' couldn't be added to Group: '%s' \n", achan->name, agrp->name);
899 }       
900
901 /* Remove the given channel from all groups */
902 static void action_groups_removeachan (bAction *act, bActionChannel *achan)
903 {
904         /* sanity checks */
905         if (ELEM(NULL, act, achan))     
906                 return;
907         
908         /* check if any group used this directly */
909         if (achan->grp) {
910                 bActionGroup *agrp= achan->grp;
911                 
912                 if (agrp->channels.first == agrp->channels.last) {
913                         if (agrp->channels.first == achan) {
914                                 agrp->channels.first= NULL;
915                                 agrp->channels.last= NULL;
916                         }
917                 }
918                 else if (agrp->channels.first == achan) {
919                         if ((achan->next) && (achan->next->grp==agrp))
920                                 agrp->channels.first= achan->next;
921                         else
922                                 agrp->channels.first= NULL;
923                 }
924                 else if (agrp->channels.last == achan) {
925                         if ((achan->prev) && (achan->prev->grp==agrp))
926                                 agrp->channels.last= achan->prev;
927                         else
928                                 agrp->channels.last= NULL;
929                 }
930                 
931                 achan->grp= NULL;
932         }
933         
934         /* now just remove from list */
935         BLI_remlink(&act->chanbase, achan);
936 }
937
938 /* Add a new Action-Group or add channels to active one */
939 void action_groups_group (short add_group)
940 {
941         bAction *act;
942         bActionChannel *achan, *anext;
943         bActionGroup *agrp;
944         void *data;
945         short datatype;
946         
947         /* validate type of data we are working on */
948         data = get_action_context(&datatype);
949         if (data == NULL) return;
950         if (datatype != ACTCONT_ACTION) return;
951         act= (bAction *)data;
952         
953         /* get active group */
954         if ((act->groups.first==NULL) || (add_group)) {         
955                 /* Add a new group, and make it active */
956                 agrp= MEM_callocN(sizeof(bActionGroup), "bActionGroup");
957                 
958                 agrp->flag |= (AGRP_ACTIVE|AGRP_SELECTED|AGRP_EXPANDED);
959                 sprintf(agrp->name, "Group");
960                 
961                 BLI_addtail(&act->groups, agrp);
962                 BLI_uniquename(&act->groups, agrp, "Group", offsetof(bActionGroup, name), 32);
963                 
964                 set_active_actiongroup(act, agrp, 1);
965                 
966                 add_group= 1;
967         }
968         else {
969                 agrp= get_active_actiongroup(act);
970                 
971                 if (agrp == NULL) {
972                         error("No Active Action Group");
973                         return;
974                 }
975         }
976         
977         /* loop through action-channels, finding those that are selected + visible to move */
978         // FIXME: this should be done with action api instead 
979         for (achan= act->chanbase.first; achan; achan= anext) {
980                 anext= achan->next;
981                 
982                 /* make sure not already in new-group */
983                 if (achan->grp != agrp) {
984                         if ((achan->grp==NULL) || (EXPANDED_AGRP(achan->grp))) { 
985                                 if (VISIBLE_ACHAN(achan) && SEL_ACHAN(achan)) {
986                                         /* unlink from everything else */
987                                         action_groups_removeachan(act, achan);
988                                         
989                                         /* add to end of group's channels */
990                                         action_groups_addachan(act, agrp, achan);
991                                 }
992                         }
993                 }
994         }
995         
996         /* updates and undo */
997         if (add_group)
998                 BIF_undo_push("Add Action Group");
999         else
1000                 BIF_undo_push("Add to Action Group");
1001         
1002         allqueue(REDRAWACTION, 0);
1003 }
1004
1005 /* Remove selected channels from their groups */
1006 void action_groups_ungroup (void)
1007 {
1008         ListBase act_data = {NULL, NULL};
1009         bActListElem *ale;
1010         bAction *act;
1011         void *data;
1012         short datatype;
1013         short filter;
1014         
1015         /* validate type of data we are working on */
1016         data = get_action_context(&datatype);
1017         if (data == NULL) return;
1018         if (datatype != ACTCONT_ACTION) return;
1019         act= (bAction *)data;
1020         
1021         /* filter data */
1022         filter= (ACTFILTER_VISIBLE|ACTFILTER_SEL);
1023         actdata_filter(&act_data, filter, act, ACTCONT_ACTION);
1024         
1025         /* Only ungroup selected action-channels */
1026         for (ale= act_data.first; ale; ale= ale->next) {
1027                 if (ale->type == ACTTYPE_ACHAN) {
1028                         action_groups_removeachan(act, ale->data);
1029                         BLI_addtail(&act->chanbase, ale->data);
1030                 }
1031         }
1032         
1033         BLI_freelistN(&act_data);
1034                 
1035         /* updates and undo */
1036         BIF_undo_push("Remove From Action Groups");
1037         
1038         allqueue(REDRAWACTION, 0);
1039 }
1040
1041 /* This function is used when inserting keyframes for pose-channels. It assigns the
1042  * action-channel with the nominated name to a group with the same name as that of 
1043  * the pose-channel with the nominated name.
1044  *
1045  * Note: this function calls validate_action_channel if action channel doesn't exist 
1046  */
1047 void verify_pchan2achan_grouping (bAction *act, bPose *pose, char name[])
1048 {
1049         bActionChannel *achan;
1050         bPoseChannel *pchan;
1051         
1052         /* sanity checks */
1053         if (ELEM3(NULL, act, pose, name))
1054                 return;
1055         if (name[0] == 0)
1056                 return;
1057                 
1058         /* try to get the channels */
1059         pchan= get_pose_channel(pose, name);
1060         if (pchan == NULL) return;
1061         achan= verify_action_channel(act, name);
1062         
1063         /* check if pchan has a group */
1064         if ((pchan->agrp_index) && (achan->grp == NULL)) {
1065                 bActionGroup *agrp, *grp=NULL;
1066                 
1067                 /* get group to try to be like */
1068                 agrp= (bActionGroup *)BLI_findlink(&pose->agroups, (pchan->agrp_index - 1));
1069                 if (agrp == NULL) {
1070                         error("PoseChannel has invalid group!");
1071                         return;
1072                 }
1073                 
1074                 /* try to find a group which is similar to the one we want (or add one) */
1075                 for (grp= act->groups.first; grp; grp= grp->next) {
1076                         if (!strcmp(grp->name, agrp->name))
1077                                 break;
1078                 }
1079                 if (grp == NULL) {
1080                         grp= MEM_callocN(sizeof(bActionGroup), "bActionGroup");
1081                         
1082                         grp->flag |= (AGRP_ACTIVE|AGRP_SELECTED|AGRP_EXPANDED);
1083                         sprintf(grp->name, agrp->name);
1084                         
1085                         BLI_addtail(&act->groups, grp);
1086                 }
1087                 
1088                 /* make sure this channel is definitely not connected to anything before adding to group */
1089                 action_groups_removeachan(act, achan);
1090                 action_groups_addachan(act, grp, achan);
1091         }
1092 }
1093
1094 /* **************************************************** */
1095 /* TRANSFORM TOOLS */
1096
1097 /* main call to start transforming keyframes */
1098 void transform_action_keys (int mode, int dummy)
1099 {
1100         void *data;
1101         short datatype;
1102         
1103         /* determine what type of data we are operating on */
1104         data = get_action_context(&datatype);
1105         if (data == NULL) return;
1106         
1107         switch (mode) {
1108                 case 'g':
1109                 {
1110                         initTransform(TFM_TIME_TRANSLATE, CTX_NONE);
1111                         Transform();
1112                 }
1113                         break;
1114                 case 's':
1115                 {
1116                         initTransform(TFM_TIME_SCALE, CTX_NONE);
1117                         Transform();
1118                 }
1119                         break;
1120                 case 't':
1121                 {
1122                         initTransform(TFM_TIME_SLIDE, CTX_NONE);
1123                         Transform();
1124                 }
1125                         break;
1126                 case 'e':
1127                 {
1128                         initTransform(TFM_TIME_EXTEND, CTX_NONE);
1129                         Transform();
1130                 }
1131                 break;
1132         }
1133 }
1134
1135 /* ----------------------------------------- */
1136
1137 /* duplicate keyframes */
1138 void duplicate_action_keys (void)
1139 {
1140         ListBase act_data = {NULL, NULL};
1141         bActListElem *ale;
1142         void *data;
1143         short datatype;
1144         int filter;
1145         
1146         /* determine what type of data we are operating on */
1147         data = get_action_context(&datatype);
1148         if (data == NULL) return;
1149         
1150         /* filter data */
1151         filter= (ACTFILTER_VISIBLE | ACTFILTER_FOREDIT | ACTFILTER_IPOKEYS);
1152         actdata_filter(&act_data, filter, data, datatype);
1153         
1154         /* loop through filtered data and duplicate selected keys */
1155         for (ale= act_data.first; ale; ale= ale->next) {
1156                 duplicate_ipo_keys((Ipo *)ale->key_data);
1157         }
1158         
1159         /* free filtered list */
1160         BLI_freelistN(&act_data);
1161         
1162         /* now, go into transform-grab mode, to move keys */
1163         BIF_TransformSetUndo("Add Duplicate");
1164         transform_action_keys('g', 0);
1165 }
1166
1167 /* this function is responsible for snapping the current frame to selected data  */
1168 void snap_cfra_action() 
1169 {
1170         ListBase act_data = {NULL, NULL};
1171         bActListElem *ale;
1172         int filter;
1173         void *data;
1174         short datatype;
1175                 
1176         /* get data */
1177         data= get_action_context(&datatype);
1178         if (data == NULL) return;
1179         
1180         /* filter data */
1181         filter= (ACTFILTER_VISIBLE | ACTFILTER_IPOKEYS);
1182         actdata_filter(&act_data, filter, data, datatype);
1183         
1184         /* snap current frame to selected data */
1185         snap_cfra_ipo_keys(NULL, -1);
1186         
1187         for (ale= act_data.first; ale; ale= ale->next) {
1188                 if (NLA_ACTION_SCALED && datatype==ACTCONT_ACTION) {
1189                         actstrip_map_ipo_keys(OBACT, ale->key_data, 0, 1); 
1190                         snap_cfra_ipo_keys(ale->key_data, 0);
1191                         actstrip_map_ipo_keys(OBACT, ale->key_data, 1, 1);
1192                 }
1193                 else 
1194                         snap_cfra_ipo_keys(ale->key_data, 0);
1195         }
1196         BLI_freelistN(&act_data);
1197         
1198         snap_cfra_ipo_keys(NULL, 1);
1199         
1200         BIF_undo_push("Snap Current Frame to Keys");
1201         allqueue(REDRAWACTION, 0);
1202         allqueue(REDRAWIPO, 0);
1203         allqueue(REDRAWNLA, 0);
1204 }
1205
1206 /* this function is responsible for snapping keyframes to frame-times */
1207 void snap_action_keys(short mode) 
1208 {
1209         ListBase act_data = {NULL, NULL};
1210         bActListElem *ale;
1211         int filter;
1212         void *data;
1213         short datatype;
1214         char str[32];
1215                 
1216         /* get data */
1217         data= get_action_context(&datatype);
1218         if (data == NULL) return;
1219         
1220         /* determine mode */
1221         switch (mode) {
1222                 case 1:
1223                         strcpy(str, "Snap Keys To Nearest Frame");
1224                         break;
1225                 case 2:
1226                         if (G.saction->flag & SACTION_DRAWTIME)
1227                                 strcpy(str, "Snap Keys To Current Time");
1228                         else
1229                                 strcpy(str, "Snap Keys To Current Frame");
1230                         break;
1231                 case 3:
1232                         strcpy(str, "Snap Keys To Nearest Marker");
1233                         break;
1234                 case 4:
1235                         strcpy(str, "Snap Keys To Nearest Second");
1236                         break;
1237                 default:
1238                         return;
1239         }
1240         
1241         /* filter data */
1242         filter= (ACTFILTER_VISIBLE | ACTFILTER_FOREDIT | ACTFILTER_IPOKEYS);
1243         actdata_filter(&act_data, filter, data, datatype);
1244         
1245         /* snap to frame */
1246         for (ale= act_data.first; ale; ale= ale->next) {
1247                 if (NLA_ACTION_SCALED && datatype==ACTCONT_ACTION) {
1248                         actstrip_map_ipo_keys(OBACT, ale->key_data, 0, 1); 
1249                         snap_ipo_keys(ale->key_data, mode);
1250                         actstrip_map_ipo_keys(OBACT, ale->key_data, 1, 1);
1251                 }
1252                 else 
1253                         snap_ipo_keys(ale->key_data, mode);
1254         }
1255         BLI_freelistN(&act_data);
1256         
1257         if (datatype == ACTCONT_ACTION)
1258                 remake_action_ipos(data);
1259         
1260         BIF_undo_push(str);
1261         allspace(REMAKEIPO, 0);
1262         allqueue(REDRAWACTION, 0);
1263         allqueue(REDRAWIPO, 0);
1264         allqueue(REDRAWNLA, 0);
1265 }
1266
1267 /* this function is responsible for snapping keyframes to frame-times */
1268 void mirror_action_keys(short mode) 
1269 {
1270         ListBase act_data = {NULL, NULL};
1271         bActListElem *ale;
1272         int filter;
1273         void *data;
1274         short datatype;
1275         char str[32];
1276                 
1277         /* get data */
1278         data= get_action_context(&datatype);
1279         if (data == NULL) return;
1280         
1281         /* determine mode */
1282         switch (mode) {
1283                 case 1:
1284                         strcpy(str, "Mirror Keys Over Current Frame");
1285                         break;
1286                 case 2:
1287                         strcpy(str, "Mirror Keys Over Y-Axis");
1288                         break;
1289                 case 3:
1290                         strcpy(str, "Mirror Keys Over X-Axis");
1291                         break;
1292                 case 4:
1293                         strcpy(str, "Mirror Keys Over Marker");
1294                         break;
1295                 default:
1296                         return;
1297         }
1298         
1299         /* filter data */
1300         filter= (ACTFILTER_VISIBLE | ACTFILTER_FOREDIT | ACTFILTER_IPOKEYS);
1301         actdata_filter(&act_data, filter, data, datatype);
1302         
1303         /* mirror */
1304         for (ale= act_data.first; ale; ale= ale->next) {
1305                 if (NLA_ACTION_SCALED && datatype==ACTCONT_ACTION) {
1306                         actstrip_map_ipo_keys(OBACT, ale->key_data, 0, 1); 
1307                         mirror_ipo_keys(ale->key_data, mode);
1308                         actstrip_map_ipo_keys(OBACT, ale->key_data, 1, 1);
1309                 }
1310                 else 
1311                         mirror_ipo_keys(ale->key_data, mode);
1312         }
1313         BLI_freelistN(&act_data);
1314         
1315         if (datatype == ACTCONT_ACTION)
1316                 remake_action_ipos(data);
1317         
1318         BIF_undo_push(str);
1319         allspace(REMAKEIPO, 0);
1320         allqueue(REDRAWACTION, 0);
1321         allqueue(REDRAWIPO, 0);
1322         allqueue(REDRAWNLA, 0);
1323 }
1324
1325 /* **************************************************** */
1326 /* ADD/REMOVE KEYFRAMES */
1327
1328 /* This function allows the user to insert keyframes on the current
1329  * frame from the Action Editor, using the current values of the channels
1330  * to be keyframed.  
1331  */
1332 void insertkey_action(void)
1333 {
1334         void *data;
1335         short datatype;
1336         
1337         Object *ob= OBACT;
1338         short mode;
1339         float cfra;
1340         
1341         /* get data */
1342         data= get_action_context(&datatype);
1343         if (data == NULL) return;
1344         cfra = frame_to_float(CFRA);
1345                 
1346         if (datatype == ACTCONT_ACTION) {
1347                 ListBase act_data = {NULL, NULL};
1348                 bActListElem *ale;
1349                 int filter;
1350                 
1351                 /* ask user what to keyframe */
1352                 mode = pupmenu("Insert Key%t|All Channels%x1|Only Selected Channels%x2");
1353                 if (mode <= 0) return;
1354                 
1355                 /* filter data */
1356                 filter= (ACTFILTER_VISIBLE | ACTFILTER_FOREDIT | ACTFILTER_ONLYICU );
1357                 if (mode == 2) filter |= ACTFILTER_SEL;
1358                 
1359                 actdata_filter(&act_data, filter, data, datatype);
1360                 
1361                 /* loop through ipo curves retrieved */
1362                 for (ale= act_data.first; ale; ale= ale->next) {
1363                         /* verify that this is indeed an ipo curve */
1364                         if (ale->key_data && ale->owner) {
1365                                 bActionChannel *achan= (bActionChannel *)ale->owner;
1366                                 IpoCurve *icu= (IpoCurve *)ale->key_data;
1367                                 
1368                                 if (ob)
1369                                         insertkey((ID *)ob, icu->blocktype, achan->name, NULL, icu->adrcode, 0);
1370                                 else
1371                                         insert_vert_icu(icu, cfra, icu->curval, 0);
1372                         }
1373                 }
1374                 
1375                 /* cleanup */
1376                 BLI_freelistN(&act_data);
1377         }
1378         else if (datatype == ACTCONT_SHAPEKEY) {
1379                 Key *key= (Key *)data;
1380                 IpoCurve *icu;
1381                 
1382                 /* ask user if they want to insert a keyframe */
1383                 mode = okee("Insert Keyframe?");
1384                 if (mode <= 0) return;
1385                 
1386                 if (key->ipo) {
1387                         for (icu= key->ipo->curve.first; icu; icu=icu->next) {
1388                                 insert_vert_icu(icu, cfra, icu->curval, 0);
1389                         }
1390                 }
1391         }
1392         
1393         BIF_undo_push("Insert Key");
1394         allspace(REMAKEIPO, 0);
1395         allqueue(REDRAWACTION, 0);
1396         allqueue(REDRAWIPO, 0);
1397         allqueue(REDRAWNLA, 0);
1398 }
1399
1400 /* delete selected keyframes */
1401 void delete_action_keys (void)
1402 {
1403         ListBase act_data = {NULL, NULL};
1404         bActListElem *ale;
1405         void *data;
1406         short datatype;
1407         int filter;
1408         
1409         /* determine what type of data we are operating on */
1410         data = get_action_context(&datatype);
1411         if (data == NULL) return;
1412         
1413         /* filter data */
1414         filter= (ACTFILTER_VISIBLE | ACTFILTER_FOREDIT | ACTFILTER_IPOKEYS);
1415         actdata_filter(&act_data, filter, data, datatype);
1416         
1417         /* loop through filtered data and delete selected keys */
1418         for (ale= act_data.first; ale; ale= ale->next) {
1419                 delete_ipo_keys((Ipo *)ale->key_data);
1420         }
1421         
1422         /* free filtered list */
1423         BLI_freelistN(&act_data);
1424         
1425         if (datatype == ACTCONT_ACTION)
1426                 remake_action_ipos(data);
1427         
1428         BIF_undo_push("Delete Action Keys");
1429         allspace(REMAKEIPO, 0);
1430         allqueue(REDRAWACTION, 0);
1431         allqueue(REDRAWIPO, 0);
1432         allqueue(REDRAWNLA, 0);
1433 }
1434
1435 /* delete selected action-channels (only achans and conchans are considered) */
1436 void delete_action_channels (void)
1437 {
1438         ListBase act_data = {NULL, NULL};
1439         bActListElem *ale, *next;
1440         bAction *act;
1441         void *data;
1442         short datatype;
1443         int filter;
1444         
1445         /* determine what type of data we are operating on */
1446         data = get_action_context(&datatype);
1447         if (data == NULL) return;
1448         if (datatype != ACTCONT_ACTION) return;
1449         act= (bAction *)data;
1450         
1451         /* deal with groups first */
1452         if (act->groups.first) {
1453                 bActionGroup *agrp, *grp;
1454                 bActionChannel *chan, *nchan;
1455                 
1456                 /* unlink achan's that belonged to this group (and make sure they're not selected if they weren't visible) */
1457                 for (agrp= act->groups.first; agrp; agrp= grp) {
1458                         grp= agrp->next;
1459                         
1460                         /* remove if group is selected */
1461                         if (SEL_AGRP(agrp)) {
1462                                 for (chan= agrp->channels.first; chan && chan->grp==agrp; chan= nchan) {
1463                                         nchan= chan->next;
1464                                         
1465                                         action_groups_removeachan(act, chan);
1466                                         BLI_addtail(&act->chanbase, chan);
1467                                         
1468                                         if (EXPANDED_AGRP(agrp) == 0)
1469                                                 chan->flag &= ~(ACHAN_SELECTED|ACHAN_HILIGHTED);
1470                                 }
1471                                 
1472                                 BLI_freelinkN(&act->groups, agrp);
1473                         }
1474                 }
1475         }
1476         
1477         /* filter data */
1478         filter= (ACTFILTER_VISIBLE | ACTFILTER_FOREDIT | ACTFILTER_CHANNELS | ACTFILTER_SEL);
1479         actdata_filter(&act_data, filter, data, datatype);
1480         
1481         /* remove irrelevant entries */
1482         for (ale= act_data.first; ale; ale= next) {
1483                 next= ale->next;
1484                 
1485                 if (ale->type != ACTTYPE_ACHAN)
1486                         BLI_freelinkN(&act_data, ale);
1487         }
1488         
1489         /* clean up action channels */
1490         for (ale= act_data.first; ale; ale= next) {
1491                 bActionChannel *achan= (bActionChannel *)ale->data;
1492                 bConstraintChannel *conchan, *cnext;
1493                 next= ale->next;
1494                 
1495                 /* release reference to ipo users */
1496                 if (achan->ipo)
1497                         achan->ipo->id.us--;
1498                         
1499                 for (conchan= achan->constraintChannels.first; conchan; conchan=cnext) {
1500                         cnext= conchan->next;
1501                         
1502                         if (conchan->ipo)
1503                                 conchan->ipo->id.us--;
1504                 }
1505                 
1506                 /* free memory */
1507                 BLI_freelistN(&achan->constraintChannels);
1508                 BLI_freelinkN(&act->chanbase, achan);
1509                 BLI_freelinkN(&act_data, ale);
1510         }
1511                 
1512         remake_action_ipos(data);
1513         
1514         BIF_undo_push("Delete Action Channels");
1515         allspace(REMAKEIPO, 0);
1516         allqueue(REDRAWACTION, 0);
1517         allqueue(REDRAWIPO, 0);
1518         allqueue(REDRAWNLA, 0);
1519 }
1520
1521 /* 'Clean' IPO curves - remove any unnecessary keyframes */
1522 void clean_action (void)
1523 {       
1524         ListBase act_data = {NULL, NULL};
1525         bActListElem *ale;
1526         int filter;
1527         void *data;
1528         short datatype, ok;
1529         
1530         /* don't proceed any further if nothing to work on or user refuses */
1531         data= get_action_context(&datatype);
1532         ok= fbutton(&G.scene->toolsettings->clean_thresh, 
1533                                 0.0000001f, 1.0, 0.001, 0.1,
1534                                 "Clean Threshold");
1535         if (!ok) return;
1536         
1537         /* filter data */
1538         filter= (ACTFILTER_VISIBLE | ACTFILTER_FOREDIT | ACTFILTER_SEL | ACTFILTER_ONLYICU);
1539         actdata_filter(&act_data, filter, data, datatype);
1540         
1541         /* loop through filtered data and clean curves */
1542         for (ale= act_data.first; ale; ale= ale->next) {
1543                 clean_ipo_curve((IpoCurve *)ale->key_data);
1544         }
1545         
1546         /* admin and redraws */
1547         BLI_freelistN(&act_data);
1548         
1549         BIF_undo_push("Clean Action");
1550         allqueue(REMAKEIPO, 0);
1551         allqueue(REDRAWIPO, 0);
1552         allqueue(REDRAWACTION, 0);
1553         allqueue(REDRAWNLA, 0);
1554 }
1555
1556
1557 /* little cache for values... */
1558 typedef struct tempFrameValCache {
1559         float frame, val;
1560 } tempFrameValCache;
1561
1562 /* Evaluates the curves between each selected keyframe on each frame, and keys the value  */
1563 void sample_action_keys (void)
1564 {       
1565         ListBase act_data = {NULL, NULL};
1566         bActListElem *ale;
1567         int filter;
1568         void *data;
1569         short datatype;
1570         
1571         /* sanity checks */
1572         data= get_action_context(&datatype);
1573         if (data == NULL) return;
1574         
1575         /* filter data */
1576         filter= (ACTFILTER_VISIBLE | ACTFILTER_FOREDIT | ACTFILTER_ONLYICU);
1577         actdata_filter(&act_data, filter, data, datatype);
1578         
1579         /* loop through filtered data and add keys between selected keyframes on every frame  */
1580         for (ale= act_data.first; ale; ale= ale->next) {
1581                 IpoCurve *icu= (IpoCurve *)ale->key_data;
1582                 BezTriple *bezt, *start=NULL, *end=NULL;
1583                 tempFrameValCache *value_cache, *fp;
1584                 int sfra, range;
1585                 int i, n;
1586                 
1587                 /* find selected keyframes... once pair has been found, add keyframes  */
1588                 for (i=0, bezt=icu->bezt; i < icu->totvert; i++, bezt++) {
1589                         /* check if selected, and which end this is */
1590                         if (BEZSELECTED(bezt)) {
1591                                 if (start) {
1592                                         /* set end */
1593                                         end= bezt;
1594                                         
1595                                         /* cache values then add keyframes using these values, as adding
1596                                          * keyframes while sampling will affect the outcome...
1597                                          */
1598                                         range= (int)( ceil(end->vec[1][0] - start->vec[1][0]) );
1599                                         sfra= (int)( floor(start->vec[1][0]) );
1600                                         
1601                                         if (range) {
1602                                                 value_cache= MEM_callocN(sizeof(tempFrameValCache)*range, "IcuFrameValCache");
1603                                                 
1604                                                 /*      sample values   */
1605                                                 for (n=0, fp=value_cache; n<range && fp; n++, fp++) {
1606                                                         fp->frame= (float)(sfra + n);
1607                                                         fp->val= eval_icu(icu, fp->frame);
1608                                                 }
1609                                                 
1610                                                 /*      add keyframes with these        */
1611                                                 for (n=0, fp=value_cache; n<range && fp; n++, fp++) {
1612                                                         insert_vert_icu(icu, fp->frame, fp->val, 1);
1613                                                 }
1614                                                 
1615                                                 /* free temp cache */
1616                                                 MEM_freeN(value_cache);
1617                                         }
1618                                         
1619                                         /* as we added keyframes, we need to compensate so that bezt is at the right place */
1620                                         bezt = icu->bezt + i + range - 1;
1621                                         i += (range - 1);
1622                                         
1623                                         /* bezt was selected, so it now marks the start of a whole new chain to search */
1624                                         start= bezt;
1625                                         end= NULL;
1626                                 }
1627                                 else {
1628                                         /* just set start keyframe */
1629                                         start= bezt;
1630                                         end= NULL;
1631                                 }
1632                         }
1633                 }
1634                 
1635                 /* recalculate channel's handles? */
1636                 calchandles_ipocurve(icu);
1637         }
1638         
1639         /* admin and redraws */
1640         BLI_freelistN(&act_data);
1641         
1642         BIF_undo_push("Sample Action Keys");
1643         allqueue(REMAKEIPO, 0);
1644         allqueue(REDRAWIPO, 0);
1645         allqueue(REDRAWACTION, 0);
1646         allqueue(REDRAWNLA, 0);
1647 }
1648
1649 /* **************************************************** */
1650 /* COPY/PASTE FOR ACTIONS */
1651 /* - The copy/paste buffer currently stores a set of Action Channels, with temporary
1652  *      IPO-blocks, and also temporary IpoCurves which only contain the selected keyframes.
1653  * - Only pastes between compatable data is possible (i.e. same achan->name, ipo-curve type, etc.)
1654  *      Unless there is only one element in the buffer, names are also tested to check for compatability.
1655  * - All pasted frames are offset by the same amount. This is calculated as the difference in the times of
1656  *      the current frame and the 'first keyframe' (i.e. the earliest one in all channels).
1657  * - The earliest frame is calculated per copy operation.
1658  */
1659
1660 /* globals for copy/paste data (like for other copy/paste buffers) */
1661 ListBase actcopybuf = {NULL, NULL};
1662 static float actcopy_firstframe= 999999999.0f;
1663
1664 /* This function frees any MEM_calloc'ed copy/paste buffer data */
1665 void free_actcopybuf ()
1666 {
1667         bActionChannel *achan, *anext;
1668         bConstraintChannel *conchan, *cnext;
1669         
1670         for (achan= actcopybuf.first; achan; achan= anext) {
1671                 anext= achan->next;
1672                 
1673                 if (achan->ipo) {
1674                         free_ipo(achan->ipo);
1675                         MEM_freeN(achan->ipo);
1676                 }
1677                 
1678                 for (conchan=achan->constraintChannels.first; conchan; conchan=cnext) {
1679                         cnext= conchan->next;
1680                         
1681                         if (conchan->ipo) {
1682                                 free_ipo(conchan->ipo);
1683                                 MEM_freeN(conchan->ipo);
1684                         }
1685                         
1686                         BLI_freelinkN(&achan->constraintChannels, conchan);
1687                 }
1688                 
1689                 BLI_freelinkN(&actcopybuf, achan);
1690         }
1691         
1692         actcopybuf.first= actcopybuf.last= NULL;
1693         actcopy_firstframe= 999999999.0f;
1694 }
1695
1696 /* This function adds data to the copy/paste buffer, freeing existing data first
1697  * Only the selected action channels gets their selected keyframes copied.
1698  */
1699 void copy_actdata ()
1700 {
1701         ListBase act_data = {NULL, NULL};
1702         bActListElem *ale;
1703         int filter;
1704         void *data;
1705         short datatype;
1706         
1707         /* clear buffer first */
1708         free_actcopybuf();
1709         
1710         /* get data */
1711         data= get_action_context(&datatype);
1712         if (data == NULL) return;
1713         
1714         /* filter data */
1715         filter= (ACTFILTER_VISIBLE | ACTFILTER_SEL | ACTFILTER_IPOKEYS);
1716         actdata_filter(&act_data, filter, data, datatype);
1717         
1718         /* assume that each of these is an ipo-block */
1719         for (ale= act_data.first; ale; ale= ale->next) {
1720                 bActionChannel *achan;
1721                 Ipo *ipo= ale->key_data;
1722                 Ipo *ipn;
1723                 IpoCurve *icu, *icn;
1724                 BezTriple *bezt;
1725                 int i;
1726                 
1727                 /* coerce an action-channel out of owner */
1728                 if (ale->ownertype == ACTTYPE_ACHAN) {
1729                         bActionChannel *achanO= ale->owner;
1730                         achan= MEM_callocN(sizeof(bActionChannel), "ActCopyPasteAchan");
1731                         strcpy(achan->name, achanO->name);
1732                 }
1733                 else if (ale->ownertype == ACTTYPE_SHAPEKEY) {
1734                         achan= MEM_callocN(sizeof(bActionChannel), "ActCopyPasteAchan");
1735                         strcpy(achan->name, "#ACP_ShapeKey");
1736                 }
1737                 else
1738                         continue;
1739                 BLI_addtail(&actcopybuf, achan);
1740                 
1741                 /* add constraint channel if needed, then add new ipo-block */
1742                 if (ale->type == ACTTYPE_CONCHAN) {
1743                         bConstraintChannel *conchanO= ale->data;
1744                         bConstraintChannel *conchan;
1745                         
1746                         conchan= MEM_callocN(sizeof(bConstraintChannel), "ActCopyPasteConchan");
1747                         strcpy(conchan->name, conchanO->name);
1748                         BLI_addtail(&achan->constraintChannels, conchan);
1749                         
1750                         conchan->ipo= ipn= MEM_callocN(sizeof(Ipo), "ActCopyPasteIpo");
1751                 }
1752                 else {
1753                         achan->ipo= ipn= MEM_callocN(sizeof(Ipo), "ActCopyPasteIpo");
1754                 }
1755                 ipn->blocktype = ipo->blocktype;
1756                 
1757                 /* now loop through curves, and only copy selected keyframes */
1758                 for (icu= ipo->curve.first; icu; icu= icu->next) {
1759                         /* allocate a new curve */
1760                         icn= MEM_callocN(sizeof(IpoCurve), "ActCopyPasteIcu");
1761                         icn->blocktype = icu->blocktype;
1762                         icn->adrcode = icu->adrcode;
1763                         BLI_addtail(&ipn->curve, icn);
1764                         
1765                         /* find selected BezTriples to add to the buffer (and set first frame) */
1766                         for (i=0, bezt=icu->bezt; i < icu->totvert; i++, bezt++) {
1767                                 if (BEZSELECTED(bezt)) {
1768                                         /* add to buffer ipo-curve */
1769                                         insert_bezt_icu(icn, bezt);
1770                                         
1771                                         /* check if this is the earliest frame encountered so far */
1772                                         if (bezt->vec[1][0] < actcopy_firstframe)
1773                                                 actcopy_firstframe= bezt->vec[1][0];
1774                                 }
1775                         }
1776                 }
1777         }
1778         
1779         /* check if anything ended up in the buffer */
1780         if (ELEM(NULL, actcopybuf.first, actcopybuf.last))
1781                 error("Nothing copied to buffer");
1782         
1783         /* free temp memory */
1784         BLI_freelistN(&act_data);
1785 }
1786
1787 void paste_actdata ()
1788 {
1789         ListBase act_data = {NULL, NULL};
1790         bActListElem *ale;
1791         int filter;
1792         void *data;
1793         short datatype;
1794         
1795         short no_name= 0;
1796         float offset = CFRA - actcopy_firstframe;
1797         
1798         /* check if buffer is empty */
1799         if (ELEM(NULL, actcopybuf.first, actcopybuf.last)) {
1800                 error("No data in buffer to paste");
1801                 return;
1802         }
1803         /* check if single channel in buffer (disregard names if so)  */
1804         if (actcopybuf.first == actcopybuf.last)
1805                 no_name= 1;
1806         
1807         /* get data */
1808         data= get_action_context(&datatype);
1809         if (data == NULL) return;
1810         
1811         /* filter data */
1812         filter= (ACTFILTER_VISIBLE | ACTFILTER_SEL | ACTFILTER_FOREDIT | ACTFILTER_IPOKEYS);
1813         actdata_filter(&act_data, filter, data, datatype);
1814         
1815         /* from selected channels */
1816         for (ale= act_data.first; ale; ale= ale->next) {
1817                 Ipo *ipo_src=NULL, *ipo_dst=ale->key_data;
1818                 bActionChannel *achan;
1819                 IpoCurve *ico, *icu;
1820                 BezTriple *bezt;
1821                 int i;
1822                 
1823                 /* find matching ipo-block */
1824                 for (achan= actcopybuf.first; achan; achan= achan->next) {
1825                         /* try to match data */
1826                         if (ale->ownertype == ACTTYPE_ACHAN) {
1827                                 bActionChannel *achant= ale->owner;
1828                                 
1829                                 /* check if we have a corresponding action channel */
1830                                 if ((no_name) || (strcmp(achan->name, achant->name)==0)) {
1831                                         /* check if this is a constraint channel */
1832                                         if (ale->type == ACTTYPE_CONCHAN) {
1833                                                 bConstraintChannel *conchant= ale->data;
1834                                                 bConstraintChannel *conchan;
1835                                                 
1836                                                 for (conchan=achan->constraintChannels.first; conchan; conchan=conchan->next) {
1837                                                         if (strcmp(conchan->name, conchant->name)==0) {
1838                                                                 ipo_src= conchan->ipo;
1839                                                                 break;
1840                                                         }
1841                                                 }
1842                                                 if (ipo_src) break;
1843                                         }
1844                                         else {
1845                                                 ipo_src= achan->ipo;
1846                                                 break;
1847                                         }
1848                                 }
1849                         }
1850                         else if (ale->ownertype == ACTTYPE_SHAPEKEY) {
1851                                 /* check if this action channel is "#ACP_ShapeKey" */
1852                                 if ((no_name) || (strcmp(achan->name, "#ACP_ShapeKey")==0)) {
1853                                         ipo_src= achan->ipo;
1854                                         break;
1855                                 }
1856                         }       
1857                 }
1858                 
1859                 /* this shouldn't happen, but it might */
1860                 if (ELEM(NULL, ipo_src, ipo_dst))
1861                         continue;
1862                 
1863                 /* loop over curves, pasting keyframes */
1864                 for (icu= ipo_dst->curve.first; icu; icu= icu->next) {
1865                         for (ico= ipo_src->curve.first; ico; ico= ico->next) {
1866                                 /* only paste if compatable blocktype + adrcode */
1867                                 if ((ico->blocktype==icu->blocktype) && (ico->adrcode==icu->adrcode)) {
1868                                         /* just start pasting, with the the first keyframe on the current frame, and so on */
1869                                         for (i=0, bezt=ico->bezt; i < ico->totvert; i++, bezt++) {                                              
1870                                                 /* temporarily apply offset to src beztriple while copying */
1871                                                 bezt->vec[0][0] += offset;
1872                                                 bezt->vec[1][0] += offset;
1873                                                 bezt->vec[2][0] += offset;
1874                                                 
1875                                                 /* insert the keyframe */
1876                                                 insert_bezt_icu(icu, bezt);
1877                                                 
1878                                                 /* un-apply offset from src beztriple after copying */
1879                                                 bezt->vec[0][0] -= offset;
1880                                                 bezt->vec[1][0] -= offset;
1881                                                 bezt->vec[2][0] -= offset;
1882                                         }
1883                                         
1884                                         /* recalculate channel's handles? */
1885                                         calchandles_ipocurve(icu);
1886                                         
1887                                         /* done for this channel */
1888                                         break;
1889                                 }
1890                         }
1891                 }
1892         }
1893         
1894         /* free temp memory */
1895         BLI_freelistN(&act_data);
1896         
1897         /* undo and redraw stuff */
1898         allqueue(REDRAWVIEW3D, 0);
1899         allspace(REMAKEIPO, 0);
1900         allqueue(REDRAWACTION, 0);
1901         allqueue(REDRAWIPO, 0);
1902         allqueue(REDRAWNLA, 0);
1903         BIF_undo_push("Paste Action Keyframes");
1904 }
1905
1906 /* **************************************************** */
1907 /* VARIOUS SETTINGS */
1908
1909 /* This function combines several features related to setting 
1910  * various ipo extrapolation/interpolation
1911  */
1912 void action_set_ipo_flags (short mode, short event)
1913 {
1914         ListBase act_data = {NULL, NULL};
1915         bActListElem *ale;
1916         void *data;
1917         short datatype;
1918         int filter;
1919         
1920         /* determine what type of data we are operating on */
1921         data = get_action_context(&datatype);
1922         if (data == NULL) return;
1923         
1924         /* determine which set of processing we are doing */
1925         switch (mode) {
1926                 case SET_EXTEND_POPUP:
1927                 {
1928                         /* present popup menu for ipo extrapolation type */
1929                         event
1930                                 =  pupmenu("Channel Extending Type %t|"
1931                                                    "Constant %x11|"
1932                                                    "Extrapolation %x12|"
1933                                                    "Cyclic %x13|"
1934                                                    "Cyclic extrapolation %x14");
1935                         if (event < 1) return;
1936                 }
1937                         break;
1938                 case SET_IPO_POPUP:
1939                 {
1940                         /* present popup menu for ipo interpolation type */
1941                         event
1942                                 =  pupmenu("Channel Ipo Type %t|"
1943                                                    "Constant %x1|"
1944                                                    "Linear %x2|"
1945                                                    "Bezier %x3");
1946                         if (event < 1) return;
1947                 }
1948                         break;
1949                         
1950                 case SET_IPO_MENU:      /* called from menus */
1951                 case SET_EXTEND_MENU:
1952                         break;
1953                         
1954                 default: /* weird, unhandled case */
1955                         return;
1956         }
1957         
1958         /* filter data */
1959         filter= (ACTFILTER_VISIBLE | ACTFILTER_SEL | ACTFILTER_FOREDIT | ACTFILTER_IPOKEYS);
1960         actdata_filter(&act_data, filter, data, datatype);
1961         
1962         /* loop through setting flags */
1963         for (ale= act_data.first; ale; ale= ale->next) {
1964                 Ipo *ipo= (Ipo *)ale->key_data; 
1965         
1966                 /* depending on the mode */
1967                 switch (mode) {
1968                         case SET_EXTEND_POPUP: /* extrapolation */
1969                         case SET_EXTEND_MENU:
1970                         {
1971                                 switch (event) {
1972                                         case SET_EXTEND_CONSTANT:
1973                                                 setexprap_ipoloop(ipo, IPO_HORIZ);
1974                                                 break;
1975                                         case SET_EXTEND_EXTRAPOLATION:
1976                                                 setexprap_ipoloop(ipo, IPO_DIR);
1977                                                 break;
1978                                         case SET_EXTEND_CYCLIC:
1979                                                 setexprap_ipoloop(ipo, IPO_CYCL);
1980                                                 break;
1981                                         case SET_EXTEND_CYCLICEXTRAPOLATION:
1982                                                 setexprap_ipoloop(ipo, IPO_CYCLX);
1983                                                 break;
1984                                 }
1985                         }
1986                                 break;
1987                         case SET_IPO_POPUP: /* interpolation */
1988                         case SET_IPO_MENU:
1989                         {
1990                                 setipotype_ipo(ipo, event);
1991                         }
1992                                 break;
1993                 }
1994         }
1995         
1996         /* cleanup */
1997         BLI_freelistN(&act_data);
1998         
1999         if (datatype == ACTCONT_ACTION)
2000                 remake_action_ipos(data);
2001         
2002         BIF_undo_push("Set Ipo Type");
2003         allspace(REMAKEIPO, 0);
2004         allqueue(REDRAWACTION, 0);
2005         allqueue(REDRAWIPO, 0);
2006         allqueue(REDRAWNLA, 0);
2007 }
2008
2009 /* this function sets the handles on keyframes */
2010 void sethandles_action_keys (int code)
2011 {
2012         ListBase act_data = {NULL, NULL};
2013         bActListElem *ale;
2014         void *data;
2015         short datatype;
2016         int filter;
2017         
2018         /* determine what type of data we are operating on */
2019         data = get_action_context(&datatype);
2020         if (data == NULL) return;
2021         
2022         /* filter data */
2023         filter= (ACTFILTER_VISIBLE | ACTFILTER_FOREDIT | ACTFILTER_IPOKEYS);
2024         actdata_filter(&act_data, filter, data, datatype);
2025         
2026         /* loop through setting flags */
2027         for (ale= act_data.first; ale; ale= ale->next) {
2028                 sethandles_ipo_keys((Ipo *)ale->key_data, code);
2029         }
2030         
2031         /* cleanup */
2032         BLI_freelistN(&act_data);
2033         if (datatype == ACTCONT_ACTION)
2034                 remake_action_ipos(data);
2035         
2036         BIF_undo_push("Set Handle Type");
2037         allspace(REMAKEIPO, 0);
2038         allqueue(REDRAWACTION, 0);
2039         allqueue(REDRAWIPO, 0);
2040         allqueue(REDRAWNLA, 0);
2041 }
2042
2043 /* ----------------------------------------- */
2044
2045 /* this gets called when nkey is pressed (no Transform Properties panel yet) */
2046 static void numbuts_action ()
2047 {
2048         void *data;
2049         short datatype;
2050         
2051         void *act_channel;
2052         short chantype;
2053         
2054         bActionGroup *agrp= NULL;
2055         bActionChannel *achan= NULL;
2056         bConstraintChannel *conchan= NULL;
2057         IpoCurve *icu= NULL;
2058         KeyBlock *kb= NULL;
2059         
2060         short mval[2];
2061         
2062         int but=0;
2063     char str[64];
2064         short expand, protect, mute;
2065         float slidermin, slidermax;
2066         
2067         
2068         /* determine what type of data we are operating on */
2069         data = get_action_context(&datatype);
2070         if (data == NULL) return;
2071         
2072         /* figure out what is under cursor */
2073         getmouseco_areawin(mval);
2074         if (mval[0] > NAMEWIDTH) 
2075                 return;
2076         act_channel= get_nearest_act_channel(mval, &chantype);
2077         
2078         /* create items for clever-numbut */
2079         if (chantype == ACTTYPE_ACHAN) {
2080                 /* Action Channel */
2081                 achan= (bActionChannel *)act_channel;
2082                 
2083                 strcpy(str, achan->name);
2084                 protect= (achan->flag & ACHAN_PROTECTED);
2085                 expand = (achan->flag & ACHAN_EXPANDED);
2086                 mute = (achan->ipo)? (achan->ipo->muteipo): 0;
2087                 
2088                 add_numbut(but++, TEX, "ActChan: ", 0, 31, str, "Name of Action Channel");
2089                 add_numbut(but++, TOG|SHO, "Expanded", 0, 24, &expand, "Action Channel is Expanded");
2090                 add_numbut(but++, TOG|SHO, "Muted", 0, 24, &mute, "Channel is Muted");
2091                 add_numbut(but++, TOG|SHO, "Protected", 0, 24, &protect, "Channel is Protected");
2092         }
2093         else if (chantype == ACTTYPE_CONCHAN) {
2094                 /* Constraint Channel */
2095                 conchan= (bConstraintChannel *)act_channel;
2096                 
2097                 strcpy(str, conchan->name);
2098                 protect= (conchan->flag & CONSTRAINT_CHANNEL_PROTECTED);
2099                 mute = (conchan->ipo)? (conchan->ipo->muteipo): 0;
2100                 
2101                 add_numbut(but++, TEX, "ConChan: ", 0, 29, str, "Name of Constraint Channel");
2102                 add_numbut(but++, TOG|SHO, "Muted", 0, 24, &mute, "Channel is Muted");
2103                 add_numbut(but++, TOG|SHO, "Protected", 0, 24, &protect, "Channel is Protected");
2104         }
2105         else if (chantype == ACTTYPE_ICU) {
2106                 /* IPO Curve */
2107                 icu= (IpoCurve *)act_channel;
2108                 
2109                 if (G.saction->pin)
2110                         sprintf(str, getname_ipocurve(icu, NULL));
2111                 else
2112                         sprintf(str, getname_ipocurve(icu, OBACT));
2113                 
2114                 if (IS_EQ(icu->slide_max, icu->slide_min)) {
2115                         if (IS_EQ(icu->ymax, icu->ymin)) {
2116                                 icu->slide_min= -100.0;
2117                                 icu->slide_max= 100.0;
2118                         }
2119                         else {
2120                                 icu->slide_min= icu->ymin;
2121                                 icu->slide_max= icu->ymax;
2122                         }
2123                 }
2124                 slidermin= icu->slide_min;
2125                 slidermax= icu->slide_max;
2126                 
2127                 //protect= (icu->flag & IPO_PROTECT);
2128                 mute = (icu->flag & IPO_MUTE);
2129                 
2130                 add_numbut(but++, NUM|FLO, "Slider Min:", -10000, slidermax, &slidermin, 0);
2131                 add_numbut(but++, NUM|FLO, "Slider Max:", slidermin, 10000, &slidermax, 0);
2132                 add_numbut(but++, TOG|SHO, "Muted", 0, 24, &mute, "Channel is Muted");
2133                 //add_numbut(but++, TOG|SHO, "Protected", 0, 24, &protect, "Channel is Protected");
2134         }
2135         else if (chantype == ACTTYPE_SHAPEKEY) {
2136                 /* Shape Key */
2137                 kb= (KeyBlock *)act_channel;
2138                 
2139                 if (kb->name[0] == '\0') {
2140                         Key *key= (Key *)data;
2141                         int keynum= BLI_findindex(&key->block, kb);
2142                         
2143                         sprintf(str, "Key %d", keynum);
2144                 }
2145                 else
2146                         strcpy(str, kb->name);
2147                 
2148                 if (kb->slidermin >= kb->slidermax) {
2149                         kb->slidermin = 0.0;
2150                         kb->slidermax = 1.0;
2151                 }
2152                 
2153             add_numbut(but++, TEX, "KB: ", 0, 24, str, 
2154                        "Does this really need a tool tip?");
2155                 add_numbut(but++, NUM|FLO, "Slider Min:", 
2156                                    -10000, kb->slidermax, &kb->slidermin, 0);
2157                 add_numbut(but++, NUM|FLO, "Slider Max:", 
2158                                    kb->slidermin, 10000, &kb->slidermax, 0);
2159         }
2160         else if (chantype == ACTTYPE_GROUP) {
2161                 /* Action Group */
2162                 agrp= (bActionGroup *)act_channel;
2163                 
2164                 strcpy(str, agrp->name);
2165                 protect= (agrp->flag & AGRP_PROTECTED);
2166                 expand = (agrp->flag & AGRP_EXPANDED);
2167                 
2168                 add_numbut(but++, TEX, "ActGroup: ", 0, 31, str, "Name of Action Group");
2169                 add_numbut(but++, TOG|SHO, "Expanded", 0, 24, &expand, "Action Group is Expanded");
2170                 add_numbut(but++, TOG|SHO, "Protected", 0, 24, &protect, "Group is Protected");
2171         }
2172         else {
2173                 /* nothing under-cursor */
2174                 return;
2175         }
2176         
2177         /* draw clever-numbut */
2178     if (do_clever_numbuts(str, but, REDRAW)) {
2179                 /* restore settings based on type */
2180                 if (icu) {
2181                         icu->slide_min= slidermin;
2182                         icu->slide_max= slidermax;
2183                         
2184                         //if (protect) icu->flag |= IPO_PROTECT;
2185                         //else icu->flag &= ~IPO_PROTECT;
2186                         if (mute) icu->flag |= IPO_MUTE;
2187                         else icu->flag &= ~IPO_MUTE;
2188                 }
2189                 else if (conchan) {
2190                         strcpy(conchan->name, str);
2191                         
2192                         if (protect) conchan->flag |= CONSTRAINT_CHANNEL_PROTECTED;
2193                         else conchan->flag &= ~CONSTRAINT_CHANNEL_PROTECTED;
2194                         
2195                         if (conchan->ipo)
2196                                 conchan->ipo->muteipo = mute;
2197                 }
2198                 else if (achan) {
2199                         strcpy(achan->name, str);
2200                         
2201                         if (expand) achan->flag |= ACHAN_EXPANDED;
2202                         else achan->flag &= ~ACHAN_EXPANDED;
2203                         
2204                         if (protect) achan->flag |= ACHAN_PROTECTED;
2205                         else achan->flag &= ~ACHAN_PROTECTED;
2206                         
2207                         if (achan->ipo)
2208                                 achan->ipo->muteipo = mute;
2209                 }
2210                 else if (agrp) {
2211                         strcpy(agrp->name, str);
2212                         BLI_uniquename(&( ((bAction *)data)->groups ), agrp, "Group", offsetof(bActionGroup, name), 32);
2213                         
2214                         if (expand) agrp->flag |= AGRP_EXPANDED;
2215                         else agrp->flag &= ~AGRP_EXPANDED;
2216                         
2217                         if (protect) agrp->flag |= AGRP_PROTECTED;
2218                         else agrp->flag &= ~AGRP_PROTECTED;
2219                 }
2220                 
2221         allqueue(REDRAWACTION, 0);
2222                 allspace(REMAKEIPO, 0);
2223                 allqueue(REDRAWIPO, 0);
2224                 allqueue(REDRAWVIEW3D, 0);
2225         }
2226 }
2227
2228
2229
2230 /* **************************************************** */
2231 /* CHANNEL SELECTION */
2232
2233 /* select_mode = SELECT_REPLACE
2234  *             = SELECT_ADD
2235  *             = SELECT_SUBTRACT
2236  *             = SELECT_INVERT
2237  */
2238 static void select_action_group (bAction *act, bActionGroup *agrp, int selectmode) 
2239 {
2240         /* Select the channel based on the selection mode */
2241         short select;
2242
2243         switch (selectmode) {
2244         case SELECT_ADD:
2245                 agrp->flag |= AGRP_SELECTED;
2246                 break;
2247         case SELECT_SUBTRACT:
2248                 agrp->flag &= ~AGRP_SELECTED;
2249                 break;
2250         case SELECT_INVERT:
2251                 agrp->flag ^= AGRP_SELECTED;
2252                 break;
2253         }
2254         select = (agrp->flag & AGRP_SELECTED) ? 1 : 0;
2255
2256         set_active_actiongroup(act, agrp, select);
2257 }
2258
2259 static void hilight_channel(bAction *act, bActionChannel *achan, short select)
2260 {
2261         bActionChannel *curchan;
2262
2263         if (!act)
2264                 return;
2265
2266         for (curchan=act->chanbase.first; curchan; curchan=curchan->next) {
2267                 if (curchan==achan && select)
2268                         curchan->flag |= ACHAN_HILIGHTED;
2269                 else
2270                         curchan->flag &= ~ACHAN_HILIGHTED;
2271         }
2272 }
2273
2274 /* messy call... */
2275 static void select_poseelement_by_name(char *name, int select)
2276 {
2277         /* Syncs selection of channels with selection of object elements in posemode */
2278         Object *ob= OBACT;
2279         bPoseChannel *pchan;
2280         
2281         if (!ob || ob->type!=OB_ARMATURE)
2282                 return;
2283         
2284         if(select==2) {
2285                 for(pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next)
2286                         pchan->bone->flag &= ~(BONE_ACTIVE);
2287         }
2288         
2289         pchan= get_pose_channel(ob->pose, name);
2290         if(pchan) {
2291                 if(select)
2292                         pchan->bone->flag |= (BONE_SELECTED);
2293                 else 
2294                         pchan->bone->flag &= ~(BONE_SELECTED);
2295                 if(select==2)
2296                         pchan->bone->flag |= (BONE_ACTIVE);
2297         }
2298 }
2299
2300 /* apparently within active object context */
2301 /* called extern, like on bone selection */
2302 void select_actionchannel_by_name (bAction *act, char *name, int select)
2303 {
2304         bActionChannel *achan;
2305
2306         if (!act)
2307                 return;
2308
2309         for (achan = act->chanbase.first; achan; achan= achan->next) {
2310                 if (!strcmp(achan->name, name)) {
2311                         if (select) {
2312                                 achan->flag |= ACHAN_SELECTED;
2313                                 hilight_channel(act, achan, 1);
2314                         }
2315                         else {
2316                                 achan->flag &= ~ACHAN_SELECTED;
2317                                 hilight_channel(act, achan, 0);
2318                         }
2319                         return;
2320                 }
2321         }
2322 }
2323
2324 /* select_mode = SELECT_REPLACE
2325  *             = SELECT_ADD
2326  *             = SELECT_SUBTRACT
2327  *             = SELECT_INVERT
2328  */
2329
2330 /* exported for outliner (ton) */
2331 /* apparently within active object context */
2332 int select_channel(bAction *act, bActionChannel *achan, int selectmode) 
2333 {
2334         /* Select the channel based on the selection mode */
2335         int flag;
2336
2337         switch (selectmode) {
2338         case SELECT_ADD:
2339                 achan->flag |= ACHAN_SELECTED;
2340                 break;
2341         case SELECT_SUBTRACT:
2342                 achan->flag &= ~ACHAN_SELECTED;
2343                 break;
2344         case SELECT_INVERT:
2345                 achan->flag ^= ACHAN_SELECTED;
2346                 break;
2347         }
2348         flag = (achan->flag & ACHAN_SELECTED) ? 1 : 0;
2349
2350         hilight_channel(act, achan, flag);
2351         select_poseelement_by_name(achan->name, flag);
2352
2353         return flag;
2354 }
2355
2356 static int select_constraint_channel(bAction *act, 
2357                                      bConstraintChannel *conchan, 
2358                                      int selectmode) 
2359 {
2360         /* Select the constraint channel based on the selection mode */
2361         int flag;
2362
2363         switch (selectmode) {
2364         case SELECT_ADD:
2365                 conchan->flag |= CONSTRAINT_CHANNEL_SELECT;
2366                 break;
2367         case SELECT_SUBTRACT:
2368                 conchan->flag &= ~CONSTRAINT_CHANNEL_SELECT;
2369                 break;
2370         case SELECT_INVERT:
2371                 conchan->flag ^= CONSTRAINT_CHANNEL_SELECT;
2372                 break;
2373         }
2374         flag = (conchan->flag & CONSTRAINT_CHANNEL_SELECT) ? 1 : 0;
2375
2376         return flag;
2377 }
2378
2379 int select_icu_channel(bAction *act, IpoCurve *icu, int selectmode) 
2380 {
2381         /* Select the channel based on the selection mode */
2382         int flag;
2383
2384         switch (selectmode) {
2385         case SELECT_ADD:
2386                 icu->flag |= IPO_SELECT;
2387                 break;
2388         case SELECT_SUBTRACT:
2389                 icu->flag &= ~IPO_SELECT;
2390                 break;
2391         case SELECT_INVERT:
2392                 icu->flag ^= IPO_SELECT;
2393                 break;
2394         }
2395         flag = (icu->flag & IPO_SELECT) ? 1 : 0;
2396         return flag;
2397 }
2398
2399 /* ----------------------------------------- */
2400
2401 /* deselects action channels in given action */
2402 void deselect_actionchannels (bAction *act, short test)
2403 {
2404         ListBase act_data = {NULL, NULL};
2405         bActListElem *ale;
2406         int filter, sel=1;
2407         
2408         /* filter data */
2409         filter= ACTFILTER_VISIBLE;
2410         actdata_filter(&act_data, filter, act, ACTCONT_ACTION);
2411         
2412         /* See if we should be selecting or deselecting */
2413         if (test) {
2414                 for (ale= act_data.first; ale; ale= ale->next) {
2415                         if (sel == 0) 
2416                                 break;
2417                         
2418                         switch (ale->type) {
2419                                 case ACTTYPE_GROUP:
2420                                         if (ale->flag & AGRP_SELECTED)
2421                                                 sel= 0;
2422                                         break;
2423                                 case ACTTYPE_ACHAN:
2424                                         if (ale->flag & ACHAN_SELECTED) 
2425                                                 sel= 0;
2426                                         break;
2427                                 case ACTTYPE_CONCHAN:
2428                                         if (ale->flag & CONSTRAINT_CHANNEL_SELECT) 
2429                                                 sel=0;
2430                                         break;
2431                                 case ACTTYPE_ICU:
2432                                         if (ale->flag & IPO_SELECT)
2433                                                 sel=0;
2434                                         break;
2435                         }
2436                 }
2437         }
2438         else
2439                 sel= 0;
2440                 
2441         /* Now set the flags */
2442         for (ale= act_data.first; ale; ale= ale->next) {
2443                 switch (ale->type) {
2444                         case ACTTYPE_GROUP:
2445                         {
2446                                 bActionGroup *agrp= (bActionGroup *)ale->data;
2447                                 
2448                                 if (sel)
2449                                         agrp->flag |= AGRP_SELECTED;
2450                                 else
2451                                         agrp->flag &= ~AGRP_SELECTED;
2452                         }
2453                                 break;
2454                         case ACTTYPE_ACHAN:
2455                         {
2456                                 bActionChannel *achan= (bActionChannel *)ale->data;
2457                                 
2458                                 if (sel)
2459                                         achan->flag |= ACHAN_SELECTED;
2460                                 else
2461                                         achan->flag &= ~ACHAN_SELECTED;
2462                                 select_poseelement_by_name(achan->name, sel);
2463                         }
2464                                 break;
2465                         case ACTTYPE_CONCHAN:
2466                         {
2467                                 bConstraintChannel *conchan= (bConstraintChannel *)ale->data;
2468                                 
2469                                 if (sel)
2470                                         conchan->flag |= CONSTRAINT_CHANNEL_SELECT;
2471                                 else
2472                                         conchan->flag &= ~CONSTRAINT_CHANNEL_SELECT;
2473                         }
2474                                 break;
2475                         case ACTTYPE_ICU:
2476                         {
2477                                 IpoCurve *icu= (IpoCurve *)ale->data;
2478                                 
2479                                 if (sel)
2480                                         icu->flag |= IPO_SELECT;
2481                                 else
2482                                         icu->flag &= ~IPO_SELECT;
2483                         }
2484                                 break;
2485                 }
2486         }
2487         
2488         /* Cleanup */
2489         BLI_freelistN(&act_data);
2490 }
2491
2492 /* deselects channels in the action editor */
2493 void deselect_action_channels (short test)
2494 {
2495         void *data;
2496         short datatype;
2497         
2498         /* determine what type of data we are operating on */
2499         data = get_action_context(&datatype);
2500         if (data == NULL) return;
2501         
2502         /* based on type */
2503         if (datatype == ACTCONT_ACTION)
2504                 deselect_actionchannels(data, test);
2505         // should shapekey channels be allowed to do this? 
2506 }
2507
2508 /* deselects keyframes in the action editor */
2509 void deselect_action_keys (short test, short sel)
2510 {
2511         ListBase act_data = {NULL, NULL};
2512         bActListElem *ale;
2513         int filter;
2514         void *data;
2515         short datatype;
2516         
2517         /* determine what type of data we are operating on */
2518         data = get_action_context(&datatype);
2519         if (data == NULL) return;
2520                 
2521         /* filter data */
2522         filter= (ACTFILTER_VISIBLE | ACTFILTER_IPOKEYS);
2523         actdata_filter(&act_data, filter, data, datatype);
2524         
2525         /* See if we should be selecting or deselecting */
2526         if (test) {
2527                 for (ale= act_data.first; ale; ale= ale->next) {
2528                         if (is_ipo_key_selected(ale->key_data)) {
2529                                 sel= 0;
2530                                 break;
2531                         }
2532                 }
2533         }
2534                 
2535         /* Now set the flags */
2536         for (ale= act_data.first; ale; ale= ale->next) {
2537                 set_ipo_key_selection(ale->key_data, sel);
2538         }
2539         
2540         /* Cleanup */
2541         BLI_freelistN(&act_data);
2542 }
2543
2544 /* selects all keyframes in the action editor - per channel or time 
2545  *      mode = 0: all in channel; mode = 1: all in frame
2546  */
2547 void selectall_action_keys (short mval[], short mode, short select_mode)
2548 {
2549         void *data;
2550         short datatype;
2551         
2552         /* determine what type of data we are operating on */
2553         data = get_action_context(&datatype);
2554         if (data == NULL) return;
2555                 
2556         if (select_mode == SELECT_REPLACE) {
2557                 deselect_action_keys(0, 0);
2558                 select_mode = SELECT_ADD;
2559         }
2560                 
2561         /* depending on mode */
2562         switch (mode) {
2563                 case 0: /* all in channel*/
2564                 {
2565                         void *act_channel;
2566                         short chantype;
2567                         
2568                         /* get channel, and act according to type */
2569                         act_channel= get_nearest_act_channel(mval, &chantype);
2570                         switch (chantype) {
2571                                 case ACTTYPE_GROUP:     
2572                                 {
2573                                         bActionGroup *agrp= (bActionGroup *)act_channel;
2574                                         bActionChannel *achan;
2575                                         bConstraintChannel *conchan;
2576                                         
2577                                         for (achan= agrp->channels.first; achan && achan->grp==agrp; achan= achan->next) {
2578                                                 select_ipo_bezier_keys(achan->ipo, select_mode);
2579                                                 
2580                                                 for (conchan=achan->constraintChannels.first; conchan; conchan=conchan->next) 
2581                                                         select_ipo_bezier_keys(conchan->ipo, select_mode);
2582                                         }
2583                                 }
2584                                         break;
2585                                 case ACTTYPE_ACHAN:
2586                                 {
2587                                         bActionChannel *achan= (bActionChannel *)act_channel;
2588                                         select_ipo_bezier_keys(achan->ipo, select_mode);
2589                                 }
2590                                         break;
2591                                 case ACTTYPE_CONCHAN:
2592                                 {
2593                                         bConstraintChannel *conchan= (bConstraintChannel *)act_channel;
2594                                         select_ipo_bezier_keys(conchan->ipo, select_mode);
2595                                 }
2596                                         break;
2597                                 case ACTTYPE_ICU:
2598                                 {
2599                                         IpoCurve *icu= (IpoCurve *)act_channel;
2600                                         select_icu_bezier_keys(icu, select_mode);
2601                                 }
2602                                         break;
2603                         }
2604                 }
2605                         break;
2606                 case 1: /* all in frame */
2607                 {
2608                         ListBase act_data = {NULL, NULL};
2609                         bActListElem *ale;
2610                         int filter;
2611                         rcti rect;
2612                         rctf rectf;
2613                         
2614                         /* use bounding box to find kframe */
2615                         rect.xmin = rect.xmax = mval[0];
2616                         rect.ymin = rect.ymax = mval[1];
2617                         
2618                         mval[0]= rect.xmin;
2619                         mval[1]= rect.ymin+2;
2620                         areamouseco_to_ipoco(G.v2d, mval, &rectf.xmin, &rectf.ymin);
2621                         rectf.xmax= rectf.xmin;
2622                         rectf.ymax= rectf.ymin;
2623                         
2624                         rectf.xmin = rectf.xmin - 0.5;
2625                         rectf.xmax = rectf.xmax + 0.5;
2626                         
2627                         /* filter data */
2628                         filter= (ACTFILTER_VISIBLE | ACTFILTER_IPOKEYS);
2629                         actdata_filter(&act_data, filter, data, datatype);
2630                                 
2631                         /* Now set the flags */
2632                         for (ale= act_data.first; ale; ale= ale->next)
2633                                 borderselect_ipo_key(ale->key_data, rectf.xmin, rectf.xmax, select_mode);
2634                         
2635                         /* Cleanup */
2636                         BLI_freelistN(&act_data);
2637                 }
2638                 break;
2639         }
2640         
2641         allqueue(REDRAWNLA, 0);
2642         allqueue(REDRAWACTION, 0);
2643         allqueue(REDRAWIPO, 0);
2644 }
2645
2646 /* Selects all visible keyframes between the specified markers */
2647 void markers_selectkeys_between (void)
2648 {
2649         ListBase act_data = {NULL, NULL};
2650         bActListElem *ale;
2651         int filter;
2652         void *data;
2653         short datatype;
2654         float min, max;
2655         
2656         /* determine what type of data we are operating on */
2657         data = get_action_context(&datatype);
2658         if (data == NULL) return;
2659         
2660         /* get extreme markers */
2661         get_minmax_markers(1, &min, &max);
2662         if (min==max) return;
2663         min -= 0.5f;
2664         max += 0.5f;
2665         
2666         /* filter data */
2667         filter= (ACTFILTER_VISIBLE | ACTFILTER_IPOKEYS);
2668         actdata_filter(&act_data, filter, data, datatype);
2669                 
2670         /* select keys in-between */
2671         for (ale= act_data.first; ale; ale= ale->next) {
2672                 if(NLA_ACTION_SCALED && datatype==ACTCONT_ACTION) {
2673                         actstrip_map_ipo_keys(OBACT, ale->key_data, 0, 1);
2674                         borderselect_ipo_key(ale->key_data, min, max, SELECT_ADD);
2675                         actstrip_map_ipo_keys(OBACT, ale->key_data, 1, 1);
2676                 }
2677                 else {
2678                         borderselect_ipo_key(ale->key_data, min, max, SELECT_ADD);
2679                 }
2680         }
2681         
2682         /* Cleanup */
2683         BLI_freelistN(&act_data);
2684 }
2685
2686 /* Selects all the keyframes on either side of the current frame (depends on which side the mouse is on) */
2687 void selectkeys_leftright (short leftright, short select_mode)
2688 {
2689         ListBase act_data = {NULL, NULL};
2690         bActListElem *ale;
2691         int filter;
2692         void *data;
2693         short datatype;
2694         float min, max;
2695         
2696         if (select_mode==SELECT_REPLACE) {
2697                 select_mode=SELECT_ADD;
2698                 deselect_action_keys(0, 0);
2699         }
2700         
2701         /* determine what type of data we are operating on */
2702         data = get_action_context(&datatype);
2703         if (data == NULL) return;
2704         
2705         if (leftright == 1) {
2706                 min = -MAXFRAMEF;
2707                 max = (float)(CFRA + 0.1f);
2708         } 
2709         else {
2710                 min = (float)(CFRA - 0.1f);
2711                 max = MAXFRAMEF;
2712         }
2713         
2714         /* filter data */
2715         filter= (ACTFILTER_VISIBLE | ACTFILTER_IPOKEYS);
2716         actdata_filter(&act_data, filter, data, datatype);
2717                 
2718         /* select keys on the side where most data occurs */
2719         for (ale= act_data.first; ale; ale= ale->next) {
2720                 if(NLA_ACTION_SCALED && datatype==ACTCONT_ACTION) {
2721                         actstrip_map_ipo_keys(OBACT, ale->key_data, 0, 1);
2722                         borderselect_ipo_key(ale->key_data, min, max, SELECT_ADD);
2723                         actstrip_map_ipo_keys(OBACT, ale->key_data, 1, 1);
2724                 }
2725                 else {
2726                         borderselect_ipo_key(ale->key_data, min, max, SELECT_ADD);
2727                 }
2728         }
2729         
2730         /* Cleanup */
2731         BLI_freelistN(&act_data);
2732         
2733         allqueue(REDRAWNLA, 0);
2734         allqueue(REDRAWACTION, 0);
2735         allqueue(REDRAWIPO, 0);
2736 }
2737
2738 /* ----------------------------------------- */
2739
2740 /* Jumps to the frame where the next/previous keyframe (that is visible) occurs 
2741  *      dir: indicates direction
2742  */
2743 void nextprev_action_keyframe (short dir)
2744 {
2745         ListBase act_data = {NULL, NULL};
2746         bActListElem *ale;
2747         int filter;
2748         void *data;
2749         short datatype;
2750         
2751         ListBase elems= {NULL, NULL};
2752         CfraElem *ce, *nearest=NULL;
2753         float dist, min_dist= 1000000;
2754         
2755         
2756         /* determine what type of data we are operating on */
2757         data = get_action_context(&datatype);
2758         if (data == NULL) return;
2759         
2760         /* abort if no direction */
2761         if (dir == 0)
2762                 return;
2763         
2764         /* get list of keyframes that can be used (in global-time) */
2765         filter= (ACTFILTER_VISIBLE | ACTFILTER_IPOKEYS);
2766         actdata_filter(&act_data, filter, data, datatype);
2767         
2768         for (ale= act_data.first; ale; ale= ale->next) {
2769                 if (NLA_ACTION_SCALED && datatype==ACTCONT_ACTION) {
2770                         actstrip_map_ipo_keys(OBACT, ale->key_data, 0, 1); 
2771                         make_cfra_list(ale->key_data, &elems);
2772                         actstrip_map_ipo_keys(OBACT, ale->key_data, 1, 1);
2773                 }
2774                 else 
2775                         make_cfra_list(ale->key_data, &elems);
2776         }
2777         
2778         BLI_freelistN(&act_data);
2779         
2780         /* find nearest keyframe to current frame */
2781         for (ce= elems.first; ce; ce= ce->next) {
2782                 dist= ABS(ce->cfra - CFRA);
2783                 
2784                 if (dist < min_dist) {
2785                         min_dist= dist;
2786                         nearest= ce;
2787                 }
2788         }
2789         
2790         /* if a nearest keyframe was found, use the one either side */
2791         if (nearest) {
2792                 short changed= 0;
2793                 
2794                 if ((dir > 0) && (nearest->next)) {
2795                         CFRA= nearest->next->cfra;
2796                         changed= 1;
2797                 }
2798                 else if ((dir < 0) && (nearest->prev)) {
2799                         CFRA= nearest->prev->cfra;
2800                         changed= 1;
2801                 }
2802                         
2803                 if (changed) {  
2804                         update_for_newframe();  
2805                         allqueue(REDRAWALL, 0);
2806                 }
2807         }
2808         
2809         /* free temp data */
2810         BLI_freelistN(&elems);
2811 }
2812
2813 /* ----------------------------------------- */
2814
2815 /* This function makes a list of the selected keyframes
2816  * in the ipo curves it has been passed
2817  */
2818 static void make_sel_cfra_list (Ipo *ipo, ListBase *elems)
2819 {
2820         IpoCurve *icu;
2821         
2822         if (ipo == NULL) return;
2823         
2824         for (icu= ipo->curve.first; icu; icu= icu->next) {
2825                 BezTriple *bezt;
2826                 int a= 0;
2827                 
2828                 for (bezt=icu->bezt; a<icu->totvert; a++, bezt++) {
2829                         if (bezt && BEZSELECTED(bezt))
2830                                 add_to_cfra_elem(elems, bezt);
2831                 }
2832         }
2833 }
2834
2835 /* This function selects all key frames in the same column(s) as a already selected key(s)
2836  * or marker(s), or all the keyframes on a particular frame (triggered by a RMB on x-scrollbar)
2837  */
2838 void column_select_action_keys (int mode)
2839 {
2840         ListBase elems= {NULL, NULL};
2841         CfraElem *ce;
2842         IpoCurve *icu;
2843         ListBase act_data = {NULL, NULL};
2844         bActListElem *ale;
2845         int filter;
2846         void *data;
2847         short datatype;
2848         
2849         /* determine what type of data we are operating on */
2850         data = get_action_context(&datatype);
2851         if (data == NULL) return;
2852         
2853         /* build list of columns */
2854         switch (mode) {
2855                 case 1: /* list of selected keys */
2856                         filter= (ACTFILTER_VISIBLE | ACTFILTER_IPOKEYS);
2857                         actdata_filter(&act_data, filter, data, datatype);
2858                         
2859                         for (ale= act_data.first; ale; ale= ale->next)
2860                                 make_sel_cfra_list(ale->key_data, &elems);
2861                         
2862                         BLI_freelistN(&act_data);
2863                         break;
2864                 case 2: /* list of selected markers */
2865                         make_marker_cfra_list(&elems, 1);
2866                         
2867                         /* apply scaled action correction if needed */
2868                         if (NLA_ACTION_SCALED && datatype==ACTCONT_ACTION) {
2869                                 for (ce= elems.first; ce; ce= ce->next) 
2870                                         ce->cfra= get_action_frame(OBACT, ce->cfra);
2871                         }
2872                         break;
2873         }
2874         
2875         /* loop through all of the keys and select additional keyframes
2876          * based on the keys found to be selected above
2877          */
2878         filter= (ACTFILTER_VISIBLE | ACTFILTER_ONLYICU);
2879         actdata_filter(&act_data, filter, data, datatype);
2880         
2881         for (ale= act_data.first; ale; ale= ale->next) {
2882                 for (ce= elems.first; ce; ce= ce->next) {
2883                         for (icu= ale->key_data; icu; icu= icu->next) {
2884                                 BezTriple *bezt;
2885                                 int verts = 0;
2886                                 
2887                                 for (bezt=icu->bezt; verts<icu->totvert; bezt++, verts++) {
2888                                         if (bezt) {
2889                                                 if( (int)(ce->cfra) == (int)(bezt->vec[1][0]) )
2890                                                         bezt->f2 |= 1;
2891                                         }
2892                                 }
2893                         }
2894                 }
2895         }
2896         
2897         BLI_freelistN(&act_data);
2898         BLI_freelistN(&elems);
2899 }
2900
2901
2902 /* some quick defines for borderselect modes */
2903 enum {
2904         ACTEDIT_BORDERSEL_ALL = 0,
2905         ACTEDIT_BORDERSEL_FRA,
2906         ACTEDIT_BORDERSEL_CHA
2907 };
2908
2909 /* borderselect: for keyframes only */
2910 void borderselect_action (void)
2911 {
2912         ListBase act_data = {NULL, NULL};
2913         bActListElem *ale;
2914         int filter;
2915         void *data;
2916         short datatype;
2917         
2918         rcti rect;
2919         rctf rectf;
2920         int val, selectmode, mode;
2921         int (*select_function)(BezTriple *);
2922         short mval[2];
2923         float ymin, ymax;
2924         
2925         /* determine what type of data we are operating on */
2926         data = get_action_context(&datatype);
2927         if (data == NULL) return;
2928         
2929         /* what should be selected (based on the starting location of cursor) */
2930         getmouseco_areawin(mval);
2931         if (IN_2D_VERT_SCROLL(mval)) 
2932                 mode = ACTEDIT_BORDERSEL_CHA;
2933         else if (IN_2D_HORIZ_SCROLL(mval))
2934                 mode = ACTEDIT_BORDERSEL_FRA;
2935         else
2936                 mode = ACTEDIT_BORDERSEL_ALL;
2937         
2938         /* draw and handle the borderselect stuff (ui) and get the select rect */
2939         if ( (val = get_border(&rect, 3)) ) {
2940                 if (val == LEFTMOUSE) {
2941                         selectmode = SELECT_ADD;
2942                         select_function = select_bezier_add;
2943                 }
2944                 else {
2945                         selectmode = SELECT_SUBTRACT;
2946                         select_function = select_bezier_subtract;
2947                 }
2948                 
2949                 mval[0]= rect.xmin;
2950                 mval[1]= rect.ymin+2;
2951                 areamouseco_to_ipoco(G.v2d, mval, &rectf.xmin, &rectf.ymin);
2952                 mval[0]= rect.xmax;
2953                 mval[1]= rect.ymax-2;
2954                 areamouseco_to_ipoco(G.v2d, mval, &rectf.xmax, &rectf.ymax);
2955                 
2956                 /* if action is mapped in NLA, it returns a correction */
2957                 if (NLA_ACTION_SCALED && datatype==ACTCONT_ACTION) {
2958                         rectf.xmin= get_action_frame(OBACT, rectf.xmin);
2959                         rectf.xmax= get_action_frame(OBACT, rectf.xmax);
2960                 }
2961                 
2962                 ymax = CHANNELHEIGHT/2;
2963                 
2964                 /* filter data */
2965                 filter= (ACTFILTER_VISIBLE | ACTFILTER_CHANNELS);
2966                 actdata_filter(&act_data, filter, data, datatype);
2967                 
2968                 /* loop over data, doing border select */
2969                 for (ale= act_data.first; ale; ale= ale->next) {
2970                         ymin=ymax-(CHANNELHEIGHT+CHANNELSKIP);
2971                         
2972                         /* what gets selected depends on the mode (based on initial position of cursor) */
2973                         switch (mode) {
2974                         case ACTEDIT_BORDERSEL_FRA: /* all in frame(s) */
2975                                 if (ale->key_data) {
2976                                         if (ale->datatype == ALE_IPO)
2977                                                 borderselect_ipo_key(ale->key_data, rectf.xmin, rectf.xmax, selectmode);
2978                                         else if (ale->datatype == ALE_ICU)
2979                                                 borderselect_icu_key(ale->key_data, rectf.xmin, rectf.xmax, select_function);
2980                                 }
2981                                 else if (ale->type == ACTTYPE_GROUP) {
2982                                         bActionGroup *agrp= ale->data;
2983                                         bActionChannel *achan;
2984                                         bConstraintChannel *conchan;
2985                                         
2986                                         for (achan= agrp->channels.first; achan && achan->grp==agrp; achan= achan->next) {
2987                                                 borderselect_ipo_key(achan->ipo, rectf.xmin, rectf.xmax, selectmode);
2988                                                 
2989                                                 for (conchan=achan->constraintChannels.first; conchan; conchan=conchan->next)
2990                                                         borderselect_ipo_key(conchan->ipo, rectf.xmin, rectf.xmax, selectmode);
2991                                         }
2992                                 }
2993                                 break;
2994                         case ACTEDIT_BORDERSEL_CHA: /* all in channel(s) */
2995                                 if (!((ymax < rectf.ymin) || (ymin > rectf.ymax))) {
2996                                         if (ale->key_data) {
2997                                                 if (ale->datatype == ALE_IPO)
2998                                                         select_ipo_bezier_keys(ale->key_data, selectmode);
2999                                                 else if (ale->datatype == ALE_ICU)
3000                                                         select_icu_bezier_keys(ale->key_data, selectmode);
3001                                         }
3002                                         else if (ale->type == ACTTYPE_GROUP) {
3003                                                 bActionGroup *agrp= ale->data;
3004                                                 bActionChannel *achan;
3005                                                 bConstraintChannel *conchan;
3006                                                 
3007                                                 for (achan= agrp->channels.first; achan && achan->grp==agrp; achan= achan->next) {
3008                                                         select_ipo_bezier_keys(achan->ipo, selectmode);
3009                                                         
3010                                                         for (conchan=achan->constraintChannels.first; conchan; conchan=conchan->next)
3011                                                                 select_ipo_bezier_keys(conchan->ipo, selectmode);
3012                                                 }
3013                                         }
3014                                 }
3015                                 break;
3016                         default: /* any keyframe inside region defined by region */
3017                                 if (!((ymax < rectf.ymin) || (ymin > rectf.ymax))) {
3018                                         if (ale->key_data) {
3019                                                 if (ale->datatype == ALE_IPO)
3020                                                         borderselect_ipo_key(ale->key_data, rectf.xmin, rectf.xmax, selectmode);
3021                                                 else if (ale->datatype == ALE_ICU)
3022                                                         borderselect_icu_key(ale->key_data, rectf.xmin, rectf.xmax, select_function);
3023                                         }
3024                                         else if (ale->type == ACTTYPE_GROUP) {
3025                                                 bActionGroup *agrp= ale->data;
3026                                                 bActionChannel *achan;
3027                                                 bConstraintChannel *conchan;
3028                                                 
3029                                                 for (achan= agrp->channels.first; achan && achan->grp==agrp; achan= achan->next) {
3030                                                         borderselect_ipo_key(achan->ipo, rectf.xmin, rectf.xmax, selectmode);
3031                                                         
3032                                                         for (conchan=achan->constraintChannels.first; conchan; conchan=conchan->next)
3033                                                                 borderselect_ipo_key(conchan->ipo, rectf.xmin, rectf.xmax, selectmode);
3034                                                 }
3035                                         }
3036                                 }
3037                         }
3038                         
3039                         ymax=ymin;
3040                 }
3041                 
3042                 /* cleanup */
3043                 BLI_freelistN(&act_data);
3044                 
3045                 BIF_undo_push("Border Select Action");
3046                 allqueue(REDRAWIPO, 0);
3047                 allqueue(REDRAWACTION, 0);
3048                 allqueue(REDRAWNLA, 0);
3049         }
3050 }
3051
3052 /* **************************************************** */
3053 /* MOUSE-HANDLING */
3054
3055 /* right-hand side - mouse click */
3056 static void mouse_action (int selectmode)
3057 {
3058         void *data;
3059         short datatype;
3060         
3061         bAction *act= NULL;
3062         bActionGroup *agrp= NULL;
3063         bActionChannel *achan= NULL;
3064         bConstraintChannel *conchan= NULL;
3065         IpoCurve *icu= NULL;
3066         TimeMarker *marker, *pmarker;
3067         
3068         void *act_channel;
3069         short sel, act_type;
3070         float selx;
3071         
3072         /* determine what type of data we are operating on */
3073         data = get_action_context(&datatype);
3074         if (data == NULL) return;
3075         if (datatype == ACTCONT_ACTION) act= (bAction *)data;
3076
3077         act_channel= get_nearest_action_key(&selx, &sel, &act_type, &achan);
3078         marker= find_nearest_marker(SCE_MARKERS, 1);
3079         pmarker= (act) ? find_nearest_marker(&act->markers, 1) : NULL;
3080         
3081         if (marker) {
3082                 /* what about scene's markers? */               
3083                 if (selectmode == SELECT_REPLACE) {                     
3084                         deselect_markers(0, 0);
3085                         marker->flag |= SELECT;
3086                 }
3087                 else if (selectmode == SELECT_INVERT) {
3088                         if (marker->flag & SELECT)
3089                                 marker->flag &= ~SELECT;
3090                         else
3091                                 marker->flag |= SELECT;
3092                 }
3093                 else if (selectmode == SELECT_ADD)