rework speed timeline picons/waves
[goodguy/history.git] / cinelerra-5.1 / cinelerra / cwindowtool.C
1 /*
2  * CINELERRA
3  * Copyright (C) 2008-2017 Adam Williams <broadcast at earthling dot net>
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 2 of the License, or
8  * (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
18  *
19  */
20
21 #include <stdio.h>
22 #include <stdint.h>
23
24 #include "automation.h"
25 #include "bccolors.h"
26 #include "clip.h"
27 #include "condition.h"
28 #include "cpanel.h"
29 #include "cplayback.h"
30 #include "cwindow.h"
31 #include "cwindowgui.h"
32 #include "cwindowtool.h"
33 #include "edl.h"
34 #include "edlsession.h"
35 #include "floatauto.h"
36 #include "floatautos.h"
37 #include "keys.h"
38 #include "language.h"
39 #include "localsession.h"
40 #include "mainsession.h"
41 #include "mainundo.h"
42 #include "maskauto.h"
43 #include "maskautos.h"
44 #include "mutex.h"
45 #include "mwindow.h"
46 #include "mwindowgui.h"
47 #include "theme.h"
48 #include "track.h"
49 #include "trackcanvas.h"
50 #include "transportque.h"
51
52
53 CWindowTool::CWindowTool(MWindow *mwindow, CWindowGUI *gui)
54  : Thread(1, 0, 0)
55 {
56         this->mwindow = mwindow;
57         this->gui = gui;
58         tool_gui = 0;
59         done = 0;
60         current_tool = CWINDOW_NONE;
61         set_synchronous(1);
62         input_lock = new Condition(0, "CWindowTool::input_lock");
63         output_lock = new Condition(1, "CWindowTool::output_lock");
64         tool_gui_lock = new Mutex("CWindowTool::tool_gui_lock");
65 }
66
67 CWindowTool::~CWindowTool()
68 {
69         done = 1;
70         stop_tool();
71         input_lock->unlock();
72         Thread::join();
73         delete input_lock;
74         delete output_lock;
75         delete tool_gui_lock;
76 }
77
78 void CWindowTool::start_tool(int operation)
79 {
80         CWindowToolGUI *new_gui = 0;
81         int result = 0;
82
83 //printf("CWindowTool::start_tool 1\n");
84         if(current_tool != operation)
85         {
86                 current_tool = operation;
87                 switch(operation)
88                 {
89                         case CWINDOW_EYEDROP:
90                                 new_gui = new CWindowEyedropGUI(mwindow, this);
91                                 break;
92                         case CWINDOW_CROP:
93                                 new_gui = new CWindowCropGUI(mwindow, this);
94                                 break;
95                         case CWINDOW_CAMERA:
96                                 new_gui = new CWindowCameraGUI(mwindow, this);
97                                 break;
98                         case CWINDOW_PROJECTOR:
99                                 new_gui = new CWindowProjectorGUI(mwindow, this);
100                                 break;
101                         case CWINDOW_MASK:
102                                 new_gui = new CWindowMaskGUI(mwindow, this);
103                                 break;
104                         case CWINDOW_RULER:
105                                 new_gui = new CWindowRulerGUI(mwindow, this);
106                                 break;
107                         default:
108                                 result = 1;
109                                 stop_tool();
110                                 break;
111                 }
112
113 //printf("CWindowTool::start_tool 1\n");
114
115
116                 if(!result)
117                 {
118                         stop_tool();
119 // Wait for previous tool GUI to finish
120                         output_lock->lock("CWindowTool::start_tool");
121                         this->tool_gui = new_gui;
122                         tool_gui->create_objects();
123
124                         if(mwindow->edl->session->tool_window &&
125                                 mwindow->session->show_cwindow) tool_gui->show_window();
126                         tool_gui->lock_window("CWindowTool::start_tool 1");
127                         tool_gui->flush();
128                         tool_gui->unlock_window();
129
130
131 // Signal thread to run next tool GUI
132                         input_lock->unlock();
133                 }
134 //printf("CWindowTool::start_tool 1\n");
135         }
136         else
137         if(tool_gui)
138         {
139                 tool_gui->lock_window("CWindowTool::start_tool");
140                 tool_gui->update();
141                 tool_gui->unlock_window();
142         }
143
144 //printf("CWindowTool::start_tool 2\n");
145
146 }
147
148
149 void CWindowTool::stop_tool()
150 {
151         if(tool_gui)
152         {
153                 tool_gui->lock_window("CWindowTool::stop_tool");
154                 tool_gui->set_done(0);
155                 tool_gui->unlock_window();
156         }
157 }
158
159 void CWindowTool::show_tool()
160 {
161         if(tool_gui && mwindow->edl->session->tool_window)
162         {
163                 tool_gui->lock_window("CWindowTool::show_tool");
164                 tool_gui->show_window();
165                 tool_gui->unlock_window();
166         }
167 }
168
169 void CWindowTool::hide_tool()
170 {
171         if(tool_gui && mwindow->edl->session->tool_window)
172         {
173                 tool_gui->lock_window("CWindowTool::show_tool");
174                 tool_gui->hide_window();
175                 tool_gui->unlock_window();
176         }
177 }
178
179
180 void CWindowTool::run()
181 {
182         while(!done)
183         {
184                 input_lock->lock("CWindowTool::run");
185                 if(!done)
186                 {
187                         tool_gui->run_window();
188                         tool_gui_lock->lock("CWindowTool::run");
189                         delete tool_gui;
190                         tool_gui = 0;
191                         tool_gui_lock->unlock();
192                 }
193                 output_lock->unlock();
194         }
195 }
196
197 void CWindowTool::update_show_window()
198 {
199         if(tool_gui)
200         {
201                 tool_gui->lock_window("CWindowTool::update_show_window");
202
203                 if(mwindow->edl->session->tool_window)
204                 {
205                         tool_gui->update();
206                         tool_gui->show_window();
207                 }
208                 else
209                         tool_gui->hide_window();
210                 tool_gui->flush();
211
212                 tool_gui->unlock_window();
213         }
214 }
215
216 void CWindowTool::raise_window()
217 {
218         if(tool_gui)
219         {
220                 gui->unlock_window();
221                 tool_gui->lock_window("CWindowTool::raise_window");
222                 tool_gui->raise_window();
223                 tool_gui->unlock_window();
224                 gui->lock_window("CWindowTool::raise_window");
225         }
226 }
227
228 void CWindowTool::update_values()
229 {
230         tool_gui_lock->lock("CWindowTool::update_values");
231         if(tool_gui)
232         {
233                 tool_gui->lock_window("CWindowTool::update_values");
234                 tool_gui->update();
235                 tool_gui->flush();
236                 tool_gui->unlock_window();
237         }
238         tool_gui_lock->unlock();
239 }
240
241
242
243
244
245
246
247 CWindowToolGUI::CWindowToolGUI(MWindow *mwindow,
248         CWindowTool *thread,
249         const char *title,
250         int w,
251         int h)
252  : BC_Window(title,
253         mwindow->session->ctool_x,
254         mwindow->session->ctool_y,
255         w,
256         h,
257         w,
258         h,
259         0,
260         0,
261         1)
262 {
263         this->mwindow = mwindow;
264         this->thread = thread;
265         current_operation = 0;
266 }
267
268 CWindowToolGUI::~CWindowToolGUI()
269 {
270 }
271
272 int CWindowToolGUI::close_event()
273 {
274         hide_window();
275         flush();
276         mwindow->edl->session->tool_window = 0;
277         unlock_window();
278
279
280
281         thread->gui->lock_window("CWindowToolGUI::close_event");
282         thread->gui->composite_panel->set_operation(mwindow->edl->session->cwindow_operation);
283         thread->gui->flush();
284         thread->gui->unlock_window();
285
286         lock_window("CWindowToolGUI::close_event");
287         return 1;
288 ;}
289
290 int CWindowToolGUI::keypress_event()
291 {
292         int result = 0;
293
294         switch( get_keypress() ) {
295         case 'w':
296         case 'W':
297                 return close_event();
298         case KEY_F1:
299         case KEY_F2:
300         case KEY_F3:
301         case KEY_F4:
302         case KEY_F5:
303         case KEY_F6:
304         case KEY_F7:
305         case KEY_F8:
306         case KEY_F9:
307         case KEY_F10:
308                 resend_event(thread->gui);
309                 result = 1;
310         }
311
312         return result;
313 }
314
315 int CWindowToolGUI::translation_event()
316 {
317         mwindow->session->ctool_x = get_x();
318         mwindow->session->ctool_y = get_y();
319         return 0;
320 }
321
322
323
324
325
326
327 CWindowCoord::CWindowCoord(CWindowToolGUI *gui, int x, int y, float value, int log_increment = 0)
328  : BC_TumbleTextBox(gui, (float)value, (float)-65536, (float)65536, x, y, 100)
329 {
330         this->gui = gui;
331         set_log_floatincrement(log_increment);
332 }
333
334 CWindowCoord::CWindowCoord(CWindowToolGUI *gui, int x, int y, int value)
335  : BC_TumbleTextBox(gui, (int64_t)value, (int64_t)-65536, (int64_t)65536, x, y, 100)
336 {
337         this->gui = gui;
338 }
339 int CWindowCoord::handle_event()
340 {
341         gui->event_caller = this;
342         gui->handle_event();
343         return 1;
344 }
345
346
347 CWindowCropOK::CWindowCropOK(MWindow *mwindow, CWindowToolGUI *gui, int x, int y)
348  : BC_GenericButton(x, y, _("Do it"))
349 {
350         this->mwindow = mwindow;
351         this->gui = gui;
352 }
353 int CWindowCropOK::handle_event()
354 {
355         mwindow->crop_video();
356         return 1;
357 }
358
359
360 int CWindowCropOK::keypress_event()
361 {
362         if(get_keypress() == 0xd)
363         {
364                 handle_event();
365                 return 1;
366         }
367         return 0;
368 }
369
370
371
372
373
374
375
376 CWindowCropGUI::CWindowCropGUI(MWindow *mwindow, CWindowTool *thread)
377  : CWindowToolGUI(mwindow,
378         thread,
379         _(PROGRAM_NAME ": Crop"),
380         330,
381         100)
382 {
383 }
384
385
386 CWindowCropGUI::~CWindowCropGUI()
387 {
388 }
389
390 void CWindowCropGUI::create_objects()
391 {
392         int x = 10, y = 10;
393         BC_Title *title;
394
395         lock_window("CWindowCropGUI::create_objects");
396         int column1 = 0;
397         int pad = MAX(BC_TextBox::calculate_h(this, MEDIUMFONT, 1, 1),
398                 BC_Title::calculate_h(this, "X")) + 5;
399         add_subwindow(title = new BC_Title(x, y, "X1:"));
400         column1 = MAX(column1, title->get_w());
401         y += pad;
402         add_subwindow(title = new BC_Title(x, y, _("W:")));
403         column1 = MAX(column1, title->get_w());
404         y += pad;
405         add_subwindow(new CWindowCropOK(mwindow, thread->tool_gui, x, y));
406
407         x += column1 + 5;
408         y = 10;
409         x1 = new CWindowCoord(thread->tool_gui, x, y,
410                 mwindow->edl->session->crop_x1);
411         x1->create_objects();
412         y += pad;
413         width = new CWindowCoord(thread->tool_gui, x, y,
414                 mwindow->edl->session->crop_x2 - mwindow->edl->session->crop_x1);
415         width->create_objects();
416
417
418         x += x1->get_w() + 10;
419         y = 10;
420         int column2 = 0;
421         add_subwindow(title = new BC_Title(x, y, "Y1:"));
422         column2 = MAX(column2, title->get_w());
423         y += pad;
424         add_subwindow(title = new BC_Title(x, y, _("H:")));
425         column2 = MAX(column2, title->get_w());
426         y += pad;
427
428         y = 10;
429         x += column2 + 5;
430         y1 = new CWindowCoord(thread->tool_gui, x, y,
431                 mwindow->edl->session->crop_y1);
432         y1->create_objects();
433         y += pad;
434         height = new CWindowCoord(thread->tool_gui, x, y,
435                 mwindow->edl->session->crop_y2 - mwindow->edl->session->crop_y1);
436         height->create_objects();
437         unlock_window();
438 }
439
440 void CWindowCropGUI::handle_event()
441 {
442         int new_x1, new_y1;
443         new_x1 = atol(x1->get_text());
444         new_y1 = atol(y1->get_text());
445         if(new_x1 != mwindow->edl->session->crop_x1)
446         {
447                 mwindow->edl->session->crop_x2 = new_x1 +
448                         mwindow->edl->session->crop_x2 -
449                         mwindow->edl->session->crop_x1;
450                 mwindow->edl->session->crop_x1 = new_x1;
451         }
452         if(new_y1 != mwindow->edl->session->crop_y1)
453         {
454                 mwindow->edl->session->crop_y2 = new_y1 +
455                         mwindow->edl->session->crop_y2 -
456                         mwindow->edl->session->crop_y1;
457                 mwindow->edl->session->crop_y1 = atol(y1->get_text());
458         }
459         mwindow->edl->session->crop_x2 = atol(width->get_text()) +
460                 mwindow->edl->session->crop_x1;
461         mwindow->edl->session->crop_y2 = atol(height->get_text()) +
462                 mwindow->edl->session->crop_y1;
463         update();
464         mwindow->cwindow->gui->lock_window("CWindowCropGUI::handle_event");
465         mwindow->cwindow->gui->canvas->draw_refresh();
466         mwindow->cwindow->gui->unlock_window();
467 }
468
469 void CWindowCropGUI::update()
470 {
471         x1->update((int64_t)mwindow->edl->session->crop_x1);
472         y1->update((int64_t)mwindow->edl->session->crop_y1);
473         width->update((int64_t)mwindow->edl->session->crop_x2 -
474                 mwindow->edl->session->crop_x1);
475         height->update((int64_t)mwindow->edl->session->crop_y2 -
476                 mwindow->edl->session->crop_y1);
477 }
478
479
480 CWindowEyedropGUI::CWindowEyedropGUI(MWindow *mwindow, CWindowTool *thread)
481  : CWindowToolGUI(mwindow, thread, _(PROGRAM_NAME ": Color"), 220, 290)
482 {
483 }
484
485 CWindowEyedropGUI::~CWindowEyedropGUI()
486 {
487 }
488
489 void CWindowEyedropGUI::create_objects()
490 {
491         int margin = mwindow->theme->widget_border;
492         int x = 10 + margin;
493         int y = 10 + margin;
494         int x2 = 70, x3 = x2 + 60;
495         lock_window("CWindowEyedropGUI::create_objects");
496         BC_Title *title0, *title1, *title2, *title3, *title4, *title5, *title6, *title7;
497         add_subwindow(title0 = new BC_Title(x, y,_("X,Y:")));
498         y += title0->get_h() + margin;
499         add_subwindow(title7 = new BC_Title(x, y, _("Radius:")));
500         y += BC_TextBox::calculate_h(this, MEDIUMFONT, 1, 1) + margin;
501
502         add_subwindow(title1 = new BC_Title(x, y, _("Red:")));
503         y += title1->get_h() + margin;
504         add_subwindow(title2 = new BC_Title(x, y, _("Green:")));
505         y += title2->get_h() + margin;
506         add_subwindow(title3 = new BC_Title(x, y, _("Blue:")));
507         y += title3->get_h() + margin;
508
509         add_subwindow(title4 = new BC_Title(x, y, "Y:"));
510         y += title4->get_h() + margin;
511         add_subwindow(title5 = new BC_Title(x, y, "U:"));
512         y += title5->get_h() + margin;
513         add_subwindow(title6 = new BC_Title(x, y, "V:"));
514
515         add_subwindow(current = new BC_Title(x2, title0->get_y(), ""));
516
517         radius = new CWindowCoord(this, x2, title7->get_y(),
518                 mwindow->edl->session->eyedrop_radius);
519         radius->create_objects();
520         radius->set_boundaries((int64_t)0, (int64_t)255);
521
522         add_subwindow(red = new BC_Title(x2, title1->get_y(), "0"));
523         add_subwindow(green = new BC_Title(x2, title2->get_y(), "0"));
524         add_subwindow(blue = new BC_Title(x2, title3->get_y(), "0"));
525         add_subwindow(rgb_hex = new BC_Title(x3, red->get_y(), "#000000"));
526
527         add_subwindow(this->y = new BC_Title(x2, title4->get_y(), "0"));
528         add_subwindow(this->u = new BC_Title(x2, title5->get_y(), "0"));
529         add_subwindow(this->v = new BC_Title(x2, title6->get_y(), "0"));
530         add_subwindow(yuv_hex = new BC_Title(x3, this->y->get_y(), "#000000"));
531
532         y = title6->get_y() + this->v->get_h() + 2*margin;
533         add_subwindow(sample = new BC_SubWindow(x, y, 50, 50));
534         y += sample->get_h() + margin;
535         add_subwindow(use_max = new CWindowEyedropCheckBox(mwindow, this, x, y));
536         update();
537         unlock_window();
538 }
539
540 void CWindowEyedropGUI::update()
541 {
542         char string[BCTEXTLEN];
543         sprintf(string, "%d, %d",
544                 thread->gui->eyedrop_x,
545                 thread->gui->eyedrop_y);
546         current->update(string);
547
548         radius->update((int64_t)mwindow->edl->session->eyedrop_radius);
549
550         LocalSession *local_session = mwindow->edl->local_session;
551         int use_max = local_session->use_max;
552         float r = use_max ? local_session->red_max : local_session->red;
553         float g = use_max ? local_session->green_max : local_session->green;
554         float b = use_max ? local_session->blue_max : local_session->blue;
555         this->red->update(r);
556         this->green->update(g);
557         this->blue->update(b);
558
559         int rx = 255*r + 0.5;  bclamp(rx,0,255);
560         int gx = 255*g + 0.5;  bclamp(gx,0,255);
561         int bx = 255*b + 0.5;  bclamp(bx,0,255);
562         char rgb_text[BCSTRLEN];
563         sprintf(rgb_text, "#%02x%02x%02x", rx, gx, bx);
564         rgb_hex->update(rgb_text);
565         
566         float y, u, v;
567         YUV::yuv.rgb_to_yuv_f(r, g, b, y, u, v);
568         this->y->update(y);
569         this->u->update(u);  u += 0.5;
570         this->v->update(v);  v += 0.5;
571
572         int yx = 255*y + 0.5;  bclamp(yx,0,255);
573         int ux = 255*u + 0.5;  bclamp(ux,0,255);
574         int vx = 255*v + 0.5;  bclamp(vx,0,255);
575         char yuv_text[BCSTRLEN];
576         sprintf(yuv_text, "#%02x%02x%02x", yx, ux, vx);
577         yuv_hex->update(yuv_text);
578
579         int rgb = (rx << 16) | (gx << 8) | (bx << 0);
580         sample->set_color(rgb);
581         sample->draw_box(0, 0, sample->get_w(), sample->get_h());
582         sample->set_color(BLACK);
583         sample->draw_rectangle(0, 0, sample->get_w(), sample->get_h());
584         sample->flash();
585 }
586
587 void CWindowEyedropGUI::handle_event()
588 {
589         int new_radius = atoi(radius->get_text());
590         if(new_radius != mwindow->edl->session->eyedrop_radius)
591         {
592                 CWindowGUI *gui = mwindow->cwindow->gui;
593                 if(gui->eyedrop_visible)
594                 {
595                         gui->lock_window("CWindowEyedropGUI::handle_event");
596 // hide it
597                         int rerender;
598                         gui->canvas->do_eyedrop(rerender, 0, 1);
599                 }
600
601                 mwindow->edl->session->eyedrop_radius = new_radius;
602
603                 if(gui->eyedrop_visible)
604                 {
605 // draw it
606                         int rerender;
607                         gui->canvas->do_eyedrop(rerender, 0, 1);
608                         gui->unlock_window();
609                 }
610         }
611 }
612
613
614
615 /* Buttons to control Keyframe-Curve-Mode for Projector or Camera */
616
617 // Configuration for all possible Keyframe Curve Mode toggles
618 struct _CVD {
619         FloatAuto::t_mode mode;
620         bool use_camera;
621         const char* icon_id;
622         const char* tooltip;
623 };
624
625 const _CVD Camera_Crv_Smooth =
626         {       FloatAuto::SMOOTH,
627                 true,
628                 "tan_smooth",
629                 N_("\"smooth\" Curve on current Camera Keyframes")
630         };
631 const _CVD Camera_Crv_Linear =
632         {       FloatAuto::LINEAR,
633                 true,
634                 "tan_linear",
635                 N_("\"linear\" Curve on current Camera Keyframes")
636         };
637 const _CVD Projector_Crv_Smooth =
638         {       FloatAuto::SMOOTH,
639                 false,
640                 "tan_smooth",
641                 N_("\"smooth\" Curve on current Projector Keyframes")
642         };
643 const _CVD Projector_Crv_Linear =
644         {       FloatAuto::LINEAR,
645                 false,
646                 "tan_linear",
647                 N_("\"linear\" Curve on current Projector Keyframes")
648         };
649
650 // Implementation Class für Keyframe Curve Mode buttons
651 //
652 // This button reflects the state of the "current" keyframe
653 // (the nearest keyframe on the left) for all three automation
654 // lines together. Clicking on this button (re)sets the curve
655 // mode for the three "current" keyframes simultanously, but
656 // never creates a new keyframe.
657 //
658 class CWindowCurveToggle : public BC_Toggle
659 {
660 public:
661         CWindowCurveToggle(_CVD mode, MWindow *mwindow, CWindowToolGUI *gui, int x, int y);
662         void check_toggle_state(FloatAuto *x, FloatAuto *y, FloatAuto *z);
663         int handle_event();
664 private:
665         _CVD cfg;
666         MWindow *mwindow;
667         CWindowToolGUI *gui;
668 };
669
670
671 CWindowCurveToggle::CWindowCurveToggle(_CVD mode, MWindow *mwindow, CWindowToolGUI *gui, int x, int y)
672  : BC_Toggle(x, y, mwindow->theme->get_image_set(mode.icon_id), false),
673    cfg(mode)
674 {
675         this->gui = gui;
676         this->mwindow = mwindow;
677         set_tooltip(_(cfg.tooltip));
678 }
679
680 void CWindowCurveToggle::check_toggle_state(FloatAuto *x, FloatAuto *y, FloatAuto *z)
681 {
682 // the toggle state is only set to ON if all
683 // three automation lines have the same curve mode.
684 // For mixed states the toggle stays off.
685         set_value( x->curve_mode == this->cfg.mode &&
686                    y->curve_mode == this->cfg.mode &&
687                    z->curve_mode == this->cfg.mode
688                  ,true // redraw to show new state
689                  );
690 }
691
692 int CWindowCurveToggle::handle_event()
693 {
694         FloatAuto *x=0, *y=0, *z=0;
695         Track *track = mwindow->cwindow->calculate_affected_track();
696
697         if(track)
698         {       mwindow->cwindow->calculate_affected_autos(&x, &y, &z,
699                         track, cfg.use_camera, 0,0,0); // don't create new keyframe
700
701                 if(x)   x->change_curve_mode(cfg.mode);
702                 if(y)   y->change_curve_mode(cfg.mode);
703                 if(z)   z->change_curve_mode(cfg.mode);
704
705                 gui->update();
706                 gui->update_preview();
707         }
708
709         return 1;
710 }
711
712
713 CWindowEyedropCheckBox::CWindowEyedropCheckBox(MWindow *mwindow, 
714         CWindowEyedropGUI *gui, int x, int y)
715  : BC_CheckBox(x, y, mwindow->edl->local_session->use_max, _("Use maximum"))
716 {
717         this->mwindow = mwindow;
718         this->gui = gui;
719 }
720
721 int CWindowEyedropCheckBox::handle_event()
722 {
723         mwindow->edl->local_session->use_max = get_value();
724         
725         gui->update();
726         return 1;
727 }
728
729
730 CWindowCameraGUI::CWindowCameraGUI(MWindow *mwindow, CWindowTool *thread)
731  : CWindowToolGUI(mwindow,
732         thread,
733         _(PROGRAM_NAME ": Camera"),
734         170,
735         170)
736 {
737 }
738 CWindowCameraGUI::~CWindowCameraGUI()
739 {
740 }
741
742 void CWindowCameraGUI::create_objects()
743 {
744         int x = 10, y = 10, x1;
745         Track *track = mwindow->cwindow->calculate_affected_track();
746         FloatAuto *x_auto = 0;
747         FloatAuto *y_auto = 0;
748         FloatAuto *z_auto = 0;
749         BC_Title *title;
750         BC_Button *button;
751
752         lock_window("CWindowCameraGUI::create_objects");
753         if(track)
754         {
755                 mwindow->cwindow->calculate_affected_autos(&x_auto,
756                         &y_auto, &z_auto, track, 1, 0, 0, 0);
757         }
758
759         add_subwindow(title = new BC_Title(x, y, "X:"));
760         x += title->get_w();
761         this->x = new CWindowCoord(this, x, y,
762                 x_auto ? x_auto->get_value() : (float)0);
763         this->x->create_objects();
764
765
766         y += 30;
767         x = 10;
768         add_subwindow(title = new BC_Title(x, y, "Y:"));
769         x += title->get_w();
770         this->y = new CWindowCoord(this, x, y,
771                 y_auto ? y_auto->get_value() : (float)0);
772         this->y->create_objects();
773         y += 30;
774         x = 10;
775         add_subwindow(title = new BC_Title(x, y, "Z:"));
776         x += title->get_w();
777         this->z = new CWindowCoord(this, x, y,
778                 z_auto ? z_auto->get_value() : (float)1);
779         this->z->create_objects();
780         this->z->set_increment(0.01);
781
782         y += 30;
783         x1 = 10;
784         add_subwindow(button = new CWindowCameraLeft(mwindow, this, x1, y));
785         x1 += button->get_w();
786         add_subwindow(button = new CWindowCameraCenter(mwindow, this, x1, y));
787         x1 += button->get_w();
788         add_subwindow(button = new CWindowCameraRight(mwindow, this, x1, y));
789
790         y += button->get_h();
791         x1 = 10;
792         add_subwindow(button = new CWindowCameraTop(mwindow, this, x1, y));
793         x1 += button->get_w();
794         add_subwindow(button = new CWindowCameraMiddle(mwindow, this, x1, y));
795         x1 += button->get_w();
796         add_subwindow(button = new CWindowCameraBottom(mwindow, this, x1, y));
797 // additional Buttons to control the curve mode of the "current" keyframe
798         x1 += button->get_w() + 15;
799         add_subwindow(this->t_smooth = new CWindowCurveToggle(Camera_Crv_Smooth, mwindow, this, x1, y));
800         x1 += button->get_w();
801         add_subwindow(this->t_linear = new CWindowCurveToggle(Camera_Crv_Linear, mwindow, this, x1, y));
802
803 // fill in current auto keyframe values, set toggle states.
804         this->update();
805         unlock_window();
806 }
807
808 void CWindowCameraGUI::update_preview()
809 {
810         mwindow->gui->lock_window("CWindowCameraGUI::update_preview");
811         mwindow->restart_brender();
812         mwindow->gui->draw_overlays(1);
813         mwindow->sync_parameters(CHANGE_PARAMS);
814         mwindow->gui->unlock_window();
815         mwindow->cwindow->refresh_frame(CHANGE_NONE);
816         mwindow->cwindow->gui->lock_window("CWindowCameraGUI::update_preview");
817         mwindow->cwindow->gui->canvas->draw_refresh();
818         mwindow->cwindow->gui->unlock_window();
819 }
820
821
822 void CWindowCameraGUI::handle_event()
823 {
824         FloatAuto *x_auto = 0;
825         FloatAuto *y_auto = 0;
826         FloatAuto *z_auto = 0;
827         Track *track = mwindow->cwindow->calculate_affected_track();
828         if(track)
829         {
830                 mwindow->undo->update_undo_before(_("camera"), this);
831                 if(event_caller == x)
832                 {
833                         x_auto = (FloatAuto*)mwindow->cwindow->calculate_affected_auto(
834                                 track->automation->autos[AUTOMATION_CAMERA_X],
835                                 1);
836                         if(x_auto)
837                         {
838                                 x_auto->set_value(atof(x->get_text()));
839                                 update();
840                                 update_preview();
841                         }
842                 }
843                 else
844                 if(event_caller == y)
845                 {
846                         y_auto = (FloatAuto*)mwindow->cwindow->calculate_affected_auto(
847                                 track->automation->autos[AUTOMATION_CAMERA_Y],
848                                 1);
849                         if(y_auto)
850                         {
851                                 y_auto->set_value(atof(y->get_text()));
852                                 update();
853                                 update_preview();
854                         }
855                 }
856                 else
857                 if(event_caller == z)
858                 {
859                         z_auto = (FloatAuto*)mwindow->cwindow->calculate_affected_auto(
860                                 track->automation->autos[AUTOMATION_CAMERA_Z],
861                                 1);
862                         if(z_auto)
863                         {
864                                 float zoom = atof(z->get_text());
865                                 if(zoom > 100.) zoom = 100.;
866                                 else
867                                 if(zoom < 0.01) zoom = 0.01;
868         // Doesn't allow user to enter from scratch
869         //              if(zoom != atof(z->get_text()))
870         //                      z->update(zoom);
871
872                                 z_auto->set_value(zoom);
873                                 mwindow->gui->lock_window("CWindowCameraGUI::handle_event");
874                                 mwindow->gui->draw_overlays(1);
875                                 mwindow->gui->unlock_window();
876                                 update();
877                                 update_preview();
878                         }
879                 }
880
881                 mwindow->undo->update_undo_after(_("camera"), LOAD_ALL);
882         }
883 }
884
885 void CWindowCameraGUI::update()
886 {
887         FloatAuto *x_auto = 0;
888         FloatAuto *y_auto = 0;
889         FloatAuto *z_auto = 0;
890         Track *track = mwindow->cwindow->calculate_affected_track();
891
892         if(track)
893         {
894                 mwindow->cwindow->calculate_affected_autos(&x_auto,
895                         &y_auto,
896                         &z_auto,
897                         track,
898                         1,
899                         0,
900                         0,
901                         0);
902         }
903
904         if(x_auto)
905                 x->update(x_auto->get_value());
906         if(y_auto)
907                 y->update(y_auto->get_value());
908         if(z_auto) {
909                 float value = z_auto->get_value();
910                 z->update(value);
911                 thread->gui->composite_panel->cpanel_zoom->update(value);
912         }
913
914         if( x_auto && y_auto && z_auto )
915         {
916                 t_smooth->check_toggle_state(x_auto, y_auto, z_auto);
917                 t_linear->check_toggle_state(x_auto, y_auto, z_auto);
918         }
919 }
920
921
922
923
924 CWindowCameraLeft::CWindowCameraLeft(MWindow *mwindow, CWindowCameraGUI *gui, int x, int y)
925  : BC_Button(x, y, mwindow->theme->get_image_set("left_justify"))
926 {
927         this->gui = gui;
928         this->mwindow = mwindow;
929         set_tooltip(_("Left justify"));
930 }
931 int CWindowCameraLeft::handle_event()
932 {
933         FloatAuto *x_auto = 0;
934         FloatAuto *z_auto = 0;
935         Track *track = mwindow->cwindow->calculate_affected_track();
936         if(track)
937         {
938                 mwindow->cwindow->calculate_affected_autos(&x_auto,
939                         0,
940                         &z_auto,
941                         track,
942                         1,
943                         1,
944                         0,
945                         0);
946         }
947
948         if(x_auto && z_auto)
949         {
950                 int w = 0, h = 0;
951                 track->get_source_dimensions(
952                         mwindow->edl->local_session->get_selectionstart(1),
953                         w,
954                         h);
955
956                 if(w && h)
957                 {
958                         mwindow->undo->update_undo_before(_("camera"), 0);
959                         x_auto->set_value(
960                                 (double)track->track_w / z_auto->get_value() / 2 -
961                                 (double)w / 2);
962                         mwindow->undo->update_undo_after(_("camera"), LOAD_ALL);
963                         gui->update();
964                         gui->update_preview();
965                 }
966         }
967
968         return 1;
969 }
970
971
972 CWindowCameraCenter::CWindowCameraCenter(MWindow *mwindow, CWindowCameraGUI *gui, int x, int y)
973  : BC_Button(x, y, mwindow->theme->get_image_set("center_justify"))
974 {
975         this->gui = gui;
976         this->mwindow = mwindow;
977         set_tooltip(_("Center horizontal"));
978 }
979 int CWindowCameraCenter::handle_event()
980 {
981         FloatAuto *x_auto = 0;
982         Track *track = mwindow->cwindow->calculate_affected_track();
983         if(track)
984                 x_auto = (FloatAuto*)mwindow->cwindow->calculate_affected_auto(
985                         track->automation->autos[AUTOMATION_CAMERA_X],
986                         1);
987
988         if(x_auto)
989         {
990                 mwindow->undo->update_undo_before(_("camera"), 0);
991                 x_auto->set_value(0);
992                 gui->update();
993                 gui->update_preview();
994                 mwindow->undo->update_undo_after(_("camera"), LOAD_ALL);
995         }
996
997         return 1;
998 }
999
1000
1001 CWindowCameraRight::CWindowCameraRight(MWindow *mwindow, CWindowCameraGUI *gui, int x, int y)
1002  : BC_Button(x, y, mwindow->theme->get_image_set("right_justify"))
1003 {
1004         this->gui = gui;
1005         this->mwindow = mwindow;
1006         set_tooltip(_("Right justify"));
1007 }
1008 int CWindowCameraRight::handle_event()
1009 {
1010         FloatAuto *x_auto = 0;
1011         FloatAuto *z_auto = 0;
1012         Track *track = mwindow->cwindow->calculate_affected_track();
1013         if(track)
1014         {
1015                 mwindow->cwindow->calculate_affected_autos(&x_auto,
1016                         0,
1017                         &z_auto,
1018                         track,
1019                         1,
1020                         1,
1021                         0,
1022                         0);
1023         }
1024
1025         if(x_auto && z_auto)
1026         {
1027                 int w = 0, h = 0;
1028                 track->get_source_dimensions(
1029                         mwindow->edl->local_session->get_selectionstart(1),
1030                         w,
1031                         h);
1032
1033                 if(w && h)
1034                 {
1035                         mwindow->undo->update_undo_before(_("camera"), 0);
1036                         x_auto->set_value( -((double)track->track_w / z_auto->get_value() / 2 -
1037                                 (double)w / 2));
1038                         gui->update();
1039                         gui->update_preview();
1040                         mwindow->undo->update_undo_after(_("camera"), LOAD_ALL);
1041                 }
1042         }
1043
1044         return 1;
1045 }
1046
1047
1048 CWindowCameraTop::CWindowCameraTop(MWindow *mwindow, CWindowCameraGUI *gui, int x, int y)
1049  : BC_Button(x, y, mwindow->theme->get_image_set("top_justify"))
1050 {
1051         this->gui = gui;
1052         this->mwindow = mwindow;
1053         set_tooltip(_("Top justify"));
1054 }
1055 int CWindowCameraTop::handle_event()
1056 {
1057         FloatAuto *y_auto = 0;
1058         FloatAuto *z_auto = 0;
1059         Track *track = mwindow->cwindow->calculate_affected_track();
1060         if(track)
1061         {
1062                 mwindow->cwindow->calculate_affected_autos(0,
1063                         &y_auto,
1064                         &z_auto,
1065                         track,
1066                         1,
1067                         0,
1068                         1,
1069                         0);
1070         }
1071
1072         if(y_auto && z_auto)
1073         {
1074                 int w = 0, h = 0;
1075                 track->get_source_dimensions(
1076                         mwindow->edl->local_session->get_selectionstart(1),
1077                         w,
1078                         h);
1079
1080                 if(w && h)
1081                 {
1082                         mwindow->undo->update_undo_before(_("camera"), 0);
1083                         y_auto->set_value((double)track->track_h / z_auto->get_value() / 2 -
1084                                 (double)h / 2);
1085                         gui->update();
1086                         gui->update_preview();
1087                         mwindow->undo->update_undo_after(_("camera"), LOAD_ALL);
1088                 }
1089         }
1090
1091         return 1;
1092 }
1093
1094
1095 CWindowCameraMiddle::CWindowCameraMiddle(MWindow *mwindow, CWindowCameraGUI *gui, int x, int y)
1096  : BC_Button(x, y, mwindow->theme->get_image_set("middle_justify"))
1097 {
1098         this->gui = gui;
1099         this->mwindow = mwindow;
1100         set_tooltip(_("Center vertical"));
1101 }
1102 int CWindowCameraMiddle::handle_event()
1103 {
1104         FloatAuto *y_auto = 0;
1105         Track *track = mwindow->cwindow->calculate_affected_track();
1106         if(track)
1107                 y_auto = (FloatAuto*)mwindow->cwindow->calculate_affected_auto(
1108                         track->automation->autos[AUTOMATION_CAMERA_Y], 1);
1109
1110         if(y_auto)
1111         {
1112                 mwindow->undo->update_undo_before(_("camera"), 0);
1113                 y_auto->set_value(0);
1114                 gui->update();
1115                 gui->update_preview();
1116                 mwindow->undo->update_undo_after(_("camera"), LOAD_ALL);
1117         }
1118
1119         return 1;
1120 }
1121
1122
1123 CWindowCameraBottom::CWindowCameraBottom(MWindow *mwindow, CWindowCameraGUI *gui, int x, int y)
1124  : BC_Button(x, y, mwindow->theme->get_image_set("bottom_justify"))
1125 {
1126         this->gui = gui;
1127         this->mwindow = mwindow;
1128         set_tooltip(_("Bottom justify"));
1129 }
1130 int CWindowCameraBottom::handle_event()
1131 {
1132         FloatAuto *y_auto = 0;
1133         FloatAuto *z_auto = 0;
1134         Track *track = mwindow->cwindow->calculate_affected_track();
1135         if(track)
1136         {
1137                 mwindow->cwindow->calculate_affected_autos(0,
1138                         &y_auto,
1139                         &z_auto,
1140                         track,
1141                         1,
1142                         0,
1143                         1,
1144                         0);
1145         }
1146
1147         if(y_auto && z_auto)
1148         {
1149                 int w = 0, h = 0;
1150                 track->get_source_dimensions(
1151                         mwindow->edl->local_session->get_selectionstart(1),
1152                         w,
1153                         h);
1154
1155                 if(w && h)
1156                 {
1157                         mwindow->undo->update_undo_before(_("camera"), 0);
1158                         y_auto->set_value(-((double)track->track_h / z_auto->get_value() / 2 -
1159                                 (double)h / 2));
1160                         gui->update();
1161                         gui->update_preview();
1162                         mwindow->undo->update_undo_after(_("camera"), LOAD_ALL);
1163                 }
1164         }
1165
1166         return 1;
1167 }
1168
1169
1170 CWindowProjectorGUI::CWindowProjectorGUI(MWindow *mwindow, CWindowTool *thread)
1171  : CWindowToolGUI(mwindow,
1172         thread,
1173         _(PROGRAM_NAME ": Projector"),
1174         170,
1175         170)
1176 {
1177 }
1178 CWindowProjectorGUI::~CWindowProjectorGUI()
1179 {
1180 }
1181 void CWindowProjectorGUI::create_objects()
1182 {
1183         int x = 10, y = 10, x1;
1184         Track *track = mwindow->cwindow->calculate_affected_track();
1185         FloatAuto *x_auto = 0;
1186         FloatAuto *y_auto = 0;
1187         FloatAuto *z_auto = 0;
1188         BC_Title *title;
1189         BC_Button *button;
1190
1191         lock_window("CWindowProjectorGUI::create_objects");
1192         if(track)
1193         {
1194                 mwindow->cwindow->calculate_affected_autos(&x_auto,
1195                         &y_auto,
1196                         &z_auto,
1197                         track,
1198                         0,
1199                         0,
1200                         0,
1201                         0);
1202         }
1203
1204         add_subwindow(title = new BC_Title(x, y, "X:"));
1205         x += title->get_w();
1206         this->x = new CWindowCoord(this, x, y,
1207                 x_auto ? x_auto->get_value() : (float)0);
1208         this->x->create_objects();
1209         y += 30;
1210         x = 10;
1211         add_subwindow(title = new BC_Title(x, y, "Y:"));
1212         x += title->get_w();
1213         this->y = new CWindowCoord(this, x, y,
1214                 y_auto ? y_auto->get_value() : (float)0);
1215         this->y->create_objects();
1216         y += 30;
1217         x = 10;
1218         add_subwindow(title = new BC_Title(x, y, "Z:"));
1219         x += title->get_w();
1220         this->z = new CWindowCoord(this, x, y,
1221                 z_auto ? z_auto->get_value() : (float)1);
1222         this->z->create_objects();
1223         this->z->set_increment(0.01);
1224
1225         y += 30;
1226         x1 = 10;
1227         add_subwindow(button = new CWindowProjectorLeft(mwindow, this, x1, y));
1228         x1 += button->get_w();
1229         add_subwindow(button = new CWindowProjectorCenter(mwindow, this, x1, y));
1230         x1 += button->get_w();
1231         add_subwindow(button = new CWindowProjectorRight(mwindow, this, x1, y));
1232
1233         y += button->get_h();
1234         x1 = 10;
1235         add_subwindow(button = new CWindowProjectorTop(mwindow, this, x1, y));
1236         x1 += button->get_w();
1237         add_subwindow(button = new CWindowProjectorMiddle(mwindow, this, x1, y));
1238         x1 += button->get_w();
1239         add_subwindow(button = new CWindowProjectorBottom(mwindow, this, x1, y));
1240
1241 // additional Buttons to control the curve mode of the "current" keyframe
1242         x1 += button->get_w() + 15;
1243         add_subwindow(this->t_smooth = new CWindowCurveToggle(Projector_Crv_Smooth, mwindow, this, x1, y));
1244         x1 += button->get_w();
1245         add_subwindow(this->t_linear = new CWindowCurveToggle(Projector_Crv_Linear, mwindow, this, x1, y));
1246
1247 // fill in current auto keyframe values, set toggle states.
1248         this->update();
1249         unlock_window();
1250 }
1251
1252 void CWindowProjectorGUI::update_preview()
1253 {
1254         mwindow->gui->lock_window("CWindowProjectorGUI::update_preview");
1255         mwindow->restart_brender();
1256         mwindow->sync_parameters(CHANGE_PARAMS);
1257         mwindow->gui->draw_overlays(1);
1258         mwindow->gui->unlock_window();
1259         mwindow->cwindow->refresh_frame(CHANGE_NONE);
1260         mwindow->cwindow->gui->lock_window("CWindowProjectorGUI::update_preview");
1261         mwindow->cwindow->gui->canvas->draw_refresh();
1262         mwindow->cwindow->gui->unlock_window();
1263 }
1264
1265 void CWindowProjectorGUI::handle_event()
1266 {
1267         FloatAuto *x_auto = 0;
1268         FloatAuto *y_auto = 0;
1269         FloatAuto *z_auto = 0;
1270         Track *track = mwindow->cwindow->calculate_affected_track();
1271
1272         if(track)
1273         {
1274                 mwindow->undo->update_undo_before(_("projector"), this);
1275                 if(event_caller == x)
1276                 {
1277                         x_auto = (FloatAuto*)mwindow->cwindow->calculate_affected_auto(
1278                                 track->automation->autos[AUTOMATION_PROJECTOR_X],
1279                                 1);
1280                         if(x_auto)
1281                         {
1282                                 x_auto->set_value(atof(x->get_text()));
1283                                 update();
1284                                 update_preview();
1285                         }
1286                 }
1287                 else
1288                 if(event_caller == y)
1289                 {
1290                         y_auto = (FloatAuto*)mwindow->cwindow->calculate_affected_auto(
1291                                 track->automation->autos[AUTOMATION_PROJECTOR_Y],
1292                                 1);
1293                         if(y_auto)
1294                         {
1295                                 y_auto->set_value(atof(y->get_text()));
1296                                 update();
1297                                 update_preview();
1298                         }
1299                 }
1300                 else
1301                 if(event_caller == z)
1302                 {
1303                         z_auto = (FloatAuto*)mwindow->cwindow->calculate_affected_auto(
1304                                 track->automation->autos[AUTOMATION_PROJECTOR_Z],
1305                                 1);
1306                         if(z_auto)
1307                         {
1308                                 float zoom = atof(z->get_text());
1309                                 if(zoom > 100.) zoom = 100.;
1310                                 else if(zoom < 0.01) zoom = 0.01;
1311 //                      if (zoom != atof(z->get_text()))
1312 //                              z->update(zoom);
1313                                 z_auto->set_value(zoom);
1314
1315                                 mwindow->gui->lock_window("CWindowProjectorGUI::handle_event");
1316                                 mwindow->gui->draw_overlays(1);
1317                                 mwindow->gui->unlock_window();
1318
1319                                 update();
1320                                 update_preview();
1321                         }
1322                 }
1323                 mwindow->undo->update_undo_after(_("projector"), LOAD_ALL);
1324         }
1325 }
1326
1327 void CWindowProjectorGUI::update()
1328 {
1329         FloatAuto *x_auto = 0;
1330         FloatAuto *y_auto = 0;
1331         FloatAuto *z_auto = 0;
1332         Track *track = mwindow->cwindow->calculate_affected_track();
1333
1334         if(track)
1335         {
1336                 mwindow->cwindow->calculate_affected_autos(&x_auto,
1337                         &y_auto,
1338                         &z_auto,
1339                         track,
1340                         0,
1341                         0,
1342                         0,
1343                         0);
1344         }
1345
1346         if(x_auto)
1347                 x->update(x_auto->get_value());
1348         if(y_auto)
1349                 y->update(y_auto->get_value());
1350         if(z_auto) {
1351                 float value = z_auto->get_value();
1352                 z->update(value);
1353                 thread->gui->composite_panel->cpanel_zoom->update(value);
1354         }
1355
1356         if( x_auto && y_auto && z_auto )
1357         {
1358                 t_smooth->check_toggle_state(x_auto, y_auto, z_auto);
1359                 t_linear->check_toggle_state(x_auto, y_auto, z_auto);
1360         }
1361 }
1362
1363 CWindowProjectorLeft::CWindowProjectorLeft(MWindow *mwindow, CWindowProjectorGUI *gui, int x, int y)
1364  : BC_Button(x, y, mwindow->theme->get_image_set("left_justify"))
1365 {
1366         this->gui = gui;
1367         this->mwindow = mwindow;
1368         set_tooltip(_("Left justify"));
1369 }
1370 int CWindowProjectorLeft::handle_event()
1371 {
1372         FloatAuto *x_auto = 0;
1373         FloatAuto *z_auto = 0;
1374         Track *track = mwindow->cwindow->calculate_affected_track();
1375         if(track)
1376         {
1377                 mwindow->cwindow->calculate_affected_autos(&x_auto,
1378                         0,
1379                         &z_auto,
1380                         track,
1381                         0,
1382                         1,
1383                         0,
1384                         0);
1385         }
1386         if(x_auto && z_auto)
1387         {
1388                 mwindow->undo->update_undo_before(_("projector"), 0);
1389                 x_auto->set_value( (double)track->track_w * z_auto->get_value() / 2 -
1390                         (double)mwindow->edl->session->output_w / 2 );
1391                 gui->update();
1392                 gui->update_preview();
1393                 mwindow->undo->update_undo_after(_("projector"), LOAD_ALL);
1394         }
1395
1396         return 1;
1397 }
1398
1399
1400 CWindowProjectorCenter::CWindowProjectorCenter(MWindow *mwindow, CWindowProjectorGUI *gui, int x, int y)
1401  : BC_Button(x, y, mwindow->theme->get_image_set("center_justify"))
1402 {
1403         this->gui = gui;
1404         this->mwindow = mwindow;
1405         set_tooltip(_("Center horizontal"));
1406 }
1407 int CWindowProjectorCenter::handle_event()
1408 {
1409         FloatAuto *x_auto = 0;
1410         Track *track = mwindow->cwindow->calculate_affected_track();
1411         if(track)
1412                 x_auto = (FloatAuto*)mwindow->cwindow->calculate_affected_auto(
1413                         track->automation->autos[AUTOMATION_PROJECTOR_X],
1414                         1);
1415
1416         if(x_auto)
1417         {
1418                 mwindow->undo->update_undo_before(_("projector"), 0);
1419                 x_auto->set_value(0);
1420                 gui->update();
1421                 gui->update_preview();
1422                 mwindow->undo->update_undo_after(_("projector"), LOAD_ALL);
1423         }
1424
1425         return 1;
1426 }
1427
1428
1429 CWindowProjectorRight::CWindowProjectorRight(MWindow *mwindow, CWindowProjectorGUI *gui, int x, int y)
1430  : BC_Button(x, y, mwindow->theme->get_image_set("right_justify"))
1431 {
1432         this->gui = gui;
1433         this->mwindow = mwindow;
1434         set_tooltip(_("Right justify"));
1435 }
1436 int CWindowProjectorRight::handle_event()
1437 {
1438         FloatAuto *x_auto = 0;
1439         FloatAuto *z_auto = 0;
1440         Track *track = mwindow->cwindow->calculate_affected_track();
1441         if(track)
1442         {
1443                 mwindow->cwindow->calculate_affected_autos(&x_auto,
1444                         0,
1445                         &z_auto,
1446                         track,
1447                         0,
1448                         1,
1449                         0,
1450                         0);
1451         }
1452
1453         if(x_auto && z_auto)
1454         {
1455                 mwindow->undo->update_undo_before(_("projector"), 0);
1456                 x_auto->set_value( -((double)track->track_w * z_auto->get_value() / 2 -
1457                         (double)mwindow->edl->session->output_w / 2));
1458                 gui->update();
1459                 gui->update_preview();
1460                 mwindow->undo->update_undo_after(_("projector"), LOAD_ALL);
1461         }
1462
1463         return 1;
1464 }
1465
1466
1467 CWindowProjectorTop::CWindowProjectorTop(MWindow *mwindow, CWindowProjectorGUI *gui, int x, int y)
1468  : BC_Button(x, y, mwindow->theme->get_image_set("top_justify"))
1469 {
1470         this->gui = gui;
1471         this->mwindow = mwindow;
1472         set_tooltip(_("Top justify"));
1473 }
1474 int CWindowProjectorTop::handle_event()
1475 {
1476         FloatAuto *y_auto = 0;
1477         FloatAuto *z_auto = 0;
1478         Track *track = mwindow->cwindow->calculate_affected_track();
1479         if(track)
1480         {
1481                 mwindow->cwindow->calculate_affected_autos(0,
1482                         &y_auto,
1483                         &z_auto,
1484                         track,
1485                         0,
1486                         0,
1487                         1,
1488                         0);
1489         }
1490
1491         if(y_auto && z_auto)
1492         {
1493                 mwindow->undo->update_undo_before(_("projector"), 0);
1494                 y_auto->set_value( (double)track->track_h * z_auto->get_value() / 2 -
1495                         (double)mwindow->edl->session->output_h / 2 );
1496                 gui->update();
1497                 gui->update_preview();
1498                 mwindow->undo->update_undo_after(_("projector"), LOAD_ALL);
1499         }
1500
1501         return 1;
1502 }
1503
1504
1505 CWindowProjectorMiddle::CWindowProjectorMiddle(MWindow *mwindow, CWindowProjectorGUI *gui, int x, int y)
1506  : BC_Button(x, y, mwindow->theme->get_image_set("middle_justify"))
1507 {
1508         this->gui = gui;
1509         this->mwindow = mwindow;
1510         set_tooltip(_("Center vertical"));
1511 }
1512 int CWindowProjectorMiddle::handle_event()
1513 {
1514         FloatAuto *y_auto = 0;
1515         Track *track = mwindow->cwindow->calculate_affected_track();
1516         if(track)
1517                 y_auto = (FloatAuto*)mwindow->cwindow->calculate_affected_auto(
1518                         track->automation->autos[AUTOMATION_PROJECTOR_Y], 1);
1519
1520         if(y_auto)
1521         {
1522                 mwindow->undo->update_undo_before(_("projector"), 0);
1523                 y_auto->set_value(0);
1524                 gui->update();
1525                 gui->update_preview();
1526                 mwindow->undo->update_undo_after(_("projector"), LOAD_ALL);
1527         }
1528
1529         return 1;
1530 }
1531
1532
1533 CWindowProjectorBottom::CWindowProjectorBottom(MWindow *mwindow, CWindowProjectorGUI *gui, int x, int y)
1534  : BC_Button(x, y, mwindow->theme->get_image_set("bottom_justify"))
1535 {
1536         this->gui = gui;
1537         this->mwindow = mwindow;
1538         set_tooltip(_("Bottom justify"));
1539 }
1540 int CWindowProjectorBottom::handle_event()
1541 {
1542         FloatAuto *y_auto = 0;
1543         FloatAuto *z_auto = 0;
1544         Track *track = mwindow->cwindow->calculate_affected_track();
1545         if(track)
1546         {
1547                 mwindow->cwindow->calculate_affected_autos(0,
1548                         &y_auto,
1549                         &z_auto,
1550                         track,
1551                         0,
1552                         0,
1553                         1,
1554                         0);
1555         }
1556
1557         if(y_auto && z_auto)
1558         {
1559                 mwindow->undo->update_undo_before(_("projector"), 0);
1560                 y_auto->set_value( -((double)track->track_h * z_auto->get_value() / 2 -
1561                         (double)mwindow->edl->session->output_h / 2));
1562                 gui->update();
1563                 gui->update_preview();
1564                 mwindow->undo->update_undo_after(_("projector"), LOAD_ALL);
1565         }
1566
1567         return 1;
1568 }
1569
1570
1571 CWindowMaskMode::CWindowMaskMode(MWindow *mwindow,
1572         CWindowToolGUI *gui, int x, int y, const char *text)
1573  : BC_PopupMenu(x, y, 220, text, 1)
1574 {
1575         this->mwindow = mwindow;
1576         this->gui = gui;
1577 }
1578
1579 void CWindowMaskMode::create_objects()
1580 {
1581         add_item(new BC_MenuItem(mode_to_text(MASK_MULTIPLY_ALPHA)));
1582         add_item(new BC_MenuItem(mode_to_text(MASK_SUBTRACT_ALPHA)));
1583 }
1584
1585 char* CWindowMaskMode::mode_to_text(int mode)
1586 {
1587         switch(mode)
1588         {
1589                 case MASK_MULTIPLY_ALPHA:
1590                         return _("Multiply alpha");
1591                         break;
1592
1593                 case MASK_SUBTRACT_ALPHA:
1594                         return _("Subtract alpha");
1595                         break;
1596         }
1597
1598         return _("Subtract alpha");
1599 }
1600
1601 int CWindowMaskMode::text_to_mode(char *text)
1602 {
1603         if(!strcasecmp(text, _("Multiply alpha")))
1604                 return MASK_MULTIPLY_ALPHA;
1605         else
1606         if(!strcasecmp(text, _("Subtract alpha")))
1607                 return MASK_SUBTRACT_ALPHA;
1608
1609         return MASK_SUBTRACT_ALPHA;
1610 }
1611
1612 int CWindowMaskMode::handle_event()
1613 {
1614         MaskAutos *autos;
1615         MaskAuto *keyframe;
1616         Track *track;
1617         MaskPoint *point;
1618         SubMask *mask;
1619 // Get existing keyframe
1620         ((CWindowMaskGUI*)gui)->get_keyframe(track, autos, keyframe, mask, point, 0);
1621         if(track)
1622         {
1623                 mwindow->undo->update_undo_before(_("mask mode"), 0);
1624 #ifdef USE_KEYFRAME_SPANNING
1625 // Create temp keyframe
1626                 MaskAuto temp_keyframe(mwindow->edl, autos);
1627                 temp_keyframe.copy_data(keyframe);
1628 // Update parameter
1629                 temp_keyframe.mode = text_to_mode(get_text());
1630 // Commit change to span of keyframes
1631                 autos->update_parameter(&temp_keyframe);
1632 #else
1633                 ((MaskAuto*)autos->default_auto)->mode =
1634                         text_to_mode(get_text());
1635 #endif
1636                 mwindow->undo->update_undo_after(_("mask mode"), LOAD_AUTOMATION);
1637         }
1638
1639 //printf("CWindowMaskMode::handle_event 1\n");
1640         gui->update_preview();
1641         return 1;
1642 }
1643
1644
1645
1646
1647
1648
1649
1650
1651 CWindowMaskDelete::CWindowMaskDelete(MWindow *mwindow,
1652         CWindowToolGUI *gui,
1653         int x,
1654         int y)
1655  : BC_GenericButton(x, y, _("Delete"))
1656 {
1657         this->mwindow = mwindow;
1658         this->gui = gui;
1659 }
1660
1661 int CWindowMaskDelete::handle_event()
1662 {
1663         MaskAutos *autos;
1664         MaskAuto *keyframe;
1665         Track *track;
1666         MaskPoint *point;
1667         SubMask *mask;
1668         int total_points = 0;
1669
1670 // Get existing keyframe
1671         ((CWindowMaskGUI*)gui)->get_keyframe(track, autos, keyframe, mask, point, 0);
1672
1673         if(track)
1674         {
1675                 mwindow->undo->update_undo_before(_("mask delete"), 0);
1676
1677 #ifdef USE_KEYFRAME_SPANNING
1678 // Create temp keyframe
1679                 MaskAuto temp_keyframe(mwindow->edl, autos);
1680                 temp_keyframe.copy_data(keyframe);
1681 // Update parameter
1682                 SubMask *submask = temp_keyframe.get_submask(mwindow->edl->session->cwindow_mask);
1683                 if( shift_down() )
1684                         submask->points.remove_all_objects();
1685
1686                 for(int i = mwindow->cwindow->gui->affected_point;
1687                         i < submask->points.total - 1;
1688                         i++)
1689                 {
1690                         *submask->points.values[i] = *submask->points.values[i + 1];
1691                 }
1692
1693                 if(submask->points.total)
1694                 {
1695                         submask->points.remove_object(
1696                                 submask->points.values[submask->points.total - 1]);
1697                 }
1698                 total_points = submask->points.total;
1699
1700 // Commit change to span of keyframes
1701                 ((MaskAutos*)track->automation->autos[AUTOMATION_MASK])->update_parameter(&temp_keyframe);
1702 #else
1703                 for(MaskAuto *current = (MaskAuto*)autos->default_auto;
1704                         current; )
1705                 {
1706                         SubMask *submask = current->get_submask(mwindow->edl->session->cwindow_mask);
1707                         if( shift_down() )
1708                                 submask->points.remove_all_objects();
1709
1710                         for(int i = mwindow->cwindow->gui->affected_point;
1711                                 i < submask->points.total - 1;
1712                                 i++)
1713                         {
1714                                 *submask->points.values[i] = *submask->points.values[i + 1];
1715                         }
1716
1717                         if(submask->points.total)
1718                         {
1719                                 submask->points.remove_object(
1720                                         submask->points.values[submask->points.total - 1]);
1721                         }
1722                         total_points = submask->points.total;
1723
1724                         if(current == (MaskAuto*)autos->default_auto)
1725                                 current = (MaskAuto*)autos->first;
1726                         else
1727                                 current = (MaskAuto*)NEXT;
1728                 }
1729 #endif
1730                 if( mwindow->cwindow->gui->affected_point >= total_points )
1731                         mwindow->cwindow->gui->affected_point =
1732                                 total_points > 0 ? total_points-1 : 0;
1733
1734                 gui->update();
1735                 gui->update_preview();
1736                 mwindow->undo->update_undo_after(_("mask delete"), LOAD_AUTOMATION);
1737         }
1738
1739
1740         return 1;
1741 }
1742
1743 int CWindowMaskDelete::keypress_event()
1744 {
1745         if(get_keypress() == BACKSPACE ||
1746                 get_keypress() == DELETE)
1747                 return handle_event();
1748         return 0;
1749 }
1750
1751
1752 // CWindowMaskCycleNext::CWindowMaskCycleNext(MWindow *mwindow, CWindowToolGUI *gui, int x, int y)
1753 //  : BC_GenericButton(x, y, _("Cycle next"))
1754 // {
1755 //      this->mwindow = mwindow;
1756 //      this->gui = gui;
1757 // }
1758 // int CWindowMaskCycleNext::handle_event()
1759 // {
1760 //      MaskAuto *keyframe;
1761 //      MaskAutos *autos;
1762 //      Track *track;
1763 //      MaskPoint *point;
1764 //      SubMask *mask;
1765 //      ((CWindowMaskGUI*)gui)->get_keyframe(track, autos, keyframe, mask, point, 0);
1766 //
1767 //      MaskPoint *temp;
1768 //
1769 // // Should apply to all keyframes
1770 //      if(keyframe && mask->points.total)
1771 //      {
1772 //              temp = mask->points.values[0];
1773 //
1774 //              for(int i = 0; i < mask->points.total - 1; i++)
1775 //              {
1776 //                      mask->points.values[i] = mask->points.values[i + 1];
1777 //              }
1778 //              mask->points.values[mask->points.total - 1] = temp;
1779 //
1780 //              mwindow->cwindow->gui->affected_point--;
1781 //              if(mwindow->cwindow->gui->affected_point < 0)
1782 //                      mwindow->cwindow->gui->affected_point = mask->points.total - 1;
1783 //
1784 //              gui->update();
1785 //              gui->update_preview();
1786 //      }
1787 //
1788 //      return 1;
1789 // }
1790 //
1791 // CWindowMaskCyclePrev::CWindowMaskCyclePrev(MWindow *mwindow, CWindowToolGUI *gui, int x, int y)
1792 //  : BC_GenericButton(x, y, _("Cycle prev"))
1793 // {
1794 //      this->mwindow = mwindow;
1795 //      this->gui = gui;
1796 // }
1797 // int CWindowMaskCyclePrev::handle_event()
1798 // {
1799 //      MaskAuto *keyframe;
1800 //      MaskAutos *autos;
1801 //      Track *track;
1802 //      MaskPoint *point;
1803 //      SubMask *mask;
1804 //      ((CWindowMaskGUI*)gui)->get_keyframe(track, autos, keyframe, mask, point, 0);
1805 //
1806 // // Should apply to all keyframes
1807 //      MaskPoint *temp;
1808 //      if(keyframe && mask->points.total)
1809 //      {
1810 //              temp = mask->points.values[mask->points.total - 1];
1811 //
1812 //              for(int i = mask->points.total - 1; i > 0; i--)
1813 //              {
1814 //                      mask->points.values[i] = mask->points.values[i - 1];
1815 //              }
1816 //              mask->points.values[0] = temp;
1817 //
1818 //              mwindow->cwindow->gui->affected_point++;
1819 //              if(mwindow->cwindow->gui->affected_point >= mask->points.total)
1820 //                      mwindow->cwindow->gui->affected_point = 0;
1821 //
1822 //              gui->update();
1823 //              gui->update_preview();
1824 //      }
1825 //      return 1;
1826 // }
1827
1828
1829 CWindowMaskNumber::CWindowMaskNumber(MWindow *mwindow,
1830         CWindowToolGUI *gui,
1831         int x,
1832         int y)
1833  : BC_TumbleTextBox(gui,
1834                 (int64_t)mwindow->edl->session->cwindow_mask,
1835                 (int64_t)0,
1836                 (int64_t)SUBMASKS - 1,
1837                 x,
1838                 y,
1839                 100)
1840 {
1841         this->mwindow = mwindow;
1842         this->gui = gui;
1843 }
1844
1845 CWindowMaskNumber::~CWindowMaskNumber()
1846 {
1847 }
1848
1849 int CWindowMaskNumber::handle_event()
1850 {
1851         mwindow->edl->session->cwindow_mask = atol(get_text());
1852         gui->update();
1853         gui->update_preview();
1854         return 1;
1855 }
1856
1857
1858 CWindowMaskAffectedPoint::CWindowMaskAffectedPoint(MWindow *mwindow,
1859         CWindowToolGUI *gui, int x, int y)
1860  : BC_TumbleTextBox(gui,
1861                 (int64_t)mwindow->cwindow->gui->affected_point,
1862                 (int64_t)0, INT64_MAX, x, y, 100)
1863 {
1864         this->mwindow = mwindow;
1865         this->gui = gui;
1866 }
1867
1868 CWindowMaskAffectedPoint::~CWindowMaskAffectedPoint()
1869 {
1870 }
1871
1872 int CWindowMaskAffectedPoint::handle_event()
1873 {
1874         int total_points = 0;
1875         int affected_point = atol(get_text());
1876         Track *track = mwindow->cwindow->calculate_affected_track();
1877         if(track) {
1878                 MaskAutos *autos = (MaskAutos*)track->automation->autos[AUTOMATION_MASK];
1879                 MaskAuto *keyframe = (MaskAuto*)mwindow->cwindow->calculate_affected_auto(autos, 0);
1880                 if( keyframe ) {
1881                         SubMask *mask = keyframe->get_submask(mwindow->edl->session->cwindow_mask);
1882                         total_points = mask->points.size();
1883                 }
1884         }
1885         int active_point = affected_point;
1886         if( affected_point >= total_points )
1887                 affected_point = total_points - 1;
1888         else if( affected_point < 0 )
1889                 affected_point = 0;
1890         if( active_point != affected_point )
1891                 update((int64_t)affected_point);
1892         mwindow->cwindow->gui->affected_point = affected_point;
1893         gui->update();
1894         gui->update_preview();
1895         return 1;
1896 }
1897
1898
1899
1900
1901
1902 CWindowMaskFeather::CWindowMaskFeather(MWindow *mwindow, CWindowToolGUI *gui, int x, int y)
1903  : BC_TumbleTextBox(gui,
1904                 (int64_t)0,
1905                 (int64_t)0,
1906                 (int64_t)0xff,
1907                 x,
1908                 y,
1909                 100)
1910 {
1911         this->mwindow = mwindow;
1912         this->gui = gui;
1913 }
1914 CWindowMaskFeather::~CWindowMaskFeather()
1915 {
1916 }
1917 int CWindowMaskFeather::handle_event()
1918 {
1919         MaskAutos *autos;
1920         MaskAuto *keyframe;
1921         Track *track;
1922         MaskPoint *point;
1923         SubMask *mask;
1924 #ifdef USE_KEYFRAME_SPANNING
1925         int create_it = 0;
1926 #else
1927         int create_it = 1;
1928 #endif
1929
1930         mwindow->undo->update_undo_before(_("mask feather"), this);
1931
1932 // Get existing keyframe
1933         ((CWindowMaskGUI*)gui)->get_keyframe(track, autos, keyframe,
1934                         mask, point, create_it);
1935
1936         if(track)
1937         {
1938 #ifdef USE_KEYFRAME_SPANNING
1939 // Create temp keyframe
1940                 MaskAuto temp_keyframe(mwindow->edl, autos);
1941                 temp_keyframe.copy_data(keyframe);
1942 // Update parameter
1943                 temp_keyframe.feather = atof(get_text());
1944 // Commit change to span of keyframes
1945                 autos->update_parameter(&temp_keyframe);
1946 #else
1947                 keyframe->feather = atof(get_text());
1948 #endif
1949
1950                 gui->update_preview();
1951         }
1952
1953         mwindow->undo->update_undo_after(_("mask feather"), LOAD_AUTOMATION);
1954         return 1;
1955 }
1956
1957
1958 CWindowMaskValue::CWindowMaskValue(MWindow *mwindow, CWindowToolGUI *gui, int x, int y)
1959  : BC_ISlider(x,
1960                         y,
1961                         0,
1962                         200,
1963                         200,
1964                         0,
1965                         100,
1966                         0)
1967 {
1968         this->mwindow = mwindow;
1969         this->gui = gui;
1970 }
1971
1972 CWindowMaskValue::~CWindowMaskValue()
1973 {
1974 }
1975
1976 int CWindowMaskValue::handle_event()
1977 {
1978         MaskAutos *autos;
1979         MaskAuto *keyframe;
1980         Track *track;
1981         MaskPoint *point;
1982         SubMask *mask;
1983 #ifdef USE_KEYFRAME_SPANNING
1984         int create_it = 0;
1985 #else
1986         int create_it = 1;
1987 #endif
1988
1989         mwindow->undo->update_undo_before(_("mask value"), this);
1990         ((CWindowMaskGUI*)gui)->get_keyframe(track, autos, keyframe,
1991                 mask, point, create_it);
1992
1993         if(track)
1994         {
1995 #ifdef USE_KEYFRAME_SPANNING
1996 // Create temp keyframe
1997                 MaskAuto temp_keyframe(mwindow->edl, autos);
1998                 temp_keyframe.copy_data(keyframe);
1999 // Update parameter
2000                 temp_keyframe.value = get_value();
2001 // Commit change to span of keyframes
2002                 autos->update_parameter(&temp_keyframe);
2003 #else
2004                 keyframe->value = get_value();
2005 #endif
2006         }
2007
2008         gui->update_preview();
2009         mwindow->undo->update_undo_after(_("mask value"), LOAD_AUTOMATION);
2010         return 1;
2011 }
2012
2013
2014 CWindowMaskBeforePlugins::CWindowMaskBeforePlugins(CWindowToolGUI *gui, int x, int y)
2015  : BC_CheckBox(x,
2016         y,
2017         1,
2018         _("Apply mask before plugins"))
2019 {
2020         this->gui = gui;
2021 }
2022
2023 int CWindowMaskBeforePlugins::handle_event()
2024 {
2025         Track *track;
2026         MaskAutos *autos;
2027         MaskAuto *keyframe;
2028         SubMask *mask;
2029         MaskPoint *point;
2030         ((CWindowMaskGUI*)gui)->get_keyframe(track, autos, keyframe, mask, point, 1);
2031
2032         if (keyframe) {
2033                 keyframe->apply_before_plugins = get_value();
2034                 gui->update_preview();
2035         }
2036         return 1;
2037 }
2038
2039
2040 CWindowDisableOpenGLMasking::CWindowDisableOpenGLMasking(CWindowToolGUI *gui, int x, int y)
2041  : BC_CheckBox(x, y, 1, _("Disable OpenGL masking"))
2042 {
2043         this->gui = gui;
2044 }
2045
2046 int CWindowDisableOpenGLMasking::handle_event()
2047 {
2048         Track *track;
2049         MaskAutos *autos;
2050         MaskAuto *keyframe;
2051         SubMask *mask;
2052         MaskPoint *point;
2053         ((CWindowMaskGUI*)gui)->get_keyframe(track, autos, keyframe, mask, point, 1);
2054
2055         if (keyframe) {
2056                 keyframe->disable_opengl_masking = get_value();
2057                 gui->update_preview();
2058         }
2059         return 1;
2060 }
2061
2062
2063
2064
2065
2066
2067
2068
2069
2070 CWindowMaskGUI::CWindowMaskGUI(MWindow *mwindow, CWindowTool *thread)
2071  : CWindowToolGUI(mwindow, thread,
2072         _(PROGRAM_NAME ": Mask"), 330, 320)
2073 {
2074         this->mwindow = mwindow;
2075         this->thread = thread;
2076         number = 0;
2077         active_point = 0;
2078         feather = 0;
2079 }
2080 CWindowMaskGUI::~CWindowMaskGUI()
2081 {
2082         lock_window("CWindowMaskGUI::~CWindowMaskGUI");
2083         delete number;
2084         delete active_point;
2085         delete feather;
2086         unlock_window();
2087 }
2088
2089 void CWindowMaskGUI::create_objects()
2090 {
2091         int x = 10, y = 10, margin = mwindow->theme->widget_border;
2092         //MaskAuto *keyframe = 0;
2093         //Track *track = mwindow->cwindow->calculate_affected_track();
2094         //if(track)
2095         //      keyframe = (MaskAuto*)mwindow->cwindow->calculate_affected_auto(track->automation->autos[AUTOMATION_MASK], 0);
2096
2097         lock_window("CWindowMaskGUI::create_objects");
2098         BC_Title *title;
2099         add_subwindow(title = new BC_Title(x, y, _("Mode:")));
2100         add_subwindow(mode = new CWindowMaskMode(mwindow,
2101                 this, x + title->get_w() + margin, y, ""));
2102         mode->create_objects();
2103         y += mode->get_h() + margin;
2104         add_subwindow(title = new BC_Title(x, y, _("Value:")));
2105         add_subwindow(value = new CWindowMaskValue(mwindow, this, x + title->get_w() + margin, y));
2106         y += value->get_h() + margin;
2107         add_subwindow(delete_point = new CWindowMaskDelete(mwindow, this, x, y));
2108         int x1 = x + delete_point->get_w() + 2*margin;
2109         add_subwindow(title = new BC_Title(x1, y, _("Point:")));
2110         x1 += title->get_w() + margin;
2111         active_point = new CWindowMaskAffectedPoint(mwindow, this, x1, y);
2112         active_point->create_objects();
2113         y += delete_point->get_h() + margin;
2114         add_subwindow(title = new BC_Title(x, y, _("Mask number:")));
2115         number = new CWindowMaskNumber(mwindow,
2116                 this, x + title->get_w() + margin, y);
2117         number->create_objects();
2118         y += number->get_h() + margin;
2119         add_subwindow(title = new BC_Title(x, y, _("Feather:")));
2120         feather = new CWindowMaskFeather(mwindow,
2121                 this, x + title->get_w() + margin, y);
2122         feather->create_objects();
2123         y += feather->get_h() + margin;
2124         add_subwindow(title = new BC_Title(x, y, "X:"));
2125         x += title->get_w() + margin;
2126         this->x = new CWindowCoord(this, x, y, (float)0.0);
2127         this->x->create_objects();
2128         x += this->x->get_w() + margin;
2129         add_subwindow(title = new BC_Title(x, y, "Y:"));
2130         x += title->get_w() + margin;
2131         this->y = new CWindowCoord(this, x, y, (float)0.0);
2132         this->y->create_objects();
2133
2134         x = 10;
2135         y += this->y->get_h() + margin;
2136         add_subwindow(title = new BC_Title(x, y, _("Press Shift to move an end point")));
2137         y += title->get_h() + margin;
2138         add_subwindow(title = new BC_Title(x, y, _("Press Ctrl to move a control point")));
2139         y += title->get_h() + margin;
2140         add_subwindow(title = new BC_Title(x, y, _("Shift+click Delete to delete the mask")));
2141         y += title->get_h() + margin;
2142         add_subwindow(title = new BC_Title(x, y, _("Press Alt to translate the mask")));
2143         y += 30;
2144
2145         add_subwindow(this->apply_before_plugins = new CWindowMaskBeforePlugins(this, 10, y));
2146         y += this->apply_before_plugins->get_h() + margin;
2147         add_subwindow(this->disable_opengl_masking = new CWindowDisableOpenGLMasking(this, 10, y));
2148
2149         update();
2150         unlock_window();
2151 }
2152
2153 void CWindowMaskGUI::get_keyframe(Track* &track,
2154         MaskAutos* &autos,
2155         MaskAuto* &keyframe,
2156         SubMask* &mask,
2157         MaskPoint* &point,
2158         int create_it)
2159 {
2160         autos = 0;
2161         keyframe = 0;
2162
2163         track = mwindow->cwindow->calculate_affected_track();
2164         if(track)
2165         {
2166                 autos = (MaskAutos*)track->automation->autos[AUTOMATION_MASK];
2167                 keyframe = (MaskAuto*)mwindow->cwindow->calculate_affected_auto(
2168                         autos,
2169                         create_it);
2170         }
2171
2172         if(keyframe)
2173                 mask = keyframe->get_submask(mwindow->edl->session->cwindow_mask);
2174         else
2175                 mask = 0;
2176
2177         point = 0;
2178         if(keyframe)
2179         {
2180                 if(mwindow->cwindow->gui->affected_point < mask->points.total &&
2181                         mwindow->cwindow->gui->affected_point >= 0)
2182                 {
2183                         point = mask->points.values[mwindow->cwindow->gui->affected_point];
2184                 }
2185         }
2186 }
2187
2188 void CWindowMaskGUI::update()
2189 {
2190         Track *track;
2191         MaskAutos *autos;
2192         MaskAuto *keyframe;
2193         SubMask *mask;
2194         MaskPoint *point;
2195 //printf("CWindowMaskGUI::update 1\n");
2196         get_keyframe(track, autos, keyframe, mask, point, 0);
2197
2198         double position = mwindow->edl->local_session->get_selectionstart(1);
2199         position = mwindow->edl->align_to_frame(position, 0);
2200         if(track)
2201         {
2202                 int64_t position_i = track->to_units(position, 0);
2203
2204                 if(point)
2205                 {
2206                         x->update(point->x);
2207                         y->update(point->y);
2208                 }
2209
2210                 if(mask)
2211                 {
2212                         feather->update((int64_t)autos->get_feather(position_i, PLAY_FORWARD));
2213                         value->update((int64_t)autos->get_value(position_i, PLAY_FORWARD));
2214                         apply_before_plugins->update((int64_t)keyframe->apply_before_plugins);
2215                         disable_opengl_masking->update((int64_t)keyframe->disable_opengl_masking);
2216                 }
2217         }
2218
2219 //printf("CWindowMaskGUI::update 1\n");
2220         active_point->update((int64_t)mwindow->cwindow->gui->affected_point);
2221         number->update((int64_t)mwindow->edl->session->cwindow_mask);
2222
2223 //printf("CWindowMaskGUI::update 1\n");
2224         if(track)
2225         {
2226 #ifdef USE_KEYFRAME_SPANNING
2227                 mode->set_text(
2228                         CWindowMaskMode::mode_to_text(keyframe->mode));
2229 #else
2230                 mode->set_text(
2231                         CWindowMaskMode::mode_to_text(((MaskAuto*)autos->default_auto)->mode));
2232 #endif
2233         }
2234 //printf("CWindowMaskGUI::update 2\n");
2235 }
2236
2237 void CWindowMaskGUI::handle_event()
2238 {
2239         Track *track;
2240         MaskAuto *keyframe;
2241         MaskAutos *autos;
2242         SubMask *mask;
2243         MaskPoint *point;
2244         get_keyframe(track, autos, keyframe, mask, point, 0);
2245
2246         mwindow->undo->update_undo_before(_("mask point"), this);
2247
2248         if(point)
2249         {
2250 #ifdef USE_KEYFRAME_SPANNING
2251 // Create temp keyframe
2252                 MaskAuto temp_keyframe(mwindow->edl, autos);
2253                 temp_keyframe.copy_data(keyframe);
2254 // Get affected point in temp keyframe
2255                 mask = temp_keyframe.get_submask(mwindow->edl->session->cwindow_mask);
2256                 if(mwindow->cwindow->gui->affected_point < mask->points.total &&
2257                         mwindow->cwindow->gui->affected_point >= 0)
2258                 {
2259                         point = mask->points.values[mwindow->cwindow->gui->affected_point];
2260                 }
2261
2262                 if(point)
2263                 {
2264                         point->x = atof(x->get_text());
2265                         point->y = atof(y->get_text());
2266 // Commit to spanned keyframes
2267                         autos->update_parameter(&temp_keyframe);
2268                 }
2269 #else
2270                 point->x = atof(x->get_text());
2271                 point->y = atof(y->get_text());
2272 #endif
2273         }
2274
2275         update_preview();
2276         mwindow->undo->update_undo_after(_("mask point"), LOAD_AUTOMATION);
2277 }
2278
2279 void CWindowMaskGUI::update_preview()
2280 {
2281         mwindow->gui->lock_window("CWindowMaskGUI::update_preview");
2282         mwindow->restart_brender();
2283         mwindow->sync_parameters(CHANGE_PARAMS);
2284         mwindow->gui->draw_overlays(1);
2285         mwindow->gui->unlock_window();
2286         mwindow->cwindow->refresh_frame(CHANGE_NONE);
2287         mwindow->cwindow->gui->lock_window("CWindowMaskGUI::update_preview");
2288         mwindow->cwindow->gui->canvas->draw_refresh();
2289         mwindow->cwindow->gui->unlock_window();
2290 }
2291
2292
2293 CWindowRulerGUI::CWindowRulerGUI(MWindow *mwindow, CWindowTool *thread)
2294  : CWindowToolGUI(mwindow,
2295         thread,
2296         _(PROGRAM_NAME ": Ruler"),
2297         320,
2298         240)
2299 {
2300 }
2301
2302 CWindowRulerGUI::~CWindowRulerGUI()
2303 {
2304 }
2305
2306 void CWindowRulerGUI::create_objects()
2307 {
2308         int x = 10, y = 10;
2309         BC_Title *title;
2310
2311         lock_window("CWindowRulerGUI::create_objects");
2312         add_subwindow(title = new BC_Title(x, y, _("Current:")));
2313         add_subwindow(current = new BC_Title(x + title->get_w() + 10, y, ""));
2314         y += title->get_h() + 5;
2315
2316         add_subwindow(title = new BC_Title(x, y, _("Point 1:")));
2317         add_subwindow(point1 = new BC_Title(x + title->get_w() + 10, y, ""));
2318         y += title->get_h() + 5;
2319
2320         add_subwindow(title = new BC_Title(x, y, _("Point 2:")));
2321         add_subwindow(point2 = new BC_Title(x + title->get_w() + 10, y, ""));
2322         y += title->get_h() + 5;
2323
2324         add_subwindow(title = new BC_Title(x, y, _("Distance:")));
2325         add_subwindow(distance = new BC_Title(x + title->get_w() + 10, y, ""));
2326         y += title->get_h() + 5;
2327         add_subwindow(title = new BC_Title(x, y, _("Angle:")));
2328         add_subwindow(angle = new BC_Title(x + title->get_w() + 10, y, ""));
2329         y += title->get_h() + 10;
2330         char string[BCTEXTLEN];
2331         sprintf(string, _("Press Ctrl to lock ruler to the\nnearest 45%c angle."), 0xb0);
2332         add_subwindow(title = new BC_Title(x,
2333                 y,
2334                 string));
2335         y += title->get_h() + 10;
2336         sprintf(string, _("Press Alt to translate the ruler."));
2337         add_subwindow(title = new BC_Title(x,
2338                 y,
2339                 string));
2340         update();
2341         unlock_window();
2342 }
2343
2344 void CWindowRulerGUI::update()
2345 {
2346         double distance_value =
2347                 sqrt(SQR(mwindow->edl->session->ruler_x2 - mwindow->edl->session->ruler_x1) +
2348                 SQR(mwindow->edl->session->ruler_y2 - mwindow->edl->session->ruler_y1));
2349         double angle_value = atan((mwindow->edl->session->ruler_y2 - mwindow->edl->session->ruler_y1) /
2350                 (mwindow->edl->session->ruler_x2 - mwindow->edl->session->ruler_x1)) *
2351                 360 /
2352                 2 /
2353                 M_PI;
2354
2355         if(EQUIV(distance_value, 0.0))
2356         {
2357                 angle_value = 0.0;
2358         }
2359         else
2360         if(angle_value < 0)
2361         {
2362                 angle_value *= -1;
2363         }
2364
2365         char string[BCTEXTLEN];
2366         sprintf(string, "%d, %d",
2367                 mwindow->session->cwindow_output_x,
2368                 mwindow->session->cwindow_output_y);
2369         current->update(string);
2370         sprintf(string, "%.0f, %.0f",
2371                 mwindow->edl->session->ruler_x1,
2372                 mwindow->edl->session->ruler_y1);
2373         point1->update(string);
2374         sprintf(string, "%.0f, %.0f",
2375                 mwindow->edl->session->ruler_x2,
2376                 mwindow->edl->session->ruler_y2);
2377         point2->update(string);
2378
2379         sprintf(string, _("%0.01f pixels"), distance_value);
2380         distance->update(string);
2381         sprintf(string, "%0.02f %c", angle_value, 0xb0);
2382         angle->update(string);
2383 }
2384
2385 void CWindowRulerGUI::handle_event()
2386 {
2387 }
2388
2389
2390
2391