Animato - Restoring most of Action Editor
[blender.git] / source / blender / editors / animation / anim_channels.c
1 /**
2  * $Id: editaction.c 17746 2008-12-08 11:19:44Z aligorith $
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): Joshua Leung
26  *
27  * ***** END GPL LICENSE BLOCK *****
28  */
29
30 #include <math.h>
31 #include <stdlib.h>
32 #include <string.h>
33 #include <float.h>
34
35 #ifdef HAVE_CONFIG_H
36 #include <config.h>
37 #endif
38
39 #include "MEM_guardedalloc.h"
40
41 #include "BLI_blenlib.h"
42 #include "BLI_arithb.h"
43
44 #include "DNA_listBase.h"
45 #include "DNA_anim_types.h"
46 #include "DNA_action_types.h"
47 #include "DNA_armature_types.h"
48 #include "DNA_camera_types.h"
49 #include "DNA_curve_types.h"
50 #include "DNA_object_types.h"
51 #include "DNA_screen_types.h"
52 #include "DNA_scene_types.h"
53 #include "DNA_space_types.h"
54 #include "DNA_constraint_types.h"
55 #include "DNA_key_types.h"
56 #include "DNA_lamp_types.h"
57 #include "DNA_material_types.h"
58 #include "DNA_userdef_types.h"
59 #include "DNA_gpencil_types.h"
60 #include "DNA_windowmanager_types.h"
61
62 #include "RNA_access.h"
63 #include "RNA_define.h"
64
65 #include "BKE_action.h"
66 #include "BKE_depsgraph.h"
67 #include "BKE_ipo.h"
68 #include "BKE_key.h"
69 #include "BKE_material.h"
70 #include "BKE_object.h"
71 #include "BKE_context.h"
72 #include "BKE_utildefines.h"
73
74 #include "UI_interface.h"
75 #include "UI_resources.h"
76 #include "UI_view2d.h"
77
78 #include "ED_anim_api.h"
79 #include "ED_keyframes_edit.h" // XXX move the select modes out of there!
80 #include "ED_screen.h"
81 #include "ED_space_api.h"
82
83 #include "WM_api.h"
84 #include "WM_types.h"
85
86 /* ************************************************************************** */
87 /* CHANNELS API */
88
89 /* -------------------------- Internal Macros ------------------------------- */
90
91 /* set/clear/toggle macro 
92  *      - channel - channel with a 'flag' member that we're setting
93  *      - smode - 0=clear, 1=set, 2=toggle
94  *      - sflag - bitflag to set
95  */
96 #define ACHANNEL_SET_FLAG(channel, smode, sflag) \
97         { \
98                 if (smode == ACHANNEL_SETFLAG_TOGGLE)   (channel)->flag ^= (sflag); \
99                 else if (smode == ACHANNEL_SETFLAG_ADD) (channel)->flag |= (sflag); \
100                 else                                                                    (channel)->flag &= ~(sflag); \
101         }
102
103 /* -------------------------- Internal Tools -------------------------------- */
104
105 /* set the given Action Group to be the 'active' one in its Action */
106 static void action_set_active_agrp (bAction *act, bActionGroup *agrp)
107 {
108         bActionGroup *grp;
109         
110         /* sanity check */
111         if (act == NULL)
112                 return;
113                 
114         /* clear active flag on all others */
115         for (grp= act->groups.first; grp; grp= grp->next)
116                 grp->flag &= ~AGRP_ACTIVE;
117                 
118         /* set the given group to be the active one */
119         if (agrp)
120                 agrp->flag |= AGRP_ACTIVE;
121 }
122
123 /* -------------------------- Exposed API ----------------------------------- */
124
125 /* Set the given ActionChannel or ActionGroup as the active one in the given action
126  *      - data: should be bAction...
127  *      - datatype: should be ANIMCONT_ACTION 
128  *      - channel_data: bActionChannel or bActionGroup
129  *      - channel_type: eAnim_ChannelType
130  */
131 void ANIM_action_set_active_channel (void *data, short datatype, void *channel_data, short channel_type)
132 {
133         /* sanity checks */
134         if ((data == NULL) || (datatype != ANIMCONT_ACTION))
135                 return;
136                 
137         switch (channel_type) {
138                 case ANIMTYPE_GROUP:
139                         action_set_active_agrp((bAction *)data, (bActionGroup *)channel_data);
140                         break;
141         }
142 }
143
144 /* Deselect all animation channels 
145  *      - data: pointer to datatype, as contained in bAnimContext
146  *      - datatype: the type of data that 'data' represents (eAnimCont_Types)
147  *      - test: check if deselecting instead of selecting
148  *      - sel: eAnimChannels_SetFlag;
149  */
150 void ANIM_deselect_anim_channels (void *data, short datatype, short test, short sel)
151 {
152         ListBase anim_data = {NULL, NULL};
153         bAnimListElem *ale;
154         int filter;
155         
156         /* filter data */
157         filter= ANIMFILTER_VISIBLE;
158         ANIM_animdata_filter(&anim_data, filter, data, datatype);
159         
160         /* See if we should be selecting or deselecting */
161         if (test) {
162                 for (ale= anim_data.first; ale; ale= ale->next) {
163                         if (sel == 0) 
164                                 break;
165                         
166                         switch (ale->type) {
167                                 case ANIMTYPE_OBJECT:
168                                         if (ale->flag & SELECT)
169                                                 sel= ACHANNEL_SETFLAG_CLEAR;
170                                         break;
171                                 case ANIMTYPE_FILLACTD:
172                                         if (ale->flag & ACT_SELECTED)
173                                                 sel= ACHANNEL_SETFLAG_CLEAR;
174                                         break;
175                                 case ANIMTYPE_GROUP:
176                                         if (ale->flag & AGRP_SELECTED)
177                                                 sel= ACHANNEL_SETFLAG_CLEAR;
178                                         break;
179                                 case ANIMTYPE_FCURVE:
180                                         if (ale->flag & FCURVE_SELECTED)
181                                                 sel= ACHANNEL_SETFLAG_CLEAR;
182                                         break;
183                         }
184                 }
185         }
186                 
187         /* Now set the flags */
188         for (ale= anim_data.first; ale; ale= ale->next) {
189                 switch (ale->type) {
190                         case ANIMTYPE_OBJECT:
191                         {
192                                 Base *base= (Base *)ale->data;
193                                 Object *ob= base->object;
194                                 
195                                 ACHANNEL_SET_FLAG(base, sel, SELECT);
196                                 ACHANNEL_SET_FLAG(ob, sel, SELECT);
197                         }
198                                 break;
199                         case ANIMTYPE_FILLACTD:
200                         {
201                                 bAction *act= (bAction *)ale->data;
202                                 
203                                 ACHANNEL_SET_FLAG(act, sel, ACT_SELECTED);
204                         }
205                                 break;
206                         case ANIMTYPE_GROUP:
207                         {
208                                 bActionGroup *agrp= (bActionGroup *)ale->data;
209                                 
210                                 ACHANNEL_SET_FLAG(agrp, sel, AGRP_SELECTED);
211                                 agrp->flag &= ~AGRP_ACTIVE;
212                         }
213                                 break;
214                         case ANIMTYPE_FCURVE:
215                         {
216                                 FCurve *fcu= (FCurve *)ale->data;
217                                 
218                                 ACHANNEL_SET_FLAG(fcu, sel, FCURVE_SELECTED);
219                                 fcu->flag &= ~FCURVE_ACTIVE;
220                         }
221                                 break;
222                 }
223         }
224         
225         /* Cleanup */
226         BLI_freelistN(&anim_data);
227 }
228
229 /* ************************************************************************** */
230 /* OPERATORS */
231
232 /* ****************** Rearrange Channels Operator ******************* */
233 /* This operator only works for Action Editor mode for now, as having it elsewhere makes things difficult */
234
235 #if 0 // XXX old animation system - needs to be updated for new system...
236
237 /* constants for channel rearranging */
238 /* WARNING: don't change exising ones without modifying rearrange func accordingly */
239 enum {
240         REARRANGE_ACTCHAN_TOP= -2,
241         REARRANGE_ACTCHAN_UP= -1,
242         REARRANGE_ACTCHAN_DOWN= 1,
243         REARRANGE_ACTCHAN_BOTTOM= 2
244 };
245
246 /* make sure all action-channels belong to a group (and clear action's list) */
247 static void split_groups_action_temp (bAction *act, bActionGroup *tgrp)
248 {
249         bActionChannel *achan;
250         bActionGroup *agrp;
251         
252         /* Separate action-channels into lists per group */
253         for (agrp= act->groups.first; agrp; agrp= agrp->next) {
254                 if (agrp->channels.first) {
255                         achan= agrp->channels.last;
256                         act->chanbase.first= achan->next;
257                         
258                         achan= agrp->channels.first;
259                         achan->prev= NULL;
260                         
261                         achan= agrp->channels.last;
262                         achan->next= NULL;
263                 }
264         }
265         
266         /* Initialise memory for temp-group */
267         memset(tgrp, 0, sizeof(bActionGroup));
268         tgrp->flag |= (AGRP_EXPANDED|AGRP_TEMP);
269         strcpy(tgrp->name, "#TempGroup");
270                 
271         /* Move any action-channels not already moved, to the temp group */
272         if (act->chanbase.first) {
273                 /* start of list */
274                 achan= act->chanbase.first;
275                 achan->prev= NULL;
276                 tgrp->channels.first= achan;
277                 act->chanbase.first= NULL;
278                 
279                 /* end of list */
280                 achan= act->chanbase.last;
281                 achan->next= NULL;
282                 tgrp->channels.last= achan;
283                 act->chanbase.last= NULL;
284         }
285         
286         /* Add temp-group to list */
287         BLI_addtail(&act->groups, tgrp);
288 }
289
290 /* link lists of channels that groups have */
291 static void join_groups_action_temp (bAction *act)
292 {
293         bActionGroup *agrp;
294         bActionChannel *achan;
295         
296         for (agrp= act->groups.first; agrp; agrp= agrp->next) {
297                 ListBase tempGroup;
298                 
299                 /* add list of channels to action's channels */
300                 tempGroup= agrp->channels;
301                 addlisttolist(&act->chanbase, &agrp->channels);
302                 agrp->channels= tempGroup;
303                 
304                 /* clear moved flag */
305                 agrp->flag &= ~AGRP_MOVED;
306                 
307                 /* if temp-group... remove from list (but don't free as it's on the stack!) */
308                 if (agrp->flag & AGRP_TEMP) {
309                         BLI_remlink(&act->groups, agrp);
310                         break;
311                 }
312         }
313         
314         /* clear "moved" flag from all achans */
315         for (achan= act->chanbase.first; achan; achan= achan->next) 
316                 achan->flag &= ~ACHAN_MOVED;
317 }
318
319
320 static short rearrange_actchannel_is_ok (Link *channel, short type)
321 {
322         if (type == ANIMTYPE_GROUP) {
323                 bActionGroup *agrp= (bActionGroup *)channel;
324                 
325                 if (SEL_AGRP(agrp) && !(agrp->flag & AGRP_MOVED))
326                         return 1;
327         }
328         else if (type == ANIMTYPE_ACHAN) {
329                 bActionChannel *achan= (bActionChannel *)channel;
330                 
331                 if (VISIBLE_ACHAN(achan) && SEL_ACHAN(achan) && !(achan->flag & ACHAN_MOVED))
332                         return 1;
333         }
334         
335         return 0;
336 }
337
338 static short rearrange_actchannel_after_ok (Link *channel, short type)
339 {
340         if (type == ANIMTYPE_GROUP) {
341                 bActionGroup *agrp= (bActionGroup *)channel;
342                 
343                 if (agrp->flag & AGRP_TEMP)
344                         return 0;
345         }
346         
347         return 1;
348 }
349
350
351 static short rearrange_actchannel_top (ListBase *list, Link *channel, short type)
352 {
353         if (rearrange_actchannel_is_ok(channel, type)) {
354                 /* take it out off the chain keep data */
355                 BLI_remlink(list, channel);
356                 
357                 /* make it first element */
358                 BLI_insertlinkbefore(list, list->first, channel);
359                 
360                 return 1;
361         }
362         
363         return 0;
364 }
365
366 static short rearrange_actchannel_up (ListBase *list, Link *channel, short type)
367 {
368         if (rearrange_actchannel_is_ok(channel, type)) {
369                 Link *prev= channel->prev;
370                 
371                 if (prev) {
372                         /* take it out off the chain keep data */
373                         BLI_remlink(list, channel);
374                         
375                         /* push it up */
376                         BLI_insertlinkbefore(list, prev, channel);
377                         
378                         return 1;
379                 }
380         }
381         
382         return 0;
383 }
384
385 static short rearrange_actchannel_down (ListBase *list, Link *channel, short type)
386 {
387         if (rearrange_actchannel_is_ok(channel, type)) {
388                 Link *next = (channel->next) ? channel->next->next : NULL;
389                 
390                 if (next) {
391                         /* take it out off the chain keep data */
392                         BLI_remlink(list, channel);
393                         
394                         /* move it down */
395                         BLI_insertlinkbefore(list, next, channel);
396                         
397                         return 1;
398                 }
399                 else if (rearrange_actchannel_after_ok(list->last, type)) {
400                         /* take it out off the chain keep data */
401                         BLI_remlink(list, channel);
402                         
403                         /* add at end */
404                         BLI_addtail(list, channel);
405                         
406                         return 1;
407                 }
408                 else {
409                         /* take it out off the chain keep data */
410                         BLI_remlink(list, channel);
411                         
412                         /* add just before end */
413                         BLI_insertlinkbefore(list, list->last, channel);
414                         
415                         return 1;
416                 }
417         }
418         
419         return 0;
420 }
421
422 static short rearrange_actchannel_bottom (ListBase *list, Link *channel, short type)
423 {
424         if (rearrange_actchannel_is_ok(channel, type)) {
425                 if (rearrange_actchannel_after_ok(list->last, type)) {
426                         /* take it out off the chain keep data */
427                         BLI_remlink(list, channel);
428                         
429                         /* add at end */
430                         BLI_addtail(list, channel);
431                         
432                         return 1;
433                 }
434         }
435         
436         return 0;
437 }
438
439
440 /* Change the order of action-channels 
441  *      mode: REARRANGE_ACTCHAN_*  
442  */
443 static void rearrange_action_channels (bAnimContext *ac, short mode)
444 {
445         bAction *act;
446         bActionChannel *achan, *chan;
447         bActionGroup *agrp, *grp;
448         bActionGroup tgrp;
449         
450         short (*rearrange_func)(ListBase *, Link *, short);
451         short do_channels = 1;
452         
453         /* Get the active action, exit if none are selected */
454         act= (bAction *)ac->data;
455         
456         /* exit if invalid mode */
457         switch (mode) {
458                 case REARRANGE_ACTCHAN_TOP:
459                         rearrange_func= rearrange_actchannel_top;
460                         break;
461                 case REARRANGE_ACTCHAN_UP:
462                         rearrange_func= rearrange_actchannel_up;
463                         break;
464                 case REARRANGE_ACTCHAN_DOWN:
465                         rearrange_func= rearrange_actchannel_down;
466                         break;
467                 case REARRANGE_ACTCHAN_BOTTOM:
468                         rearrange_func= rearrange_actchannel_bottom;
469                         break;
470                 default:
471                         return;
472         }
473         
474         /* make sure we're only operating with groups */
475         split_groups_action_temp(act, &tgrp);
476         
477         /* rearrange groups first (and then, only consider channels if the groups weren't moved) */
478         #define GET_FIRST(list) ((mode > 0) ? (list.first) : (list.last))
479         #define GET_NEXT(item) ((mode > 0) ? (item->next) : (item->prev))
480         
481         for (agrp= GET_FIRST(act->groups); agrp; agrp= grp) {
482                 /* Get next group to consider */
483                 grp= GET_NEXT(agrp);
484                 
485                 /* try to do group first */
486                 if (rearrange_func(&act->groups, (Link *)agrp, ANIMTYPE_GROUP)) {
487                         do_channels= 0;
488                         agrp->flag |= AGRP_MOVED;
489                 }
490         }
491         
492         if (do_channels) {
493                 for (agrp= GET_FIRST(act->groups); agrp; agrp= grp) {
494                         /* Get next group to consider */
495                         grp= GET_NEXT(agrp);
496                         
497                         /* only consider action-channels if they're visible (group expanded) */
498                         if (EXPANDED_AGRP(agrp)) {
499                                 for (achan= GET_FIRST(agrp->channels); achan; achan= chan) {
500                                         /* Get next channel to consider */
501                                         chan= GET_NEXT(achan);
502                                         
503                                         /* Try to do channel */
504                                         if (rearrange_func(&agrp->channels, (Link *)achan, ANIMTYPE_ACHAN))
505                                                 achan->flag |= ACHAN_MOVED;
506                                 }
507                         }
508                 }
509         }
510         #undef GET_FIRST
511         #undef GET_NEXT
512         
513         /* assemble lists into one list (and clear moved tags) */
514         join_groups_action_temp(act);
515 }
516
517 /* ------------------- */
518
519 static int animchannels_rearrange_exec(bContext *C, wmOperator *op)
520 {
521         bAnimContext ac;
522         short mode;
523         
524         /* get editor data - only for Action Editor (for now) */
525         if (ANIM_animdata_get_context(C, &ac) == 0)
526                 return OPERATOR_CANCELLED;
527         if (ac.datatype != ANIMCONT_ACTION)
528                 return OPERATOR_PASS_THROUGH;
529                 
530         /* get mode, then rearrange channels */
531         mode= RNA_enum_get(op->ptr, "direction");
532         rearrange_action_channels(&ac, mode);
533         
534         /* set notifier tha things have changed */
535         ANIM_animdata_send_notifiers(C, &ac, ANIM_CHANGED_CHANNELS);
536         
537         return OPERATOR_FINISHED;
538 }
539  
540
541 void ANIM_OT_channels_move_up (wmOperatorType *ot)
542 {
543         /* identifiers */
544         ot->name= "Move Channel(s) Up";
545         ot->idname= "ANIM_OT_channels_move_up";
546         
547         /* api callbacks */
548         ot->exec= animchannels_rearrange_exec;
549         ot->poll= ED_operator_areaactive;
550         
551         /* flags */
552         ot->flag= OPTYPE_REGISTER/*|OPTYPE_UNDO*/;
553         
554         /* props */
555         RNA_def_enum(ot->srna, "direction", NULL /* XXX add enum for this */, REARRANGE_ACTCHAN_UP, "Direction", "");
556 }
557
558 void ANIM_OT_channels_move_down (wmOperatorType *ot)
559 {
560         /* identifiers */
561         ot->name= "Move Channel(s) Down";
562         ot->idname= "ANIM_OT_channels_move_down";
563         
564         /* api callbacks */
565         ot->exec= animchannels_rearrange_exec;
566         ot->poll= ED_operator_areaactive;
567         
568         /* flags */
569         ot->flag= OPTYPE_REGISTER/*|OPTYPE_UNDO*/;
570         
571         /* props */
572         RNA_def_enum(ot->srna, "direction", NULL /* XXX add enum for this */, REARRANGE_ACTCHAN_DOWN, "Direction", "");
573 }
574
575 void ANIM_OT_channels_move_top (wmOperatorType *ot)
576 {
577         /* identifiers */
578         ot->name= "Move Channel(s) to Top";
579         ot->idname= "ANIM_OT_channels_move_to_top";
580         
581         /* api callbacks */
582         ot->exec= animchannels_rearrange_exec;
583         ot->poll= ED_operator_areaactive;
584         
585         /* flags */
586         ot->flag= OPTYPE_REGISTER/*|OPTYPE_UNDO*/;
587         
588         /* props */
589         RNA_def_enum(ot->srna, "direction", NULL /* XXX add enum for this */, REARRANGE_ACTCHAN_TOP, "Direction", "");
590 }
591
592 void ANIM_OT_channels_move_bottom (wmOperatorType *ot)
593 {
594         /* identifiers */
595         ot->name= "Move Channel(s) to Bottom";
596         ot->idname= "ANIM_OT_channels_move_to_bottom";
597         
598         /* api callbacks */
599         ot->exec= animchannels_rearrange_exec;
600         ot->poll= ED_operator_areaactive;
601         
602         /* flags */
603         ot->flag= OPTYPE_REGISTER/*|OPTYPE_UNDO*/;
604         
605         /* props */
606         RNA_def_enum(ot->srna, "direction", NULL /* XXX add enum for this */, REARRANGE_ACTCHAN_BOTTOM, "Direction", "");
607 }
608
609 #endif // XXX old animation system - needs to be updated for new system...
610
611 /* ********************** Set Flags Operator *********************** */
612
613 enum {
614 //      ACHANNEL_SETTING_SELECT = 0,
615         ACHANNEL_SETTING_PROTECT = 1,
616         ACHANNEL_SETTING_MUTE,
617 } eAnimChannel_Settings;
618
619 /* defines for setting animation-channel flags */
620 EnumPropertyItem prop_animchannel_setflag_types[] = {
621         {ACHANNEL_SETFLAG_CLEAR, "DISABLE", "Disable", ""},
622         {ACHANNEL_SETFLAG_ADD, "ENABLE", "Enable", ""},
623         {ACHANNEL_SETFLAG_TOGGLE, "TOGGLE", "Toggle", ""},
624         {0, NULL, NULL, NULL}
625 };
626
627 /* defines for set animation-channel settings */
628 EnumPropertyItem prop_animchannel_settings_types[] = {
629         {ACHANNEL_SETTING_PROTECT, "PROTECT", "Protect", ""},
630         {ACHANNEL_SETTING_MUTE, "MUTE", "Mute", ""},
631         {0, NULL, NULL, NULL}
632 };
633
634
635 /* ------------------- */
636
637 /* Set/clear a particular flag (setting) for all selected + visible channels 
638  *      setting: the setting to modify
639  *      mode: eAnimChannels_SetFlag
640  */
641 static void setflag_anim_channels (bAnimContext *ac, short setting, short mode)
642 {
643         ListBase anim_data = {NULL, NULL};
644         bAnimListElem *ale;
645         int filter;
646         
647         /* filter data */
648         filter= (ANIMFILTER_VISIBLE | ANIMFILTER_CHANNELS | ANIMFILTER_SEL);
649         ANIM_animdata_filter(&anim_data, filter, ac->data, ac->datatype);
650         
651         /* affect selected channels */
652         for (ale= anim_data.first; ale; ale= ale->next) {
653                 switch (ale->type) {
654                         case ANIMTYPE_GROUP:
655                         {
656                                 bActionGroup *agrp= (bActionGroup *)ale->data;
657                                 
658                                 /* only 'protect' is available */
659                                 if (setting == ACHANNEL_SETTING_PROTECT) {
660                                         ACHANNEL_SET_FLAG(agrp, mode, AGRP_PROTECTED);
661                                 }
662                         }
663                                 break;
664                         case ANIMTYPE_FCURVE:
665                         {
666                                 FCurve *fcu= (FCurve *)ale->data;
667                                 
668                                 /* mute */
669                                 if (setting == ACHANNEL_SETTING_MUTE) {
670                                         ACHANNEL_SET_FLAG(fcu, mode, FCURVE_MUTED);
671                                 }
672                                 else if (setting == ACHANNEL_SETTING_PROTECT) {
673                                         ACHANNEL_SET_FLAG(fcu, mode, FCURVE_PROTECTED);
674                                 }
675                         }
676                                 break;
677                         case ANIMTYPE_GPLAYER:
678                         {
679                                 bGPDlayer *gpl= (bGPDlayer *)ale->data;
680                                 
681                                 /* 'protect' and 'mute' */
682                                 if (setting == ACHANNEL_SETTING_MUTE) {
683                                         /* mute */
684                                         ACHANNEL_SET_FLAG(gpl, mode, GP_LAYER_HIDE);
685                                 }
686                                 else if (setting == ACHANNEL_SETTING_PROTECT) {
687                                         /* protected */
688                                         ACHANNEL_SET_FLAG(gpl, mode, GP_LAYER_LOCKED);
689                                 }
690                         }
691                                 break;
692                 }
693         }
694         
695         BLI_freelistN(&anim_data);
696 }
697
698 /* ------------------- */
699
700 static int animchannels_setflag_exec(bContext *C, wmOperator *op)
701 {
702         bAnimContext ac;
703         short mode, setting;
704         
705         /* get editor data */
706         if (ANIM_animdata_get_context(C, &ac) == 0)
707                 return OPERATOR_CANCELLED;
708                 
709         /* mode (eAnimChannels_SetFlag), setting (eAnimChannel_Settings) */
710         mode= RNA_enum_get(op->ptr, "mode");
711         setting= RNA_enum_get(op->ptr, "type");
712         
713         /* modify setting */
714         setflag_anim_channels(&ac, setting, mode);
715         
716         /* set notifier tha things have changed */
717         ANIM_animdata_send_notifiers(C, &ac, ANIM_CHANGED_CHANNELS);
718         
719         return OPERATOR_FINISHED;
720 }
721
722
723 void ANIM_OT_channels_enable_setting (wmOperatorType *ot)
724 {
725         /* identifiers */
726         ot->name= "Enable Channel Setting";
727         ot->idname= "ANIM_OT_channels_enable_setting";
728         
729         /* api callbacks */
730         ot->invoke= WM_menu_invoke;
731         ot->exec= animchannels_setflag_exec;
732         ot->poll= ED_operator_areaactive;
733         
734         /* flags */
735         ot->flag= OPTYPE_REGISTER/*|OPTYPE_UNDO*/;
736         
737         /* props */
738                 /* flag-setting mode */
739         RNA_def_enum(ot->srna, "mode", prop_animchannel_setflag_types, ACHANNEL_SETFLAG_ADD, "Mode", "");
740                 /* setting to set */
741         RNA_def_enum(ot->srna, "type", prop_animchannel_settings_types, 0, "Type", "");
742 }
743
744 void ANIM_OT_channels_disable_setting (wmOperatorType *ot)
745 {
746         /* identifiers */
747         ot->name= "Disable Channel Setting";
748         ot->idname= "ANIM_OT_channels_disable_setting";
749         
750         /* api callbacks */
751         ot->invoke= WM_menu_invoke;
752         ot->exec= animchannels_setflag_exec;
753         ot->poll= ED_operator_areaactive;
754         
755         /* flags */
756         ot->flag= OPTYPE_REGISTER/*|OPTYPE_UNDO*/;
757         
758         /* props */
759                 /* flag-setting mode */
760         RNA_def_enum(ot->srna, "mode", prop_animchannel_setflag_types, ACHANNEL_SETFLAG_CLEAR, "Mode", "");
761                 /* setting to set */
762         RNA_def_enum(ot->srna, "type", prop_animchannel_settings_types, 0, "Type", "");
763 }
764
765 void ANIM_OT_channels_toggle_setting (wmOperatorType *ot)
766 {
767         /* identifiers */
768         ot->name= "Toggle Channel Setting";
769         ot->idname= "ANIM_OT_channels_toggle_setting";
770         
771         /* api callbacks */
772         ot->invoke= WM_menu_invoke;
773         ot->exec= animchannels_setflag_exec;
774         ot->poll= ED_operator_areaactive;
775         
776         /* flags */
777         ot->flag= OPTYPE_REGISTER/*|OPTYPE_UNDO*/;
778         
779         /* props */
780                 /* flag-setting mode */
781         RNA_def_enum(ot->srna, "mode", prop_animchannel_setflag_types, ACHANNEL_SETFLAG_TOGGLE, "Mode", "");
782                 /* setting to set */
783         RNA_def_enum(ot->srna, "type", prop_animchannel_settings_types, 0, "Type", "");
784 }
785
786 /* ********************** Select All Operator *********************** */
787
788 static int animchannels_deselectall_exec(bContext *C, wmOperator *op)
789 {
790         bAnimContext ac;
791         
792         /* get editor data */
793         if (ANIM_animdata_get_context(C, &ac) == 0)
794                 return OPERATOR_CANCELLED;
795                 
796         /* 'standard' behaviour - check if selected, then apply relevant selection */
797         if (RNA_boolean_get(op->ptr, "invert"))
798                 ANIM_deselect_anim_channels(ac.data, ac.datatype, 0, ACHANNEL_SETFLAG_TOGGLE);
799         else
800                 ANIM_deselect_anim_channels(ac.data, ac.datatype, 1, ACHANNEL_SETFLAG_ADD);
801         
802         /* set notifier tha things have changed */
803         ANIM_animdata_send_notifiers(C, &ac, ANIM_CHANGED_CHANNELS);
804         
805         return OPERATOR_FINISHED;
806 }
807  
808 void ANIM_OT_channels_deselectall (wmOperatorType *ot)
809 {
810         /* identifiers */
811         ot->name= "Select All";
812         ot->idname= "ANIM_OT_channels_deselectall";
813         
814         /* api callbacks */
815         ot->exec= animchannels_deselectall_exec;
816         ot->poll= ED_operator_areaactive;
817         
818         /* flags */
819         ot->flag= OPTYPE_REGISTER/*|OPTYPE_UNDO*/;
820         
821         /* props */
822         RNA_def_boolean(ot->srna, "invert", 0, "Invert", "");
823 }
824
825 /* ******************** Borderselect Operator *********************** */
826
827 static void borderselect_anim_channels (bAnimContext *ac, rcti *rect, short selectmode)
828 {
829         ListBase anim_data = {NULL, NULL};
830         bAnimListElem *ale;
831         int filter;
832         
833         View2D *v2d= &ac->ar->v2d;
834         rctf rectf;
835         float ymin=0, ymax=(float)(-ACHANNEL_HEIGHT);
836         
837         /* convert border-region to view coordinates */
838         UI_view2d_region_to_view(v2d, rect->xmin, rect->ymin+2, &rectf.xmin, &rectf.ymin);
839         UI_view2d_region_to_view(v2d, rect->xmax, rect->ymax-2, &rectf.xmax, &rectf.ymax);
840         
841         /* filter data */
842         filter= (ANIMFILTER_VISIBLE | ANIMFILTER_CHANNELS);
843         ANIM_animdata_filter(&anim_data, filter, ac->data, ac->datatype);
844         
845         /* loop over data, doing border select */
846         for (ale= anim_data.first; ale; ale= ale->next) {
847                 ymin= ymax - ACHANNEL_STEP;
848                 
849                 /* if channel is within border-select region, alter it */
850                 if (!((ymax < rectf.ymin) || (ymin > rectf.ymax))) {
851                         /* only the following types can be selected */
852                         switch (ale->type) {
853                                 case ANIMTYPE_OBJECT: /* object */
854                                 {
855                                         Base *base= (Base *)ale->data;
856                                         Object *ob= base->object;
857                                         
858                                         ACHANNEL_SET_FLAG(base, selectmode, SELECT);
859                                         ACHANNEL_SET_FLAG(ob, selectmode, SELECT);
860                                 }
861                                         break;
862                                 case ANIMTYPE_GROUP: /* action group */
863                                 {
864                                         bActionGroup *agrp= (bActionGroup *)ale->data;
865                                         
866                                         ACHANNEL_SET_FLAG(agrp, selectmode, AGRP_SELECTED);
867                                         agrp->flag &= ~AGRP_ACTIVE;
868                                 }
869                                         break;
870                                 case ANIMTYPE_FCURVE: /* F-Curve channel */
871                                 {
872                                         FCurve *fcu = (FCurve *)ale->data;
873                                         
874                                         ACHANNEL_SET_FLAG(fcu, selectmode, FCURVE_SELECTED);
875                                 }
876                                         break;
877                                 case ANIMTYPE_GPLAYER: /* grease-pencil layer */
878                                 {
879                                         bGPDlayer *gpl = (bGPDlayer *)ale->data;
880                                         
881                                         ACHANNEL_SET_FLAG(gpl, selectmode, GP_LAYER_SELECT);
882                                 }
883                                         break;
884                         }
885                 }
886                 
887                 /* set minimum extent to be the maximum of the next channel */
888                 ymax= ymin;
889         }
890         
891         /* cleanup */
892         BLI_freelistN(&anim_data);
893 }
894
895 /* ------------------- */
896
897 static int animchannels_borderselect_exec(bContext *C, wmOperator *op)
898 {
899         bAnimContext ac;
900         rcti rect;
901         short selectmode=0;
902         int event;
903         
904         /* get editor data */
905         if (ANIM_animdata_get_context(C, &ac) == 0)
906                 return OPERATOR_CANCELLED;
907         
908         /* get settings from operator */
909         rect.xmin= RNA_int_get(op->ptr, "xmin");
910         rect.ymin= RNA_int_get(op->ptr, "ymin");
911         rect.xmax= RNA_int_get(op->ptr, "xmax");
912         rect.ymax= RNA_int_get(op->ptr, "ymax");
913                 
914         event= RNA_int_get(op->ptr, "event_type");
915         if (event == LEFTMOUSE) // FIXME... hardcoded
916                 selectmode = ACHANNEL_SETFLAG_ADD;
917         else
918                 selectmode = ACHANNEL_SETFLAG_CLEAR;
919         
920         /* apply borderselect animation channels */
921         borderselect_anim_channels(&ac, &rect, selectmode);
922         
923         return OPERATOR_FINISHED;
924
925
926 void ANIM_OT_channels_borderselect(wmOperatorType *ot)
927 {
928         /* identifiers */
929         ot->name= "Border Select";
930         ot->idname= "ANIM_OT_channels_borderselect";
931         
932         /* api callbacks */
933         ot->invoke= WM_border_select_invoke;
934         ot->exec= animchannels_borderselect_exec;
935         ot->modal= WM_border_select_modal;
936         
937         ot->poll= ED_operator_areaactive;
938         
939         /* flags */
940         ot->flag= OPTYPE_REGISTER/*|OPTYPE_UNDO*/;
941         
942         /* rna */
943         RNA_def_int(ot->srna, "event_type", 0, INT_MIN, INT_MAX, "Event Type", "", INT_MIN, INT_MAX);
944         RNA_def_int(ot->srna, "xmin", 0, INT_MIN, INT_MAX, "X Min", "", INT_MIN, INT_MAX);
945         RNA_def_int(ot->srna, "xmax", 0, INT_MIN, INT_MAX, "X Max", "", INT_MIN, INT_MAX);
946         RNA_def_int(ot->srna, "ymin", 0, INT_MIN, INT_MAX, "Y Min", "", INT_MIN, INT_MAX);
947         RNA_def_int(ot->srna, "ymax", 0, INT_MIN, INT_MAX, "Y Max", "", INT_MIN, INT_MAX);
948 }
949
950 /* ******************** Mouse-Click Operator *********************** */
951 /* Depending on the channel that was clicked on, the mouse click will activate whichever
952  * part of the channel is relevant.
953  *
954  * NOTE: eventually, this should probably be phased out when many of these things are replaced with buttons
955  */
956
957 static void mouse_anim_channels (bAnimContext *ac, float x, int channel_index, short selectmode)
958 {
959         ListBase anim_data = {NULL, NULL};
960         bAnimListElem *ale;
961         int filter;
962         
963         /* get the channel that was clicked on */
964                 /* filter channels */
965         filter= (ANIMFILTER_VISIBLE | ANIMFILTER_CHANNELS);
966         filter= ANIM_animdata_filter(&anim_data, filter, ac->data, ac->datatype);
967         
968                 /* get channel from index */
969         ale= BLI_findlink(&anim_data, channel_index);
970         if (ale == NULL) {
971                 /* channel not found */
972                 printf("Error: animation channel (index = %d) not found in mouse_anim_channels() \n", channel_index);
973                 
974                 BLI_freelistN(&anim_data);
975                 return;
976         }
977         
978         /* selectmode -1 is a special case for ActionGroups only, which selects all of the channels underneath it only... */
979         // TODO: should this feature be extended to work with other channel types too?
980         if ((selectmode == -1) && (ale->type != ANIMTYPE_GROUP)) {
981                 /* normal channels should not behave normally in this case */
982                 BLI_freelistN(&anim_data);
983                 return;
984         }
985         
986         /* action to take depends on what channel we've got */
987         switch (ale->type) {
988                 case ANIMTYPE_OBJECT:
989                 {
990                         bDopeSheet *ads= (bDopeSheet *)ac->data;
991                         Scene *sce= (Scene *)ads->source;
992                         Base *base= (Base *)ale->data;
993                         Object *ob= base->object;
994                         
995                         if (x < 16) {
996                                 /* toggle expand */
997                                 ob->nlaflag ^= OB_ADS_COLLAPSED; // XXX 
998                         }
999                         else {
1000                                 /* set selection status */
1001                                 if (selectmode == SELECT_INVERT) {
1002                                         /* swap select */
1003                                         base->flag ^= SELECT;
1004                                         ob->flag= base->flag;
1005                                 }
1006                                 else {
1007                                         Base *b;
1008                                         
1009                                         /* deleselect all */
1010                                         for (b= sce->base.first; b; b= b->next) {
1011                                                 b->flag &= ~SELECT;
1012                                                 b->object->flag= b->flag;
1013                                         }
1014                                         
1015                                         /* select object now */
1016                                         base->flag |= SELECT;
1017                                         ob->flag |= SELECT;
1018                                 }
1019                                 
1020                                 /* xxx should be ED_base_object_activate(), but we need context pointer for that... */
1021                                 //set_active_base(base);
1022                         }
1023                 }
1024                         break;
1025                 case ANIMTYPE_FILLACTD:
1026                 {
1027                         bAction *act= (bAction *)ale->data;
1028                         act->flag ^= ACT_EXPANDED;
1029                 }
1030                         break;
1031                 case ANIMTYPE_FILLMATD:
1032                 {
1033                         Object *ob= (Object *)ale->data;
1034                         ob->nlaflag ^= OB_ADS_SHOWMATS; // XXX 
1035                 }
1036                         break;
1037                                 
1038                 case ANIMTYPE_DSMAT:
1039                 {
1040                         Material *ma= (Material *)ale->data;
1041                         ma->flag ^= MA_DS_EXPAND;
1042                 }
1043                         break;
1044                 case ANIMTYPE_DSLAM:
1045                 {
1046                         Lamp *la= (Lamp *)ale->data;
1047                         la->flag ^= LA_DS_EXPAND;
1048                 }
1049                         break;
1050                 case ANIMTYPE_DSCAM:
1051                 {
1052                         Camera *ca= (Camera *)ale->data;
1053                         ca->flag ^= CAM_DS_EXPAND;
1054                 }
1055                         break;
1056                 case ANIMTYPE_DSCUR:
1057                 {
1058                         Curve *cu= (Curve *)ale->data;
1059                         cu->flag ^= CU_DS_EXPAND;
1060                 }
1061                         break;
1062                 case ANIMTYPE_DSSKEY:
1063                 {
1064                         Key *key= (Key *)ale->data;
1065                         key->flag ^= KEYBLOCK_DS_EXPAND;
1066                 }
1067                         break;
1068                         
1069                 case ANIMTYPE_GROUP: 
1070                 {
1071                         bActionGroup *agrp= (bActionGroup *)ale->data;
1072                         short offset= (ac->datatype == ANIMCONT_DOPESHEET)? 21 : 0;
1073                         
1074                         if ((x < (offset+17)) && (agrp->channels.first)) {
1075                                 /* toggle expand */
1076                                 agrp->flag ^= AGRP_EXPANDED;
1077                         }
1078                         else if (x >= (ACHANNEL_NAMEWIDTH-ACHANNEL_BUTTON_WIDTH)) {
1079                                 /* toggle protection/locking */
1080                                 agrp->flag ^= AGRP_PROTECTED;
1081                         }
1082                         else {
1083                                 /* select/deselect group */
1084                                 if (selectmode == SELECT_INVERT) {
1085                                         /* inverse selection status of this group only */
1086                                         agrp->flag ^= AGRP_SELECTED;
1087                                 }
1088                                 else if (selectmode == -1) {
1089                                         /* select all in group (and deselect everthing else) */ 
1090                                         bActionChannel *achan;
1091                                         
1092                                         /* deselect all other channels */
1093                                         ANIM_deselect_anim_channels(ac->data, ac->datatype, 0, ACHANNEL_SETFLAG_CLEAR);
1094                                         
1095                                         /* only select channels in group and group itself */
1096                                         for (achan= agrp->channels.first; achan && achan->grp==agrp; achan= achan->next)
1097                                                 achan->flag |= ACHAN_SELECTED;
1098                                         agrp->flag |= AGRP_SELECTED;                                    
1099                                 }
1100                                 else {
1101                                         /* select group by itself */
1102                                         ANIM_deselect_anim_channels(ac->data, ac->datatype, 0, ACHANNEL_SETFLAG_CLEAR);
1103                                         agrp->flag |= AGRP_SELECTED;
1104                                 }
1105                                 
1106                                 /* if group is selected now, and we're in Action Editor mode (so that we have pointer to active action),
1107                                  * we can make this group the 'active' one in that action
1108                                  */
1109                                 if ((agrp->flag & AGRP_SELECTED) && (ac->datatype == ANIMCONT_ACTION))
1110                                         action_set_active_agrp((bAction *)ac->data, agrp);
1111                         }
1112                 }
1113                         break;
1114                 case ANIMTYPE_FCURVE: 
1115                 {
1116                         FCurve *fcu= (FCurve *)ale->data;
1117                         
1118                         if (x >= (ACHANNEL_NAMEWIDTH-ACHANNEL_BUTTON_WIDTH)) {
1119                                 /* toggle protection */
1120                                 fcu->flag ^= FCURVE_PROTECTED;
1121                         }
1122                         else if (x >= (ACHANNEL_NAMEWIDTH-2*ACHANNEL_BUTTON_WIDTH)) {
1123                                 /* toggle mute */
1124                                 fcu->flag ^= FCURVE_MUTED;
1125                         }
1126                         else {
1127                                 /* select/deselect */
1128                                 fcu->flag ^= FCURVE_SELECTED;
1129                         }
1130                 }
1131                         break;
1132                 case ANIMTYPE_GPDATABLOCK:
1133                 {
1134                         bGPdata *gpd= (bGPdata *)ale->data;
1135                         
1136                         /* toggle expand */
1137                         gpd->flag ^= GP_DATA_EXPAND;
1138                 }
1139                         break;
1140                 case ANIMTYPE_GPLAYER:
1141                 {
1142 #if 0 // XXX future of this is unclear
1143                         bGPdata *gpd= (bGPdata *)ale->owner;
1144                         bGPDlayer *gpl= (bGPDlayer *)ale->data;
1145                         
1146                         if (x >= (ACHANNEL_NAMEWIDTH-16)) {
1147                                 /* toggle lock */
1148                                 gpl->flag ^= GP_LAYER_LOCKED;
1149                         }
1150                         else if (x >= (ACHANNEL_NAMEWIDTH-32)) {
1151                                 /* toggle hide */
1152                                 gpl->flag ^= GP_LAYER_HIDE;
1153                         }
1154                         else {
1155                                 /* select/deselect */
1156                                 //if (G.qual & LR_SHIFTKEY) {
1157                                         //select_gplayer_channel(gpd, gpl, SELECT_INVERT);
1158                                 //}
1159                                 //else {
1160                                         //deselect_gpencil_layers(data, 0);
1161                                         //select_gplayer_channel(gpd, gpl, SELECT_INVERT);
1162                                 //}
1163                         }
1164 #endif // XXX future of this is unclear
1165                 }
1166                         break;
1167                 case ANIMTYPE_SHAPEKEY:
1168                         /* TODO: shapekey channels cannot be selected atm... */
1169                         break;
1170                 default:
1171                         printf("Error: Invalid channel type in mouse_anim_channels() \n");
1172         }
1173         
1174         /* free channels */
1175         BLI_freelistN(&anim_data);
1176 }
1177
1178 /* ------------------- */
1179
1180 /* handle clicking */
1181 static int animchannels_mouseclick_invoke(bContext *C, wmOperator *op, wmEvent *event)
1182 {
1183         bAnimContext ac;
1184         Scene *scene;
1185         ARegion *ar;
1186         View2D *v2d;
1187         int mval[2], channel_index;
1188         short selectmode;
1189         float x, y;
1190         
1191         
1192         /* get editor data */
1193         if (ANIM_animdata_get_context(C, &ac) == 0)
1194                 return OPERATOR_CANCELLED;
1195                 
1196         /* get useful pointers from animation context data */
1197         scene= ac.scene;
1198         ar= ac.ar;
1199         v2d= &ar->v2d;
1200         
1201         /* get mouse coordinates (in region coordinates) */
1202         mval[0]= (event->x - ar->winrct.xmin);
1203         mval[1]= (event->y - ar->winrct.ymin);
1204         
1205         /* select mode is either replace (deselect all, then add) or add/extend */
1206         if (RNA_boolean_get(op->ptr, "extend_select"))
1207                 selectmode= SELECT_INVERT;
1208         else if (RNA_boolean_get(op->ptr, "select_children_only"))
1209                 selectmode= -1; /* this is a bit of a special case for ActionGroups only... should it be removed or extended to all instead? */
1210         else
1211                 selectmode= SELECT_REPLACE;
1212         
1213         /* figure out which channel user clicked in 
1214          * Note: although channels technically start at y= ACHANNEL_FIRST, we need to adjust by half a channel's height
1215          *              so that the tops of channels get caught ok. Since ACHANNEL_FIRST is really ACHANNEL_HEIGHT, we simply use
1216          *              ACHANNEL_HEIGHT_HALF.
1217          */
1218         UI_view2d_region_to_view(v2d, mval[0], mval[1], &x, &y);
1219         UI_view2d_listview_view_to_cell(v2d, ACHANNEL_NAMEWIDTH, ACHANNEL_STEP, 0, (float)ACHANNEL_HEIGHT_HALF, x, y, NULL, &channel_index);
1220         
1221         /* handle mouse-click in the relevant channel then */
1222         mouse_anim_channels(&ac, x, channel_index, selectmode);
1223         
1224         /* set notifier tha things have changed */
1225         ANIM_animdata_send_notifiers(C, &ac, ANIM_CHANGED_CHANNELS);
1226         
1227         return OPERATOR_FINISHED;
1228 }
1229  
1230 void ANIM_OT_channels_mouseclick (wmOperatorType *ot)
1231 {
1232         /* identifiers */
1233         ot->name= "Mouse Click on Channels";
1234         ot->idname= "ANIM_OT_channels_mouseclick";
1235         
1236         /* api callbacks */
1237         ot->invoke= animchannels_mouseclick_invoke;
1238         ot->poll= ED_operator_areaactive;
1239         
1240         /* id-props */
1241         RNA_def_boolean(ot->srna, "extend_select", 0, "Extend Select", ""); // SHIFTKEY
1242         RNA_def_boolean(ot->srna, "select_children_only", 0, "Select Children Only", ""); // CTRLKEY|SHIFTKEY
1243 }
1244
1245 /* ************************************************************************** */
1246 /* Operator Registration */
1247
1248 void ED_operatortypes_animchannels(void)
1249 {
1250         WM_operatortype_append(ANIM_OT_channels_deselectall);
1251         WM_operatortype_append(ANIM_OT_channels_borderselect);
1252         WM_operatortype_append(ANIM_OT_channels_mouseclick);
1253         
1254         WM_operatortype_append(ANIM_OT_channels_enable_setting);
1255         WM_operatortype_append(ANIM_OT_channels_disable_setting);
1256         WM_operatortype_append(ANIM_OT_channels_toggle_setting);
1257         
1258                 // XXX these need to be updated for new system... todo...
1259         //WM_operatortype_append(ANIM_OT_channels_move_up);
1260         //WM_operatortype_append(ANIM_OT_channels_move_down);
1261         //WM_operatortype_append(ANIM_OT_channels_move_top);
1262         //WM_operatortype_append(ANIM_OT_channels_move_bottom);
1263 }
1264
1265 void ED_keymap_animchannels(wmWindowManager *wm)
1266 {
1267         ListBase *keymap = WM_keymap_listbase(wm, "Animation_Channels", 0, 0);
1268         
1269         /* selection */
1270                 /* click-select */
1271                 // XXX for now, only leftmouse.... 
1272         WM_keymap_add_item(keymap, "ANIM_OT_channels_mouseclick", LEFTMOUSE, KM_PRESS, 0, 0);
1273         RNA_boolean_set(WM_keymap_add_item(keymap, "ANIM_OT_channels_mouseclick", LEFTMOUSE, KM_PRESS, KM_SHIFT, 0)->ptr, "extend_select", 1);
1274         RNA_boolean_set(WM_keymap_add_item(keymap, "ANIM_OT_channels_mouseclick", LEFTMOUSE, KM_PRESS, KM_CTRL|KM_SHIFT, 0)->ptr, "select_children_only", 1);
1275         
1276                 /* deselect all */
1277         WM_keymap_add_item(keymap, "ANIM_OT_channels_deselectall", AKEY, KM_PRESS, 0, 0);
1278         RNA_boolean_set(WM_keymap_add_item(keymap, "ANIM_OT_channels_deselectall", IKEY, KM_PRESS, KM_CTRL, 0)->ptr, "invert", 1);
1279         
1280                 /* borderselect */
1281         WM_keymap_add_item(keymap, "ANIM_OT_channels_borderselect", BKEY, KM_PRESS, 0, 0);
1282         
1283         /* settings */
1284         WM_keymap_add_item(keymap, "ANIM_OT_channels_toggle_setting", WKEY, KM_PRESS, KM_SHIFT, 0);
1285         WM_keymap_add_item(keymap, "ANIM_OT_channels_enable_setting", WKEY, KM_PRESS, KM_CTRL|KM_SHIFT, 0);
1286         WM_keymap_add_item(keymap, "ANIM_OT_channels_disable_setting", WKEY, KM_PRESS, KM_ALT, 0);
1287         
1288         /* rearranging - actions only */
1289         //WM_keymap_add_item(keymap, "ANIM_OT_channels_move_up", PAGEUPKEY, KM_PRESS, KM_SHIFT, 0);
1290         //WM_keymap_add_item(keymap, "ANIM_OT_channels_move_down", PAGEDOWNKEY, KM_PRESS, KM_SHIFT, 0);
1291         //WM_keymap_add_item(keymap, "ANIM_OT_channels_move_to_top", PAGEUPKEY, KM_PRESS, KM_CTRL|KM_SHIFT, 0);
1292         //WM_keymap_add_item(keymap, "ANIM_OT_channels_move_to_bottom", PAGEDOWNKEY, KM_PRESS, KM_CTRL|KM_SHIFT, 0);
1293 }
1294
1295 /* ************************************************************************** */