remove/comment unused defines.
[blender.git] / source / blender / editors / animation / anim_markers.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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19  *
20  * The Original Code is Copyright (C) 2008 Blender Foundation.
21  * All rights reserved.
22  *
23  * 
24  * Contributor(s): Blender Foundation
25  *
26  * ***** END GPL LICENSE BLOCK *****
27  */
28
29 #include <math.h>
30
31 #include "MEM_guardedalloc.h"
32
33 #include "DNA_scene_types.h"
34 #include "DNA_object_types.h"
35
36 #include "RNA_access.h"
37 #include "RNA_define.h"
38 #include "RNA_enum_types.h"
39
40 #include "BLI_blenlib.h"
41 #include "BLI_utildefines.h"
42
43 #include "BKE_context.h"
44 #include "BKE_fcurve.h"
45 #include "BKE_main.h"
46 #include "BKE_report.h"
47 #include "BKE_scene.h"
48
49 #include "WM_api.h"
50 #include "WM_types.h"
51
52 #include "BIF_gl.h"
53 #include "BIF_glutil.h"
54
55 #include "UI_interface.h"
56 #include "UI_interface_icons.h"
57 #include "UI_view2d.h"
58 #include "UI_resources.h"
59
60 #include "ED_anim_api.h"
61 #include "ED_markers.h"
62 #include "ED_screen.h"
63 #include "ED_util.h"
64 #include "ED_numinput.h"
65 #include "ED_object.h"
66 #include "ED_types.h"
67
68 /* ************* Marker API **************** */
69
70 /* helper function for getting the list of markers to work on */
71 static ListBase *context_get_markers(Scene *scene, ScrArea *sa)
72 {
73         /* local marker sets... */
74         if (sa) {
75                 if (sa->spacetype == SPACE_ACTION) {
76                         SpaceAction *saction = (SpaceAction *)sa->spacedata.first;
77                         
78                         /* local markers can only be shown when there's only a single active action to grab them from 
79                          *      - flag only takes effect when there's an action, otherwise it can get too confusing?
80                          */
81                         if (ELEM(saction->mode, SACTCONT_ACTION, SACTCONT_SHAPEKEY) && (saction->action)) 
82                         {
83                                 if (saction->flag & SACTION_POSEMARKERS_SHOW)
84                                         return &saction->action->markers;
85                         }
86                 }
87         }
88         
89         /* default to using the scene's markers */
90         return &scene->markers;
91 }
92
93 /* ............. */
94
95 /* public API for getting markers from context */
96 ListBase *ED_context_get_markers(const bContext *C)
97 {
98         return context_get_markers(CTX_data_scene(C), CTX_wm_area(C));
99 }
100
101 /* public API for getting markers from "animation" context */
102 ListBase *ED_animcontext_get_markers(const bAnimContext *ac)
103 {
104         if (ac)
105                 return context_get_markers(ac->scene, ac->sa);
106         else
107                 return NULL;
108 }
109
110 /* --------------------------------- */
111
112 /* Get the marker that is closest to this point */
113 /* XXX for select, the min_dist should be small */
114 TimeMarker *ED_markers_find_nearest_marker (ListBase *markers, float x) 
115 {
116         TimeMarker *marker, *nearest=NULL;
117         float dist, min_dist= 1000000;
118         
119         if (markers) {
120                 for (marker= markers->first; marker; marker= marker->next) {
121                         dist = ABS((float)marker->frame - x);
122                         
123                         if (dist < min_dist) {
124                                 min_dist= dist;
125                                 nearest= marker;
126                         }
127                 }
128         }
129         
130         return nearest;
131 }
132
133 /* Return the time of the marker that occurs on a frame closest to the given time */
134 int ED_markers_find_nearest_marker_time (ListBase *markers, float x)
135 {
136         TimeMarker *nearest= ED_markers_find_nearest_marker(markers, x);
137         return (nearest) ? (nearest->frame) : (int)floor(x + 0.5f);
138 }
139
140
141 void ED_markers_get_minmax (ListBase *markers, short sel, float *first, float *last)
142 {
143         TimeMarker *marker;
144         float min, max;
145         int selcount = 0;
146         
147         /* sanity check */
148         //printf("markers = %p -  %p, %p \n", markers, markers->first, markers->last);
149         if (markers == NULL) {
150                 *first = 0.0f;
151                 *last = 0.0f;
152                 return;
153         }
154         
155         if (markers->first && markers->last) {
156                 TimeMarker *fm= markers->first;
157                 TimeMarker *lm= markers->last;
158                 
159                 min= (float)fm->frame;
160                 max= (float)lm->frame;
161         }
162         else {
163                 *first = 0.0f;
164                 *last = 0.0f;
165                 return;
166         }
167         
168         /* count how many markers are usable - see later */
169         if (sel) {
170                 for (marker= markers->first; marker; marker= marker->next) {
171                         if (marker->flag & SELECT)
172                                 selcount++;
173                 }
174         }
175         else
176                 selcount= BLI_countlist(markers);
177         
178         /* if only selected are to be considered, only consider the selected ones
179          * (optimisation for not searching list) 
180          */
181         if (selcount > 1) {
182                 for (marker= markers->first; marker; marker= marker->next) {
183                         if (sel) {
184                                 if (marker->flag & SELECT) {
185                                         if (marker->frame < min)
186                                                 min= (float)marker->frame;
187                                         if (marker->frame > max)
188                                                 max= (float)marker->frame;
189                                 }
190                         }
191                         else {
192                                 if (marker->frame < min)
193                                         min= (float)marker->frame;
194                                 if (marker->frame > max)
195                                         max= (float)marker->frame;
196                         }       
197                 }
198         }
199         
200         /* set the min/max values */
201         *first= min;
202         *last= max;
203 }
204
205 /* --------------------------------- */
206
207 /* Adds a marker to list of cfra elems */
208 void add_marker_to_cfra_elem(ListBase *lb, TimeMarker *marker, short only_sel)
209 {
210         CfraElem *ce, *cen;
211         
212         /* should this one only be considered if it is selected? */
213         if ((only_sel) && ((marker->flag & SELECT)==0))
214                 return;
215         
216         /* insertion sort - try to find a previous cfra elem */
217         for (ce= lb->first; ce; ce= ce->next) {
218                 if (ce->cfra == marker->frame) {
219                         /* do because of double keys */
220                         if (marker->flag & SELECT) 
221                                 ce->sel= marker->flag;
222                         return;
223                 }
224                 else if (ce->cfra > marker->frame) break;
225         }       
226         
227         cen= MEM_callocN(sizeof(CfraElem), "add_to_cfra_elem"); 
228         if (ce) BLI_insertlinkbefore(lb, ce, cen);
229         else BLI_addtail(lb, cen);
230
231         cen->cfra= marker->frame;
232         cen->sel= marker->flag;
233 }
234
235 /* This function makes a list of all the markers. The only_sel
236  * argument is used to specify whether only the selected markers
237  * are added.
238  */
239 void ED_markers_make_cfra_list(ListBase *markers, ListBase *lb, short only_sel)
240 {
241         TimeMarker *marker;
242         
243         if (markers == NULL)
244                 return;
245         
246         for (marker= markers->first; marker; marker= marker->next)
247                 add_marker_to_cfra_elem(lb, marker, only_sel);
248 }
249
250 /* --------------------------------- */
251
252 /* Get the first selected marker */
253 TimeMarker *ED_markers_get_first_selected(ListBase *markers)
254 {
255         TimeMarker *marker;
256         
257         if (markers) {
258                 for (marker = markers->first; marker; marker = marker->next) {
259                         if (marker->flag & SELECT)
260                                 return marker;
261                 }
262         }
263         
264         return NULL;
265 }
266
267 /* ************* Marker Drawing ************ */
268
269 /* function to draw markers */
270 static void draw_marker(View2D *v2d, TimeMarker *marker, int cfra, int flag)
271 {
272         float xpos, ypixels, xscale, yscale;
273         int icon_id= 0;
274         
275         xpos = marker->frame;
276         
277         /* no time correction for framelen! space is drawn with old values */
278         ypixels= v2d->mask.ymax-v2d->mask.ymin;
279         UI_view2d_getscale(v2d, &xscale, &yscale);
280         
281         glScalef(1.0f/xscale, 1.0f, 1.0f);
282         
283         glEnable(GL_BLEND);
284         glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);                      
285         
286         /* vertical line - dotted */
287 #ifdef DURIAN_CAMERA_SWITCH
288         if ((marker->camera) || (flag & DRAW_MARKERS_LINES))
289 #else
290         if (flag & DRAW_MARKERS_LINES)
291 #endif
292         {
293                 setlinestyle(3);
294                 
295                 if (marker->flag & SELECT)
296                         glColor4ub(255, 255, 255, 96);
297                 else
298                         glColor4ub(0, 0, 0, 96);
299                 
300                 glBegin(GL_LINES);
301                         glVertex2f((xpos*xscale)+0.5f, 12.0f);
302                         glVertex2f((xpos*xscale)+0.5f, (v2d->cur.ymax+12.0f)*yscale);
303                 glEnd();
304                 
305                 setlinestyle(0);
306         }
307         
308         /* 5 px to offset icon to align properly, space / pixels corrects for zoom */
309         if (flag & DRAW_MARKERS_LOCAL) {
310                 icon_id= (marker->flag & ACTIVE) ? ICON_PMARKER_ACT : 
311                 (marker->flag & SELECT) ? ICON_PMARKER_SEL : 
312                 ICON_PMARKER;
313         }
314         else {
315                 icon_id= (marker->flag & SELECT) ? ICON_MARKER_HLT : 
316                 ICON_MARKER;
317         }
318         
319         UI_icon_draw(xpos*xscale-5.0f, 16.0f, icon_id);
320         
321         glBlendFunc(GL_ONE, GL_ZERO);
322         glDisable(GL_BLEND);
323         
324         /* and the marker name too, shifted slightly to the top-right */
325         if (marker->name && marker->name[0]) {
326                 float x, y;
327                 
328                 if (marker->flag & SELECT) {
329                         UI_ThemeColor(TH_TEXT_HI);
330                         x= xpos*xscale + 4.0f;
331                         y= (ypixels <= 39.0f)? (ypixels-10.0f) : 29.0f;
332                 }
333                 else {
334                         UI_ThemeColor(TH_TEXT);
335                         if((marker->frame <= cfra) && (marker->frame+5 > cfra)) {
336                                 x= xpos*xscale + 4.0f;
337                                 y= (ypixels <= 39.0f)? (ypixels - 10.0f) : 29.0f;
338                         }
339                         else {
340                                 x= xpos*xscale + 4.0f;
341                                 y= 17.0f;
342                         }
343                 }
344
345 #ifdef DURIAN_CAMERA_SWITCH
346                 if(marker->camera && marker->camera->restrictflag & OB_RESTRICT_RENDER) {
347                         float col[4];
348                         glGetFloatv(GL_CURRENT_COLOR, col);
349                         col[3]= 0.4;
350                         glColor4fv(col);
351                 }
352 #endif
353
354                 UI_DrawString(x, y, marker->name);
355         }
356         
357         glScalef(xscale, 1.0f, 1.0f);
358 }
359
360 /* Draw Scene-Markers in time window */
361 void draw_markers_time(const bContext *C, int flag)
362 {
363         ListBase *markers= ED_context_get_markers(C);
364         View2D *v2d= UI_view2d_fromcontext(C);
365         TimeMarker *marker;
366         
367         if (markers == NULL)
368                 return;
369         
370         /* unselected markers are drawn at the first time */
371         for (marker= markers->first; marker; marker= marker->next) {
372                 if ((marker->flag & SELECT) == 0) 
373                         draw_marker(v2d, marker, CTX_data_scene(C)->r.cfra, flag);
374         }
375         
376         /* selected markers are drawn later */
377         for (marker= markers->first; marker; marker= marker->next) {
378                 if (marker->flag & SELECT) 
379                         draw_marker(v2d, marker, CTX_data_scene(C)->r.cfra, flag);
380         }
381 }
382
383 /* ************************ Marker Wrappers API ********************* */
384 /* These wrappers allow marker operators to function within the confines 
385  * of standard animation editors, such that they can coexist with the 
386  * primary operations of those editors.
387  */
388
389 /* maximum y-axis value (in region screen-space) that marker events should still be accepted for  */
390 #define ANIMEDIT_MARKER_YAXIS_MAX       40
391
392 /* ------------------------ */
393
394 /* special poll() which checks if there are selected markers first */
395 static int ed_markers_poll_selected_markers(bContext *C)
396 {
397         ListBase *markers = ED_context_get_markers(C);
398         
399         /* first things first: markers can only exist in timeline views */
400         if (ED_operator_animview_active(C) == 0)
401                 return 0;
402                 
403         /* check if some marker is selected */
404         return ED_markers_get_first_selected(markers) != NULL;
405 }
406  
407 /* ------------------------ */ 
408
409 /* Second-tier invoke() callback that performs context validation before running the  
410  * "custom"/third-tier invoke() callback supplied as the last arg (which would normally
411  * be the operator's invoke() callback elsewhere)
412  *
413  * < invoke_func: (fn(bContext*, wmOperator*, wmEvent*)=int) "standard" invoke function 
414  *                      that operator would otherwise have used. If NULL, the operator's standard
415  *                      exec() callback will be called instead in the appropriate places.
416  */
417 static int ed_markers_opwrap_invoke_custom(bContext *C, wmOperator *op, wmEvent *evt, 
418                 int (*invoke_func)(bContext*,wmOperator*,wmEvent*))
419 {
420         ScrArea *sa = CTX_wm_area(C);
421         int retval = OPERATOR_PASS_THROUGH;
422         
423         /* only timeline view doesn't need calling-location validation as it's the only dedicated view */
424         if (sa->spacetype != SPACE_TIME) {
425                 /* restrict y-values to within ANIMEDIT_MARKER_YAXIS_MAX of the view's vertical extents, including scrollbars */
426                 if (evt->mval[1] > ANIMEDIT_MARKER_YAXIS_MAX) {
427                         /* not ok... "pass-through" to let normal editor's operators have a chance at tackling this event... */
428                         //printf("MARKER-WRAPPER-DEBUG: event mval[1] = %d, so over accepted tolerance\n", evt->mval[1]);
429                         return OPERATOR_CANCELLED|OPERATOR_PASS_THROUGH;
430                 }
431         }
432         
433         /* allow operator to run now */
434         if (invoke_func)
435                 retval = invoke_func(C, op, evt);
436         else if (op->type->exec)
437                 retval = op->type->exec(C, op);
438         else
439                 BKE_report(op->reports, RPT_ERROR, "Programming error: operator doesn't actually have code to do anything!");
440                 
441         /* return status modifications - for now, make this spacetype dependent as above */
442         if (sa->spacetype != SPACE_TIME) {
443                 /* unless successful, must add "pass-through" to let normal operator's have a chance at tackling this event */
444                 if (retval != OPERATOR_FINISHED)
445                         retval |= OPERATOR_PASS_THROUGH;
446         }
447         
448         return retval;
449 }
450
451 /* standard wrapper - first-tier invoke() callback to be directly assigned to operator typedata
452  * for operators which don't need any special invoke calls. Any operators with special invoke calls
453  * though will need to implement their own wrapper which calls the second-tier callback themselves
454  * (passing through the custom invoke function they use)
455  */
456 static int ed_markers_opwrap_invoke(bContext *C, wmOperator *op, wmEvent *evt)
457 {
458         return ed_markers_opwrap_invoke_custom(C, op, evt, NULL);
459 }
460
461 /* ************************** add markers *************************** */
462
463 /* add TimeMarker at curent frame */
464 static int ed_marker_add(bContext *C, wmOperator *UNUSED(op))
465 {
466         ListBase *markers= ED_context_get_markers(C);
467         TimeMarker *marker;
468         int frame= CTX_data_scene(C)->r.cfra;
469         
470         if (markers == NULL)
471                 return OPERATOR_CANCELLED;
472         
473         /* two markers can't be at the same place */
474         for (marker= markers->first; marker; marker= marker->next) {
475                 if (marker->frame == frame) 
476                         return OPERATOR_CANCELLED;
477         }
478         
479         /* deselect all */
480         for (marker= markers->first; marker; marker= marker->next)
481                 marker->flag &= ~SELECT;
482         
483         marker = MEM_callocN(sizeof(TimeMarker), "TimeMarker");
484         marker->flag= SELECT;
485         marker->frame= frame;
486         sprintf(marker->name, "F_%02d", frame); // XXX - temp code only
487         BLI_addtail(markers, marker);
488         
489         WM_event_add_notifier(C, NC_SCENE|ND_MARKERS, NULL);
490         WM_event_add_notifier(C, NC_ANIMATION|ND_MARKERS, NULL);
491         
492         return OPERATOR_FINISHED;
493 }
494
495 static void MARKER_OT_add(wmOperatorType *ot)
496 {
497         /* identifiers */
498         ot->name= "Add Time Marker";
499         ot->description= "Add a new time marker";
500         ot->idname= "MARKER_OT_add";
501         
502         /* api callbacks */
503         ot->exec= ed_marker_add;
504         ot->invoke = ed_markers_opwrap_invoke;
505         ot->poll= ED_operator_animview_active;
506         
507         /* flags */
508         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
509 }
510
511 /* ************************** transform markers *************************** */
512
513
514 /* operator state vars used:  
515         frs: delta movement
516
517 functions:
518
519         init()   check selection, add customdata with old values and some lookups
520
521         apply()  do the actual movement
522
523         exit()  cleanup, send notifier
524
525         cancel() to escape from modal
526
527 callbacks:
528
529         exec()  calls init, apply, exit 
530
531         invoke() calls init, adds modal handler
532
533         modal() accept modal events while doing it, ends with apply and exit, or cancel
534
535 */
536
537 typedef struct MarkerMove {
538         SpaceLink *slink;
539         ListBase *markers;
540         int event_type;         /* store invoke-event, to verify */
541         int *oldframe, evtx, firstx;
542         NumInput num;
543 } MarkerMove;
544
545 /* copy selection to temp buffer */
546 /* return 0 if not OK */
547 static int ed_marker_move_init(bContext *C, wmOperator *op)
548 {
549         ListBase *markers= ED_context_get_markers(C);
550         MarkerMove *mm;
551         TimeMarker *marker;
552         int totmark=0;
553         int a;
554
555         if(markers == NULL) return 0;
556         
557         for (marker= markers->first; marker; marker= marker->next)
558                 if (marker->flag & SELECT) totmark++;
559         
560         if (totmark==0) return 0;
561         
562         op->customdata= mm= MEM_callocN(sizeof(MarkerMove), "Markermove");
563         mm->slink= CTX_wm_space_data(C);
564         mm->markers= markers;
565         mm->oldframe= MEM_callocN(totmark*sizeof(int), "MarkerMove oldframe");
566
567         initNumInput(&mm->num);
568         mm->num.idx_max = 0; /* one axis */
569         mm->num.flag |= NUM_NO_FRACTION;
570         mm->num.increment = 1.0f;
571         
572         for (a=0, marker= markers->first; marker; marker= marker->next) {
573                 if (marker->flag & SELECT) {
574                         mm->oldframe[a]= marker->frame;
575                         a++;
576                 }
577         }
578         
579         return 1;
580 }
581
582 /* free stuff */
583 static void ed_marker_move_exit(bContext *C, wmOperator *op)
584 {
585         MarkerMove *mm= op->customdata;
586         
587         /* free data */
588         MEM_freeN(mm->oldframe);
589         MEM_freeN(op->customdata);
590         op->customdata= NULL;
591         
592         /* clear custom header prints */
593         ED_area_headerprint(CTX_wm_area(C), NULL);
594 }
595
596 static int ed_marker_move_invoke(bContext *C, wmOperator *op, wmEvent *evt)
597 {
598         if(ed_marker_move_init(C, op)) {
599                 MarkerMove *mm= op->customdata;
600                 
601                 mm->evtx= evt->x;
602                 mm->firstx= evt->x;
603                 mm->event_type= evt->type;
604                 
605                 /* add temp handler */
606                 WM_event_add_modal_handler(C, op);
607                 
608                 /* reset frs delta */
609                 RNA_int_set(op->ptr, "frames", 0);
610                 
611                 return OPERATOR_RUNNING_MODAL;
612         }
613         
614         return OPERATOR_CANCELLED;
615 }
616
617 static int ed_marker_move_invoke_wrapper(bContext *C, wmOperator *op, wmEvent *evt)
618 {
619         return ed_markers_opwrap_invoke_custom(C, op, evt, ed_marker_move_invoke);
620 }
621
622 /* note, init has to be called succesfully */
623 static void ed_marker_move_apply(wmOperator *op)
624 {
625         MarkerMove *mm= op->customdata;
626         TimeMarker *marker;
627         int a, offs;
628         
629         offs= RNA_int_get(op->ptr, "frames");
630         for (a=0, marker= mm->markers->first; marker; marker= marker->next) {
631                 if (marker->flag & SELECT) {
632                         marker->frame= mm->oldframe[a] + offs;
633                         a++;
634                 }
635         }
636 }
637
638 /* only for modal */
639 static void ed_marker_move_cancel(bContext *C, wmOperator *op)
640 {
641         RNA_int_set(op->ptr, "frames", 0);
642         ed_marker_move_apply(op);
643         ed_marker_move_exit(C, op);     
644         
645         WM_event_add_notifier(C, NC_SCENE|ND_MARKERS, NULL);
646         WM_event_add_notifier(C, NC_ANIMATION|ND_MARKERS, NULL);
647 }
648
649
650
651 static int ed_marker_move_modal(bContext *C, wmOperator *op, wmEvent *evt)
652 {
653         Scene *scene= CTX_data_scene(C);
654         MarkerMove *mm= op->customdata;
655         View2D *v2d= UI_view2d_fromcontext(C);
656         TimeMarker *marker, *selmarker=NULL;
657         float dx, fac;
658         char str[256];
659                 
660         switch(evt->type) {
661                 case ESCKEY:
662                         ed_marker_move_cancel(C, op);
663                         return OPERATOR_CANCELLED;
664                 
665                 case RETKEY:
666                 case PADENTER:
667                 case LEFTMOUSE:
668                 case MIDDLEMOUSE:
669                 case RIGHTMOUSE:
670                         if (WM_modal_tweak_exit(evt, mm->event_type)) {
671                                 ed_marker_move_exit(C, op);
672                                 WM_event_add_notifier(C, NC_SCENE|ND_MARKERS, NULL);
673                                 WM_event_add_notifier(C, NC_ANIMATION|ND_MARKERS, NULL);
674                                 return OPERATOR_FINISHED;
675                         }
676                         
677                         break;
678                 case MOUSEMOVE:
679                         if (hasNumInput(&mm->num))
680                                 break;
681                         
682                         dx= v2d->mask.xmax-v2d->mask.xmin;
683                         dx= (v2d->cur.xmax-v2d->cur.xmin)/dx;
684                         
685                         if (evt->x != mm->evtx) {       /* XXX maybe init for firsttime */
686                                 int a, offs, totmark=0;
687                                 
688                                 mm->evtx= evt->x;
689                                 
690                                 fac= ((float)(evt->x - mm->firstx)*dx);
691                                 
692                                 if (ELEM(mm->slink->spacetype, SPACE_TIME, SPACE_SOUND)) 
693                                         apply_keyb_grid(evt->shift, evt->ctrl, &fac, 0.0, FPS, 0.1*FPS, 0);
694                                 else
695                                         apply_keyb_grid(evt->shift, evt->ctrl, &fac, 0.0, 1.0, 0.1, 0 /*was: U.flag & USER_AUTOGRABGRID*/);
696                                 
697                                 offs= (int)fac;
698                                 RNA_int_set(op->ptr, "frames", offs);
699                                 ed_marker_move_apply(op);
700                                 
701                                 /* cruft below is for header print */
702                                 for (a=0, marker= mm->markers->first; marker; marker= marker->next) {
703                                         if (marker->flag & SELECT) {
704                                                 selmarker= marker;
705                                                 a++; totmark++;
706                                         }
707                                 }
708                                 
709                                 if (totmark==1) {       
710                                         /* we print current marker value */
711                                         if (ELEM(mm->slink->spacetype, SPACE_TIME, SPACE_SOUND)) {
712                                                 SpaceTime *stime= (SpaceTime *)mm->slink;
713                                                 if (stime->flag & TIME_DRAWFRAMES) 
714                                                         sprintf(str, "Marker %d offset %d", selmarker->frame, offs);
715                                                 else 
716                                                         sprintf(str, "Marker %.2f offset %.2f", FRA2TIME(selmarker->frame), FRA2TIME(offs));
717                                         }
718                                         else if (mm->slink->spacetype == SPACE_ACTION) {
719                                                 SpaceAction *saction= (SpaceAction *)mm->slink;
720                                                 if (saction->flag & SACTION_DRAWTIME)
721                                                         sprintf(str, "Marker %.2f offset %.2f", FRA2TIME(selmarker->frame), FRA2TIME(offs));
722                                                 else
723                                                         sprintf(str, "Marker %.2f offset %.2f", (double)(selmarker->frame), (double)(offs));
724                                         }
725                                         else {
726                                                 sprintf(str, "Marker %.2f offset %.2f", (double)(selmarker->frame), (double)(offs));
727                                         }
728                                 }
729                                 else {
730                                         /* we only print the offset */
731                                         if (ELEM(mm->slink->spacetype, SPACE_TIME, SPACE_SOUND)) { 
732                                                 SpaceTime *stime= (SpaceTime *)mm->slink;
733                                                 if (stime->flag & TIME_DRAWFRAMES) 
734                                                         sprintf(str, "Marker offset %d ", offs);
735                                                 else 
736                                                         sprintf(str, "Marker offset %.2f ", FRA2TIME(offs));
737                                         }
738                                         else if (mm->slink->spacetype == SPACE_ACTION) {
739                                                 SpaceAction *saction= (SpaceAction *)mm->slink;
740                                                 if (saction->flag & SACTION_DRAWTIME)
741                                                         sprintf(str, "Marker offset %.2f ", FRA2TIME(offs));
742                                                 else
743                                                         sprintf(str, "Marker offset %.2f ", (double)(offs));
744                                         }
745                                         else {
746                                                 sprintf(str, "Marker offset %.2f ", (double)(offs));
747                                         }
748                                 }
749                                 
750                                 WM_event_add_notifier(C, NC_SCENE|ND_MARKERS, NULL);
751                                 WM_event_add_notifier(C, NC_ANIMATION|ND_MARKERS, NULL);
752                                 ED_area_headerprint(CTX_wm_area(C), str);
753                         }
754         }
755
756         if (evt->val==KM_PRESS) {
757                 float vec[3];
758                 char str_tx[256];
759                 
760                 if (handleNumInput(&mm->num, evt))
761                 {
762                         applyNumInput(&mm->num, vec);
763                         outputNumInput(&mm->num, str_tx);
764                         
765                         RNA_int_set(op->ptr, "frames", vec[0]);
766                         ed_marker_move_apply(op);
767                         // ed_marker_header_update(C, op, str, (int)vec[0]);
768                         // strcat(str, str_tx);
769                         sprintf(str, "Marker offset %s", str_tx);
770                         ED_area_headerprint(CTX_wm_area(C), str);
771                         
772                         WM_event_add_notifier(C, NC_SCENE|ND_MARKERS, NULL);
773                         WM_event_add_notifier(C, NC_ANIMATION|ND_MARKERS, NULL);
774                 }
775         }
776
777         return OPERATOR_RUNNING_MODAL;
778 }
779
780 static int ed_marker_move_exec(bContext *C, wmOperator *op)
781 {
782         if(ed_marker_move_init(C, op)) {
783                 ed_marker_move_apply(op);
784                 ed_marker_move_exit(C, op);
785                 return OPERATOR_FINISHED;
786         }
787         return OPERATOR_PASS_THROUGH;
788 }
789
790 static void MARKER_OT_move(wmOperatorType *ot)
791 {
792         /* identifiers */
793         ot->name= "Move Time Marker";
794         ot->description= "Move selected time marker(s)";
795         ot->idname= "MARKER_OT_move";
796         
797         /* api callbacks */
798         ot->exec= ed_marker_move_exec;
799         ot->invoke= ed_marker_move_invoke_wrapper;
800         ot->modal= ed_marker_move_modal;
801         ot->poll= ed_markers_poll_selected_markers;
802         
803         /* flags */
804         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO|OPTYPE_BLOCKING|OPTYPE_GRAB_POINTER;
805         
806         /* rna storage */
807         RNA_def_int(ot->srna, "frames", 0, INT_MIN, INT_MAX, "Frames", "", INT_MIN, INT_MAX);
808 }
809
810 /* ************************** duplicate markers *************************** */
811
812 /* operator state vars used:  
813         frs: delta movement
814
815 functions:
816
817         apply()  do the actual duplicate
818
819 callbacks:
820
821         exec()  calls apply, move_exec
822
823         invoke() calls apply, move_invoke
824
825         modal() uses move_modal
826
827 */
828
829
830 /* duplicate selected TimeMarkers */
831 static void ed_marker_duplicate_apply(bContext *C)
832 {
833         ListBase *markers= ED_context_get_markers(C);
834         TimeMarker *marker, *newmarker;
835         
836         if (markers == NULL) 
837                 return;
838
839         /* go through the list of markers, duplicate selected markers and add duplicated copies
840          * to the begining of the list (unselect original markers) 
841          */
842         for (marker= markers->first; marker; marker= marker->next) {
843                 if (marker->flag & SELECT) {
844                         /* unselect selected marker */
845                         marker->flag &= ~SELECT;
846                         
847                         /* create and set up new marker */
848                         newmarker = MEM_callocN(sizeof(TimeMarker), "TimeMarker");
849                         newmarker->flag= SELECT;
850                         newmarker->frame= marker->frame;
851                         BLI_strncpy(newmarker->name, marker->name, sizeof(marker->name));
852                         
853 #ifdef DURIAN_CAMERA_SWITCH
854                         newmarker->camera= marker->camera;
855 #endif
856
857                         /* new marker is added to the begining of list */
858                         BLI_addhead(markers, newmarker);
859                 }
860         }
861 }
862
863 static int ed_marker_duplicate_exec(bContext *C, wmOperator *op)
864 {
865         ed_marker_duplicate_apply(C);
866         ed_marker_move_exec(C, op);     /* assumes frs delta set */
867         
868         return OPERATOR_FINISHED;
869         
870 }
871
872 static int ed_marker_duplicate_invoke(bContext *C, wmOperator *op, wmEvent *evt)
873 {
874         ed_marker_duplicate_apply(C);
875         return ed_marker_move_invoke(C, op, evt);
876 }
877
878 static int ed_marker_duplicate_invoke_wrapper(bContext *C, wmOperator *op, wmEvent *evt)
879 {
880         return ed_markers_opwrap_invoke_custom(C, op, evt, ed_marker_duplicate_invoke);
881 }
882
883 static void MARKER_OT_duplicate(wmOperatorType *ot)
884 {
885         /* identifiers */
886         ot->name= "Duplicate Time Marker";
887         ot->description= "Duplicate selected time marker(s)";
888         ot->idname= "MARKER_OT_duplicate";
889         
890         /* api callbacks */
891         ot->exec= ed_marker_duplicate_exec;
892         ot->invoke= ed_marker_duplicate_invoke_wrapper;
893         ot->modal= ed_marker_move_modal;
894         ot->poll= ed_markers_poll_selected_markers;
895         
896         /* flags */
897         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
898         
899         /* rna storage */
900         RNA_def_int(ot->srna, "frames", 0, INT_MIN, INT_MAX, "Frames", "", INT_MIN, INT_MAX);
901 }
902
903 /* ************************** selection ************************************/
904
905 /* select/deselect TimeMarker at current frame */
906 static void select_timeline_marker_frame(ListBase *markers, int frame, unsigned char shift)
907 {
908         TimeMarker *marker;
909         int select=0;
910         
911         for (marker= markers->first; marker; marker= marker->next) {
912                 /* if Shift is not set, then deselect Markers */
913                 if (!shift) marker->flag &= ~SELECT;
914                 
915                 /* this way a not-shift select will allways give 1 selected marker */
916                 if ((marker->frame == frame) && (!select)) {
917                         if (marker->flag & SELECT) 
918                                 marker->flag &= ~SELECT;
919                         else
920                                 marker->flag |= SELECT;
921                         select = 1;
922                 }
923         }
924 }
925
926 static int ed_marker_select(bContext *C, wmEvent *evt, int extend, int camera)
927 {
928         ListBase *markers= ED_context_get_markers(C);
929         View2D *v2d= UI_view2d_fromcontext(C);
930         float viewx;
931         int x, y, cfra;
932         
933         if (markers == NULL)
934                 return OPERATOR_PASS_THROUGH;
935
936         x= evt->x - CTX_wm_region(C)->winrct.xmin;
937         y= evt->y - CTX_wm_region(C)->winrct.ymin;
938         
939         UI_view2d_region_to_view(v2d, x, y, &viewx, NULL);      
940         
941         cfra= ED_markers_find_nearest_marker_time(markers, viewx);
942         
943         if (extend)
944                 select_timeline_marker_frame(markers, cfra, 1);
945         else
946                 select_timeline_marker_frame(markers, cfra, 0);
947         
948 #ifdef DURIAN_CAMERA_SWITCH
949
950         if (camera) {
951                 Scene *scene= CTX_data_scene(C);
952                 Base *base;
953                 TimeMarker *marker;
954                 int sel= 0;
955                 
956                 if (!extend)
957                         scene_deselect_all(scene);
958                 
959                 for (marker= markers->first; marker; marker= marker->next) {
960                         if(marker->frame==cfra) {
961                                 sel= (marker->flag & SELECT);
962                                 break;
963                         }
964                 }
965                 
966                 for (marker= markers->first; marker; marker= marker->next) {
967                         if (marker->camera) {
968                                 if (marker->frame==cfra) {
969                                         base= object_in_scene(marker->camera, scene);
970                                         if (base) {
971                                                 ED_base_object_select(base, sel);
972                                                 if(sel)
973                                                         ED_base_object_activate(C, base);
974                                         }
975                                 }
976                         }
977                 }
978                 
979                 WM_event_add_notifier(C, NC_SCENE|ND_OB_SELECT, scene);
980         }
981 #endif
982
983         WM_event_add_notifier(C, NC_SCENE|ND_MARKERS, NULL);
984         WM_event_add_notifier(C, NC_ANIMATION|ND_MARKERS, NULL);
985
986         /* allowing tweaks */
987         return OPERATOR_PASS_THROUGH;
988 }
989
990 static int ed_marker_select_invoke(bContext *C, wmOperator *op, wmEvent *evt)
991 {
992         short extend= RNA_boolean_get(op->ptr, "extend");
993         short camera= 0;
994 #ifdef DURIAN_CAMERA_SWITCH
995         camera= RNA_boolean_get(op->ptr, "camera");
996 #endif
997         return ed_marker_select(C, evt, extend, camera);
998 }
999
1000 static int ed_marker_select_invoke_wrapper(bContext *C, wmOperator *op, wmEvent *evt)
1001 {
1002         return ed_markers_opwrap_invoke_custom(C, op, evt, ed_marker_select_invoke);
1003 }
1004
1005 static void MARKER_OT_select(wmOperatorType *ot)
1006 {
1007         /* identifiers */
1008         ot->name= "Select Time Marker";
1009         ot->description= "Select time marker(s)";
1010         ot->idname= "MARKER_OT_select";
1011         
1012         /* api callbacks */
1013         ot->invoke= ed_marker_select_invoke_wrapper;
1014         ot->poll= ED_operator_animview_active;
1015         
1016         /* flags */
1017         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
1018
1019         RNA_def_boolean(ot->srna, "extend", 0, "Extend", "extend the selection");
1020 #ifdef DURIAN_CAMERA_SWITCH
1021         RNA_def_boolean(ot->srna, "camera", 0, "Camera", "Select the camera");
1022 #endif
1023 }
1024
1025 /* *************************** border select markers **************** */
1026
1027 /* operator state vars used: (added by default WM callbacks)   
1028         xmin, ymin     
1029         xmax, ymax     
1030
1031 customdata: the wmGesture pointer, with subwindow
1032
1033 callbacks:
1034
1035         exec()  has to be filled in by user
1036
1037         invoke() default WM function
1038                         adds modal handler
1039
1040         modal() default WM function 
1041                         accept modal events while doing it, calls exec(), handles ESC and border drawing
1042
1043         poll()  has to be filled in by user for context
1044 */
1045
1046 static int ed_marker_border_select_exec(bContext *C, wmOperator *op)
1047 {
1048         View2D *v2d= UI_view2d_fromcontext(C);
1049         ListBase *markers= ED_context_get_markers(C);
1050         TimeMarker *marker;
1051         float xminf, xmaxf, yminf, ymaxf;
1052         int gesture_mode= RNA_int_get(op->ptr, "gesture_mode");
1053         int xmin= RNA_int_get(op->ptr, "xmin");
1054         int xmax= RNA_int_get(op->ptr, "xmax");
1055         int ymin= RNA_int_get(op->ptr, "ymin");
1056         int ymax= RNA_int_get(op->ptr, "ymax");
1057         
1058         UI_view2d_region_to_view(v2d, xmin, ymin, &xminf, &yminf);      
1059         UI_view2d_region_to_view(v2d, xmax, ymax, &xmaxf, &ymaxf);      
1060         
1061         if (markers == NULL)
1062                 return 0;
1063         
1064         /* XXX marker context */
1065         for (marker= markers->first; marker; marker= marker->next) {
1066                 if ((marker->frame > xminf) && (marker->frame <= xmaxf)) {
1067                         switch (gesture_mode) {
1068                                 case GESTURE_MODAL_SELECT:
1069                                         marker->flag |= SELECT;
1070                                         break;
1071                                 case GESTURE_MODAL_DESELECT:
1072                                         marker->flag &= ~SELECT;
1073                                         break;
1074                         }
1075                 }
1076         }
1077         
1078         WM_event_add_notifier(C, NC_SCENE|ND_MARKERS, NULL);
1079         WM_event_add_notifier(C, NC_ANIMATION|ND_MARKERS, NULL);
1080
1081         return 1;
1082 }
1083
1084 static int ed_marker_select_border_invoke_wrapper(bContext *C, wmOperator *op, wmEvent *evt)
1085 {
1086         return ed_markers_opwrap_invoke_custom(C, op, evt, WM_border_select_invoke);
1087 }
1088
1089 static void MARKER_OT_select_border(wmOperatorType *ot)
1090 {
1091         /* identifiers */
1092         ot->name= "Marker Border select";
1093         ot->description= "Select all time markers using border selection";
1094         ot->idname= "MARKER_OT_select_border";
1095         
1096         /* api callbacks */
1097         ot->exec= ed_marker_border_select_exec;
1098         ot->invoke= ed_marker_select_border_invoke_wrapper;
1099         ot->modal= WM_border_select_modal;
1100         
1101         ot->poll= ED_operator_animview_active;
1102         
1103         /* flags */
1104         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
1105         
1106         /* rna */
1107         WM_operator_properties_gesture_border(ot, FALSE);
1108 }
1109
1110 /* *********************** (de)select all ***************** */
1111
1112 static int ed_marker_select_all_exec(bContext *C, wmOperator *op)
1113 {
1114         ListBase *markers= ED_context_get_markers(C);
1115         TimeMarker *marker;
1116         int action = RNA_enum_get(op->ptr, "action");
1117
1118         if (markers == NULL)
1119                 return OPERATOR_CANCELLED;
1120
1121         if (action == SEL_TOGGLE) {
1122                 action = (ED_markers_get_first_selected(markers) != NULL) ? SEL_DESELECT : SEL_SELECT;
1123         }
1124         
1125         for(marker= markers->first; marker; marker= marker->next) {
1126                 switch (action) {
1127                 case SEL_SELECT:
1128                         marker->flag |= SELECT;
1129                         break;
1130                 case SEL_DESELECT:
1131                         marker->flag &= ~SELECT;
1132                         break;
1133                 case SEL_INVERT:
1134                         marker->flag ^= SELECT;
1135                         break;
1136                 }
1137         }
1138         
1139         WM_event_add_notifier(C, NC_SCENE|ND_MARKERS, NULL);
1140         WM_event_add_notifier(C, NC_ANIMATION|ND_MARKERS, NULL);
1141
1142         return OPERATOR_FINISHED;
1143 }
1144
1145 static void MARKER_OT_select_all(wmOperatorType *ot)
1146 {
1147         /* identifiers */
1148         ot->name= "(De)select all markers";
1149         ot->description= "Change selection of all time markers";
1150         ot->idname= "MARKER_OT_select_all";
1151         
1152         /* api callbacks */
1153         ot->exec= ed_marker_select_all_exec;
1154         ot->invoke = ed_markers_opwrap_invoke;
1155         ot->poll= ED_operator_animview_active;
1156         
1157         /* flags */
1158         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
1159         
1160         /* rna */
1161         WM_operator_properties_select_all(ot);
1162 }
1163
1164 /* ***************** remove marker *********************** */
1165
1166 /* remove selected TimeMarkers */
1167 static int ed_marker_delete_exec(bContext *C, wmOperator *UNUSED(op))
1168 {
1169         ListBase *markers= ED_context_get_markers(C);
1170         TimeMarker *marker, *nmarker;
1171         short changed= 0;
1172         
1173         if (markers == NULL)
1174                 return OPERATOR_CANCELLED;
1175         
1176         for (marker= markers->first; marker; marker= nmarker) {
1177                 nmarker= marker->next;
1178                 if (marker->flag & SELECT) {
1179                         BLI_freelinkN(markers, marker);
1180                         changed= 1;
1181                 }
1182         }
1183         
1184         if (changed) {
1185                 WM_event_add_notifier(C, NC_SCENE|ND_MARKERS, NULL);
1186                 WM_event_add_notifier(C, NC_ANIMATION|ND_MARKERS, NULL);
1187         }
1188         
1189         return OPERATOR_FINISHED;
1190 }
1191
1192 static int ed_marker_delete_invoke_wrapper(bContext *C, wmOperator *op, wmEvent *evt)
1193 {
1194         // XXX: must we keep these confirmations?
1195         return ed_markers_opwrap_invoke_custom(C, op, evt, WM_operator_confirm);
1196 }
1197
1198 static void MARKER_OT_delete(wmOperatorType *ot)
1199 {
1200         /* identifiers */
1201         ot->name= "Delete Markers";
1202         ot->description= "Delete selected time marker(s)";
1203         ot->idname= "MARKER_OT_delete";
1204         
1205         /* api callbacks */
1206         ot->invoke= ed_marker_delete_invoke_wrapper;
1207         ot->exec= ed_marker_delete_exec;
1208         ot->poll= ed_markers_poll_selected_markers;
1209         
1210         /* flags */
1211         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;  
1212 }
1213
1214
1215 /* **************** rename marker ***************** */
1216
1217 /* rename first selected TimeMarker */
1218 static int ed_marker_rename_exec(bContext *C, wmOperator *op)
1219 {
1220         TimeMarker *marker= ED_markers_get_first_selected(ED_context_get_markers(C));
1221
1222         if(marker) {
1223                 RNA_string_get(op->ptr, "name", marker->name);
1224
1225                 WM_event_add_notifier(C, NC_SCENE|ND_MARKERS, NULL);
1226                 WM_event_add_notifier(C, NC_ANIMATION|ND_MARKERS, NULL);
1227
1228                 return OPERATOR_FINISHED;
1229         }
1230         else {
1231                 return OPERATOR_CANCELLED;
1232         }
1233 }
1234
1235 static int ed_marker_rename_invoke_wrapper(bContext *C, wmOperator *op, wmEvent *evt)
1236 {
1237         /* must initialise the marker name first if there is a marker selected */
1238         TimeMarker *marker = ED_markers_get_first_selected(ED_context_get_markers(C));
1239         if (marker)
1240                 RNA_string_set(op->ptr, "name", marker->name);
1241         
1242         /* now see if the operator is usable */
1243         return ed_markers_opwrap_invoke_custom(C, op, evt, WM_operator_props_popup);
1244 }
1245
1246 static void MARKER_OT_rename(wmOperatorType *ot)
1247 {
1248         /* identifiers */
1249         ot->name= "Rename Marker";
1250         ot->description= "Rename first selected time marker";
1251         ot->idname= "MARKER_OT_rename";
1252         
1253         /* api callbacks */
1254         ot->invoke= ed_marker_rename_invoke_wrapper;
1255         ot->exec= ed_marker_rename_exec;
1256         ot->poll= ed_markers_poll_selected_markers;
1257         
1258         /* flags */
1259         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;  
1260         
1261         /* properties */
1262         ot->prop = RNA_def_string(ot->srna, "name", "RenamedMarker", sizeof(((TimeMarker *)NULL)->name), "Name", "New name for marker");
1263         //RNA_def_boolean(ot->srna, "ensure_unique", 0, "Ensure Unique", "Ensure that new name is unique within collection of markers");
1264 }
1265
1266 /* **************** make links to scene ***************** */
1267
1268 static int ed_marker_make_links_scene_exec(bContext *C, wmOperator *op)
1269 {
1270         ListBase *markers= ED_context_get_markers(C);
1271         Scene *scene_to= BLI_findlink(&CTX_data_main(C)->scene, RNA_enum_get(op->ptr, "scene"));
1272         TimeMarker *marker, *marker_new;
1273
1274         if (scene_to==NULL) {
1275                 BKE_report(op->reports, RPT_ERROR, "Scene not found");
1276                 return OPERATOR_CANCELLED;
1277         }
1278
1279         if (scene_to == CTX_data_scene(C)) {
1280                 BKE_report(op->reports, RPT_ERROR, "Can't re-link markers into the same scene");
1281                 return OPERATOR_CANCELLED;
1282         }
1283
1284         /* copy markers */
1285         for (marker= markers->first; marker; marker= marker->next) {
1286                 if (marker->flag & SELECT) {
1287                         marker_new= MEM_dupallocN(marker);
1288                         marker_new->prev= marker_new->next = NULL;
1289                         
1290                         BLI_addtail(&scene_to->markers, marker_new);
1291                 }
1292         }
1293
1294         return OPERATOR_FINISHED;
1295 }
1296
1297 static void MARKER_OT_make_links_scene(wmOperatorType *ot)
1298 {
1299         PropertyRNA *prop;
1300
1301         /* identifiers */
1302         ot->name= "Make Links to Scene";
1303         ot->description= "Copy selected markers to another scene";
1304         ot->idname= "MARKER_OT_make_links_scene";
1305
1306         /* api callbacks */
1307         ot->exec= ed_marker_make_links_scene_exec;
1308         ot->invoke = ed_markers_opwrap_invoke;
1309         ot->poll= ed_markers_poll_selected_markers;
1310
1311         /* flags */
1312         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
1313
1314         /* properties */
1315         prop= RNA_def_enum(ot->srna, "scene", DummyRNA_NULL_items, 0, "Scene", "");
1316         RNA_def_enum_funcs(prop, RNA_scene_itemf);
1317         ot->prop= prop;
1318
1319 }
1320
1321 #ifdef DURIAN_CAMERA_SWITCH
1322 /* ******************************* camera bind marker ***************** */
1323
1324 static int ed_marker_camera_bind_exec(bContext *C, wmOperator *UNUSED(op))
1325 {
1326         Scene *scene= CTX_data_scene(C);
1327         ListBase *markers= ED_context_get_markers(C);
1328         TimeMarker *marker;
1329
1330         marker= ED_markers_get_first_selected(markers);
1331         if(marker == NULL)
1332                 return OPERATOR_CANCELLED;
1333
1334         marker->camera= scene->camera;
1335
1336         WM_event_add_notifier(C, NC_SCENE|ND_MARKERS, NULL);
1337         WM_event_add_notifier(C, NC_ANIMATION|ND_MARKERS, NULL);
1338
1339         return OPERATOR_FINISHED;
1340 }
1341
1342 static void MARKER_OT_camera_bind(wmOperatorType *ot)
1343 {
1344         /* identifiers */
1345         ot->name= "Bind Camera to Markers";
1346         ot->description= "Bind the active camera to selected markers(s)";
1347         ot->idname= "MARKER_OT_camera_bind";
1348
1349         /* api callbacks */
1350         ot->exec= ed_marker_camera_bind_exec;
1351         ot->invoke = ed_markers_opwrap_invoke;
1352         ot->poll= ed_markers_poll_selected_markers;
1353
1354         /* flags */
1355         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
1356 }
1357 #endif
1358
1359 /* ************************** registration **********************************/
1360
1361 /* called in screen_ops.c:ED_operatortypes_screen() */
1362 void ED_operatortypes_marker(void)
1363 {
1364         WM_operatortype_append(MARKER_OT_add);
1365         WM_operatortype_append(MARKER_OT_move);
1366         WM_operatortype_append(MARKER_OT_duplicate);
1367         WM_operatortype_append(MARKER_OT_select);
1368         WM_operatortype_append(MARKER_OT_select_border);
1369         WM_operatortype_append(MARKER_OT_select_all);
1370         WM_operatortype_append(MARKER_OT_delete);
1371         WM_operatortype_append(MARKER_OT_rename);
1372         WM_operatortype_append(MARKER_OT_make_links_scene);
1373 #ifdef DURIAN_CAMERA_SWITCH
1374         WM_operatortype_append(MARKER_OT_camera_bind);
1375 #endif
1376 }
1377
1378 /* called in screen_ops.c:ED_keymap_screen() */
1379 void ED_marker_keymap(wmKeyConfig *keyconf)
1380 {
1381         wmKeyMap *keymap= WM_keymap_find(keyconf, "Markers", 0, 0);
1382         wmKeyMapItem *kmi;
1383         
1384         WM_keymap_verify_item(keymap, "MARKER_OT_add", MKEY, KM_PRESS, 0, 0);
1385         WM_keymap_verify_item(keymap, "MARKER_OT_move", EVT_TWEAK_S, KM_ANY, 0, 0);
1386         WM_keymap_verify_item(keymap, "MARKER_OT_duplicate", DKEY, KM_PRESS, KM_SHIFT, 0);
1387         WM_keymap_verify_item(keymap, "MARKER_OT_select", SELECTMOUSE, KM_PRESS, 0, 0);
1388         RNA_boolean_set(WM_keymap_add_item(keymap, "MARKER_OT_select", SELECTMOUSE, KM_PRESS, KM_SHIFT, 0)->ptr, "extend", 1);
1389
1390 #ifdef DURIAN_CAMERA_SWITCH
1391         kmi= WM_keymap_add_item(keymap, "MARKER_OT_select", SELECTMOUSE, KM_PRESS, KM_CTRL, 0);
1392         RNA_boolean_set(kmi->ptr, "camera", 1);
1393
1394         kmi= WM_keymap_add_item(keymap, "MARKER_OT_select", SELECTMOUSE, KM_PRESS, KM_SHIFT|KM_CTRL, 0);
1395         RNA_boolean_set(kmi->ptr, "extend", 1);
1396         RNA_boolean_set(kmi->ptr, "camera", 1);
1397 #endif
1398         
1399         WM_keymap_verify_item(keymap, "MARKER_OT_select_border", BKEY, KM_PRESS, 0, 0);
1400         WM_keymap_verify_item(keymap, "MARKER_OT_select_all", AKEY, KM_PRESS, 0, 0);
1401         WM_keymap_verify_item(keymap, "MARKER_OT_delete", XKEY, KM_PRESS, 0, 0);
1402         WM_keymap_verify_item(keymap, "MARKER_OT_delete", DELKEY, KM_PRESS, 0, 0);
1403         WM_keymap_verify_item(keymap, "MARKER_OT_rename", MKEY, KM_PRESS, KM_CTRL, 0);
1404         
1405         WM_keymap_add_item(keymap, "MARKER_OT_move", GKEY, KM_PRESS, 0, 0);
1406 #ifdef DURIAN_CAMERA_SWITCH
1407         WM_keymap_add_item(keymap, "MARKER_OT_camera_bind", BKEY, KM_PRESS, KM_CTRL, 0);
1408 #endif
1409 }