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