3 * Copyright (C) 2008-2017 Adam Williams <broadcast at earthling dot net>
4 * Copyright (C) 2003-2016 Cinelerra CV contributors
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.
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.
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
25 #include "automation.h"
29 #include "condition.h"
31 #include "cplayback.h"
33 #include "cwindowgui.h"
34 #include "cwindowtool.h"
36 #include "edlsession.h"
39 #include "floatauto.h"
40 #include "floatautos.h"
41 #include "gwindowgui.h"
44 #include "localsession.h"
45 #include "mainsession.h"
48 #include "maskautos.h"
51 #include "mwindowgui.h"
55 #include "trackcanvas.h"
56 #include "transportque.h"
60 CWindowTool::CWindowTool(MWindow *mwindow, CWindowGUI *gui)
63 this->mwindow = mwindow;
67 current_tool = CWINDOW_NONE;
69 input_lock = new Condition(0, "CWindowTool::input_lock");
70 output_lock = new Condition(1, "CWindowTool::output_lock");
71 tool_gui_lock = new Mutex("CWindowTool::tool_gui_lock");
74 CWindowTool::~CWindowTool()
85 void CWindowTool::start_tool(int operation)
87 CWindowToolGUI *new_gui = 0;
90 //printf("CWindowTool::start_tool 1\n");
91 if(current_tool != operation)
93 int previous_tool = current_tool;
94 current_tool = operation;
98 new_gui = new CWindowEyedropGUI(mwindow, this);
101 new_gui = new CWindowCropGUI(mwindow, this);
104 new_gui = new CWindowCameraGUI(mwindow, this);
106 case CWINDOW_PROJECTOR:
107 new_gui = new CWindowProjectorGUI(mwindow, this);
110 new_gui = new CWindowMaskGUI(mwindow, this);
113 new_gui = new CWindowRulerGUI(mwindow, this);
115 case CWINDOW_PROTECT:
116 mwindow->edl->session->tool_window = 0;
117 gui->composite_panel->operation[CWINDOW_TOOL_WINDOW]->update(0);
125 //printf("CWindowTool::start_tool 1\n");
131 // Wait for previous tool GUI to finish
132 output_lock->lock("CWindowTool::start_tool");
133 this->tool_gui = new_gui;
134 tool_gui->create_objects();
135 if( previous_tool == CWINDOW_PROTECT || previous_tool == CWINDOW_NONE ) {
136 mwindow->edl->session->tool_window = 1;
137 gui->composite_panel->operation[CWINDOW_TOOL_WINDOW]->update(1);
139 mwindow->edl->session->tool_window = new_gui ? 1 : 0;
140 update_show_window();
142 // Signal thread to run next tool GUI
143 input_lock->unlock();
145 //printf("CWindowTool::start_tool 1\n");
150 tool_gui->lock_window("CWindowTool::start_tool");
152 tool_gui->unlock_window();
155 //printf("CWindowTool::start_tool 2\n");
160 void CWindowTool::stop_tool()
164 tool_gui->lock_window("CWindowTool::stop_tool");
165 tool_gui->set_done(0);
166 tool_gui->unlock_window();
170 void CWindowTool::show_tool()
172 if(tool_gui && mwindow->edl->session->tool_window)
174 tool_gui->lock_window("CWindowTool::show_tool");
175 tool_gui->show_window();
176 tool_gui->unlock_window();
180 void CWindowTool::hide_tool()
182 if(tool_gui && mwindow->edl->session->tool_window)
184 tool_gui->lock_window("CWindowTool::show_tool");
185 tool_gui->hide_window();
186 tool_gui->unlock_window();
190 void CWindowTool::raise_tool()
192 if(tool_gui && mwindow->edl->session->tool_window)
194 tool_gui->lock_window("CWindowTool::show_tool");
195 tool_gui->raise_window();
196 tool_gui->unlock_window();
201 void CWindowTool::run()
205 input_lock->lock("CWindowTool::run");
208 tool_gui->run_window();
209 tool_gui_lock->lock("CWindowTool::run");
212 tool_gui_lock->unlock();
214 output_lock->unlock();
218 void CWindowTool::update_show_window()
222 tool_gui->lock_window("CWindowTool::update_show_window");
224 if(mwindow->edl->session->tool_window)
227 tool_gui->show_window();
230 tool_gui->hide_window();
233 tool_gui->unlock_window();
237 void CWindowTool::raise_window()
241 gui->unlock_window();
242 tool_gui->lock_window("CWindowTool::raise_window");
243 tool_gui->raise_window();
244 tool_gui->unlock_window();
245 gui->lock_window("CWindowTool::raise_window");
249 void CWindowTool::update_values()
251 tool_gui_lock->lock("CWindowTool::update_values");
254 tool_gui->lock_window("CWindowTool::update_values");
257 tool_gui->unlock_window();
259 tool_gui_lock->unlock();
268 CWindowToolGUI::CWindowToolGUI(MWindow *mwindow,
269 CWindowTool *thread, const char *title, int w, int h)
271 mwindow->session->ctool_x, mwindow->session->ctool_y,
274 this->mwindow = mwindow;
275 this->thread = thread;
276 current_operation = 0;
280 CWindowToolGUI::~CWindowToolGUI()
284 int CWindowToolGUI::close_event()
288 mwindow->edl->session->tool_window = 0;
290 thread->gui->lock_window("CWindowToolGUI::close_event");
291 thread->gui->composite_panel->set_operation(mwindow->edl->session->cwindow_operation);
292 thread->gui->flush();
293 thread->gui->unlock_window();
294 lock_window("CWindowToolGUI::close_event");
298 int CWindowToolGUI::keypress_event()
302 switch( get_keypress() ) {
305 return close_event();
318 resend_event(thread->gui);
322 if( result ) return result;
323 return context_help_check_and_show();
326 int CWindowToolGUI::translation_event()
328 mwindow->session->ctool_x = get_x();
329 mwindow->session->ctool_y = get_y();
333 void CWindowToolGUI::update_auto(Track *track, int idx, CWindowCoord *vp)
335 FloatAuto *float_auto = (FloatAuto*)mwindow->cwindow->calculate_affected_auto(
336 track->automation->autos[idx], 1);
337 if( !float_auto ) return;
338 float v = float_auto->get_value(edge);
339 float t = atof(vp->get_text());
341 float_auto->bump_value(t, edge, span);
342 if( idx == AUTOMATION_PROJECTOR_Z || idx == AUTOMATION_CAMERA_Z ) {
343 mwindow->gui->lock_window("CWindowToolGUI::update_auto");
344 mwindow->gui->draw_overlays(1);
345 mwindow->gui->unlock_window();
351 void CWindowToolGUI::update_preview(int changed_edl)
354 draw_preview(changed_edl);
355 lock_window("CWindowToolGUI::update_preview");
358 void CWindowToolGUI::draw_preview(int changed_edl)
360 CWindowGUI *cgui = mwindow->cwindow->gui;
361 cgui->lock_window("CWindowToolGUI::draw_preview");
362 int change_type = !changed_edl ? CHANGE_PARAMS : CHANGE_EDL;
363 cgui->sync_parameters(change_type, 0, 1);
364 cgui->unlock_window();
368 CWindowCoord::CWindowCoord(CWindowToolGUI *gui, int x, int y, float value, int type)
369 : BC_TumbleTextBox(gui, (float)value, (float)-65536, (float)65536, x, y, xS(70), 3)
377 CWindowCoord::CWindowCoord(CWindowToolGUI *gui, int x, int y, int value, int type)
378 : BC_TumbleTextBox(gui, (int64_t)value, (int64_t)-65536, (int64_t)65536, x, y, xS(70))
386 void CWindowCoord::create_objects()
388 BC_TumbleTextBox::create_objects();
390 float v = atof(get_text());
392 int x1 = get_x() + BC_TumbleTextBox::get_w() + xs10, y1 = get_y();
393 gui->add_subwindow(min_tumbler = new CWindowToolAutoRangeTumbler(this, x1, y1,
395 x1 += min_tumbler->get_w() + xs10;
396 int group = Automation::autogrouptype(type, 0);
397 float min = gui->mwindow->edl->local_session->automation_mins[group];
398 float max = gui->mwindow->edl->local_session->automation_maxs[group];
399 gui->add_subwindow(slider = new CWindowCoordSlider(this,
400 x1, y1, xS(150), min, max, v));
401 x1 += slider->get_w() + xS(10);
402 gui->add_subwindow(max_tumbler = new CWindowToolAutoRangeTumbler(this, x1, y1,
404 x1 += max_tumbler->get_w() + xS(10);
405 gui->add_subwindow(range_reset = new CWindowToolAutoRangeReset(this, x1, y1));
406 x1 += range_reset->get_w() + xS(10);
407 gui->add_subwindow(range_text = new CWindowToolAutoRangeTextBox(this, x1, y1));
408 range_text->update_range();
409 x1 += range_text->get_w() + xS(10);
410 gui->add_subwindow(range = new CWindowCoordRangeTumbler(this, x1, y1));
414 void CWindowCoord::update_gui(float value)
416 BC_TumbleTextBox::update(value);
418 int group = Automation::autogrouptype(type, 0);
419 LocalSession *local_session = gui->mwindow->edl->local_session;
420 slider->update(slider->get_pointer_motion_range(), value,
421 local_session->automation_mins[group],
422 local_session->automation_maxs[group]);
423 int x1 = range->get_x() + range->get_w() + xS(5);
424 int y1 = range->get_y() + yS(5), d = xS(16);
425 gui->set_color(GWindowGUI::auto_colors[type]);
426 gui->draw_disc(x1, y1, d, d);
430 int CWindowCoord::handle_event()
433 slider->update(atof(get_text()));
434 gui->event_caller = this;
439 CWindowCoordSlider::CWindowCoordSlider(CWindowCoord *coord,
440 int x, int y, int w, float mn, float mx, float value)
441 : BC_FSlider(x, y, 0, w, w, mn, mx, value)
447 CWindowCoordSlider::~CWindowCoordSlider()
451 int CWindowCoordSlider::handle_event()
453 float value = get_value();
454 coord->update(value);
455 coord->gui->event_caller = coord;
456 coord->gui->handle_event();
460 CWindowCoordRangeTumbler::CWindowCoordRangeTumbler(CWindowCoord *coord, int x, int y)
465 CWindowCoordRangeTumbler::~CWindowCoordRangeTumbler()
469 int CWindowCoordRangeTumbler::update(float scale)
471 CWindowCoordSlider *slider = coord->slider;
472 MWindow *mwindow = coord->gui->mwindow;
473 LocalSession *local_session = mwindow->edl->local_session;
474 int group = Automation::autogrouptype(coord->type, 0);
475 float min = local_session->automation_mins[group];
476 float max = local_session->automation_maxs[group];
479 case AUTOGROUPTYPE_ZOOM: min = 0.005; max = 5.0; break;
480 case AUTOGROUPTYPE_X: min = -1000; max = 1000; break;
481 case AUTOGROUPTYPE_Y: min = -1000; max = 1000; break;
485 case AUTOGROUPTYPE_ZOOM: { // exp
486 float lmin = log(min), lmax = log(max);
487 float lr = (lmax - lmin) * scale;
488 if( (min = exp(lmin - lr)) < ZOOM_MIN ) min = ZOOM_MIN;
489 if( (max = exp(lmax + lr)) > ZOOM_MAX ) max = ZOOM_MAX;
491 case AUTOGROUPTYPE_X:
492 case AUTOGROUPTYPE_Y: { // linear
493 float dr = (max - min) * scale;
494 if( (min -= dr) < XY_MIN ) min = XY_MIN;
495 if( (max += dr) > XY_MAX ) max = XY_MAX;
498 slider->update(slider->get_pointer_motion_range(),
499 slider->get_value(), min, max);
501 MWindowGUI *mgui = mwindow->gui;
502 mgui->lock_window("CWindowCoordRangeTumbler::update");
503 local_session->zoombar_showautotype = group;
504 local_session->automation_mins[group] = min;
505 local_session->automation_maxs[group] = max;
506 mgui->zoombar->update_autozoom();
507 mgui->draw_overlays(0);
508 mgui->update_patchbay();
509 mgui->flash_canvas(1);
510 mgui->unlock_window();
511 lock_window("CWindowCoordRangeTumbler::update");
512 return coord->range_text->update_range();
515 int CWindowCoordRangeTumbler::handle_up_event()
517 return update(0.125);
519 int CWindowCoordRangeTumbler::handle_down_event()
524 CWindowCropApply::CWindowCropApply(MWindow *mwindow, CWindowCropGUI *crop_gui, int x, int y)
525 : BC_GenericButton(x, y, _("Apply"))
527 this->mwindow = mwindow;
528 this->crop_gui = crop_gui;
530 int CWindowCropApply::handle_event()
532 mwindow->crop_video(crop_gui->crop_mode->mode);
537 int CWindowCropApply::keypress_event()
539 if(get_keypress() == 0xd)
544 return context_help_check_and_show();
547 const char *CWindowCropOpMode::crop_ops[] = {
553 CWindowCropOpMode::CWindowCropOpMode(MWindow *mwindow, CWindowCropGUI *crop_gui,
554 int mode, int x, int y)
555 : BC_PopupMenu(x, y, xS(140), _(crop_ops[mode]), 1)
557 this->mwindow = mwindow;
558 this->crop_gui = crop_gui;
561 CWindowCropOpMode::~CWindowCropOpMode()
565 void CWindowCropOpMode::create_objects()
567 for( int id=0,nid=sizeof(crop_ops)/sizeof(crop_ops[0]); id<nid; ++id )
568 add_item(new CWindowCropOpItem(this, _(crop_ops[id]), id));
572 int CWindowCropOpMode::handle_event()
574 set_text(_(crop_ops[mode]));
578 CWindowCropOpItem::CWindowCropOpItem(CWindowCropOpMode *popup, const char *text, int id)
585 int CWindowCropOpItem::handle_event()
587 popup->set_text(get_text());
589 return popup->handle_event();
596 CWindowCropGUI::CWindowCropGUI(MWindow *mwindow, CWindowTool *thread)
597 : CWindowToolGUI(mwindow, thread, _(PROGRAM_NAME ": Crop"), xS(330), yS(100))
599 // *** CONTEXT_HELP ***
600 context_help_set_keyword("Cropping");
604 CWindowCropGUI::~CWindowCropGUI()
608 void CWindowCropGUI::create_objects()
610 int xs5 = xS(5), xs10 = xS(10);
611 int ys5 = yS(5), ys10 = yS(10);
612 int x = xs10, y = ys10;
615 lock_window("CWindowCropGUI::create_objects");
617 int pad = MAX(BC_TextBox::calculate_h(this, MEDIUMFONT, 1, 1),
618 BC_Title::calculate_h(this, "X")) + ys5;
619 add_subwindow(title = new BC_Title(x, y, "X1:"));
620 column1 = MAX(column1, title->get_w());
622 add_subwindow(title = new BC_Title(x, y, _("W:")));
623 column1 = MAX(column1, title->get_w());
625 add_subwindow(new CWindowCropApply(mwindow, this, x, y));
629 x1 = new CWindowCoord(thread->tool_gui, x, y,
630 mwindow->edl->session->crop_x1);
631 x1->create_objects();
632 x1->set_boundaries((int64_t)0, (int64_t)65536);
634 width = new CWindowCoord(thread->tool_gui, x, y,
635 mwindow->edl->session->crop_x2 - mwindow->edl->session->crop_x1);
636 width->create_objects();
637 width->set_boundaries((int64_t)1, (int64_t)65536);
640 x += x1->get_w() + xs10;
643 add_subwindow(title = new BC_Title(x, y, "Y1:"));
644 column2 = MAX(column2, title->get_w());
646 add_subwindow(title = new BC_Title(x, y, _("H:")));
647 column2 = MAX(column2, title->get_w());
652 y1 = new CWindowCoord(thread->tool_gui, x, y,
653 mwindow->edl->session->crop_y1);
654 y1->create_objects();
655 y1->set_boundaries((int64_t)0, (int64_t)65536);
658 height = new CWindowCoord(thread->tool_gui, x, y,
659 mwindow->edl->session->crop_y2 - mwindow->edl->session->crop_y1);
660 height->create_objects();
661 height->set_boundaries((int64_t)1, (int64_t)65536);
664 add_subwindow(crop_mode = new CWindowCropOpMode(mwindow, this,
665 CROP_REFORMAT, x, y));
666 crop_mode->create_objects();
671 void CWindowCropGUI::handle_event()
674 new_x1 = atol(x1->get_text());
675 new_y1 = atol(y1->get_text());
676 if(new_x1 != mwindow->edl->session->crop_x1)
678 mwindow->edl->session->crop_x2 = new_x1 +
679 mwindow->edl->session->crop_x2 -
680 mwindow->edl->session->crop_x1;
681 mwindow->edl->session->crop_x1 = new_x1;
683 if(new_y1 != mwindow->edl->session->crop_y1)
685 mwindow->edl->session->crop_y2 = new_y1 +
686 mwindow->edl->session->crop_y2 -
687 mwindow->edl->session->crop_y1;
688 mwindow->edl->session->crop_y1 = atol(y1->get_text());
690 mwindow->edl->session->crop_x2 = atol(width->get_text()) +
691 mwindow->edl->session->crop_x1;
692 mwindow->edl->session->crop_y2 = atol(height->get_text()) +
693 mwindow->edl->session->crop_y1;
695 mwindow->cwindow->gui->canvas->redraw(1);
698 void CWindowCropGUI::update()
700 x1->update((int64_t)mwindow->edl->session->crop_x1);
701 y1->update((int64_t)mwindow->edl->session->crop_y1);
702 width->update((int64_t)mwindow->edl->session->crop_x2 -
703 mwindow->edl->session->crop_x1);
704 height->update((int64_t)mwindow->edl->session->crop_y2 -
705 mwindow->edl->session->crop_y1);
709 CWindowEyedropGUI::CWindowEyedropGUI(MWindow *mwindow, CWindowTool *thread)
710 : CWindowToolGUI(mwindow, thread, _(PROGRAM_NAME ": Color"), xS(220), yS(290))
712 // *** CONTEXT_HELP ***
713 context_help_set_keyword("Compositor Toolbar");
716 CWindowEyedropGUI::~CWindowEyedropGUI()
720 void CWindowEyedropGUI::create_objects()
722 int xs10 = xS(10), ys10 = yS(10);
723 int margin = mwindow->theme->widget_border;
724 int x = xs10 + margin;
725 int y = ys10 + margin;
726 int x2 = xS(70), x3 = x2 + xS(60);
727 lock_window("CWindowEyedropGUI::create_objects");
728 BC_Title *title0, *title1, *title2, *title3, *title4, *title5, *title6, *title7;
729 add_subwindow(title0 = new BC_Title(x, y,_("X,Y:")));
730 y += title0->get_h() + margin;
731 add_subwindow(title7 = new BC_Title(x, y, _("Radius:")));
732 y += BC_TextBox::calculate_h(this, MEDIUMFONT, 1, 1) + margin;
734 add_subwindow(title1 = new BC_Title(x, y, _("Red:")));
735 y += title1->get_h() + margin;
736 add_subwindow(title2 = new BC_Title(x, y, _("Green:")));
737 y += title2->get_h() + margin;
738 add_subwindow(title3 = new BC_Title(x, y, _("Blue:")));
739 y += title3->get_h() + margin;
741 add_subwindow(title4 = new BC_Title(x, y, "Y:"));
742 y += title4->get_h() + margin;
743 add_subwindow(title5 = new BC_Title(x, y, "U:"));
744 y += title5->get_h() + margin;
745 add_subwindow(title6 = new BC_Title(x, y, "V:"));
747 add_subwindow(current = new BC_Title(x2, title0->get_y(), ""));
749 radius = new CWindowCoord(this, x2, title7->get_y(),
750 mwindow->edl->session->eyedrop_radius);
751 radius->create_objects();
752 radius->set_boundaries((int64_t)0, (int64_t)255);
754 add_subwindow(red = new BC_Title(x2, title1->get_y(), "0"));
755 add_subwindow(green = new BC_Title(x2, title2->get_y(), "0"));
756 add_subwindow(blue = new BC_Title(x2, title3->get_y(), "0"));
757 add_subwindow(rgb_hex = new BC_Title(x3, red->get_y(), "#000000"));
759 add_subwindow(this->y = new BC_Title(x2, title4->get_y(), "0"));
760 add_subwindow(this->u = new BC_Title(x2, title5->get_y(), "0"));
761 add_subwindow(this->v = new BC_Title(x2, title6->get_y(), "0"));
762 add_subwindow(yuv_hex = new BC_Title(x3, this->y->get_y(), "#000000"));
764 y = title6->get_y() + this->v->get_h() + 2*margin;
765 add_subwindow(sample = new BC_SubWindow(x, y, xS(50), yS(50)));
766 y += sample->get_h() + margin;
767 add_subwindow(use_max = new CWindowEyedropCheckBox(mwindow, this, x, y));
772 void CWindowEyedropGUI::update()
774 char string[BCTEXTLEN];
775 sprintf(string, "%d, %d",
776 thread->gui->eyedrop_x,
777 thread->gui->eyedrop_y);
778 current->update(string);
780 radius->update((int64_t)mwindow->edl->session->eyedrop_radius);
782 LocalSession *local_session = mwindow->edl->local_session;
783 int use_max = local_session->use_max;
784 float r = use_max ? local_session->red_max : local_session->red;
785 float g = use_max ? local_session->green_max : local_session->green;
786 float b = use_max ? local_session->blue_max : local_session->blue;
787 this->red->update(r);
788 this->green->update(g);
789 this->blue->update(b);
791 int rx = 255*r + 0.5; bclamp(rx,0,255);
792 int gx = 255*g + 0.5; bclamp(gx,0,255);
793 int bx = 255*b + 0.5; bclamp(bx,0,255);
794 char rgb_text[BCSTRLEN];
795 sprintf(rgb_text, "#%02x%02x%02x", rx, gx, bx);
796 rgb_hex->update(rgb_text);
799 YUV::yuv.rgb_to_yuv_f(r, g, b, y, u, v);
801 this->u->update(u += 0.5);
802 this->v->update(v += 0.5);
804 int yx = 255*y + 0.5; bclamp(yx,0,255);
805 int ux = 255*u + 0.5; bclamp(ux,0,255);
806 int vx = 255*v + 0.5; bclamp(vx,0,255);
807 char yuv_text[BCSTRLEN];
808 sprintf(yuv_text, "#%02x%02x%02x", yx, ux, vx);
809 yuv_hex->update(yuv_text);
811 int rgb = (rx << 16) | (gx << 8) | (bx << 0);
812 sample->set_color(rgb);
813 sample->draw_box(0, 0, sample->get_w(), sample->get_h());
814 sample->set_color(BLACK);
815 sample->draw_rectangle(0, 0, sample->get_w(), sample->get_h());
819 void CWindowEyedropGUI::handle_event()
821 int new_radius = atoi(radius->get_text());
822 if(new_radius != mwindow->edl->session->eyedrop_radius)
824 CWindowGUI *gui = mwindow->cwindow->gui;
825 if(gui->eyedrop_visible)
827 gui->lock_window("CWindowEyedropGUI::handle_event");
830 gui->canvas->do_eyedrop(rerender, 0, 1);
833 mwindow->edl->session->eyedrop_radius = new_radius;
835 if(gui->eyedrop_visible)
839 gui->canvas->do_eyedrop(rerender, 0, 1);
840 gui->unlock_window();
847 /* Buttons to control Keyframe-Curve-Mode for Projector or Camera */
849 // Configuration for all possible Keyframe Curve Mode toggles
851 FloatAuto::t_mode mode;
857 const _CVD Camera_Crv_Smooth = { FloatAuto::SMOOTH, true, "tan_smooth",
858 N_("\"smooth\" Curve on current Camera Keyframes") };
859 const _CVD Camera_Crv_Linear = { FloatAuto::LINEAR, true, "tan_linear",
860 N_("\"linear\" Curve on current Camera Keyframes") };
861 const _CVD Camera_Crv_Tangent = { FloatAuto::TFREE, true, "tan_tangent",
862 N_("\"tangent\" Curve on current Camera Keyframes") };
863 const _CVD Camera_Crv_Free = { FloatAuto::FREE, true, "tan_free",
864 N_("\"free\" Curve on current Camera Keyframes") };
865 const _CVD Camera_Crv_Bump = { FloatAuto::BUMP, true, "tan_bump",
866 N_("\"bump\" Curve on current Camera Keyframes") };
868 const _CVD Projector_Crv_Smooth = { FloatAuto::SMOOTH, false, "tan_smooth",
869 N_("\"smooth\" Curve on current Projector Keyframes") };
870 const _CVD Projector_Crv_Linear = { FloatAuto::LINEAR, false, "tan_linear",
871 N_("\"linear\" Curve on current Projector Keyframes") };
872 const _CVD Projector_Crv_Tangent = { FloatAuto::TFREE, false, "tan_tangent",
873 N_("\"tangent\" Curve on current Projector Keyframes") };
874 const _CVD Projector_Crv_Free = { FloatAuto::FREE, false, "tan_free",
875 N_("\"free\" Curve on current Projector Keyframes") };
876 const _CVD Projector_Crv_Bump = { FloatAuto::BUMP, false, "tan_bump",
877 N_("\"bump\" Curve on current Projector Keyframes") };
879 // Implementation Class für Keyframe Curve Mode buttons
881 // This button reflects the state of the "current" keyframe
882 // (the nearest keyframe on the left) for all three automation
883 // lines together. Clicking on this button (re)sets the curve
884 // mode for the three "current" keyframes simultanously, but
885 // never creates a new keyframe.
887 class CWindowCurveToggle : public BC_Toggle
890 CWindowCurveToggle(const _CVD &mode,
891 MWindow *mwindow, CWindowToolGUI *gui, int x, int y);
892 void check_toggle_state(FloatAuto *x, FloatAuto *y, FloatAuto *z);
901 CWindowCurveToggle::CWindowCurveToggle(const _CVD &mode,
902 MWindow *mwindow, CWindowToolGUI *gui, int x, int y)
903 : BC_Toggle(x, y, mwindow->theme->get_image_set(mode.icon_id), false),
907 this->mwindow = mwindow;
908 set_tooltip(_(cfg.tooltip));
911 void CWindowCurveToggle::check_toggle_state(FloatAuto *x, FloatAuto *y, FloatAuto *z)
913 // the toggle state is only set to ON if all
914 // three automation lines have the same curve mode.
915 // For mixed states the toggle stays off.
916 set_value( x->curve_mode == this->cfg.mode &&
917 y->curve_mode == this->cfg.mode &&
918 z->curve_mode == this->cfg.mode
919 ,true // redraw to show new state
923 int CWindowCurveToggle::handle_event()
925 Track *track = mwindow->cwindow->calculate_affected_track();
927 FloatAuto *x=0, *y=0, *z=0;
928 mwindow->cwindow->calculate_affected_autos(track,
929 &x, &y, &z, cfg.use_camera, 0,0,0); // don't create new keyframe
930 if( x ) x->change_curve_mode(cfg.mode);
931 if( y ) y->change_curve_mode(cfg.mode);
932 if( z ) z->change_curve_mode(cfg.mode);
935 gui->update_preview();
942 CWindowEyedropCheckBox::CWindowEyedropCheckBox(MWindow *mwindow,
943 CWindowEyedropGUI *gui, int x, int y)
944 : BC_CheckBox(x, y, mwindow->edl->local_session->use_max, _("Use maximum"))
946 this->mwindow = mwindow;
950 int CWindowEyedropCheckBox::handle_event()
952 mwindow->edl->local_session->use_max = get_value();
959 CWindowCameraGUI::CWindowCameraGUI(MWindow *mwindow, CWindowTool *thread)
960 : CWindowToolGUI(mwindow, thread, _(PROGRAM_NAME ": Camera"), xS(580), yS(200))
962 // *** CONTEXT_HELP ***
963 context_help_set_keyword("Camera and Projector");
965 CWindowCameraGUI::~CWindowCameraGUI()
969 void CWindowCameraGUI::create_objects()
971 int xs5 = xS(5), xs10 = xS(10), xs15 = xS(15), xs25 = xS(25);
972 int ys10 = yS(10), ys30 = yS(30);
973 int x = xs10, y = ys10;
974 Track *track = mwindow->cwindow->calculate_affected_track();
975 FloatAuto *x_auto = 0, *y_auto = 0, *z_auto = 0;
980 lock_window("CWindowCameraGUI::create_objects");
982 mwindow->cwindow->calculate_affected_autos(track,
983 &x_auto, &y_auto, &z_auto, 1, 0, 0, 0);
986 add_subwindow(bar1 = new BC_TitleBar(x1, y, xS(340), xs10, xs10, _("Position")));
987 x1 += bar1->get_w() + xS(35);
988 add_subwindow(bar2 = new BC_TitleBar(x1, y, get_w()-x1-xs10, xs10, xs10, _("Range")));
989 y += bar1->get_h() + ys10;
991 add_subwindow(title = new BC_Title(x, y, "X:"));
992 x1 = x + title->get_w() + xS(3);
993 float xvalue = x_auto ? x_auto->get_value() : 0;
994 this->x = new CWindowCoord(this, x1, y, xvalue, AUTOMATION_CAMERA_X);
995 this->x->create_objects();
996 this->x->range->set_tooltip(_("expand X range"));
998 add_subwindow(title = new BC_Title(x = xs10, y, "Y:"));
999 float yvalue = y_auto ? y_auto->get_value() : 0;
1000 this->y = new CWindowCoord(this, x1, y, yvalue, AUTOMATION_CAMERA_Y);
1001 this->y->create_objects();
1002 this->y->range->set_tooltip(_("expand Y range"));
1004 add_subwindow(title = new BC_Title(x = xs10, y, "Z:"));
1005 float zvalue = z_auto ? z_auto->get_value() : 1;
1006 this->z = new CWindowCoord(this, x1, y, zvalue, AUTOMATION_CAMERA_Z);
1007 this->z->create_objects();
1008 this->z->set_increment(0.01);
1009 this->z->range->set_tooltip(_("expand Zoom range"));
1013 add_subwindow(bar3 = new BC_TitleBar(x1, y, xS(180)-x1, xs5, xs5, _("Justify")));
1014 x1 += bar3->get_w() + xS(35);
1015 add_subwindow(bar4 = new BC_TitleBar(x1, y, xS(375)-x1, xs5, xs5, _("Curve type")));
1016 bar4->context_help_set_keyword("Using Autos");
1017 x1 += bar4->get_w() + xS(25);
1018 add_subwindow(bar5 = new BC_TitleBar(x1, y, get_w()-xS(60)-x1, xs5, xs5, _("Keyframe")));
1019 bar5->context_help_set_keyword("Using Autos");
1020 y += bar3->get_h() + ys10;
1023 add_subwindow(button = new CWindowCameraLeft(mwindow, this, x1, y));
1024 x1 += button->get_w();
1025 add_subwindow(button = new CWindowCameraCenter(mwindow, this, x1, y));
1026 x1 += button->get_w();
1027 add_subwindow(button = new CWindowCameraRight(mwindow, this, x1, y));
1028 x1 += button->get_w() + xs25;
1029 add_subwindow(button = new CWindowCameraTop(mwindow, this, x1, y));
1030 x1 += button->get_w();
1031 add_subwindow(button = new CWindowCameraMiddle(mwindow, this, x1, y));
1032 x1 += button->get_w();
1033 add_subwindow(button = new CWindowCameraBottom(mwindow, this, x1, y));
1034 x1 += button->get_w() + xS(35);
1035 add_subwindow(t_smooth = new CWindowCurveToggle(Camera_Crv_Smooth, mwindow, this, x1, y));
1036 t_smooth->context_help_set_keyword("Using Autos");
1037 x1 += t_smooth->get_w() + xs10;
1038 add_subwindow(t_linear = new CWindowCurveToggle(Camera_Crv_Linear, mwindow, this, x1, y));
1039 t_linear->context_help_set_keyword("Using Autos");
1040 x1 += t_linear->get_w() + xs10;
1041 add_subwindow(t_tangent = new CWindowCurveToggle(Camera_Crv_Tangent, mwindow, this, x1, y));
1042 t_tangent->context_help_set_keyword("Using Autos");
1043 x1 += t_tangent->get_w() + xs10;
1044 add_subwindow(t_free = new CWindowCurveToggle(Camera_Crv_Free, mwindow, this, x1, y));
1045 t_free->context_help_set_keyword("Using Autos");
1046 x1 += t_free->get_w() + xs10;
1047 add_subwindow(t_bump = new CWindowCurveToggle(Camera_Crv_Bump, mwindow, this, x1, y));
1048 t_bump->context_help_set_keyword("Bump autos");
1049 x1 += button->get_w() + xs25;
1051 add_subwindow(add_keyframe = new CWindowCameraAddKeyframe(mwindow, this, x1, y));
1052 add_keyframe->context_help_set_keyword("Using Autos");
1053 x1 += add_keyframe->get_w() + xs15;
1054 add_subwindow(auto_edge = new CWindowCurveAutoEdge(mwindow, this, x1, y));
1055 auto_edge->context_help_set_keyword("Bump autos");
1056 x1 += auto_edge->get_w() + xs10;
1057 add_subwindow(auto_span = new CWindowCurveAutoSpan(mwindow, this, x1, y));
1058 auto_span->context_help_set_keyword("Bump autos");
1059 x1 += auto_span->get_w() + xS(50);
1060 add_subwindow(reset = new CWindowCameraReset(mwindow, this, x1, y));
1062 // fill in current auto keyframe values, set toggle states.
1067 void CWindowCameraGUI::handle_event()
1069 Track *track = mwindow->cwindow->calculate_affected_track();
1070 if( !track ) return;
1071 mwindow->undo->update_undo_before(_("camera"), this);
1072 if( event_caller == x )
1073 update_auto(track, AUTOMATION_CAMERA_X, x);
1074 else if( event_caller == y )
1075 update_auto(track, AUTOMATION_CAMERA_Y, y);
1076 else if( event_caller == z )
1077 update_auto(track, AUTOMATION_CAMERA_Z, z);
1078 mwindow->undo->update_undo_after(_("camera"), LOAD_ALL);
1081 void CWindowCameraGUI::update()
1083 FloatAuto *x_auto = 0;
1084 FloatAuto *y_auto = 0;
1085 FloatAuto *z_auto = 0;
1086 Track *track = mwindow->cwindow->calculate_affected_track();
1087 int bg_color = get_resources()->text_background;
1088 int hi_color = bg_color ^ 0x444444;
1090 mwindow->cwindow->calculate_affected_autos(track,
1091 &x_auto, &y_auto, &z_auto, 1, 0, 0, 0);
1095 int color = (edge || span) && x_auto->curve_mode == FloatAuto::BUMP ?
1096 hi_color : bg_color;
1097 x->get_textbox()->set_back_color(color);
1098 float xvalue = x_auto->get_value(edge);
1099 x->update_gui(xvalue);
1102 int color = (edge || span) && y_auto->curve_mode == FloatAuto::BUMP ?
1103 hi_color : bg_color;
1104 y->get_textbox()->set_back_color(color);
1105 float yvalue = y_auto->get_value(edge);
1106 y->update_gui(yvalue);
1109 int color = (edge || span) && z_auto->curve_mode == FloatAuto::BUMP ?
1110 hi_color : bg_color;
1111 z->get_textbox()->set_back_color(color);
1112 float zvalue = z_auto->get_value(edge);
1113 z->update_gui(zvalue);
1114 thread->gui->lock_window("CWindowCameraGUI::update");
1115 thread->gui->composite_panel->cpanel_zoom->update(zvalue);
1116 thread->gui->unlock_window();
1119 if( x_auto && y_auto && z_auto ) {
1120 t_smooth->check_toggle_state(x_auto, y_auto, z_auto);
1121 t_linear->check_toggle_state(x_auto, y_auto, z_auto);
1122 t_tangent->check_toggle_state(x_auto, y_auto, z_auto);
1123 t_free->check_toggle_state(x_auto, y_auto, z_auto);
1124 t_bump->check_toggle_state(x_auto, y_auto, z_auto);
1126 x->range_text->update_range();
1127 y->range_text->update_range();
1128 z->range_text->update_range();
1131 CWindowToolAutoRangeTumbler::CWindowToolAutoRangeTumbler(CWindowCoord *coord, int x, int y,
1132 int use_max, const char *tip)
1133 : BC_Tumbler(x, y, coord->gui->mwindow->theme->get_image_set("auto_range"),
1136 this->coord = coord;
1137 this->use_max = use_max;
1141 int CWindowToolAutoRangeTumbler::handle_up_event()
1143 coord->gui->mwindow->update_autorange(coord->type, 1, use_max);
1144 coord->range_text->update_range();
1148 int CWindowToolAutoRangeTumbler::handle_down_event()
1150 coord->gui->mwindow->update_autorange(coord->type, 0, use_max);
1151 coord->range_text->update_range();
1155 CWindowToolAutoRangeReset::CWindowToolAutoRangeReset(CWindowCoord *coord, int x, int y)
1156 : BC_Button(x, y, coord->gui->mwindow->theme->get_image_set("reset_button"))
1158 this->coord = coord;
1159 set_tooltip(_("Reset"));
1162 int CWindowToolAutoRangeReset::handle_event()
1165 int group = Automation::autogrouptype(coord->type, 0);
1166 MWindow *mwindow = coord->gui->mwindow;
1167 LocalSession *local_session = mwindow->edl->local_session;
1168 float min = local_session->automation_mins[group];
1169 float max = local_session->automation_maxs[group];
1171 case AUTOGROUPTYPE_ZOOM: // exp
1172 min = 0.005; max= 5.000; v = 1;
1174 case AUTOGROUPTYPE_X:
1175 max = mwindow->edl->session->output_w;
1178 case AUTOGROUPTYPE_Y:
1179 max = mwindow->edl->session->output_h;
1183 local_session->automation_mins[group] = min;
1184 local_session->automation_maxs[group] = max;
1185 coord->range_text->update_range();
1187 MWindowGUI *mgui = mwindow->gui;
1188 mgui->lock_window("CWindowToolAutoRangeReset::update");
1189 int color = GWindowGUI::auto_colors[coord->type];
1190 mgui->zoombar->update_autozoom(group, color);
1191 mgui->draw_overlays(0);
1192 mgui->update_patchbay();
1193 mgui->flash_canvas(1);
1194 mgui->unlock_window();
1195 mwindow->save_backup();
1196 lock_window("CWindowToolAutoRangeReset::update");
1197 CWindowCoordSlider *slider = coord->slider;
1198 slider->update(slider->get_pointer_motion_range(), v, min, max);
1199 return slider->handle_event();
1202 CWindowToolAutoRangeTextBox::CWindowToolAutoRangeTextBox(CWindowCoord *coord, int x, int y)
1203 : BC_TextBox(x, y, xS(130), 1, "0.000 to 0.000")
1205 this->coord = coord;
1206 set_tooltip(_("Automation range"));
1209 int CWindowToolAutoRangeTextBox::button_press_event()
1211 if (!is_event_win()) return 0;
1212 int use_max = get_cursor_x() < get_w()/2 ? 0 : 1;
1213 switch( get_buttonpress() ) {
1215 coord->gui->mwindow->update_autorange(coord->type, 1, use_max);
1218 coord->gui->mwindow->update_autorange(coord->type, 0, use_max);
1221 return BC_TextBox::button_press_event();
1223 return coord->range_text->update_range();
1226 int CWindowToolAutoRangeTextBox::handle_event()
1229 if( sscanf(this->get_text(),"%f to%f",&imin, &imax) == 2 ) {
1230 MWindow *mwindow = coord->gui->mwindow;
1231 int group = Automation::autogrouptype(coord->type, 0);
1232 LocalSession *local_session = mwindow->edl->local_session;
1233 float min = imin, max = imax;
1235 case AUTOGROUPTYPE_ZOOM:
1236 if( min < ZOOM_MIN ) min = ZOOM_MIN;
1237 if( max > ZOOM_MAX ) max = ZOOM_MAX;
1239 case AUTOGROUPTYPE_X:
1240 case AUTOGROUPTYPE_Y:
1241 if( min < XY_MIN ) min = XY_MIN;
1242 if( max > XY_MAX ) max = XY_MAX;
1246 local_session->automation_mins[group] = min;
1247 local_session->automation_maxs[group] = max;
1248 if( min != imin || max != imax ) update_range();
1249 mwindow->gui->lock_window("CWindowToolAutoRangeTextBox::handle_event");
1250 int color = GWindowGUI::auto_colors[coord->type];
1251 mwindow->gui->zoombar->update_autozoom(group, color);
1252 mwindow->gui->draw_overlays(0);
1253 mwindow->gui->update_patchbay();
1254 mwindow->gui->flash_canvas(1);
1255 mwindow->gui->unlock_window();
1261 int CWindowToolAutoRangeTextBox::update_range()
1263 char string[BCSTRLEN];
1264 LocalSession *local_session = coord->gui->mwindow->edl->local_session;
1265 int group = Automation::autogrouptype(coord->type, 0);
1266 float min = local_session->automation_mins[group];
1267 float max = local_session->automation_maxs[group];
1269 case AUTOGROUPTYPE_ZOOM:
1270 sprintf(string, "%0.03f to %0.03f\n", min, max);
1272 case AUTOGROUPTYPE_X:
1273 case AUTOGROUPTYPE_Y:
1274 sprintf(string, "%0.0f to %.0f\n", min, max);
1282 CWindowCameraLeft::CWindowCameraLeft(MWindow *mwindow, CWindowCameraGUI *gui, int x, int y)
1283 : BC_Button(x, y, mwindow->theme->get_image_set("left_justify"))
1286 this->mwindow = mwindow;
1287 set_tooltip(_("Left justify"));
1289 int CWindowCameraLeft::handle_event()
1291 FloatAuto *x_auto = 0;
1292 FloatAuto *z_auto = 0;
1293 Track *track = mwindow->cwindow->calculate_affected_track();
1295 mwindow->cwindow->calculate_affected_autos(track,
1296 &x_auto, 0, &z_auto, 1, 1, 0, 0);
1299 if(x_auto && z_auto)
1302 track->get_source_dimensions(
1303 mwindow->edl->local_session->get_selectionstart(1),
1308 mwindow->undo->update_undo_before(_("camera"), 0);
1310 (double)track->track_w / z_auto->get_value() / 2 -
1312 mwindow->undo->update_undo_after(_("camera"), LOAD_ALL);
1314 gui->update_preview();
1322 CWindowCameraCenter::CWindowCameraCenter(MWindow *mwindow, CWindowCameraGUI *gui, int x, int y)
1323 : BC_Button(x, y, mwindow->theme->get_image_set("center_justify"))
1326 this->mwindow = mwindow;
1327 set_tooltip(_("Center horizontal"));
1329 int CWindowCameraCenter::handle_event()
1331 FloatAuto *x_auto = 0;
1332 Track *track = mwindow->cwindow->calculate_affected_track();
1334 x_auto = (FloatAuto*)mwindow->cwindow->calculate_affected_auto(
1335 track->automation->autos[AUTOMATION_CAMERA_X], 1);
1339 mwindow->undo->update_undo_before(_("camera"), 0);
1340 x_auto->set_value(0);
1342 gui->update_preview();
1343 mwindow->undo->update_undo_after(_("camera"), LOAD_ALL);
1350 CWindowCameraRight::CWindowCameraRight(MWindow *mwindow, CWindowCameraGUI *gui, int x, int y)
1351 : BC_Button(x, y, mwindow->theme->get_image_set("right_justify"))
1354 this->mwindow = mwindow;
1355 set_tooltip(_("Right justify"));
1357 int CWindowCameraRight::handle_event()
1359 FloatAuto *x_auto = 0;
1360 FloatAuto *z_auto = 0;
1361 Track *track = mwindow->cwindow->calculate_affected_track();
1363 mwindow->cwindow->calculate_affected_autos(track,
1364 &x_auto, 0, &z_auto, 1, 1, 0, 0);
1367 if(x_auto && z_auto)
1370 track->get_source_dimensions(
1371 mwindow->edl->local_session->get_selectionstart(1),
1376 mwindow->undo->update_undo_before(_("camera"), 0);
1377 x_auto->set_value( -((double)track->track_w / z_auto->get_value() / 2 -
1380 gui->update_preview();
1381 mwindow->undo->update_undo_after(_("camera"), LOAD_ALL);
1389 CWindowCameraTop::CWindowCameraTop(MWindow *mwindow, CWindowCameraGUI *gui, int x, int y)
1390 : BC_Button(x, y, mwindow->theme->get_image_set("top_justify"))
1393 this->mwindow = mwindow;
1394 set_tooltip(_("Top justify"));
1396 int CWindowCameraTop::handle_event()
1398 FloatAuto *y_auto = 0;
1399 FloatAuto *z_auto = 0;
1400 Track *track = mwindow->cwindow->calculate_affected_track();
1402 mwindow->cwindow->calculate_affected_autos(track,
1403 0, &y_auto, &z_auto, 1, 0, 1, 0);
1406 if(y_auto && z_auto)
1409 track->get_source_dimensions(
1410 mwindow->edl->local_session->get_selectionstart(1),
1415 mwindow->undo->update_undo_before(_("camera"), 0);
1416 y_auto->set_value((double)track->track_h / z_auto->get_value() / 2 -
1419 gui->update_preview();
1420 mwindow->undo->update_undo_after(_("camera"), LOAD_ALL);
1428 CWindowCameraMiddle::CWindowCameraMiddle(MWindow *mwindow, CWindowCameraGUI *gui, int x, int y)
1429 : BC_Button(x, y, mwindow->theme->get_image_set("middle_justify"))
1432 this->mwindow = mwindow;
1433 set_tooltip(_("Center vertical"));
1435 int CWindowCameraMiddle::handle_event()
1437 FloatAuto *y_auto = 0;
1438 Track *track = mwindow->cwindow->calculate_affected_track();
1440 y_auto = (FloatAuto*)mwindow->cwindow->calculate_affected_auto(
1441 track->automation->autos[AUTOMATION_CAMERA_Y], 1);
1445 mwindow->undo->update_undo_before(_("camera"), 0);
1446 y_auto->set_value(0);
1448 gui->update_preview();
1449 mwindow->undo->update_undo_after(_("camera"), LOAD_ALL);
1456 CWindowCameraBottom::CWindowCameraBottom(MWindow *mwindow, CWindowCameraGUI *gui, int x, int y)
1457 : BC_Button(x, y, mwindow->theme->get_image_set("bottom_justify"))
1460 this->mwindow = mwindow;
1461 set_tooltip(_("Bottom justify"));
1463 int CWindowCameraBottom::handle_event()
1465 FloatAuto *y_auto = 0;
1466 FloatAuto *z_auto = 0;
1467 Track *track = mwindow->cwindow->calculate_affected_track();
1469 mwindow->cwindow->calculate_affected_autos(track,
1470 0, &y_auto, &z_auto, 1, 0, 1, 0);
1473 if(y_auto && z_auto)
1476 track->get_source_dimensions(
1477 mwindow->edl->local_session->get_selectionstart(1),
1482 mwindow->undo->update_undo_before(_("camera"), 0);
1483 y_auto->set_value(-((double)track->track_h / z_auto->get_value() / 2 -
1486 gui->update_preview();
1487 mwindow->undo->update_undo_after(_("camera"), LOAD_ALL);
1494 CWindowCameraAddKeyframe::CWindowCameraAddKeyframe(MWindow *mwindow,
1495 CWindowToolGUI *gui, int x, int y)
1496 : BC_Button(x, y, mwindow->theme->get_image_set("keyframe_button"))
1498 this->mwindow = mwindow;
1500 set_tooltip(_("Add Keyframe: Shift-F11"));
1503 int CWindowCameraAddKeyframe::handle_event()
1505 return gui->press(&CWindowCanvas::camera_keyframe);
1508 CWindowCameraReset::CWindowCameraReset(MWindow *mwindow,
1509 CWindowToolGUI *gui, int x, int y)
1510 : BC_Button(x, y, mwindow->theme->get_image_set("reset_button"))
1512 this->mwindow = mwindow;
1514 set_tooltip(_("Reset Camera: F11"));
1517 int CWindowCameraReset::handle_event()
1519 mwindow->edl->local_session->reset_view_limits();
1520 CWindowCameraGUI *gui = (CWindowCameraGUI *)this->gui;
1521 return gui->press(&CWindowCanvas::reset_camera);
1524 CWindowCurveAutoEdge::CWindowCurveAutoEdge(MWindow *mwindow,
1525 CWindowToolGUI *gui, int x, int y)
1526 : BC_Toggle(x, y, mwindow->theme->get_image_set("bump_edge"), gui->edge)
1528 this->mwindow = mwindow;
1530 set_tooltip(_("Bump edit edge left/right"));
1533 int CWindowCurveAutoEdge::handle_event()
1535 gui->edge = get_value();
1540 CWindowCurveAutoSpan::CWindowCurveAutoSpan(MWindow *mwindow,
1541 CWindowToolGUI *gui, int x, int y)
1542 : BC_Toggle(x, y, mwindow->theme->get_image_set("bump_span"), gui->span)
1544 this->mwindow = mwindow;
1546 set_tooltip(_("Bump spans to next/prev"));
1549 int CWindowCurveAutoSpan::handle_event()
1551 gui->span = get_value();
1557 CWindowProjectorGUI::CWindowProjectorGUI(MWindow *mwindow, CWindowTool *thread)
1558 : CWindowToolGUI(mwindow, thread, _(PROGRAM_NAME ": Projector"), xS(580), yS(200))
1560 // *** CONTEXT_HELP ***
1561 context_help_set_keyword("Camera and Projector");
1563 CWindowProjectorGUI::~CWindowProjectorGUI()
1566 void CWindowProjectorGUI::create_objects()
1568 int xs5 = xS(5), xs10 = xS(10), xs15 = xS(15), xs25 = xS(25);
1569 int ys10 = yS(10), ys30 = yS(30);
1570 int x = xs10, y = ys10;
1571 Track *track = mwindow->cwindow->calculate_affected_track();
1572 FloatAuto *x_auto = 0;
1573 FloatAuto *y_auto = 0;
1574 FloatAuto *z_auto = 0;
1579 lock_window("CWindowProjectorGUI::create_objects");
1581 mwindow->cwindow->calculate_affected_autos(track,
1582 &x_auto, &y_auto, &z_auto, 0, 0, 0, 0);
1585 add_subwindow(bar1 = new BC_TitleBar(x1, y, xS(340), xs10, xs10, _("Position")));
1586 x1 += bar1->get_w() + xS(35);
1587 add_subwindow(bar2 = new BC_TitleBar(x1, y, get_w()-x1-xs10, xs10, xs10, _("Range")));
1588 y += bar1->get_h() + ys10;
1589 add_subwindow(title = new BC_Title(x = xs10, y, "X:"));
1590 x1 = x + title->get_w() + xS(3);
1591 float xvalue = x_auto ? x_auto->get_value() : 0;
1592 this->x = new CWindowCoord(this, x1, y, xvalue, AUTOMATION_PROJECTOR_X);
1593 this->x->create_objects();
1594 this->x->range->set_tooltip(_("expand X range"));
1596 add_subwindow(title = new BC_Title(x = xs10, y, "Y:"));
1597 float yvalue = y_auto ? y_auto->get_value() : 0;
1598 this->y = new CWindowCoord(this, x1, y, yvalue, AUTOMATION_PROJECTOR_Y);
1599 this->y->create_objects();
1600 this->y->range->set_tooltip(_("expand Y range"));
1602 add_subwindow(title = new BC_Title(x = xs10, y, "Z:"));
1603 float zvalue = z_auto ? z_auto->get_value() : 1;
1604 this->z = new CWindowCoord(this, x1, y, zvalue, AUTOMATION_PROJECTOR_Z);
1605 this->z->create_objects();
1606 this->z->range->set_tooltip(_("expand Zoom range"));
1607 this->z->set_increment(0.01);
1611 add_subwindow(bar3 = new BC_TitleBar(x1, y, xS(180)-x1, xs5, xs5, _("Justify")));
1612 x1 += bar3->get_w() + xS(35);
1613 add_subwindow(bar4 = new BC_TitleBar(x1, y, xS(375)-x1, xs5, xs5, _("Curve type")));
1614 bar4->context_help_set_keyword("Using Autos");
1615 x1 += bar4->get_w() + xS(25);
1616 add_subwindow(bar5 = new BC_TitleBar(x1, y, get_w()-xS(60)-x1, xs5, xs5, _("Keyframe")));
1617 bar5->context_help_set_keyword("Using Autos");
1618 y += bar3->get_h() + ys10;
1621 add_subwindow(button = new CWindowProjectorLeft(mwindow, this, x1, y));
1622 x1 += button->get_w();
1623 add_subwindow(button = new CWindowProjectorCenter(mwindow, this, x1, y));
1624 x1 += button->get_w();
1625 add_subwindow(button = new CWindowProjectorRight(mwindow, this, x1, y));
1626 x1 += button->get_w() + xs25;
1627 add_subwindow(button = new CWindowProjectorTop(mwindow, this, x1, y));
1628 x1 += button->get_w();
1629 add_subwindow(button = new CWindowProjectorMiddle(mwindow, this, x1, y));
1630 x1 += button->get_w();
1631 add_subwindow(button = new CWindowProjectorBottom(mwindow, this, x1, y));
1632 x1 += button->get_w() + xS(35);
1633 add_subwindow(t_smooth = new CWindowCurveToggle(Projector_Crv_Smooth, mwindow, this, x1, y));
1634 t_smooth->context_help_set_keyword("Using Autos");
1635 x1 += t_smooth->get_w() + xs10;
1636 add_subwindow(t_linear = new CWindowCurveToggle(Projector_Crv_Linear, mwindow, this, x1, y));
1637 t_linear->context_help_set_keyword("Using Autos");
1638 x1 += t_linear->get_w() + xs10;
1639 add_subwindow(t_tangent = new CWindowCurveToggle(Projector_Crv_Tangent, mwindow, this, x1, y));
1640 t_tangent->context_help_set_keyword("Using Autos");
1641 x1 += t_tangent->get_w() + xs10;
1642 add_subwindow(t_free = new CWindowCurveToggle(Projector_Crv_Free, mwindow, this, x1, y));
1643 t_free->context_help_set_keyword("Using Autos");
1644 x1 += t_free->get_w() + xs10;
1645 add_subwindow(t_bump = new CWindowCurveToggle(Projector_Crv_Bump, mwindow, this, x1, y));
1646 t_bump->context_help_set_keyword("Bump autos");
1647 x1 += button->get_w() + xs25;
1649 add_subwindow(add_keyframe = new CWindowProjectorAddKeyframe(mwindow, this, x1, y));
1650 add_keyframe->context_help_set_keyword("Using Autos");
1651 x1 += add_keyframe->get_w() + xs15;
1652 add_subwindow(auto_edge = new CWindowCurveAutoEdge(mwindow, this, x1, y));
1653 auto_edge->context_help_set_keyword("Bump autos");
1654 x1 += auto_edge->get_w() + xs10;
1655 add_subwindow(auto_span = new CWindowCurveAutoSpan(mwindow, this, x1, y));
1656 auto_span->context_help_set_keyword("Bump autos");
1657 x1 += auto_span->get_w() + xS(50);
1658 add_subwindow(reset = new CWindowProjectorReset(mwindow, this, x1, y));
1660 // fill in current auto keyframe values, set toggle states.
1665 void CWindowProjectorGUI::handle_event()
1667 Track *track = mwindow->cwindow->calculate_affected_track();
1668 if( !track ) return;
1669 mwindow->undo->update_undo_before(_("projector"), this);
1670 if( event_caller == x )
1671 update_auto(track, AUTOMATION_PROJECTOR_X, x);
1672 else if( event_caller == y )
1673 update_auto(track, AUTOMATION_PROJECTOR_Y, y);
1674 else if( event_caller == z )
1675 update_auto(track, AUTOMATION_PROJECTOR_Z, z);
1676 mwindow->undo->update_undo_after(_("projector"), LOAD_ALL);
1679 void CWindowProjectorGUI::update()
1681 FloatAuto *x_auto = 0;
1682 FloatAuto *y_auto = 0;
1683 FloatAuto *z_auto = 0;
1684 Track *track = mwindow->cwindow->calculate_affected_track();
1685 int bg_color = get_resources()->text_background;
1686 int hi_color = bg_color ^ 0x444444;
1688 mwindow->cwindow->calculate_affected_autos(track,
1689 &x_auto, &y_auto, &z_auto, 0, 0, 0, 0);
1693 int color = (edge || span) && x_auto->curve_mode == FloatAuto::BUMP ?
1694 hi_color : bg_color;
1695 x->get_textbox()->set_back_color(color);
1696 float xvalue = x_auto->get_value(edge);
1697 x->update_gui(xvalue);
1700 int color = (edge || span) && y_auto->curve_mode == FloatAuto::BUMP ?
1701 hi_color : bg_color;
1702 y->get_textbox()->set_back_color(color);
1703 float yvalue = y_auto->get_value(edge);
1704 y->update_gui(yvalue);
1707 int color = (edge || span) && z_auto->curve_mode == FloatAuto::BUMP ?
1708 hi_color : bg_color;
1709 z->get_textbox()->set_back_color(color);
1710 float zvalue = z_auto->get_value(edge);
1711 z->update_gui(zvalue);
1712 thread->gui->lock_window("CWindowProjectorGUI::update");
1713 thread->gui->composite_panel->cpanel_zoom->update(zvalue);
1714 thread->gui->unlock_window();
1717 if( x_auto && y_auto && z_auto ) {
1718 t_smooth->check_toggle_state(x_auto, y_auto, z_auto);
1719 t_linear->check_toggle_state(x_auto, y_auto, z_auto);
1720 t_tangent->check_toggle_state(x_auto, y_auto, z_auto);
1721 t_free->check_toggle_state(x_auto, y_auto, z_auto);
1722 t_bump->check_toggle_state(x_auto, y_auto, z_auto);
1724 x->range_text->update_range();
1725 y->range_text->update_range();
1726 z->range_text->update_range();
1729 CWindowProjectorLeft::CWindowProjectorLeft(MWindow *mwindow, CWindowProjectorGUI *gui, int x, int y)
1730 : BC_Button(x, y, mwindow->theme->get_image_set("left_justify"))
1733 this->mwindow = mwindow;
1734 set_tooltip(_("Left justify"));
1736 int CWindowProjectorLeft::handle_event()
1738 FloatAuto *x_auto = 0;
1739 FloatAuto *z_auto = 0;
1740 Track *track = mwindow->cwindow->calculate_affected_track();
1742 mwindow->cwindow->calculate_affected_autos(track,
1743 &x_auto, 0, &z_auto, 0, 1, 0, 0);
1745 if(x_auto && z_auto)
1747 mwindow->undo->update_undo_before(_("projector"), 0);
1748 x_auto->set_value( (double)track->track_w * z_auto->get_value() / 2 -
1749 (double)mwindow->edl->session->output_w / 2 );
1751 gui->update_preview();
1752 mwindow->undo->update_undo_after(_("projector"), LOAD_ALL);
1759 CWindowProjectorCenter::CWindowProjectorCenter(MWindow *mwindow, CWindowProjectorGUI *gui, int x, int y)
1760 : BC_Button(x, y, mwindow->theme->get_image_set("center_justify"))
1763 this->mwindow = mwindow;
1764 set_tooltip(_("Center horizontal"));
1766 int CWindowProjectorCenter::handle_event()
1768 FloatAuto *x_auto = 0;
1769 Track *track = mwindow->cwindow->calculate_affected_track();
1771 x_auto = (FloatAuto*)mwindow->cwindow->calculate_affected_auto(
1772 track->automation->autos[AUTOMATION_PROJECTOR_X], 1);
1776 mwindow->undo->update_undo_before(_("projector"), 0);
1777 x_auto->set_value(0);
1779 gui->update_preview();
1780 mwindow->undo->update_undo_after(_("projector"), LOAD_ALL);
1787 CWindowProjectorRight::CWindowProjectorRight(MWindow *mwindow, CWindowProjectorGUI *gui, int x, int y)
1788 : BC_Button(x, y, mwindow->theme->get_image_set("right_justify"))
1791 this->mwindow = mwindow;
1792 set_tooltip(_("Right justify"));
1794 int CWindowProjectorRight::handle_event()
1796 FloatAuto *x_auto = 0;
1797 FloatAuto *z_auto = 0;
1798 Track *track = mwindow->cwindow->calculate_affected_track();
1800 mwindow->cwindow->calculate_affected_autos(track,
1801 &x_auto, 0, &z_auto, 0, 1, 0, 0);
1804 if(x_auto && z_auto)
1806 mwindow->undo->update_undo_before(_("projector"), 0);
1807 x_auto->set_value( -((double)track->track_w * z_auto->get_value() / 2 -
1808 (double)mwindow->edl->session->output_w / 2));
1810 gui->update_preview();
1811 mwindow->undo->update_undo_after(_("projector"), LOAD_ALL);
1818 CWindowProjectorTop::CWindowProjectorTop(MWindow *mwindow, CWindowProjectorGUI *gui, int x, int y)
1819 : BC_Button(x, y, mwindow->theme->get_image_set("top_justify"))
1822 this->mwindow = mwindow;
1823 set_tooltip(_("Top justify"));
1825 int CWindowProjectorTop::handle_event()
1827 FloatAuto *y_auto = 0;
1828 FloatAuto *z_auto = 0;
1829 Track *track = mwindow->cwindow->calculate_affected_track();
1831 mwindow->cwindow->calculate_affected_autos(track,
1832 0, &y_auto, &z_auto, 0, 0, 1, 0);
1835 if(y_auto && z_auto)
1837 mwindow->undo->update_undo_before(_("projector"), 0);
1838 y_auto->set_value( (double)track->track_h * z_auto->get_value() / 2 -
1839 (double)mwindow->edl->session->output_h / 2 );
1841 gui->update_preview();
1842 mwindow->undo->update_undo_after(_("projector"), LOAD_ALL);
1849 CWindowProjectorMiddle::CWindowProjectorMiddle(MWindow *mwindow, CWindowProjectorGUI *gui, int x, int y)
1850 : BC_Button(x, y, mwindow->theme->get_image_set("middle_justify"))
1853 this->mwindow = mwindow;
1854 set_tooltip(_("Center vertical"));
1856 int CWindowProjectorMiddle::handle_event()
1858 FloatAuto *y_auto = 0;
1859 Track *track = mwindow->cwindow->calculate_affected_track();
1861 y_auto = (FloatAuto*)mwindow->cwindow->calculate_affected_auto(
1862 track->automation->autos[AUTOMATION_PROJECTOR_Y], 1);
1866 mwindow->undo->update_undo_before(_("projector"), 0);
1867 y_auto->set_value(0);
1869 gui->update_preview();
1870 mwindow->undo->update_undo_after(_("projector"), LOAD_ALL);
1877 CWindowProjectorBottom::CWindowProjectorBottom(MWindow *mwindow, CWindowProjectorGUI *gui, int x, int y)
1878 : BC_Button(x, y, mwindow->theme->get_image_set("bottom_justify"))
1881 this->mwindow = mwindow;
1882 set_tooltip(_("Bottom justify"));
1884 int CWindowProjectorBottom::handle_event()
1886 FloatAuto *y_auto = 0;
1887 FloatAuto *z_auto = 0;
1888 Track *track = mwindow->cwindow->calculate_affected_track();
1890 mwindow->cwindow->calculate_affected_autos(track,
1891 0, &y_auto, &z_auto, 0, 0, 1, 0);
1894 if(y_auto && z_auto)
1896 mwindow->undo->update_undo_before(_("projector"), 0);
1897 y_auto->set_value( -((double)track->track_h * z_auto->get_value() / 2 -
1898 (double)mwindow->edl->session->output_h / 2));
1900 gui->update_preview();
1901 mwindow->undo->update_undo_after(_("projector"), LOAD_ALL);
1907 CWindowProjectorAddKeyframe::CWindowProjectorAddKeyframe(MWindow *mwindow,
1908 CWindowToolGUI *gui, int x, int y)
1909 : BC_Button(x, y, mwindow->theme->get_image_set("keyframe_button"))
1911 this->mwindow = mwindow;
1913 set_tooltip(_("Add Keyframe: Shift-F12"));
1916 int CWindowProjectorAddKeyframe::handle_event()
1918 return gui->press(&CWindowCanvas::projector_keyframe);
1921 CWindowProjectorReset::CWindowProjectorReset(MWindow *mwindow,
1922 CWindowToolGUI *gui, int x, int y)
1923 : BC_Button(x, y, mwindow->theme->get_image_set("reset_button"))
1925 this->mwindow = mwindow;
1927 set_tooltip(_("Reset Projector: F12"));
1930 int CWindowProjectorReset::handle_event()
1932 mwindow->edl->local_session->reset_view_limits();
1933 CWindowProjectorGUI *gui = (CWindowProjectorGUI *)this->gui;
1934 return gui->press(&CWindowCanvas::reset_projector);
1937 int CWindowToolGUI::press(void (CWindowCanvas::*fn)())
1940 CWindowGUI *cw_gui = thread->gui;
1941 cw_gui->lock_window("CWindowGUI::press");
1942 (cw_gui->canvas->*fn)();
1943 cw_gui->unlock_window();
1944 lock_window("CWindowToolGUI::press");
1948 CWindowMaskOnTrack::CWindowMaskOnTrack(MWindow *mwindow, CWindowMaskGUI *gui,
1949 int x, int y, int w, const char *text)
1950 : BC_PopupTextBox(gui, 0, text, x, y, w, yS(120))
1952 this->mwindow = mwindow;
1956 CWindowMaskOnTrack::~CWindowMaskOnTrack()
1960 int CWindowMaskOnTrack::handle_event()
1962 CWindowMaskItem *track_item = 0;
1963 int k = get_number(), track_id = -1;
1964 //printf("selected %d = %s\n", k, k<0 ? "()" : track_items[k]->get_text());
1966 track_item = (CWindowMaskItem *)track_items[k];
1967 Track *track = track_item ? mwindow->edl->tracks->get_track_by_id(track_item->id) : 0;
1968 if( track && track->is_armed() ) track_id = track->get_id();
1971 track_id = mwindow->cwindow->mask_track_id;
1972 set_back_color(track_id >= 0 ?
1973 gui->get_resources()->text_background :
1974 gui->get_resources()->text_background_disarmed);
1975 if( mwindow->cwindow->mask_track_id != track_id )
1976 gui->mask_on_track->update(track_item ? track_item->get_text() : "");
1977 mwindow->cwindow->mask_track_id = track_id;
1978 mwindow->edl->local_session->solo_track_id = -1;
1979 gui->mask_solo_track->update(0);
1981 gui->update_preview(1);
1985 void CWindowMaskOnTrack::update_items()
1987 track_items.remove_all_objects();
1988 int high_color = gui->get_resources()->button_highlighted;
1989 for( Track *track=mwindow->edl->tracks->first; track; track=track->next ) {
1990 if( track->data_type != TRACK_VIDEO ) continue;
1991 MaskAutos *mask_autos = (MaskAutos*)track->automation->autos[AUTOMATION_MASK];
1992 int color = !track->is_armed() ? RED : mask_autos->first ? high_color : -1;
1993 MaskAuto *mask_auto = (MaskAuto*)mask_autos->default_auto;
1994 for( int i=0; color<0 && i<mask_auto->masks.size(); ++i )
1995 if( mask_auto->masks[i]->points.size() > 0 ) color = high_color;
1996 track_items.append(new CWindowMaskItem(track->title, track->get_id(), color));
1998 update_list(&track_items);
2001 CWindowMaskTrackTumbler::CWindowMaskTrackTumbler(MWindow *mwindow, CWindowMaskGUI *gui,
2005 this->mwindow = mwindow;
2008 CWindowMaskTrackTumbler::~CWindowMaskTrackTumbler()
2012 int CWindowMaskTrackTumbler::handle_up_event()
2017 int CWindowMaskTrackTumbler::handle_down_event()
2019 return do_event(-1);
2022 int CWindowMaskTrackTumbler::do_event(int dir)
2024 CWindowMaskItem *track_item = 0;
2025 CWindowMaskItem **items = (CWindowMaskItem**)&gui->mask_on_track->track_items[0];
2026 int n = gui->mask_on_track->track_items.size();
2027 int id = mwindow->cwindow->mask_track_id;
2030 while( --k >= 0 && items[k]->id != id );
2034 track_item = items[k];
2037 track_item = items[0];
2039 Track *track = track_item ? mwindow->edl->tracks->get_track_by_id(track_item->id) : 0;
2040 int track_id = track_item && track && track->is_armed() ? track_item->id : -1;
2041 gui->mask_on_track->set_back_color(track_id >= 0 ?
2042 gui->get_resources()->text_background :
2043 gui->get_resources()->text_background_disarmed);
2044 gui->mask_on_track->update(track_item ? track_item->get_text() : "");
2045 mwindow->cwindow->mask_track_id = track_item ? track_item->id : -1;
2046 mwindow->edl->local_session->solo_track_id = -1;
2047 gui->mask_solo_track->update(0);
2049 gui->update_preview(1);
2054 CWindowMaskName::CWindowMaskName(MWindow *mwindow, CWindowMaskGUI *gui,
2055 int x, int y, const char *text)
2056 : BC_PopupTextBox(gui, 0, text, x, y, xS(100), yS(160))
2058 this->mwindow = mwindow;
2062 CWindowMaskName::~CWindowMaskName()
2066 int CWindowMaskName::handle_event()
2073 //printf("CWindowMaskGUI::update 1\n");
2074 gui->get_keyframe(track, autos, keyframe, mask, point, 0);
2076 int k = get_number();
2077 if( k < 0 ) k = mwindow->edl->session->cwindow_mask;
2078 else mwindow->edl->session->cwindow_mask = k;
2079 if( k >= 0 && k < mask_items.size() ) {
2080 mask_items[k]->set_text(get_text());
2081 update_list(&mask_items);
2083 #ifdef USE_KEYFRAME_SPANNING
2084 MaskAuto temp_keyframe(mwindow->edl, autos);
2085 temp_keyframe.copy_data(keyframe);
2086 SubMask *submask = temp_keyframe.get_submask(mwindow->edl->session->cwindow_mask);
2087 memset(submask->name, 0, sizeof(submask->name));
2088 strncpy(submask->name, get_text(), sizeof(submask->name)-1);
2089 ((MaskAutos*)track->automation->autos[AUTOMATION_MASK])->update_parameter(&temp_keyframe);
2091 for(MaskAuto *current = (MaskAuto*)autos->default_auto; current; ) {
2092 SubMask *submask = current->get_submask(mwindow->edl->session->cwindow_mask);
2093 memset(submask->name, 0, sizeof(submask->name));
2094 strncpy(submask->name, get_text(), sizeof(submask->name)-1);
2095 current = current == (MaskAuto*)autos->default_auto ?
2096 (MaskAuto*)autos->first : (MaskAuto*)NEXT;
2100 gui->update_preview();
2105 void CWindowMaskName::update_items(MaskAuto *keyframe)
2107 mask_items.remove_all_objects();
2108 int sz = !keyframe ? 0 : keyframe->masks.size();
2109 for( int i=0; i<SUBMASKS; ++i ) {
2110 char text[BCSTRLEN]; memset(text, 0, sizeof(text));
2112 SubMask *sub_mask = keyframe->masks.get(i);
2113 strncpy(text, sub_mask->name, sizeof(text)-1);
2116 sprintf(text, "%d", i);
2117 mask_items.append(new CWindowMaskItem(text));
2119 update_list(&mask_items);
2123 CWindowMaskButton::CWindowMaskButton(MWindow *mwindow, CWindowMaskGUI *gui,
2124 int x, int y, int no, int v)
2125 : BC_CheckBox(x, y, v)
2127 this->mwindow = mwindow;
2132 CWindowMaskButton::~CWindowMaskButton()
2136 int CWindowMaskButton::handle_event()
2138 mwindow->edl->session->cwindow_mask = no;
2139 gui->mask_name->update(gui->mask_name->mask_items[no]->get_text());
2141 gui->update_preview();
2145 CWindowMaskThumbler::CWindowMaskThumbler(MWindow *mwindow, CWindowMaskGUI *gui,
2149 this->mwindow = mwindow;
2153 CWindowMaskThumbler::~CWindowMaskThumbler()
2157 int CWindowMaskThumbler::handle_up_event()
2162 int CWindowMaskThumbler::handle_down_event()
2164 return do_event(-1);
2167 int CWindowMaskThumbler::do_event(int dir)
2169 int k = mwindow->edl->session->cwindow_mask;
2170 if( (k+=dir) >= SUBMASKS ) k = 0;
2171 else if( k < 0 ) k = SUBMASKS-1;
2172 mwindow->edl->session->cwindow_mask = k;
2173 gui->mask_name->update(gui->mask_name->mask_items[k]->get_text());
2175 gui->update_preview();
2179 CWindowMaskEnable::CWindowMaskEnable(MWindow *mwindow, CWindowMaskGUI *gui,
2180 int x, int y, int no, int v)
2181 : BC_CheckBox(x, y, v)
2183 this->mwindow = mwindow;
2188 CWindowMaskEnable::~CWindowMaskEnable()
2192 int CWindowMaskEnable::handle_event()
2194 Track *track = mwindow->cwindow->calculate_mask_track();
2196 mwindow->undo->update_undo_before(_("mask enable"), this);
2199 track->masks |= bit;
2201 track->masks &= ~bit;
2203 gui->update_preview(1);
2204 mwindow->undo->update_undo_after(_("mask enable"), LOAD_PATCHES);
2209 CWindowMaskUnclear::CWindowMaskUnclear(MWindow *mwindow,
2210 CWindowMaskGUI *gui, int x, int y)
2211 : BC_Button(x, y, mwindow->theme->get_image_set("unclear_button"))
2213 this->mwindow = mwindow;
2215 set_tooltip(_("Show/Hide mask"));
2218 int CWindowMaskUnclear::handle_event()
2220 Track *track = mwindow->cwindow->calculate_mask_track();
2222 mwindow->undo->update_undo_before(_("mask enables"), this);
2223 int m = (1<<SUBMASKS)-1;
2224 if( track->masks == m )
2228 for( int i=0; i<SUBMASKS; ++i )
2229 gui->mask_enables[i]->update((track->masks>>i) & 1);
2230 gui->update_preview(1);
2231 mwindow->undo->update_undo_after(_("mask enables"), LOAD_PATCHES);
2236 CWindowMaskSoloTrack::CWindowMaskSoloTrack(MWindow *mwindow,
2237 CWindowMaskGUI *gui, int x, int y, int v)
2238 : BC_CheckBox(x, y, v, _("Solo"))
2240 this->mwindow = mwindow;
2242 set_tooltip(_("Solo video track"));
2245 int CWindowMaskSoloTrack::handle_event()
2247 mwindow->edl->local_session->solo_track_id =
2248 get_value() ? mwindow->cwindow->mask_track_id : -1;
2249 gui->update_preview(1);
2253 int CWindowMaskSoloTrack::calculate_w(BC_WindowBase *gui)
2256 calculate_extents(gui, &w, &h, _("Solo"));
2260 CWindowMaskDelMask::CWindowMaskDelMask(MWindow *mwindow,
2261 CWindowMaskGUI *gui, int x, int y)
2262 : BC_GenericButton(x, y, _("Delete"))
2264 this->mwindow = mwindow;
2266 set_tooltip(_("Delete mask"));
2269 int CWindowMaskDelMask::handle_event()
2278 // Get existing keyframe
2279 gui->get_keyframe(track, autos, keyframe, mask, point, 0);
2282 mwindow->undo->update_undo_before(_("mask delete"), 0);
2284 #ifdef USE_KEYFRAME_SPANNING
2285 // Create temp keyframe
2286 MaskAuto temp_keyframe(mwindow->edl, autos);
2287 temp_keyframe.copy_data(keyframe);
2288 SubMask *submask = temp_keyframe.get_submask(mwindow->edl->session->cwindow_mask);
2289 submask->points.remove_all_objects();
2291 // Commit change to span of keyframes
2292 ((MaskAutos*)track->automation->autos[AUTOMATION_MASK])->update_parameter(&temp_keyframe);
2294 for(MaskAuto *current = (MaskAuto*)autos->default_auto; current; ) {
2295 SubMask *submask = current->get_submask(mwindow->edl->session->cwindow_mask);
2296 submask->points.remove_all_objects();
2297 current = current == (MaskAuto*)autos->default_auto ?
2298 (MaskAuto*)autos->first : (MaskAuto*)NEXT;
2302 if( mwindow->cwindow->gui->affected_point >= total_points )
2303 mwindow->cwindow->gui->affected_point =
2304 total_points > 0 ? total_points-1 : 0;
2307 gui->update_preview();
2308 mwindow->undo->update_undo_after(_("mask delete"), LOAD_AUTOMATION);
2314 CWindowMaskDelPoint::CWindowMaskDelPoint(MWindow *mwindow,
2315 CWindowMaskGUI *gui, int x, int y)
2316 : BC_GenericButton(x, y, _("Delete"))
2318 this->mwindow = mwindow;
2320 set_tooltip(_("Delete point"));
2323 int CWindowMaskDelPoint::handle_event()
2332 // Get existing keyframe
2333 gui->get_keyframe(track, autos, keyframe, mask, point, 0);
2335 mwindow->undo->update_undo_before(_("point delete"), 0);
2337 #ifdef USE_KEYFRAME_SPANNING
2338 // Create temp keyframe
2339 MaskAuto temp_keyframe(mwindow->edl, autos);
2340 temp_keyframe.copy_data(keyframe);
2342 SubMask *submask = temp_keyframe.get_submask(mwindow->edl->session->cwindow_mask);
2343 int i = mwindow->cwindow->gui->affected_point;
2344 for( ; i<submask->points.total-1; ++i )
2345 *submask->points.values[i] = *submask->points.values[i+1];
2346 if( submask->points.total > 0 ) {
2347 point = submask->points.values[submask->points.total-1];
2348 submask->points.remove_object(point);
2350 total_points = submask->points.total;
2352 // Commit change to span of keyframes
2353 ((MaskAutos*)track->automation->autos[AUTOMATION_MASK])->update_parameter(&temp_keyframe);
2356 MaskAuto *current = (MaskAuto*)autos->default_auto;
2358 SubMask *submask = current->get_submask(mwindow->edl->session->cwindow_mask);
2359 int i = mwindow->cwindow->gui->affected_point;
2360 for( ; i<submask->points.total-1; ++i )
2361 *submask->points.values[i] = *submask->points.values[i+1];
2362 if( submask->points.total > 0 ) {
2363 point = submask->points.values[submask->points.total-1];
2364 submask->points.remove_object(point);
2366 total_points = submask->points.total;
2367 current = current == (MaskAuto*)autos->default_auto ?
2368 (MaskAuto*)autos->first : (MaskAuto*)NEXT;
2371 if( mwindow->cwindow->gui->affected_point >= total_points )
2372 mwindow->cwindow->gui->affected_point =
2373 total_points > 0 ? total_points-1 : 0;
2376 gui->update_preview();
2377 mwindow->undo->update_undo_after(_("point delete"), LOAD_AUTOMATION);
2384 CWindowMaskAffectedPoint::CWindowMaskAffectedPoint(MWindow *mwindow,
2385 CWindowMaskGUI *gui, int x, int y)
2386 : BC_TumbleTextBox(gui,
2387 (int64_t)mwindow->cwindow->gui->affected_point,
2388 (int64_t)0, INT64_MAX, x, y, xS(70))
2390 this->mwindow = mwindow;
2394 CWindowMaskAffectedPoint::~CWindowMaskAffectedPoint()
2398 int CWindowMaskAffectedPoint::handle_event()
2400 int total_points = 0;
2401 int affected_point = atol(get_text());
2402 Track *track = mwindow->cwindow->calculate_mask_track();
2404 MaskAutos *autos = (MaskAutos*)track->automation->autos[AUTOMATION_MASK];
2405 MaskAuto *keyframe = (MaskAuto*)mwindow->cwindow->calculate_affected_auto(autos, 0);
2407 SubMask *mask = keyframe->get_submask(mwindow->edl->session->cwindow_mask);
2408 total_points = mask->points.size();
2411 int active_point = affected_point;
2412 if( affected_point >= total_points )
2413 affected_point = total_points - 1;
2414 if( affected_point < 0 )
2416 if( active_point != affected_point )
2417 update((int64_t)affected_point);
2418 mwindow->cwindow->gui->affected_point = affected_point;
2420 gui->update_preview();
2425 CWindowMaskFocus::CWindowMaskFocus(MWindow *mwindow, CWindowMaskGUI *gui, int x, int y)
2426 : BC_CheckBox(x, y, gui->focused, _("Focus"))
2428 this->mwindow = mwindow;
2430 set_tooltip(_("Center for rotate/scale"));
2433 CWindowMaskFocus::~CWindowMaskFocus()
2437 int CWindowMaskFocus::handle_event()
2439 gui->focused = get_value();
2441 gui->update_preview();
2445 int CWindowMaskFocus::calculate_w(CWindowMaskGUI *gui)
2448 calculate_extents(gui, &w, &h, _("Focus"));
2452 CWindowMaskScaleXY::CWindowMaskScaleXY(MWindow *mwindow, CWindowMaskGUI *gui,
2453 int x, int y, VFrame **data, int v, int id, const char *tip)
2454 : BC_Toggle(x, y, data, v)
2457 this->mwindow = mwindow;
2462 CWindowMaskScaleXY::~CWindowMaskScaleXY()
2466 int CWindowMaskScaleXY::handle_event()
2468 gui->scale_mode = id;
2469 gui->mask_scale_x->update(id == MASK_SCALE_X);
2470 gui->mask_scale_y->update(id == MASK_SCALE_Y);
2471 gui->mask_scale_xy->update(id == MASK_SCALE_XY);
2475 CWindowMaskHelp::CWindowMaskHelp(MWindow *mwindow, CWindowMaskGUI *gui, int x, int y)
2476 : BC_CheckBox(x, y, 0, _("Help"))
2478 this->mwindow = mwindow;
2480 set_tooltip(_("Show help text"));
2483 CWindowMaskHelp::~CWindowMaskHelp()
2487 int CWindowMaskHelp::handle_event()
2489 gui->helped = get_value();
2490 gui->resize_window(gui->get_w(),
2491 gui->helped ? gui->help_h : gui->help_y);
2496 CWindowMaskDrawMarkers::CWindowMaskDrawMarkers(MWindow *mwindow, CWindowMaskGUI *gui, int x, int y)
2497 : BC_CheckBox(x, y, gui->markers, _("Markers"))
2499 this->mwindow = mwindow;
2501 set_tooltip("Display points");
2504 CWindowMaskDrawMarkers::~CWindowMaskDrawMarkers()
2508 int CWindowMaskDrawMarkers::handle_event()
2510 gui->markers = get_value();
2512 gui->update_preview();
2516 CWindowMaskDrawBoundary::CWindowMaskDrawBoundary(MWindow *mwindow, CWindowMaskGUI *gui, int x, int y)
2517 : BC_CheckBox(x, y, gui->boundary, _("Boundary"))
2519 this->mwindow = mwindow;
2521 set_tooltip("Display mask outline");
2524 CWindowMaskDrawBoundary::~CWindowMaskDrawBoundary()
2528 int CWindowMaskDrawBoundary::handle_event()
2530 gui->boundary = get_value();
2532 gui->update_preview();
2537 CWindowMaskFeather::CWindowMaskFeather(MWindow *mwindow, CWindowMaskGUI *gui, int x, int y)
2538 : BC_TumbleTextBox(gui, 0, INT_MIN, INT_MAX, x, y, xS(64), 2)
2540 this->mwindow = mwindow;
2543 CWindowMaskFeather::~CWindowMaskFeather()
2547 int CWindowMaskFeather::update(float v)
2549 gui->feather_slider->update(v);
2550 return BC_TumbleTextBox::update(v);
2553 int CWindowMaskFeather::update_value(float v)
2560 #ifdef USE_KEYFRAME_SPANNING
2566 mwindow->undo->update_undo_before(_("mask feather"), this);
2568 // Get existing keyframe
2569 gui->get_keyframe(track, autos, keyframe,
2570 mask, point, create_it);
2572 int gang = gui->gang_feather->get_value();
2573 #ifdef USE_KEYFRAME_SPANNING
2574 MaskAuto temp_keyframe(mwindow->edl, autos);
2575 temp_keyframe.copy_data(keyframe);
2576 keyframe = &temp_keyframe;
2578 float change = v - mask->feather;
2579 int k = mwindow->edl->session->cwindow_mask;
2580 int n = gang ? keyframe->masks.size() : k+1;
2581 for( int i=gang? 0 : k; i<n; ++i ) {
2582 if( !gui->mask_enables[i]->get_value() ) continue;
2583 SubMask *sub_mask = keyframe->get_submask(i);
2584 float feather = sub_mask->feather + change;
2585 sub_mask->feather = feather;
2587 #ifdef USE_KEYFRAME_SPANNING
2588 autos->update_parameter(keyframe);
2590 gui->update_preview();
2593 mwindow->undo->update_undo_after(_("mask feather"), LOAD_AUTOMATION);
2597 int CWindowMaskFeather::handle_event()
2599 float v = atof(get_text());
2600 if( fabsf(v) > MAX_FEATHER )
2601 BC_TumbleTextBox::update((float)(v>=0 ? MAX_FEATHER : -MAX_FEATHER));
2602 gui->feather_slider->update(v);
2603 return gui->feather->update_value(v);
2606 CWindowMaskFeatherSlider::CWindowMaskFeatherSlider(MWindow *mwindow,
2607 CWindowMaskGUI *gui, int x, int y, int w, float v)
2608 : BC_FSlider(x, y, 0, w, w, -FEATHER_MAX-5, FEATHER_MAX+5, v)
2610 this->mwindow = mwindow;
2612 set_precision(0.01);
2613 timer = new Timer();
2619 CWindowMaskFeatherSlider::~CWindowMaskFeatherSlider()
2624 int CWindowMaskFeatherSlider::handle_event()
2627 float v = get_value();
2628 if( fabsf(v) > MAX_FEATHER )
2629 v = v>=0 ? MAX_FEATHER : -MAX_FEATHER;
2630 if( stick && timer->get_difference() >= 250 )
2631 stick = 0; // no events for .25 sec
2632 if( stick && (last_v * (v-last_v)) < 0 )
2633 stick = 0; // dv changed direction
2642 if( max > MAX_FEATHER ) max = MAX_FEATHER;
2643 update(get_w(), v=last_v, -max-5, max+5);
2644 button_release_event();
2647 else if( v > max ) { v = max; sticky = 24; }
2648 else if( v < -max ) { v = -max; sticky = 24; }
2649 else if( v>=0 ? last_v<0 : last_v>=0 ) { v = 0; sticky = 16; }
2650 if( sticky ) { update(v); stick = sticky; timer->update(); }
2652 gui->feather->BC_TumbleTextBox::update(v);
2653 return gui->feather->update_value(v);
2656 int CWindowMaskFeatherSlider::update(float v)
2658 float vv = fabsf(v);
2659 if( vv > MAX_FEATHER ) vv = MAX_FEATHER;
2660 while( max < vv ) max *= 1.25;
2661 return update(get_w(), v, -max-5, max+5);
2663 int CWindowMaskFeatherSlider::update(int r, float v, float mn, float mx)
2665 return BC_FSlider::update(r, v, mn, mx);
2668 CWindowMaskFade::CWindowMaskFade(MWindow *mwindow, CWindowMaskGUI *gui, int x, int y)
2669 : BC_TumbleTextBox(gui, 0, -100.f, 100.f, x, y, xS(64), 2)
2671 this->mwindow = mwindow;
2674 CWindowMaskFade::~CWindowMaskFade()
2678 int CWindowMaskFade::update(float v)
2680 gui->fade_slider->update(v);
2681 return BC_TumbleTextBox::update(v);
2684 int CWindowMaskFade::update_value(float v)
2691 #ifdef USE_KEYFRAME_SPANNING
2697 mwindow->undo->update_undo_before(_("mask fade"), this);
2699 // Get existing keyframe
2700 gui->get_keyframe(track, autos, keyframe,
2701 mask, point, create_it);
2703 int gang = gui->gang_fader->get_value();
2704 #ifdef USE_KEYFRAME_SPANNING
2705 MaskAuto temp_keyframe(mwindow->edl, autos);
2706 temp_keyframe.copy_data(keyframe);
2707 keyframe = &temp_keyframe;
2709 float change = v - mask->fader;
2710 int k = mwindow->edl->session->cwindow_mask;
2711 int n = gang ? keyframe->masks.size() : k+1;
2712 for( int i=gang? 0 : k; i<n; ++i ) {
2713 if( !gui->mask_enables[i]->get_value() ) continue;
2714 SubMask *sub_mask = keyframe->get_submask(i);
2715 float fader = sub_mask->fader + change;
2716 bclamp(fader, -100.f, 100.f);
2717 sub_mask->fader = fader;
2719 #ifdef USE_KEYFRAME_SPANNING
2720 autos->update_parameter(keyframe);
2722 gui->update_preview();
2725 mwindow->undo->update_undo_after(_("mask fade"), LOAD_AUTOMATION);
2729 int CWindowMaskFade::handle_event()
2731 float v = atof(get_text());
2732 gui->fade_slider->update(v);
2733 return gui->fade->update_value(v);
2736 CWindowMaskFadeSlider::CWindowMaskFadeSlider(MWindow *mwindow, CWindowMaskGUI *gui,
2737 int x, int y, int w)
2738 : BC_ISlider(x, y, 0, w, w, -200, 200, 0)
2740 this->mwindow = mwindow;
2742 timer = new Timer();
2747 CWindowMaskFadeSlider::~CWindowMaskFadeSlider()
2752 int CWindowMaskFadeSlider::handle_event()
2754 float v = 100*get_value()/200;
2756 int64_t ms = timer->get_difference();
2757 if( ms < 250 && --stick > 0 ) {
2758 if( get_value() == 0 ) return 1;
2766 else if( (last_v>=0 && v<0) || (last_v<0 && v>=0) ) {
2773 gui->fade->BC_TumbleTextBox::update(v);
2774 return gui->fade->update_value(v);
2777 int CWindowMaskFadeSlider::update(int64_t v)
2779 return BC_ISlider::update(200*v/100);
2782 CWindowMaskGangFader::CWindowMaskGangFader(MWindow *mwindow,
2783 CWindowMaskGUI *gui, int x, int y)
2784 : BC_Toggle(x, y, mwindow->theme->get_image_set("gangpatch_data"), 0)
2786 this->mwindow = mwindow;
2788 set_tooltip(_("Gang fader"));
2791 CWindowMaskGangFader::~CWindowMaskGangFader()
2795 int CWindowMaskGangFader::handle_event()
2800 CWindowMaskGangFocus::CWindowMaskGangFocus(MWindow *mwindow,
2801 CWindowMaskGUI *gui, int x, int y)
2802 : BC_Toggle(x, y, mwindow->theme->get_image_set("gangpatch_data"), 0)
2804 this->mwindow = mwindow;
2806 set_tooltip(_("Gang rotate/scale/translate"));
2809 CWindowMaskGangFocus::~CWindowMaskGangFocus()
2813 int CWindowMaskGangFocus::handle_event()
2818 CWindowMaskGangPoint::CWindowMaskGangPoint(MWindow *mwindow,
2819 CWindowMaskGUI *gui, int x, int y)
2820 : BC_Toggle(x, y, mwindow->theme->get_image_set("gangpatch_data"), 0)
2822 this->mwindow = mwindow;
2824 set_tooltip(_("Gang points"));
2827 CWindowMaskGangPoint::~CWindowMaskGangPoint()
2831 int CWindowMaskGangPoint::handle_event()
2837 CWindowMaskSmoothButton::CWindowMaskSmoothButton(MWindow *mwindow, CWindowMaskGUI *gui,
2838 const char *tip, int type, int on, int x, int y, const char *images)
2839 : BC_Button(x, y, mwindow->theme->get_image_set(images))
2841 this->mwindow = mwindow;
2848 int CWindowMaskSmoothButton::handle_event()
2850 return gui->smooth_mask(type, on);
2853 CWindowMaskBeforePlugins::CWindowMaskBeforePlugins(CWindowMaskGUI *gui, int x, int y)
2854 : BC_CheckBox(x, y, 1, _("Apply mask before plugins"))
2859 int CWindowMaskBeforePlugins::handle_event()
2866 gui->get_keyframe(track, autos, keyframe, mask, point, 1);
2869 int v = get_value();
2870 #ifdef USE_KEYFRAME_SPANNING
2871 MaskAuto temp_keyframe(gui->mwindow->edl, autos);
2872 temp_keyframe.copy_data(keyframe);
2873 temp_keyframe.apply_before_plugins = v;
2874 autos->update_parameter(&temp_keyframe);
2876 keyframe->apply_before_plugins = v;
2878 gui->update_preview();
2884 CWindowDisableOpenGLMasking::CWindowDisableOpenGLMasking(CWindowMaskGUI *gui, int x, int y)
2885 : BC_CheckBox(x, y, 1, _("Disable OpenGL masking"))
2890 int CWindowDisableOpenGLMasking::handle_event()
2897 gui->get_keyframe(track, autos, keyframe, mask, point, 1);
2900 int v = get_value();
2901 #ifdef USE_KEYFRAME_SPANNING
2902 MaskAuto temp_keyframe(gui->mwindow->edl, autos);
2903 temp_keyframe.copy_data(keyframe);
2904 temp_keyframe.disable_opengl_masking = v;
2905 autos->update_parameter(&temp_keyframe);
2907 keyframe->disable_opengl_masking = v;
2909 gui->update_preview();
2915 CWindowMaskClrMask::CWindowMaskClrMask(MWindow *mwindow,
2916 CWindowMaskGUI *gui, int x, int y)
2917 : BC_Button(x, y, mwindow->theme->get_image_set("reset_button"))
2919 this->mwindow = mwindow;
2921 set_tooltip(_("Delete all masks"));
2924 CWindowMaskClrMask::~CWindowMaskClrMask()
2928 int CWindowMaskClrMask::calculate_w(MWindow *mwindow)
2930 VFrame *vfrm = *mwindow->theme->get_image_set("reset_button");
2931 return vfrm->get_w();
2934 int CWindowMaskClrMask::handle_event()
2942 // Get existing keyframe
2943 gui->get_keyframe(track, autos, keyframe, mask, point, 0);
2946 mwindow->undo->update_undo_before(_("del masks"), 0);
2947 ((MaskAutos*)track->automation->autos[AUTOMATION_MASK])->clear_all();
2948 mwindow->undo->update_undo_after(_("del masks"), LOAD_AUTOMATION);
2952 gui->update_preview(1);
2956 CWindowMaskGangFeather::CWindowMaskGangFeather(MWindow *mwindow,
2957 CWindowMaskGUI *gui, int x, int y)
2958 : BC_Toggle(x, y, mwindow->theme->get_image_set("gangpatch_data"), 0)
2960 this->mwindow = mwindow;
2962 set_tooltip(_("Gang feather"));
2965 CWindowMaskGangFeather::~CWindowMaskGangFeather()
2969 int CWindowMaskGangFeather::handle_event()
2974 CWindowMaskGUI::CWindowMaskGUI(MWindow *mwindow, CWindowTool *thread)
2975 : CWindowToolGUI(mwindow, thread,
2976 _(PROGRAM_NAME ": Mask"), xS(440), yS(700))
2978 this->mwindow = mwindow;
2979 this->thread = thread;
2988 // *** CONTEXT_HELP ***
2989 context_help_set_keyword("Masks");
2991 CWindowMaskGUI::~CWindowMaskGUI()
2993 lock_window("CWindowMaskGUI::~CWindowMaskGUI");
2995 delete active_point;
2999 delete preset_dialog;
3002 void CWindowMaskGUI::create_objects()
3005 Theme *theme = mwindow->theme;
3006 int xs10 = xS(10), ys10 = yS(10);
3007 int x = xs10, y = ys10;
3008 int margin = theme->widget_border;
3009 int clr_w = CWindowMaskClrMask::calculate_w(mwindow);
3010 int clr_x = get_w()-x - clr_w;
3012 lock_window("CWindowMaskGUI::create_objects");
3013 BC_TitleBar *title_bar;
3014 add_subwindow(title_bar = new BC_TitleBar(x, y, get_w()-2*x, xS(20), xS(10),
3015 _("Masks on Track")));
3016 y += title_bar->get_h() + margin;
3018 add_subwindow(title = new BC_Title(x,y, _("Track:")));
3019 int x1 = x + xS(90), ww = clr_x-2*margin - x1;
3020 for( int i=0,n=sizeof(t)/sizeof(t[0]); i<n; ++i ) t[i] = x1+(i*ww)/n;
3022 Track *track = mwindow->cwindow->calculate_affected_track();
3023 const char *text = track ? track->title : "";
3024 mwindow->cwindow->mask_track_id = track ? track->get_id() : -1;
3025 mask_on_track = new CWindowMaskOnTrack(mwindow, this, x1, y, xS(100), text);
3026 mask_on_track->create_objects();
3027 mask_on_track->set_tooltip(_("Video track"));
3028 int x2 = x1 + mask_on_track->get_w();
3029 add_subwindow(mask_track_tumbler = new CWindowMaskTrackTumbler(mwindow, this, x2, y));
3030 mwindow->edl->local_session->solo_track_id = -1;
3031 add_subwindow(mask_solo_track = new CWindowMaskSoloTrack(mwindow, this, del_x, y, 0));
3032 y += mask_on_track->get_h() + margin;
3033 add_subwindow(title_bar = new BC_TitleBar(x, y, get_w()-2*x, xS(20), xS(10),
3035 y += title_bar->get_h() + margin;
3036 add_subwindow(title = new BC_Title(x, y, _("Mask:")));
3037 mask_name = new CWindowMaskName(mwindow, this, x1, y, "");
3038 mask_name->create_objects();
3039 mask_name->set_tooltip(_("Mask name"));
3040 add_subwindow(mask_clr = new CWindowMaskClrMask(mwindow, this, clr_x, y));
3041 add_subwindow(mask_del = new CWindowMaskDelMask(mwindow, this, del_x, y));
3042 y += mask_name->get_h() + 2*margin;
3044 // add_subwindow(bar = new BC_Bar(x, y, get_w()-2*x));
3045 // y += bar->get_h() + 2*margin;
3047 add_subwindow(title = new BC_Title(x, y, _("Select:")));
3049 BC_CheckBox::calculate_extents(this, &bw, &bh);
3050 for( int i=0; i<SUBMASKS; ++i ) {
3051 int v = i == mwindow->edl->session->cwindow_mask ? 1 : 0;
3052 mask_buttons[i] = new CWindowMaskButton(mwindow, this, t[i], y, i, v);
3053 add_subwindow(mask_buttons[i]);
3055 add_subwindow(mask_thumbler = new CWindowMaskThumbler(mwindow, this, clr_x, y));
3057 for( int i=0; i<SUBMASKS; ++i ) {
3058 char text[BCSTRLEN]; sprintf(text, "%d", i);
3059 int tx = (bw - get_text_width(MEDIUMFONT, text)) / 2;
3060 mask_blabels[i] = new BC_Title(t[i]+tx, y, text);
3061 add_subwindow(mask_blabels[i]);
3063 y += mask_blabels[0]->get_h() + margin;
3064 add_subwindow(title = new BC_Title(x, y, _("Enable:")));
3065 for( int i=0; i<SUBMASKS; ++i ) {
3066 mask_enables[i] = new CWindowMaskEnable(mwindow, this, t[i], y, i, 1);
3067 add_subwindow(mask_enables[i]);
3069 add_subwindow(mask_unclr = new CWindowMaskUnclear(mwindow, this, clr_x, y));
3070 y += mask_enables[0]->get_h() + 2*margin;
3071 add_subwindow(title_bar = new BC_TitleBar(x, y, get_w()-2*x, xS(20), xS(10),
3072 _("Preset Shapes")));
3073 y += title_bar->get_h() + margin;
3074 add_subwindow(mask_shape_sqr = new CWindowMaskShape(mwindow, this,
3075 "mask_prst_sqr_images", MASK_SHAPE_SQUARE, t[0], y, _("Square")));
3076 add_subwindow(mask_shape_crc = new CWindowMaskShape(mwindow, this,
3077 "mask_prst_crc_images", MASK_SHAPE_CIRCLE, t[1], y, _("Circle")));
3078 add_subwindow(mask_shape_tri = new CWindowMaskShape(mwindow, this,
3079 "mask_prst_tri_images", MASK_SHAPE_TRIANGLE, t[2], y, _("Triangle")));
3080 add_subwindow(mask_shape_ovl = new CWindowMaskShape(mwindow, this,
3081 "mask_prst_ovl_images", MASK_SHAPE_OVAL, t[3], y, _("Oval")));
3082 add_subwindow(mask_load_list = new CWindowMaskLoadList(mwindow, this));
3083 add_subwindow(mask_load = new CWindowMaskLoad(mwindow, this, t[5], y, xS(80)));
3084 add_subwindow(mask_save = new CWindowMaskSave(mwindow, this, t[6], y, xS(80)));
3085 add_subwindow(mask_delete = new CWindowMaskDelete(mwindow, this, t[7], y, xS(80)));
3086 y += mask_load->get_h() + 2*margin;
3087 add_subwindow(title_bar = new BC_TitleBar(x, y, get_w()-2*x, xS(20), xS(10),
3088 _("Position & Scale")));
3089 y += title_bar->get_h() + 2*margin;
3090 add_subwindow(mask_center = new CWindowMaskCenter(mwindow, this, t[0], y, xS(80)));
3091 add_subwindow(mask_normal = new CWindowMaskNormal(mwindow, this, t[1], y, xS(80)));
3093 add_subwindow(mask_scale_x = new CWindowMaskScaleXY(mwindow, this,
3094 t[5], y, theme->get_image_set("mask_scale_x"), 0, MASK_SCALE_X, _("xlate/scale x")));
3095 add_subwindow(mask_scale_y = new CWindowMaskScaleXY(mwindow, this,
3096 t[6], y, theme->get_image_set("mask_scale_y"), 0, MASK_SCALE_Y, _("xlate/scale y")));
3097 add_subwindow(mask_scale_xy = new CWindowMaskScaleXY(mwindow, this,
3098 t[7], y, theme->get_image_set("mask_scale_xy"), 1, MASK_SCALE_XY, _("xlate/scale xy")));
3099 y += mask_center->get_h() + 2*margin;
3100 add_subwindow(title_bar = new BC_TitleBar(x, y, get_w()-2*x, xS(20), xS(10),
3101 _("Fade & Feather")));
3102 y += title_bar->get_h() + 2*margin;
3104 add_subwindow(title = new BC_Title(x, y, _("Fade:")));
3105 fade = new CWindowMaskFade(mwindow, this, x1, y);
3106 fade->create_objects();
3107 x2 = x1 + fade->get_w() + 2*margin;
3108 int w2 = clr_x-2*margin - x2;
3109 add_subwindow(fade_slider = new CWindowMaskFadeSlider(mwindow, this, x2, y, w2));
3110 add_subwindow(gang_fader = new CWindowMaskGangFader(mwindow, this, clr_x, y));
3111 y += fade->get_h() + margin;
3112 add_subwindow(title = new BC_Title(x, y, _("Feather:")));
3113 feather = new CWindowMaskFeather(mwindow, this, x1, y);
3114 feather->create_objects();
3115 w2 = clr_x - 2*margin - x2;
3116 feather_slider = new CWindowMaskFeatherSlider(mwindow, this, x2, y, w2, 0);
3117 add_subwindow(feather_slider);
3118 add_subwindow(gang_feather = new CWindowMaskGangFeather(mwindow, this, clr_x, y));
3119 y += feather->get_h() + 2*margin;
3120 add_subwindow(title_bar = new BC_TitleBar(x, y, get_w()-2*x, xS(20), xS(10),
3122 y += title_bar->get_h() + margin;
3124 add_subwindow(title = new BC_Title(x, y, _("Point:")));
3125 active_point = new CWindowMaskAffectedPoint(mwindow, this, t[0], y);
3126 active_point->create_objects();
3127 // typ=0, this mask, this point
3128 add_subwindow(mask_pnt_linear = new CWindowMaskSmoothButton(mwindow, this,
3129 _("linear point"), 0, 0, t[3], y, "mask_pnt_linear_images"));
3130 add_subwindow(mask_pnt_smooth = new CWindowMaskSmoothButton(mwindow, this,
3131 _("smooth point"), 0, 1, t[4], y, "mask_pnt_smooth_images"));
3132 add_subwindow(del_point = new CWindowMaskDelPoint(mwindow, this, del_x, y));
3133 add_subwindow(gang_point = new CWindowMaskGangPoint(mwindow, this, clr_x, y));
3134 y += active_point->get_h() + margin;
3135 add_subwindow(title = new BC_Title(x, y, "X:"));
3136 this->x = new CWindowCoord(this, t[0], y, (float)0.0);
3137 this->x->create_objects();
3138 // typ>0, this mask, all points
3139 add_subwindow(mask_crv_linear = new CWindowMaskSmoothButton(mwindow, this,
3140 _("linear curve"), 1, 0, t[3], y, "mask_crv_linear_images"));
3141 add_subwindow(mask_crv_smooth = new CWindowMaskSmoothButton(mwindow, this,
3142 _("smooth curve"), 1, 1, t[4], y, "mask_crv_smooth_images"));
3143 add_subwindow(draw_markers = new CWindowMaskDrawMarkers(mwindow, this, del_x, y));
3144 y += this->x->get_h() + margin;
3145 add_subwindow(title = new BC_Title(x, y, "Y:"));
3146 this->y = new CWindowCoord(this, x1, y, (float)0.0);
3147 this->y->create_objects();
3148 // typ<0, all masks, all points
3149 add_subwindow(mask_all_linear = new CWindowMaskSmoothButton(mwindow, this,
3150 _("linear all"), -1, 0, t[3], y, "mask_all_linear_images"));
3151 add_subwindow(mask_all_smooth = new CWindowMaskSmoothButton(mwindow, this,
3152 _("smooth all"), -1, 1, t[4], y, "mask_all_smooth_images"));
3153 add_subwindow(draw_boundary = new CWindowMaskDrawBoundary(mwindow, this, del_x, y));
3154 y += this->y->get_h() + 2*margin;
3155 add_subwindow(title_bar = new BC_TitleBar(x, y, get_w()-2*x, xS(20), xS(10),
3157 y += title_bar->get_h() + margin;
3159 add_subwindow(title = new BC_Title(x, y, "X:"));
3160 float cx = mwindow->edl->session->output_w / 2.f;
3161 focus_x = new CWindowCoord(this, x1, y, cx);
3162 focus_x->create_objects();
3163 add_subwindow(focus = new CWindowMaskFocus(mwindow, this, del_x, y));
3164 add_subwindow(gang_focus = new CWindowMaskGangFocus(mwindow, this, clr_x, y));
3165 y += focus_x->get_h() + margin;
3166 add_subwindow(title = new BC_Title(x, y, "Y:"));
3167 float cy = mwindow->edl->session->output_h / 2.f;
3168 focus_y = new CWindowCoord(this, x1, y, cy);
3169 focus_y->create_objects();
3170 y += focus_y->get_h() + 2*margin;
3171 add_subwindow(bar = new BC_Bar(x, y, get_w()-2*x));
3172 y += bar->get_h() + margin;
3173 add_subwindow(this->apply_before_plugins = new CWindowMaskBeforePlugins(this, x, y));
3174 y += this->apply_before_plugins->get_h();
3175 add_subwindow(this->disable_opengl_masking = new CWindowDisableOpenGLMasking(this, x, y));
3176 add_subwindow(help = new CWindowMaskHelp(mwindow, this, del_x, y));
3177 y += this->disable_opengl_masking->get_h() + 2*margin;
3179 add_subwindow(bar = new BC_Bar(x, y, get_w()-2*x));
3180 y += bar->get_h() + 2*margin;
3181 add_subwindow(title = new BC_Title(x, y, _(
3182 "Shift+LMB: move an end point\n"
3183 "Ctrl+LMB: move a control point\n"
3184 "Alt+LMB: to drag translate the mask\n"
3185 "Shift+MMB: Set Pivot Point at pointer\n"
3186 "Wheel: rotate around Pivot Point\n"
3187 "Shift+Wheel: scale around Pivot Point\n"
3188 "Ctrl+Wheel: rotate/scale around pointer")));
3189 help_h = y + title->get_h() + 2*margin;
3191 resize_window(get_w(), help_y);
3195 int CWindowMaskGUI::close_event()
3198 return CWindowToolGUI::close_event();
3201 void CWindowMaskGUI::done_event()
3203 if( mwindow->in_destructor ) return;
3204 int &solo_track_id = mwindow->edl->local_session->solo_track_id;
3205 if( solo_track_id >= 0 ) {
3211 void CWindowMaskGUI::get_keyframe(Track* &track,
3212 MaskAutos* &autos, MaskAuto* &keyframe,
3213 SubMask* &mask, MaskPoint* &point, int create_it)
3218 track = mwindow->cwindow->calculate_mask_track();
3220 track = mwindow->cwindow->calculate_affected_track();
3223 autos = (MaskAutos*)track->automation->autos[AUTOMATION_MASK];
3224 keyframe = (MaskAuto*)mwindow->cwindow->calculate_affected_auto(
3229 mask = !keyframe ? 0 :
3230 keyframe->get_submask(mwindow->edl->session->cwindow_mask);
3234 if( mwindow->cwindow->gui->affected_point < mask->points.total &&
3235 mwindow->cwindow->gui->affected_point >= 0 ) {
3236 point = mask->points.values[mwindow->cwindow->gui->affected_point];
3241 void CWindowMaskGUI::update()
3248 //printf("CWindowMaskGUI::update 1\n");
3249 get_keyframe(track, autos, keyframe, mask, point, 0);
3250 mwindow->cwindow->mask_track_id = track ? track->get_id() : -1;
3251 mask_on_track->set_back_color(!track || track->is_armed() ?
3252 get_resources()->text_background :
3253 get_resources()->text_background_disarmed);
3254 mask_on_track->update_items();
3255 mask_on_track->update(!track ? "" : track->title);
3256 mask_name->update_items(keyframe);
3257 const char *text = "";
3258 int sz = !keyframe ? 0 : keyframe->masks.size();
3259 int k = mwindow->edl->session->cwindow_mask;
3260 if( k >= 0 && k < sz )
3261 text = keyframe->masks[k]->name;
3263 k = mwindow->edl->session->cwindow_mask = 0;
3264 mask_name->update(text);
3265 update_buttons(keyframe, k);
3267 x->update(point->x);
3268 y->update(point->y);
3271 double position = mwindow->edl->local_session->get_selectionstart(1);
3272 int64_t position_i = track->to_units(position, 0);
3273 feather->update(autos->get_feather(position_i, k, PLAY_FORWARD));
3274 fade->update(autos->get_fader(position_i, k, PLAY_FORWARD));
3275 int show_mask = track->masks;
3276 for( int i=0; i<SUBMASKS; ++i )
3277 mask_enables[i]->update((show_mask>>i) & 1);
3280 apply_before_plugins->update(keyframe->apply_before_plugins);
3281 disable_opengl_masking->update(keyframe->disable_opengl_masking);
3283 active_point->update((int64_t)mwindow->cwindow->gui->affected_point);
3286 void CWindowMaskGUI::handle_event()
3289 if( event_caller == this->focus_x ||
3290 event_caller == this->focus_y ) {
3293 else if( event_caller == this->x ||
3294 event_caller == this->y ) {
3300 get_keyframe(track, autos, keyframe, mask, point, 0);
3302 mwindow->undo->update_undo_before(_("mask point"), this);
3305 float px = atof(x->get_text());
3306 float py = atof(y->get_text());
3307 float dx = px - point->x, dy = py - point->y;
3308 #ifdef USE_KEYFRAME_SPANNING
3309 // Create temp keyframe
3310 MaskAuto temp_keyframe(mwindow->edl, autos);
3311 temp_keyframe.copy_data(keyframe);
3312 // Get affected point in temp keyframe
3313 mask = temp_keyframe.get_submask(mwindow->edl->session->cwindow_mask);
3315 MaskPoints &points = mask->points;
3316 int gang = gang_point->get_value();
3317 int k = mwindow->cwindow->gui->affected_point;
3318 int n = gang ? points.size() : k+1;
3319 for( int i=gang? 0 : k; i<n; ++i ) {
3320 if( i < 0 || i >= points.size() ) continue;
3321 MaskPoint *point = points[i];
3322 point->x += dx; point->y += dy;
3324 #ifdef USE_KEYFRAME_SPANNING
3325 // Commit to spanned keyframes
3326 autos->update_parameter(&temp_keyframe);
3329 mwindow->undo->update_undo_after(_("mask point"), LOAD_AUTOMATION);
3337 void CWindowMaskGUI::set_focused(int v, float cx, float cy)
3339 CWindowGUI *cgui = mwindow->cwindow->gui;
3340 cgui->unlock_window();
3341 lock_window("CWindowMaskGUI::set_focused");
3343 focus->update(focused = v);
3344 focus_x->update(cx);
3345 focus_y->update(cy);
3347 cgui->lock_window("CWindowCanvas::set_focused");
3350 void CWindowMaskGUI::update_buttons(MaskAuto *keyframe, int k)
3352 int text_color = get_resources()->default_text_color;
3353 int high_color = get_resources()->button_highlighted;
3354 for( int i=0; i<SUBMASKS; ++i ) {
3355 int color = text_color;
3357 SubMask *submask = keyframe->get_submask(i);
3358 if( submask && submask->points.size() )
3361 mask_blabels[i]->set_color(color);
3362 mask_buttons[i]->update(i==k ? 1 : 0);
3366 // typ=0, this mask, this point
3367 // typ>0, this mask, all points
3368 // typ<0, all masks, all points
3369 // dxy= on? pt[+1]-pt[-1] : dxy=0
3370 int CWindowMaskGUI::smooth_mask(int typ, int on)
3377 #ifdef USE_KEYFRAME_SPANNING
3383 mwindow->undo->update_undo_before(_("mask smooth"), this);
3385 // Get existing keyframe
3386 get_keyframe(track, autos, keyframe,
3387 mask, point, create_it);
3389 #ifdef USE_KEYFRAME_SPANNING
3390 MaskAuto temp_keyframe(mwindow->edl, autos);
3391 temp_keyframe.copy_data(keyframe);
3392 keyframe = &temp_keyframe;
3394 int k = mwindow->edl->session->cwindow_mask;
3395 int n = typ>=0 ? k+1 : keyframe->masks.size();
3396 for( int j=typ<0? 0 : k; j<n; ++j ) {
3397 if( !mask_enables[j]->get_value() ) continue;
3398 SubMask *sub_mask = keyframe->get_submask(j);
3399 MaskPoints &points = sub_mask->points;
3400 int psz = points.size();
3401 if( psz < 3 ) continue;
3402 int l = mwindow->cwindow->gui->affected_point;
3403 if( l > psz ) l = psz;
3404 int m = typ ? psz : l+1;
3405 for( int i=typ ? 0 : l; i<m; ++i ) {
3406 int i0 = i-1, i1 = i+1;
3407 if( i0 < 0 ) i0 = psz-1;
3408 if( i1 >= psz ) i1 = 0;
3409 MaskPoint *p0 = points[i0];
3410 MaskPoint *p = points[i];
3411 MaskPoint *p1 = points[i1];
3412 float dx = !on ? 0 : p1->x - p0->x;
3413 float dy = !on ? 0 : p1->y - p0->y;
3414 p->control_x1 = -dx/4; p->control_y1 = -dy/4;
3415 p->control_x2 = dx/4; p->control_y2 = dy/4;
3418 #ifdef USE_KEYFRAME_SPANNING
3419 autos->update_parameter(keyframe);
3424 mwindow->undo->update_undo_after(_("mask smooth"), LOAD_AUTOMATION);
3428 int CWindowMaskGUI::save_mask(const char *nm)
3430 int k = mwindow->edl->session->cwindow_mask;
3436 get_keyframe(track, autos, keyframe, mask, point, 0);
3437 if( !track ) return 0;
3438 SubMask *sub_mask = keyframe->get_submask(k);
3439 ArrayList<SubMask *> masks;
3441 int i = masks.size();
3443 if( strcmp(masks[i]->name, nm) ) continue;
3444 masks.remove_object_number(i++);
3446 mask = new SubMask(0, -1);
3447 strncpy(mask->name, nm, sizeof(mask->name)-1);
3448 mask->copy_from(*sub_mask, 0);
3451 masks.remove_all_objects();
3455 int CWindowMaskGUI::del_mask(const char *nm)
3457 ArrayList<SubMask *> masks;
3459 int i = masks.size();
3461 if( strcmp(masks[i]->name, nm) ) continue;
3462 masks.remove_object_number(i++);
3465 masks.remove_all_objects();
3469 int CWindowMaskGUI::center_mask()
3471 int k = mwindow->edl->session->cwindow_mask;
3477 #ifdef USE_KEYFRAME_SPANNING
3482 get_keyframe(track, autos, keyframe,
3483 mask, point, create_it);
3484 if( !track ) return 0;
3485 mwindow->undo->update_undo_before(_("mask center"), this);
3487 // Get existing keyframe
3488 #ifdef USE_KEYFRAME_SPANNING
3489 MaskAuto temp_keyframe(mwindow->edl, autos);
3490 temp_keyframe.copy_data(keyframe);
3491 keyframe = &temp_keyframe;
3493 SubMask *sub_mask = keyframe->get_submask(k);
3494 MaskPoints &points = sub_mask->points;
3495 int psz = points.size();
3497 float cx = 0, cy = 0;
3498 for( int i=0; i<psz; ++i ) {
3499 MaskPoint *p = points[i];
3500 cx += p->x; cy += p->y;
3502 cx /= psz; cy /= psz;
3503 cx -= mwindow->edl->session->output_w / 2.f;
3504 cy -= mwindow->edl->session->output_h / 2.f;
3505 for( int i=0; i<psz; ++i ) {
3506 MaskPoint *p = points[i];
3507 p->x -= cx; p->y -= cy;
3510 #ifdef USE_KEYFRAME_SPANNING
3511 autos->update_parameter(keyframe);
3514 mwindow->undo->update_undo_after(_("mask center"), LOAD_AUTOMATION);
3518 int CWindowMaskGUI::normal_mask()
3520 int k = mwindow->edl->session->cwindow_mask;
3526 #ifdef USE_KEYFRAME_SPANNING
3531 // Get existing keyframe
3532 get_keyframe(track, autos, keyframe,
3533 mask, point, create_it);
3534 if( !track ) return 0;
3535 mwindow->undo->update_undo_before(_("mask normal"), this);
3537 #ifdef USE_KEYFRAME_SPANNING
3538 MaskAuto temp_keyframe(mwindow->edl, autos);
3539 temp_keyframe.copy_data(keyframe);
3540 keyframe = &temp_keyframe;
3542 SubMask *sub_mask = keyframe->get_submask(k);
3543 MaskPoints &points = sub_mask->points;
3544 int psz = points.size();
3545 float cx = 0, cy = 0;
3548 for( int i=0; i<psz; ++i ) {
3549 MaskPoint *p = points[i];
3550 cx += p->x; cy += p->y;
3552 cx /= psz; cy /= psz;
3553 for( int i=0; i<psz; ++i ) {
3554 MaskPoint *p = points[i];
3555 float dx = fabsf(p->x-cx), dy = fabsf(p->y-cy);
3556 double d = sqrt(dx*dx + dy*dy);
3557 if( dr < d ) dr = d;
3561 float out_w = mwindow->edl->session->output_w;
3562 float out_h = mwindow->edl->session->output_h;
3563 float r = bmax(out_w, out_h);
3564 float s = r / (4 * dr * sqrt(2.));
3565 for( int i=0; i<psz; ++i ) {
3566 MaskPoint *p = points[i];
3567 float x = p->x, y = p->y;
3568 p->x = (x-cx) * s + cx;
3569 p->y = (y-cy) * s + cy;
3570 p->control_x1 *= s; p->control_y1 *= s;
3571 p->control_x2 *= s; p->control_y2 *= s;
3574 #ifdef USE_KEYFRAME_SPANNING
3575 autos->update_parameter(keyframe);
3579 mwindow->undo->update_undo_after(_("mask normal"), LOAD_AUTOMATION);
3584 CWindowMaskLoadList::CWindowMaskLoadList(MWindow *mwindow, CWindowMaskGUI *gui)
3585 : BC_ListBox(-1, -1, 1, 1, LISTBOX_TEXT, 0, 0, 0, 1, 0, 1)
3587 this->mwindow = mwindow;
3592 CWindowMaskLoadList::~CWindowMaskLoadList()
3597 int CWindowMaskLoadList::handle_event()
3604 #ifdef USE_KEYFRAME_SPANNING
3610 mwindow->undo->update_undo_before(_("mask shape"), this);
3612 // Get existing keyframe
3613 gui->get_keyframe(track, autos, keyframe,
3614 mask, point, create_it);
3615 CWindowMaskItem *item = (CWindowMaskItem *) get_selection(0, 0);
3616 if( track && item ) {
3617 #ifdef USE_KEYFRAME_SPANNING
3618 MaskAuto temp_keyframe(mwindow->edl, autos);
3619 temp_keyframe.copy_data(keyframe);
3620 keyframe = &temp_keyframe;
3621 mask = temp_keyframe.get_submask(mwindow->edl->session->cwindow_mask);
3623 ArrayList<SubMask *> masks;
3624 gui->load_masks(masks);
3625 mask->copy_from(*masks[item->id], 0);
3626 masks.remove_all_objects();
3627 #ifdef USE_KEYFRAME_SPANNING
3628 autos->update_parameter(keyframe);
3631 gui->update_preview(1);
3633 mwindow->undo->update_undo_after(_("mask shape"), LOAD_AUTOMATION);
3637 void CWindowMaskLoadList::create_objects()
3639 shape_items.remove_all_objects();
3640 ArrayList<SubMask *> masks;
3641 gui->load_masks(masks);
3642 for( int i=0; i<masks.size(); ++i )
3643 shape_items.append(new CWindowMaskItem(masks[i]->name, i));
3644 masks.remove_all_objects();
3645 update(&shape_items, 0, 0, 1);
3648 CWindowMaskLoad::CWindowMaskLoad(MWindow *mwindow,
3649 CWindowMaskGUI *gui, int x, int y, int w)
3650 : BC_Button(x, y, mwindow->theme->get_image_set("mask_prst_load_images"))
3652 this->mwindow = mwindow;
3654 set_tooltip(_("Load preset"));
3657 int CWindowMaskLoad::handle_event()
3659 gui->mask_load_list->create_objects();
3661 get_abs_cursor(px, py);
3662 return gui->mask_load_list->activate(px, py, xS(120),yS(160));
3666 CWindowMaskSave::CWindowMaskSave(MWindow *mwindow,
3667 CWindowMaskGUI *gui, int x, int y, int w)
3668 : BC_Button(x, y, mwindow->theme->get_image_set("mask_prst_save_images"))
3670 this->mwindow = mwindow;
3672 set_tooltip(_("Save preset"));
3675 CWindowMaskSave::~CWindowMaskSave()
3679 int CWindowMaskSave::handle_event()
3686 gui->get_keyframe(track, autos, keyframe, mask, point, 0);
3689 gui->get_abs_cursor(sx, sy);
3690 if( !gui->preset_dialog )
3691 gui->preset_dialog = new CWindowMaskPresetDialog(mwindow, gui);
3692 gui->preset_dialog->start_dialog(sx, sy, keyframe);
3697 CWindowMaskPresetDialog::CWindowMaskPresetDialog(MWindow *mwindow, CWindowMaskGUI *gui)
3700 this->mwindow = mwindow;
3705 CWindowMaskPresetDialog::~CWindowMaskPresetDialog()
3710 void CWindowMaskPresetDialog::handle_close_event(int result)
3715 void CWindowMaskPresetDialog::handle_done_event(int result)
3717 if( result ) return;
3718 const char *nm = pgui->preset_text->get_text();
3725 BC_Window* CWindowMaskPresetDialog::new_gui()
3727 pgui = new CWindowMaskPresetGUI(this, sx, sy,
3728 keyframe ? _(PROGRAM_NAME ": Save Mask") :
3729 _(PROGRAM_NAME ": Delete Mask"));
3730 pgui->create_objects();
3734 void CWindowMaskPresetDialog::start_dialog(int sx, int sy, MaskAuto *keyframe)
3737 this->sx = sx; this->sy = sy;
3738 this->keyframe = keyframe;
3742 CWindowMaskPresetGUI::CWindowMaskPresetGUI(CWindowMaskPresetDialog *preset_dialog,
3743 int x, int y, const char *title)
3744 : BC_Window(title, x, y, xS(320), yS(100), xS(320), yS(100), 0, 0, 1)
3746 this->preset_dialog = preset_dialog;
3747 // *** CONTEXT_HELP ***
3748 context_help_set_keyword("Masks");
3751 void CWindowMaskPresetGUI::create_objects()
3753 int xs8 = xS(8), xs10 = xS(10);
3755 int x = xs10, y = ys10;
3756 lock_window("CWindowMaskPresetGUI::create_objects");
3758 add_subwindow(title = new BC_Title(x, y,
3759 preset_dialog->keyframe ? _("Save mask:") : _("Delete mask:")));
3760 int x1 = x + title->get_w() + xs8;
3761 int x2 = get_w() - x - xs8 - x1 -
3762 BC_WindowBase::get_resources()->listbox_button[0]->get_w();
3763 CWindowMaskGUI *gui = preset_dialog->gui;
3764 preset_text = new CWindowMaskPresetText(this,
3765 x1, y, x2, yS(120), gui->mask_name->get_text());
3766 preset_text->create_objects();
3767 preset_text->set_tooltip(_("Mask name"));
3768 preset_text->update_items();
3769 add_subwindow(new BC_OKButton(this));
3770 add_subwindow(new BC_CancelButton(this));
3776 CWindowMaskPresetText::CWindowMaskPresetText(CWindowMaskPresetGUI *pgui,
3777 int x, int y, int w, int h, const char *text)
3778 : BC_PopupTextBox(pgui, 0, text, x, y, w, h)
3783 int CWindowMaskPresetText::handle_event()
3785 int k = get_number();
3786 if( k >= 0 && k<mask_items.size() )
3787 update(mask_items[k]->get_text());
3791 void CWindowMaskPresetText::update_items()
3793 mask_items.remove_all_objects();
3794 ArrayList<SubMask *> masks;
3795 pgui->preset_dialog->gui->load_masks(masks);
3796 for( int i=0; i<masks.size(); ++i ) {
3797 char text[BCSTRLEN]; memset(text, 0, sizeof(text));
3798 strncpy(text, masks[i]->name, sizeof(text)-1);
3799 mask_items.append(new CWindowMaskItem(text));
3801 masks.remove_all_objects();
3802 update_list(&mask_items);
3806 CWindowMaskDelete::CWindowMaskDelete(MWindow *mwindow,
3807 CWindowMaskGUI *gui, int x, int y, int w)
3808 : BC_Button(x, y, mwindow->theme->get_image_set("mask_prst_trsh_images"))
3810 this->mwindow = mwindow;
3812 set_tooltip(_("Delete preset"));
3815 int CWindowMaskDelete::handle_event()
3818 gui->get_abs_cursor(sx, sy);
3819 if( !gui->preset_dialog )
3820 gui->preset_dialog = new CWindowMaskPresetDialog(mwindow, gui);
3821 gui->preset_dialog->start_dialog(sx, sy, 0);
3826 CWindowMaskCenter::CWindowMaskCenter(MWindow *mwindow,
3827 CWindowMaskGUI *gui, int x, int y, int w)
3828 : BC_Button(x, y, mwindow->theme->get_image_set("mask_pstn_cen_images"))
3830 this->mwindow = mwindow;
3832 set_tooltip(_("center mask"));
3835 int CWindowMaskCenter::handle_event()
3837 return gui->center_mask();
3841 CWindowMaskNormal::CWindowMaskNormal(MWindow *mwindow,
3842 CWindowMaskGUI *gui, int x, int y, int w)
3843 : BC_Button(x, y, mwindow->theme->get_image_set("mask_pstn_nrm_images"))
3845 this->mwindow = mwindow;
3847 set_tooltip(_("normalize mask"));
3850 int CWindowMaskNormal::handle_event()
3852 return gui->normal_mask();
3856 CWindowMaskShape::CWindowMaskShape(MWindow *mwindow, CWindowMaskGUI *gui,
3857 const char *images, int shape, int x, int y, const char *tip)
3858 : BC_Button(x, y, mwindow->theme->get_image_set(images))
3860 this->mwindow = mwindow;
3862 this->shape = shape;
3866 CWindowMaskShape::~CWindowMaskShape()
3870 void CWindowMaskShape::builtin_shape(int i, SubMask *sub_mask)
3872 int out_w = mwindow->edl->session->output_w;
3873 int out_h = mwindow->edl->session->output_h;
3874 float cx = out_w/2.f, cy = out_h/2.f;
3875 float r = bmax(cx, cy) / 4.f;
3876 double c = 4*(sqrt(2.)-1)/3; // bezier aprox circle
3877 float r2 = r / 2.f, rc = r*c, r4 = r / 4.f;
3879 MaskPoints &points = sub_mask->points;
3880 points.remove_all_objects();
3882 case MASK_SHAPE_SQUARE:
3883 points.append(pt = new MaskPoint());
3884 pt->x = cx - r; pt->y = cy - r;
3885 points.append(pt = new MaskPoint());
3886 pt->x = cx + r; pt->y = cy - r;
3887 points.append(pt = new MaskPoint());
3888 pt->x = cx + r; pt->y = cy + r;
3889 points.append(pt = new MaskPoint());
3890 pt->x = cx - r; pt->y = cy + r;
3892 case MASK_SHAPE_CIRCLE:
3893 points.append(pt = new MaskPoint());
3894 pt->x = cx - r; pt->y = cy - r;
3895 pt->control_x1 = -rc; pt->control_y1 = rc;
3896 pt->control_x2 = rc; pt->control_y2 = -rc;
3897 points.append(pt = new MaskPoint());
3898 pt->x = cx + r; pt->y = cy - r;
3899 pt->control_x1 = -rc; pt->control_y1 = -rc;
3900 pt->control_x2 = rc; pt->control_y2 = rc;
3901 points.append(pt = new MaskPoint());
3902 pt->x = cx + r; pt->y = cy + r;
3903 pt->control_x1 = rc; pt->control_y1 = -rc;
3904 pt->control_x2 = -rc; pt->control_y2 = rc;
3905 points.append(pt = new MaskPoint());
3906 pt->x = cx - r; pt->y = cy + r;
3907 pt->control_x1 = rc; pt->control_y1 = rc;
3908 pt->control_x2 = -rc; pt->control_y2 = -rc;
3910 case MASK_SHAPE_TRIANGLE:
3911 points.append(pt = new MaskPoint());
3912 pt->x = cx + 0; pt->y = cy - r*(sqrt(3.)-1.);
3913 points.append(pt = new MaskPoint());
3914 pt->x = cx + r; pt->y = cy + r;
3915 points.append(pt = new MaskPoint());
3916 pt->x = cx - r; pt->y = cy + r;
3918 case MASK_SHAPE_OVAL:
3919 points.append(pt = new MaskPoint());
3920 pt->x = cx - r; pt->y = cy - r2;
3921 pt->control_x1 = -r2; pt->control_y1 = r4;
3922 pt->control_x2 = r2; pt->control_y2 = -r4;
3923 points.append(pt = new MaskPoint());
3924 pt->x = cx + r; pt->y = cy - r2;
3925 pt->control_x1 = -r2; pt->control_y1 = -r4;
3926 pt->control_x2 = r2; pt->control_y2 = r4;
3927 points.append(pt = new MaskPoint());
3928 pt->x = cx + r; pt->y = cy + r2;
3929 pt->control_x1 = r2; pt->control_y1 = -r4;
3930 pt->control_x2 = -r2; pt->control_y2 = r4;
3931 points.append(pt = new MaskPoint());
3932 pt->x = cx - r; pt->y = cy + r2;
3933 pt->control_x1 = r2; pt->control_y1 = r4;
3934 pt->control_x2 = -r2; pt->control_y2 = -r4;
3939 int CWindowMaskShape::handle_event()
3946 #ifdef USE_KEYFRAME_SPANNING
3952 mwindow->undo->update_undo_before(_("mask shape"), this);
3954 // Get existing keyframe
3955 gui->get_keyframe(track, autos, keyframe,
3956 mask, point, create_it);
3958 #ifdef USE_KEYFRAME_SPANNING
3959 MaskAuto temp_keyframe(mwindow->edl, autos);
3960 temp_keyframe.copy_data(keyframe);
3961 keyframe = &temp_keyframe;
3962 mask = temp_keyframe.get_submask(mwindow->edl->session->cwindow_mask);
3965 builtin_shape(shape, mask);
3966 #ifdef USE_KEYFRAME_SPANNING
3967 autos->update_parameter(keyframe);
3970 gui->update_preview(1);
3973 mwindow->undo->update_undo_after(_("mask shape"), LOAD_AUTOMATION);
3977 void CWindowMaskGUI::load_masks(ArrayList<SubMask *> &masks)
3979 char path[BCTEXTLEN];
3980 sprintf(path, "%s/%s", File::get_config_path(), MASKS_FILE);
3982 fs.complete_path(path);
3984 file.read_from_file(path, 1);
3986 masks.remove_all_objects();
3988 while( !(result = file.read_tag()) ) {
3989 if( file.tag.title_is("MASK") ) {
3990 SubMask *sub_mask = new SubMask(0, -1);
3991 char name[BCTEXTLEN]; name[0] = 0;
3992 file.tag.get_property("NAME", name);
3993 strncpy(sub_mask->name, name, sizeof(sub_mask->name));
3994 sub_mask->load(&file);
3995 masks.append(sub_mask);
4000 void CWindowMaskGUI::save_masks(ArrayList<SubMask *> &masks)
4003 for( int i=0; i<masks.size(); ++i ) {
4004 SubMask *sub_mask = masks[i];
4005 sub_mask->copy(&file);
4007 file.terminate_string();
4009 char path[BCTEXTLEN];
4010 sprintf(path, "%s/%s", File::get_config_path(), MASKS_FILE);
4012 fs.complete_path(path);
4013 file.write_to_file(path);
4017 CWindowRulerGUI::CWindowRulerGUI(MWindow *mwindow, CWindowTool *thread)
4018 : CWindowToolGUI(mwindow, thread, _(PROGRAM_NAME ": Ruler"), xS(320), yS(240))
4020 // *** CONTEXT_HELP ***
4021 context_help_set_keyword("Compositor Toolbar");
4024 CWindowRulerGUI::~CWindowRulerGUI()
4028 void CWindowRulerGUI::create_objects()
4030 int xs10 = xS(10), xs200 = xS(200);
4031 int ys5 = yS(5), ys10 = yS(10);
4032 int x = xs10, y = ys10, x1 = xS(100);
4035 lock_window("CWindowRulerGUI::create_objects");
4036 add_subwindow(title = new BC_Title(x, y, _("Current:")));
4037 add_subwindow(current = new BC_TextBox(x1, y, xs200, 1, ""));
4038 y += title->get_h() + ys5;
4039 add_subwindow(title = new BC_Title(x, y, _("Point 1:")));
4040 add_subwindow(point1 = new BC_TextBox(x1, y, xs200, 1, ""));
4041 y += title->get_h() + ys5;
4042 add_subwindow(title = new BC_Title(x, y, _("Point 2:")));
4043 add_subwindow(point2 = new BC_TextBox(x1, y, xs200, 1, ""));
4044 y += title->get_h() + ys5;
4045 add_subwindow(title = new BC_Title(x, y, _("Deltas:")));
4046 add_subwindow(deltas = new BC_TextBox(x1, y, xs200, 1, ""));
4047 y += title->get_h() + ys5;
4048 add_subwindow(title = new BC_Title(x, y, _("Distance:")));
4049 add_subwindow(distance = new BC_TextBox(x1, y, xs200, 1, ""));
4050 y += title->get_h() + ys5;
4051 add_subwindow(title = new BC_Title(x, y, _("Angle:")));
4052 add_subwindow(angle = new BC_TextBox(x1, y, xs200, 1, ""));
4053 y += title->get_h() + ys10;
4054 char string[BCTEXTLEN];
4056 _("Press Ctrl to lock ruler to the\nnearest 45%c%c angle."),
4057 0xc2, 0xb0); // degrees utf
4058 add_subwindow(title = new BC_Title(x,
4061 y += title->get_h() + ys10;
4062 sprintf(string, _("Press Alt to translate the ruler."));
4063 add_subwindow(title = new BC_Title(x,
4070 void CWindowRulerGUI::update()
4072 char string[BCTEXTLEN];
4073 int cx = mwindow->session->cwindow_output_x;
4074 int cy = mwindow->session->cwindow_output_y;
4075 sprintf(string, "%d, %d", cx, cy);
4076 current->update(string);
4077 double x1 = mwindow->edl->session->ruler_x1;
4078 double y1 = mwindow->edl->session->ruler_y1;
4079 sprintf(string, "%.0f, %.0f", x1, y1);
4080 point1->update(string);
4081 double x2 = mwindow->edl->session->ruler_x2;
4082 double y2 = mwindow->edl->session->ruler_y2;
4083 sprintf(string, "%.0f, %.0f", x2, y2);
4084 point2->update(string);
4085 double dx = x2 - x1, dy = y2 - y1;
4086 sprintf(string, "%s%.0f, %s%.0f", (dx>=0? "+":""), dx, (dy>=0? "+":""), dy);
4087 deltas->update(string);
4088 double d = sqrt(dx*dx + dy*dy);
4089 sprintf(string, _("%0.01f pixels"), d);
4090 distance->update(string);
4091 double a = d > 0 ? (atan2(-dy, dx) * 180/M_PI) : 0.;
4092 sprintf(string, "%0.02f %c%c", a, 0xc2, 0xb0);
4093 angle->update(string);
4096 void CWindowRulerGUI::handle_event()