1 #include "automation.h"
10 #include "cwindowgui.h"
12 #include "cwindowtool.h"
13 #include "editpanel.h"
15 #include "edlsession.h"
16 #include "floatauto.h"
17 #include "floatautos.h"
20 #include "localsession.h"
21 #include "mainclock.h"
24 #include "mainsession.h"
26 #include "maskautos.h"
27 #include "meterpanel.h"
28 #include "mwindowgui.h"
31 #include "playtransport.h"
33 #include "trackcanvas.h"
35 #include "transportque.h"
39 static double my_zoom_table[] =
52 static int total_zooms = sizeof(my_zoom_table) / sizeof(double);
55 CWindowGUI::CWindowGUI(MWindow *mwindow, CWindow *cwindow)
56 : BC_Window(PROGRAM_NAME ": Compositor",
57 mwindow->session->cwindow_x,
58 mwindow->session->cwindow_y,
59 mwindow->session->cwindow_w,
60 mwindow->session->cwindow_h,
66 BC_WindowBase::get_resources()->bg_color,
67 mwindow->edl->session->get_cwindow_display())
69 this->mwindow = mwindow;
70 this->cwindow = cwindow;
75 affected_keyframe = 0;
81 current_operation = CWINDOW_NONE;
89 CWindowGUI::~CWindowGUI()
91 if(tool_panel) delete tool_panel;
93 delete composite_panel;
102 int CWindowGUI::create_objects()
104 set_icon(mwindow->theme->get_image("cwindow_icon"));
106 active = new BC_Pixmap(this, mwindow->theme->get_image("cwindow_active"));
107 inactive = new BC_Pixmap(this, mwindow->theme->get_image("cwindow_inactive"));
109 mwindow->theme->get_cwindow_sizes(this, mwindow->session->cwindow_controls);
110 mwindow->theme->draw_cwindow_bg(this);
113 // Meters required by composite panel
114 meters = new CWindowMeters(mwindow,
116 mwindow->theme->cmeter_x,
117 mwindow->theme->cmeter_y,
118 mwindow->theme->cmeter_h);
119 meters->create_objects();
122 composite_panel = new CPanel(mwindow,
124 mwindow->theme->ccomposite_x,
125 mwindow->theme->ccomposite_y,
126 mwindow->theme->ccomposite_w,
127 mwindow->theme->ccomposite_h);
128 composite_panel->create_objects();
130 canvas = new CWindowCanvas(mwindow, this);
131 canvas->create_objects(mwindow->edl);
134 add_subwindow(timebar = new CTimeBar(mwindow,
136 mwindow->theme->ctimebar_x,
137 mwindow->theme->ctimebar_y,
138 mwindow->theme->ctimebar_w,
139 mwindow->theme->ctimebar_h));
140 timebar->create_objects();
142 add_subwindow(slider = new CWindowSlider(mwindow,
144 mwindow->theme->cslider_x,
145 mwindow->theme->cslider_y,
146 mwindow->theme->cslider_w));
148 transport = new CWindowTransport(mwindow,
150 mwindow->theme->ctransport_x,
151 mwindow->theme->ctransport_y);
152 transport->create_objects();
153 transport->set_slider(slider);
155 edit_panel = new CWindowEditing(mwindow, cwindow);
156 edit_panel->set_meters(meters);
157 edit_panel->create_objects();
159 // add_subwindow(clock = new MainClock(mwindow,
160 // mwindow->theme->ctime_x,
161 // mwindow->theme->ctime_y));
163 zoom_panel = new CWindowZoom(mwindow,
165 mwindow->theme->czoom_x,
166 mwindow->theme->czoom_y);
167 zoom_panel->create_objects();
168 zoom_panel->zoom_text->add_item(new BC_MenuItem(AUTO_ZOOM));
169 if(!mwindow->edl->session->cwindow_scrollbars) zoom_panel->set_text(AUTO_ZOOM);
171 // destination = new CWindowDestination(mwindow,
173 // mwindow->theme->cdest_x,
174 // mwindow->theme->cdest_y);
175 // destination->create_objects();
177 // Must create after meter panel
178 tool_panel = new CWindowTool(mwindow, this);
179 tool_panel->Thread::start();
181 set_operation(mwindow->edl->session->cwindow_operation);
184 canvas->draw_refresh();
191 int CWindowGUI::translation_event()
193 mwindow->session->cwindow_x = get_x();
194 mwindow->session->cwindow_y = get_y();
198 int CWindowGUI::resize_event(int w, int h)
200 mwindow->session->cwindow_x = get_x();
201 mwindow->session->cwindow_y = get_y();
202 mwindow->session->cwindow_w = w;
203 mwindow->session->cwindow_h = h;
205 mwindow->theme->get_cwindow_sizes(this, mwindow->session->cwindow_controls);
206 mwindow->theme->draw_cwindow_bg(this);
209 composite_panel->reposition_buttons(mwindow->theme->ccomposite_x,
210 mwindow->theme->ccomposite_y);
212 canvas->reposition_window(mwindow->edl,
213 mwindow->theme->ccanvas_x,
214 mwindow->theme->ccanvas_y,
215 mwindow->theme->ccanvas_w,
216 mwindow->theme->ccanvas_h);
218 timebar->resize_event();
220 slider->reposition_window(mwindow->theme->cslider_x,
221 mwindow->theme->cslider_y,
222 mwindow->theme->cslider_w);
223 // Recalibrate pointer motion range
224 slider->set_position();
226 transport->reposition_buttons(mwindow->theme->ctransport_x,
227 mwindow->theme->ctransport_y);
229 edit_panel->reposition_buttons(mwindow->theme->cedit_x,
230 mwindow->theme->cedit_y);
232 // clock->reposition_window(mwindow->theme->ctime_x,
233 // mwindow->theme->ctime_y);
235 zoom_panel->reposition_window(mwindow->theme->czoom_x,
236 mwindow->theme->czoom_y);
238 // destination->reposition_window(mwindow->theme->cdest_x,
239 // mwindow->theme->cdest_y);
241 meters->reposition_window(mwindow->theme->cmeter_x,
242 mwindow->theme->cmeter_y,
243 mwindow->theme->cmeter_h);
247 BC_WindowBase::resize_event(w, h);
251 int CWindowGUI::button_press_event()
253 if(canvas->get_canvas())
254 return canvas->button_press_event_base(canvas->get_canvas());
258 int CWindowGUI::cursor_leave_event()
260 if(canvas->get_canvas())
261 return canvas->cursor_leave_event_base(canvas->get_canvas());
265 int CWindowGUI::cursor_enter_event()
267 if(canvas->get_canvas())
268 return canvas->cursor_enter_event_base(canvas->get_canvas());
272 int CWindowGUI::button_release_event()
274 if(canvas->get_canvas())
275 return canvas->button_release_event();
279 int CWindowGUI::cursor_motion_event()
281 if(canvas->get_canvas())
283 canvas->get_canvas()->unhide_cursor();
284 return canvas->cursor_motion_event();
295 void CWindowGUI::draw_status()
297 if(canvas->get_canvas() &&
298 canvas->get_canvas()->get_video_on() ||
299 canvas->is_processing)
302 mwindow->theme->cstatus_x,
303 mwindow->theme->cstatus_y);
307 draw_pixmap(inactive,
308 mwindow->theme->cstatus_x,
309 mwindow->theme->cstatus_y);
312 flash(mwindow->theme->cstatus_x,
313 mwindow->theme->cstatus_y,
319 void CWindowGUI::zoom_canvas(int do_auto, double value, int update_menu)
322 mwindow->edl->session->cwindow_scrollbars = 0;
324 mwindow->edl->session->cwindow_scrollbars = 1;
326 float old_zoom = mwindow->edl->session->cwindow_zoom;
327 float new_zoom = value;
328 float x = canvas->w / 2;
329 float y = canvas->h / 2;
330 canvas->canvas_to_output(mwindow->edl,
334 x -= canvas->w_visible / 2 * old_zoom / new_zoom;
335 y -= canvas->h_visible / 2 * old_zoom / new_zoom;
337 canvas->update_zoom((int)x,
340 canvas->reposition_window(mwindow->edl,
341 mwindow->theme->ccanvas_x,
342 mwindow->theme->ccanvas_y,
343 mwindow->theme->ccanvas_w,
344 mwindow->theme->ccanvas_h);
345 canvas->draw_refresh();
350 // Don't refresh the canvas in a load file operation which is going to
351 // refresh it anyway.
352 void CWindowGUI::set_operation(int value)
354 mwindow->edl->session->cwindow_operation = value;
356 composite_panel->set_operation(value);
357 edit_panel->update();
359 tool_panel->start_tool(value);
360 canvas->draw_refresh();
363 void CWindowGUI::update_tool()
365 tool_panel->update_values();
368 int CWindowGUI::close_event()
370 cwindow->hide_window();
375 int CWindowGUI::keypress_event()
379 switch(get_keypress())
397 if(mwindow->session->cwindow_fullscreen)
398 canvas->stop_fullscreen();
400 canvas->start_fullscreen();
401 lock_window("CWindowGUI::keypress_event 1");
405 if(mwindow->session->cwindow_fullscreen)
406 canvas->stop_fullscreen();
407 lock_window("CWindowGUI::keypress_event 2");
411 if(!result) result = transport->keypress_event();
417 void CWindowGUI::reset_affected()
424 void CWindowGUI::keyboard_zoomin()
426 // if(mwindow->edl->session->cwindow_scrollbars)
428 zoom_panel->zoom_tumbler->handle_up_event();
435 void CWindowGUI::keyboard_zoomout()
437 // if(mwindow->edl->session->cwindow_scrollbars)
439 zoom_panel->zoom_tumbler->handle_down_event();
447 void CWindowGUI::drag_motion()
449 if(get_hidden()) return;
451 if(mwindow->session->current_operation == DRAG_ASSET ||
452 mwindow->session->current_operation == DRAG_VTRANSITION ||
453 mwindow->session->current_operation == DRAG_VEFFECT)
455 int old_status = mwindow->session->ccanvas_highlighted;
456 int cursor_x = get_relative_cursor_x();
457 int cursor_y = get_relative_cursor_y();
459 mwindow->session->ccanvas_highlighted = get_cursor_over_window() &&
460 cursor_x >= canvas->x &&
461 cursor_x < canvas->x + canvas->w &&
462 cursor_y >= canvas->y &&
463 cursor_y < canvas->y + canvas->h;
466 if(old_status != mwindow->session->ccanvas_highlighted)
467 canvas->draw_refresh();
471 int CWindowGUI::drag_stop()
474 if(get_hidden()) return 0;
476 if((mwindow->session->current_operation == DRAG_ASSET ||
477 mwindow->session->current_operation == DRAG_VTRANSITION ||
478 mwindow->session->current_operation == DRAG_VEFFECT) &&
479 mwindow->session->ccanvas_highlighted)
482 mwindow->session->ccanvas_highlighted = 0;
483 canvas->draw_refresh();
489 if(mwindow->session->current_operation == DRAG_ASSET)
491 if(mwindow->session->drag_assets->total)
493 mwindow->gui->lock_window("CWindowGUI::drag_stop 1");
495 mwindow->load_assets(mwindow->session->drag_assets,
496 mwindow->edl->local_session->get_selectionstart(),
498 mwindow->session->track_highlighted,
500 mwindow->edl->session->labels_follow_edits,
501 mwindow->edl->session->plugins_follow_edits);
504 if(mwindow->session->drag_clips->total)
506 mwindow->gui->lock_window("CWindowGUI::drag_stop 2");
508 mwindow->paste_edls(mwindow->session->drag_clips,
510 mwindow->session->track_highlighted,
511 mwindow->edl->local_session->get_selectionstart(),
512 mwindow->edl->session->labels_follow_edits,
513 mwindow->edl->session->plugins_follow_edits);
516 if(mwindow->session->drag_assets->total ||
517 mwindow->session->drag_clips->total)
519 mwindow->save_backup();
520 mwindow->restart_brender();
521 mwindow->gui->update(1, 1, 1, 1, 0, 1, 0);
522 mwindow->undo->update_undo(_("insert assets"), LOAD_ALL);
523 mwindow->gui->unlock_window();
524 mwindow->sync_parameters(LOAD_ALL);
528 if(mwindow->session->current_operation == DRAG_VEFFECT)
530 //printf("CWindowGUI::drag_stop 1\n");
531 Track *affected_track = cwindow->calculate_affected_track();
532 //printf("CWindowGUI::drag_stop 2\n");
534 mwindow->gui->lock_window("CWindowGUI::drag_stop 3");
535 mwindow->insert_effects_cwindow(affected_track);
536 mwindow->session->current_operation = NO_OPERATION;
537 mwindow->gui->unlock_window();
540 if(mwindow->session->current_operation == DRAG_VTRANSITION)
542 Track *affected_track = cwindow->calculate_affected_track();
543 mwindow->gui->lock_window("CWindowGUI::drag_stop 4");
544 mwindow->paste_transition_cwindow(affected_track);
545 mwindow->session->current_operation = NO_OPERATION;
546 mwindow->gui->unlock_window();
553 CWindowEditing::CWindowEditing(MWindow *mwindow, CWindow *cwindow)
556 mwindow->theme->cedit_x,
557 mwindow->theme->cedit_y,
558 mwindow->edl->session->editing_mode,
575 this->mwindow = mwindow;
576 this->cwindow = cwindow;
579 void CWindowEditing::set_inpoint()
581 mwindow->set_inpoint(0);
584 void CWindowEditing::set_outpoint()
586 mwindow->set_outpoint(0);
593 CWindowMeters::CWindowMeters(MWindow *mwindow, CWindowGUI *gui, int x, int y, int h)
594 : MeterPanel(mwindow,
599 mwindow->edl->session->audio_channels,
600 mwindow->edl->session->cwindow_meter)
602 this->mwindow = mwindow;
606 CWindowMeters::~CWindowMeters()
610 int CWindowMeters::change_status_event()
612 mwindow->edl->session->cwindow_meter = use_meters;
613 mwindow->theme->get_cwindow_sizes(gui, mwindow->session->cwindow_controls);
614 gui->resize_event(gui->get_w(), gui->get_h());
621 CWindowZoom::CWindowZoom(MWindow *mwindow, CWindowGUI *gui, int x, int y)
624 (double)mwindow->edl->session->cwindow_zoom,
632 this->mwindow = mwindow;
636 CWindowZoom::~CWindowZoom()
640 int CWindowZoom::handle_event()
642 if(!strcasecmp(AUTO_ZOOM, get_text()))
644 gui->zoom_canvas(1, get_value(), 0);
648 gui->zoom_canvas(0, get_value(), 0);
656 CWindowSlider::CWindowSlider(MWindow *mwindow, CWindow *cwindow, int x, int y, int pixels)
657 : BC_PercentageSlider(x,
666 this->mwindow = mwindow;
667 this->cwindow = cwindow;
668 set_precision(0.00001);
671 CWindowSlider::~CWindowSlider()
675 int CWindowSlider::handle_event()
678 cwindow->playback_engine->interrupt_playback(1);
679 lock_window("CWindowSlider::handle_event 1");
681 mwindow->gui->lock_window("CWindowSlider::handle_event 2");
682 mwindow->select_point((double)get_value());
683 mwindow->gui->unlock_window();
687 void CWindowSlider::set_position()
689 double new_length = mwindow->edl->tracks->total_playable_length();
690 if(mwindow->edl->local_session->preview_end <= 0 ||
691 mwindow->edl->local_session->preview_end > new_length)
692 mwindow->edl->local_session->preview_end = new_length;
693 if(mwindow->edl->local_session->preview_start >
694 mwindow->edl->local_session->preview_end)
695 mwindow->edl->local_session->preview_start = 0;
699 update(mwindow->theme->cslider_w,
700 mwindow->edl->local_session->get_selectionstart(1),
701 mwindow->edl->local_session->preview_start,
702 mwindow->edl->local_session->preview_end);
706 int CWindowSlider::increase_value()
709 cwindow->gui->transport->handle_transport(SINGLE_FRAME_FWD);
710 lock_window("CWindowSlider::increase_value");
714 int CWindowSlider::decrease_value()
717 cwindow->gui->transport->handle_transport(SINGLE_FRAME_REWIND);
718 lock_window("CWindowSlider::decrease_value");
723 // CWindowDestination::CWindowDestination(MWindow *mwindow, CWindowGUI *cwindow, int x, int y)
724 // : BC_PopupTextBox(cwindow,
725 // &cwindow->destinations,
726 // cwindow->destinations.values[cwindow->cwindow->destination]->get_text(),
732 // this->mwindow = mwindow;
733 // this->cwindow = cwindow;
736 // CWindowDestination::~CWindowDestination()
740 // int CWindowDestination::handle_event()
746 CWindowTransport::CWindowTransport(MWindow *mwindow,
750 : PlayTransport(mwindow,
758 EDL* CWindowTransport::get_edl()
763 void CWindowTransport::goto_start()
765 gui->unlock_window();
766 handle_transport(REWIND, 1);
768 mwindow->gui->lock_window("CWindowTransport::goto_start 1");
769 mwindow->goto_start();
770 mwindow->gui->unlock_window();
772 gui->lock_window("CWindowTransport::goto_start 2");
775 void CWindowTransport::goto_end()
777 gui->unlock_window();
778 handle_transport(GOTO_END, 1);
780 mwindow->gui->lock_window("CWindowTransport::goto_end 1");
782 mwindow->gui->unlock_window();
784 gui->lock_window("CWindowTransport::goto_end 2");
789 CWindowCanvas::CWindowCanvas(MWindow *mwindow, CWindowGUI *gui)
792 mwindow->theme->ccanvas_x,
793 mwindow->theme->ccanvas_y,
794 mwindow->theme->ccanvas_w,
795 mwindow->theme->ccanvas_h,
798 mwindow->edl->session->cwindow_scrollbars,
801 this->mwindow = mwindow;
805 void CWindowCanvas::status_event()
810 int CWindowCanvas::get_fullscreen()
812 return mwindow->session->cwindow_fullscreen;
815 void CWindowCanvas::set_fullscreen(int value)
817 mwindow->session->cwindow_fullscreen = value;
821 void CWindowCanvas::update_zoom(int x, int y, float zoom)
823 use_scrollbars = mwindow->edl->session->cwindow_scrollbars;
825 mwindow->edl->session->cwindow_xscroll = x;
826 mwindow->edl->session->cwindow_yscroll = y;
827 mwindow->edl->session->cwindow_zoom = zoom;
830 int CWindowCanvas::get_xscroll()
832 return mwindow->edl->session->cwindow_xscroll;
835 int CWindowCanvas::get_yscroll()
837 return mwindow->edl->session->cwindow_yscroll;
841 float CWindowCanvas::get_zoom()
843 return mwindow->edl->session->cwindow_zoom;
846 void CWindowCanvas::draw_refresh()
848 if(get_canvas() && !get_canvas()->get_video_on())
850 get_canvas()->clear_box(0, 0, get_canvas()->get_w(), get_canvas()->get_h());
854 float in_x1, in_y1, in_x2, in_y2;
855 float out_x1, out_y1, out_x2, out_y2;
856 get_transfers(mwindow->edl,
866 get_canvas()->clear_box(0,
868 get_canvas()->get_w(),
869 get_canvas()->get_h());
871 // printf("CWindowCanvas::draw_refresh %f %f %f %f -> %f %f %f %f\n",
872 // in_x1, in_y1, in_x2, in_y2, out_x1, out_y1, out_x2, out_y2);
875 if(out_x2 > out_x1 &&
880 // Can't use OpenGL here because it is called asynchronously of the
881 // playback operation.
882 get_canvas()->draw_vframe(refresh_frame,
885 (int)(out_x2 - out_x1),
886 (int)(out_y2 - out_y1),
889 (int)(in_x2 - in_x1),
890 (int)(in_y2 - in_y1),
896 get_canvas()->flash();
898 //printf("CWindowCanvas::draw_refresh 10\n");
901 #define CROPHANDLE_W 10
902 #define CROPHANDLE_H 10
904 void CWindowCanvas::draw_crophandle(int x, int y)
906 get_canvas()->draw_box(x, y, CROPHANDLE_W, CROPHANDLE_H);
911 #define FIRST_CONTROL_W 20
912 #define FIRST_CONTROL_H 20
914 #define BC_INFINITY 65536
916 #define SQR(x) ((x) * (x))
919 int CWindowCanvas::do_mask(int &redraw,
925 // Retrieve points from top recordable track
926 //printf("CWindowCanvas::do_mask 1\n");
927 Track *track = gui->cwindow->calculate_affected_track();
928 //printf("CWindowCanvas::do_mask 2\n");
931 //printf("CWindowCanvas::do_mask 3\n");
933 MaskAutos *mask_autos = (MaskAutos*)track->automation->autos[AUTOMATION_MASK];
934 int64_t position = track->to_units(
935 mwindow->edl->local_session->get_selectionstart(1),
937 ArrayList<MaskPoint*> points;
938 mask_autos->get_points(&points, mwindow->edl->session->cwindow_mask,
941 //printf("CWindowCanvas::do_mask 4\n");
943 // Projector zooms relative to the center of the track output.
944 float half_track_w = (float)track->track_w / 2;
945 float half_track_h = (float)track->track_h / 2;
946 // Translate mask to projection
947 float projector_x, projector_y, projector_z;
948 track->automation->get_projector(&projector_x,
955 // Get position of cursor relative to mask
956 float mask_cursor_x = get_cursor_x();
957 float mask_cursor_y = get_cursor_y();
958 canvas_to_output(mwindow->edl, 0, mask_cursor_x, mask_cursor_y);
960 projector_x += mwindow->edl->session->output_w / 2;
961 projector_y += mwindow->edl->session->output_h / 2;
963 mask_cursor_x -= projector_x;
964 mask_cursor_y -= projector_y;
965 mask_cursor_x = mask_cursor_x / projector_z + half_track_w;
966 mask_cursor_y = mask_cursor_y / projector_z + half_track_h;
971 gui->x_origin = mask_cursor_x;
972 gui->y_origin = mask_cursor_y;
976 // Points of closest line
977 int shortest_point1 = -1;
978 int shortest_point2 = -1;
980 int shortest_point = -1;
981 // Distance to closest line
982 float shortest_line_distance = BC_INFINITY;
983 // Distance to closest point
984 float shortest_point_distance = BC_INFINITY;
985 int selected_point = -1;
986 int selected_control_point = -1;
987 float selected_control_point_distance = BC_INFINITY;
988 ArrayList<int> x_points;
989 ArrayList<int> y_points;
995 get_canvas()->set_color(WHITE);
996 get_canvas()->set_inverse();
998 //printf("CWindowCanvas::do_mask 1 %d\n", points.total);
1000 // Never draw closed polygon and a closed
1001 // polygon is harder to add points to.
1002 for(int i = 0; i < points.total && !result; i++)
1004 MaskPoint *point1 = points.values[i];
1005 MaskPoint *point2 = (i >= points.total - 1) ?
1007 points.values[i + 1];
1008 float x0, x1, x2, x3;
1009 float y0, y1, y2, y3;
1010 float old_x, old_y, x, y;
1011 int segments = (int)(sqrt(SQR(point1->x - point2->x) + SQR(point1->y - point2->y)));
1013 //printf("CWindowCanvas::do_mask 1 %f, %f -> %f, %f projectorz=%f\n",
1014 //point1->x, point1->y, point2->x, point2->y, projector_z);
1015 for(int j = 0; j <= segments && !result; j++)
1017 //printf("CWindowCanvas::do_mask 1 %f, %f -> %f, %f\n", x0, y0, x3, y3);
1020 x1 = point1->x + point1->control_x2;
1021 y1 = point1->y + point1->control_y2;
1022 x2 = point2->x + point2->control_x1;
1023 y2 = point2->y + point2->control_y1;
1027 float t = (float)j / segments;
1028 float tpow2 = t * t;
1029 float tpow3 = t * t * t;
1031 float invtpow2 = invt * invt;
1032 float invtpow3 = invt * invt * invt;
1035 + 3 * t * invtpow2 * x1
1036 + 3 * tpow2 * invt * x2
1039 + 3 * t * invtpow2 * y1
1040 + 3 * tpow2 * invt * y2
1043 x = (x - half_track_w) * projector_z + projector_x;
1044 y = (y - half_track_h) * projector_z + projector_y;
1047 // Test new point addition
1050 float line_distance =
1051 sqrt(SQR(x - mask_cursor_x) + SQR(y - mask_cursor_y));
1053 //printf("CWindowCanvas::do_mask 1 x=%f mask_cursor_x=%f y=%f mask_cursor_y=%f %f %f %d, %d\n",
1054 //x, mask_cursor_x, y, mask_cursor_y, line_distance, shortest_line_distance, shortest_point1, shortest_point2);
1055 if(line_distance < shortest_line_distance ||
1056 shortest_point1 < 0)
1058 shortest_line_distance = line_distance;
1059 shortest_point1 = i;
1060 shortest_point2 = (i >= points.total - 1) ? 0 : (i + 1);
1061 //printf("CWindowCanvas::do_mask 2 %f %f %d, %d\n", line_distance, shortest_line_distance, shortest_point1, shortest_point2);
1065 float point_distance1 =
1066 sqrt(SQR(point1->x - mask_cursor_x) + SQR(point1->y - mask_cursor_y));
1067 float point_distance2 =
1068 sqrt(SQR(point2->x - mask_cursor_x) + SQR(point2->y - mask_cursor_y));
1070 if(point_distance1 < shortest_point_distance ||
1073 shortest_point_distance = point_distance1;
1077 if(point_distance2 < shortest_point_distance ||
1080 shortest_point_distance = point_distance2;
1081 shortest_point = (i >= points.total - 1) ? 0 : (i + 1);
1085 output_to_canvas(mwindow->edl, 0, x, y);
1088 #define TEST_BOX(cursor_x, cursor_y, target_x, target_y) \
1089 (cursor_x >= target_x - CONTROL_W / 2 && \
1090 cursor_x < target_x + CONTROL_W / 2 && \
1091 cursor_y >= target_y - CONTROL_H / 2 && \
1092 cursor_y < target_y + CONTROL_H / 2)
1094 // Test existing point selection
1097 float canvas_x = (x0 - half_track_w) * projector_z + projector_x;
1098 float canvas_y = (y0 - half_track_h) * projector_z + projector_y;
1099 int cursor_x = get_cursor_x();
1100 int cursor_y = get_cursor_y();
1103 if(gui->shift_down())
1105 float control_x = (x1 - half_track_w) * projector_z + projector_x;
1106 float control_y = (y1 - half_track_h) * projector_z + projector_y;
1107 output_to_canvas(mwindow->edl, 0, control_x, control_y);
1110 sqrt(SQR(control_x - cursor_x) + SQR(control_y - cursor_y));
1112 if(distance < selected_control_point_distance)
1115 selected_control_point = 1;
1116 selected_control_point_distance = distance;
1121 output_to_canvas(mwindow->edl, 0, canvas_x, canvas_y);
1122 if(!gui->ctrl_down())
1124 if(TEST_BOX(cursor_x, cursor_y, canvas_x, canvas_y))
1131 selected_point = shortest_point;
1135 // Test second point
1136 canvas_x = (x3 - half_track_w) * projector_z + projector_x;
1137 canvas_y = (y3 - half_track_h) * projector_z + projector_y;
1138 if(gui->shift_down())
1140 float control_x = (x2 - half_track_w) * projector_z + projector_x;
1141 float control_y = (y2 - half_track_h) * projector_z + projector_y;
1142 output_to_canvas(mwindow->edl, 0, control_x, control_y);
1145 sqrt(SQR(control_x - cursor_x) + SQR(control_y - cursor_y));
1147 //printf("CWindowCanvas::do_mask %d %f %f\n", i, distance, selected_control_point_distance);
1148 if(distance < selected_control_point_distance)
1150 selected_point = (i < points.total - 1 ? i + 1 : 0);
1151 selected_control_point = 0;
1152 selected_control_point_distance = distance;
1156 if(i < points.total - 1)
1158 output_to_canvas(mwindow->edl, 0, canvas_x, canvas_y);
1159 if(!gui->ctrl_down())
1161 if(TEST_BOX(cursor_x, cursor_y, canvas_x, canvas_y))
1163 selected_point = (i < points.total - 1 ? i + 1 : 0);
1168 selected_point = shortest_point;
1177 // Draw joining line
1180 x_points.append((int)x);
1181 y_points.append((int)y);
1192 // Draw second anchor
1193 if(i < points.total - 1)
1195 if(i == gui->affected_point - 1)
1196 get_canvas()->draw_disc((int)x - CONTROL_W / 2,
1197 (int)y - CONTROL_W / 2,
1201 get_canvas()->draw_circle((int)x - CONTROL_W / 2,
1202 (int)y - CONTROL_W / 2,
1205 // char string[BCTEXTLEN];
1206 // sprintf(string, "%d", (i < points.total - 1 ? i + 1 : 0));
1207 // canvas->draw_text((int)x + CONTROL_W, (int)y + CONTROL_W, string);
1210 // Draw second control point. Discard x2 and y2 after this.
1211 x2 = (x2 - half_track_w) * projector_z + projector_x;
1212 y2 = (y2 - half_track_h) * projector_z + projector_y;
1213 output_to_canvas(mwindow->edl, 0, x2, y2);
1214 get_canvas()->draw_line((int)x, (int)y, (int)x2, (int)y2);
1215 get_canvas()->draw_rectangle((int)x2 - CONTROL_W / 2,
1216 (int)y2 - CONTROL_H / 2,
1226 // Draw first anchor
1229 get_canvas()->draw_disc((int)x - FIRST_CONTROL_W / 2,
1230 (int)y - FIRST_CONTROL_H / 2,
1235 // Draw first control point. Discard x1 and y1 after this.
1238 x1 = (x1 - half_track_w) * projector_z + projector_x;
1239 y1 = (y1 - half_track_h) * projector_z + projector_y;
1240 output_to_canvas(mwindow->edl, 0, x1, y1);
1241 get_canvas()->draw_line((int)x, (int)y, (int)x1, (int)y1);
1242 get_canvas()->draw_rectangle((int)x1 - CONTROL_W / 2,
1243 (int)y1 - CONTROL_H / 2,
1247 x_points.append((int)x);
1248 y_points.append((int)y);
1251 //printf("CWindowCanvas::do_mask 1\n");
1257 //printf("CWindowCanvas::do_mask 1\n");
1261 get_canvas()->draw_polygon(&x_points, &y_points);
1262 get_canvas()->set_opaque();
1264 //printf("CWindowCanvas::do_mask 1\n");
1273 if(button_press && !result)
1275 gui->affected_track = gui->cwindow->calculate_affected_track();
1276 // Get current keyframe
1277 if(gui->affected_track)
1278 gui->affected_keyframe =
1279 gui->cwindow->calculate_affected_auto(
1280 gui->affected_track->automation->autos[AUTOMATION_MASK],
1283 MaskAuto *keyframe = (MaskAuto*)gui->affected_keyframe;
1284 SubMask *mask = keyframe->get_submask(mwindow->edl->session->cwindow_mask);
1287 // Translate entire keyframe
1288 if(gui->alt_down() && mask->points.total)
1290 gui->current_operation = CWINDOW_MASK_TRANSLATE;
1291 gui->affected_point = 0;
1294 // Existing point or control point was selected
1295 if(selected_point >= 0)
1297 gui->affected_point = selected_point;
1299 if(selected_control_point == 0)
1300 gui->current_operation = CWINDOW_MASK_CONTROL_IN;
1302 if(selected_control_point == 1)
1303 gui->current_operation = CWINDOW_MASK_CONTROL_OUT;
1305 gui->current_operation = mwindow->edl->session->cwindow_operation;
1308 // No existing point or control point was selected so create a new one
1309 if(!gui->shift_down() && !gui->alt_down())
1311 // Create the template
1312 MaskPoint *point = new MaskPoint;
1313 point->x = mask_cursor_x;
1314 point->y = mask_cursor_y;
1315 point->control_x1 = 0;
1316 point->control_y1 = 0;
1317 point->control_x2 = 0;
1318 point->control_y2 = 0;
1321 if(shortest_point2 < shortest_point1)
1323 shortest_point2 ^= shortest_point1;
1324 shortest_point1 ^= shortest_point2;
1325 shortest_point2 ^= shortest_point1;
1330 // printf("CWindowGUI::do_mask 40\n");
1331 // mwindow->edl->dump();
1332 // printf("CWindowGUI::do_mask 50\n");
1336 //printf("CWindowCanvas::do_mask 1 %f %f %d %d\n",
1337 // shortest_line_distance, shortest_point_distance, shortest_point1, shortest_point2);
1338 //printf("CWindowCanvas::do_mask %d %d\n", shortest_point1, shortest_point2);
1340 // Append to end of list
1341 if(labs(shortest_point1 - shortest_point2) > 1)
1343 // Need to apply the new point to every keyframe
1344 for(MaskAuto *current = (MaskAuto*)mask_autos->default_auto;
1347 SubMask *submask = current->get_submask(mwindow->edl->session->cwindow_mask);
1348 MaskPoint *new_point = new MaskPoint;
1349 submask->points.append(new_point);
1350 *new_point = *point;
1351 if(current == (MaskAuto*)mask_autos->default_auto)
1352 current = (MaskAuto*)mask_autos->first;
1354 current = (MaskAuto*)NEXT;
1357 gui->affected_point = mask->points.total - 1;
1361 // Insert between 2 points, shifting back point 2
1362 if(shortest_point1 >= 0 && shortest_point2 >= 0)
1364 for(MaskAuto *current = (MaskAuto*)mask_autos->default_auto;
1367 SubMask *submask = current->get_submask(mwindow->edl->session->cwindow_mask);
1368 // In case the keyframe point count isn't synchronized with the rest of the keyframes,
1370 if(submask->points.total >= shortest_point2)
1372 MaskPoint *new_point = new MaskPoint;
1373 submask->points.append(0);
1374 for(int i = submask->points.total - 1;
1375 i > shortest_point2;
1377 submask->points.values[i] = submask->points.values[i - 1];
1378 submask->points.values[shortest_point2] = new_point;
1380 *new_point = *point;
1383 if(current == (MaskAuto*)mask_autos->default_auto)
1384 current = (MaskAuto*)mask_autos->first;
1386 current = (MaskAuto*)NEXT;
1390 gui->affected_point = shortest_point2;
1395 // printf("CWindowGUI::do_mask 20\n");
1396 // mwindow->edl->dump();
1397 // printf("CWindowGUI::do_mask 30\n");
1402 // Create the first point.
1405 //printf("CWindowCanvas::do_mask 1\n");
1406 for(MaskAuto *current = (MaskAuto*)mask_autos->default_auto;
1409 SubMask *submask = current->get_submask(mwindow->edl->session->cwindow_mask);
1410 MaskPoint *new_point = new MaskPoint;
1411 submask->points.append(new_point);
1412 *new_point = *point;
1413 if(current == (MaskAuto*)mask_autos->default_auto)
1414 current = (MaskAuto*)mask_autos->first;
1416 current = (MaskAuto*)NEXT;
1419 //printf("CWindowCanvas::do_mask 2\n");
1420 // Create a second point if none existed before
1421 if(mask->points.total < 2)
1423 for(MaskAuto *current = (MaskAuto*)mask_autos->default_auto;
1426 SubMask *submask = current->get_submask(mwindow->edl->session->cwindow_mask);
1427 MaskPoint *new_point = new MaskPoint;
1428 submask->points.append(new_point);
1429 *new_point = *point;
1430 if(current == (MaskAuto*)mask_autos->default_auto)
1431 current = (MaskAuto*)mask_autos->first;
1433 current = (MaskAuto*)NEXT;
1436 gui->affected_point = mask->points.total - 1;
1437 //printf("CWindowCanvas::do_mask 3 %d\n", mask->points.total);
1442 gui->current_operation = mwindow->edl->session->cwindow_operation;
1443 // Delete the template
1445 //printf("CWindowGUI::do_mask 1\n");
1446 mwindow->undo->update_undo(_("mask point"), LOAD_AUTOMATION);
1447 //printf("CWindowGUI::do_mask 10\n");
1456 if(button_press && result)
1458 MaskAuto *keyframe = (MaskAuto*)gui->affected_keyframe;
1459 SubMask *mask = keyframe->get_submask(mwindow->edl->session->cwindow_mask);
1460 MaskPoint *point = mask->points.values[gui->affected_point];
1461 gui->center_x = point->x;
1462 gui->center_y = point->y;
1463 gui->control_in_x = point->control_x1;
1464 gui->control_in_y = point->control_y1;
1465 gui->control_out_x = point->control_x2;
1466 gui->control_out_y = point->control_y2;
1469 //printf("CWindowCanvas::do_mask 8\n");
1472 MaskAuto *keyframe = (MaskAuto*)gui->affected_keyframe;
1473 SubMask *mask = keyframe->get_submask(mwindow->edl->session->cwindow_mask);
1474 if(gui->affected_point < mask->points.total)
1476 MaskPoint *point = mask->points.values[gui->affected_point];
1477 // float cursor_x = get_cursor_x();
1478 // float cursor_y = get_cursor_y();
1479 // canvas_to_output(mwindow->edl, 0, cursor_x, cursor_y);
1480 float cursor_x = mask_cursor_x;
1481 float cursor_y = mask_cursor_y;
1482 //printf("CWindowCanvas::do_mask 9 %d %d\n", mask->points.total, gui->affected_point);
1484 float last_x = point->x;
1485 float last_y = point->y;
1486 float last_control_x1 = point->control_x1;
1487 float last_control_y1 = point->control_y1;
1488 float last_control_x2 = point->control_x2;
1489 float last_control_y2 = point->control_y2;
1492 switch(gui->current_operation)
1495 point->x = cursor_x - gui->x_origin + gui->center_x;
1496 point->y = cursor_y - gui->y_origin + gui->center_y;
1499 case CWINDOW_MASK_CONTROL_IN:
1500 point->control_x1 = cursor_x - gui->x_origin + gui->control_in_x;
1501 point->control_y1 = cursor_y - gui->y_origin + gui->control_in_y;
1504 case CWINDOW_MASK_CONTROL_OUT:
1505 point->control_x2 = cursor_x - gui->x_origin + gui->control_out_x;
1506 point->control_y2 = cursor_y - gui->y_origin + gui->control_out_y;
1509 case CWINDOW_MASK_TRANSLATE:
1510 for(int i = 0; i < mask->points.total; i++)
1512 mask->points.values[i]->x += cursor_x - gui->x_origin;
1513 mask->points.values[i]->y += cursor_y - gui->y_origin;
1515 gui->x_origin = cursor_x;
1516 gui->y_origin = cursor_y;
1521 if( !EQUIV(last_x, point->x) ||
1522 !EQUIV(last_y, point->y) ||
1523 !EQUIV(last_control_x1, point->control_x1) ||
1524 !EQUIV(last_control_y1, point->control_y1) ||
1525 !EQUIV(last_control_x2, point->control_x2) ||
1526 !EQUIV(last_control_y2, point->control_y2))
1534 //printf("CWindowCanvas::do_mask 2 %d %d %d\n", result, rerender, redraw);
1536 points.remove_all_objects();
1537 //printf("CWindowCanvas::do_mask 20\n");
1542 int CWindowCanvas::do_eyedrop(int &rerender, int button_press)
1545 float cursor_x = get_cursor_x();
1546 float cursor_y = get_cursor_y();
1551 gui->current_operation = CWINDOW_EYEDROP;
1554 if(gui->current_operation == CWINDOW_EYEDROP)
1556 canvas_to_output(mwindow->edl, 0, cursor_x, cursor_y);
1558 // Get color out of frame.
1559 // Doesn't work during playback because that bypasses the refresh frame.
1562 CLAMP(cursor_x, 0, refresh_frame->get_w() - 1);
1563 CLAMP(cursor_y, 0, refresh_frame->get_h() - 1);
1565 // Decompression coefficients straight out of jpeglib
1566 #define V_TO_R 1.40200
1567 #define V_TO_G -0.71414
1569 #define U_TO_G -0.34414
1570 #define U_TO_B 1.77200
1572 #define GET_COLOR(type, components, max, do_yuv) \
1574 type *row = (type*)(refresh_frame->get_rows()[(int)cursor_y]) + \
1575 (int)cursor_x * components; \
1576 float red = (float)*row++ / max; \
1577 float green = (float)*row++ / max; \
1578 float blue = (float)*row++ / max; \
1581 mwindow->edl->local_session->red = red + V_TO_R * (blue - 0.5); \
1582 mwindow->edl->local_session->green = red + U_TO_G * (green - 0.5) + V_TO_G * (blue - 0.5); \
1583 mwindow->edl->local_session->blue = red + U_TO_B * (green - 0.5); \
1587 mwindow->edl->local_session->red = red; \
1588 mwindow->edl->local_session->green = green; \
1589 mwindow->edl->local_session->blue = blue; \
1593 switch(refresh_frame->get_color_model())
1596 GET_COLOR(unsigned char, 3, 0xff, 1);
1599 GET_COLOR(unsigned char, 4, 0xff, 1);
1602 GET_COLOR(uint16_t, 3, 0xffff, 1);
1604 case BC_YUVA16161616:
1605 GET_COLOR(uint16_t, 4, 0xffff, 1);
1608 GET_COLOR(unsigned char, 3, 0xff, 0);
1611 GET_COLOR(unsigned char, 4, 0xff, 0);
1614 GET_COLOR(float, 3, 1.0, 0);
1617 GET_COLOR(float, 4, 1.0, 0);
1623 mwindow->edl->local_session->red = 0;
1624 mwindow->edl->local_session->green = 0;
1625 mwindow->edl->local_session->blue = 0;
1634 // Can't rerender since the color value is from the output of any effect it
1642 void CWindowCanvas::draw_overlays()
1644 if(mwindow->edl->session->safe_regions)
1646 draw_safe_regions();
1649 if(mwindow->edl->session->cwindow_scrollbars)
1651 // Always draw output rectangle
1652 float x1, y1, x2, y2;
1654 x2 = mwindow->edl->session->output_w;
1656 y2 = mwindow->edl->session->output_h;
1657 output_to_canvas(mwindow->edl, 0, x1, y1);
1658 output_to_canvas(mwindow->edl, 0, x2, y2);
1660 get_canvas()->set_inverse();
1661 get_canvas()->set_color(WHITE);
1663 get_canvas()->draw_rectangle((int)x1,
1668 get_canvas()->set_opaque();
1671 if(mwindow->session->ccanvas_highlighted)
1673 get_canvas()->set_color(WHITE);
1674 get_canvas()->set_inverse();
1675 get_canvas()->draw_rectangle(0, 0, get_canvas()->get_w(), get_canvas()->get_h());
1676 get_canvas()->draw_rectangle(1, 1, get_canvas()->get_w() - 2, get_canvas()->get_h() - 2);
1677 get_canvas()->set_opaque();
1680 int temp1 = 0, temp2 = 0;
1681 //printf("CWindowCanvas::draw_overlays 1 %d\n", mwindow->edl->session->cwindow_operation);
1682 switch(mwindow->edl->session->cwindow_operation)
1684 case CWINDOW_CAMERA:
1688 case CWINDOW_PROJECTOR:
1697 do_mask(temp1, temp2, 0, 0, 1);
1702 void CWindowCanvas::draw_safe_regions()
1704 float action_x1, action_x2, action_y1, action_y2;
1705 float title_x1, title_x2, title_y1, title_y2;
1707 action_x1 = mwindow->edl->session->output_w / 2 - mwindow->edl->session->output_w / 2 * 0.9;
1708 action_x2 = mwindow->edl->session->output_w / 2 + mwindow->edl->session->output_w / 2 * 0.9;
1709 action_y1 = mwindow->edl->session->output_h / 2 - mwindow->edl->session->output_h / 2 * 0.9;
1710 action_y2 = mwindow->edl->session->output_h / 2 + mwindow->edl->session->output_h / 2 * 0.9;
1711 title_x1 = mwindow->edl->session->output_w / 2 - mwindow->edl->session->output_w / 2 * 0.8;
1712 title_x2 = mwindow->edl->session->output_w / 2 + mwindow->edl->session->output_w / 2 * 0.8;
1713 title_y1 = mwindow->edl->session->output_h / 2 - mwindow->edl->session->output_h / 2 * 0.8;
1714 title_y2 = mwindow->edl->session->output_h / 2 + mwindow->edl->session->output_h / 2 * 0.8;
1716 output_to_canvas(mwindow->edl, 0, action_x1, action_y1);
1717 output_to_canvas(mwindow->edl, 0, action_x2, action_y2);
1718 output_to_canvas(mwindow->edl, 0, title_x1, title_y1);
1719 output_to_canvas(mwindow->edl, 0, title_x2, title_y2);
1721 get_canvas()->set_inverse();
1722 get_canvas()->set_color(WHITE);
1724 get_canvas()->draw_rectangle((int)action_x1,
1726 (int)(action_x2 - action_x1),
1727 (int)(action_y2 - action_y1));
1728 get_canvas()->draw_rectangle((int)title_x1,
1730 (int)(title_x2 - title_x1),
1731 (int)(title_y2 - title_y1));
1733 get_canvas()->set_opaque();
1736 void CWindowCanvas::reset_keyframe(int do_camera)
1738 FloatAuto *x_keyframe = 0;
1739 FloatAuto *y_keyframe = 0;
1740 FloatAuto *z_keyframe = 0;
1741 Track *affected_track = 0;
1743 affected_track = gui->cwindow->calculate_affected_track();
1747 gui->cwindow->calculate_affected_autos(&x_keyframe,
1756 x_keyframe->value = 0;
1757 y_keyframe->value = 0;
1758 z_keyframe->value = 1;
1760 mwindow->sync_parameters(CHANGE_PARAMS);
1765 void CWindowCanvas::reset_camera()
1770 void CWindowCanvas::reset_projector()
1775 int CWindowCanvas::test_crop(int button_press, int &redraw)
1778 int handle_selected = -1;
1779 float x1 = mwindow->edl->session->crop_x1;
1780 float y1 = mwindow->edl->session->crop_y1;
1781 float x2 = mwindow->edl->session->crop_x2;
1782 float y2 = mwindow->edl->session->crop_y2;
1783 float cursor_x = get_cursor_x();
1784 float cursor_y = get_cursor_y();
1785 float canvas_x1 = x1;
1786 float canvas_y1 = y1;
1787 float canvas_x2 = x2;
1788 float canvas_y2 = y2;
1789 float canvas_cursor_x = cursor_x;
1790 float canvas_cursor_y = cursor_y;
1792 canvas_to_output(mwindow->edl, 0, cursor_x, cursor_y);
1793 // Use screen normalized coordinates for hot spot tests.
1794 output_to_canvas(mwindow->edl, 0, canvas_x1, canvas_y1);
1795 output_to_canvas(mwindow->edl, 0, canvas_x2, canvas_y2);
1798 if(gui->current_operation == CWINDOW_CROP)
1800 handle_selected = gui->crop_handle;
1803 if(canvas_cursor_x >= canvas_x1 && canvas_cursor_x < canvas_x1 + CROPHANDLE_W &&
1804 canvas_cursor_y >= canvas_y1 && canvas_cursor_y < canvas_y1 + CROPHANDLE_H)
1806 handle_selected = 0;
1807 gui->crop_origin_x = x1;
1808 gui->crop_origin_y = y1;
1811 if(canvas_cursor_x >= canvas_x2 - CROPHANDLE_W && canvas_cursor_x < canvas_x2 &&
1812 canvas_cursor_y >= canvas_y1 && canvas_cursor_y < canvas_y1 + CROPHANDLE_H)
1814 handle_selected = 1;
1815 gui->crop_origin_x = x2;
1816 gui->crop_origin_y = y1;
1819 if(canvas_cursor_x >= canvas_x1 && canvas_cursor_x < canvas_x1 + CROPHANDLE_W &&
1820 canvas_cursor_y >= canvas_y2 - CROPHANDLE_H && canvas_cursor_y < canvas_y2)
1822 handle_selected = 2;
1823 gui->crop_origin_x = x1;
1824 gui->crop_origin_y = y2;
1827 if(canvas_cursor_x >= canvas_x2 - CROPHANDLE_W && canvas_cursor_x < canvas_x2 &&
1828 canvas_cursor_y >= canvas_y2 - CROPHANDLE_H && canvas_cursor_y < canvas_y2)
1830 handle_selected = 3;
1831 gui->crop_origin_x = x2;
1832 gui->crop_origin_y = y2;
1837 gui->crop_origin_x = cursor_x;
1838 gui->crop_origin_y = cursor_y;
1841 // printf("test crop %d %d\n",
1842 // gui->current_operation,
1843 // handle_selected);
1850 gui->crop_translate = 1;
1851 gui->crop_origin_x1 = x1;
1852 gui->crop_origin_y1 = y1;
1853 gui->crop_origin_x2 = x2;
1854 gui->crop_origin_y2 = y2;
1857 gui->crop_translate = 0;
1859 gui->current_operation = CWINDOW_CROP;
1860 gui->crop_handle = handle_selected;
1861 gui->x_origin = cursor_x;
1862 gui->y_origin = cursor_y;
1865 if(handle_selected < 0 && !gui->crop_translate)
1869 mwindow->edl->session->crop_x1 = (int)x1;
1870 mwindow->edl->session->crop_y1 = (int)y1;
1871 mwindow->edl->session->crop_x2 = (int)x2;
1872 mwindow->edl->session->crop_y2 = (int)y2;
1877 // Translate all 4 points
1878 if(gui->current_operation == CWINDOW_CROP && gui->crop_translate)
1880 x1 = cursor_x - gui->x_origin + gui->crop_origin_x1;
1881 y1 = cursor_y - gui->y_origin + gui->crop_origin_y1;
1882 x2 = cursor_x - gui->x_origin + gui->crop_origin_x2;
1883 y2 = cursor_y - gui->y_origin + gui->crop_origin_y2;
1885 mwindow->edl->session->crop_x1 = (int)x1;
1886 mwindow->edl->session->crop_y1 = (int)y1;
1887 mwindow->edl->session->crop_x2 = (int)x2;
1888 mwindow->edl->session->crop_y2 = (int)y2;
1894 if(gui->current_operation == CWINDOW_CROP)
1896 switch(gui->crop_handle)
1899 x1 = gui->crop_origin_x;
1900 y1 = gui->crop_origin_y;
1901 x2 = gui->crop_origin_x;
1902 y2 = gui->crop_origin_y;
1903 if(cursor_x < gui->x_origin)
1905 if(cursor_y < gui->y_origin)
1911 if(cursor_y >= gui->y_origin)
1918 if(cursor_x >= gui->x_origin)
1920 if(cursor_y < gui->y_origin)
1926 if(cursor_y >= gui->y_origin)
1933 // printf("test crop %d %d %d %d\n",
1934 // mwindow->edl->session->crop_x1,
1935 // mwindow->edl->session->crop_y1,
1936 // mwindow->edl->session->crop_x2,
1937 // mwindow->edl->session->crop_y2);
1940 x1 = cursor_x - gui->x_origin + gui->crop_origin_x;
1941 y1 = cursor_y - gui->y_origin + gui->crop_origin_y;
1944 x2 = cursor_x - gui->x_origin + gui->crop_origin_x;
1945 y1 = cursor_y - gui->y_origin + gui->crop_origin_y;
1948 x1 = cursor_x - gui->x_origin + gui->crop_origin_x;
1949 y2 = cursor_y - gui->y_origin + gui->crop_origin_y;
1952 x2 = cursor_x - gui->x_origin + gui->crop_origin_x;
1953 y2 = cursor_y - gui->y_origin + gui->crop_origin_y;
1957 if(!EQUIV(mwindow->edl->session->crop_x1, x1) ||
1958 !EQUIV(mwindow->edl->session->crop_x2, x2) ||
1959 !EQUIV(mwindow->edl->session->crop_y1, y1) ||
1960 !EQUIV(mwindow->edl->session->crop_y2, y2))
1967 switch (gui->crop_handle)
1969 case 0: gui->crop_handle = 1; break;
1970 case 1: gui->crop_handle = 0; break;
1971 case 2: gui->crop_handle = 3; break;
1972 case 3: gui->crop_handle = 2; break;
1982 switch (gui->crop_handle)
1984 case 0: gui->crop_handle = 2; break;
1985 case 1: gui->crop_handle = 3; break;
1986 case 2: gui->crop_handle = 0; break;
1987 case 3: gui->crop_handle = 1; break;
1992 mwindow->edl->session->crop_x1 = (int)x1;
1993 mwindow->edl->session->crop_y1 = (int)y1;
1994 mwindow->edl->session->crop_x2 = (int)x2;
1995 mwindow->edl->session->crop_y2 = (int)y2;
2001 // Update cursor font
2002 if(handle_selected >= 0)
2004 switch(handle_selected)
2007 set_cursor(UPLEFT_RESIZE);
2010 set_cursor(UPRIGHT_RESIZE);
2013 set_cursor(DOWNLEFT_RESIZE);
2016 set_cursor(DOWNRIGHT_RESIZE);
2023 set_cursor(ARROW_CURSOR);
2025 #define CLAMP(x, y, z) ((x) = ((x) < (y) ? (y) : ((x) > (z) ? (z) : (x))))
2029 CLAMP(mwindow->edl->session->crop_x1, 0, mwindow->edl->session->output_w);
2030 CLAMP(mwindow->edl->session->crop_x2, 0, mwindow->edl->session->output_w);
2031 CLAMP(mwindow->edl->session->crop_y1, 0, mwindow->edl->session->output_h);
2032 CLAMP(mwindow->edl->session->crop_y2, 0, mwindow->edl->session->output_h);
2033 // printf("CWindowCanvas::test_crop %d %d %d %d\n",
2034 // mwindow->edl->session->crop_x2,
2035 // mwindow->edl->session->crop_y2,
2036 // mwindow->edl->calculate_output_w(0),
2037 // mwindow->edl->calculate_output_h(0));
2043 void CWindowCanvas::draw_crop()
2045 get_canvas()->set_inverse();
2046 get_canvas()->set_color(WHITE);
2048 float x1 = mwindow->edl->session->crop_x1;
2049 float y1 = mwindow->edl->session->crop_y1;
2050 float x2 = mwindow->edl->session->crop_x2;
2051 float y2 = mwindow->edl->session->crop_y2;
2053 output_to_canvas(mwindow->edl, 0, x1, y1);
2054 output_to_canvas(mwindow->edl, 0, x2, y2);
2056 if(x2 - x1 && y2 - y1)
2057 get_canvas()->draw_rectangle((int)x1,
2062 draw_crophandle((int)x1, (int)y1);
2063 draw_crophandle((int)x2 - CROPHANDLE_W, (int)y1);
2064 draw_crophandle((int)x1, (int)y2 - CROPHANDLE_H);
2065 draw_crophandle((int)x2 - CROPHANDLE_W, (int)y2 - CROPHANDLE_H);
2066 get_canvas()->set_opaque();
2076 void CWindowCanvas::draw_bezier(int do_camera)
2078 Track *track = gui->cwindow->calculate_affected_track();
2085 int64_t position = track->to_units(
2086 mwindow->edl->local_session->get_selectionstart(1),
2089 track->automation->get_projector(¢er_x,
2095 // center_x += track->track_w / 2;
2096 // center_y += track->track_h / 2;
2097 center_x += mwindow->edl->session->output_w / 2;
2098 center_y += mwindow->edl->session->output_h / 2;
2099 float track_x1 = center_x - track->track_w / 2 * center_z;
2100 float track_y1 = center_y - track->track_h / 2 * center_z;
2101 float track_x2 = track_x1 + track->track_w * center_z;
2102 float track_y2 = track_y1 + track->track_h * center_z;
2104 output_to_canvas(mwindow->edl, 0, track_x1, track_y1);
2105 output_to_canvas(mwindow->edl, 0, track_x2, track_y2);
2107 #define DRAW_PROJECTION(offset) \
2108 get_canvas()->draw_rectangle((int)track_x1 + offset, \
2109 (int)track_y1 + offset, \
2110 (int)(track_x2 - track_x1), \
2111 (int)(track_y2 - track_y1)); \
2112 get_canvas()->draw_line((int)track_x1 + offset, \
2113 (int)track_y1 + offset, \
2114 (int)track_x2 + offset, \
2115 (int)track_y2 + offset); \
2116 get_canvas()->draw_line((int)track_x2 + offset, \
2117 (int)track_y1 + offset, \
2118 (int)track_x1 + offset, \
2119 (int)track_y2 + offset); \
2123 get_canvas()->set_color(BLACK);
2126 // canvas->set_inverse();
2128 get_canvas()->set_color(GREEN);
2130 get_canvas()->set_color(RED);
2133 // canvas->set_opaque();
2139 int CWindowCanvas::test_bezier(int button_press,
2147 // Processing drag operation.
2148 // Create keyframe during first cursor motion.
2152 float cursor_x = get_cursor_x();
2153 float cursor_y = get_cursor_y();
2154 canvas_to_output(mwindow->edl, 0, cursor_x, cursor_y);
2156 if(gui->current_operation == CWINDOW_CAMERA ||
2157 gui->current_operation == CWINDOW_PROJECTOR)
2159 if(!gui->ctrl_down() && gui->shift_down() && !gui->translating_zoom)
2161 gui->translating_zoom = 1;
2162 gui->reset_affected();
2165 if(!gui->ctrl_down() && !gui->shift_down() && gui->translating_zoom)
2167 gui->translating_zoom = 0;
2168 gui->reset_affected();
2171 // Get target keyframe
2172 float last_center_x;
2173 float last_center_y;
2174 float last_center_z;
2177 if(!gui->affected_x && !gui->affected_y && !gui->affected_z)
2179 FloatAutos *affected_x_autos;
2180 FloatAutos *affected_y_autos;
2181 FloatAutos *affected_z_autos;
2182 if(!gui->affected_track) return 0;
2183 if(mwindow->edl->session->cwindow_operation == CWINDOW_CAMERA)
2185 affected_x_autos = (FloatAutos*)gui->affected_track->automation->autos[AUTOMATION_CAMERA_X];
2186 affected_y_autos = (FloatAutos*)gui->affected_track->automation->autos[AUTOMATION_CAMERA_Y];
2187 affected_z_autos = (FloatAutos*)gui->affected_track->automation->autos[AUTOMATION_CAMERA_Z];
2191 affected_x_autos = (FloatAutos*)gui->affected_track->automation->autos[AUTOMATION_PROJECTOR_X];
2192 affected_y_autos = (FloatAutos*)gui->affected_track->automation->autos[AUTOMATION_PROJECTOR_Y];
2193 affected_z_autos = (FloatAutos*)gui->affected_track->automation->autos[AUTOMATION_PROJECTOR_Z];
2197 if(gui->translating_zoom)
2200 (FloatAuto*)gui->cwindow->calculate_affected_auto(
2201 affected_z_autos, 1);
2206 (FloatAuto*)gui->cwindow->calculate_affected_auto(
2207 affected_x_autos, 1);
2209 (FloatAuto*)gui->cwindow->calculate_affected_auto(
2210 affected_y_autos, 1);
2215 if(gui->translating_zoom)
2217 gui->center_z = gui->affected_z->value;
2221 gui->center_x = gui->affected_x->value;
2222 gui->center_y = gui->affected_y->value;
2230 if(gui->translating_zoom)
2232 last_center_z = gui->affected_z->value;
2236 last_center_x = gui->affected_x->value;
2237 last_center_y = gui->affected_y->value;
2240 if(gui->translating_zoom)
2242 gui->affected_z->value = gui->center_z +
2243 (cursor_y - gui->y_origin) / 128;
2244 if(!EQUIV(last_center_z, gui->affected_z->value))
2253 gui->affected_x->value = gui->center_x + cursor_x - gui->x_origin;
2254 gui->affected_y->value = gui->center_y + cursor_y - gui->y_origin;
2255 if(!EQUIV(last_center_x, gui->affected_x->value) ||
2256 !EQUIV(last_center_y, gui->affected_y->value))
2268 // Begin drag operation. Don't create keyframe here.
2270 // Get affected track off of the first recordable video track.
2271 // Calculating based on the alpha channel would require recording what layer
2272 // each output pixel belongs to as they're rendered and stacked. Forget it.
2273 gui->affected_track = gui->cwindow->calculate_affected_track();
2274 gui->reset_affected();
2276 if(gui->affected_track)
2278 gui->current_operation =
2279 mwindow->edl->session->cwindow_operation;
2287 int CWindowCanvas::test_zoom(int &redraw)
2290 float zoom = get_zoom();
2294 if(!mwindow->edl->session->cwindow_scrollbars)
2296 mwindow->edl->session->cwindow_scrollbars = 1;
2298 x = mwindow->edl->session->output_w / 2;
2299 y = mwindow->edl->session->output_h / 2;
2305 canvas_to_output(mwindow->edl,
2310 //printf("CWindowCanvas::test_zoom 1 %f %f\n", x, y);
2312 // Find current zoom in table
2313 int current_index = 0;
2314 for(current_index = 0 ; current_index < total_zooms; current_index++)
2315 if(EQUIV(my_zoom_table[current_index], zoom)) break;
2319 if(get_buttonpress() == 5 ||
2330 CLAMP(current_index, 0, total_zooms - 1);
2331 zoom = my_zoom_table[current_index];
2334 x = x - w / zoom / 2;
2335 y = y - h / zoom / 2;
2340 // check_boundaries(mwindow->edl, x_i, y_i, zoom);
2342 //printf("CWindowCanvas::test_zoom 2 %d %d\n", x_i, y_i);
2347 reposition_window(mwindow->edl,
2348 mwindow->theme->ccanvas_x,
2349 mwindow->theme->ccanvas_y,
2350 mwindow->theme->ccanvas_w,
2351 mwindow->theme->ccanvas_h);
2356 gui->zoom_panel->update(zoom);
2362 void CWindowCanvas::calculate_origin()
2364 gui->x_origin = get_cursor_x();
2365 gui->y_origin = get_cursor_y();
2366 //printf("CWindowCanvas::calculate_origin 1 %f %f\n", gui->x_origin, gui->y_origin);
2367 canvas_to_output(mwindow->edl, 0, gui->x_origin, gui->y_origin);
2368 //printf("CWindowCanvas::calculate_origin 2 %f %f\n", gui->x_origin, gui->y_origin);
2372 int CWindowCanvas::cursor_leave_event()
2374 set_cursor(ARROW_CURSOR);
2378 int CWindowCanvas::cursor_enter_event()
2381 switch(mwindow->edl->session->cwindow_operation)
2383 case CWINDOW_CAMERA:
2384 case CWINDOW_PROJECTOR:
2385 set_cursor(MOVE_CURSOR);
2388 set_cursor(MOVE_CURSOR);
2391 test_crop(0, redraw);
2393 case CWINDOW_PROTECT:
2394 set_cursor(ARROW_CURSOR);
2397 set_cursor(CROSS_CURSOR);
2399 case CWINDOW_EYEDROP:
2400 set_cursor(CROSS_CURSOR);
2406 int CWindowCanvas::cursor_motion_event()
2408 int redraw = 0, result = 0, rerender = 0, redraw_canvas = 0;
2411 switch(gui->current_operation)
2413 case CWINDOW_SCROLL:
2415 float zoom = get_zoom();
2416 float cursor_x = get_cursor_x();
2417 float cursor_y = get_cursor_y();
2419 float zoom_x, zoom_y, conformed_w, conformed_h;
2420 get_zooms(mwindow->edl, 0, zoom_x, zoom_y, conformed_w, conformed_h);
2421 cursor_x = (float)cursor_x / zoom_x + gui->x_offset;
2422 cursor_y = (float)cursor_y / zoom_y + gui->y_offset;
2426 int x = (int)(gui->x_origin - cursor_x + gui->x_offset);
2427 int y = (int)(gui->y_origin - cursor_y + gui->y_offset);
2432 update_scrollbars();
2438 case CWINDOW_CAMERA:
2439 result = test_bezier(0, redraw, redraw_canvas, rerender, 1);
2442 case CWINDOW_PROJECTOR:
2443 result = test_bezier(0, redraw, redraw_canvas, rerender, 0);
2448 //printf("CWindowCanvas::cursor_motion_event 1 %d %d\n", x, y);
2449 result = test_crop(0, redraw);
2453 case CWINDOW_MASK_CONTROL_IN:
2454 case CWINDOW_MASK_CONTROL_OUT:
2455 case CWINDOW_MASK_TRANSLATE:
2456 result = do_mask(redraw,
2463 case CWINDOW_EYEDROP:
2464 result = do_eyedrop(rerender, 0);
2473 switch(mwindow->edl->session->cwindow_operation)
2476 result = test_crop(0, redraw);
2482 // If the window is never unlocked before calling send_command the
2483 // display shouldn't get stuck on the old video frame although it will
2484 // flicker between the old video frame and the new video frame.
2494 mwindow->gui->lock_window("CWindowCanvas::cursor_motion_event 1");
2495 mwindow->gui->canvas->draw_overlays();
2496 mwindow->gui->canvas->flash();
2497 mwindow->gui->unlock_window();
2502 mwindow->restart_brender();
2503 mwindow->sync_parameters(CHANGE_PARAMS);
2504 gui->cwindow->playback_engine->que->send_command(CURRENT_FRAME,
2508 if(!redraw) gui->update_tool();
2513 int CWindowCanvas::button_press_event()
2517 int redraw_canvas = 0;
2520 if(Canvas::button_press_event()) return 1;
2522 gui->translating_zoom = gui->shift_down();
2525 //printf("CWindowCanvas::button_press_event 2 %f %f\n", gui->x_origin, gui->y_origin, gui->x_origin, gui->y_origin);
2527 float zoom_x, zoom_y, conformed_w, conformed_h;
2528 get_zooms(mwindow->edl, 0, zoom_x, zoom_y, conformed_w, conformed_h);
2529 gui->x_offset = get_x_offset(mwindow->edl, 0, zoom_x, conformed_w, conformed_h);
2530 gui->y_offset = get_y_offset(mwindow->edl, 0, zoom_y, conformed_w, conformed_h);
2533 if(get_buttonpress() == 2)
2535 gui->current_operation = CWINDOW_SCROLL;
2541 switch(mwindow->edl->session->cwindow_operation)
2543 case CWINDOW_CAMERA:
2544 result = test_bezier(1, redraw, redraw_canvas, rerender, 1);
2547 case CWINDOW_PROJECTOR:
2548 result = test_bezier(1, redraw, redraw_canvas, rerender, 0);
2552 result = test_zoom(redraw);
2556 result = test_crop(1, redraw);
2560 if(get_buttonpress() == 1)
2561 result = do_mask(redraw, rerender, 1, 0, 0);
2564 case CWINDOW_EYEDROP:
2565 result = do_eyedrop(rerender, 1);
2576 // rerendering can also be caused by press event
2579 mwindow->restart_brender();
2580 mwindow->sync_parameters(CHANGE_PARAMS);
2581 gui->cwindow->playback_engine->que->send_command(CURRENT_FRAME,
2585 if(!redraw) gui->update_tool();
2590 int CWindowCanvas::button_release_event()
2594 switch(gui->current_operation)
2596 case CWINDOW_SCROLL:
2600 case CWINDOW_CAMERA:
2601 mwindow->undo->update_undo(_("camera"), LOAD_AUTOMATION);
2604 case CWINDOW_PROJECTOR:
2605 mwindow->undo->update_undo(_("projector"), LOAD_AUTOMATION);
2609 case CWINDOW_MASK_CONTROL_IN:
2610 case CWINDOW_MASK_CONTROL_OUT:
2611 case CWINDOW_MASK_TRANSLATE:
2612 mwindow->undo->update_undo(_("mask point"), LOAD_AUTOMATION);
2617 gui->current_operation = CWINDOW_NONE;
2621 void CWindowCanvas::zoom_resize_window(float percentage)
2623 int canvas_w, canvas_h;
2624 calculate_sizes(mwindow->edl->get_aspect_ratio(),
2625 mwindow->edl->session->output_w,
2626 mwindow->edl->session->output_h,
2631 new_w = canvas_w + (gui->get_w() - mwindow->theme->ccanvas_w);
2632 new_h = canvas_h + (gui->get_h() - mwindow->theme->ccanvas_h);
2633 gui->resize_window(new_w, new_h);
2634 gui->resize_event(new_w, new_h);
2637 void CWindowCanvas::toggle_controls()
2639 mwindow->session->cwindow_controls = !mwindow->session->cwindow_controls;
2640 gui->resize_event(gui->get_w(), gui->get_h());
2643 int CWindowCanvas::get_cwindow_controls()
2645 return mwindow->session->cwindow_controls;