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