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