Rename clip proxy rebuild function so it's no longer called in the same way
[blender.git] / source / blender / editors / space_clip / clip_ops.c
1 /*
2  * ***** BEGIN GPL LICENSE BLOCK *****
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version. 
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software Foundation,
16  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17  *
18  * The Original Code is Copyright (C) 2011 Blender Foundation.
19  * All rights reserved.
20  *
21  *
22  * Contributor(s): Blender Foundation,
23  *                 Sergey Sharybin
24  *
25  * ***** END GPL LICENSE BLOCK *****
26  */
27
28 /** \file blender/editors/space_clip/clip_ops.c
29  *  \ingroup spclip
30  */
31
32 #include <errno.h>
33
34 #include "MEM_guardedalloc.h"
35
36 #include "DNA_userdef_types.h"
37 #include "DNA_scene_types.h"    /* min/max frames */
38
39 #include "BLI_utildefines.h"
40 #include "BLI_math.h"
41
42 #include "BKE_context.h"
43 #include "BKE_global.h"
44 #include "BKE_report.h"
45 #include "BKE_main.h"
46 #include "BKE_library.h"
47 #include "BKE_movieclip.h"
48 #include "BKE_sound.h"
49 #include "BKE_tracking.h"
50
51 #include "WM_api.h"
52 #include "WM_types.h"
53
54 #include "IMB_imbuf_types.h"
55 #include "IMB_imbuf.h"
56
57 #include "ED_screen.h"
58 #include "ED_clip.h"
59
60 #include "UI_interface.h"
61
62 #include "RNA_access.h"
63 #include "RNA_define.h"
64
65 #include "UI_view2d.h"
66
67 #include "clip_intern.h"        // own include
68
69 /******************** view navigation utilities *********************/
70
71 static void sclip_zoom_set(SpaceClip *sc, ARegion *ar, float zoom)
72 {
73         float oldzoom= sc->zoom;
74         int width, height;
75
76         sc->zoom= zoom;
77
78         if (sc->zoom > 0.1f && sc->zoom < 4.0f)
79                 return;
80
81         /* check zoom limits */
82         ED_space_clip_size(sc, &width, &height);
83
84         width*= sc->zoom;
85         height*= sc->zoom;
86
87         if((width < 4) && (height < 4))
88                 sc->zoom= oldzoom;
89         else if((ar->winrct.xmax - ar->winrct.xmin) <= sc->zoom)
90                 sc->zoom= oldzoom;
91         else if((ar->winrct.ymax - ar->winrct.ymin) <= sc->zoom)
92                 sc->zoom= oldzoom;
93 }
94
95 static void sclip_zoom_set_factor(SpaceClip *sc, ARegion *ar, float zoomfac)
96 {
97         sclip_zoom_set(sc, ar, sc->zoom*zoomfac);
98 }
99
100
101 /******************** open clip operator ********************/
102
103 static void clip_filesel(bContext *C, wmOperator *op, const char *path)
104 {
105         RNA_string_set(op->ptr, "filepath", path);
106         WM_event_add_fileselect(C, op);
107 }
108
109 static void open_init(bContext *C, wmOperator *op)
110 {
111         PropertyPointerRNA *pprop;
112
113         op->customdata= pprop= MEM_callocN(sizeof(PropertyPointerRNA), "OpenPropertyPointerRNA");
114         uiIDContextProperty(C, &pprop->ptr, &pprop->prop);
115 }
116
117 static int open_cancel(bContext *UNUSED(C), wmOperator *op)
118 {
119         MEM_freeN(op->customdata);
120         op->customdata= NULL;
121
122         return OPERATOR_CANCELLED;
123 }
124
125 static int open_exec(bContext *C, wmOperator *op)
126 {
127         SpaceClip *sc= CTX_wm_space_clip(C);
128         PropertyPointerRNA *pprop;
129         PointerRNA idptr;
130         MovieClip *clip= NULL;
131         char str[FILE_MAX];
132
133         RNA_string_get(op->ptr, "filepath", str);
134         /* default to frame 1 if there's no scene in context */
135
136         errno= 0;
137
138         clip= BKE_add_movieclip_file(str);
139
140         if(!clip) {
141                 if(op->customdata)
142                         MEM_freeN(op->customdata);
143
144                 BKE_reportf(op->reports, RPT_ERROR, "Can't read: \"%s\", %s.", str, errno ? strerror(errno) : "Unsupported movie clip format");
145
146                 return OPERATOR_CANCELLED;
147         }
148
149         if(!op->customdata)
150                 open_init(C, op);
151
152         /* hook into UI */
153         pprop= op->customdata;
154
155         if(pprop->prop) {
156                 /* when creating new ID blocks, use is already 1, but RNA
157                  * pointer se also increases user, so this compensates it */
158                 clip->id.us--;
159
160                 RNA_id_pointer_create(&clip->id, &idptr);
161                 RNA_property_pointer_set(&pprop->ptr, pprop->prop, idptr);
162                 RNA_property_update(C, &pprop->ptr, pprop->prop);
163         }
164         else if(sc) {
165                 ED_space_clip_set(C, sc, clip);
166         }
167
168         WM_event_add_notifier(C, NC_MOVIECLIP|NA_ADDED, clip);
169
170         MEM_freeN(op->customdata);
171
172         return OPERATOR_FINISHED;
173 }
174
175 static int open_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event))
176 {
177         SpaceClip *sc= CTX_wm_space_clip(C);
178         char *path= U.textudir;
179         MovieClip *clip= NULL;
180
181         if(sc)
182                 clip= ED_space_clip(sc);
183
184         if(clip)
185                 path= clip->name;
186
187         if(!RNA_property_is_set(op->ptr, "relative_path"))
188                 RNA_boolean_set(op->ptr, "relative_path", U.flag & USER_RELPATHS);
189
190         if(RNA_property_is_set(op->ptr, "filepath"))
191                 return open_exec(C, op);
192
193         open_init(C, op);
194
195         clip_filesel(C, op, path);
196
197         return OPERATOR_RUNNING_MODAL;
198 }
199
200 void CLIP_OT_open(wmOperatorType *ot)
201 {
202         /* identifiers */
203         ot->name= "Open Clip";
204         ot->description= "Open clip";
205         ot->idname= "CLIP_OT_open";
206
207         /* api callbacks */
208         ot->exec= open_exec;
209         ot->invoke= open_invoke;
210         ot->cancel= open_cancel;
211
212         /* flags */
213         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
214
215         /* properties */
216         WM_operator_properties_filesel(ot, FOLDERFILE|IMAGEFILE|MOVIEFILE, FILE_SPECIAL, FILE_OPENFILE, WM_FILESEL_FILEPATH|WM_FILESEL_RELPATH);
217 }
218
219 /******************* reload clip operator *********************/
220
221 static int reload_exec(bContext *C, wmOperator *UNUSED(op))
222 {
223         SpaceClip *sc= CTX_wm_space_clip(C);
224         MovieClip *clip= CTX_data_edit_movieclip(C);
225
226         if(!clip)
227                 return OPERATOR_CANCELLED;
228
229         sc->scopes.ok= 0;
230
231         BKE_movieclip_reload(clip);
232
233         WM_event_add_notifier(C, NC_MOVIECLIP|NA_EDITED, clip);
234
235         return OPERATOR_FINISHED;
236 }
237
238 void CLIP_OT_reload(wmOperatorType *ot)
239 {
240         /* identifiers */
241         ot->name= "Reload Clip";
242         ot->description= "Reload clip";
243         ot->idname= "CLIP_OT_reload";
244
245         /* api callbacks */
246         ot->exec= reload_exec;
247 }
248
249 /********************** view pan operator *********************/
250
251 typedef struct ViewPanData {
252         float x, y;
253         float xof, yof, xorig, yorig;
254         int event_type;
255         float *vec;
256 } ViewPanData;
257
258 static void view_pan_init(bContext *C, wmOperator *op, wmEvent *event)
259 {
260         SpaceClip *sc= CTX_wm_space_clip(C);
261         ViewPanData *vpd;
262
263         op->customdata= vpd= MEM_callocN(sizeof(ViewPanData), "ClipViewPanData");
264         WM_cursor_modal(CTX_wm_window(C), BC_NSEW_SCROLLCURSOR);
265
266         vpd->x= event->x;
267         vpd->y= event->y;
268
269         if(sc->flag&SC_LOCK_SELECTION) vpd->vec= &sc->xlockof;
270         else vpd->vec= &sc->xof;
271
272         copy_v2_v2(&vpd->xof, vpd->vec);
273         copy_v2_v2(&vpd->xorig, &vpd->xof);
274
275         vpd->event_type= event->type;
276
277         WM_event_add_modal_handler(C, op);
278 }
279
280 static void view_pan_exit(bContext *C, wmOperator *op, int cancel)
281 {
282         ViewPanData *vpd= op->customdata;
283
284         if(cancel) {
285                 copy_v2_v2(vpd->vec, &vpd->xorig);
286
287                 ED_region_tag_redraw(CTX_wm_region(C));
288         }
289
290         WM_cursor_restore(CTX_wm_window(C));
291         MEM_freeN(op->customdata);
292 }
293
294 static int view_pan_exec(bContext *C, wmOperator *op)
295 {
296         SpaceClip *sc= CTX_wm_space_clip(C);
297         float offset[2];
298
299         RNA_float_get_array(op->ptr, "offset", offset);
300
301         if(sc->flag&SC_LOCK_SELECTION) {
302                 sc->xlockof+= offset[0];
303                 sc->ylockof+= offset[1];
304         } else {
305                 sc->xof+= offset[0];
306                 sc->yof+= offset[1];
307         }
308
309         ED_region_tag_redraw(CTX_wm_region(C));
310
311         return OPERATOR_FINISHED;
312 }
313
314 static int view_pan_invoke(bContext *C, wmOperator *op, wmEvent *event)
315 {
316         if (event->type==MOUSEPAN) {
317                 SpaceClip *sc= CTX_wm_space_clip(C);
318                 float offset[2];
319
320                 offset[0]= (event->x - event->prevx)/sc->zoom;
321                 offset[1]= (event->y - event->prevy)/sc->zoom;
322
323                 RNA_float_set_array(op->ptr, "offset", offset);
324
325                 view_pan_exec(C, op);
326                 return OPERATOR_FINISHED;
327         }
328         else {
329                 view_pan_init(C, op, event);
330                 return OPERATOR_RUNNING_MODAL;
331         }
332 }
333
334 static int view_pan_modal(bContext *C, wmOperator *op, wmEvent *event)
335 {
336         SpaceClip *sc= CTX_wm_space_clip(C);
337         ViewPanData *vpd= op->customdata;
338         float offset[2];
339
340         switch(event->type) {
341                 case MOUSEMOVE:
342                         copy_v2_v2(vpd->vec, &vpd->xorig);
343                         offset[0]= (vpd->x - event->x)/sc->zoom;
344                         offset[1]= (vpd->y - event->y)/sc->zoom;
345                         RNA_float_set_array(op->ptr, "offset", offset);
346                         view_pan_exec(C, op);
347                         break;
348                 case ESCKEY:
349                         view_pan_exit(C, op, 1);
350                         return OPERATOR_CANCELLED;
351                 case SPACEKEY:
352                         view_pan_exit(C, op, 0);
353                         return OPERATOR_FINISHED;
354                 default:
355                         if(event->type==vpd->event_type &&  event->val==KM_RELEASE) {
356                                 view_pan_exit(C, op, 0);
357                                 return OPERATOR_FINISHED;
358                         }
359                         break;
360         }
361
362         return OPERATOR_RUNNING_MODAL;
363 }
364
365 static int view_pan_cancel(bContext *C, wmOperator *op)
366 {
367         view_pan_exit(C, op, 1);
368
369         return OPERATOR_CANCELLED;
370 }
371
372 void CLIP_OT_view_pan(wmOperatorType *ot)
373 {
374         /* identifiers */
375         ot->name= "View Pan";
376         ot->idname= "CLIP_OT_view_pan";
377
378         /* api callbacks */
379         ot->exec= view_pan_exec;
380         ot->invoke= view_pan_invoke;
381         ot->modal= view_pan_modal;
382         ot->cancel= view_pan_cancel;
383         ot->poll= ED_space_clip_poll;
384
385         /* flags */
386         ot->flag= OPTYPE_BLOCKING;
387
388         /* properties */
389         RNA_def_float_vector(ot->srna, "offset", 2, NULL, -FLT_MAX, FLT_MAX,
390                 "Offset", "Offset in floating point units, 1.0 is the width and height of the image", -FLT_MAX, FLT_MAX);
391 }
392
393 /********************** view zoom operator *********************/
394
395 typedef struct ViewZoomData {
396         float x, y;
397         float zoom;
398         int event_type;
399 } ViewZoomData;
400
401 static void view_zoom_init(bContext *C, wmOperator *op, wmEvent *event)
402 {
403         SpaceClip *sc= CTX_wm_space_clip(C);
404         ViewZoomData *vpd;
405
406         op->customdata= vpd= MEM_callocN(sizeof(ViewZoomData), "ClipViewZoomData");
407         WM_cursor_modal(CTX_wm_window(C), BC_NSEW_SCROLLCURSOR);
408
409         vpd->x= event->x;
410         vpd->y= event->y;
411         vpd->zoom= sc->zoom;
412         vpd->event_type= event->type;
413
414         WM_event_add_modal_handler(C, op);
415 }
416
417 static void view_zoom_exit(bContext *C, wmOperator *op, int cancel)
418 {
419         SpaceClip *sc= CTX_wm_space_clip(C);
420         ViewZoomData *vpd= op->customdata;
421
422         if(cancel) {
423                 sc->zoom= vpd->zoom;
424                 ED_region_tag_redraw(CTX_wm_region(C));
425         }
426
427         WM_cursor_restore(CTX_wm_window(C));
428         MEM_freeN(op->customdata);
429 }
430
431 static int view_zoom_exec(bContext *C, wmOperator *op)
432 {
433         SpaceClip *sc= CTX_wm_space_clip(C);
434         ARegion *ar= CTX_wm_region(C);
435
436         sclip_zoom_set_factor(sc, ar, RNA_float_get(op->ptr, "factor"));
437
438         ED_region_tag_redraw(CTX_wm_region(C));
439
440         return OPERATOR_FINISHED;
441 }
442
443 static int view_zoom_invoke(bContext *C, wmOperator *op, wmEvent *event)
444 {
445         if (event->type==MOUSEZOOM) {
446                 SpaceClip *sc= CTX_wm_space_clip(C);
447                 ARegion *ar= CTX_wm_region(C);
448                 float factor;
449
450                 factor= 1.0f + (event->x-event->prevx+event->y-event->prevy)/300.0f;
451                 RNA_float_set(op->ptr, "factor", factor);
452                 sclip_zoom_set(sc, ar, sc->zoom*factor);
453                 ED_region_tag_redraw(CTX_wm_region(C));
454
455                 return OPERATOR_FINISHED;
456         }
457         else {
458                 view_zoom_init(C, op, event);
459                 return OPERATOR_RUNNING_MODAL;
460         }
461 }
462
463 static int view_zoom_modal(bContext *C, wmOperator *op, wmEvent *event)
464 {
465         SpaceClip *sc= CTX_wm_space_clip(C);
466         ARegion *ar= CTX_wm_region(C);
467         ViewZoomData *vpd= op->customdata;
468         float factor;
469
470         switch(event->type) {
471                 case MOUSEMOVE:
472                         factor= 1.0f + (vpd->x-event->x+vpd->y-event->y)/300.0f;
473                         RNA_float_set(op->ptr, "factor", factor);
474                         sclip_zoom_set(sc, ar, vpd->zoom*factor);
475                         ED_region_tag_redraw(CTX_wm_region(C));
476                         break;
477                 default:
478                         if(event->type==vpd->event_type && event->val==KM_RELEASE) {
479                                 view_zoom_exit(C, op, 0);
480                                 return OPERATOR_FINISHED;
481                         }
482                         break;
483         }
484
485         return OPERATOR_RUNNING_MODAL;
486 }
487
488 static int view_zoom_cancel(bContext *C, wmOperator *op)
489 {
490         view_zoom_exit(C, op, 1);
491         return OPERATOR_CANCELLED;
492 }
493
494 void CLIP_OT_view_zoom(wmOperatorType *ot)
495 {
496         /* identifiers */
497         ot->name= "View Zoom";
498         ot->idname= "CLIP_OT_view_zoom";
499
500         /* api callbacks */
501         ot->exec= view_zoom_exec;
502         ot->invoke= view_zoom_invoke;
503         ot->modal= view_zoom_modal;
504         ot->cancel= view_zoom_cancel;
505         ot->poll= ED_space_clip_poll;
506
507         /* flags */
508         ot->flag= OPTYPE_BLOCKING|OPTYPE_GRAB_POINTER;
509
510         /* properties */
511         RNA_def_float(ot->srna, "factor", 0.0f, 0.0f, FLT_MAX,
512                 "Factor", "Zoom factor, values higher than 1.0 zoom in, lower values zoom out", -FLT_MAX, FLT_MAX);
513 }
514
515 /********************** view zoom in/out operator *********************/
516
517 static int view_zoom_in_exec(bContext *C, wmOperator *UNUSED(op))
518 {
519         SpaceClip *sc= CTX_wm_space_clip(C);
520         ARegion *ar= CTX_wm_region(C);
521
522         sclip_zoom_set_factor(sc, ar, 1.25f);
523
524         ED_region_tag_redraw(CTX_wm_region(C));
525
526         return OPERATOR_FINISHED;
527 }
528
529 static int view_zoom_out_exec(bContext *C, wmOperator *UNUSED(op))
530 {
531         SpaceClip *sc= CTX_wm_space_clip(C);
532         ARegion *ar= CTX_wm_region(C);
533
534         sclip_zoom_set_factor(sc, ar, 0.8f);
535
536         ED_region_tag_redraw(CTX_wm_region(C));
537
538         return OPERATOR_FINISHED;
539 }
540
541 static int view_zoom_inout_invoke(bContext *C, wmOperator *op, wmEvent *event, int out)
542 {
543         SpaceClip *sc= CTX_wm_space_clip(C);
544         float co[2], oldzoom= sc->zoom;
545
546         ED_clip_mouse_pos(C, event, co);
547
548         if(out)
549                 view_zoom_out_exec(C, op);
550         else
551                 view_zoom_in_exec(C, op);
552
553         if(U.uiflag&USER_ZOOM_TO_MOUSEPOS) {
554                 int width, height;
555
556                 ED_space_clip_size(sc, &width, &height);
557
558                 sc->xof+= ((co[0]-0.5f)*width-sc->xof)*(sc->zoom-oldzoom)/sc->zoom;
559                 sc->yof+= ((co[1]-0.5f)*height-sc->yof)*(sc->zoom-oldzoom)/sc->zoom;
560         }
561
562         return OPERATOR_FINISHED;
563 }
564
565 static int view_zoom_in_invoke(bContext *C, wmOperator *op, wmEvent *event)
566 {
567         return view_zoom_inout_invoke(C, op, event, 0);
568 }
569
570 void CLIP_OT_view_zoom_in(wmOperatorType *ot)
571 {
572         /* identifiers */
573         ot->name= "View Zoom In";
574         ot->idname= "CLIP_OT_view_zoom_in";
575
576         /* api callbacks */
577         ot->exec= view_zoom_in_exec;
578         ot->invoke= view_zoom_in_invoke;
579         ot->poll= ED_space_clip_poll;
580 }
581
582 static int view_zoom_out_invoke(bContext *C, wmOperator *op, wmEvent *event)
583 {
584         return view_zoom_inout_invoke(C, op, event, 1);
585 }
586
587 void CLIP_OT_view_zoom_out(wmOperatorType *ot)
588 {
589         /* identifiers */
590         ot->name= "View Zoom Out";
591         ot->idname= "CLIP_OT_view_zoom_out";
592
593         /* api callbacks */
594         ot->exec= view_zoom_out_exec;
595         ot->invoke= view_zoom_out_invoke;
596         ot->poll= ED_space_clip_poll;
597 }
598
599 /********************** view zoom ratio operator *********************/
600
601 static int view_zoom_ratio_exec(bContext *C, wmOperator *op)
602 {
603         SpaceClip *sc= CTX_wm_space_clip(C);
604         ARegion *ar= CTX_wm_region(C);
605
606         sclip_zoom_set(sc, ar, RNA_float_get(op->ptr, "ratio"));
607
608         /* ensure pixel exact locations for draw */
609         sc->xof= (int)sc->xof;
610         sc->yof= (int)sc->yof;
611
612         ED_region_tag_redraw(CTX_wm_region(C));
613
614         return OPERATOR_FINISHED;
615 }
616
617 void CLIP_OT_view_zoom_ratio(wmOperatorType *ot)
618 {
619         /* identifiers */
620         ot->name= "View Zoom Ratio";
621         ot->idname= "CLIP_OT_view_zoom_ratio";
622
623         /* api callbacks */
624         ot->exec= view_zoom_ratio_exec;
625         ot->poll= ED_space_clip_poll;
626
627         /* properties */
628         RNA_def_float(ot->srna, "ratio", 0.0f, 0.0f, FLT_MAX,
629                 "Ratio", "Zoom ratio, 1.0 is 1:1, higher is zoomed in, lower is zoomed out", -FLT_MAX, FLT_MAX);
630 }
631
632 /********************** view all operator *********************/
633
634 static int view_all_exec(bContext *C, wmOperator *UNUSED(op))
635 {
636         SpaceClip *sc;
637         ARegion *ar;
638         int w, h, width, height;
639         float aspx, aspy;
640
641         /* retrieve state */
642         sc= CTX_wm_space_clip(C);
643         ar= CTX_wm_region(C);
644
645         ED_space_clip_size(sc, &w, &h);
646         ED_space_clip_aspect(sc, &aspx, &aspy);
647
648         w= w*aspx;
649         h= h*aspy;
650
651         /* check if the image will fit in the image with zoom==1 */
652         width= ar->winrct.xmax - ar->winrct.xmin + 1;
653         height= ar->winrct.ymax - ar->winrct.ymin + 1;
654
655         if((w >= width || h >= height) && (width > 0 && height > 0)) {
656                 float zoomx, zoomy;
657
658                 /* find the zoom value that will fit the image in the image space */
659                 zoomx= (float)width/w;
660                 zoomy= (float)height/h;
661                 sclip_zoom_set(sc, ar, 1.0f/power_of_2(1/MIN2(zoomx, zoomy)));
662         }
663         else
664                 sclip_zoom_set(sc, ar, 1.0f);
665
666         sc->xof= sc->yof= 0.0f;
667
668         ED_region_tag_redraw(CTX_wm_region(C));
669
670         return OPERATOR_FINISHED;
671 }
672
673 void CLIP_OT_view_all(wmOperatorType *ot)
674 {
675         /* identifiers */
676         ot->name= "View All";
677         ot->idname= "CLIP_OT_view_all";
678
679         /* api callbacks */
680         ot->exec= view_all_exec;
681         ot->poll= ED_space_clip_poll;
682 }
683
684 /********************** view selected operator *********************/
685
686 static int view_selected_exec(bContext *C, wmOperator *UNUSED(op))
687 {
688         SpaceClip *sc= CTX_wm_space_clip(C);
689         ARegion *ar= CTX_wm_region(C);
690
691         sc->xlockof= 0.0f;
692         sc->ylockof= 0.0f;
693
694         ED_clip_view_selection(sc, ar, 1);
695         ED_region_tag_redraw(CTX_wm_region(C));
696
697         return OPERATOR_FINISHED;
698 }
699
700 void CLIP_OT_view_selected(wmOperatorType *ot)
701 {
702         /* identifiers */
703         ot->name= "View Selected";
704         ot->idname= "CLIP_OT_view_selected";
705
706         /* api callbacks */
707         ot->exec= view_selected_exec;
708         ot->poll= ED_space_clip_poll;
709 }
710
711 /********************** change frame operator *********************/
712
713 static int change_frame_poll(bContext *C)
714 {
715         /* prevent changes during render */
716         if(G.rendering)
717                 return 0;
718
719         return ED_space_clip_poll(C);
720 }
721
722 static void change_frame_apply(bContext *C, wmOperator *op)
723 {
724         Scene *scene= CTX_data_scene(C);
725
726         /* set the new frame number */
727         CFRA= RNA_int_get(op->ptr, "frame");
728         FRAMENUMBER_MIN_CLAMP(CFRA);
729         SUBFRA = 0.0f;
730
731         /* do updates */
732         sound_seek_scene(CTX_data_main(C), CTX_data_scene(C));
733         WM_event_add_notifier(C, NC_SCENE|ND_FRAME, scene);
734 }
735
736 static int change_frame_exec(bContext *C, wmOperator *op)
737 {
738         change_frame_apply(C, op);
739
740         return OPERATOR_FINISHED;
741 }
742
743 static int frame_from_event(bContext *C, wmEvent *event)
744 {
745         ARegion *ar= CTX_wm_region(C);
746         Scene *scene= CTX_data_scene(C);
747         int framenr= 0;
748
749         if(ar->regiontype == RGN_TYPE_WINDOW) {
750                 float sfra= SFRA, efra= EFRA, framelen= ar->winx/(efra-sfra+1);
751
752                 framenr= sfra+event->mval[0]/framelen;
753         } else {
754                 float viewx, viewy;
755
756                 UI_view2d_region_to_view(&ar->v2d, event->mval[0], event->mval[1], &viewx, &viewy);
757
758                 framenr= (int)floor(viewx+0.5f);
759         }
760
761         return framenr;
762 }
763
764 static int change_frame_invoke(bContext *C, wmOperator *op, wmEvent *event)
765 {
766         ARegion *ar= CTX_wm_region(C);
767
768         if(ar->regiontype == RGN_TYPE_WINDOW) {
769                 if(event->mval[1]>16)
770                         return OPERATOR_PASS_THROUGH;
771         }
772
773         RNA_int_set(op->ptr, "frame", frame_from_event(C, event));
774
775         change_frame_apply(C, op);
776
777         /* add temp handler */
778         WM_event_add_modal_handler(C, op);
779
780         return OPERATOR_RUNNING_MODAL;
781 }
782
783 static int change_frame_modal(bContext *C, wmOperator *op, wmEvent *event)
784 {
785         switch (event->type) {
786                 case ESCKEY:
787                         return OPERATOR_FINISHED;
788
789                 case MOUSEMOVE:
790                         RNA_int_set(op->ptr, "frame", frame_from_event(C, event));
791                         change_frame_apply(C, op);
792                         break;
793
794                 case LEFTMOUSE:
795                 case RIGHTMOUSE:
796                         if (event->val==KM_RELEASE)
797                                 return OPERATOR_FINISHED;
798                         break;
799         }
800
801         return OPERATOR_RUNNING_MODAL;
802 }
803
804 void CLIP_OT_change_frame(wmOperatorType *ot)
805 {
806         /* identifiers */
807         ot->name= "Change frame";
808         ot->idname= "CLIP_OT_change_frame";
809         ot->description= "Interactively change the current frame number";
810
811         /* api callbacks */
812         ot->exec= change_frame_exec;
813         ot->invoke= change_frame_invoke;
814         ot->modal= change_frame_modal;
815         ot->poll= change_frame_poll;
816
817         /* flags */
818         ot->flag= OPTYPE_BLOCKING|OPTYPE_UNDO;
819
820         /* rna */
821         RNA_def_int(ot->srna, "frame", 0, MINAFRAME, MAXFRAME, "Frame", "", MINAFRAME, MAXFRAME);
822 }
823
824 /********************** rebuild proxies operator *********************/
825
826 typedef struct ProxyBuildJob {
827         Scene *scene;
828         struct Main *main;
829         MovieClip *clip;
830 } ProxyJob;
831
832 static void proxy_freejob(void *pjv)
833 {
834         ProxyJob *pj= pjv;
835
836         MEM_freeN(pj);
837 }
838
839 /* only this runs inside thread */
840 static void proxy_startjob(void *pjv, short *stop, short *do_update, float *progress)
841 {
842         ProxyJob *pj= pjv;
843         Scene *scene=pj->scene;
844         MovieClip *clip= pj->clip;
845         struct MovieDistortion *distortion= NULL;
846         int cfra, undistort;
847         short tc_flag, size_flag, quality, build_flag;
848         int sfra= SFRA, efra= EFRA;
849         int build_sizes[4], build_count= 0;
850
851         tc_flag= clip->proxy.build_tc_flag;
852         size_flag= clip->proxy.build_size_flag;
853         quality= clip->proxy.quality;
854         build_flag= clip->proxy.build_flag;
855         undistort= build_flag&MCLIP_PROXY_RENDER_UNDISTORT;
856
857         if(clip->source == MCLIP_SRC_MOVIE) {
858                 if(clip->anim)
859                         IMB_anim_index_rebuild(clip->anim, tc_flag, size_flag, quality, stop, do_update, progress);
860
861                 if(!undistort) {
862                         return;
863                 }
864                 else {
865                         sfra= 1;
866                         efra= IMB_anim_get_duration(clip->anim, IMB_TC_NONE);
867                 }
868         }
869
870         if(size_flag&IMB_PROXY_25) build_sizes[build_count++]= MCLIP_PROXY_RENDER_SIZE_25;
871         if(size_flag&IMB_PROXY_50) build_sizes[build_count++]= MCLIP_PROXY_RENDER_SIZE_50;
872         if(size_flag&IMB_PROXY_75) build_sizes[build_count++]= MCLIP_PROXY_RENDER_SIZE_75;
873         if(size_flag&IMB_PROXY_100) build_sizes[build_count++]= MCLIP_PROXY_RENDER_SIZE_100;
874
875         if(undistort)
876                 distortion= BKE_tracking_distortion_create();
877
878         for(cfra= sfra; cfra<=efra; cfra++) {
879                 if(clip->source != MCLIP_SRC_MOVIE)
880                         BKE_movieclip_build_proxy_frame(clip, NULL, cfra, build_sizes, build_count, 0);
881
882                 if(undistort)
883                         BKE_movieclip_build_proxy_frame(clip, distortion, cfra, build_sizes, build_count, 1);
884
885                 if(*stop || G.afbreek)
886                         break;
887
888                 *do_update= 1;
889                 *progress= ((float)cfra)/(efra-sfra);
890         }
891
892         if(distortion)
893                 BKE_tracking_distortion_destroy(distortion);
894 }
895
896 static int clip_rebuild_proxy_exec(bContext *C, wmOperator *UNUSED(op))
897 {
898         wmJob * steve;
899         ProxyJob *pj;
900         Scene *scene= CTX_data_scene(C);
901         ScrArea *sa= CTX_wm_area(C);
902         SpaceClip *sc= CTX_wm_space_clip(C);
903         MovieClip *clip= ED_space_clip(sc);
904
905         if((clip->flag&MCLIP_USE_PROXY)==0)
906                 return OPERATOR_CANCELLED;
907
908         steve= WM_jobs_get(CTX_wm_manager(C), CTX_wm_window(C), sa, "Building Proxies", WM_JOB_PROGRESS);
909
910         pj= MEM_callocN(sizeof(ProxyJob), "proxy rebuild job");
911         pj->scene= scene;
912         pj->main= CTX_data_main(C);
913         pj->clip= clip;
914
915         WM_jobs_customdata(steve, pj, proxy_freejob);
916         WM_jobs_timer(steve, 0.2, NC_MOVIECLIP|ND_DISPLAY, 0);
917         WM_jobs_callbacks(steve, proxy_startjob, NULL, NULL, NULL);
918
919         G.afbreek= 0;
920         WM_jobs_start(CTX_wm_manager(C), steve);
921
922         ED_area_tag_redraw(CTX_wm_area(C));
923
924         return OPERATOR_FINISHED;
925 }
926
927 void CLIP_OT_rebuild_proxy(wmOperatorType *ot)
928 {
929         /* identifiers */
930         ot->name= "Rebuild Proxy and Timecode Indices";
931         ot->idname= "CLIP_OT_rebuild_proxy";
932         ot->description= "Rebuild all selected proxies and timecode indeces in the background";
933
934         /* api callbacks */
935         ot->exec= clip_rebuild_proxy_exec;
936         ot->poll= ED_space_clip_poll;
937
938         /* flags */
939         ot->flag= OPTYPE_REGISTER;
940 }
941
942 /********************** mode set operator *********************/
943
944 static int mode_set_exec(bContext *C, wmOperator *op)
945 {
946         SpaceClip *sc= CTX_wm_space_clip(C);
947         int mode= RNA_enum_get(op->ptr, "mode");
948         int toggle= RNA_boolean_get(op->ptr, "toggle");
949
950         if(sc->mode==mode) {
951                 if(toggle)
952                         sc->mode= SC_MODE_TRACKING;
953         } else {
954                 sc->mode= mode;
955         }
956
957         WM_event_add_notifier(C, NC_SPACE|ND_SPACE_CLIP, NULL);
958
959         return OPERATOR_FINISHED;
960 }
961
962 void CLIP_OT_mode_set(wmOperatorType *ot)
963 {
964         static EnumPropertyItem mode_items[] = {
965                 {SC_MODE_TRACKING, "TRACKING", 0, "Tracking", "Show tracking and solving tools"},
966                 {SC_MODE_RECONSTRUCTION, "RECONSTRUCTION", 0, "Reconstruction", "Show tracking/reconstruction tools"},
967                 {SC_MODE_DISTORTION, "DISTORTION", 0, "Distortion", "Show distortion tools"},
968                 {0, NULL, 0, NULL, NULL}};
969
970
971         /* identifiers */
972         ot->name= "Set Clip Mode";
973         ot->description = "Set the clip interaction mode";
974         ot->idname= "CLIP_OT_mode_set";
975
976         /* api callbacks */
977         ot->exec= mode_set_exec;
978
979         ot->poll= ED_space_clip_poll;
980
981         /* properties */
982         RNA_def_enum(ot->srna, "mode", mode_items, SC_MODE_TRACKING, "Mode", "");
983         RNA_def_boolean(ot->srna, "toggle", 0, "Toggle", "");
984 }
985
986 /********************** macroses *********************/
987
988 void ED_operatormacros_clip(void)
989 {
990         wmOperatorType *ot;
991         wmOperatorTypeMacro *otmacro;
992
993         ot= WM_operatortype_append_macro("CLIP_OT_add_marker_move", "Add Marker and Move", OPTYPE_UNDO|OPTYPE_REGISTER);
994         ot->description = "Add new marker and move it on movie";
995         WM_operatortype_macro_define(ot, "CLIP_OT_add_marker");
996         otmacro= WM_operatortype_macro_define(ot, "TRANSFORM_OT_translate");
997         RNA_struct_idprops_unset(otmacro->ptr, "release_confirm");
998
999         ot= WM_operatortype_append_macro("CLIP_OT_add_marker_slide", "Add Marker and Slide", OPTYPE_UNDO|OPTYPE_REGISTER);
1000         ot->description = "Add new marker and slide it with mouse until mouse button release";
1001         WM_operatortype_macro_define(ot, "CLIP_OT_add_marker");
1002         otmacro= WM_operatortype_macro_define(ot, "TRANSFORM_OT_translate");
1003         RNA_boolean_set(otmacro->ptr, "release_confirm", 1);
1004 }