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