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