Credit Andrew - improve in-tree documentation
[goodguy/cinelerra.git] / 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         FloatAuto *x=0, *y=0, *z=0;
700         Track *track = mwindow->cwindow->calculate_affected_track();
701
702         if(track)
703         {       mwindow->cwindow->calculate_affected_autos(&x, &y, &z,
704                         track, cfg.use_camera, 0,0,0); // don't create new keyframe
705
706                 if(x)   x->change_curve_mode(cfg.mode);
707                 if(y)   y->change_curve_mode(cfg.mode);
708                 if(z)   z->change_curve_mode(cfg.mode);
709
710                 gui->update();
711                 gui->update_preview();
712         }
713
714         return 1;
715 }
716
717
718 CWindowEyedropCheckBox::CWindowEyedropCheckBox(MWindow *mwindow, 
719         CWindowEyedropGUI *gui, int x, int y)
720  : BC_CheckBox(x, y, mwindow->edl->local_session->use_max, _("Use maximum"))
721 {
722         this->mwindow = mwindow;
723         this->gui = gui;
724 }
725
726 int CWindowEyedropCheckBox::handle_event()
727 {
728         mwindow->edl->local_session->use_max = get_value();
729         
730         gui->update();
731         return 1;
732 }
733
734
735 CWindowCameraGUI::CWindowCameraGUI(MWindow *mwindow, CWindowTool *thread)
736  : CWindowToolGUI(mwindow,
737         thread,
738         _(PROGRAM_NAME ": Camera"),
739         170,
740         170)
741 {
742 }
743 CWindowCameraGUI::~CWindowCameraGUI()
744 {
745 }
746
747 void CWindowCameraGUI::create_objects()
748 {
749         int x = 10, y = 10, x1;
750         Track *track = mwindow->cwindow->calculate_affected_track();
751         FloatAuto *x_auto = 0;
752         FloatAuto *y_auto = 0;
753         FloatAuto *z_auto = 0;
754         BC_Title *title;
755         BC_Button *button;
756
757         lock_window("CWindowCameraGUI::create_objects");
758         if(track)
759         {
760                 mwindow->cwindow->calculate_affected_autos(&x_auto,
761                         &y_auto, &z_auto, track, 1, 0, 0, 0);
762         }
763
764         add_subwindow(title = new BC_Title(x, y, "X:"));
765         x += title->get_w();
766         this->x = new CWindowCoord(this, x, y,
767                 x_auto ? x_auto->get_value() : (float)0);
768         this->x->create_objects();
769
770
771         y += 30;
772         x = 10;
773         add_subwindow(title = new BC_Title(x, y, "Y:"));
774         x += title->get_w();
775         this->y = new CWindowCoord(this, x, y,
776                 y_auto ? y_auto->get_value() : (float)0);
777         this->y->create_objects();
778         y += 30;
779         x = 10;
780         add_subwindow(title = new BC_Title(x, y, "Z:"));
781         x += title->get_w();
782         this->z = new CWindowCoord(this, x, y,
783                 z_auto ? z_auto->get_value() : (float)1);
784         this->z->create_objects();
785         this->z->set_increment(0.01);
786
787         y += 30;
788         x1 = 10;
789         add_subwindow(button = new CWindowCameraLeft(mwindow, this, x1, y));
790         x1 += button->get_w();
791         add_subwindow(button = new CWindowCameraCenter(mwindow, this, x1, y));
792         x1 += button->get_w();
793         add_subwindow(button = new CWindowCameraRight(mwindow, this, x1, y));
794
795         y += button->get_h();
796         x1 = 10;
797         add_subwindow(button = new CWindowCameraTop(mwindow, this, x1, y));
798         x1 += button->get_w();
799         add_subwindow(button = new CWindowCameraMiddle(mwindow, this, x1, y));
800         x1 += button->get_w();
801         add_subwindow(button = new CWindowCameraBottom(mwindow, this, x1, y));
802 // additional Buttons to control the curve mode of the "current" keyframe
803         x1 += button->get_w() + 15;
804         add_subwindow(this->t_smooth = new CWindowCurveToggle(Camera_Crv_Smooth, mwindow, this, x1, y));
805         x1 += button->get_w();
806         add_subwindow(this->t_linear = new CWindowCurveToggle(Camera_Crv_Linear, mwindow, this, x1, y));
807
808 // fill in current auto keyframe values, set toggle states.
809         this->update();
810         unlock_window();
811 }
812
813 void CWindowCameraGUI::update_preview()
814 {
815         mwindow->gui->lock_window("CWindowCameraGUI::update_preview");
816         mwindow->restart_brender();
817         mwindow->gui->draw_overlays(1);
818         mwindow->sync_parameters(CHANGE_PARAMS);
819         mwindow->gui->unlock_window();
820         mwindow->cwindow->refresh_frame(CHANGE_NONE);
821         mwindow->cwindow->gui->lock_window("CWindowCameraGUI::update_preview");
822         mwindow->cwindow->gui->canvas->draw_refresh();
823         mwindow->cwindow->gui->unlock_window();
824 }
825
826
827 void CWindowCameraGUI::handle_event()
828 {
829         FloatAuto *x_auto = 0;
830         FloatAuto *y_auto = 0;
831         FloatAuto *z_auto = 0;
832         Track *track = mwindow->cwindow->calculate_affected_track();
833         if(track)
834         {
835                 mwindow->undo->update_undo_before(_("camera"), this);
836                 if(event_caller == x)
837                 {
838                         x_auto = (FloatAuto*)mwindow->cwindow->calculate_affected_auto(
839                                 track->automation->autos[AUTOMATION_CAMERA_X],
840                                 1);
841                         if(x_auto)
842                         {
843                                 x_auto->set_value(atof(x->get_text()));
844                                 update();
845                                 update_preview();
846                         }
847                 }
848                 else
849                 if(event_caller == y)
850                 {
851                         y_auto = (FloatAuto*)mwindow->cwindow->calculate_affected_auto(
852                                 track->automation->autos[AUTOMATION_CAMERA_Y],
853                                 1);
854                         if(y_auto)
855                         {
856                                 y_auto->set_value(atof(y->get_text()));
857                                 update();
858                                 update_preview();
859                         }
860                 }
861                 else
862                 if(event_caller == z)
863                 {
864                         z_auto = (FloatAuto*)mwindow->cwindow->calculate_affected_auto(
865                                 track->automation->autos[AUTOMATION_CAMERA_Z],
866                                 1);
867                         if(z_auto)
868                         {
869                                 float zoom = atof(z->get_text());
870                                 if(zoom > 100.) zoom = 100.;
871                                 else
872                                 if(zoom < 0.01) zoom = 0.01;
873         // Doesn't allow user to enter from scratch
874         //              if(zoom != atof(z->get_text()))
875         //                      z->update(zoom);
876
877                                 z_auto->set_value(zoom);
878                                 mwindow->gui->lock_window("CWindowCameraGUI::handle_event");
879                                 mwindow->gui->draw_overlays(1);
880                                 mwindow->gui->unlock_window();
881                                 update();
882                                 update_preview();
883                         }
884                 }
885
886                 mwindow->undo->update_undo_after(_("camera"), LOAD_ALL);
887         }
888 }
889
890 void CWindowCameraGUI::update()
891 {
892         FloatAuto *x_auto = 0;
893         FloatAuto *y_auto = 0;
894         FloatAuto *z_auto = 0;
895         Track *track = mwindow->cwindow->calculate_affected_track();
896
897         if(track)
898         {
899                 mwindow->cwindow->calculate_affected_autos(&x_auto,
900                         &y_auto,
901                         &z_auto,
902                         track,
903                         1,
904                         0,
905                         0,
906                         0);
907         }
908
909         if(x_auto)
910                 x->update(x_auto->get_value());
911         if(y_auto)
912                 y->update(y_auto->get_value());
913         if(z_auto) {
914                 float value = z_auto->get_value();
915                 z->update(value);
916                 thread->gui->lock_window("CWindowCameraGUI::update");
917                 thread->gui->composite_panel->cpanel_zoom->update(value);
918                 thread->gui->unlock_window();
919         }
920
921         if( x_auto && y_auto && z_auto )
922         {
923                 t_smooth->check_toggle_state(x_auto, y_auto, z_auto);
924                 t_linear->check_toggle_state(x_auto, y_auto, z_auto);
925         }
926 }
927
928
929
930
931 CWindowCameraLeft::CWindowCameraLeft(MWindow *mwindow, CWindowCameraGUI *gui, int x, int y)
932  : BC_Button(x, y, mwindow->theme->get_image_set("left_justify"))
933 {
934         this->gui = gui;
935         this->mwindow = mwindow;
936         set_tooltip(_("Left justify"));
937 }
938 int CWindowCameraLeft::handle_event()
939 {
940         FloatAuto *x_auto = 0;
941         FloatAuto *z_auto = 0;
942         Track *track = mwindow->cwindow->calculate_affected_track();
943         if(track)
944         {
945                 mwindow->cwindow->calculate_affected_autos(&x_auto,
946                         0,
947                         &z_auto,
948                         track,
949                         1,
950                         1,
951                         0,
952                         0);
953         }
954
955         if(x_auto && z_auto)
956         {
957                 int w = 0, h = 0;
958                 track->get_source_dimensions(
959                         mwindow->edl->local_session->get_selectionstart(1),
960                         w,
961                         h);
962
963                 if(w && h)
964                 {
965                         mwindow->undo->update_undo_before(_("camera"), 0);
966                         x_auto->set_value(
967                                 (double)track->track_w / z_auto->get_value() / 2 -
968                                 (double)w / 2);
969                         mwindow->undo->update_undo_after(_("camera"), LOAD_ALL);
970                         gui->update();
971                         gui->update_preview();
972                 }
973         }
974
975         return 1;
976 }
977
978
979 CWindowCameraCenter::CWindowCameraCenter(MWindow *mwindow, CWindowCameraGUI *gui, int x, int y)
980  : BC_Button(x, y, mwindow->theme->get_image_set("center_justify"))
981 {
982         this->gui = gui;
983         this->mwindow = mwindow;
984         set_tooltip(_("Center horizontal"));
985 }
986 int CWindowCameraCenter::handle_event()
987 {
988         FloatAuto *x_auto = 0;
989         Track *track = mwindow->cwindow->calculate_affected_track();
990         if(track)
991                 x_auto = (FloatAuto*)mwindow->cwindow->calculate_affected_auto(
992                         track->automation->autos[AUTOMATION_CAMERA_X],
993                         1);
994
995         if(x_auto)
996         {
997                 mwindow->undo->update_undo_before(_("camera"), 0);
998                 x_auto->set_value(0);
999                 gui->update();
1000                 gui->update_preview();
1001                 mwindow->undo->update_undo_after(_("camera"), LOAD_ALL);
1002         }
1003
1004         return 1;
1005 }
1006
1007
1008 CWindowCameraRight::CWindowCameraRight(MWindow *mwindow, CWindowCameraGUI *gui, int x, int y)
1009  : BC_Button(x, y, mwindow->theme->get_image_set("right_justify"))
1010 {
1011         this->gui = gui;
1012         this->mwindow = mwindow;
1013         set_tooltip(_("Right justify"));
1014 }
1015 int CWindowCameraRight::handle_event()
1016 {
1017         FloatAuto *x_auto = 0;
1018         FloatAuto *z_auto = 0;
1019         Track *track = mwindow->cwindow->calculate_affected_track();
1020         if(track)
1021         {
1022                 mwindow->cwindow->calculate_affected_autos(&x_auto,
1023                         0,
1024                         &z_auto,
1025                         track,
1026                         1,
1027                         1,
1028                         0,
1029                         0);
1030         }
1031
1032         if(x_auto && z_auto)
1033         {
1034                 int w = 0, h = 0;
1035                 track->get_source_dimensions(
1036                         mwindow->edl->local_session->get_selectionstart(1),
1037                         w,
1038                         h);
1039
1040                 if(w && h)
1041                 {
1042                         mwindow->undo->update_undo_before(_("camera"), 0);
1043                         x_auto->set_value( -((double)track->track_w / z_auto->get_value() / 2 -
1044                                 (double)w / 2));
1045                         gui->update();
1046                         gui->update_preview();
1047                         mwindow->undo->update_undo_after(_("camera"), LOAD_ALL);
1048                 }
1049         }
1050
1051         return 1;
1052 }
1053
1054
1055 CWindowCameraTop::CWindowCameraTop(MWindow *mwindow, CWindowCameraGUI *gui, int x, int y)
1056  : BC_Button(x, y, mwindow->theme->get_image_set("top_justify"))
1057 {
1058         this->gui = gui;
1059         this->mwindow = mwindow;
1060         set_tooltip(_("Top justify"));
1061 }
1062 int CWindowCameraTop::handle_event()
1063 {
1064         FloatAuto *y_auto = 0;
1065         FloatAuto *z_auto = 0;
1066         Track *track = mwindow->cwindow->calculate_affected_track();
1067         if(track)
1068         {
1069                 mwindow->cwindow->calculate_affected_autos(0,
1070                         &y_auto,
1071                         &z_auto,
1072                         track,
1073                         1,
1074                         0,
1075                         1,
1076                         0);
1077         }
1078
1079         if(y_auto && z_auto)
1080         {
1081                 int w = 0, h = 0;
1082                 track->get_source_dimensions(
1083                         mwindow->edl->local_session->get_selectionstart(1),
1084                         w,
1085                         h);
1086
1087                 if(w && h)
1088                 {
1089                         mwindow->undo->update_undo_before(_("camera"), 0);
1090                         y_auto->set_value((double)track->track_h / z_auto->get_value() / 2 -
1091                                 (double)h / 2);
1092                         gui->update();
1093                         gui->update_preview();
1094                         mwindow->undo->update_undo_after(_("camera"), LOAD_ALL);
1095                 }
1096         }
1097
1098         return 1;
1099 }
1100
1101
1102 CWindowCameraMiddle::CWindowCameraMiddle(MWindow *mwindow, CWindowCameraGUI *gui, int x, int y)
1103  : BC_Button(x, y, mwindow->theme->get_image_set("middle_justify"))
1104 {
1105         this->gui = gui;
1106         this->mwindow = mwindow;
1107         set_tooltip(_("Center vertical"));
1108 }
1109 int CWindowCameraMiddle::handle_event()
1110 {
1111         FloatAuto *y_auto = 0;
1112         Track *track = mwindow->cwindow->calculate_affected_track();
1113         if(track)
1114                 y_auto = (FloatAuto*)mwindow->cwindow->calculate_affected_auto(
1115                         track->automation->autos[AUTOMATION_CAMERA_Y], 1);
1116
1117         if(y_auto)
1118         {
1119                 mwindow->undo->update_undo_before(_("camera"), 0);
1120                 y_auto->set_value(0);
1121                 gui->update();
1122                 gui->update_preview();
1123                 mwindow->undo->update_undo_after(_("camera"), LOAD_ALL);
1124         }
1125
1126         return 1;
1127 }
1128
1129
1130 CWindowCameraBottom::CWindowCameraBottom(MWindow *mwindow, CWindowCameraGUI *gui, int x, int y)
1131  : BC_Button(x, y, mwindow->theme->get_image_set("bottom_justify"))
1132 {
1133         this->gui = gui;
1134         this->mwindow = mwindow;
1135         set_tooltip(_("Bottom justify"));
1136 }
1137 int CWindowCameraBottom::handle_event()
1138 {
1139         FloatAuto *y_auto = 0;
1140         FloatAuto *z_auto = 0;
1141         Track *track = mwindow->cwindow->calculate_affected_track();
1142         if(track)
1143         {
1144                 mwindow->cwindow->calculate_affected_autos(0,
1145                         &y_auto,
1146                         &z_auto,
1147                         track,
1148                         1,
1149                         0,
1150                         1,
1151                         0);
1152         }
1153
1154         if(y_auto && z_auto)
1155         {
1156                 int w = 0, h = 0;
1157                 track->get_source_dimensions(
1158                         mwindow->edl->local_session->get_selectionstart(1),
1159                         w,
1160                         h);
1161
1162                 if(w && h)
1163                 {
1164                         mwindow->undo->update_undo_before(_("camera"), 0);
1165                         y_auto->set_value(-((double)track->track_h / z_auto->get_value() / 2 -
1166                                 (double)h / 2));
1167                         gui->update();
1168                         gui->update_preview();
1169                         mwindow->undo->update_undo_after(_("camera"), LOAD_ALL);
1170                 }
1171         }
1172
1173         return 1;
1174 }
1175
1176
1177 CWindowProjectorGUI::CWindowProjectorGUI(MWindow *mwindow, CWindowTool *thread)
1178  : CWindowToolGUI(mwindow,
1179         thread,
1180         _(PROGRAM_NAME ": Projector"),
1181         170,
1182         170)
1183 {
1184 }
1185 CWindowProjectorGUI::~CWindowProjectorGUI()
1186 {
1187 }
1188 void CWindowProjectorGUI::create_objects()
1189 {
1190         int x = 10, y = 10, x1;
1191         Track *track = mwindow->cwindow->calculate_affected_track();
1192         FloatAuto *x_auto = 0;
1193         FloatAuto *y_auto = 0;
1194         FloatAuto *z_auto = 0;
1195         BC_Title *title;
1196         BC_Button *button;
1197
1198         lock_window("CWindowProjectorGUI::create_objects");
1199         if(track)
1200         {
1201                 mwindow->cwindow->calculate_affected_autos(&x_auto,
1202                         &y_auto,
1203                         &z_auto,
1204                         track,
1205                         0,
1206                         0,
1207                         0,
1208                         0);
1209         }
1210
1211         add_subwindow(title = new BC_Title(x, y, "X:"));
1212         x += title->get_w();
1213         this->x = new CWindowCoord(this, x, y,
1214                 x_auto ? x_auto->get_value() : (float)0);
1215         this->x->create_objects();
1216         y += 30;
1217         x = 10;
1218         add_subwindow(title = new BC_Title(x, y, "Y:"));
1219         x += title->get_w();
1220         this->y = new CWindowCoord(this, x, y,
1221                 y_auto ? y_auto->get_value() : (float)0);
1222         this->y->create_objects();
1223         y += 30;
1224         x = 10;
1225         add_subwindow(title = new BC_Title(x, y, "Z:"));
1226         x += title->get_w();
1227         this->z = new CWindowCoord(this, x, y,
1228                 z_auto ? z_auto->get_value() : (float)1);
1229         this->z->create_objects();
1230         this->z->set_increment(0.01);
1231
1232         y += 30;
1233         x1 = 10;
1234         add_subwindow(button = new CWindowProjectorLeft(mwindow, this, x1, y));
1235         x1 += button->get_w();
1236         add_subwindow(button = new CWindowProjectorCenter(mwindow, this, x1, y));
1237         x1 += button->get_w();
1238         add_subwindow(button = new CWindowProjectorRight(mwindow, this, x1, y));
1239
1240         y += button->get_h();
1241         x1 = 10;
1242         add_subwindow(button = new CWindowProjectorTop(mwindow, this, x1, y));
1243         x1 += button->get_w();
1244         add_subwindow(button = new CWindowProjectorMiddle(mwindow, this, x1, y));
1245         x1 += button->get_w();
1246         add_subwindow(button = new CWindowProjectorBottom(mwindow, this, x1, y));
1247
1248 // additional Buttons to control the curve mode of the "current" keyframe
1249         x1 += button->get_w() + 15;
1250         add_subwindow(this->t_smooth = new CWindowCurveToggle(Projector_Crv_Smooth, mwindow, this, x1, y));
1251         x1 += button->get_w();
1252         add_subwindow(this->t_linear = new CWindowCurveToggle(Projector_Crv_Linear, mwindow, this, x1, y));
1253
1254 // fill in current auto keyframe values, set toggle states.
1255         this->update();
1256         unlock_window();
1257 }
1258
1259 void CWindowProjectorGUI::update_preview()
1260 {
1261         mwindow->gui->lock_window("CWindowProjectorGUI::update_preview");
1262         mwindow->restart_brender();
1263         mwindow->sync_parameters(CHANGE_PARAMS);
1264         mwindow->gui->draw_overlays(1);
1265         mwindow->gui->unlock_window();
1266         mwindow->cwindow->refresh_frame(CHANGE_NONE);
1267         mwindow->cwindow->gui->lock_window("CWindowProjectorGUI::update_preview");
1268         mwindow->cwindow->gui->canvas->draw_refresh();
1269         mwindow->cwindow->gui->unlock_window();
1270 }
1271
1272 void CWindowProjectorGUI::handle_event()
1273 {
1274         FloatAuto *x_auto = 0;
1275         FloatAuto *y_auto = 0;
1276         FloatAuto *z_auto = 0;
1277         Track *track = mwindow->cwindow->calculate_affected_track();
1278
1279         if(track)
1280         {
1281                 mwindow->undo->update_undo_before(_("projector"), this);
1282                 if(event_caller == x)
1283                 {
1284                         x_auto = (FloatAuto*)mwindow->cwindow->calculate_affected_auto(
1285                                 track->automation->autos[AUTOMATION_PROJECTOR_X],
1286                                 1);
1287                         if(x_auto)
1288                         {
1289                                 x_auto->set_value(atof(x->get_text()));
1290                                 update();
1291                                 update_preview();
1292                         }
1293                 }
1294                 else
1295                 if(event_caller == y)
1296                 {
1297                         y_auto = (FloatAuto*)mwindow->cwindow->calculate_affected_auto(
1298                                 track->automation->autos[AUTOMATION_PROJECTOR_Y],
1299                                 1);
1300                         if(y_auto)
1301                         {
1302                                 y_auto->set_value(atof(y->get_text()));
1303                                 update();
1304                                 update_preview();
1305                         }
1306                 }
1307                 else
1308                 if(event_caller == z)
1309                 {
1310                         z_auto = (FloatAuto*)mwindow->cwindow->calculate_affected_auto(
1311                                 track->automation->autos[AUTOMATION_PROJECTOR_Z],
1312                                 1);
1313                         if(z_auto)
1314                         {
1315                                 float zoom = atof(z->get_text());
1316                                 if(zoom > 100.) zoom = 100.;
1317                                 else if(zoom < 0.01) zoom = 0.01;
1318 //                      if (zoom != atof(z->get_text()))
1319 //                              z->update(zoom);
1320                                 z_auto->set_value(zoom);
1321
1322                                 mwindow->gui->lock_window("CWindowProjectorGUI::handle_event");
1323                                 mwindow->gui->draw_overlays(1);
1324                                 mwindow->gui->unlock_window();
1325
1326                                 update();
1327                                 update_preview();
1328                         }
1329                 }
1330                 mwindow->undo->update_undo_after(_("projector"), LOAD_ALL);
1331         }
1332 }
1333
1334 void CWindowProjectorGUI::update()
1335 {
1336         FloatAuto *x_auto = 0;
1337         FloatAuto *y_auto = 0;
1338         FloatAuto *z_auto = 0;
1339         Track *track = mwindow->cwindow->calculate_affected_track();
1340
1341         if(track)
1342         {
1343                 mwindow->cwindow->calculate_affected_autos(&x_auto,
1344                         &y_auto,
1345                         &z_auto,
1346                         track,
1347                         0,
1348                         0,
1349                         0,
1350                         0);
1351         }
1352
1353         if(x_auto)
1354                 x->update(x_auto->get_value());
1355         if(y_auto)
1356                 y->update(y_auto->get_value());
1357         if(z_auto) {
1358                 float value = z_auto->get_value();
1359                 z->update(value);
1360                 thread->gui->lock_window("CWindowProjectorGUI::update");
1361                 thread->gui->composite_panel->cpanel_zoom->update(value);
1362                 thread->gui->unlock_window();
1363         }
1364
1365         if( x_auto && y_auto && z_auto )
1366         {
1367                 t_smooth->check_toggle_state(x_auto, y_auto, z_auto);
1368                 t_linear->check_toggle_state(x_auto, y_auto, z_auto);
1369         }
1370 }
1371
1372 CWindowProjectorLeft::CWindowProjectorLeft(MWindow *mwindow, CWindowProjectorGUI *gui, int x, int y)
1373  : BC_Button(x, y, mwindow->theme->get_image_set("left_justify"))
1374 {
1375         this->gui = gui;
1376         this->mwindow = mwindow;
1377         set_tooltip(_("Left justify"));
1378 }
1379 int CWindowProjectorLeft::handle_event()
1380 {
1381         FloatAuto *x_auto = 0;
1382         FloatAuto *z_auto = 0;
1383         Track *track = mwindow->cwindow->calculate_affected_track();
1384         if(track)
1385         {
1386                 mwindow->cwindow->calculate_affected_autos(&x_auto,
1387                         0,
1388                         &z_auto,
1389                         track,
1390                         0,
1391                         1,
1392                         0,
1393                         0);
1394         }
1395         if(x_auto && z_auto)
1396         {
1397                 mwindow->undo->update_undo_before(_("projector"), 0);
1398                 x_auto->set_value( (double)track->track_w * z_auto->get_value() / 2 -
1399                         (double)mwindow->edl->session->output_w / 2 );
1400                 gui->update();
1401                 gui->update_preview();
1402                 mwindow->undo->update_undo_after(_("projector"), LOAD_ALL);
1403         }
1404
1405         return 1;
1406 }
1407
1408
1409 CWindowProjectorCenter::CWindowProjectorCenter(MWindow *mwindow, CWindowProjectorGUI *gui, int x, int y)
1410  : BC_Button(x, y, mwindow->theme->get_image_set("center_justify"))
1411 {
1412         this->gui = gui;
1413         this->mwindow = mwindow;
1414         set_tooltip(_("Center horizontal"));
1415 }
1416 int CWindowProjectorCenter::handle_event()
1417 {
1418         FloatAuto *x_auto = 0;
1419         Track *track = mwindow->cwindow->calculate_affected_track();
1420         if(track)
1421                 x_auto = (FloatAuto*)mwindow->cwindow->calculate_affected_auto(
1422                         track->automation->autos[AUTOMATION_PROJECTOR_X],
1423                         1);
1424
1425         if(x_auto)
1426         {
1427                 mwindow->undo->update_undo_before(_("projector"), 0);
1428                 x_auto->set_value(0);
1429                 gui->update();
1430                 gui->update_preview();
1431                 mwindow->undo->update_undo_after(_("projector"), LOAD_ALL);
1432         }
1433
1434         return 1;
1435 }
1436
1437
1438 CWindowProjectorRight::CWindowProjectorRight(MWindow *mwindow, CWindowProjectorGUI *gui, int x, int y)
1439  : BC_Button(x, y, mwindow->theme->get_image_set("right_justify"))
1440 {
1441         this->gui = gui;
1442         this->mwindow = mwindow;
1443         set_tooltip(_("Right justify"));
1444 }
1445 int CWindowProjectorRight::handle_event()
1446 {
1447         FloatAuto *x_auto = 0;
1448         FloatAuto *z_auto = 0;
1449         Track *track = mwindow->cwindow->calculate_affected_track();
1450         if(track)
1451         {
1452                 mwindow->cwindow->calculate_affected_autos(&x_auto,
1453                         0,
1454                         &z_auto,
1455                         track,
1456                         0,
1457                         1,
1458                         0,
1459                         0);
1460         }
1461
1462         if(x_auto && z_auto)
1463         {
1464                 mwindow->undo->update_undo_before(_("projector"), 0);
1465                 x_auto->set_value( -((double)track->track_w * z_auto->get_value() / 2 -
1466                         (double)mwindow->edl->session->output_w / 2));
1467                 gui->update();
1468                 gui->update_preview();
1469                 mwindow->undo->update_undo_after(_("projector"), LOAD_ALL);
1470         }
1471
1472         return 1;
1473 }
1474
1475
1476 CWindowProjectorTop::CWindowProjectorTop(MWindow *mwindow, CWindowProjectorGUI *gui, int x, int y)
1477  : BC_Button(x, y, mwindow->theme->get_image_set("top_justify"))
1478 {
1479         this->gui = gui;
1480         this->mwindow = mwindow;
1481         set_tooltip(_("Top justify"));
1482 }
1483 int CWindowProjectorTop::handle_event()
1484 {
1485         FloatAuto *y_auto = 0;
1486         FloatAuto *z_auto = 0;
1487         Track *track = mwindow->cwindow->calculate_affected_track();
1488         if(track)
1489         {
1490                 mwindow->cwindow->calculate_affected_autos(0,
1491                         &y_auto,
1492                         &z_auto,
1493                         track,
1494                         0,
1495                         0,
1496                         1,
1497                         0);
1498         }
1499
1500         if(y_auto && z_auto)
1501         {
1502                 mwindow->undo->update_undo_before(_("projector"), 0);
1503                 y_auto->set_value( (double)track->track_h * z_auto->get_value() / 2 -
1504                         (double)mwindow->edl->session->output_h / 2 );
1505                 gui->update();
1506                 gui->update_preview();
1507                 mwindow->undo->update_undo_after(_("projector"), LOAD_ALL);
1508         }
1509
1510         return 1;
1511 }
1512
1513
1514 CWindowProjectorMiddle::CWindowProjectorMiddle(MWindow *mwindow, CWindowProjectorGUI *gui, int x, int y)
1515  : BC_Button(x, y, mwindow->theme->get_image_set("middle_justify"))
1516 {
1517         this->gui = gui;
1518         this->mwindow = mwindow;
1519         set_tooltip(_("Center vertical"));
1520 }
1521 int CWindowProjectorMiddle::handle_event()
1522 {
1523         FloatAuto *y_auto = 0;
1524         Track *track = mwindow->cwindow->calculate_affected_track();
1525         if(track)
1526                 y_auto = (FloatAuto*)mwindow->cwindow->calculate_affected_auto(
1527                         track->automation->autos[AUTOMATION_PROJECTOR_Y], 1);
1528
1529         if(y_auto)
1530         {
1531                 mwindow->undo->update_undo_before(_("projector"), 0);
1532                 y_auto->set_value(0);
1533                 gui->update();
1534                 gui->update_preview();
1535                 mwindow->undo->update_undo_after(_("projector"), LOAD_ALL);
1536         }
1537
1538         return 1;
1539 }
1540
1541
1542 CWindowProjectorBottom::CWindowProjectorBottom(MWindow *mwindow, CWindowProjectorGUI *gui, int x, int y)
1543  : BC_Button(x, y, mwindow->theme->get_image_set("bottom_justify"))
1544 {
1545         this->gui = gui;
1546         this->mwindow = mwindow;
1547         set_tooltip(_("Bottom justify"));
1548 }
1549 int CWindowProjectorBottom::handle_event()
1550 {
1551         FloatAuto *y_auto = 0;
1552         FloatAuto *z_auto = 0;
1553         Track *track = mwindow->cwindow->calculate_affected_track();
1554         if(track)
1555         {
1556                 mwindow->cwindow->calculate_affected_autos(0,
1557                         &y_auto,
1558                         &z_auto,
1559                         track,
1560                         0,
1561                         0,
1562                         1,
1563                         0);
1564         }
1565
1566         if(y_auto && z_auto)
1567         {
1568                 mwindow->undo->update_undo_before(_("projector"), 0);
1569                 y_auto->set_value( -((double)track->track_h * z_auto->get_value() / 2 -
1570                         (double)mwindow->edl->session->output_h / 2));
1571                 gui->update();
1572                 gui->update_preview();
1573                 mwindow->undo->update_undo_after(_("projector"), LOAD_ALL);
1574         }
1575
1576         return 1;
1577 }
1578
1579
1580 CWindowMaskMode::CWindowMaskMode(MWindow *mwindow,
1581         CWindowToolGUI *gui, int x, int y, const char *text)
1582  : BC_PopupMenu(x, y, 220, text, 1)
1583 {
1584         this->mwindow = mwindow;
1585         this->gui = gui;
1586 }
1587
1588 void CWindowMaskMode::create_objects()
1589 {
1590         add_item(new BC_MenuItem(mode_to_text(MASK_MULTIPLY_ALPHA)));
1591         add_item(new BC_MenuItem(mode_to_text(MASK_SUBTRACT_ALPHA)));
1592 }
1593
1594 char* CWindowMaskMode::mode_to_text(int mode)
1595 {
1596         switch(mode)
1597         {
1598                 case MASK_MULTIPLY_ALPHA:
1599                         return _("Multiply alpha");
1600                         break;
1601
1602                 case MASK_SUBTRACT_ALPHA:
1603                         return _("Subtract alpha");
1604                         break;
1605         }
1606
1607         return _("Subtract alpha");
1608 }
1609
1610 int CWindowMaskMode::text_to_mode(char *text)
1611 {
1612         if(!strcasecmp(text, _("Multiply alpha")))
1613                 return MASK_MULTIPLY_ALPHA;
1614         else
1615         if(!strcasecmp(text, _("Subtract alpha")))
1616                 return MASK_SUBTRACT_ALPHA;
1617
1618         return MASK_SUBTRACT_ALPHA;
1619 }
1620
1621 int CWindowMaskMode::handle_event()
1622 {
1623         MaskAutos *autos;
1624         MaskAuto *keyframe;
1625         Track *track;
1626         MaskPoint *point;
1627         SubMask *mask;
1628 // Get existing keyframe
1629         ((CWindowMaskGUI*)gui)->get_keyframe(track, autos, keyframe, mask, point, 0);
1630         if(track)
1631         {
1632                 mwindow->undo->update_undo_before(_("mask mode"), 0);
1633 #ifdef USE_KEYFRAME_SPANNING
1634 // Create temp keyframe
1635                 MaskAuto temp_keyframe(mwindow->edl, autos);
1636                 temp_keyframe.copy_data(keyframe);
1637 // Update parameter
1638                 temp_keyframe.mode = text_to_mode(get_text());
1639 // Commit change to span of keyframes
1640                 autos->update_parameter(&temp_keyframe);
1641 #else
1642                 ((MaskAuto*)autos->default_auto)->mode =
1643                         text_to_mode(get_text());
1644 #endif
1645                 mwindow->undo->update_undo_after(_("mask mode"), LOAD_AUTOMATION);
1646         }
1647
1648 //printf("CWindowMaskMode::handle_event 1\n");
1649         gui->update_preview();
1650         return 1;
1651 }
1652
1653
1654
1655
1656
1657
1658
1659
1660 CWindowMaskDelete::CWindowMaskDelete(MWindow *mwindow,
1661         CWindowToolGUI *gui,
1662         int x,
1663         int y)
1664  : BC_GenericButton(x, y, _("Delete"))
1665 {
1666         this->mwindow = mwindow;
1667         this->gui = gui;
1668 }
1669
1670 int CWindowMaskDelete::handle_event()
1671 {
1672         MaskAutos *autos;
1673         MaskAuto *keyframe;
1674         Track *track;
1675         MaskPoint *point;
1676         SubMask *mask;
1677         int total_points = 0;
1678
1679 // Get existing keyframe
1680         ((CWindowMaskGUI*)gui)->get_keyframe(track, autos, keyframe, mask, point, 0);
1681
1682         if(track)
1683         {
1684                 mwindow->undo->update_undo_before(_("mask delete"), 0);
1685
1686 #ifdef USE_KEYFRAME_SPANNING
1687 // Create temp keyframe
1688                 MaskAuto temp_keyframe(mwindow->edl, autos);
1689                 temp_keyframe.copy_data(keyframe);
1690 // Update parameter
1691                 SubMask *submask = temp_keyframe.get_submask(mwindow->edl->session->cwindow_mask);
1692                 if( shift_down() )
1693                         submask->points.remove_all_objects();
1694
1695                 for(int i = mwindow->cwindow->gui->affected_point;
1696                         i < submask->points.total - 1;
1697                         i++)
1698                 {
1699                         *submask->points.values[i] = *submask->points.values[i + 1];
1700                 }
1701
1702                 if(submask->points.total)
1703                 {
1704                         submask->points.remove_object(
1705                                 submask->points.values[submask->points.total - 1]);
1706                 }
1707                 total_points = submask->points.total;
1708
1709 // Commit change to span of keyframes
1710                 ((MaskAutos*)track->automation->autos[AUTOMATION_MASK])->update_parameter(&temp_keyframe);
1711 #else
1712                 for(MaskAuto *current = (MaskAuto*)autos->default_auto;
1713                         current; )
1714                 {
1715                         SubMask *submask = current->get_submask(mwindow->edl->session->cwindow_mask);
1716                         if( shift_down() )
1717                                 submask->points.remove_all_objects();
1718
1719                         for(int i = mwindow->cwindow->gui->affected_point;
1720                                 i < submask->points.total - 1;
1721                                 i++)
1722                         {
1723                                 *submask->points.values[i] = *submask->points.values[i + 1];
1724                         }
1725
1726                         if(submask->points.total)
1727                         {
1728                                 submask->points.remove_object(
1729                                         submask->points.values[submask->points.total - 1]);
1730                         }
1731                         total_points = submask->points.total;
1732
1733                         if(current == (MaskAuto*)autos->default_auto)
1734                                 current = (MaskAuto*)autos->first;
1735                         else
1736                                 current = (MaskAuto*)NEXT;
1737                 }
1738 #endif
1739                 if( mwindow->cwindow->gui->affected_point >= total_points )
1740                         mwindow->cwindow->gui->affected_point =
1741                                 total_points > 0 ? total_points-1 : 0;
1742
1743                 gui->update();
1744                 gui->update_preview();
1745                 mwindow->undo->update_undo_after(_("mask delete"), LOAD_AUTOMATION);
1746         }
1747
1748
1749         return 1;
1750 }
1751
1752 int CWindowMaskDelete::keypress_event()
1753 {
1754         if(get_keypress() == BACKSPACE ||
1755                 get_keypress() == DELETE)
1756                 return handle_event();
1757         return 0;
1758 }
1759
1760
1761 // CWindowMaskCycleNext::CWindowMaskCycleNext(MWindow *mwindow, CWindowToolGUI *gui, int x, int y)
1762 //  : BC_GenericButton(x, y, _("Cycle next"))
1763 // {
1764 //      this->mwindow = mwindow;
1765 //      this->gui = gui;
1766 // }
1767 // int CWindowMaskCycleNext::handle_event()
1768 // {
1769 //      MaskAuto *keyframe;
1770 //      MaskAutos *autos;
1771 //      Track *track;
1772 //      MaskPoint *point;
1773 //      SubMask *mask;
1774 //      ((CWindowMaskGUI*)gui)->get_keyframe(track, autos, keyframe, mask, point, 0);
1775 //
1776 //      MaskPoint *temp;
1777 //
1778 // // Should apply to all keyframes
1779 //      if(keyframe && mask->points.total)
1780 //      {
1781 //              temp = mask->points.values[0];
1782 //
1783 //              for(int i = 0; i < mask->points.total - 1; i++)
1784 //              {
1785 //                      mask->points.values[i] = mask->points.values[i + 1];
1786 //              }
1787 //              mask->points.values[mask->points.total - 1] = temp;
1788 //
1789 //              mwindow->cwindow->gui->affected_point--;
1790 //              if(mwindow->cwindow->gui->affected_point < 0)
1791 //                      mwindow->cwindow->gui->affected_point = mask->points.total - 1;
1792 //
1793 //              gui->update();
1794 //              gui->update_preview();
1795 //      }
1796 //
1797 //      return 1;
1798 // }
1799 //
1800 // CWindowMaskCyclePrev::CWindowMaskCyclePrev(MWindow *mwindow, CWindowToolGUI *gui, int x, int y)
1801 //  : BC_GenericButton(x, y, _("Cycle prev"))
1802 // {
1803 //      this->mwindow = mwindow;
1804 //      this->gui = gui;
1805 // }
1806 // int CWindowMaskCyclePrev::handle_event()
1807 // {
1808 //      MaskAuto *keyframe;
1809 //      MaskAutos *autos;
1810 //      Track *track;
1811 //      MaskPoint *point;
1812 //      SubMask *mask;
1813 //      ((CWindowMaskGUI*)gui)->get_keyframe(track, autos, keyframe, mask, point, 0);
1814 //
1815 // // Should apply to all keyframes
1816 //      MaskPoint *temp;
1817 //      if(keyframe && mask->points.total)
1818 //      {
1819 //              temp = mask->points.values[mask->points.total - 1];
1820 //
1821 //              for(int i = mask->points.total - 1; i > 0; i--)
1822 //              {
1823 //                      mask->points.values[i] = mask->points.values[i - 1];
1824 //              }
1825 //              mask->points.values[0] = temp;
1826 //
1827 //              mwindow->cwindow->gui->affected_point++;
1828 //              if(mwindow->cwindow->gui->affected_point >= mask->points.total)
1829 //                      mwindow->cwindow->gui->affected_point = 0;
1830 //
1831 //              gui->update();
1832 //              gui->update_preview();
1833 //      }
1834 //      return 1;
1835 // }
1836
1837
1838 CWindowMaskNumber::CWindowMaskNumber(MWindow *mwindow,
1839         CWindowToolGUI *gui,
1840         int x,
1841         int y)
1842  : BC_TumbleTextBox(gui,
1843                 (int64_t)mwindow->edl->session->cwindow_mask,
1844                 (int64_t)0,
1845                 (int64_t)SUBMASKS - 1,
1846                 x,
1847                 y,
1848                 100)
1849 {
1850         this->mwindow = mwindow;
1851         this->gui = gui;
1852 }
1853
1854 CWindowMaskNumber::~CWindowMaskNumber()
1855 {
1856 }
1857
1858 int CWindowMaskNumber::handle_event()
1859 {
1860         mwindow->edl->session->cwindow_mask = atol(get_text());
1861         gui->update();
1862         gui->update_preview();
1863         return 1;
1864 }
1865
1866
1867 CWindowMaskAffectedPoint::CWindowMaskAffectedPoint(MWindow *mwindow,
1868         CWindowToolGUI *gui, int x, int y)
1869  : BC_TumbleTextBox(gui,
1870                 (int64_t)mwindow->cwindow->gui->affected_point,
1871                 (int64_t)0, INT64_MAX, x, y, 100)
1872 {
1873         this->mwindow = mwindow;
1874         this->gui = gui;
1875 }
1876
1877 CWindowMaskAffectedPoint::~CWindowMaskAffectedPoint()
1878 {
1879 }
1880
1881 int CWindowMaskAffectedPoint::handle_event()
1882 {
1883         int total_points = 0;
1884         int affected_point = atol(get_text());
1885         Track *track = mwindow->cwindow->calculate_affected_track();
1886         if(track) {
1887                 MaskAutos *autos = (MaskAutos*)track->automation->autos[AUTOMATION_MASK];
1888                 MaskAuto *keyframe = (MaskAuto*)mwindow->cwindow->calculate_affected_auto(autos, 0);
1889                 if( keyframe ) {
1890                         SubMask *mask = keyframe->get_submask(mwindow->edl->session->cwindow_mask);
1891                         total_points = mask->points.size();
1892                 }
1893         }
1894         int active_point = affected_point;
1895         if( affected_point >= total_points )
1896                 affected_point = total_points - 1;
1897         else if( affected_point < 0 )
1898                 affected_point = 0;
1899         if( active_point != affected_point )
1900                 update((int64_t)affected_point);
1901         mwindow->cwindow->gui->affected_point = affected_point;
1902         gui->update();
1903         gui->update_preview();
1904         return 1;
1905 }
1906
1907
1908
1909
1910
1911 CWindowMaskFeather::CWindowMaskFeather(MWindow *mwindow, CWindowToolGUI *gui, int x, int y)
1912  : BC_TumbleTextBox(gui,
1913                 (int64_t)0,
1914                 (int64_t)0,
1915                 (int64_t)0xff,
1916                 x,
1917                 y,
1918                 100)
1919 {
1920         this->mwindow = mwindow;
1921         this->gui = gui;
1922 }
1923 CWindowMaskFeather::~CWindowMaskFeather()
1924 {
1925 }
1926 int CWindowMaskFeather::handle_event()
1927 {
1928         MaskAutos *autos;
1929         MaskAuto *keyframe;
1930         Track *track;
1931         MaskPoint *point;
1932         SubMask *mask;
1933 #ifdef USE_KEYFRAME_SPANNING
1934         int create_it = 0;
1935 #else
1936         int create_it = 1;
1937 #endif
1938
1939         mwindow->undo->update_undo_before(_("mask feather"), this);
1940
1941 // Get existing keyframe
1942         ((CWindowMaskGUI*)gui)->get_keyframe(track, autos, keyframe,
1943                         mask, point, create_it);
1944
1945         if(track)
1946         {
1947 #ifdef USE_KEYFRAME_SPANNING
1948 // Create temp keyframe
1949                 MaskAuto temp_keyframe(mwindow->edl, autos);
1950                 temp_keyframe.copy_data(keyframe);
1951 // Update parameter
1952                 temp_keyframe.feather = atof(get_text());
1953 // Commit change to span of keyframes
1954                 autos->update_parameter(&temp_keyframe);
1955 #else
1956                 keyframe->feather = atof(get_text());
1957 #endif
1958
1959                 gui->update_preview();
1960         }
1961
1962         mwindow->undo->update_undo_after(_("mask feather"), LOAD_AUTOMATION);
1963         return 1;
1964 }
1965
1966
1967 CWindowMaskValue::CWindowMaskValue(MWindow *mwindow, CWindowToolGUI *gui, int x, int y)
1968  : BC_ISlider(x,
1969                         y,
1970                         0,
1971                         200,
1972                         200,
1973                         0,
1974                         100,
1975                         0)
1976 {
1977         this->mwindow = mwindow;
1978         this->gui = gui;
1979 }
1980
1981 CWindowMaskValue::~CWindowMaskValue()
1982 {
1983 }
1984
1985 int CWindowMaskValue::handle_event()
1986 {
1987         MaskAutos *autos;
1988         MaskAuto *keyframe;
1989         Track *track;
1990         MaskPoint *point;
1991         SubMask *mask;
1992 #ifdef USE_KEYFRAME_SPANNING
1993         int create_it = 0;
1994 #else
1995         int create_it = 1;
1996 #endif
1997
1998         mwindow->undo->update_undo_before(_("mask value"), this);
1999         ((CWindowMaskGUI*)gui)->get_keyframe(track, autos, keyframe,
2000                 mask, point, create_it);
2001
2002         if(track)
2003         {
2004 #ifdef USE_KEYFRAME_SPANNING
2005 // Create temp keyframe
2006                 MaskAuto temp_keyframe(mwindow->edl, autos);
2007                 temp_keyframe.copy_data(keyframe);
2008 // Update parameter
2009                 temp_keyframe.value = get_value();
2010 // Commit change to span of keyframes
2011                 autos->update_parameter(&temp_keyframe);
2012 #else
2013                 keyframe->value = get_value();
2014 #endif
2015         }
2016
2017         gui->update_preview();
2018         mwindow->undo->update_undo_after(_("mask value"), LOAD_AUTOMATION);
2019         return 1;
2020 }
2021
2022
2023 CWindowMaskBeforePlugins::CWindowMaskBeforePlugins(CWindowToolGUI *gui, int x, int y)
2024  : BC_CheckBox(x,
2025         y,
2026         1,
2027         _("Apply mask before plugins"))
2028 {
2029         this->gui = gui;
2030 }
2031
2032 int CWindowMaskBeforePlugins::handle_event()
2033 {
2034         Track *track;
2035         MaskAutos *autos;
2036         MaskAuto *keyframe;
2037         SubMask *mask;
2038         MaskPoint *point;
2039         ((CWindowMaskGUI*)gui)->get_keyframe(track, autos, keyframe, mask, point, 1);
2040
2041         if (keyframe) {
2042                 keyframe->apply_before_plugins = get_value();
2043                 gui->update_preview();
2044         }
2045         return 1;
2046 }
2047
2048
2049 CWindowDisableOpenGLMasking::CWindowDisableOpenGLMasking(CWindowToolGUI *gui, int x, int y)
2050  : BC_CheckBox(x, y, 1, _("Disable OpenGL masking"))
2051 {
2052         this->gui = gui;
2053 }
2054
2055 int CWindowDisableOpenGLMasking::handle_event()
2056 {
2057         Track *track;
2058         MaskAutos *autos;
2059         MaskAuto *keyframe;
2060         SubMask *mask;
2061         MaskPoint *point;
2062         ((CWindowMaskGUI*)gui)->get_keyframe(track, autos, keyframe, mask, point, 1);
2063
2064         if (keyframe) {
2065                 keyframe->disable_opengl_masking = get_value();
2066                 gui->update_preview();
2067         }
2068         return 1;
2069 }
2070
2071
2072
2073
2074
2075
2076
2077
2078
2079 CWindowMaskGUI::CWindowMaskGUI(MWindow *mwindow, CWindowTool *thread)
2080  : CWindowToolGUI(mwindow, thread,
2081         _(PROGRAM_NAME ": Mask"), 330, 320)
2082 {
2083         this->mwindow = mwindow;
2084         this->thread = thread;
2085         number = 0;
2086         active_point = 0;
2087         feather = 0;
2088 }
2089 CWindowMaskGUI::~CWindowMaskGUI()
2090 {
2091         lock_window("CWindowMaskGUI::~CWindowMaskGUI");
2092         delete number;
2093         delete active_point;
2094         delete feather;
2095         unlock_window();
2096 }
2097
2098 void CWindowMaskGUI::create_objects()
2099 {
2100         int x = 10, y = 10, margin = mwindow->theme->widget_border;
2101         //MaskAuto *keyframe = 0;
2102         //Track *track = mwindow->cwindow->calculate_affected_track();
2103         //if(track)
2104         //      keyframe = (MaskAuto*)mwindow->cwindow->calculate_affected_auto(track->automation->autos[AUTOMATION_MASK], 0);
2105
2106         lock_window("CWindowMaskGUI::create_objects");
2107         BC_Title *title;
2108         add_subwindow(title = new BC_Title(x, y, _("Mode:")));
2109         add_subwindow(mode = new CWindowMaskMode(mwindow,
2110                 this, x + title->get_w() + margin, y, ""));
2111         mode->create_objects();
2112         y += mode->get_h() + margin;
2113         add_subwindow(title = new BC_Title(x, y, _("Value:")));
2114         add_subwindow(value = new CWindowMaskValue(mwindow, this, x + title->get_w() + margin, y));
2115         y += value->get_h() + margin;
2116         add_subwindow(delete_point = new CWindowMaskDelete(mwindow, this, x, y));
2117         int x1 = x + delete_point->get_w() + 2*margin;
2118         add_subwindow(title = new BC_Title(x1, y, _("Point:")));
2119         x1 += title->get_w() + margin;
2120         active_point = new CWindowMaskAffectedPoint(mwindow, this, x1, y);
2121         active_point->create_objects();
2122         y += delete_point->get_h() + margin;
2123         add_subwindow(title = new BC_Title(x, y, _("Mask number:")));
2124         number = new CWindowMaskNumber(mwindow,
2125                 this, x + title->get_w() + margin, y);
2126         number->create_objects();
2127         y += number->get_h() + margin;
2128         add_subwindow(title = new BC_Title(x, y, _("Feather:")));
2129         feather = new CWindowMaskFeather(mwindow,
2130                 this, x + title->get_w() + margin, y);
2131         feather->create_objects();
2132         y += feather->get_h() + margin;
2133         add_subwindow(title = new BC_Title(x, y, "X:"));
2134         x += title->get_w() + margin;
2135         this->x = new CWindowCoord(this, x, y, (float)0.0);
2136         this->x->create_objects();
2137         x += this->x->get_w() + margin;
2138         add_subwindow(title = new BC_Title(x, y, "Y:"));
2139         x += title->get_w() + margin;
2140         this->y = new CWindowCoord(this, x, y, (float)0.0);
2141         this->y->create_objects();
2142
2143         x = 10;
2144         y += this->y->get_h() + margin;
2145         add_subwindow(title = new BC_Title(x, y, _("Press Shift to move an end point")));
2146         y += title->get_h() + margin;
2147         add_subwindow(title = new BC_Title(x, y, _("Press Ctrl to move a control point")));
2148         y += title->get_h() + margin;
2149         add_subwindow(title = new BC_Title(x, y, _("Shift+click Delete to delete the mask")));
2150         y += title->get_h() + margin;
2151         add_subwindow(title = new BC_Title(x, y, _("Press Alt to translate the mask")));
2152         y += 30;
2153
2154         add_subwindow(this->apply_before_plugins = new CWindowMaskBeforePlugins(this, 10, y));
2155         y += this->apply_before_plugins->get_h() + margin;
2156         add_subwindow(this->disable_opengl_masking = new CWindowDisableOpenGLMasking(this, 10, y));
2157
2158         update();
2159         unlock_window();
2160 }
2161
2162 void CWindowMaskGUI::get_keyframe(Track* &track,
2163         MaskAutos* &autos,
2164         MaskAuto* &keyframe,
2165         SubMask* &mask,
2166         MaskPoint* &point,
2167         int create_it)
2168 {
2169         autos = 0;
2170         keyframe = 0;
2171
2172         track = mwindow->cwindow->calculate_affected_track();
2173         if(track)
2174         {
2175                 autos = (MaskAutos*)track->automation->autos[AUTOMATION_MASK];
2176                 keyframe = (MaskAuto*)mwindow->cwindow->calculate_affected_auto(
2177                         autos,
2178                         create_it);
2179         }
2180
2181         if(keyframe)
2182                 mask = keyframe->get_submask(mwindow->edl->session->cwindow_mask);
2183         else
2184                 mask = 0;
2185
2186         point = 0;
2187         if(keyframe)
2188         {
2189                 if(mwindow->cwindow->gui->affected_point < mask->points.total &&
2190                         mwindow->cwindow->gui->affected_point >= 0)
2191                 {
2192                         point = mask->points.values[mwindow->cwindow->gui->affected_point];
2193                 }
2194         }
2195 }
2196
2197 void CWindowMaskGUI::update()
2198 {
2199         Track *track;
2200         MaskAutos *autos;
2201         MaskAuto *keyframe;
2202         SubMask *mask;
2203         MaskPoint *point;
2204 //printf("CWindowMaskGUI::update 1\n");
2205         get_keyframe(track, autos, keyframe, mask, point, 0);
2206
2207         double position = mwindow->edl->local_session->get_selectionstart(1);
2208         position = mwindow->edl->align_to_frame(position, 0);
2209         if(track)
2210         {
2211                 int64_t position_i = track->to_units(position, 0);
2212
2213                 if(point)
2214                 {
2215                         x->update(point->x);
2216                         y->update(point->y);
2217                 }
2218
2219                 if(mask)
2220                 {
2221                         feather->update((int64_t)autos->get_feather(position_i, PLAY_FORWARD));
2222                         value->update((int64_t)autos->get_value(position_i, PLAY_FORWARD));
2223                         apply_before_plugins->update((int64_t)keyframe->apply_before_plugins);
2224                         disable_opengl_masking->update((int64_t)keyframe->disable_opengl_masking);
2225                 }
2226         }
2227
2228 //printf("CWindowMaskGUI::update 1\n");
2229         active_point->update((int64_t)mwindow->cwindow->gui->affected_point);
2230         number->update((int64_t)mwindow->edl->session->cwindow_mask);
2231
2232 //printf("CWindowMaskGUI::update 1\n");
2233         if(track)
2234         {
2235 #ifdef USE_KEYFRAME_SPANNING
2236                 mode->set_text(
2237                         CWindowMaskMode::mode_to_text(keyframe->mode));
2238 #else
2239                 mode->set_text(
2240                         CWindowMaskMode::mode_to_text(((MaskAuto*)autos->default_auto)->mode));
2241 #endif
2242         }
2243 //printf("CWindowMaskGUI::update 2\n");
2244 }
2245
2246 void CWindowMaskGUI::handle_event()
2247 {
2248         Track *track;
2249         MaskAuto *keyframe;
2250         MaskAutos *autos;
2251         SubMask *mask;
2252         MaskPoint *point;
2253         get_keyframe(track, autos, keyframe, mask, point, 0);
2254
2255         mwindow->undo->update_undo_before(_("mask point"), this);
2256
2257         if(point)
2258         {
2259 #ifdef USE_KEYFRAME_SPANNING
2260 // Create temp keyframe
2261                 MaskAuto temp_keyframe(mwindow->edl, autos);
2262                 temp_keyframe.copy_data(keyframe);
2263 // Get affected point in temp keyframe
2264                 mask = temp_keyframe.get_submask(mwindow->edl->session->cwindow_mask);
2265                 if(mwindow->cwindow->gui->affected_point < mask->points.total &&
2266                         mwindow->cwindow->gui->affected_point >= 0)
2267                 {
2268                         point = mask->points.values[mwindow->cwindow->gui->affected_point];
2269                 }
2270
2271                 if(point)
2272                 {
2273                         point->x = atof(x->get_text());
2274                         point->y = atof(y->get_text());
2275 // Commit to spanned keyframes
2276                         autos->update_parameter(&temp_keyframe);
2277                 }
2278 #else
2279                 point->x = atof(x->get_text());
2280                 point->y = atof(y->get_text());
2281 #endif
2282         }
2283
2284         update_preview();
2285         mwindow->undo->update_undo_after(_("mask point"), LOAD_AUTOMATION);
2286 }
2287
2288 void CWindowMaskGUI::update_preview()
2289 {
2290         mwindow->gui->lock_window("CWindowMaskGUI::update_preview");
2291         mwindow->restart_brender();
2292         mwindow->sync_parameters(CHANGE_PARAMS);
2293         mwindow->gui->draw_overlays(1);
2294         mwindow->gui->unlock_window();
2295         mwindow->cwindow->refresh_frame(CHANGE_NONE);
2296         mwindow->cwindow->gui->lock_window("CWindowMaskGUI::update_preview");
2297         mwindow->cwindow->gui->canvas->draw_refresh();
2298         mwindow->cwindow->gui->unlock_window();
2299 }
2300
2301
2302 CWindowRulerGUI::CWindowRulerGUI(MWindow *mwindow, CWindowTool *thread)
2303  : CWindowToolGUI(mwindow,
2304         thread,
2305         _(PROGRAM_NAME ": Ruler"),
2306         320,
2307         240)
2308 {
2309 }
2310
2311 CWindowRulerGUI::~CWindowRulerGUI()
2312 {
2313 }
2314
2315 void CWindowRulerGUI::create_objects()
2316 {
2317         int x = 10, y = 10, x1 = 100;
2318         BC_Title *title;
2319
2320         lock_window("CWindowRulerGUI::create_objects");
2321         add_subwindow(title = new BC_Title(x, y, _("Current:")));
2322         add_subwindow(current = new BC_TextBox(x1, y, 200, 1, ""));
2323         y += title->get_h() + 5;
2324         add_subwindow(title = new BC_Title(x, y, _("Point 1:")));
2325         add_subwindow(point1 = new BC_TextBox(x1, y, 200, 1, ""));
2326         y += title->get_h() + 5;
2327         add_subwindow(title = new BC_Title(x, y, _("Point 2:")));
2328         add_subwindow(point2 = new BC_TextBox(x1, y, 200, 1, ""));
2329         y += title->get_h() + 5;
2330         add_subwindow(title = new BC_Title(x, y, _("Deltas:")));
2331         add_subwindow(deltas = new BC_TextBox(x1, y, 200, 1, ""));
2332         y += title->get_h() + 5;
2333         add_subwindow(title = new BC_Title(x, y, _("Distance:")));
2334         add_subwindow(distance = new BC_TextBox(x1, y, 200, 1, ""));
2335         y += title->get_h() + 5;
2336         add_subwindow(title = new BC_Title(x, y, _("Angle:")));
2337         add_subwindow(angle = new BC_TextBox(x1, y, 200, 1, ""));
2338         y += title->get_h() + 10;
2339         char string[BCTEXTLEN];
2340         sprintf(string,
2341                  _("Press Ctrl to lock ruler to the\nnearest 45%c%c angle."),
2342                 0xc2, 0xb0); // degrees utf
2343         add_subwindow(title = new BC_Title(x,
2344                 y,
2345                 string));
2346         y += title->get_h() + 10;
2347         sprintf(string, _("Press Alt to translate the ruler."));
2348         add_subwindow(title = new BC_Title(x,
2349                 y,
2350                 string));
2351         update();
2352         unlock_window();
2353 }
2354
2355 void CWindowRulerGUI::update()
2356 {
2357         char string[BCTEXTLEN];
2358         int cx = mwindow->session->cwindow_output_x;
2359         int cy = mwindow->session->cwindow_output_y;
2360         sprintf(string, "%d, %d", cx, cy);
2361         current->update(string);
2362         double x1 = mwindow->edl->session->ruler_x1;
2363         double y1 = mwindow->edl->session->ruler_y1;
2364         sprintf(string, "%.0f, %.0f", x1, y1);
2365         point1->update(string);
2366         double x2 = mwindow->edl->session->ruler_x2;
2367         double y2 = mwindow->edl->session->ruler_y2;
2368         sprintf(string, "%.0f, %.0f", x2, y2);
2369         point2->update(string);
2370         double dx = x2 - x1, dy = y2 - y1;
2371         sprintf(string, "%s%.0f, %s%.0f", (dx>=0? "+":""), dx, (dy>=0? "+":""), dy);
2372         deltas->update(string);
2373         double d = sqrt(dx*dx + dy*dy);
2374         sprintf(string, _("%0.01f pixels"), d);
2375         distance->update(string);
2376         double a = d > 0 ? (atan2(-dy, dx) * 180/M_PI) : 0.;
2377         sprintf(string, "%0.02f %c%c", a, 0xc2, 0xb0);
2378         angle->update(string);
2379 }
2380
2381 void CWindowRulerGUI::handle_event()
2382 {
2383 }
2384
2385
2386
2387