3 * Copyright (C) 2008-2017 Adam Williams <broadcast at earthling dot net>
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.
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.
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
24 #include "automation.h"
28 #include "condition.h"
30 #include "cplayback.h"
32 #include "cwindowgui.h"
33 #include "cwindowtool.h"
35 #include "edlsession.h"
36 #include "floatauto.h"
37 #include "floatautos.h"
40 #include "localsession.h"
41 #include "mainsession.h"
44 #include "maskautos.h"
47 #include "mwindowgui.h"
51 #include "trackcanvas.h"
52 #include "transportque.h"
55 CWindowTool::CWindowTool(MWindow *mwindow, CWindowGUI *gui)
58 this->mwindow = mwindow;
62 current_tool = CWINDOW_NONE;
64 input_lock = new Condition(0, "CWindowTool::input_lock");
65 output_lock = new Condition(1, "CWindowTool::output_lock");
66 tool_gui_lock = new Mutex("CWindowTool::tool_gui_lock");
69 CWindowTool::~CWindowTool()
80 void CWindowTool::start_tool(int operation)
82 CWindowToolGUI *new_gui = 0;
85 //printf("CWindowTool::start_tool 1\n");
86 if(current_tool != operation)
88 int previous_tool = current_tool;
89 current_tool = operation;
93 new_gui = new CWindowEyedropGUI(mwindow, this);
96 new_gui = new CWindowCropGUI(mwindow, this);
99 new_gui = new CWindowCameraGUI(mwindow, this);
101 case CWINDOW_PROJECTOR:
102 new_gui = new CWindowProjectorGUI(mwindow, this);
105 new_gui = new CWindowMaskGUI(mwindow, this);
108 new_gui = new CWindowRulerGUI(mwindow, this);
110 case CWINDOW_PROTECT:
111 mwindow->edl->session->tool_window = 0;
112 gui->composite_panel->operation[CWINDOW_TOOL_WINDOW]->update(0);
120 //printf("CWindowTool::start_tool 1\n");
126 // Wait for previous tool GUI to finish
127 output_lock->lock("CWindowTool::start_tool");
128 this->tool_gui = new_gui;
129 tool_gui->create_objects();
130 if( previous_tool == CWINDOW_PROTECT || previous_tool == CWINDOW_NONE ) {
131 mwindow->edl->session->tool_window = 1;
132 gui->composite_panel->operation[CWINDOW_TOOL_WINDOW]->update(1);
134 update_show_window();
136 // Signal thread to run next tool GUI
137 input_lock->unlock();
139 //printf("CWindowTool::start_tool 1\n");
144 tool_gui->lock_window("CWindowTool::start_tool");
146 tool_gui->unlock_window();
149 //printf("CWindowTool::start_tool 2\n");
154 void CWindowTool::stop_tool()
158 tool_gui->lock_window("CWindowTool::stop_tool");
159 tool_gui->set_done(0);
160 tool_gui->unlock_window();
164 void CWindowTool::show_tool()
166 if(tool_gui && mwindow->edl->session->tool_window)
168 tool_gui->lock_window("CWindowTool::show_tool");
169 tool_gui->show_window();
170 tool_gui->unlock_window();
174 void CWindowTool::hide_tool()
176 if(tool_gui && mwindow->edl->session->tool_window)
178 tool_gui->lock_window("CWindowTool::show_tool");
179 tool_gui->hide_window();
180 tool_gui->unlock_window();
184 void CWindowTool::raise_tool()
186 if(tool_gui && mwindow->edl->session->tool_window)
188 tool_gui->lock_window("CWindowTool::show_tool");
189 tool_gui->raise_window();
190 tool_gui->unlock_window();
195 void CWindowTool::run()
199 input_lock->lock("CWindowTool::run");
202 tool_gui->run_window();
203 tool_gui_lock->lock("CWindowTool::run");
206 tool_gui_lock->unlock();
208 output_lock->unlock();
212 void CWindowTool::update_show_window()
216 tool_gui->lock_window("CWindowTool::update_show_window");
218 if(mwindow->edl->session->tool_window)
221 tool_gui->show_window();
224 tool_gui->hide_window();
227 tool_gui->unlock_window();
231 void CWindowTool::raise_window()
235 gui->unlock_window();
236 tool_gui->lock_window("CWindowTool::raise_window");
237 tool_gui->raise_window();
238 tool_gui->unlock_window();
239 gui->lock_window("CWindowTool::raise_window");
243 void CWindowTool::update_values()
245 tool_gui_lock->lock("CWindowTool::update_values");
248 tool_gui->lock_window("CWindowTool::update_values");
251 tool_gui->unlock_window();
253 tool_gui_lock->unlock();
262 CWindowToolGUI::CWindowToolGUI(MWindow *mwindow,
268 mwindow->session->ctool_x,
269 mwindow->session->ctool_y,
278 this->mwindow = mwindow;
279 this->thread = thread;
280 current_operation = 0;
283 CWindowToolGUI::~CWindowToolGUI()
287 int CWindowToolGUI::close_event()
291 mwindow->edl->session->tool_window = 0;
293 thread->gui->lock_window("CWindowToolGUI::close_event");
294 thread->gui->composite_panel->set_operation(mwindow->edl->session->cwindow_operation);
295 thread->gui->flush();
296 thread->gui->unlock_window();
297 lock_window("CWindowToolGUI::close_event");
301 int CWindowToolGUI::keypress_event()
305 switch( get_keypress() ) {
308 return close_event();
321 resend_event(thread->gui);
328 int CWindowToolGUI::translation_event()
330 mwindow->session->ctool_x = get_x();
331 mwindow->session->ctool_y = get_y();
336 void CWindowToolGUI::update_preview(int changed_edl)
339 draw_preview(changed_edl);
340 lock_window("CWindowToolGUI::update_preview");
343 void CWindowToolGUI::draw_preview(int changed_edl)
345 CWindowGUI *cgui = mwindow->cwindow->gui;
346 cgui->lock_window("CWindowToolGUI::draw_preview");
347 int change_type = !changed_edl ? CHANGE_PARAMS : CHANGE_EDL;
348 cgui->sync_parameters(change_type, 0, 1);
349 cgui->unlock_window();
353 CWindowCoord::CWindowCoord(CWindowToolGUI *gui, int x, int y, float value, int log_increment = 0)
354 : BC_TumbleTextBox(gui, (float)value, (float)-65536, (float)65536, x, y, 100, 3)
357 set_log_floatincrement(log_increment);
360 CWindowCoord::CWindowCoord(CWindowToolGUI *gui, int x, int y, int value)
361 : BC_TumbleTextBox(gui, (int64_t)value, (int64_t)-65536, (int64_t)65536, x, y, 100, 3)
365 int CWindowCoord::handle_event()
367 gui->event_caller = this;
373 CWindowCropOK::CWindowCropOK(MWindow *mwindow, CWindowToolGUI *gui, int x, int y)
374 : BC_GenericButton(x, y, _("Do it"))
376 this->mwindow = mwindow;
379 int CWindowCropOK::handle_event()
381 mwindow->crop_video();
386 int CWindowCropOK::keypress_event()
388 if(get_keypress() == 0xd)
402 CWindowCropGUI::CWindowCropGUI(MWindow *mwindow, CWindowTool *thread)
403 : CWindowToolGUI(mwindow,
405 _(PROGRAM_NAME ": Crop"),
412 CWindowCropGUI::~CWindowCropGUI()
416 void CWindowCropGUI::create_objects()
421 lock_window("CWindowCropGUI::create_objects");
423 int pad = MAX(BC_TextBox::calculate_h(this, MEDIUMFONT, 1, 1),
424 BC_Title::calculate_h(this, "X")) + 5;
425 add_subwindow(title = new BC_Title(x, y, "X1:"));
426 column1 = MAX(column1, title->get_w());
428 add_subwindow(title = new BC_Title(x, y, _("W:")));
429 column1 = MAX(column1, title->get_w());
431 add_subwindow(new CWindowCropOK(mwindow, thread->tool_gui, x, y));
435 x1 = new CWindowCoord(thread->tool_gui, x, y,
436 mwindow->edl->session->crop_x1);
437 x1->create_objects();
439 width = new CWindowCoord(thread->tool_gui, x, y,
440 mwindow->edl->session->crop_x2 - mwindow->edl->session->crop_x1);
441 width->create_objects();
444 x += x1->get_w() + 10;
447 add_subwindow(title = new BC_Title(x, y, "Y1:"));
448 column2 = MAX(column2, title->get_w());
450 add_subwindow(title = new BC_Title(x, y, _("H:")));
451 column2 = MAX(column2, title->get_w());
456 y1 = new CWindowCoord(thread->tool_gui, x, y,
457 mwindow->edl->session->crop_y1);
458 y1->create_objects();
460 height = new CWindowCoord(thread->tool_gui, x, y,
461 mwindow->edl->session->crop_y2 - mwindow->edl->session->crop_y1);
462 height->create_objects();
466 void CWindowCropGUI::handle_event()
469 new_x1 = atol(x1->get_text());
470 new_y1 = atol(y1->get_text());
471 if(new_x1 != mwindow->edl->session->crop_x1)
473 mwindow->edl->session->crop_x2 = new_x1 +
474 mwindow->edl->session->crop_x2 -
475 mwindow->edl->session->crop_x1;
476 mwindow->edl->session->crop_x1 = new_x1;
478 if(new_y1 != mwindow->edl->session->crop_y1)
480 mwindow->edl->session->crop_y2 = new_y1 +
481 mwindow->edl->session->crop_y2 -
482 mwindow->edl->session->crop_y1;
483 mwindow->edl->session->crop_y1 = atol(y1->get_text());
485 mwindow->edl->session->crop_x2 = atol(width->get_text()) +
486 mwindow->edl->session->crop_x1;
487 mwindow->edl->session->crop_y2 = atol(height->get_text()) +
488 mwindow->edl->session->crop_y1;
490 mwindow->cwindow->gui->canvas->redraw(1);
493 void CWindowCropGUI::update()
495 x1->update((int64_t)mwindow->edl->session->crop_x1);
496 y1->update((int64_t)mwindow->edl->session->crop_y1);
497 width->update((int64_t)mwindow->edl->session->crop_x2 -
498 mwindow->edl->session->crop_x1);
499 height->update((int64_t)mwindow->edl->session->crop_y2 -
500 mwindow->edl->session->crop_y1);
504 CWindowEyedropGUI::CWindowEyedropGUI(MWindow *mwindow, CWindowTool *thread)
505 : CWindowToolGUI(mwindow, thread, _(PROGRAM_NAME ": Color"), 220, 290)
509 CWindowEyedropGUI::~CWindowEyedropGUI()
513 void CWindowEyedropGUI::create_objects()
515 int margin = mwindow->theme->widget_border;
518 int x2 = 70, x3 = x2 + 60;
519 lock_window("CWindowEyedropGUI::create_objects");
520 BC_Title *title0, *title1, *title2, *title3, *title4, *title5, *title6, *title7;
521 add_subwindow(title0 = new BC_Title(x, y,_("X,Y:")));
522 y += title0->get_h() + margin;
523 add_subwindow(title7 = new BC_Title(x, y, _("Radius:")));
524 y += BC_TextBox::calculate_h(this, MEDIUMFONT, 1, 1) + margin;
526 add_subwindow(title1 = new BC_Title(x, y, _("Red:")));
527 y += title1->get_h() + margin;
528 add_subwindow(title2 = new BC_Title(x, y, _("Green:")));
529 y += title2->get_h() + margin;
530 add_subwindow(title3 = new BC_Title(x, y, _("Blue:")));
531 y += title3->get_h() + margin;
533 add_subwindow(title4 = new BC_Title(x, y, "Y:"));
534 y += title4->get_h() + margin;
535 add_subwindow(title5 = new BC_Title(x, y, "U:"));
536 y += title5->get_h() + margin;
537 add_subwindow(title6 = new BC_Title(x, y, "V:"));
539 add_subwindow(current = new BC_Title(x2, title0->get_y(), ""));
541 radius = new CWindowCoord(this, x2, title7->get_y(),
542 mwindow->edl->session->eyedrop_radius);
543 radius->create_objects();
544 radius->set_boundaries((int64_t)0, (int64_t)255);
546 add_subwindow(red = new BC_Title(x2, title1->get_y(), "0"));
547 add_subwindow(green = new BC_Title(x2, title2->get_y(), "0"));
548 add_subwindow(blue = new BC_Title(x2, title3->get_y(), "0"));
549 add_subwindow(rgb_hex = new BC_Title(x3, red->get_y(), "#000000"));
551 add_subwindow(this->y = new BC_Title(x2, title4->get_y(), "0"));
552 add_subwindow(this->u = new BC_Title(x2, title5->get_y(), "0"));
553 add_subwindow(this->v = new BC_Title(x2, title6->get_y(), "0"));
554 add_subwindow(yuv_hex = new BC_Title(x3, this->y->get_y(), "#000000"));
556 y = title6->get_y() + this->v->get_h() + 2*margin;
557 add_subwindow(sample = new BC_SubWindow(x, y, 50, 50));
558 y += sample->get_h() + margin;
559 add_subwindow(use_max = new CWindowEyedropCheckBox(mwindow, this, x, y));
564 void CWindowEyedropGUI::update()
566 char string[BCTEXTLEN];
567 sprintf(string, "%d, %d",
568 thread->gui->eyedrop_x,
569 thread->gui->eyedrop_y);
570 current->update(string);
572 radius->update((int64_t)mwindow->edl->session->eyedrop_radius);
574 LocalSession *local_session = mwindow->edl->local_session;
575 int use_max = local_session->use_max;
576 float r = use_max ? local_session->red_max : local_session->red;
577 float g = use_max ? local_session->green_max : local_session->green;
578 float b = use_max ? local_session->blue_max : local_session->blue;
579 this->red->update(r);
580 this->green->update(g);
581 this->blue->update(b);
583 int rx = 255*r + 0.5; bclamp(rx,0,255);
584 int gx = 255*g + 0.5; bclamp(gx,0,255);
585 int bx = 255*b + 0.5; bclamp(bx,0,255);
586 char rgb_text[BCSTRLEN];
587 sprintf(rgb_text, "#%02x%02x%02x", rx, gx, bx);
588 rgb_hex->update(rgb_text);
591 YUV::yuv.rgb_to_yuv_f(r, g, b, y, u, v);
593 this->u->update(u); u += 0.5;
594 this->v->update(v); v += 0.5;
596 int yx = 255*y + 0.5; bclamp(yx,0,255);
597 int ux = 255*u + 0.5; bclamp(ux,0,255);
598 int vx = 255*v + 0.5; bclamp(vx,0,255);
599 char yuv_text[BCSTRLEN];
600 sprintf(yuv_text, "#%02x%02x%02x", yx, ux, vx);
601 yuv_hex->update(yuv_text);
603 int rgb = (rx << 16) | (gx << 8) | (bx << 0);
604 sample->set_color(rgb);
605 sample->draw_box(0, 0, sample->get_w(), sample->get_h());
606 sample->set_color(BLACK);
607 sample->draw_rectangle(0, 0, sample->get_w(), sample->get_h());
611 void CWindowEyedropGUI::handle_event()
613 int new_radius = atoi(radius->get_text());
614 if(new_radius != mwindow->edl->session->eyedrop_radius)
616 CWindowGUI *gui = mwindow->cwindow->gui;
617 if(gui->eyedrop_visible)
619 gui->lock_window("CWindowEyedropGUI::handle_event");
622 gui->canvas->do_eyedrop(rerender, 0, 1);
625 mwindow->edl->session->eyedrop_radius = new_radius;
627 if(gui->eyedrop_visible)
631 gui->canvas->do_eyedrop(rerender, 0, 1);
632 gui->unlock_window();
639 /* Buttons to control Keyframe-Curve-Mode for Projector or Camera */
641 // Configuration for all possible Keyframe Curve Mode toggles
643 FloatAuto::t_mode mode;
649 const _CVD Camera_Crv_Smooth =
653 N_("\"smooth\" Curve on current Camera Keyframes")
655 const _CVD Camera_Crv_Linear =
659 N_("\"linear\" Curve on current Camera Keyframes")
661 const _CVD Projector_Crv_Smooth =
665 N_("\"smooth\" Curve on current Projector Keyframes")
667 const _CVD Projector_Crv_Linear =
671 N_("\"linear\" Curve on current Projector Keyframes")
674 // Implementation Class für Keyframe Curve Mode buttons
676 // This button reflects the state of the "current" keyframe
677 // (the nearest keyframe on the left) for all three automation
678 // lines together. Clicking on this button (re)sets the curve
679 // mode for the three "current" keyframes simultanously, but
680 // never creates a new keyframe.
682 class CWindowCurveToggle : public BC_Toggle
685 CWindowCurveToggle(_CVD mode, MWindow *mwindow, CWindowToolGUI *gui, int x, int y);
686 void check_toggle_state(FloatAuto *x, FloatAuto *y, FloatAuto *z);
695 CWindowCurveToggle::CWindowCurveToggle(_CVD mode, MWindow *mwindow, CWindowToolGUI *gui, int x, int y)
696 : BC_Toggle(x, y, mwindow->theme->get_image_set(mode.icon_id), false),
700 this->mwindow = mwindow;
701 set_tooltip(_(cfg.tooltip));
704 void CWindowCurveToggle::check_toggle_state(FloatAuto *x, FloatAuto *y, FloatAuto *z)
706 // the toggle state is only set to ON if all
707 // three automation lines have the same curve mode.
708 // For mixed states the toggle stays off.
709 set_value( x->curve_mode == this->cfg.mode &&
710 y->curve_mode == this->cfg.mode &&
711 z->curve_mode == this->cfg.mode
712 ,true // redraw to show new state
716 int CWindowCurveToggle::handle_event()
718 Track *track = mwindow->cwindow->calculate_affected_track();
720 FloatAuto *x=0, *y=0, *z=0;
721 mwindow->cwindow->calculate_affected_autos(track,
722 &x, &y, &z, cfg.use_camera, 0,0,0); // don't create new keyframe
723 if( x ) x->change_curve_mode(cfg.mode);
724 if( y ) y->change_curve_mode(cfg.mode);
725 if( z ) z->change_curve_mode(cfg.mode);
728 gui->update_preview();
735 CWindowEyedropCheckBox::CWindowEyedropCheckBox(MWindow *mwindow,
736 CWindowEyedropGUI *gui, int x, int y)
737 : BC_CheckBox(x, y, mwindow->edl->local_session->use_max, _("Use maximum"))
739 this->mwindow = mwindow;
743 int CWindowEyedropCheckBox::handle_event()
745 mwindow->edl->local_session->use_max = get_value();
752 CWindowCameraGUI::CWindowCameraGUI(MWindow *mwindow, CWindowTool *thread)
753 : CWindowToolGUI(mwindow,
755 _(PROGRAM_NAME ": Camera"),
760 CWindowCameraGUI::~CWindowCameraGUI()
764 void CWindowCameraGUI::create_objects()
766 int x = 10, y = 10, x1;
767 Track *track = mwindow->cwindow->calculate_affected_track();
768 FloatAuto *x_auto = 0, *y_auto = 0, *z_auto = 0;
772 lock_window("CWindowCameraGUI::create_objects");
774 mwindow->cwindow->calculate_affected_autos(track,
775 &x_auto, &y_auto, &z_auto, 1, 0, 0, 0);
778 add_subwindow(title = new BC_Title(x, y, "X:"));
780 this->x = new CWindowCoord(this, x, y,
781 x_auto ? x_auto->get_value() : (float)0);
782 this->x->create_objects();
787 add_subwindow(title = new BC_Title(x, y, "Y:"));
789 this->y = new CWindowCoord(this, x, y,
790 y_auto ? y_auto->get_value() : (float)0);
791 this->y->create_objects();
794 add_subwindow(title = new BC_Title(x, y, "Z:"));
796 this->z = new CWindowCoord(this, x, y,
797 z_auto ? z_auto->get_value() : (float)1);
798 this->z->create_objects();
799 this->z->set_increment(0.01);
803 add_subwindow(button = new CWindowCameraLeft(mwindow, this, x1, y));
804 x1 += button->get_w();
805 add_subwindow(button = new CWindowCameraCenter(mwindow, this, x1, y));
806 x1 += button->get_w();
807 add_subwindow(button = new CWindowCameraRight(mwindow, this, x1, y));
809 y += button->get_h();
811 add_subwindow(button = new CWindowCameraTop(mwindow, this, x1, y));
812 x1 += button->get_w();
813 add_subwindow(button = new CWindowCameraMiddle(mwindow, this, x1, y));
814 x1 += button->get_w();
815 add_subwindow(button = new CWindowCameraBottom(mwindow, this, x1, y));
816 // additional Buttons to control the curve mode of the "current" keyframe
817 x1 += button->get_w() + 15;
818 add_subwindow(this->t_smooth = new CWindowCurveToggle(Camera_Crv_Smooth, mwindow, this, x1, y));
819 x1 += button->get_w();
820 add_subwindow(this->t_linear = new CWindowCurveToggle(Camera_Crv_Linear, mwindow, this, x1, y));
822 // fill in current auto keyframe values, set toggle states.
827 void CWindowCameraGUI::handle_event()
829 FloatAuto *x_auto = 0;
830 FloatAuto *y_auto = 0;
831 FloatAuto *z_auto = 0;
832 Track *track = mwindow->cwindow->calculate_affected_track();
835 mwindow->undo->update_undo_before(_("camera"), this);
836 if(event_caller == x)
838 x_auto = (FloatAuto*)mwindow->cwindow->calculate_affected_auto(
839 track->automation->autos[AUTOMATION_CAMERA_X],
843 x_auto->set_value(atof(x->get_text()));
849 if(event_caller == y)
851 y_auto = (FloatAuto*)mwindow->cwindow->calculate_affected_auto(
852 track->automation->autos[AUTOMATION_CAMERA_Y],
856 y_auto->set_value(atof(y->get_text()));
862 if(event_caller == z)
864 z_auto = (FloatAuto*)mwindow->cwindow->calculate_affected_auto(
865 track->automation->autos[AUTOMATION_CAMERA_Z],
869 float zoom = atof(z->get_text());
870 if(zoom > 100.) zoom = 100.;
872 if(zoom < 0.01) zoom = 0.01;
873 // Doesn't allow user to enter from scratch
874 // if(zoom != atof(z->get_text()))
877 z_auto->set_value(zoom);
878 mwindow->gui->lock_window("CWindowCameraGUI::handle_event");
879 mwindow->gui->draw_overlays(1);
880 mwindow->gui->unlock_window();
886 mwindow->undo->update_undo_after(_("camera"), LOAD_ALL);
890 void CWindowCameraGUI::update()
892 FloatAuto *x_auto = 0;
893 FloatAuto *y_auto = 0;
894 FloatAuto *z_auto = 0;
895 Track *track = mwindow->cwindow->calculate_affected_track();
897 mwindow->cwindow->calculate_affected_autos(track,
898 &x_auto, &y_auto, &z_auto, 1, 0, 0, 0);
902 x->update(x_auto->get_value());
904 y->update(y_auto->get_value());
906 float value = z_auto->get_value();
908 thread->gui->lock_window("CWindowCameraGUI::update");
909 thread->gui->composite_panel->cpanel_zoom->update(value);
910 thread->gui->unlock_window();
913 if( x_auto && y_auto && z_auto )
915 t_smooth->check_toggle_state(x_auto, y_auto, z_auto);
916 t_linear->check_toggle_state(x_auto, y_auto, z_auto);
923 CWindowCameraLeft::CWindowCameraLeft(MWindow *mwindow, CWindowCameraGUI *gui, int x, int y)
924 : BC_Button(x, y, mwindow->theme->get_image_set("left_justify"))
927 this->mwindow = mwindow;
928 set_tooltip(_("Left justify"));
930 int CWindowCameraLeft::handle_event()
932 FloatAuto *x_auto = 0;
933 FloatAuto *z_auto = 0;
934 Track *track = mwindow->cwindow->calculate_affected_track();
936 mwindow->cwindow->calculate_affected_autos(track,
937 &x_auto, 0, &z_auto, 1, 1, 0, 0);
943 track->get_source_dimensions(
944 mwindow->edl->local_session->get_selectionstart(1),
950 mwindow->undo->update_undo_before(_("camera"), 0);
952 (double)track->track_w / z_auto->get_value() / 2 -
954 mwindow->undo->update_undo_after(_("camera"), LOAD_ALL);
956 gui->update_preview();
964 CWindowCameraCenter::CWindowCameraCenter(MWindow *mwindow, CWindowCameraGUI *gui, int x, int y)
965 : BC_Button(x, y, mwindow->theme->get_image_set("center_justify"))
968 this->mwindow = mwindow;
969 set_tooltip(_("Center horizontal"));
971 int CWindowCameraCenter::handle_event()
973 FloatAuto *x_auto = 0;
974 Track *track = mwindow->cwindow->calculate_affected_track();
976 x_auto = (FloatAuto*)mwindow->cwindow->calculate_affected_auto(
977 track->automation->autos[AUTOMATION_CAMERA_X],
982 mwindow->undo->update_undo_before(_("camera"), 0);
983 x_auto->set_value(0);
985 gui->update_preview();
986 mwindow->undo->update_undo_after(_("camera"), LOAD_ALL);
993 CWindowCameraRight::CWindowCameraRight(MWindow *mwindow, CWindowCameraGUI *gui, int x, int y)
994 : BC_Button(x, y, mwindow->theme->get_image_set("right_justify"))
997 this->mwindow = mwindow;
998 set_tooltip(_("Right justify"));
1000 int CWindowCameraRight::handle_event()
1002 FloatAuto *x_auto = 0;
1003 FloatAuto *z_auto = 0;
1004 Track *track = mwindow->cwindow->calculate_affected_track();
1006 mwindow->cwindow->calculate_affected_autos(track,
1007 &x_auto, 0, &z_auto, 1, 1, 0, 0);
1010 if(x_auto && z_auto)
1013 track->get_source_dimensions(
1014 mwindow->edl->local_session->get_selectionstart(1),
1020 mwindow->undo->update_undo_before(_("camera"), 0);
1021 x_auto->set_value( -((double)track->track_w / z_auto->get_value() / 2 -
1024 gui->update_preview();
1025 mwindow->undo->update_undo_after(_("camera"), LOAD_ALL);
1033 CWindowCameraTop::CWindowCameraTop(MWindow *mwindow, CWindowCameraGUI *gui, int x, int y)
1034 : BC_Button(x, y, mwindow->theme->get_image_set("top_justify"))
1037 this->mwindow = mwindow;
1038 set_tooltip(_("Top justify"));
1040 int CWindowCameraTop::handle_event()
1042 FloatAuto *y_auto = 0;
1043 FloatAuto *z_auto = 0;
1044 Track *track = mwindow->cwindow->calculate_affected_track();
1046 mwindow->cwindow->calculate_affected_autos(track,
1047 0, &y_auto, &z_auto, 1, 0, 1, 0);
1050 if(y_auto && z_auto)
1053 track->get_source_dimensions(
1054 mwindow->edl->local_session->get_selectionstart(1),
1060 mwindow->undo->update_undo_before(_("camera"), 0);
1061 y_auto->set_value((double)track->track_h / z_auto->get_value() / 2 -
1064 gui->update_preview();
1065 mwindow->undo->update_undo_after(_("camera"), LOAD_ALL);
1073 CWindowCameraMiddle::CWindowCameraMiddle(MWindow *mwindow, CWindowCameraGUI *gui, int x, int y)
1074 : BC_Button(x, y, mwindow->theme->get_image_set("middle_justify"))
1077 this->mwindow = mwindow;
1078 set_tooltip(_("Center vertical"));
1080 int CWindowCameraMiddle::handle_event()
1082 FloatAuto *y_auto = 0;
1083 Track *track = mwindow->cwindow->calculate_affected_track();
1085 y_auto = (FloatAuto*)mwindow->cwindow->calculate_affected_auto(
1086 track->automation->autos[AUTOMATION_CAMERA_Y], 1);
1090 mwindow->undo->update_undo_before(_("camera"), 0);
1091 y_auto->set_value(0);
1093 gui->update_preview();
1094 mwindow->undo->update_undo_after(_("camera"), LOAD_ALL);
1101 CWindowCameraBottom::CWindowCameraBottom(MWindow *mwindow, CWindowCameraGUI *gui, int x, int y)
1102 : BC_Button(x, y, mwindow->theme->get_image_set("bottom_justify"))
1105 this->mwindow = mwindow;
1106 set_tooltip(_("Bottom justify"));
1108 int CWindowCameraBottom::handle_event()
1110 FloatAuto *y_auto = 0;
1111 FloatAuto *z_auto = 0;
1112 Track *track = mwindow->cwindow->calculate_affected_track();
1114 mwindow->cwindow->calculate_affected_autos(track,
1115 0, &y_auto, &z_auto, 1, 0, 1, 0);
1118 if(y_auto && z_auto)
1121 track->get_source_dimensions(
1122 mwindow->edl->local_session->get_selectionstart(1),
1128 mwindow->undo->update_undo_before(_("camera"), 0);
1129 y_auto->set_value(-((double)track->track_h / z_auto->get_value() / 2 -
1132 gui->update_preview();
1133 mwindow->undo->update_undo_after(_("camera"), LOAD_ALL);
1141 CWindowProjectorGUI::CWindowProjectorGUI(MWindow *mwindow, CWindowTool *thread)
1142 : CWindowToolGUI(mwindow,
1144 _(PROGRAM_NAME ": Projector"),
1149 CWindowProjectorGUI::~CWindowProjectorGUI()
1152 void CWindowProjectorGUI::create_objects()
1154 int x = 10, y = 10, x1;
1155 Track *track = mwindow->cwindow->calculate_affected_track();
1156 FloatAuto *x_auto = 0;
1157 FloatAuto *y_auto = 0;
1158 FloatAuto *z_auto = 0;
1162 lock_window("CWindowProjectorGUI::create_objects");
1164 mwindow->cwindow->calculate_affected_autos(track,
1165 &x_auto, &y_auto, &z_auto, 0, 0, 0, 0);
1168 add_subwindow(title = new BC_Title(x, y, "X:"));
1169 x += title->get_w();
1170 this->x = new CWindowCoord(this, x, y,
1171 x_auto ? x_auto->get_value() : (float)0);
1172 this->x->create_objects();
1175 add_subwindow(title = new BC_Title(x, y, "Y:"));
1176 x += title->get_w();
1177 this->y = new CWindowCoord(this, x, y,
1178 y_auto ? y_auto->get_value() : (float)0);
1179 this->y->create_objects();
1182 add_subwindow(title = new BC_Title(x, y, "Z:"));
1183 x += title->get_w();
1184 this->z = new CWindowCoord(this, x, y,
1185 z_auto ? z_auto->get_value() : (float)1);
1186 this->z->create_objects();
1187 this->z->set_increment(0.01);
1191 add_subwindow(button = new CWindowProjectorLeft(mwindow, this, x1, y));
1192 x1 += button->get_w();
1193 add_subwindow(button = new CWindowProjectorCenter(mwindow, this, x1, y));
1194 x1 += button->get_w();
1195 add_subwindow(button = new CWindowProjectorRight(mwindow, this, x1, y));
1197 y += button->get_h();
1199 add_subwindow(button = new CWindowProjectorTop(mwindow, this, x1, y));
1200 x1 += button->get_w();
1201 add_subwindow(button = new CWindowProjectorMiddle(mwindow, this, x1, y));
1202 x1 += button->get_w();
1203 add_subwindow(button = new CWindowProjectorBottom(mwindow, this, x1, y));
1205 // additional Buttons to control the curve mode of the "current" keyframe
1206 x1 += button->get_w() + 15;
1207 add_subwindow(this->t_smooth = new CWindowCurveToggle(Projector_Crv_Smooth, mwindow, this, x1, y));
1208 x1 += button->get_w();
1209 add_subwindow(this->t_linear = new CWindowCurveToggle(Projector_Crv_Linear, mwindow, this, x1, y));
1211 // fill in current auto keyframe values, set toggle states.
1216 void CWindowProjectorGUI::handle_event()
1218 FloatAuto *x_auto = 0;
1219 FloatAuto *y_auto = 0;
1220 FloatAuto *z_auto = 0;
1221 Track *track = mwindow->cwindow->calculate_affected_track();
1225 mwindow->undo->update_undo_before(_("projector"), this);
1226 if(event_caller == x)
1228 x_auto = (FloatAuto*)mwindow->cwindow->calculate_affected_auto(
1229 track->automation->autos[AUTOMATION_PROJECTOR_X],
1233 x_auto->set_value(atof(x->get_text()));
1239 if(event_caller == y)
1241 y_auto = (FloatAuto*)mwindow->cwindow->calculate_affected_auto(
1242 track->automation->autos[AUTOMATION_PROJECTOR_Y],
1246 y_auto->set_value(atof(y->get_text()));
1252 if(event_caller == z)
1254 z_auto = (FloatAuto*)mwindow->cwindow->calculate_affected_auto(
1255 track->automation->autos[AUTOMATION_PROJECTOR_Z],
1259 float zoom = atof(z->get_text());
1260 if(zoom > 100.) zoom = 100.;
1261 else if(zoom < 0.01) zoom = 0.01;
1262 // if (zoom != atof(z->get_text()))
1264 z_auto->set_value(zoom);
1266 mwindow->gui->lock_window("CWindowProjectorGUI::handle_event");
1267 mwindow->gui->draw_overlays(1);
1268 mwindow->gui->unlock_window();
1274 mwindow->undo->update_undo_after(_("projector"), LOAD_ALL);
1278 void CWindowProjectorGUI::update()
1280 FloatAuto *x_auto = 0;
1281 FloatAuto *y_auto = 0;
1282 FloatAuto *z_auto = 0;
1283 Track *track = mwindow->cwindow->calculate_affected_track();
1285 mwindow->cwindow->calculate_affected_autos(track,
1286 &x_auto, &y_auto, &z_auto, 0, 0, 0, 0);
1290 x->update(x_auto->get_value());
1292 y->update(y_auto->get_value());
1294 float value = z_auto->get_value();
1296 thread->gui->lock_window("CWindowProjectorGUI::update");
1297 thread->gui->composite_panel->cpanel_zoom->update(value);
1298 thread->gui->unlock_window();
1301 if( x_auto && y_auto && z_auto )
1303 t_smooth->check_toggle_state(x_auto, y_auto, z_auto);
1304 t_linear->check_toggle_state(x_auto, y_auto, z_auto);
1308 CWindowProjectorLeft::CWindowProjectorLeft(MWindow *mwindow, CWindowProjectorGUI *gui, int x, int y)
1309 : BC_Button(x, y, mwindow->theme->get_image_set("left_justify"))
1312 this->mwindow = mwindow;
1313 set_tooltip(_("Left justify"));
1315 int CWindowProjectorLeft::handle_event()
1317 FloatAuto *x_auto = 0;
1318 FloatAuto *z_auto = 0;
1319 Track *track = mwindow->cwindow->calculate_affected_track();
1321 mwindow->cwindow->calculate_affected_autos(track,
1322 &x_auto, 0, &z_auto, 0, 1, 0, 0);
1324 if(x_auto && z_auto)
1326 mwindow->undo->update_undo_before(_("projector"), 0);
1327 x_auto->set_value( (double)track->track_w * z_auto->get_value() / 2 -
1328 (double)mwindow->edl->session->output_w / 2 );
1330 gui->update_preview();
1331 mwindow->undo->update_undo_after(_("projector"), LOAD_ALL);
1338 CWindowProjectorCenter::CWindowProjectorCenter(MWindow *mwindow, CWindowProjectorGUI *gui, int x, int y)
1339 : BC_Button(x, y, mwindow->theme->get_image_set("center_justify"))
1342 this->mwindow = mwindow;
1343 set_tooltip(_("Center horizontal"));
1345 int CWindowProjectorCenter::handle_event()
1347 FloatAuto *x_auto = 0;
1348 Track *track = mwindow->cwindow->calculate_affected_track();
1350 x_auto = (FloatAuto*)mwindow->cwindow->calculate_affected_auto(
1351 track->automation->autos[AUTOMATION_PROJECTOR_X],
1356 mwindow->undo->update_undo_before(_("projector"), 0);
1357 x_auto->set_value(0);
1359 gui->update_preview();
1360 mwindow->undo->update_undo_after(_("projector"), LOAD_ALL);
1367 CWindowProjectorRight::CWindowProjectorRight(MWindow *mwindow, CWindowProjectorGUI *gui, int x, int y)
1368 : BC_Button(x, y, mwindow->theme->get_image_set("right_justify"))
1371 this->mwindow = mwindow;
1372 set_tooltip(_("Right justify"));
1374 int CWindowProjectorRight::handle_event()
1376 FloatAuto *x_auto = 0;
1377 FloatAuto *z_auto = 0;
1378 Track *track = mwindow->cwindow->calculate_affected_track();
1380 mwindow->cwindow->calculate_affected_autos(track,
1381 &x_auto, 0, &z_auto, 0, 1, 0, 0);
1384 if(x_auto && z_auto)
1386 mwindow->undo->update_undo_before(_("projector"), 0);
1387 x_auto->set_value( -((double)track->track_w * z_auto->get_value() / 2 -
1388 (double)mwindow->edl->session->output_w / 2));
1390 gui->update_preview();
1391 mwindow->undo->update_undo_after(_("projector"), LOAD_ALL);
1398 CWindowProjectorTop::CWindowProjectorTop(MWindow *mwindow, CWindowProjectorGUI *gui, int x, int y)
1399 : BC_Button(x, y, mwindow->theme->get_image_set("top_justify"))
1402 this->mwindow = mwindow;
1403 set_tooltip(_("Top justify"));
1405 int CWindowProjectorTop::handle_event()
1407 FloatAuto *y_auto = 0;
1408 FloatAuto *z_auto = 0;
1409 Track *track = mwindow->cwindow->calculate_affected_track();
1411 mwindow->cwindow->calculate_affected_autos(track,
1412 0, &y_auto, &z_auto, 0, 0, 1, 0);
1415 if(y_auto && z_auto)
1417 mwindow->undo->update_undo_before(_("projector"), 0);
1418 y_auto->set_value( (double)track->track_h * z_auto->get_value() / 2 -
1419 (double)mwindow->edl->session->output_h / 2 );
1421 gui->update_preview();
1422 mwindow->undo->update_undo_after(_("projector"), LOAD_ALL);
1429 CWindowProjectorMiddle::CWindowProjectorMiddle(MWindow *mwindow, CWindowProjectorGUI *gui, int x, int y)
1430 : BC_Button(x, y, mwindow->theme->get_image_set("middle_justify"))
1433 this->mwindow = mwindow;
1434 set_tooltip(_("Center vertical"));
1436 int CWindowProjectorMiddle::handle_event()
1438 FloatAuto *y_auto = 0;
1439 Track *track = mwindow->cwindow->calculate_affected_track();
1441 y_auto = (FloatAuto*)mwindow->cwindow->calculate_affected_auto(
1442 track->automation->autos[AUTOMATION_PROJECTOR_Y], 1);
1446 mwindow->undo->update_undo_before(_("projector"), 0);
1447 y_auto->set_value(0);
1449 gui->update_preview();
1450 mwindow->undo->update_undo_after(_("projector"), LOAD_ALL);
1457 CWindowProjectorBottom::CWindowProjectorBottom(MWindow *mwindow, CWindowProjectorGUI *gui, int x, int y)
1458 : BC_Button(x, y, mwindow->theme->get_image_set("bottom_justify"))
1461 this->mwindow = mwindow;
1462 set_tooltip(_("Bottom justify"));
1464 int CWindowProjectorBottom::handle_event()
1466 FloatAuto *y_auto = 0;
1467 FloatAuto *z_auto = 0;
1468 Track *track = mwindow->cwindow->calculate_affected_track();
1470 mwindow->cwindow->calculate_affected_autos(track,
1471 0, &y_auto, &z_auto, 0, 0, 1, 0);
1474 if(y_auto && z_auto)
1476 mwindow->undo->update_undo_before(_("projector"), 0);
1477 y_auto->set_value( -((double)track->track_h * z_auto->get_value() / 2 -
1478 (double)mwindow->edl->session->output_h / 2));
1480 gui->update_preview();
1481 mwindow->undo->update_undo_after(_("projector"), LOAD_ALL);
1488 CWindowMaskOnTrack::CWindowMaskOnTrack(MWindow *mwindow, CWindowMaskGUI *gui,
1489 int x, int y, int w, const char *text)
1490 : BC_PopupTextBox(gui, 0, text, x, y, w, 120)
1492 this->mwindow = mwindow;
1496 CWindowMaskOnTrack::~CWindowMaskOnTrack()
1500 int CWindowMaskOnTrack::handle_event()
1502 CWindowMaskItem *track_item = 0;
1503 int k = get_number(), track_id = -1;
1504 //printf("selected %d = %s\n", k, k<0 ? "()" : track_items[k]->get_text());
1506 track_item = (CWindowMaskItem *)track_items[k];
1507 Track *track = track_item ? mwindow->edl->tracks->get_track_by_id(track_item->id) : 0;
1508 if( track && track->record ) track_id = track->get_id();
1511 track_id = mwindow->cwindow->mask_track_id;
1512 set_back_color(track_id >= 0 ?
1513 gui->get_resources()->text_background :
1514 gui->get_resources()->text_background_disarmed);
1515 if( mwindow->cwindow->mask_track_id != track_id )
1516 gui->mask_on_track->update(track_item ? track_item->get_text() : "");
1517 mwindow->cwindow->mask_track_id = track_id;
1518 mwindow->edl->local_session->solo_track_id = -1;
1519 gui->mask_solo_track->update(0);
1521 gui->update_preview(1);
1525 void CWindowMaskOnTrack::update_items()
1527 track_items.remove_all_objects();
1528 int high_color = gui->get_resources()->button_highlighted;
1529 for( Track *track=mwindow->edl->tracks->first; track; track=track->next ) {
1530 if( track->data_type != TRACK_VIDEO ) continue;
1531 MaskAutos *mask_autos = (MaskAutos*)track->automation->autos[AUTOMATION_MASK];
1532 int color = !track->record ? RED : mask_autos->first ? high_color : -1;
1533 MaskAuto *mask_auto = (MaskAuto*)mask_autos->default_auto;
1534 for( int i=0; color<0 && i<mask_auto->masks.size(); ++i )
1535 if( mask_auto->masks[i]->points.size() > 0 ) color = high_color;
1536 track_items.append(new CWindowMaskItem(track->title, track->get_id(), color));
1538 update_list(&track_items);
1541 CWindowMaskTrackTumbler::CWindowMaskTrackTumbler(MWindow *mwindow, CWindowMaskGUI *gui,
1545 this->mwindow = mwindow;
1548 CWindowMaskTrackTumbler::~CWindowMaskTrackTumbler()
1552 int CWindowMaskTrackTumbler::handle_up_event()
1557 int CWindowMaskTrackTumbler::handle_down_event()
1559 return do_event(-1);
1562 int CWindowMaskTrackTumbler::do_event(int dir)
1564 CWindowMaskItem *track_item = 0;
1565 CWindowMaskItem **items = (CWindowMaskItem**)&gui->mask_on_track->track_items[0];
1566 int n = gui->mask_on_track->track_items.size();
1567 int id = mwindow->cwindow->mask_track_id;
1570 while( --k >= 0 && items[k]->id != id );
1574 track_item = items[k];
1577 track_item = items[0];
1579 Track *track = track_item ? mwindow->edl->tracks->get_track_by_id(track_item->id) : 0;
1580 int track_id = track_item && track && track->record ? track_item->id : -1;
1581 gui->mask_on_track->set_back_color(track_id >= 0 ?
1582 gui->get_resources()->text_background :
1583 gui->get_resources()->text_background_disarmed);
1584 gui->mask_on_track->update(track_item ? track_item->get_text() : "");
1585 mwindow->cwindow->mask_track_id = track_item ? track_item->id : -1;
1586 mwindow->edl->local_session->solo_track_id = -1;
1587 gui->mask_solo_track->update(0);
1589 gui->update_preview(1);
1594 CWindowMaskName::CWindowMaskName(MWindow *mwindow, CWindowMaskGUI *gui,
1595 int x, int y, const char *text)
1596 : BC_PopupTextBox(gui, 0, text, x, y, 100, 160)
1598 this->mwindow = mwindow;
1602 CWindowMaskName::~CWindowMaskName()
1606 int CWindowMaskName::handle_event()
1613 //printf("CWindowMaskGUI::update 1\n");
1614 gui->get_keyframe(track, autos, keyframe, mask, point, 0);
1616 int k = get_number();
1617 if( k < 0 ) k = mwindow->edl->session->cwindow_mask;
1618 else mwindow->edl->session->cwindow_mask = k;
1619 if( k >= 0 && k < mask_items.size() ) {
1620 mask_items[k]->set_text(get_text());
1621 update_list(&mask_items);
1623 #ifdef USE_KEYFRAME_SPANNING
1624 MaskAuto temp_keyframe(mwindow->edl, autos);
1625 temp_keyframe.copy_data(keyframe);
1626 SubMask *submask = temp_keyframe.get_submask(mwindow->edl->session->cwindow_mask);
1627 memset(submask->name, 0, sizeof(submask->name));
1628 strncpy(submask->name, get_text(), sizeof(submask->name)-1);
1629 ((MaskAutos*)track->automation->autos[AUTOMATION_MASK])->update_parameter(&temp_keyframe);
1631 for(MaskAuto *current = (MaskAuto*)autos->default_auto; current; ) {
1632 SubMask *submask = current->get_submask(mwindow->edl->session->cwindow_mask);
1633 memset(submask->name, 0, sizeof(submask->name));
1634 strncpy(submask->name, get_text(), sizeof(submask->name));
1635 current = current == (MaskAuto*)autos->default_auto ?
1636 (MaskAuto*)autos->first : (MaskAuto*)NEXT;
1640 gui->update_preview();
1645 void CWindowMaskName::update_items(MaskAuto *keyframe)
1647 mask_items.remove_all_objects();
1648 int sz = !keyframe ? 0 : keyframe->masks.size();
1649 for( int i=0; i<SUBMASKS; ++i ) {
1650 char text[BCSTRLEN];
1652 SubMask *sub_mask = keyframe->masks.get(i);
1653 strncpy(text, sub_mask->name, sizeof(text));
1656 sprintf(text, "%d", i);
1657 mask_items.append(new CWindowMaskItem(text));
1659 update_list(&mask_items);
1663 CWindowMaskButton::CWindowMaskButton(MWindow *mwindow, CWindowMaskGUI *gui,
1664 int x, int y, int no, int v)
1665 : BC_CheckBox(x, y, v)
1667 this->mwindow = mwindow;
1672 CWindowMaskButton::~CWindowMaskButton()
1676 int CWindowMaskButton::handle_event()
1678 mwindow->edl->session->cwindow_mask = no;
1679 gui->mask_name->update(gui->mask_name->mask_items[no]->get_text());
1681 gui->update_preview();
1685 CWindowMaskThumbler::CWindowMaskThumbler(MWindow *mwindow, CWindowMaskGUI *gui,
1689 this->mwindow = mwindow;
1693 CWindowMaskThumbler::~CWindowMaskThumbler()
1697 int CWindowMaskThumbler::handle_up_event()
1702 int CWindowMaskThumbler::handle_down_event()
1704 return do_event(-1);
1707 int CWindowMaskThumbler::do_event(int dir)
1709 int k = mwindow->edl->session->cwindow_mask;
1710 if( (k+=dir) >= SUBMASKS ) k = 0;
1711 else if( k < 0 ) k = SUBMASKS-1;
1712 mwindow->edl->session->cwindow_mask = k;
1713 gui->mask_name->update(gui->mask_name->mask_items[k]->get_text());
1715 gui->update_preview();
1719 CWindowMaskEnable::CWindowMaskEnable(MWindow *mwindow, CWindowMaskGUI *gui,
1720 int x, int y, int no, int v)
1721 : BC_CheckBox(x, y, v)
1723 this->mwindow = mwindow;
1728 CWindowMaskEnable::~CWindowMaskEnable()
1732 int CWindowMaskEnable::handle_event()
1734 Track *track = mwindow->cwindow->calculate_mask_track();
1736 mwindow->undo->update_undo_before(_("mask enable"), this);
1739 track->masks |= bit;
1741 track->masks &= ~bit;
1743 gui->update_preview(1);
1744 mwindow->undo->update_undo_after(_("mask enable"), LOAD_PATCHES);
1749 CWindowMaskUnclear::CWindowMaskUnclear(MWindow *mwindow,
1750 CWindowMaskGUI *gui, int x, int y, int w)
1751 : BC_GenericButton(x, y, w, _("Enable"))
1753 this->mwindow = mwindow;
1755 set_tooltip(_("Show/Hide mask"));
1758 int CWindowMaskUnclear::handle_event()
1760 Track *track = mwindow->cwindow->calculate_mask_track();
1762 mwindow->undo->update_undo_before(_("mask enables"), this);
1763 int m = (1<<SUBMASKS)-1;
1764 if( track->masks == m )
1768 for( int i=0; i<SUBMASKS; ++i )
1769 gui->mask_enables[i]->update((track->masks>>i) & 1);
1770 gui->update_preview(1);
1771 mwindow->undo->update_undo_after(_("mask enables"), LOAD_PATCHES);
1776 CWindowMaskSoloTrack::CWindowMaskSoloTrack(MWindow *mwindow,
1777 CWindowMaskGUI *gui, int x, int y, int v)
1778 : BC_CheckBox(x, y, v, _("Solo"))
1780 this->mwindow = mwindow;
1782 set_tooltip(_("Solo video track"));
1785 int CWindowMaskSoloTrack::handle_event()
1787 mwindow->edl->local_session->solo_track_id =
1788 get_value() ? mwindow->cwindow->mask_track_id : -1;
1789 gui->update_preview(1);
1793 int CWindowMaskSoloTrack::calculate_w(BC_WindowBase *gui)
1796 calculate_extents(gui, &w, &h, _("Solo"));
1800 CWindowMaskDelMask::CWindowMaskDelMask(MWindow *mwindow,
1801 CWindowMaskGUI *gui, int x, int y)
1802 : BC_GenericButton(x, y, _("Delete"))
1804 this->mwindow = mwindow;
1806 set_tooltip(_("Delete mask"));
1809 int CWindowMaskDelMask::handle_event()
1818 // Get existing keyframe
1819 gui->get_keyframe(track, autos, keyframe, mask, point, 0);
1822 mwindow->undo->update_undo_before(_("mask delete"), 0);
1824 #ifdef USE_KEYFRAME_SPANNING
1825 // Create temp keyframe
1826 MaskAuto temp_keyframe(mwindow->edl, autos);
1827 temp_keyframe.copy_data(keyframe);
1828 SubMask *submask = temp_keyframe.get_submask(mwindow->edl->session->cwindow_mask);
1829 submask->points.remove_all_objects();
1831 // Commit change to span of keyframes
1832 ((MaskAutos*)track->automation->autos[AUTOMATION_MASK])->update_parameter(&temp_keyframe);
1834 for(MaskAuto *current = (MaskAuto*)autos->default_auto; current; ) {
1835 SubMask *submask = current->get_submask(mwindow->edl->session->cwindow_mask);
1836 submask->points.clear();
1837 current = current == (MaskAuto*)autos->default_auto ?
1838 (MaskAuto*)autos->first : (MaskAuto*)NEXT;
1842 if( mwindow->cwindow->gui->affected_point >= total_points )
1843 mwindow->cwindow->gui->affected_point =
1844 total_points > 0 ? total_points-1 : 0;
1847 gui->update_preview();
1848 mwindow->undo->update_undo_after(_("mask delete"), LOAD_AUTOMATION);
1854 CWindowMaskDelPoint::CWindowMaskDelPoint(MWindow *mwindow,
1855 CWindowMaskGUI *gui, int x, int y)
1856 : BC_GenericButton(x, y, _("Delete"))
1858 this->mwindow = mwindow;
1860 set_tooltip(_("Delete point"));
1863 int CWindowMaskDelPoint::handle_event()
1872 // Get existing keyframe
1873 gui->get_keyframe(track, autos, keyframe, mask, point, 0);
1875 mwindow->undo->update_undo_before(_("point delete"), 0);
1877 #ifdef USE_KEYFRAME_SPANNING
1878 // Create temp keyframe
1879 MaskAuto temp_keyframe(mwindow->edl, autos);
1880 temp_keyframe.copy_data(keyframe);
1882 SubMask *submask = temp_keyframe.get_submask(mwindow->edl->session->cwindow_mask);
1883 int i = mwindow->cwindow->gui->affected_point;
1884 for( ; i<submask->points.total-1; ++i )
1885 *submask->points.values[i] = *submask->points.values[i+1];
1886 if( submask->points.total > 0 ) {
1887 point = submask->points.values[submask->points.total-1];
1888 submask->points.remove_object(point);
1890 total_points = submask->points.total;
1892 // Commit change to span of keyframes
1893 ((MaskAutos*)track->automation->autos[AUTOMATION_MASK])->update_parameter(&temp_keyframe);
1895 MaskAuto *current = (MaskAuto*)autos->default_auto;
1897 SubMask *submask = current->get_submask(mwindow->edl->session->cwindow_mask);
1898 int i = mwindow->cwindow->gui->affected_point;
1899 for( ; i<submask->points.total-1; ++i ) {
1900 *submask->points.values[i] = *submask->points.values[i+1];
1901 if( submask->points.total > 0 ) {
1902 point = submask->points.values[submask->points.total-1];
1903 submask->points.remove_object(point);
1905 total_points = submask->points.total;
1906 current = current == (MaskAuto*)autos->default_auto ?
1907 (MaskAuto*)autos->first : (MaskAuto*)NEXT;
1910 if( mwindow->cwindow->gui->affected_point >= total_points )
1911 mwindow->cwindow->gui->affected_point =
1912 total_points > 0 ? total_points-1 : 0;
1915 gui->update_preview();
1916 mwindow->undo->update_undo_after(_("mask delete"), LOAD_AUTOMATION);
1922 int CWindowMaskDelPoint::keypress_event()
1924 if( get_keypress() == BACKSPACE ||
1925 get_keypress() == DELETE )
1926 return handle_event();
1933 CWindowMaskAffectedPoint::CWindowMaskAffectedPoint(MWindow *mwindow,
1934 CWindowMaskGUI *gui, int x, int y)
1935 : BC_TumbleTextBox(gui,
1936 (int64_t)mwindow->cwindow->gui->affected_point,
1937 (int64_t)0, INT64_MAX, x, y, 100)
1939 this->mwindow = mwindow;
1943 CWindowMaskAffectedPoint::~CWindowMaskAffectedPoint()
1947 int CWindowMaskAffectedPoint::handle_event()
1949 int total_points = 0;
1950 int affected_point = atol(get_text());
1951 Track *track = mwindow->cwindow->calculate_mask_track();
1953 MaskAutos *autos = (MaskAutos*)track->automation->autos[AUTOMATION_MASK];
1954 MaskAuto *keyframe = (MaskAuto*)mwindow->cwindow->calculate_affected_auto(autos, 0);
1956 SubMask *mask = keyframe->get_submask(mwindow->edl->session->cwindow_mask);
1957 total_points = mask->points.size();
1960 int active_point = affected_point;
1961 if( affected_point >= total_points )
1962 affected_point = total_points - 1;
1963 if( affected_point < 0 )
1965 if( active_point != affected_point )
1966 update((int64_t)affected_point);
1967 mwindow->cwindow->gui->affected_point = affected_point;
1969 gui->update_preview();
1974 CWindowMaskFocus::CWindowMaskFocus(MWindow *mwindow, CWindowMaskGUI *gui, int x, int y)
1975 : BC_CheckBox(x, y, gui->focused, _("Focus"))
1977 this->mwindow = mwindow;
1979 set_tooltip(_("Center for rotate/scale"));
1982 CWindowMaskFocus::~CWindowMaskFocus()
1986 int CWindowMaskFocus::handle_event()
1988 gui->focused = get_value();
1990 gui->update_preview();
1994 CWindowMaskHelp::CWindowMaskHelp(MWindow *mwindow, CWindowMaskGUI *gui, int x, int y)
1995 : BC_CheckBox(x, y, 0, _("Help"))
1997 this->mwindow = mwindow;
1999 set_tooltip(_("Show help text"));
2002 CWindowMaskHelp::~CWindowMaskHelp()
2006 int CWindowMaskHelp::handle_event()
2008 gui->helped = get_value();
2009 gui->resize_window(gui->get_w(),
2010 gui->helped ? gui->help_h : gui->help_y);
2015 CWindowMaskDrawMarkers::CWindowMaskDrawMarkers(MWindow *mwindow, CWindowMaskGUI *gui, int x, int y)
2016 : BC_CheckBox(x, y, gui->markers, _("Markers"))
2018 this->mwindow = mwindow;
2020 set_tooltip("Display points");
2023 CWindowMaskDrawMarkers::~CWindowMaskDrawMarkers()
2027 int CWindowMaskDrawMarkers::handle_event()
2029 gui->markers = get_value();
2031 gui->update_preview();
2035 CWindowMaskDrawBoundary::CWindowMaskDrawBoundary(MWindow *mwindow, CWindowMaskGUI *gui, int x, int y)
2036 : BC_CheckBox(x, y, gui->boundary, _("Boundary"))
2038 this->mwindow = mwindow;
2040 set_tooltip("Display mask outline");
2043 CWindowMaskDrawBoundary::~CWindowMaskDrawBoundary()
2047 int CWindowMaskDrawBoundary::handle_event()
2049 gui->boundary = get_value();
2051 gui->update_preview();
2056 CWindowMaskFeather::CWindowMaskFeather(MWindow *mwindow, CWindowMaskGUI *gui, int x, int y)
2057 : BC_TumbleTextBox(gui, 0, -FEATHER_MAX, FEATHER_MAX, x, y, 64, 2)
2059 this->mwindow = mwindow;
2062 CWindowMaskFeather::~CWindowMaskFeather()
2066 int CWindowMaskFeather::update(float v)
2068 gui->feather_slider->update(v);
2069 return BC_TumbleTextBox::update(v);
2072 int CWindowMaskFeather::update_value(float v)
2079 #ifdef USE_KEYFRAME_SPANNING
2085 mwindow->undo->update_undo_before(_("mask feather"), this);
2087 // Get existing keyframe
2088 gui->get_keyframe(track, autos, keyframe,
2089 mask, point, create_it);
2091 int gang = gui->gang_feather->get_value();
2092 #ifdef USE_KEYFRAME_SPANNING
2093 MaskAuto temp_keyframe(mwindow->edl, autos);
2094 temp_keyframe.copy_data(keyframe);
2095 keyframe = &temp_keyframe;
2097 float change = v - mask->feather;
2098 int k = mwindow->edl->session->cwindow_mask;
2099 int n = gang ? keyframe->masks.size() : k+1;
2100 for( int i=gang? 0 : k; i<n; ++i ) {
2101 SubMask *sub_mask = keyframe->get_submask(i);
2102 float feather = sub_mask->feather + change;
2103 bclamp(feather, -FEATHER_MAX, FEATHER_MAX);
2104 sub_mask->feather = feather;
2106 #ifdef USE_KEYFRAME_SPANNING
2107 autos->update_parameter(keyframe);
2109 gui->update_preview();
2112 mwindow->undo->update_undo_after(_("mask feather"), LOAD_AUTOMATION);
2116 int CWindowMaskFeather::handle_event()
2118 float v = atof(get_text());
2119 gui->feather_slider->update(v);
2120 return gui->feather->update_value(v);
2123 CWindowMaskFeatherSlider::CWindowMaskFeatherSlider(MWindow *mwindow,
2124 CWindowMaskGUI *gui, int x, int y, int w, float v)
2125 : BC_FSlider(x, y, 0, w, w, -FEATHER_MAX, FEATHER_MAX, v)
2127 this->mwindow = mwindow;
2129 set_precision(0.01);
2130 timer = new Timer();
2135 CWindowMaskFeatherSlider::~CWindowMaskFeatherSlider()
2140 int CWindowMaskFeatherSlider::handle_event()
2142 float v = get_value();
2144 int64_t ms = timer->get_difference();
2145 if( ms < 250 && --stick > 0 ) {
2146 if( get_value() == 0 ) return 1;
2154 else if( (last_v>=0 && v<0) || (last_v<0 && v>=0) ) {
2161 gui->feather->BC_TumbleTextBox::update(v);
2162 return gui->feather->update_value(v);
2165 int CWindowMaskFeatherSlider::update(float v)
2167 return BC_FSlider::update(v);
2170 CWindowMaskFade::CWindowMaskFade(MWindow *mwindow, CWindowMaskGUI *gui, int x, int y)
2171 : BC_TumbleTextBox(gui, 0, -100.f, 100.f, x, y, 64, 2)
2173 this->mwindow = mwindow;
2176 CWindowMaskFade::~CWindowMaskFade()
2180 int CWindowMaskFade::update(float v)
2182 gui->fade_slider->update(v);
2183 return BC_TumbleTextBox::update(v);
2186 int CWindowMaskFade::update_value(float v)
2193 #ifdef USE_KEYFRAME_SPANNING
2199 mwindow->undo->update_undo_before(_("mask fade"), this);
2201 // Get existing keyframe
2202 gui->get_keyframe(track, autos, keyframe,
2203 mask, point, create_it);
2205 int gang = gui->gang_fader->get_value();
2206 #ifdef USE_KEYFRAME_SPANNING
2207 MaskAuto temp_keyframe(mwindow->edl, autos);
2208 temp_keyframe.copy_data(keyframe);
2209 keyframe = &temp_keyframe;
2211 float change = v - mask->fader;
2212 int k = mwindow->edl->session->cwindow_mask;
2213 int n = gang ? keyframe->masks.size() : k+1;
2214 for( int i=gang? 0 : k; i<n; ++i ) {
2215 SubMask *sub_mask = keyframe->get_submask(i);
2216 float fader = sub_mask->fader + change;
2217 bclamp(fader, -100.f, 100.f);
2218 sub_mask->fader = fader;
2220 #ifdef USE_KEYFRAME_SPANNING
2221 autos->update_parameter(keyframe);
2223 gui->update_preview();
2226 mwindow->undo->update_undo_after(_("mask fade"), LOAD_AUTOMATION);
2230 int CWindowMaskFade::handle_event()
2232 float v = atof(get_text());
2233 gui->fade_slider->update(v);
2234 return gui->fade->update_value(v);
2237 CWindowMaskFadeSlider::CWindowMaskFadeSlider(MWindow *mwindow, CWindowMaskGUI *gui,
2238 int x, int y, int w)
2239 : BC_ISlider(x, y, 0, w, w, -200, 200, 0)
2241 this->mwindow = mwindow;
2243 timer = new Timer();
2248 CWindowMaskFadeSlider::~CWindowMaskFadeSlider()
2253 int CWindowMaskFadeSlider::handle_event()
2255 float v = 100*get_value()/200;
2257 int64_t ms = timer->get_difference();
2258 if( ms < 250 && --stick > 0 ) {
2259 if( get_value() == 0 ) return 1;
2267 else if( (last_v>=0 && v<0) || (last_v<0 && v>=0) ) {
2274 gui->fade->BC_TumbleTextBox::update(v);
2275 return gui->fade->update_value(v);
2278 int CWindowMaskFadeSlider::update(int64_t v)
2280 return BC_ISlider::update(200*v/100);
2283 CWindowMaskGangFader::CWindowMaskGangFader(MWindow *mwindow,
2284 CWindowMaskGUI *gui, int x, int y)
2285 : BC_Toggle(x, y, mwindow->theme->get_image_set("gangpatch_data"), 0)
2287 this->mwindow = mwindow;
2289 set_tooltip(_("Gang fader"));
2292 CWindowMaskGangFader::~CWindowMaskGangFader()
2296 int CWindowMaskGangFader::handle_event()
2301 CWindowMaskGangFocus::CWindowMaskGangFocus(MWindow *mwindow,
2302 CWindowMaskGUI *gui, int x, int y)
2303 : BC_Toggle(x, y, mwindow->theme->get_image_set("gangpatch_data"), 0)
2305 this->mwindow = mwindow;
2307 set_tooltip(_("Gang rotate/scale/translate"));
2310 CWindowMaskGangFocus::~CWindowMaskGangFocus()
2314 int CWindowMaskGangFocus::handle_event()
2320 CWindowMaskSmoothButton::CWindowMaskSmoothButton(MWindow *mwindow, CWindowMaskGUI *gui,
2321 const char *tip, int type, int on, int x, int y, const char *images)
2322 : BC_Button(x, y, mwindow->theme->get_image_set(images))
2324 this->mwindow = mwindow;
2331 int CWindowMaskSmoothButton::handle_event()
2333 return gui->smooth_mask(type, on);
2336 CWindowMaskBeforePlugins::CWindowMaskBeforePlugins(CWindowMaskGUI *gui, int x, int y)
2337 : BC_CheckBox(x, y, 1, _("Apply mask before plugins"))
2342 int CWindowMaskBeforePlugins::handle_event()
2349 gui->get_keyframe(track, autos, keyframe, mask, point, 1);
2352 int v = get_value();
2353 #ifdef USE_KEYFRAME_SPANNING
2354 MaskAuto temp_keyframe(gui->mwindow->edl, autos);
2355 temp_keyframe.copy_data(keyframe);
2356 temp_keyframe.apply_before_plugins = v;
2357 autos->update_parameter(&temp_keyframe);
2359 keyframe->apply_before_plugins = v;
2361 gui->update_preview();
2367 CWindowDisableOpenGLMasking::CWindowDisableOpenGLMasking(CWindowMaskGUI *gui, int x, int y)
2368 : BC_CheckBox(x, y, 1, _("Disable OpenGL masking"))
2373 int CWindowDisableOpenGLMasking::handle_event()
2380 gui->get_keyframe(track, autos, keyframe, mask, point, 1);
2383 int v = get_value();
2384 #ifdef USE_KEYFRAME_SPANNING
2385 MaskAuto temp_keyframe(gui->mwindow->edl, autos);
2386 temp_keyframe.copy_data(keyframe);
2387 temp_keyframe.disable_opengl_masking = v;
2388 autos->update_parameter(&temp_keyframe);
2390 keyframe->disable_opengl_masking = v;
2392 gui->update_preview();
2398 CWindowMaskClrMask::CWindowMaskClrMask(MWindow *mwindow,
2399 CWindowMaskGUI *gui, int x, int y)
2400 : BC_Button(x, y, mwindow->theme->get_image_set("reset_button"))
2402 this->mwindow = mwindow;
2404 set_tooltip(_("Delete all masks"));
2407 CWindowMaskClrMask::~CWindowMaskClrMask()
2411 int CWindowMaskClrMask::calculate_w(MWindow *mwindow)
2413 VFrame *vfrm = *mwindow->theme->get_image_set("reset_button");
2414 return vfrm->get_w();
2417 int CWindowMaskClrMask::handle_event()
2425 // Get existing keyframe
2426 gui->get_keyframe(track, autos, keyframe, mask, point, 0);
2429 mwindow->undo->update_undo_before(_("del masks"), 0);
2430 ((MaskAutos*)track->automation->autos[AUTOMATION_MASK])->clear_all();
2431 mwindow->undo->update_undo_after(_("del masks"), LOAD_AUTOMATION);
2435 gui->update_preview(1);
2439 CWindowMaskGangFeather::CWindowMaskGangFeather(MWindow *mwindow,
2440 CWindowMaskGUI *gui, int x, int y)
2441 : BC_Toggle(x, y, mwindow->theme->get_image_set("gangpatch_data"), 0)
2443 this->mwindow = mwindow;
2445 set_tooltip(_("Gang feather"));
2448 CWindowMaskGangFeather::~CWindowMaskGangFeather()
2452 int CWindowMaskGangFeather::handle_event()
2457 CWindowMaskGUI::CWindowMaskGUI(MWindow *mwindow, CWindowTool *thread)
2458 : CWindowToolGUI(mwindow, thread,
2459 _(PROGRAM_NAME ": Mask"), 430, 680)
2461 this->mwindow = mwindow;
2462 this->thread = thread;
2470 CWindowMaskGUI::~CWindowMaskGUI()
2472 lock_window("CWindowMaskGUI::~CWindowMaskGUI");
2474 delete active_point;
2480 void CWindowMaskGUI::create_objects()
2482 int x = 10, y = 10, margin = mwindow->theme->widget_border;
2483 int clr_w = CWindowMaskClrMask::calculate_w(mwindow);
2484 int clr_x = get_w()-x - clr_w;
2485 int del_w = CWindowMaskDelMask::calculate_w(this,_("Delete"));
2486 int del_x = clr_x-2*margin - del_w;
2488 lock_window("CWindowMaskGUI::create_objects");
2489 BC_TitleBar *title_bar;
2490 add_subwindow(title_bar = new BC_TitleBar(x, y, get_w()-2*x, 20, 10, _("Masks on Track")));
2491 y += title_bar->get_h() + margin;
2493 add_subwindow(title = new BC_Title(x,y, _("Track:")));
2495 Track *track = mwindow->cwindow->calculate_affected_track();
2496 const char *text = track ? track->title : "";
2497 mwindow->cwindow->mask_track_id = track ? track->get_id() : -1;
2498 mask_on_track = new CWindowMaskOnTrack(mwindow, this, x1, y, 100, text);
2499 mask_on_track->create_objects();
2500 mask_on_track->set_tooltip(_("Video track"));
2501 int x2 = x1 + mask_on_track->get_w();
2502 add_subwindow(mask_track_tumbler = new CWindowMaskTrackTumbler(mwindow, this, x2, y));
2503 mwindow->edl->local_session->solo_track_id = -1;
2504 x2 = del_x + (del_w - CWindowMaskSoloTrack::calculate_w(this)) / 2;
2505 add_subwindow(mask_solo_track = new CWindowMaskSoloTrack(mwindow, this, x2, y, 0));
2506 y += mask_on_track->get_h() + margin;
2507 add_subwindow(title_bar = new BC_TitleBar(x, y, get_w()-2*x, 20, 10, _("Masks")));
2508 y += title_bar->get_h() + margin;
2509 add_subwindow(title = new BC_Title(x, y, _("Mask:")));
2510 mask_name = new CWindowMaskName(mwindow, this, x1, y, "");
2511 mask_name->create_objects();
2512 mask_name->set_tooltip(_("Mask name"));
2513 add_subwindow(clr_mask = new CWindowMaskClrMask(mwindow, this, clr_x, y));
2514 add_subwindow(del_mask = new CWindowMaskDelMask(mwindow, this, del_x, y));
2515 y += mask_name->get_h() + 2*margin;
2517 add_subwindow(title = new BC_Title(x, y, _("Select:")));
2519 BC_CheckBox::calculate_extents(this, &bw, &bh);
2520 int bdx = bw + 2*margin;
2522 for( int i=0; i<SUBMASKS; x2+=bdx, ++i ) {
2523 int v = i == mwindow->edl->session->cwindow_mask ? 1 : 0;
2524 mask_buttons[i] = new CWindowMaskButton(mwindow, this, x2, y, i, v);
2525 add_subwindow(mask_buttons[i]);
2528 add_subwindow(mask_thumbler = new CWindowMaskThumbler(mwindow, this, x2, y));
2531 for( int i=0; i<SUBMASKS; x2+=bdx, ++i ) {
2532 char text[BCSTRLEN]; sprintf(text, "%d", i);
2533 int tx = (bw - get_text_width(MEDIUMFONT, text)) / 2;
2534 mask_blabels[i] = new BC_Title(x2+tx, y, text);
2535 add_subwindow(mask_blabels[i]);
2537 y += mask_blabels[0]->get_h() + margin;
2538 add_subwindow(unclr_mask = new CWindowMaskUnclear(mwindow, this, x, y, x1-x-2*margin));
2540 for( int i=0; i<SUBMASKS; x2+=bdx, ++i ) {
2541 mask_enables[i] = new CWindowMaskEnable(mwindow, this, x2, y, i, 1);
2542 add_subwindow(mask_enables[i]);
2544 y += mask_enables[0]->get_h() + 2*margin;
2545 add_subwindow(title_bar = new BC_TitleBar(x, y, get_w()-2*x, 20, 10, _("Fade & Feather")));
2546 y += title_bar->get_h() + margin;
2548 add_subwindow(title = new BC_Title(x, y, _("Fade:")));
2549 fade = new CWindowMaskFade(mwindow, this, x1, y);
2550 fade->create_objects();
2551 x2 = x1 + fade->get_w() + 2*margin;
2552 int w2 = clr_x-2*margin - x2;
2553 add_subwindow(fade_slider = new CWindowMaskFadeSlider(mwindow, this, x2, y, w2));
2554 add_subwindow(gang_fader = new CWindowMaskGangFader(mwindow, this, clr_x, y));
2555 y += fade->get_h() + margin;
2556 add_subwindow(title = new BC_Title(x, y, _("Feather:")));
2557 feather = new CWindowMaskFeather(mwindow, this, x1, y);
2558 feather->create_objects();
2559 w2 = clr_x - 2*margin - x2;
2560 feather_slider = new CWindowMaskFeatherSlider(mwindow, this, x2, y, w2, 0);
2561 add_subwindow(feather_slider);
2562 add_subwindow(gang_feather = new CWindowMaskGangFeather(mwindow, this, clr_x, y));
2563 y += feather->get_h() + 2*margin;
2564 add_subwindow(title_bar = new BC_TitleBar(x, y, get_w()-2*x, 20, 10, _("Mask Points")));
2565 y += title_bar->get_h() + margin;
2568 add_subwindow(title = new BC_Title(x, y, _("Point:")));
2569 active_point = new CWindowMaskAffectedPoint(mwindow, this, x1, y);
2570 active_point->create_objects();
2571 int x3 = x1 + active_point->get_w() + 4*margin;
2572 // typ=0, this mask, this point
2573 add_subwindow(mask_pnt_linear = new CWindowMaskSmoothButton(mwindow, this,
2574 _("sharp point"), 0, 0, x3, y, "mask_pnt_linear_images"));
2575 int x4 = x3 + mask_pnt_linear->get_w() + 2*margin;
2576 add_subwindow(mask_pnt_smooth = new CWindowMaskSmoothButton(mwindow, this,
2577 _("smooth point"), 0, 1, x4, y, "mask_pnt_smooth_images"));
2578 add_subwindow(del_point = new CWindowMaskDelPoint(mwindow, this, del_x, y));
2579 y += active_point->get_h() + margin;
2580 add_subwindow(title = new BC_Title(x, y, "X:"));
2581 this->x = new CWindowCoord(this, x1, y, (float)0.0);
2582 this->x->create_objects();
2583 // typ>0, this mask, all points
2584 add_subwindow(mask_crv_linear = new CWindowMaskSmoothButton(mwindow, this,
2585 _("sharp curve"), 1, 0, x3, y, "mask_crv_linear_images"));
2586 add_subwindow(mask_crv_smooth = new CWindowMaskSmoothButton(mwindow, this,
2587 _("smooth curve"), 1, 1, x4, y, "mask_crv_smooth_images"));
2588 add_subwindow(draw_markers = new CWindowMaskDrawMarkers(mwindow, this, del_x, y));
2589 y += this->x->get_h() + margin;
2590 add_subwindow(title = new BC_Title(x, y, "Y:"));
2591 this->y = new CWindowCoord(this, x1, y, (float)0.0);
2592 this->y->create_objects();
2593 // typ<0, all masks, all points
2594 add_subwindow(mask_all_linear = new CWindowMaskSmoothButton(mwindow, this,
2595 _("sharp all"), -1, 0, x3, y, "mask_all_linear_images"));
2596 add_subwindow(mask_all_smooth = new CWindowMaskSmoothButton(mwindow, this,
2597 _("smooth all"), -1, 1, x4, y, "mask_all_smooth_images"));
2598 add_subwindow(draw_boundary = new CWindowMaskDrawBoundary(mwindow, this, del_x, y));
2599 y += this->y->get_h() + 2*margin;
2600 add_subwindow(title_bar = new BC_TitleBar(x, y, get_w()-2*x, 20, 10, _("Pivot Point")));
2601 y += title_bar->get_h() + margin;
2603 add_subwindow(title = new BC_Title(x, y, "X:"));
2604 float cx = mwindow->edl->session->output_w / 2.f;
2605 focus_x = new CWindowCoord(this, x1, y, cx);
2606 focus_x->create_objects();
2607 add_subwindow(focus = new CWindowMaskFocus(mwindow, this, del_x, y));
2608 add_subwindow(gang_focus = new CWindowMaskGangFocus(mwindow, this, clr_x, y));
2609 y += focus_x->get_h() + margin;
2610 add_subwindow(title = new BC_Title(x, y, "Y:"));
2611 float cy = mwindow->edl->session->output_h / 2.f;
2612 focus_y = new CWindowCoord(this, x1, y, cy);
2613 focus_y->create_objects();
2614 y += focus_x->get_h() + 2*margin;
2616 add_subwindow(bar = new BC_Bar(x, y, get_w()-2*x));
2617 y += bar->get_h() + margin;
2618 add_subwindow(this->apply_before_plugins = new CWindowMaskBeforePlugins(this, 10, y));
2619 y += this->apply_before_plugins->get_h();
2620 add_subwindow(this->disable_opengl_masking = new CWindowDisableOpenGLMasking(this, 10, y));
2621 add_subwindow(help = new CWindowMaskHelp(mwindow, this, del_x, y));
2622 y += this->disable_opengl_masking->get_h() + 2*margin;
2624 add_subwindow(new BC_Bar(x, y, get_w()-2*x));
2625 y += bar->get_h() + 2*margin;
2626 add_subwindow(title = new BC_Title(x, y, _(
2627 "Shift+LMB: move an end point\n"
2628 "Ctrl+LMB: move a control point\n"
2629 "Alt+LMB: to drag translate the mask\n"
2630 "Shift+Key Delete: to delete the point\n"
2631 "Shift+MMB: Set Pivot Point at pointer\n"
2632 "Wheel: rotate around Pivot Point\n"
2633 "Shift+Wheel: scale around Pivot Point\n"
2634 "Ctrl+Wheel: rotate/scale around pointer")));
2635 help_h = y + title->get_h() + 2*margin;
2637 resize_window(get_w(), help_y);
2641 int CWindowMaskGUI::close_event()
2644 return CWindowToolGUI::close_event();
2647 void CWindowMaskGUI::done_event()
2649 if( mwindow->in_destructor ) return;
2650 int &solo_track_id = mwindow->edl->local_session->solo_track_id;
2651 if( solo_track_id >= 0 ) {
2657 void CWindowMaskGUI::get_keyframe(Track* &track,
2658 MaskAutos* &autos, MaskAuto* &keyframe,
2659 SubMask* &mask, MaskPoint* &point, int create_it)
2664 track = mwindow->cwindow->calculate_mask_track();
2666 track = mwindow->cwindow->calculate_affected_track();
2669 autos = (MaskAutos*)track->automation->autos[AUTOMATION_MASK];
2670 keyframe = (MaskAuto*)mwindow->cwindow->calculate_affected_auto(
2675 mask = !keyframe ? 0 :
2676 keyframe->get_submask(mwindow->edl->session->cwindow_mask);
2680 if( mwindow->cwindow->gui->affected_point < mask->points.total &&
2681 mwindow->cwindow->gui->affected_point >= 0 ) {
2682 point = mask->points.values[mwindow->cwindow->gui->affected_point];
2687 void CWindowMaskGUI::update()
2694 //printf("CWindowMaskGUI::update 1\n");
2695 get_keyframe(track, autos, keyframe, mask, point, 0);
2696 mwindow->cwindow->mask_track_id = track ? track->get_id() : -1;
2697 mask_on_track->set_back_color(!track || track->record ?
2698 get_resources()->text_background :
2699 get_resources()->text_background_disarmed);
2700 mask_on_track->update_items();
2701 mask_on_track->update(!track ? "" : track->title);
2702 mask_name->update_items(keyframe);
2703 const char *text = "";
2704 int sz = !keyframe ? 0 : keyframe->masks.size();
2705 int k = mwindow->edl->session->cwindow_mask;
2706 if( k >= 0 && k < sz )
2707 text = keyframe->masks[k]->name;
2709 k = mwindow->edl->session->cwindow_mask = 0;
2710 mask_name->update(text);
2711 update_buttons(keyframe, k);
2713 x->update(point->x);
2714 y->update(point->y);
2717 double position = mwindow->edl->local_session->get_selectionstart(1);
2718 int64_t position_i = track->to_units(position, 0);
2719 feather->update(autos->get_feather(position_i, k, PLAY_FORWARD));
2720 fade->update(autos->get_fader(position_i, k, PLAY_FORWARD));
2721 int show_mask = track->masks;
2722 for( int i=0; i<SUBMASKS; ++i )
2723 mask_enables[i]->update((show_mask>>i) & 1);
2726 apply_before_plugins->update(keyframe->apply_before_plugins);
2727 disable_opengl_masking->update(keyframe->disable_opengl_masking);
2729 active_point->update((int64_t)mwindow->cwindow->gui->affected_point);
2732 void CWindowMaskGUI::handle_event()
2739 get_keyframe(track, autos, keyframe, mask, point, 0);
2741 mwindow->undo->update_undo_before(_("mask point"), this);
2745 #ifdef USE_KEYFRAME_SPANNING
2746 // Create temp keyframe
2747 MaskAuto temp_keyframe(mwindow->edl, autos);
2748 temp_keyframe.copy_data(keyframe);
2749 // Get affected point in temp keyframe
2750 mask = temp_keyframe.get_submask(mwindow->edl->session->cwindow_mask);
2751 if(mwindow->cwindow->gui->affected_point < mask->points.total &&
2752 mwindow->cwindow->gui->affected_point >= 0)
2754 point = mask->points.values[mwindow->cwindow->gui->affected_point];
2759 point->x = atof(x->get_text());
2760 point->y = atof(y->get_text());
2761 // Commit to spanned keyframes
2762 autos->update_parameter(&temp_keyframe);
2765 point->x = atof(x->get_text());
2766 point->y = atof(y->get_text());
2771 mwindow->undo->update_undo_after(_("mask point"), LOAD_AUTOMATION);
2774 void CWindowMaskGUI::set_focused(int v, float cx, float cy)
2776 CWindowGUI *cgui = mwindow->cwindow->gui;
2777 cgui->unlock_window();
2778 lock_window("CWindowMaskGUI::set_focused");
2780 focus->update(focused = v);
2781 focus_x->update(cx);
2782 focus_y->update(cy);
2784 cgui->lock_window("CWindowCanvas::set_focused");
2787 void CWindowMaskGUI::update_buttons(MaskAuto *keyframe, int k)
2789 int text_color = get_resources()->default_text_color;
2790 int high_color = get_resources()->button_highlighted;
2791 for( int i=0; i<SUBMASKS; ++i ) {
2792 int color = text_color;
2794 SubMask *submask = keyframe->get_submask(i);
2795 if( submask && submask->points.size() )
2798 mask_blabels[i]->set_color(color);
2799 mask_buttons[i]->update(i==k ? 1 : 0);
2803 // typ=0, this mask, this point
2804 // typ>0, this mask, all points
2805 // typ<0, all masks, all points
2806 // dxy= on? pt[+1]-pt[-1] : dxy=0
2807 int CWindowMaskGUI::smooth_mask(int typ, int on)
2814 #ifdef USE_KEYFRAME_SPANNING
2820 mwindow->undo->update_undo_before(_("mask smooth"), this);
2822 // Get existing keyframe
2823 get_keyframe(track, autos, keyframe,
2824 mask, point, create_it);
2826 #ifdef USE_KEYFRAME_SPANNING
2827 MaskAuto temp_keyframe(mwindow->edl, autos);
2828 temp_keyframe.copy_data(keyframe);
2829 keyframe = &temp_keyframe;
2831 int k = mwindow->edl->session->cwindow_mask;
2832 int n = typ>=0 ? k+1 : keyframe->masks.size();
2833 for( int j=typ<0? 0 : k; j<n; ++j ) {
2834 SubMask *sub_mask = keyframe->get_submask(j);
2835 ArrayList<MaskPoint*> &points = sub_mask->points;
2836 int psz = points.size();
2837 if( psz < 3 ) continue;
2838 int l = mwindow->cwindow->gui->affected_point;
2839 int m = typ ? psz : l+1;
2840 for( int i=typ<0? 0 : l; i<m; ++i ) {
2841 int i0 = i-1, i1 = i+1;
2842 if( i0 < 0 ) i0 = psz-1;
2843 if( i1 >= psz ) i1 = 0;
2844 MaskPoint *p0 = points[i0];
2845 MaskPoint *p = points[i];
2846 MaskPoint *p1 = points[i1];
2847 float dx = !on ? 0 : p1->x - p0->x;
2848 float dy = !on ? 0 : p1->y - p0->y;
2849 p->control_x1 = -dx/4; p->control_y1 = -dy/4;
2850 p->control_x2 = dx/4; p->control_y2 = dy/4;
2853 #ifdef USE_KEYFRAME_SPANNING
2854 autos->update_parameter(keyframe);
2859 mwindow->undo->update_undo_after(_("mask smooth"), LOAD_AUTOMATION);
2863 CWindowRulerGUI::CWindowRulerGUI(MWindow *mwindow, CWindowTool *thread)
2864 : CWindowToolGUI(mwindow, thread, _(PROGRAM_NAME ": Ruler"), 320, 240)
2868 CWindowRulerGUI::~CWindowRulerGUI()
2872 void CWindowRulerGUI::create_objects()
2874 int x = 10, y = 10, x1 = 100;
2877 lock_window("CWindowRulerGUI::create_objects");
2878 add_subwindow(title = new BC_Title(x, y, _("Current:")));
2879 add_subwindow(current = new BC_TextBox(x1, y, 200, 1, ""));
2880 y += title->get_h() + 5;
2881 add_subwindow(title = new BC_Title(x, y, _("Point 1:")));
2882 add_subwindow(point1 = new BC_TextBox(x1, y, 200, 1, ""));
2883 y += title->get_h() + 5;
2884 add_subwindow(title = new BC_Title(x, y, _("Point 2:")));
2885 add_subwindow(point2 = new BC_TextBox(x1, y, 200, 1, ""));
2886 y += title->get_h() + 5;
2887 add_subwindow(title = new BC_Title(x, y, _("Deltas:")));
2888 add_subwindow(deltas = new BC_TextBox(x1, y, 200, 1, ""));
2889 y += title->get_h() + 5;
2890 add_subwindow(title = new BC_Title(x, y, _("Distance:")));
2891 add_subwindow(distance = new BC_TextBox(x1, y, 200, 1, ""));
2892 y += title->get_h() + 5;
2893 add_subwindow(title = new BC_Title(x, y, _("Angle:")));
2894 add_subwindow(angle = new BC_TextBox(x1, y, 200, 1, ""));
2895 y += title->get_h() + 10;
2896 char string[BCTEXTLEN];
2898 _("Press Ctrl to lock ruler to the\nnearest 45%c%c angle."),
2899 0xc2, 0xb0); // degrees utf
2900 add_subwindow(title = new BC_Title(x,
2903 y += title->get_h() + 10;
2904 sprintf(string, _("Press Alt to translate the ruler."));
2905 add_subwindow(title = new BC_Title(x,
2912 void CWindowRulerGUI::update()
2914 char string[BCTEXTLEN];
2915 int cx = mwindow->session->cwindow_output_x;
2916 int cy = mwindow->session->cwindow_output_y;
2917 sprintf(string, "%d, %d", cx, cy);
2918 current->update(string);
2919 double x1 = mwindow->edl->session->ruler_x1;
2920 double y1 = mwindow->edl->session->ruler_y1;
2921 sprintf(string, "%.0f, %.0f", x1, y1);
2922 point1->update(string);
2923 double x2 = mwindow->edl->session->ruler_x2;
2924 double y2 = mwindow->edl->session->ruler_y2;
2925 sprintf(string, "%.0f, %.0f", x2, y2);
2926 point2->update(string);
2927 double dx = x2 - x1, dy = y2 - y1;
2928 sprintf(string, "%s%.0f, %s%.0f", (dx>=0? "+":""), dx, (dy>=0? "+":""), dy);
2929 deltas->update(string);
2930 double d = sqrt(dx*dx + dy*dy);
2931 sprintf(string, _("%0.01f pixels"), d);
2932 distance->update(string);
2933 double a = d > 0 ? (atan2(-dy, dx) * 180/M_PI) : 0.;
2934 sprintf(string, "%0.02f %c%c", a, 0xc2, 0xb0);
2935 angle->update(string);
2938 void CWindowRulerGUI::handle_event()