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