329b09ecc8bacacd120cf6ed7f965ebf5df5392a
[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::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                 if( shift_down() )
1666                         submask->points.remove_all_objects();
1667
1668                 for(int i = mwindow->cwindow->gui->affected_point;
1669                         i < submask->points.total - 1;
1670                         i++)
1671                 {
1672                         *submask->points.values[i] = *submask->points.values[i + 1];
1673                 }
1674
1675                 if(submask->points.total)
1676                 {
1677                         submask->points.remove_object(
1678                                 submask->points.values[submask->points.total - 1]);
1679                 }
1680                 total_points = submask->points.total;
1681
1682 // Commit change to span of keyframes
1683                 ((MaskAutos*)track->automation->autos[AUTOMATION_MASK])->update_parameter(&temp_keyframe);
1684 #else
1685                 for(MaskAuto *current = (MaskAuto*)autos->default_auto;
1686                         current; )
1687                 {
1688                         SubMask *submask = current->get_submask(mwindow->edl->session->cwindow_mask);
1689                         if( shift_down() )
1690                                 submask->points.remove_all_objects();
1691
1692                         for(int i = mwindow->cwindow->gui->affected_point;
1693                                 i < submask->points.total - 1;
1694                                 i++)
1695                         {
1696                                 *submask->points.values[i] = *submask->points.values[i + 1];
1697                         }
1698
1699                         if(submask->points.total)
1700                         {
1701                                 submask->points.remove_object(
1702                                         submask->points.values[submask->points.total - 1]);
1703                         }
1704                         total_points = submask->points.total;
1705
1706                         if(current == (MaskAuto*)autos->default_auto)
1707                                 current = (MaskAuto*)autos->first;
1708                         else
1709                                 current = (MaskAuto*)NEXT;
1710                 }
1711 #endif
1712                 if( mwindow->cwindow->gui->affected_point >= total_points )
1713                         mwindow->cwindow->gui->affected_point =
1714                                 total_points > 0 ? total_points-1 : 0;
1715
1716                 gui->update();
1717                 gui->update_preview();
1718                 mwindow->undo->update_undo_after(_("mask delete"), LOAD_AUTOMATION);
1719         }
1720
1721
1722         return 1;
1723 }
1724
1725 int CWindowMaskDelete::keypress_event()
1726 {
1727         if(get_keypress() == BACKSPACE ||
1728                 get_keypress() == DELETE)
1729                 return handle_event();
1730         return 0;
1731 }
1732
1733
1734 // CWindowMaskCycleNext::CWindowMaskCycleNext(MWindow *mwindow, CWindowToolGUI *gui, int x, int y)
1735 //  : BC_GenericButton(x, y, _("Cycle next"))
1736 // {
1737 //      this->mwindow = mwindow;
1738 //      this->gui = gui;
1739 // }
1740 // int CWindowMaskCycleNext::handle_event()
1741 // {
1742 //      MaskAuto *keyframe;
1743 //      MaskAutos *autos;
1744 //      Track *track;
1745 //      MaskPoint *point;
1746 //      SubMask *mask;
1747 //      ((CWindowMaskGUI*)gui)->get_keyframe(track, autos, keyframe, mask, point, 0);
1748 //
1749 //      MaskPoint *temp;
1750 //
1751 // // Should apply to all keyframes
1752 //      if(keyframe && mask->points.total)
1753 //      {
1754 //              temp = mask->points.values[0];
1755 //
1756 //              for(int i = 0; i < mask->points.total - 1; i++)
1757 //              {
1758 //                      mask->points.values[i] = mask->points.values[i + 1];
1759 //              }
1760 //              mask->points.values[mask->points.total - 1] = temp;
1761 //
1762 //              mwindow->cwindow->gui->affected_point--;
1763 //              if(mwindow->cwindow->gui->affected_point < 0)
1764 //                      mwindow->cwindow->gui->affected_point = mask->points.total - 1;
1765 //
1766 //              gui->update();
1767 //              gui->update_preview();
1768 //      }
1769 //
1770 //      return 1;
1771 // }
1772 //
1773 // CWindowMaskCyclePrev::CWindowMaskCyclePrev(MWindow *mwindow, CWindowToolGUI *gui, int x, int y)
1774 //  : BC_GenericButton(x, y, _("Cycle prev"))
1775 // {
1776 //      this->mwindow = mwindow;
1777 //      this->gui = gui;
1778 // }
1779 // int CWindowMaskCyclePrev::handle_event()
1780 // {
1781 //      MaskAuto *keyframe;
1782 //      MaskAutos *autos;
1783 //      Track *track;
1784 //      MaskPoint *point;
1785 //      SubMask *mask;
1786 //      ((CWindowMaskGUI*)gui)->get_keyframe(track, autos, keyframe, mask, point, 0);
1787 //
1788 // // Should apply to all keyframes
1789 //      MaskPoint *temp;
1790 //      if(keyframe && mask->points.total)
1791 //      {
1792 //              temp = mask->points.values[mask->points.total - 1];
1793 //
1794 //              for(int i = mask->points.total - 1; i > 0; i--)
1795 //              {
1796 //                      mask->points.values[i] = mask->points.values[i - 1];
1797 //              }
1798 //              mask->points.values[0] = temp;
1799 //
1800 //              mwindow->cwindow->gui->affected_point++;
1801 //              if(mwindow->cwindow->gui->affected_point >= mask->points.total)
1802 //                      mwindow->cwindow->gui->affected_point = 0;
1803 //
1804 //              gui->update();
1805 //              gui->update_preview();
1806 //      }
1807 //      return 1;
1808 // }
1809
1810
1811 CWindowMaskNumber::CWindowMaskNumber(MWindow *mwindow,
1812         CWindowToolGUI *gui,
1813         int x,
1814         int y)
1815  : BC_TumbleTextBox(gui,
1816                 (int64_t)mwindow->edl->session->cwindow_mask,
1817                 (int64_t)0,
1818                 (int64_t)SUBMASKS - 1,
1819                 x,
1820                 y,
1821                 100)
1822 {
1823         this->mwindow = mwindow;
1824         this->gui = gui;
1825 }
1826
1827 CWindowMaskNumber::~CWindowMaskNumber()
1828 {
1829 }
1830
1831 int CWindowMaskNumber::handle_event()
1832 {
1833         mwindow->edl->session->cwindow_mask = atol(get_text());
1834         gui->update();
1835         gui->update_preview();
1836         return 1;
1837 }
1838
1839
1840 CWindowMaskAffectedPoint::CWindowMaskAffectedPoint(MWindow *mwindow,
1841         CWindowToolGUI *gui, int x, int y)
1842  : BC_TumbleTextBox(gui,
1843                 (int64_t)mwindow->cwindow->gui->affected_point,
1844                 (int64_t)0, INT64_MAX, x, y, 100)
1845 {
1846         this->mwindow = mwindow;
1847         this->gui = gui;
1848 }
1849
1850 CWindowMaskAffectedPoint::~CWindowMaskAffectedPoint()
1851 {
1852 }
1853
1854 int CWindowMaskAffectedPoint::handle_event()
1855 {
1856         int total_points = 0;
1857         int affected_point = atol(get_text());
1858         Track *track = mwindow->cwindow->calculate_affected_track();
1859         if(track) {
1860                 MaskAutos *autos = (MaskAutos*)track->automation->autos[AUTOMATION_MASK];
1861                 MaskAuto *keyframe = (MaskAuto*)mwindow->cwindow->calculate_affected_auto(autos, 0);
1862                 if( keyframe ) {
1863                         SubMask *mask = keyframe->get_submask(mwindow->edl->session->cwindow_mask);
1864                         total_points = mask->points.size();
1865                 }
1866         }
1867         int active_point = affected_point;
1868         if( affected_point >= total_points )
1869                 affected_point = total_points - 1;
1870         else if( affected_point < 0 )
1871                 affected_point = 0;
1872         if( active_point != affected_point )
1873                 update((int64_t)affected_point);
1874         mwindow->cwindow->gui->affected_point = affected_point;
1875         gui->update();
1876         gui->update_preview();
1877         return 1;
1878 }
1879
1880
1881
1882
1883
1884 CWindowMaskFeather::CWindowMaskFeather(MWindow *mwindow, CWindowToolGUI *gui, int x, int y)
1885  : BC_TumbleTextBox(gui,
1886                 (int64_t)0,
1887                 (int64_t)0,
1888                 (int64_t)0xff,
1889                 x,
1890                 y,
1891                 100)
1892 {
1893         this->mwindow = mwindow;
1894         this->gui = gui;
1895 }
1896 CWindowMaskFeather::~CWindowMaskFeather()
1897 {
1898 }
1899 int CWindowMaskFeather::handle_event()
1900 {
1901         MaskAutos *autos;
1902         MaskAuto *keyframe;
1903         Track *track;
1904         MaskPoint *point;
1905         SubMask *mask;
1906 #ifdef USE_KEYFRAME_SPANNING
1907         int create_it = 0;
1908 #else
1909         int create_it = 1;
1910 #endif
1911
1912         mwindow->undo->update_undo_before(_("mask feather"), this);
1913
1914 // Get existing keyframe
1915         ((CWindowMaskGUI*)gui)->get_keyframe(track, autos, keyframe,
1916                         mask, point, create_it);
1917
1918         if(track)
1919         {
1920 #ifdef USE_KEYFRAME_SPANNING
1921 // Create temp keyframe
1922                 MaskAuto temp_keyframe(mwindow->edl, autos);
1923                 temp_keyframe.copy_data(keyframe);
1924 // Update parameter
1925                 temp_keyframe.feather = atof(get_text());
1926 // Commit change to span of keyframes
1927                 autos->update_parameter(&temp_keyframe);
1928 #else
1929                 keyframe->feather = atof(get_text());
1930 #endif
1931
1932                 gui->update_preview();
1933         }
1934
1935         mwindow->undo->update_undo_after(_("mask feather"), LOAD_AUTOMATION);
1936         return 1;
1937 }
1938
1939
1940 CWindowMaskValue::CWindowMaskValue(MWindow *mwindow, CWindowToolGUI *gui, int x, int y)
1941  : BC_ISlider(x,
1942                         y,
1943                         0,
1944                         200,
1945                         200,
1946                         0,
1947                         100,
1948                         0)
1949 {
1950         this->mwindow = mwindow;
1951         this->gui = gui;
1952 }
1953
1954 CWindowMaskValue::~CWindowMaskValue()
1955 {
1956 }
1957
1958 int CWindowMaskValue::handle_event()
1959 {
1960         MaskAutos *autos;
1961         MaskAuto *keyframe;
1962         Track *track;
1963         MaskPoint *point;
1964         SubMask *mask;
1965 #ifdef USE_KEYFRAME_SPANNING
1966         int create_it = 0;
1967 #else
1968         int create_it = 1;
1969 #endif
1970
1971         mwindow->undo->update_undo_before(_("mask value"), this);
1972         ((CWindowMaskGUI*)gui)->get_keyframe(track, autos, keyframe,
1973                 mask, point, create_it);
1974
1975         if(track)
1976         {
1977 #ifdef USE_KEYFRAME_SPANNING
1978 // Create temp keyframe
1979                 MaskAuto temp_keyframe(mwindow->edl, autos);
1980                 temp_keyframe.copy_data(keyframe);
1981 // Update parameter
1982                 temp_keyframe.value = get_value();
1983 // Commit change to span of keyframes
1984                 autos->update_parameter(&temp_keyframe);
1985 #else
1986                 keyframe->value = get_value();
1987 #endif
1988         }
1989
1990         gui->update_preview();
1991         mwindow->undo->update_undo_after(_("mask value"), LOAD_AUTOMATION);
1992         return 1;
1993 }
1994
1995
1996 CWindowMaskBeforePlugins::CWindowMaskBeforePlugins(CWindowToolGUI *gui, int x, int y)
1997  : BC_CheckBox(x,
1998         y,
1999         1,
2000         _("Apply mask before plugins"))
2001 {
2002         this->gui = gui;
2003 }
2004
2005 int CWindowMaskBeforePlugins::handle_event()
2006 {
2007         Track *track;
2008         MaskAutos *autos;
2009         MaskAuto *keyframe;
2010         SubMask *mask;
2011         MaskPoint *point;
2012         ((CWindowMaskGUI*)gui)->get_keyframe(track, autos, keyframe, mask, point, 1);
2013
2014         if (keyframe) {
2015                 keyframe->apply_before_plugins = get_value();
2016                 gui->update_preview();
2017         }
2018         return 1;
2019 }
2020
2021
2022 CWindowDisableOpenGLMasking::CWindowDisableOpenGLMasking(CWindowToolGUI *gui, int x, int y)
2023  : BC_CheckBox(x, y, 1, _("Disable OpenGL masking"))
2024 {
2025         this->gui = gui;
2026 }
2027
2028 int CWindowDisableOpenGLMasking::handle_event()
2029 {
2030         Track *track;
2031         MaskAutos *autos;
2032         MaskAuto *keyframe;
2033         SubMask *mask;
2034         MaskPoint *point;
2035         ((CWindowMaskGUI*)gui)->get_keyframe(track, autos, keyframe, mask, point, 1);
2036
2037         if (keyframe) {
2038                 keyframe->disable_opengl_masking = get_value();
2039                 gui->update_preview();
2040         }
2041         return 1;
2042 }
2043
2044
2045
2046
2047
2048
2049
2050
2051
2052 CWindowMaskGUI::CWindowMaskGUI(MWindow *mwindow, CWindowTool *thread)
2053  : CWindowToolGUI(mwindow,
2054         thread,
2055         _(PROGRAM_NAME ": Mask"),
2056         330,
2057         310)
2058 {
2059         this->mwindow = mwindow;
2060         this->thread = thread;
2061         number = 0;
2062         active_point = 0;
2063         feather = 0;
2064 }
2065 CWindowMaskGUI::~CWindowMaskGUI()
2066 {
2067         lock_window("CWindowMaskGUI::~CWindowMaskGUI");
2068         delete number;
2069         delete active_point;
2070         delete feather;
2071         unlock_window();
2072 }
2073
2074 void CWindowMaskGUI::create_objects()
2075 {
2076         int x = 10, y = 10, margin = mwindow->theme->widget_border;
2077         //MaskAuto *keyframe = 0;
2078         //Track *track = mwindow->cwindow->calculate_affected_track();
2079         //if(track)
2080         //      keyframe = (MaskAuto*)mwindow->cwindow->calculate_affected_auto(track->automation->autos[AUTOMATION_MASK], 0);
2081
2082         lock_window("CWindowMaskGUI::create_objects");
2083         BC_Title *title;
2084         add_subwindow(title = new BC_Title(x, y, _("Mode:")));
2085         add_subwindow(mode = new CWindowMaskMode(mwindow,
2086                 this, x + title->get_w() + margin, y, ""));
2087         mode->create_objects();
2088         y += mode->get_h() + margin;
2089         add_subwindow(title = new BC_Title(x, y, _("Value:")));
2090         add_subwindow(value = new CWindowMaskValue(mwindow, this, x + title->get_w() + margin, y));
2091         y += value->get_h() + margin;
2092         add_subwindow(delete_point = new CWindowMaskDelete(mwindow, this, x, y));
2093         int x1 = x + delete_point->get_w() + 2*margin;
2094         add_subwindow(title = new BC_Title(x1, y, _("Point:")));
2095         x1 += title->get_w() + margin;
2096         active_point = new CWindowMaskAffectedPoint(mwindow, this, x1, y);
2097         active_point->create_objects();
2098         y += delete_point->get_h() + margin;
2099         add_subwindow(title = new BC_Title(x, y, _("Mask number:")));
2100         number = new CWindowMaskNumber(mwindow,
2101                 this, x + title->get_w() + margin, y);
2102         number->create_objects();
2103         y += number->get_h() + margin;
2104         add_subwindow(title = new BC_Title(x, y, _("Feather:")));
2105         feather = new CWindowMaskFeather(mwindow,
2106                 this, x + title->get_w() + margin, y);
2107         feather->create_objects();
2108         y += feather->get_h() + margin;
2109         add_subwindow(title = new BC_Title(x, y, "X:"));
2110         x += title->get_w() + margin;
2111         this->x = new CWindowCoord(this, x, y, (float)0.0);
2112         this->x->create_objects();
2113         x += this->x->get_w() + margin;
2114         add_subwindow(title = new BC_Title(x, y, "Y:"));
2115         x += title->get_w() + margin;
2116         this->y = new CWindowCoord(this, x, y, (float)0.0);
2117         this->y->create_objects();
2118
2119         x = 10;
2120         y += this->y->get_h() + margin;
2121         add_subwindow(title = new BC_Title(x, y, _("Press Shift to move an end point")));
2122         y += title->get_h() + margin;
2123         add_subwindow(title = new BC_Title(x, y, _("Press Ctrl to move a control point")));
2124         y += title->get_h() + margin;
2125         add_subwindow(title = new BC_Title(x, y, _("Press Alt to translate the mask")));
2126         y += 30;
2127
2128         add_subwindow(this->apply_before_plugins = new CWindowMaskBeforePlugins(this, 10, y));
2129         y += this->apply_before_plugins->get_h() + margin;
2130         add_subwindow(this->disable_opengl_masking = new CWindowDisableOpenGLMasking(this, 10, y));
2131
2132         update();
2133         unlock_window();
2134 }
2135
2136 void CWindowMaskGUI::get_keyframe(Track* &track,
2137         MaskAutos* &autos,
2138         MaskAuto* &keyframe,
2139         SubMask* &mask,
2140         MaskPoint* &point,
2141         int create_it)
2142 {
2143         autos = 0;
2144         keyframe = 0;
2145
2146         track = mwindow->cwindow->calculate_affected_track();
2147         if(track)
2148         {
2149                 autos = (MaskAutos*)track->automation->autos[AUTOMATION_MASK];
2150                 keyframe = (MaskAuto*)mwindow->cwindow->calculate_affected_auto(
2151                         autos,
2152                         create_it);
2153         }
2154
2155         if(keyframe)
2156                 mask = keyframe->get_submask(mwindow->edl->session->cwindow_mask);
2157         else
2158                 mask = 0;
2159
2160         point = 0;
2161         if(keyframe)
2162         {
2163                 if(mwindow->cwindow->gui->affected_point < mask->points.total &&
2164                         mwindow->cwindow->gui->affected_point >= 0)
2165                 {
2166                         point = mask->points.values[mwindow->cwindow->gui->affected_point];
2167                 }
2168         }
2169 }
2170
2171 void CWindowMaskGUI::update()
2172 {
2173         Track *track;
2174         MaskAutos *autos;
2175         MaskAuto *keyframe;
2176         SubMask *mask;
2177         MaskPoint *point;
2178 //printf("CWindowMaskGUI::update 1\n");
2179         get_keyframe(track, autos, keyframe, mask, point, 0);
2180
2181         double position = mwindow->edl->local_session->get_selectionstart(1);
2182         position = mwindow->edl->align_to_frame(position, 0);
2183         if(track)
2184         {
2185                 int64_t position_i = track->to_units(position, 0);
2186
2187                 if(point)
2188                 {
2189                         x->update(point->x);
2190                         y->update(point->y);
2191                 }
2192
2193                 if(mask)
2194                 {
2195                         feather->update((int64_t)autos->get_feather(position_i, PLAY_FORWARD));
2196                         value->update((int64_t)autos->get_value(position_i, PLAY_FORWARD));
2197                         apply_before_plugins->update((int64_t)keyframe->apply_before_plugins);
2198                         disable_opengl_masking->update((int64_t)keyframe->disable_opengl_masking);
2199                 }
2200         }
2201
2202 //printf("CWindowMaskGUI::update 1\n");
2203         active_point->update((int64_t)mwindow->cwindow->gui->affected_point);
2204         number->update((int64_t)mwindow->edl->session->cwindow_mask);
2205
2206 //printf("CWindowMaskGUI::update 1\n");
2207         if(track)
2208         {
2209 #ifdef USE_KEYFRAME_SPANNING
2210                 mode->set_text(
2211                         CWindowMaskMode::mode_to_text(keyframe->mode));
2212 #else
2213                 mode->set_text(
2214                         CWindowMaskMode::mode_to_text(((MaskAuto*)autos->default_auto)->mode));
2215 #endif
2216         }
2217 //printf("CWindowMaskGUI::update 2\n");
2218 }
2219
2220 void CWindowMaskGUI::handle_event()
2221 {
2222         Track *track;
2223         MaskAuto *keyframe;
2224         MaskAutos *autos;
2225         SubMask *mask;
2226         MaskPoint *point;
2227         get_keyframe(track, autos, keyframe, mask, point, 0);
2228
2229         mwindow->undo->update_undo_before(_("mask point"), this);
2230
2231         if(point)
2232         {
2233 #ifdef USE_KEYFRAME_SPANNING
2234 // Create temp keyframe
2235                 MaskAuto temp_keyframe(mwindow->edl, autos);
2236                 temp_keyframe.copy_data(keyframe);
2237 // Get affected point in temp keyframe
2238                 mask = temp_keyframe.get_submask(mwindow->edl->session->cwindow_mask);
2239                 if(mwindow->cwindow->gui->affected_point < mask->points.total &&
2240                         mwindow->cwindow->gui->affected_point >= 0)
2241                 {
2242                         point = mask->points.values[mwindow->cwindow->gui->affected_point];
2243                 }
2244
2245                 if(point)
2246                 {
2247                         point->x = atof(x->get_text());
2248                         point->y = atof(y->get_text());
2249 // Commit to spanned keyframes
2250                         autos->update_parameter(&temp_keyframe);
2251                 }
2252 #else
2253                 point->x = atof(x->get_text());
2254                 point->y = atof(y->get_text());
2255 #endif
2256         }
2257
2258         update_preview();
2259         mwindow->undo->update_undo_after(_("mask point"), LOAD_AUTOMATION);
2260 }
2261
2262 void CWindowMaskGUI::update_preview()
2263 {
2264         mwindow->gui->lock_window("CWindowMaskGUI::update_preview");
2265         mwindow->restart_brender();
2266         mwindow->sync_parameters(CHANGE_PARAMS);
2267         mwindow->gui->draw_overlays(1);
2268         mwindow->gui->unlock_window();
2269         mwindow->cwindow->refresh_frame(CHANGE_NONE);
2270         mwindow->cwindow->gui->lock_window("CWindowMaskGUI::update_preview");
2271         mwindow->cwindow->gui->canvas->draw_refresh();
2272         mwindow->cwindow->gui->unlock_window();
2273 }
2274
2275
2276 CWindowRulerGUI::CWindowRulerGUI(MWindow *mwindow, CWindowTool *thread)
2277  : CWindowToolGUI(mwindow,
2278         thread,
2279         _(PROGRAM_NAME ": Ruler"),
2280         320,
2281         240)
2282 {
2283 }
2284
2285 CWindowRulerGUI::~CWindowRulerGUI()
2286 {
2287 }
2288
2289 void CWindowRulerGUI::create_objects()
2290 {
2291         int x = 10, y = 10;
2292         BC_Title *title;
2293
2294         lock_window("CWindowRulerGUI::create_objects");
2295         add_subwindow(title = new BC_Title(x, y, _("Current:")));
2296         add_subwindow(current = new BC_Title(x + title->get_w() + 10, y, ""));
2297         y += title->get_h() + 5;
2298
2299         add_subwindow(title = new BC_Title(x, y, _("Point 1:")));
2300         add_subwindow(point1 = new BC_Title(x + title->get_w() + 10, y, ""));
2301         y += title->get_h() + 5;
2302
2303         add_subwindow(title = new BC_Title(x, y, _("Point 2:")));
2304         add_subwindow(point2 = new BC_Title(x + title->get_w() + 10, y, ""));
2305         y += title->get_h() + 5;
2306
2307         add_subwindow(title = new BC_Title(x, y, _("Distance:")));
2308         add_subwindow(distance = new BC_Title(x + title->get_w() + 10, y, ""));
2309         y += title->get_h() + 5;
2310         add_subwindow(title = new BC_Title(x, y, _("Angle:")));
2311         add_subwindow(angle = new BC_Title(x + title->get_w() + 10, y, ""));
2312         y += title->get_h() + 10;
2313         char string[BCTEXTLEN];
2314         sprintf(string, _("Press Ctrl to lock ruler to the\nnearest 45%c angle."), 0xb0);
2315         add_subwindow(title = new BC_Title(x,
2316                 y,
2317                 string));
2318         y += title->get_h() + 10;
2319         sprintf(string, _("Press Alt to translate the ruler."));
2320         add_subwindow(title = new BC_Title(x,
2321                 y,
2322                 string));
2323         update();
2324         unlock_window();
2325 }
2326
2327 void CWindowRulerGUI::update()
2328 {
2329         double distance_value =
2330                 sqrt(SQR(mwindow->edl->session->ruler_x2 - mwindow->edl->session->ruler_x1) +
2331                 SQR(mwindow->edl->session->ruler_y2 - mwindow->edl->session->ruler_y1));
2332         double angle_value = atan((mwindow->edl->session->ruler_y2 - mwindow->edl->session->ruler_y1) /
2333                 (mwindow->edl->session->ruler_x2 - mwindow->edl->session->ruler_x1)) *
2334                 360 /
2335                 2 /
2336                 M_PI;
2337
2338         if(EQUIV(distance_value, 0.0))
2339         {
2340                 angle_value = 0.0;
2341         }
2342         else
2343         if(angle_value < 0)
2344         {
2345                 angle_value *= -1;
2346         }
2347
2348         char string[BCTEXTLEN];
2349         sprintf(string, "%d, %d",
2350                 mwindow->session->cwindow_output_x,
2351                 mwindow->session->cwindow_output_y);
2352         current->update(string);
2353         sprintf(string, "%.0f, %.0f",
2354                 mwindow->edl->session->ruler_x1,
2355                 mwindow->edl->session->ruler_y1);
2356         point1->update(string);
2357         sprintf(string, "%.0f, %.0f",
2358                 mwindow->edl->session->ruler_x2,
2359                 mwindow->edl->session->ruler_y2);
2360         point2->update(string);
2361
2362         sprintf(string, _("%0.01f pixels"), distance_value);
2363         distance->update(string);
2364         sprintf(string, "%0.02f %c", angle_value, 0xb0);
2365         angle->update(string);
2366 }
2367
2368 void CWindowRulerGUI::handle_event()
2369 {
2370 }
2371
2372
2373
2374