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