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