r125: This commit was manufactured by cvs2svn to create tag 'r1_1_7-last'.
[cinelerra_cv/mob.git] / hvirtual / cinelerra / cwindowgui.C
blob66a1415f8ecc7ebace81d5983347cf9c59678352
1 //#include "apanel.h"
2 #include "automation.h"
3 #include "autos.h"
4 #include "bezierauto.h"
5 #include "bezierautos.h"
6 #include "canvas.h"
7 #include "clip.h"
8 #include "cpanel.h"
9 #include "cplayback.h"
10 #include "ctimebar.h"
11 #include "cursors.h"
12 #include "cwindowgui.h"
13 #include "cwindow.h"
14 #include "cwindowtool.h"
15 #include "editpanel.h"
16 #include "edl.h"
17 #include "edlsession.h"
18 #include "floatauto.h"
19 #include "floatautos.h"
20 #include "localsession.h"
21 #include "mainclock.h"
22 #include "mainmenu.h"
23 #include "mainundo.h"
24 #include "mainsession.h"
25 #include "maskauto.h"
26 #include "maskautos.h"
27 #include "meterpanel.h"
28 #include "mwindowgui.h"
29 #include "mwindow.h"
30 #include "mwindow.h"
31 #include "playtransport.h"
32 #include "theme.h"
33 #include "trackcanvas.h"
34 #include "tracks.h"
35 #include "transportque.h"
36 #include "vtrack.h"
39 #include <libintl.h>
40 #define _(String) gettext(String)
41 #define gettext_noop(String) String
42 #define N_(String) gettext_noop (String)
45 CWindowGUI::CWindowGUI(MWindow *mwindow, CWindow *cwindow)
46  : BC_Window(PROGRAM_NAME ": Compositor",
47         mwindow->session->cwindow_x, 
48     mwindow->session->cwindow_y, 
49     mwindow->session->cwindow_w, 
50     mwindow->session->cwindow_h,
51     100,
52     100,
53     1,
54     1,
55     1,
56         BLACK,
57         mwindow->edl->session->get_cwindow_display())
59         this->mwindow = mwindow;
60     this->cwindow = cwindow;
61         affected_track = 0;
62         affected_auto = 0;
63         affected_point = 0;
64         x_offset = 0;
65         y_offset = 0;
66         x_origin = 0;
67         y_origin = 0;
68         current_operation = CWINDOW_NONE;
69         tool_panel = 0;
70         translating_zoom = 0;
73 CWindowGUI::~CWindowGUI()
75         if(tool_panel) delete tool_panel;
76         delete meters;
77         delete composite_panel;
78         delete canvas;
79         delete transport;
80         delete edit_panel;
81         delete zoom_panel;
84 int CWindowGUI::create_objects()
86 //printf("CWindowGUI::create_objects 1\n");
87         set_icon(mwindow->theme->cwindow_icon);
89 //printf("CWindowGUI::create_objects 1\n");
91 //printf("CWindowGUI::create_objects 1\n");
92         mwindow->theme->get_cwindow_sizes(this);
93 //printf("CWindowGUI::create_objects 1\n");
94         mwindow->theme->draw_cwindow_bg(this);
95         flash();
96 //printf("CWindowGUI::create_objects 1\n");
98 //printf("CWindowGUI::create_objects 1\n");
99 // Meters required by composite panel
100         meters = new CWindowMeters(mwindow, 
101                 this,
102                 mwindow->theme->cmeter_x,
103                 mwindow->theme->cmeter_y,
104                 mwindow->theme->cmeter_h);
105         meters->create_objects();
106 //printf("CWindowGUI::create_objects 1\n");
108 //printf("CWindowGUI::create_objects 1\n");
110         composite_panel = new CPanel(mwindow, 
111                 this, 
112                 mwindow->theme->ccomposite_x,
113                 mwindow->theme->ccomposite_y,
114                 mwindow->theme->ccomposite_w,
115                 mwindow->theme->ccomposite_h);
116         composite_panel->create_objects();
117 //printf("CWindowGUI::create_objects 1\n");
119         canvas = new CWindowCanvas(mwindow, this);
120         canvas->create_objects(mwindow->edl);
121 //printf("CWindowGUI::create_objects 1\n");
124         add_subwindow(timebar = new CTimeBar(mwindow,
125                 this,
126                 mwindow->theme->ctimebar_x,
127                 mwindow->theme->ctimebar_y,
128                 mwindow->theme->ctimebar_w, 
129                 mwindow->theme->ctimebar_h));
130         timebar->create_objects();
131 //printf("CWindowGUI::create_objects 2\n");
133         add_subwindow(slider = new CWindowSlider(mwindow, 
134                 cwindow, 
135                 mwindow->theme->cslider_x,
136                 mwindow->theme->cslider_y, 
137                 mwindow->theme->cslider_w));
138 //printf("CWindowGUI::create_objects 1\n");
140         transport = new CWindowTransport(mwindow, 
141                 this, 
142                 mwindow->theme->ctransport_x, 
143                 mwindow->theme->ctransport_y);
144         transport->create_objects();
145         transport->set_slider(slider);
147         edit_panel = new CWindowEditing(mwindow, cwindow);
148         edit_panel->set_meters(meters);
149         edit_panel->create_objects();
150 //printf("CWindowGUI::create_objects 1\n");
152 //      add_subwindow(clock = new MainClock(mwindow, 
153 //              mwindow->theme->ctime_x, 
154 //              mwindow->theme->ctime_y));
155 // 
156         zoom_panel = new CWindowZoom(mwindow, 
157                 this, 
158                 mwindow->theme->czoom_x, 
159                 mwindow->theme->czoom_y);
160         zoom_panel->create_objects();
161         zoom_panel->zoom_text->add_item(new BC_MenuItem(AUTO_ZOOM));
162         if(!mwindow->edl->session->cwindow_scrollbars) zoom_panel->set_text(AUTO_ZOOM);
163 //printf("CWindowGUI::create_objects 1\n");
165 //      destination = new CWindowDestination(mwindow, 
166 //              this, 
167 //              mwindow->theme->cdest_x,
168 //              mwindow->theme->cdest_y);
169 //      destination->create_objects();
171 // Must create after meter panel
172         tool_panel = new CWindowTool(mwindow, this);
173         tool_panel->Thread::start();
174         
175         set_operation(mwindow->edl->session->cwindow_operation);
176         canvas->draw_refresh();
179 //printf("CWindowGUI::create_objects 2\n");
180         return 0;
183 int CWindowGUI::translation_event()
185         mwindow->session->cwindow_x = get_x();
186         mwindow->session->cwindow_y = get_y();
187         return 0;
190 int CWindowGUI::resize_event(int w, int h)
192         mwindow->session->cwindow_x = get_x();
193         mwindow->session->cwindow_y = get_y();
194         mwindow->session->cwindow_w = w;
195         mwindow->session->cwindow_h = h;
197 //printf("CWindowGUI::resize_event 1\n");
198         mwindow->theme->get_cwindow_sizes(this);
199         mwindow->theme->draw_cwindow_bg(this);
200         flash();
202 //printf("CWindowGUI::resize_event 1\n");
203         composite_panel->reposition_buttons(mwindow->theme->ccomposite_x,
204                 mwindow->theme->ccomposite_y);
205 //printf("CWindowGUI::resize_event 1\n");
207         canvas->reposition_window(mwindow->edl,
208                 mwindow->theme->ccanvas_x,
209                 mwindow->theme->ccanvas_y,
210                 mwindow->theme->ccanvas_w,
211                 mwindow->theme->ccanvas_h);
213         timebar->resize_event();
215         slider->reposition_window(mwindow->theme->cslider_x,
216                 mwindow->theme->cslider_y, 
217                 mwindow->theme->cslider_w);
218 // Recalibrate pointer motion range
219         slider->set_position();
220 //printf("CWindowGUI::resize_event 1\n");
222         transport->reposition_buttons(mwindow->theme->ctransport_x, 
223                 mwindow->theme->ctransport_y);
224 //printf("CWindowGUI::resize_event 1\n");
226         edit_panel->reposition_buttons(mwindow->theme->cedit_x, 
227                 mwindow->theme->cedit_y);
228 //printf("CWindowGUI::resize_event 1\n");
230 //      clock->reposition_window(mwindow->theme->ctime_x, 
231 //              mwindow->theme->ctime_y);
232 //printf("CWindowGUI::resize_event 1\n");
234         zoom_panel->reposition_window(mwindow->theme->czoom_x, 
235                 mwindow->theme->czoom_y);
236 //printf("CWindowGUI::resize_event 1\n");
238 //      destination->reposition_window(mwindow->theme->cdest_x,
239 //              mwindow->theme->cdest_y);
240 //printf("CWindowGUI::resize_event 1\n");
242         meters->reposition_window(mwindow->theme->cmeter_x,
243                 mwindow->theme->cmeter_y,
244                 mwindow->theme->cmeter_h);
245 //printf("CWindowGUI::resize_event 2\n");
247         BC_WindowBase::resize_event(w, h);
248         return 1;
256 // TODO
257 // Don't refresh the canvas in a load file operation which is going to
258 // refresh it anyway.
259 void CWindowGUI::set_operation(int value)
261 //printf("CWindowGUI::set_operation 1 %d\n", value);
262         mwindow->edl->session->cwindow_operation = value;
263 //printf("CWindowGUI::set_operation 1 %d\n", value);
265         composite_panel->set_operation(value);
266 //printf("CWindowGUI::set_operation 1 %d\n", value);
267         edit_panel->update();
269         tool_panel->start_tool(value);
270         canvas->draw_refresh();
271 //printf("CWindowGUI::set_operation 2 %d\n", value);
274 void CWindowGUI::update_tool()
276 //printf("CWindowGUI::update_tool 1\n");
277         tool_panel->update_values();
280 int CWindowGUI::close_event()
282 //printf("CWindowGUI::close_event 1\n");
283         hide_window();
284 //printf("CWindowGUI::close_event 1\n");
285         mwindow->session->show_cwindow = 0;
286 //printf("CWindowGUI::close_event 1\n");
287         mwindow->gui->lock_window();
288 //printf("CWindowGUI::close_event 1\n");
289         mwindow->gui->mainmenu->show_cwindow->set_checked(0);
290 //printf("CWindowGUI::close_event 1\n");
291         mwindow->gui->unlock_window();
292 //printf("CWindowGUI::close_event 1\n");
293         mwindow->save_defaults();
294 //printf("CWindowGUI::close_event 2\n");
295         return 1;
299 int CWindowGUI::keypress_event()
301         int result = 0;
303 //printf("CWindowGUI::keypress_event 1\n");
304         switch(get_keypress())
305         {
306                 case 'w':
307                 case 'W':
308                         close_event();
309                         result = 1;
310                         break;
311         }
313 //printf("CWindowGUI::keypress_event 1\n");
314         if(!result) result = transport->keypress_event();
316 //printf("CWindowGUI::keypress_event 2\n");
317         return result;
320 void CWindowGUI::drag_motion()
322         if(get_hidden()) return;
324         if(mwindow->session->current_operation == DRAG_ASSET ||
325                 mwindow->session->current_operation == DRAG_VTRANSITION ||
326                 mwindow->session->current_operation == DRAG_VEFFECT)
327         {
328                 int old_status = mwindow->session->ccanvas_highlighted;
329                 int cursor_x = get_relative_cursor_x();
330                 int cursor_y = get_relative_cursor_y();
332                 mwindow->session->ccanvas_highlighted = get_cursor_over_window() &&
333                         cursor_x >= canvas->x &&
334                         cursor_x < canvas->x + canvas->w &&
335                         cursor_y >= canvas->y &&
336                         cursor_y < canvas->y + canvas->h;
339                 if(old_status != mwindow->session->ccanvas_highlighted)
340                         canvas->draw_refresh();
341         }
344 int CWindowGUI::drag_stop()
346         int result = 0;
347         if(get_hidden()) return 0;
349         if((mwindow->session->current_operation == DRAG_ASSET ||
350                 mwindow->session->current_operation == DRAG_VTRANSITION ||
351                 mwindow->session->current_operation == DRAG_VEFFECT) &&
352                 mwindow->session->ccanvas_highlighted)
353         {
354 // Hide highlighting
355                 mwindow->session->ccanvas_highlighted = 0;
356                 canvas->draw_refresh();
357                 result = 1;
358         }
359         else
360                 return 0;
362         if(mwindow->session->current_operation == DRAG_ASSET)
363         {
364                 if(mwindow->session->drag_assets->total)
365                 {
366                         mwindow->gui->lock_window();
367                         mwindow->undo->update_undo_before(_("insert assets"), 
368                                 LOAD_ALL);
369                         mwindow->clear(0);
370                         mwindow->load_assets(mwindow->session->drag_assets, 
371                                 mwindow->edl->local_session->get_selectionstart(), 
372                                 LOAD_PASTE,
373                                 mwindow->session->track_highlighted,
374                                 0,
375                                 mwindow->edl->session->labels_follow_edits, 
376                                 mwindow->edl->session->plugins_follow_edits);
377                 }
379                 if(mwindow->session->drag_clips->total)
380                 {
381                         mwindow->gui->lock_window();
382                         mwindow->undo->update_undo_before(_("insert assets"), 
383                                 LOAD_ALL);
384                         mwindow->clear(0);
385                         mwindow->paste_edls(mwindow->session->drag_clips, 
386                                 LOAD_PASTE, 
387                                 mwindow->session->track_highlighted,
388                                 mwindow->edl->local_session->get_selectionstart(),
389                                 mwindow->edl->session->labels_follow_edits, 
390                                 mwindow->edl->session->plugins_follow_edits);
391                 }
393                 if(mwindow->session->drag_assets->total ||
394                         mwindow->session->drag_clips->total)
395                 {
396                         mwindow->save_backup();
397                         mwindow->restart_brender();
398                         mwindow->gui->update(1, 1, 1, 1, 0, 1, 0);
399                         mwindow->undo->update_undo_after();
400                         mwindow->gui->unlock_window();
401                         mwindow->sync_parameters(LOAD_ALL);
402                 }
403         }
405         if(mwindow->session->current_operation == DRAG_VEFFECT)
406         {
407 //printf("CWindowGUI::drag_stop 1\n");
408                 Track *affected_track = cwindow->calculate_affected_track();
409 //printf("CWindowGUI::drag_stop 2\n");
411                 mwindow->gui->lock_window();
412                 mwindow->insert_effects_cwindow(affected_track);
413                 mwindow->session->current_operation = NO_OPERATION;
414                 mwindow->gui->unlock_window();
415         }
417         if(mwindow->session->current_operation == DRAG_VTRANSITION)
418         {
419                 Track *affected_track = cwindow->calculate_affected_track();
420                 mwindow->gui->lock_window();
421                 mwindow->paste_transition_cwindow(affected_track);
422                 mwindow->session->current_operation = NO_OPERATION;
423                 mwindow->gui->unlock_window();
424         }
426         return result;
430 CWindowEditing::CWindowEditing(MWindow *mwindow, CWindow *cwindow)
431  : EditPanel(mwindow, 
432                 cwindow->gui, 
433                 mwindow->theme->cedit_x, 
434                 mwindow->theme->cedit_y,
435                 mwindow->edl->session->editing_mode, 
436                 0,
437                 1,
438                 0, 
439                 0,
440                 1,
441                 1,
442                 1,
443                 1,
444                 1,
445                 0,
446                 1,
447                 1,
448                 1,
449                 0,
450                 1)
452         this->mwindow = mwindow;
453         this->cwindow = cwindow;
456 void CWindowEditing::set_inpoint()
458         mwindow->set_inpoint(0);
461 void CWindowEditing::set_outpoint()
463         mwindow->set_outpoint(0);
470 CWindowMeters::CWindowMeters(MWindow *mwindow, CWindowGUI *gui, int x, int y, int h)
471  : MeterPanel(mwindow, 
472                 gui,
473                 x,
474                 y,
475                 h,
476                 mwindow->edl->session->audio_channels,
477                 mwindow->edl->session->cwindow_meter)
479         this->mwindow = mwindow;
480         this->gui = gui;
483 CWindowMeters::~CWindowMeters()
487 int CWindowMeters::change_status_event()
489 //printf("CWindowMeters::change_status_event 1 %d\n", gui->meters->use_meters);
490         mwindow->edl->session->cwindow_meter = use_meters;
491         mwindow->theme->get_cwindow_sizes(gui);
492         gui->resize_event(gui->get_w(), gui->get_h());
493         return 1;
498 #define MIN_ZOOM 0.25
499 #define MAX_ZOOM 4.0
501 CWindowZoom::CWindowZoom(MWindow *mwindow, CWindowGUI *gui, int x, int y)
502  : ZoomPanel(mwindow, 
503         gui, 
504         (long)mwindow->edl->session->cwindow_zoom, 
505         x, 
506         y,
507         100, 
508         MIN_ZOOM, 
509         MAX_ZOOM, 
510         ZOOM_PERCENTAGE)
512         this->mwindow = mwindow;
513         this->gui = gui;
516 CWindowZoom::~CWindowZoom()
520 int CWindowZoom::handle_event()
522         if(!strcasecmp(AUTO_ZOOM, get_text()))
523         {
524                 mwindow->edl->session->cwindow_scrollbars = 0;
525         }
526         else
527         {
528                 mwindow->edl->session->cwindow_scrollbars = 1;
529         }
531 //printf("CWindowZoom::handle_event 1 %d %d\n", gui->canvas->get_xscroll(), gui->canvas->get_yscroll());
532         gui->canvas->update_zoom(gui->canvas->get_xscroll(), 
533                 gui->canvas->get_yscroll(), 
534                 get_value());
535 //printf("CWindowZoom::handle_event 2 %d %d\n", gui->canvas->get_xscroll(), gui->canvas->get_yscroll());
536         gui->canvas->reposition_window(mwindow->edl, 
537                 mwindow->theme->ccanvas_x,
538                 mwindow->theme->ccanvas_y,
539                 mwindow->theme->ccanvas_w,
540                 mwindow->theme->ccanvas_h);
541 //printf("CWindowZoom::handle_event 3 %d %d\n", gui->canvas->get_xscroll(), gui->canvas->get_yscroll());
542         gui->canvas->draw_refresh();
543 //printf("CWindowZoom::handle_event 4 %d %d\n", gui->canvas->get_xscroll(), gui->canvas->get_yscroll());
544         return 1;
549 CWindowSlider::CWindowSlider(MWindow *mwindow, CWindow *cwindow, int x, int y, int pixels)
550  : BC_PercentageSlider(x, 
551                         y,
552                         0,
553                         pixels, 
554                         pixels, 
555                         0, 
556                         1, 
557                         0)
559         this->mwindow = mwindow;
560         this->cwindow = cwindow;
563 CWindowSlider::~CWindowSlider()
567 int CWindowSlider::handle_event()
569         unlock_window();
570         cwindow->playback_engine->interrupt_playback(1);
571         lock_window();
572         
573         mwindow->gui->lock_window();
574         mwindow->select_point((double)get_value());
575         mwindow->gui->unlock_window();
576         return 1;
579 void CWindowSlider::set_position()
581         double new_length = mwindow->edl->tracks->total_playable_length();
582         if(mwindow->edl->local_session->preview_end <= 0 ||
583                 mwindow->edl->local_session->preview_end > new_length)
584                 mwindow->edl->local_session->preview_end = new_length;
585         if(mwindow->edl->local_session->preview_start > 
586                 mwindow->edl->local_session->preview_end)
587                 mwindow->edl->local_session->preview_start = 0;
591         update(mwindow->theme->cslider_w, 
592                 mwindow->edl->local_session->selectionstart, 
593                 mwindow->edl->local_session->preview_start, 
594                 mwindow->edl->local_session->preview_end);
598 int CWindowSlider::increase_value()
600         unlock_window();
601         cwindow->gui->transport->handle_transport(SINGLE_FRAME_FWD);
602 //printf("CWindowSlider::increase_value 1\n");
603         lock_window();
604         return 1;
607 int CWindowSlider::decrease_value()
609         unlock_window();
610         cwindow->gui->transport->handle_transport(SINGLE_FRAME_REWIND);
611 //printf("CWindowSlider::decrease_value 1\n");
612         lock_window();
613         return 1;
617 // CWindowDestination::CWindowDestination(MWindow *mwindow, CWindowGUI *cwindow, int x, int y)
618 //  : BC_PopupTextBox(cwindow, 
619 //      &cwindow->destinations, 
620 //      cwindow->destinations.values[cwindow->cwindow->destination]->get_text(),
621 //      x, 
622 //      y, 
623 //      70, 
624 //      200)
625 // {
626 //      this->mwindow = mwindow;
627 //      this->cwindow = cwindow;
628 // }
629 // 
630 // CWindowDestination::~CWindowDestination()
631 // {
632 // }
633 // 
634 // int CWindowDestination::handle_event()
635 // {
636 //      return 1;
637 // }
640 CWindowTransport::CWindowTransport(MWindow *mwindow, 
641         CWindowGUI *gui, 
642         int x, 
643         int y)
644  : PlayTransport(mwindow, 
645         gui, 
646         x, 
647         y)
649         this->gui = gui;
652 EDL* CWindowTransport::get_edl()
654         return mwindow->edl;
657 void CWindowTransport::goto_start()
659         gui->unlock_window();
660         handle_transport(REWIND, 1);
662         mwindow->gui->lock_window();
663         mwindow->goto_start();
664         mwindow->gui->unlock_window();
666         gui->lock_window();
669 void CWindowTransport::goto_end()
671         gui->unlock_window();
672         handle_transport(GOTO_END, 1);
674         mwindow->gui->lock_window();
675         mwindow->goto_end();
676         mwindow->gui->unlock_window();
678         gui->lock_window();
683 CWindowCanvas::CWindowCanvas(MWindow *mwindow, CWindowGUI *gui)
684  : Canvas(gui,
685                 mwindow->theme->ccanvas_x,
686                 mwindow->theme->ccanvas_y,
687                 mwindow->theme->ccanvas_w,
688                 mwindow->theme->ccanvas_h,
689                 0,
690                 0,
691                 mwindow->edl->session->cwindow_scrollbars,
692                 1)
694         this->mwindow = mwindow;
695         this->gui = gui;
698 void CWindowCanvas::update_zoom(int x, int y, float zoom)
700         use_scrollbars = mwindow->edl->session->cwindow_scrollbars;
702         mwindow->edl->session->cwindow_xscroll = x;
703         mwindow->edl->session->cwindow_yscroll = y;
704         mwindow->edl->session->cwindow_zoom = zoom;
707 int CWindowCanvas::get_xscroll()
709         return mwindow->edl->session->cwindow_xscroll;
712 int CWindowCanvas::get_yscroll()
714         return mwindow->edl->session->cwindow_yscroll;
718 float CWindowCanvas::get_zoom()
720         return mwindow->edl->session->cwindow_zoom;
723 void CWindowCanvas::draw_refresh()
725         if(!canvas->video_is_on())
726         {
727 //printf("CWindowCanvas::draw_refresh 1 %f\n", mwindow->edl->session->cwindow_zoom);
728                 canvas->clear_box(0, 0, canvas->get_w(), canvas->get_h());
729 //printf("CWindowCanvas::draw_refresh 2\n");
731                 if(refresh_frame)
732                 {
733                         int in_x, in_y, in_w, in_h, out_x, out_y, out_w, out_h;
734 //printf("CWindowCanvas::draw_refresh 3\n");
735                         get_transfers(mwindow->edl, 
736                                 in_x, 
737                                 in_y, 
738                                 in_w, 
739                                 in_h, 
740                                 out_x, 
741                                 out_y, 
742                                 out_w, 
743                                 out_h);
746 // printf("CWindowCanvas::draw_refresh %d %d %d %d -> %d %d %d %d\n", in_x, in_y, in_w, in_h, out_x, out_y, out_w, out_h);
747 //                      canvas->clear_box(0, 0, canvas->get_w(), canvas->get_h());
750 //printf("CWindowCanvas::draw_refresh 5\n");
751                         if(out_w > 0 && out_h > 0 && in_w > 0 && in_h > 0)
752                                 canvas->draw_vframe(refresh_frame,
753                                                 out_x, 
754                                                 out_y, 
755                                                 out_w, 
756                                                 out_h,
757                                                 in_x, 
758                                                 in_y, 
759                                                 in_w, 
760                                                 in_h,
761                                                 0);
762 //printf("CWindowCanvas::draw_refresh 6\n");
763                 }
764                 else
765                 {
766 //printf("CWindowCanvas::draw_refresh 7\n");
767                         canvas->clear_box(0, 0, canvas->get_w(), canvas->get_h());
768 //printf("CWindowCanvas::draw_refresh 8\n");
769                 }
771 //printf("CWindowCanvas::draw_refresh 9\n");
772                 draw_overlays();
773                 canvas->flash();
774                 canvas->flush();
775 //printf("CWindowCanvas::draw_refresh 10\n");
776         }
779 #define CROPHANDLE_W 10
780 #define CROPHANDLE_H 10
782 void CWindowCanvas::draw_crophandle(int x, int y)
784         canvas->draw_box(x, y, CROPHANDLE_W, CROPHANDLE_H);
787 #define CONTROL_W 10
788 #define CONTROL_H 10
789 #define FIRST_CONTROL_W 20
790 #define FIRST_CONTROL_H 20
791 #undef BC_INFINITY
792 #define BC_INFINITY 65536
793 #ifndef SQR
794 #define SQR(x) ((x) * (x))
795 #endif
797 int CWindowCanvas::do_mask(int &redraw, 
798                 int &rerender, 
799                 int button_press, 
800                 int cursor_motion,
801                 int draw)
803 // Retrieve points from top recordable track
804 //printf("CWindowCanvas::do_mask 1\n");
805         Track *track = gui->cwindow->calculate_affected_track();
806 //printf("CWindowCanvas::do_mask 2\n");
808         if(!track) return 0;
809 //printf("CWindowCanvas::do_mask 3\n");
811         MaskAutos *mask_autos = track->automation->mask_autos;
812         long position = track->to_units(mwindow->edl->local_session->selectionstart,
813                 0);
814         ArrayList<MaskPoint*> points;
815         mask_autos->get_points(&points, mwindow->edl->session->cwindow_mask,
816                 position, 
817                 PLAY_FORWARD);
818 //printf("CWindowCanvas::do_mask 4\n");
820 // Translate mask to projection
821         BezierAutos *projector_autos = track->automation->projector_autos;
822         FloatAutos *projector_zooms = track->automation->pzoom_autos;
823         BezierAuto *before = 0, *after = 0;
824         FloatAuto *zoom_before = 0, *zoom_after = 0;
825         float projector_x, projector_y, projector_z;
826 // Projector zooms relative to the center of the track output.
827         float half_track_w = (float)track->track_w / 2;
828         float half_track_h = (float)track->track_h / 2;
829         projector_autos->get_center(projector_x, 
830                         projector_y, 
831                         projector_z, 
832                         position, 
833                         PLAY_FORWARD, 
834                         &before, 
835                         &after);
836         projector_z = projector_zooms->get_value(position,
837                 PLAY_FORWARD,
838                 zoom_before,
839                 zoom_after);
840 // printf("CWindowCanvas::do_mask 1 %f %f %f\n", projector_x, 
841 //                      projector_y, 
842 //                      projector_z);
845 // Get position of cursor relative to mask
846         float mask_cursor_x = get_cursor_x();
847         float mask_cursor_y = get_cursor_y();
848         canvas_to_output(mwindow->edl, 0, mask_cursor_x, mask_cursor_y);
850         mask_cursor_x -= projector_x;
851         mask_cursor_y -= projector_y;
852         mask_cursor_x = half_track_w + (mask_cursor_x - half_track_w) / projector_z;
853         mask_cursor_y = half_track_h + (mask_cursor_y - half_track_h) / projector_z;
855 // Fix cursor origin
856         if(button_press)
857         {
858                 gui->x_origin = mask_cursor_x;
859                 gui->y_origin = mask_cursor_y;
860         }
862         int result = 0;
863 // Points of closest line
864         int shortest_point1 = -1;
865         int shortest_point2 = -1;
866 // Closest point
867         int shortest_point = -1;
868 // Distance to closest line
869         float shortest_line_distance = BC_INFINITY;
870 // Distance to closest point
871         float shortest_point_distance = BC_INFINITY;
872         int selected_point = -1;
873         int selected_control_point = -1;
874         float selected_control_point_distance = BC_INFINITY;
875         ArrayList<int> x_points;
876         ArrayList<int> y_points;
878         if(!cursor_motion)
879         {
880                 if(draw)
881                 {
882                         canvas->set_color(WHITE);
883                         canvas->set_inverse();
884                 }
885 //printf("CWindowCanvas::do_mask 1 %d\n", points.total);
887 // Never draw closed polygon and a closed
888 // polygon is harder to add points to.
889                 for(int i = 0; i < points.total && !result; i++)
890                 {
891                         MaskPoint *point1 = points.values[i];
892                         MaskPoint *point2 = (i >= points.total - 1) ? 
893                                 points.values[0] : 
894                                 points.values[i + 1];
895                         float x0, x1, x2, x3;
896                         float y0, y1, y2, y3;
897                         float old_x, old_y, x, y;
898                         int segments = (int)(sqrt(SQR(point1->x - point2->x) + SQR(point1->y - point2->y)));
900 //printf("CWindowCanvas::do_mask 1 %f, %f -> %f, %f projectorz=%f\n",
901 //point1->x, point1->y, point2->x, point2->y, projector_z);
902                         for(int j = 0; j <= segments && !result; j++)
903                         {
904 //printf("CWindowCanvas::do_mask 1 %f, %f -> %f, %f\n", x0, y0, x3, y3);
905                                 x0 = point1->x;
906                                 y0 = point1->y;
907                                 x1 = point1->x + point1->control_x2;
908                                 y1 = point1->y + point1->control_y2;
909                                 x2 = point2->x + point2->control_x1;
910                                 y2 = point2->y + point2->control_y1;
911                                 x3 = point2->x;
912                                 y3 = point2->y;
914                                 float t = (float)j / segments;
915                                 float tpow2 = t * t;
916                                 float tpow3 = t * t * t;
917                                 float invt = 1 - t;
918                                 float invtpow2 = invt * invt;
919                                 float invtpow3 = invt * invt * invt;
921                                 x = (        invtpow3 * x0
922                                         + 3 * t     * invtpow2 * x1
923                                         + 3 * tpow2 * invt     * x2 
924                                         +     tpow3            * x3);
925                                 y = (        invtpow3 * y0 
926                                         + 3 * t     * invtpow2 * y1
927                                         + 3 * tpow2 * invt     * y2 
928                                         +     tpow3            * y3);
930                                 x = half_track_w + (x - half_track_w) * projector_z + projector_x;
931                                 y = half_track_h + (y - half_track_h) * projector_z + projector_y;
934 // Test new point addition
935                                 if(button_press)
936                                 {
937                                         float line_distance = 
938                                                 sqrt(SQR(x - mask_cursor_x) + SQR(y - mask_cursor_y));
940 //printf("CWindowCanvas::do_mask 1 x=%f mask_cursor_x=%f y=%f mask_cursor_y=%f %f %f %d, %d\n", 
941 //x, mask_cursor_x, y, mask_cursor_y, line_distance, shortest_line_distance, shortest_point1, shortest_point2);
942                                         if(line_distance < shortest_line_distance || 
943                                                 shortest_point1 < 0)
944                                         {
945                                                 shortest_line_distance = line_distance;
946                                                 shortest_point1 = i;
947                                                 shortest_point2 = (i >= points.total - 1) ? 0 : (i + 1);
948 //printf("CWindowCanvas::do_mask 2 %f %f %d, %d\n", line_distance, shortest_line_distance, shortest_point1, shortest_point2);
949                                         }
952                                         float point_distance1 = 
953                                                 sqrt(SQR(point1->x - mask_cursor_x) + SQR(point1->y - mask_cursor_y));
954                                         float point_distance2 = 
955                                                 sqrt(SQR(point2->x - mask_cursor_x) + SQR(point2->y - mask_cursor_y));
957                                         if(point_distance1 < shortest_point_distance || 
958                                                 shortest_point < 0)
959                                         {
960                                                 shortest_point_distance = point_distance1;
961                                                 shortest_point = i;
962                                         }
964                                         if(point_distance2 < shortest_point_distance || 
965                                                 shortest_point < 0)
966                                         {
967                                                 shortest_point_distance = point_distance2;
968                                                 shortest_point = (i >= points.total - 1) ? 0 : (i + 1);
969                                         }
970                                 }
972                                 output_to_canvas(mwindow->edl, 0, x, y);
975 #define TEST_BOX(cursor_x, cursor_y, target_x, target_y) \
976         (cursor_x >= target_x - CONTROL_W / 2 && \
977         cursor_x < target_x + CONTROL_W / 2 && \
978         cursor_y >= target_y - CONTROL_H / 2 && \
979         cursor_y < target_y + CONTROL_H / 2)
981 // Test existing point selection
982                                 if(button_press)
983                                 {
984                                         float canvas_x = half_track_w + (x0 - half_track_w) * projector_z + projector_x;
985                                         float canvas_y = half_track_h + (y0 - half_track_h) * projector_z + projector_y;
986                                         int cursor_x = get_cursor_x();
987                                         int cursor_y = get_cursor_y();
989 // Test first point
990                                         if(gui->shift_down())
991                                         {
992                                                 float control_x = half_track_w + (x1 - half_track_w) * projector_z + projector_x;
993                                                 float control_y = half_track_h + (y1 - half_track_h) * projector_z + projector_y;
994                                                 output_to_canvas(mwindow->edl, 0, control_x, control_y);
996                                                 float distance = 
997                                                         sqrt(SQR(control_x - cursor_x) + SQR(control_y - cursor_y));
999                                                 if(distance < selected_control_point_distance)
1000                                                 {
1001                                                         selected_point = i;
1002                                                         selected_control_point = 1;
1003                                                         selected_control_point_distance = distance;
1004                                                 }
1005                                         }
1006                                         else
1007                                         {
1008                                                 output_to_canvas(mwindow->edl, 0, canvas_x, canvas_y);
1009                                                 if(!gui->ctrl_down())
1010                                                 {
1011                                                         if(TEST_BOX(cursor_x, cursor_y, canvas_x, canvas_y))
1012                                                         {
1013                                                                 selected_point = i;
1014                                                         }
1015                                                 }
1016                                                 else
1017                                                 {
1018                                                         selected_point = shortest_point;
1019                                                 }
1020                                         }
1022 // Test second point
1023                                         canvas_x = half_track_w + (x3 - half_track_w) * projector_z + projector_x;
1024                                         canvas_y = half_track_h + (y3 - half_track_h) * projector_z + projector_y;
1025                                         if(gui->shift_down())
1026                                         {
1027                                                 float control_x = half_track_w + (x2 - half_track_w) * projector_z + projector_x;
1028                                                 float control_y = half_track_h + (y2 - half_track_h) * projector_z + projector_y;
1029                                                 output_to_canvas(mwindow->edl, 0, control_x, control_y);
1031                                                 float distance = 
1032                                                         sqrt(SQR(control_x - cursor_x) + SQR(control_y - cursor_y));
1034 //printf("CWindowCanvas::do_mask %d %f %f\n", i, distance, selected_control_point_distance);
1035                                                 if(distance < selected_control_point_distance)
1036                                                 {
1037                                                         selected_point = (i < points.total - 1 ? i + 1 : 0);
1038                                                         selected_control_point = 0;
1039                                                         selected_control_point_distance = distance;
1040                                                 }
1041                                         }
1042                                         else
1043                                         if(i < points.total - 1)
1044                                         {
1045                                                 output_to_canvas(mwindow->edl, 0, canvas_x, canvas_y);
1046                                                 if(!gui->ctrl_down())
1047                                                 {
1048                                                         if(TEST_BOX(cursor_x, cursor_y, canvas_x, canvas_y))
1049                                                         {
1050                                                                 selected_point = (i < points.total - 1 ? i + 1 : 0);
1051                                                         }
1052                                                 }
1053                                                 else
1054                                                 {
1055                                                         selected_point = shortest_point;
1056                                                 }
1057                                         }
1058                                 }
1062                                 if(j > 0)
1063                                 {
1064 // Draw joining line
1065                                         if(draw)
1066                                         {
1067                                                 x_points.append((int)x);
1068                                                 y_points.append((int)y);
1069                                         }
1071                                         if(j == segments)
1072                                         {
1077                                                 if(draw)
1078                                                 {
1079 // Draw second anchor
1080                                                         if(i < points.total - 1)
1081                                                         {
1082                                                                 if(i == gui->affected_point - 1)
1083                                                                         canvas->draw_disc((int)x - CONTROL_W / 2, 
1084                                                                                 (int)y - CONTROL_W / 2, 
1085                                                                                 CONTROL_W, 
1086                                                                                 CONTROL_W);
1087                                                                 else
1088                                                                         canvas->draw_circle((int)x - CONTROL_W / 2, 
1089                                                                                 (int)y - CONTROL_W / 2, 
1090                                                                                 CONTROL_W, 
1091                                                                                 CONTROL_W);
1092 // char string[BCTEXTLEN];
1093 // sprintf(string, "%d", (i < points.total - 1 ? i + 1 : 0));
1094 // canvas->draw_text((int)x + CONTROL_W, (int)y + CONTROL_W, string);
1095                                                         }
1097 // Draw second control point.  Discard x2 and y2 after this.
1098                                                         x2 = half_track_w + (x2 - half_track_w) * projector_z + projector_x;
1099                                                         y2 = half_track_h + (y2 - half_track_h) * projector_z + projector_y;
1100                                                         output_to_canvas(mwindow->edl, 0, x2, y2);
1101                                                         canvas->draw_line((int)x, (int)y, (int)x2, (int)y2);
1102                                                         canvas->draw_rectangle((int)x2 - CONTROL_W / 2,
1103                                                                 (int)y2 - CONTROL_H / 2,
1104                                                                 CONTROL_W,
1105                                                                 CONTROL_H);
1106                                                 }
1107                                         }
1108                                 }
1109                                 else
1110                                 {
1113 // Draw first anchor
1114                                         if(i == 0 && draw)
1115                                         {
1116                                                 canvas->draw_disc((int)x - FIRST_CONTROL_W / 2, 
1117                                                         (int)y - FIRST_CONTROL_H / 2, 
1118                                                         FIRST_CONTROL_W, 
1119                                                         FIRST_CONTROL_H);
1120                                         }
1122 // Draw first control point.  Discard x1 and y1 after this.
1123                                         if(draw)
1124                                         {
1125                                                 x1 = half_track_w + (x1 - half_track_w) * projector_z + projector_x;
1126                                                 y1 = half_track_h + (y1 - half_track_h) * projector_z + projector_y;
1127                                                 output_to_canvas(mwindow->edl, 0, x1, y1);
1128                                                 canvas->draw_line((int)x, (int)y, (int)x1, (int)y1);
1129                                                 canvas->draw_rectangle((int)x1 - CONTROL_W / 2,
1130                                                         (int)y1 - CONTROL_H / 2,
1131                                                         CONTROL_W,
1132                                                         CONTROL_H);
1133                                         
1134                                                 x_points.append((int)x);
1135                                                 y_points.append((int)y);
1136                                         }
1137                                 }
1138 //printf("CWindowCanvas::do_mask 1\n");
1140                                 old_x = x;
1141                                 old_y = y;
1142                         }
1143                 }
1144 //printf("CWindowCanvas::do_mask 1\n");
1146                 if(draw)
1147                 {
1148                         canvas->draw_polygon(&x_points, &y_points);
1149                         canvas->set_opaque();
1150                 }
1151 //printf("CWindowCanvas::do_mask 1\n");
1152         }
1160         if(button_press && !result)
1161         {
1162 //printf("CWindowCanvas::do_mask 5\n");
1163                 gui->affected_track = gui->cwindow->calculate_affected_track();
1164 // Get current keyframe
1165                 if(gui->affected_track)
1166                         gui->affected_auto = 
1167                                 gui->cwindow->calculate_affected_auto(gui->affected_track->automation->mask_autos);
1169                 MaskAuto *keyframe = (MaskAuto*)gui->affected_auto;
1170                 SubMask *mask = keyframe->get_submask(mwindow->edl->session->cwindow_mask);
1172 //printf("CWindowCanvas::do_mask 6 %d %d\n", gui->alt_down(), mask->points.total);
1174 // Translate entire keyframe
1175                 if(gui->alt_down() && mask->points.total)
1176                 {
1177                         gui->current_operation = CWINDOW_MASK_TRANSLATE;
1178                         gui->affected_point = 0;
1179                 }
1180                 else
1181 // Existing point or control point was selected
1182                 if(selected_point >= 0)
1183                 {
1184                         gui->affected_point = selected_point;
1186                         if(selected_control_point == 0)
1187                                 gui->current_operation = CWINDOW_MASK_CONTROL_IN;
1188                         else
1189                         if(selected_control_point == 1)
1190                                 gui->current_operation = CWINDOW_MASK_CONTROL_OUT;
1191                         else
1192                                 gui->current_operation = mwindow->edl->session->cwindow_operation;
1193                 }
1194                 else
1195 // No existing point or control point was selected so create a new one
1196                 if(!gui->shift_down() && !gui->alt_down())
1197                 {
1198 // Create the template
1199                         MaskPoint *point = new MaskPoint;
1200                         point->x = mask_cursor_x;
1201                         point->y = mask_cursor_y;
1202                         point->control_x1 = 0;
1203                         point->control_y1 = 0;
1204                         point->control_x2 = 0;
1205                         point->control_y2 = 0;
1207                         mwindow->undo->update_undo_before(_("mask point"), LOAD_AUTOMATION);
1209                         if(shortest_point2 < shortest_point1)
1210                         {
1211                                 shortest_point2 ^= shortest_point1;
1212                                 shortest_point1 ^= shortest_point2;
1213                                 shortest_point2 ^= shortest_point1;
1214                         }
1221 //printf("CWindowCanvas::do_mask 1 %f %f %d %d\n", 
1222 //      shortest_line_distance, shortest_point_distance, shortest_point1, shortest_point2);
1223 //printf("CWindowCanvas::do_mask %d %d\n", shortest_point1, shortest_point2);
1225 // Append to end of list
1226                         if(labs(shortest_point1 - shortest_point2) > 1)
1227                         {
1228 // Need to apply the new point to every keyframe
1229                                 for(MaskAuto *current = (MaskAuto*)mask_autos->default_auto;
1230                                         current; )
1231                                 {
1232                                         SubMask *submask = current->get_submask(mwindow->edl->session->cwindow_mask);
1233                                         MaskPoint *new_point = new MaskPoint;
1234                                         submask->points.append(new_point);
1235                                         *new_point = *point;
1236                                         if(current == (MaskAuto*)mask_autos->default_auto)
1237                                                 current = (MaskAuto*)mask_autos->first;
1238                                         else
1239                                                 current = (MaskAuto*)NEXT;
1240                                 }
1242                                 gui->affected_point = mask->points.total - 1;
1243                                 result = 1;
1244                         }
1245                         else
1246 // Insert between 2 points, shifting back point 2
1247                         if(shortest_point1 >= 0 && shortest_point2 >= 0)
1248                         {
1249                                 for(MaskAuto *current = (MaskAuto*)mask_autos->default_auto;
1250                                         current; )
1251                                 {
1252                                         SubMask *submask = current->get_submask(mwindow->edl->session->cwindow_mask);
1253                                         MaskPoint *new_point = new MaskPoint;
1254                                         submask->points.append(0);
1255                                         for(int i = submask->points.total - 1; 
1256                                                 i > shortest_point2; 
1257                                                 i--)
1258                                                 submask->points.values[i] = submask->points.values[i - 1];
1259                                         submask->points.values[shortest_point2] = new_point;
1261                                         *new_point = *point;
1262                                         if(current == (MaskAuto*)mask_autos->default_auto)
1263                                                 current = (MaskAuto*)mask_autos->first;
1264                                         else
1265                                                 current = (MaskAuto*)NEXT;
1266                                 }
1269                                 gui->affected_point = shortest_point2;
1270                                 result = 1;
1271                         }
1272 //printf("CWindowCanvas::do_mask 3 %d\n", mask->points.total);
1279 // Create the first point.
1280                         if(!result)
1281                         {
1282 //printf("CWindowCanvas::do_mask 1\n");
1283                                 for(MaskAuto *current = (MaskAuto*)mask_autos->default_auto;
1284                                         current; )
1285                                 {
1286                                         SubMask *submask = current->get_submask(mwindow->edl->session->cwindow_mask);
1287                                         MaskPoint *new_point = new MaskPoint;
1288                                         submask->points.append(new_point);
1289                                         *new_point = *point;
1290                                         if(current == (MaskAuto*)mask_autos->default_auto)
1291                                                 current = (MaskAuto*)mask_autos->first;
1292                                         else
1293                                                 current = (MaskAuto*)NEXT;
1294                                 }
1296 //printf("CWindowCanvas::do_mask 2\n");
1297 // Create a second point if none existed before
1298                                 if(mask->points.total < 2)
1299                                 {
1300                                         for(MaskAuto *current = (MaskAuto*)mask_autos->default_auto;
1301                                                 current; )
1302                                         {
1303                                                 SubMask *submask = current->get_submask(mwindow->edl->session->cwindow_mask);
1304                                                 MaskPoint *new_point = new MaskPoint;
1305                                                 submask->points.append(new_point);
1306                                                 *new_point = *point;
1307                                                 if(current == (MaskAuto*)mask_autos->default_auto)
1308                                                         current = (MaskAuto*)mask_autos->first;
1309                                                 else
1310                                                         current = (MaskAuto*)NEXT;
1311                                         }
1312                                 }
1313                                 gui->affected_point = mask->points.total - 1;
1314 //printf("CWindowCanvas::do_mask 3 %d\n", mask->points.total);
1315                         }
1319 //printf("CWindowCanvas::do_mask 2 %d %d %f %f\n", get_cursor_x(), get_cursor_y(), gui->affected_point->x, gui->affected_point->y);
1320                         gui->current_operation = mwindow->edl->session->cwindow_operation;
1321 // Delete the template
1322                         delete point;
1323                         mwindow->undo->update_undo_after();
1324 //printf("CWindowCanvas::do_mask 4\n");
1325                 }
1327                 result = 1;
1328                 redraw = 1;
1329         }
1330 //printf("CWindowCanvas::do_mask 7\n");
1332         if(button_press && result)
1333         {
1334                 MaskAuto *keyframe = (MaskAuto*)gui->affected_auto;
1335                 SubMask *mask = keyframe->get_submask(mwindow->edl->session->cwindow_mask);
1336                 MaskPoint *point = mask->points.values[gui->affected_point];
1337                 gui->center_x = point->x;
1338                 gui->center_y = point->y;
1339                 gui->control_in_x = point->control_x1;
1340                 gui->control_in_y = point->control_y1;
1341                 gui->control_out_x = point->control_x2;
1342                 gui->control_out_y = point->control_y2;
1343 // printf("CWindowCanvas::do_mask 1 %p %p %d\n", 
1344 //      gui->affected_auto, 
1345 //      gui->affected_point,
1346 //      gui->current_operation);
1347         }
1349 //printf("CWindowCanvas::do_mask 8\n");
1350         if(cursor_motion)
1351         {
1352                 MaskAuto *keyframe = (MaskAuto*)gui->affected_auto;
1353                 SubMask *mask = keyframe->get_submask(mwindow->edl->session->cwindow_mask);
1354                 if(gui->affected_point < mask->points.total)
1355                 {
1356                         MaskPoint *point = mask->points.values[gui->affected_point];
1357 //                      float cursor_x = get_cursor_x();
1358 //                      float cursor_y = get_cursor_y();
1359 //                      canvas_to_output(mwindow->edl, 0, cursor_x, cursor_y);
1360                         float cursor_x = mask_cursor_x;
1361                         float cursor_y = mask_cursor_y;
1362 //printf("CWindowCanvas::do_mask 9 %d %d\n", mask->points.total, gui->affected_point);
1364                         float last_x = point->x;
1365                         float last_y = point->y;
1366                         float last_control_x1 = point->control_x1;
1367                         float last_control_y1 = point->control_y1;
1368                         float last_control_x2 = point->control_x2;
1369                         float last_control_y2 = point->control_y2;
1372                         switch(gui->current_operation)
1373                         {
1374                                 case CWINDOW_MASK:
1375                                         point->x = cursor_x - gui->x_origin + gui->center_x;
1376                                         point->y = cursor_y - gui->y_origin + gui->center_y;
1377                                         break;
1379                                 case CWINDOW_MASK_CONTROL_IN:
1380                                         point->control_x1 = cursor_x - gui->x_origin + gui->control_in_x;
1381                                         point->control_y1 = cursor_y - gui->y_origin + gui->control_in_y;
1382                                         break;
1384                                 case CWINDOW_MASK_CONTROL_OUT:
1385                                         point->control_x2 = cursor_x - gui->x_origin + gui->control_out_x;
1386                                         point->control_y2 = cursor_y - gui->y_origin + gui->control_out_y;
1387                                         break;
1389                                 case CWINDOW_MASK_TRANSLATE:
1390                                         for(int i = 0; i < mask->points.total; i++)
1391                                         {
1392                                                 mask->points.values[i]->x += cursor_x - gui->x_origin;
1393                                                 mask->points.values[i]->y += cursor_y - gui->y_origin;
1394                                         }
1395                                         gui->x_origin = cursor_x;
1396                                         gui->y_origin = cursor_y;
1397                                         break;
1398                         }
1401                         if( !EQUIV(last_x, point->x) ||
1402                                 !EQUIV(last_y, point->y) ||
1403                                 !EQUIV(last_control_x1, point->control_x1) ||
1404                                 !EQUIV(last_control_y1, point->control_y1) ||
1405                                 !EQUIV(last_control_x2, point->control_x2) ||
1406                                 !EQUIV(last_control_y2, point->control_y2))
1407                         {
1408                                 mwindow->undo->update_undo_before(_("tweek"), LOAD_AUTOMATION);
1409                                 rerender = 1;
1410                                 redraw = 1;
1411                         }
1412                 }
1413                 result = 1;
1414         }
1415 //printf("CWindowCanvas::do_mask 2 %d %d %d\n", result, rerender, redraw);
1417         points.remove_all_objects();
1418 //printf("CWindowCanvas::do_mask 20\n");
1419         return result;
1422 void CWindowCanvas::draw_overlays()
1424 //printf("CWindowCanvas::draw_overlays 1\n");
1425         if(mwindow->edl->session->safe_regions)
1426         {
1427                 draw_safe_regions();
1428         }
1430         if(mwindow->edl->session->cwindow_scrollbars)
1431         {
1432 // Always draw output rectangle
1433                 float x1, y1, x2, y2;
1434                 x1 = 0;
1435                 x2 = mwindow->edl->session->output_w;
1436                 y1 = 0;
1437                 y2 = mwindow->edl->session->output_h;
1438                 output_to_canvas(mwindow->edl, 0, x1, y1);
1439                 output_to_canvas(mwindow->edl, 0, x2, y2);
1441                 canvas->set_inverse();
1442                 canvas->set_color(WHITE);
1444                 canvas->draw_rectangle((int)x1, 
1445                                 (int)y1, 
1446                                 (int)(x2 - x1), 
1447                                 (int)(y2 - y1));
1449                 canvas->set_opaque();
1450         }
1452         if(mwindow->session->ccanvas_highlighted)
1453         {
1454                 canvas->set_color(WHITE);
1455                 canvas->set_inverse();
1456                 canvas->draw_rectangle(0, 0, canvas->get_w(), canvas->get_h());
1457                 canvas->draw_rectangle(1, 1, canvas->get_w() - 2, canvas->get_h() - 2);
1458                 canvas->set_opaque();
1459         }
1461         int temp1 = 0, temp2 = 0;
1462 //printf("CWindowCanvas::draw_overlays 1 %d\n", mwindow->edl->session->cwindow_operation);
1463         switch(mwindow->edl->session->cwindow_operation)
1464         {
1465                 case CWINDOW_CAMERA:
1466                         draw_bezier(1);
1467                         break;
1469                 case CWINDOW_PROJECTOR:
1470                         draw_bezier(0);
1471                         break;
1473                 case CWINDOW_CROP:
1474                         draw_crop();
1475                         break;
1477                 case CWINDOW_MASK:
1478                         do_mask(temp1, temp2, 0, 0, 1);
1479                         break;
1480         }
1481 //printf("CWindowCanvas::draw_overlays 2\n");
1484 void CWindowCanvas::draw_safe_regions()
1486         float action_x1, action_x2, action_y1, action_y2;
1487         float title_x1, title_x2, title_y1, title_y2;
1489         action_x1 = mwindow->edl->session->output_w / 2 - mwindow->edl->session->output_w / 2 * 0.9;
1490         action_x2 = mwindow->edl->session->output_w / 2 + mwindow->edl->session->output_w / 2 * 0.9;
1491         action_y1 = mwindow->edl->session->output_h / 2 - mwindow->edl->session->output_h / 2 * 0.9;
1492         action_y2 = mwindow->edl->session->output_h / 2 + mwindow->edl->session->output_h / 2 * 0.9;
1493         title_x1 = mwindow->edl->session->output_w / 2 - mwindow->edl->session->output_w / 2 * 0.8;
1494         title_x2 = mwindow->edl->session->output_w / 2 + mwindow->edl->session->output_w / 2 * 0.8;
1495         title_y1 = mwindow->edl->session->output_h / 2 - mwindow->edl->session->output_h / 2 * 0.8;
1496         title_y2 = mwindow->edl->session->output_h / 2 + mwindow->edl->session->output_h / 2 * 0.8;
1498         output_to_canvas(mwindow->edl, 0, action_x1, action_y1);
1499         output_to_canvas(mwindow->edl, 0, action_x2, action_y2);
1500         output_to_canvas(mwindow->edl, 0, title_x1, title_y1);
1501         output_to_canvas(mwindow->edl, 0, title_x2, title_y2);
1503         canvas->set_inverse();
1504         canvas->set_color(WHITE);
1506         canvas->draw_rectangle((int)action_x1, 
1507                         (int)action_y1, 
1508                         (int)(action_x2 - action_x1), 
1509                         (int)(action_y2 - action_y1));
1510         canvas->draw_rectangle((int)title_x1, 
1511                         (int)title_y1, 
1512                         (int)(title_x2 - title_x1), 
1513                         (int)(title_y2 - title_y1));
1515         canvas->set_opaque();
1518 void CWindowCanvas::reset_keyframe(int do_camera)
1520         BezierAuto *translate_keyframe = 0;
1521         FloatAuto *zoom_keyframe = 0;
1522         Track *affected_track = 0;
1524         affected_track = gui->cwindow->calculate_affected_track();
1526         if(affected_track)
1527         {
1528                 if(do_camera)
1529                 {
1530                         translate_keyframe = (BezierAuto*)gui->cwindow->calculate_affected_auto(
1531                                 affected_track->automation->camera_autos);
1532                         zoom_keyframe = (FloatAuto*)gui->cwindow->calculate_affected_auto(
1533                                 affected_track->automation->czoom_autos);
1534                 }
1535                 else
1536                 {
1537                         translate_keyframe = (BezierAuto*)gui->cwindow->calculate_affected_auto(
1538                                 affected_track->automation->projector_autos);
1539                         zoom_keyframe = (FloatAuto*)gui->cwindow->calculate_affected_auto(
1540                                 affected_track->automation->pzoom_autos);
1541                 }
1543                 translate_keyframe->center_x = 0;
1544                 translate_keyframe->center_y = 0;
1545                 translate_keyframe->center_z = 1;
1546                 zoom_keyframe->value = 1;
1548                 mwindow->sync_parameters(CHANGE_PARAMS);
1549                 gui->update_tool();
1550 //              gui->cwindow->playback_engine->que->send_command(CURRENT_FRAME, 
1551 //                      CHANGE_NONE,
1552 //                      mwindow->edl,
1553 //                      1);
1554         }
1557 void CWindowCanvas::reset_camera()
1559         reset_keyframe(1);
1562 void CWindowCanvas::reset_projector()
1564         reset_keyframe(0);
1567 int CWindowCanvas::test_crop(int button_press, int &redraw)
1569         int result = 0;
1570         int handle_selected = -1;
1571         float x1 = mwindow->edl->session->crop_x1;
1572         float y1 = mwindow->edl->session->crop_y1;
1573         float x2 = mwindow->edl->session->crop_x2;
1574         float y2 = mwindow->edl->session->crop_y2;
1575         float cursor_x = get_cursor_x();
1576         float cursor_y = get_cursor_y();
1577         float canvas_x1 = x1;
1578         float canvas_y1 = y1;
1579         float canvas_x2 = x2;
1580         float canvas_y2 = y2;
1581         float canvas_cursor_x = cursor_x;
1582         float canvas_cursor_y = cursor_y;
1584         canvas_to_output(mwindow->edl, 0, cursor_x, cursor_y);
1585 // Use screen normalized coordinates for hot spot tests.
1586         output_to_canvas(mwindow->edl, 0, canvas_x1, canvas_y1);
1587         output_to_canvas(mwindow->edl, 0, canvas_x2, canvas_y2);
1589         if(gui->current_operation == CWINDOW_CROP)
1590         {
1591                 handle_selected = gui->crop_handle;
1592         }
1593         else
1594         if(canvas_cursor_x >= canvas_x1 && canvas_cursor_x < canvas_x1 + CROPHANDLE_W &&
1595                 canvas_cursor_y >= canvas_y1 && canvas_cursor_y < canvas_y1 + CROPHANDLE_H)
1596         {
1597                 handle_selected = 0;
1598                 gui->crop_origin_x = x1;
1599                 gui->crop_origin_y = y1;
1600         }
1601         else
1602         if(canvas_cursor_x >= canvas_x2 - CROPHANDLE_W && canvas_cursor_x < canvas_x2 &&
1603                 canvas_cursor_y >= canvas_y1 && canvas_cursor_y < canvas_y1 + CROPHANDLE_H)
1604         {
1605                 handle_selected = 1;
1606                 gui->crop_origin_x = x2;
1607                 gui->crop_origin_y = y1;
1608         }
1609         else
1610         if(canvas_cursor_x >= canvas_x1 && canvas_cursor_x < canvas_x1 + CROPHANDLE_W &&
1611                 canvas_cursor_y >= canvas_y2 - CROPHANDLE_H && canvas_cursor_y < canvas_y2)
1612         {
1613                 handle_selected = 2;
1614                 gui->crop_origin_x = x1;
1615                 gui->crop_origin_y = y2;
1616         }
1617         else
1618         if(canvas_cursor_x >= canvas_x2 - CROPHANDLE_W && canvas_cursor_x < canvas_x2 &&
1619                 canvas_cursor_y >= canvas_y2 - CROPHANDLE_H && canvas_cursor_y < canvas_y2)
1620         {
1621                 handle_selected = 3;
1622                 gui->crop_origin_x = x2;
1623                 gui->crop_origin_y = y2;
1624         }
1625         else
1626 // Start new box
1627         {
1628                 gui->crop_origin_x = cursor_x;
1629                 gui->crop_origin_y = cursor_y;
1630         }
1632 // printf("test crop %d %d\n", 
1633 //      gui->current_operation,
1634 //      handle_selected);
1636 // Start dragging.
1637         if(button_press)
1638         {
1639                 gui->current_operation = CWINDOW_CROP;
1640                 gui->crop_handle = handle_selected;
1641                 gui->x_origin = cursor_x;
1642                 gui->y_origin = cursor_y;
1643                 result = 1;
1645                 if(handle_selected < 0) 
1646                 {
1647                         x2 = x1 = cursor_x;
1648                         y2 = y1 = cursor_y;
1649                         mwindow->edl->session->crop_x1 = (int)x1;
1650                         mwindow->edl->session->crop_y1 = (int)y1;
1651                         mwindow->edl->session->crop_x2 = (int)x2;
1652                         mwindow->edl->session->crop_y2 = (int)y2;
1653                         redraw = 1;
1654                 }
1655         }
1656     else
1657 // Update dragging
1658         if(gui->current_operation == CWINDOW_CROP)
1659         {
1660                 float x_difference, y_difference;
1661                 if(gui->crop_handle >= 0)
1662                 {
1663                         float zoom_x, zoom_y, conformed_w, conformed_h;
1664                         get_zooms(mwindow->edl, 0, zoom_x, zoom_y, conformed_w, conformed_h);
1665                         x_difference = cursor_x - gui->x_origin;
1666                 }
1668                 switch(gui->crop_handle)
1669                 {
1670                         case -1:
1671                                 x1 = gui->crop_origin_x;
1672                                 y1 = gui->crop_origin_y;
1673                                 x2 = gui->crop_origin_x;
1674                                 y2 = gui->crop_origin_y;
1675                                 if(cursor_x < gui->x_origin)
1676                                 {
1677                                         if(cursor_y < gui->y_origin)
1678                                         {
1679                                                 x1 = cursor_x;
1680                                                 y1 = cursor_y;
1681                                         }
1682                                         else
1683                                         if(cursor_y >= gui->y_origin)
1684                                         {
1685                                                 x1 = cursor_x;
1686                                                 y2 = cursor_y;
1687                                         }
1688                                 }
1689                                 else
1690                                 if(cursor_x  >= gui->x_origin)
1691                                 {
1692                                         if(cursor_y < gui->y_origin)
1693                                         {
1694                                                 y1 = cursor_y;
1695                                                 x2 = cursor_x;
1696                                         }
1697                                         else
1698                                         if(cursor_y >= gui->y_origin)
1699                                         {
1700                                                 x2 = cursor_x;
1701                                                 y2 = cursor_y;
1702                                         }
1703                                 }
1705 // printf("test crop %d %d %d %d\n", 
1706 //      mwindow->edl->session->crop_x1,
1707 //      mwindow->edl->session->crop_y1,
1708 //      mwindow->edl->session->crop_x2,
1709 //      mwindow->edl->session->crop_y2);
1710                                 break;
1711                         case 0:
1712                                 x1 = cursor_x - gui->x_origin + gui->crop_origin_x;
1713                                 y1 = cursor_y - gui->y_origin + gui->crop_origin_y;
1714                                 break;
1715                         case 1:
1716                                 x2 = cursor_x - gui->x_origin + gui->crop_origin_x;
1717                                 y1 = cursor_y - gui->y_origin + gui->crop_origin_y;
1718                                 break;
1719                         case 2:
1720                                 x1 = cursor_x - gui->x_origin + gui->crop_origin_x;
1721                                 y2 = cursor_y - gui->y_origin + gui->crop_origin_y;
1722                                 break;
1723                         case 3:
1724                                 x2 = cursor_x - gui->x_origin + gui->crop_origin_x;
1725                                 y2 = cursor_y - gui->y_origin + gui->crop_origin_y;
1726                                 break;
1727                 }
1729                 if(!EQUIV(mwindow->edl->session->crop_x1, x1) ||
1730                         !EQUIV(mwindow->edl->session->crop_x2, x2) ||
1731                         !EQUIV(mwindow->edl->session->crop_y1, y1) ||
1732                         !EQUIV(mwindow->edl->session->crop_y2, y2))
1733                 {
1734                         mwindow->edl->session->crop_x1 = (int)x1;
1735                         mwindow->edl->session->crop_y1 = (int)y1;
1736                         mwindow->edl->session->crop_x2 = (int)x2;
1737                         mwindow->edl->session->crop_y2 = (int)y2;
1738                         result = 1;
1739                         redraw = 1;
1740                 }
1741         }
1742         else
1743 // Update cursor font
1744         if(handle_selected >= 0)
1745         {
1746                 switch(handle_selected)
1747                 {
1748                         case 0:
1749                                 set_cursor(UPLEFT_RESIZE);
1750                                 break;
1751                         case 1:
1752                                 set_cursor(UPRIGHT_RESIZE);
1753                                 break;
1754                         case 2:
1755                                 set_cursor(DOWNLEFT_RESIZE);
1756                                 break;
1757                         case 3:
1758                                 set_cursor(DOWNRIGHT_RESIZE);
1759                                 break;
1760                 }
1761                 result = 1;
1762         }
1763         else
1764         {
1765                 set_cursor(ARROW_CURSOR);
1766         }
1767 #define CLAMP(x, y, z) ((x) = ((x) < (y) ? (y) : ((x) > (z) ? (z) : (x))))
1768         
1769         if(redraw)
1770         {
1771                 CLAMP(mwindow->edl->session->crop_x1, 0, mwindow->edl->calculate_output_w(0));
1772                 CLAMP(mwindow->edl->session->crop_x2, 0, mwindow->edl->calculate_output_w(0));
1773                 CLAMP(mwindow->edl->session->crop_y1, 0, mwindow->edl->calculate_output_h(0));
1774                 CLAMP(mwindow->edl->session->crop_y2, 0, mwindow->edl->calculate_output_h(0));
1775 // printf("CWindowCanvas::test_crop %d %d %d %d\n", 
1776 //      mwindow->edl->session->crop_x2,
1777 //      mwindow->edl->session->crop_y2,
1778 //      mwindow->edl->calculate_output_w(0), 
1779 //      mwindow->edl->calculate_output_h(0));
1780         }
1781         return result;
1785 void CWindowCanvas::draw_crop()
1787         canvas->set_inverse();
1788         canvas->set_color(WHITE);
1790         float x1 = mwindow->edl->session->crop_x1;
1791         float y1 = mwindow->edl->session->crop_y1;
1792         float x2 = mwindow->edl->session->crop_x2;
1793         float y2 = mwindow->edl->session->crop_y2;
1795         output_to_canvas(mwindow->edl, 0, x1, y1);
1796         output_to_canvas(mwindow->edl, 0, x2, y2);
1798         if(x2 - x1 && y2 - y1)
1799                 canvas->draw_rectangle((int)x1, 
1800                         (int)y1, 
1801                         (int)(x2 - x1), 
1802                         (int)(y2 - y1));
1804         draw_crophandle((int)x1, (int)y1);
1805         draw_crophandle((int)x2 - CROPHANDLE_W, (int)y1);
1806         draw_crophandle((int)x1, (int)y2 - CROPHANDLE_H);
1807         draw_crophandle((int)x2 - CROPHANDLE_W, (int)y2 - CROPHANDLE_H);
1808         canvas->set_opaque();
1813 #define BEZIER_W 20
1814 #define BEZIER_H 20
1816 int CWindowCanvas::do_bezier_center(BezierAuto *current, 
1817         BezierAutos *camera_autos,
1818         BezierAutos *projector_autos, 
1819         FloatAutos *czoom_autos,
1820         FloatAutos *pzoom_autos,
1821         int camera, 
1822         int draw)
1824         float center_x = 0, center_y = 0, center_z = 0;
1825         BezierAuto *before = 0, *after = 0;
1826         FloatAuto *previous = 0, *next = 0;
1827         VTrack *track = (VTrack*)current->autos->track;
1828         long position = track->to_units(
1829                                 mwindow->edl->local_session->selectionstart, 
1830                                 0);
1832 // Get center of current frame.  Draw everything relative to this.
1833         if(camera)
1834         {
1835                 camera_autos->get_center(center_x, 
1836                         center_y, 
1837                         center_z, 
1838                         (float)position,
1839                         PLAY_FORWARD, 
1840                         &before, 
1841                         &after);
1842                 center_z = czoom_autos->get_value(position,
1843                         PLAY_FORWARD,
1844                         previous,
1845                         next);
1847                 float projector_x, projector_y, projector_z;
1848                 before = after = 0;
1849                 projector_autos->get_center(projector_x, 
1850                         projector_y, 
1851                         projector_z,
1852                         (float)position,
1853                         PLAY_FORWARD,
1854                         &before,
1855                         &after);
1856                 previous = next = 0;
1857                 projector_z = pzoom_autos->get_value(position,
1858                         PLAY_FORWARD,
1859                         previous,
1860                         next);
1862                 center_x -= projector_x;
1863                 center_y -= projector_y;
1864                 center_z = projector_z;
1865 //printf("CWindowCanvas::do_bezier_center 1 %p %f %f\n", 
1866 //current, projector_y, center_y);
1867         }
1868         else
1869         {
1870                 center_z = pzoom_autos->get_value(current->position,
1871                         PLAY_FORWARD,
1872                         previous,
1873                         next);
1874         }
1878         float auto_x = current->center_x - center_x + mwindow->edl->session->output_w / 2;
1879         float auto_y = current->center_y - center_y + mwindow->edl->session->output_h / 2;
1880         float track_x1 = auto_x - track->track_w / 2 * center_z;
1881         float track_y1 = auto_y - track->track_h / 2 * center_z;
1882         float track_x2 = track_x1 + track->track_w * center_z;
1883         float track_y2 = track_y1 + track->track_h * center_z;
1884         float control_in_x = auto_x + current->control_in_x;
1885         float control_in_y = auto_y + current->control_in_y;
1886         float control_out_x = auto_x + current->control_out_x;
1887         float control_out_y = auto_y + current->control_out_y;
1888         int control_point = 0;
1891         output_to_canvas(mwindow->edl, 0, auto_x, auto_y);
1892         output_to_canvas(mwindow->edl, 0, control_out_x, control_out_y);
1893         output_to_canvas(mwindow->edl, 0, control_in_x, control_in_y);
1894         output_to_canvas(mwindow->edl, 0, track_x1, track_y1);
1895         output_to_canvas(mwindow->edl, 0, track_x2, track_y2);
1897 #define DRAW_THING(offset) \
1898         canvas->draw_line((int)control_in_x + offset,  \
1899                 (int)control_in_y + offset,  \
1900                 (int)auto_x + offset,  \
1901                 (int)auto_y + offset); \
1902         canvas->draw_line((int)control_out_x + offset,  \
1903                 (int)control_out_y + offset,  \
1904                 (int)auto_x + offset,  \
1905                 (int)auto_y + offset); \
1906         canvas->draw_rectangle((int)control_in_x - CONTROL_W / 2 + offset,  \
1907                 (int)control_in_y - CONTROL_H / 2 + offset, \
1908                 CONTROL_W, \
1909                 CONTROL_H); \
1910         canvas->draw_rectangle((int)control_out_x - CONTROL_W / 2 + offset,  \
1911                 (int)control_out_y - CONTROL_H / 2 + offset, \
1912                 CONTROL_W, \
1913                 CONTROL_H); \
1915         if(0) \
1916         { \
1917                 canvas->draw_line((int)auto_x - BEZIER_W / 2,  \
1918                         (int)auto_y - BEZIER_H / 2 + offset, \
1919                         (int)auto_x + BEZIER_W / 2, \
1920                         (int)auto_y + BEZIER_H / 2 + offset); \
1921                 canvas->draw_line((int)auto_x - BEZIER_W / 2,  \
1922                         (int)auto_y + BEZIER_H / 2 + offset, \
1923                         (int)auto_x + BEZIER_W / 2, \
1924                         (int)auto_y - BEZIER_H / 2 + offset); \
1925         } \
1926         else \
1927         { \
1928                 canvas->draw_rectangle((int)track_x1 + offset, \
1929                         (int)track_y1 + offset, \
1930                         (int)(track_x2 - track_x1), \
1931                         (int)(track_y2 - track_y1)); \
1932                 canvas->draw_line((int)track_x1 + offset,  \
1933                         (int)track_y1 + offset, \
1934                         (int)track_x2 + offset, \
1935                         (int)track_y2 + offset); \
1936                 canvas->draw_line((int)track_x2 + offset,  \
1937                         (int)track_y1 + offset, \
1938                         (int)track_x1 + offset, \
1939                         (int)track_y2 + offset); \
1940         }
1942         if(draw)
1943         {
1944                 canvas->set_color(BLACK);
1945                 DRAW_THING(1);
1947                 if(current->position > position)
1948                         canvas->set_color(GREEN);
1949                 else
1950                         canvas->set_color(RED);
1952                 DRAW_THING(0);
1953 // printf("CWindowCanvas::do_bezier_center 2 %f,%f %f,%f\n", 
1954 // control_in_x, 
1955 // control_in_y, 
1956 // control_out_x,
1957 // control_out_y);
1958         }
1959         else
1960         {
1961                 int cursor_x = get_cursor_x();
1962                 int cursor_y = get_cursor_y();
1963                 
1964 #ifndef SQR
1965 #define SQR(x) ((x) * (x))
1966 #endif
1968                 float distance1 = sqrt(SQR(cursor_x - control_in_x) + 
1969                         SQR(cursor_y - control_in_y));
1970                 float distance2 = sqrt(SQR(cursor_x - control_out_x) + 
1971                         SQR(cursor_y - control_out_y));
1972 // printf("CWindowCanvas::do_bezier_center 3 %f,%f %f,%f\n", 
1973 // control_in_x, 
1974 // control_in_y, 
1975 // control_out_x,
1976 // control_out_y);
1978                 control_point = distance2 < distance1;
1979         }
1980         
1981         return control_point;
1986 void CWindowCanvas::draw_bezier_joining(BezierAuto *first, 
1987         BezierAuto *last, 
1988         BezierAutos *camera_autos,
1989         BezierAutos *projector_autos, 
1990         FloatAutos *czoom_autos,
1991         FloatAutos *pzoom_autos,
1992         int camera)
1994         if(first == last) return;
1995         
1996         float center_x = 0, center_y = 0, center_z = 0;
1997         BezierAuto *before = 0, *after = 0;
1998         long position = first->autos->track->to_units(
1999                                         mwindow->edl->local_session->selectionstart, 
2000                                         0);
2002 // Get center of current position.  Draw everything relative to this.
2003         if(camera)
2004         {
2005                 camera_autos->get_center(center_x, 
2006                                 center_y, 
2007                                 center_z, 
2008                                 (float)position, 
2009                                 PLAY_FORWARD, 
2010                                 &before, 
2011                                 &after);
2013                 float projector_x, projector_y, projector_z;
2014                 before = after = 0;
2015                 projector_autos->get_center(projector_x, 
2016                         projector_y, 
2017                         projector_z,
2018                         (float)position,
2019                         PLAY_FORWARD,
2020                         &before,
2021                         &after);
2023                 center_x -= projector_x;
2024                 center_y -= projector_y;
2025         }
2027 //      int segments = 10;
2028         int segments = MAX(canvas->get_w(), canvas->get_h());
2029         int step = (last->position - first->position) / segments;
2030         float old_x, old_y;
2031         if(step < 1) step = 1;
2033         for(long frame = first->position; 
2034                 frame < last->position; 
2035                 frame += step)
2036         {
2037                 float new_x, new_y, new_z;
2038                 float x1, y1, x2, y2;
2040                 ((BezierAutos*)(first->autos))->get_center(new_x, 
2041                         new_y, 
2042                         new_z, 
2043                         frame, 
2044                         PLAY_FORWARD, 
2045                         &before, 
2046                         &after);
2048                 if(frame == first->position)
2049                 {
2050                         old_x = new_x;
2051                         old_y = new_y;
2052                 }
2054                 x1 = old_x - center_x + mwindow->edl->session->output_w / 2;
2055                 y1 = old_y - center_y + mwindow->edl->session->output_h / 2;
2056                 x2 = new_x - center_x + mwindow->edl->session->output_w / 2;
2057                 y2 = new_y - center_y + mwindow->edl->session->output_h / 2;
2058                 output_to_canvas(mwindow->edl, 0, x1, y1);
2059                 output_to_canvas(mwindow->edl, 0, x2, y2);
2061                 canvas->set_color(BLACK);
2062                 canvas->draw_line((int)x1 + 1, (int)y1 + 1, (int)x2 + 1, (int)y2 + 1);
2064                 if(frame >= position)
2065                         canvas->set_color(GREEN);
2066                 else
2067                         canvas->set_color(RED);
2069                 canvas->draw_line((int)x1, (int)y1, (int)x2, (int)y2);
2070                 old_x = new_x;
2071                 old_y = new_y;
2072         }
2077 void CWindowCanvas::draw_bezier(int do_camera)
2079         Track *track = gui->cwindow->calculate_affected_track();
2080         BezierAutos *autos, *camera_autos, *projector_autos;
2081         BezierAuto *first = 0, *mid = 0, *last = 0;
2082         BezierAuto *before = 0, *after = 0;
2083         FloatAutos *czoom_autos, *pzoom_autos;
2085 // No track at initialization
2086         if(!track) return;
2088         camera_autos = track->automation->camera_autos;
2089         projector_autos = track->automation->projector_autos;
2090         czoom_autos = track->automation->czoom_autos;
2091         pzoom_autos = track->automation->pzoom_autos;
2093         if(do_camera)
2094                 autos = track->automation->camera_autos;
2095         else
2096                 autos = track->automation->projector_autos;
2099         long position = track->to_units(mwindow->edl->local_session->selectionstart, 
2100                                         0);
2103 // Rules for which autos to draw:
2105 // No automation besides default:
2106 //     mid = default
2108 // Automation on or after current position only
2109 //     mid = first, last = next
2111 // Automation before current position only
2112 //     mid = last, first = previous
2113 // 
2114 // Automation on current position only
2115 //     mid = first
2117 // Automation before and after current position
2118 //     first = previous, mid = next, last = next->next
2120         for(first = (BezierAuto*)autos->last; 
2121                 first; 
2122                 first = (BezierAuto*)first->previous)
2123                 if(first->position < position)
2124                         break;
2126         if(first)
2127         {
2128                 mid = (BezierAuto*)first->next;
2129                 if(!mid)
2130                 {
2131                         mid = first;
2132                         first = (BezierAuto*)first->previous;
2133                 }
2134         }
2135         else
2136                 mid = (BezierAuto*)autos->first;
2138         if(mid)
2139                 last = (BezierAuto*)mid->next;
2140         else
2141                 mid = (BezierAuto*)autos->default_auto;
2143         if(!last)
2144         {
2145                 last = mid;
2146                 mid = first;
2147                 if(mid) first = (BezierAuto*)mid->previous;
2148         }
2149         
2150         if(!first)
2151         {
2152                 first = mid;
2153                 mid = last;
2154                 if(mid) last = (BezierAuto*)mid->next;
2155         }
2157 //printf("draw_bezier 1 %p %p %p\n", first, mid, last);
2161 // Draw joining lines
2162         if(first && mid)
2163                 draw_bezier_joining(first, 
2164                         mid, 
2165                         camera_autos, 
2166                         projector_autos, 
2167                         czoom_autos,
2168                         pzoom_autos,
2169                         do_camera);
2171         if(mid && last)
2172                 draw_bezier_joining(mid, 
2173                         last, 
2174                         camera_autos, 
2175                         projector_autos, 
2176                         czoom_autos,
2177                         pzoom_autos,
2178                         do_camera);
2180 //printf("draw_bezier 2 %p %p %p\n", first, mid, last);
2183 // Draw centers of autos
2184         if(first) 
2185                 do_bezier_center(first, 
2186                         camera_autos, 
2187                         projector_autos, 
2188                         czoom_autos,
2189                         pzoom_autos,
2190                         do_camera, 
2191                         1);
2192         if(mid) 
2193                 do_bezier_center(mid, 
2194                         camera_autos, 
2195                         projector_autos, 
2196                         czoom_autos,
2197                         pzoom_autos,
2198                         do_camera, 
2199                         1);
2200         if(last) 
2201                 do_bezier_center(last, 
2202                         camera_autos, 
2203                         projector_autos, 
2204                         czoom_autos,
2205                         pzoom_autos,
2206                         do_camera, 
2207                         1);
2209 //printf("draw_bezier 3 %p %p %p\n", first, mid, last);
2217 int CWindowCanvas::test_bezier(int button_press, 
2218         int &redraw, 
2219         int &redraw_canvas,
2220         int &rerender,
2221         int do_camera)
2223         int result = 0;
2225 // Processing drag operation.
2226 // Create keyframe during first cursor motion.
2227         if(!button_press)
2228         {
2230                 float cursor_x = get_cursor_x();
2231                 float cursor_y = get_cursor_y();
2232                 canvas_to_output(mwindow->edl, 0, cursor_x, cursor_y);
2234                 if(gui->current_operation == CWINDOW_CAMERA ||
2235                         gui->current_operation == CWINDOW_PROJECTOR)
2236                 {
2237                         if(!gui->ctrl_down() && gui->shift_down() && !gui->translating_zoom)
2238                         {
2239                                 gui->translating_zoom = 1;
2240                                 gui->affected_auto = 0;
2241                         }
2242                         else
2243                         if(!gui->ctrl_down() && !gui->shift_down() && gui->translating_zoom)
2244                         {
2245                                 gui->translating_zoom = 0;
2246                                 gui->affected_auto = 0;
2247                         }
2249 // Get target keyframe
2250                         BezierAutos *camera_autos = gui->affected_track->automation->camera_autos;
2251                         BezierAutos *projector_autos = gui->affected_track->automation->projector_autos;
2252                         FloatAutos *czoom_autos = gui->affected_track->automation->czoom_autos;
2253                         FloatAutos *pzoom_autos = gui->affected_track->automation->pzoom_autos;
2254                         float last_center_x;
2255                         float last_center_y;
2256                         float last_center_z;
2259                         if(!gui->affected_auto)
2260                         {
2261                                 mwindow->undo->update_undo_before(_("keyframe"), LOAD_AUTOMATION);
2262                                 if(mwindow->edl->session->cwindow_operation == CWINDOW_CAMERA)
2263                                 {
2264                                         if(gui->translating_zoom)
2265                                         {
2266                                                 gui->affected_auto = 
2267                                                         gui->cwindow->calculate_affected_auto((Autos*)czoom_autos, 1);
2268                                         }
2269                                         else
2270                                                 gui->affected_auto = 
2271                                                         gui->cwindow->calculate_affected_auto((Autos*)camera_autos, 1);
2272                                 }
2273                                 else
2274                                 if(mwindow->edl->session->cwindow_operation == CWINDOW_PROJECTOR)
2275                                 {
2276                                         if(gui->translating_zoom)
2277                                         {
2278                                                 gui->affected_auto = 
2279                                                         gui->cwindow->calculate_affected_auto((Autos*)pzoom_autos, 1);
2280                                         }
2281                                         else
2282                                                 gui->affected_auto = 
2283                                                         gui->cwindow->calculate_affected_auto((Autos*)projector_autos, 1);
2284                                 }
2286                                 calculate_origin();
2287                                 
2288                                 if(gui->translating_zoom)
2289                                 {
2290                                         gui->center_z = ((FloatAuto*)gui->affected_auto)->value;
2291                                 }
2292                                 else
2293                                 {
2294                                         gui->center_x = ((BezierAuto*)gui->affected_auto)->center_x;
2295                                         gui->center_y = ((BezierAuto*)gui->affected_auto)->center_y;
2296                                 }
2298                                 rerender = 1;
2299                                 redraw = 1;
2300                         }
2302                         BezierAuto *bezier_keyframe = (BezierAuto*)gui->affected_auto;
2303                         FloatAuto *zoom_keyframe = (FloatAuto*)gui->affected_auto;
2305                         if(gui->translating_zoom)
2306                         {
2307                                 last_center_z = zoom_keyframe->value;
2308                         }
2309                         else
2310                         {
2311                                 last_center_x = bezier_keyframe->center_x;
2312                                 last_center_y = bezier_keyframe->center_y;
2313                         }
2315                         if(gui->translating_zoom)
2316                         {
2317                                 zoom_keyframe->value = gui->center_z + (cursor_y - gui->y_origin) / 128;
2318                                 if(!EQUIV(last_center_z, zoom_keyframe->value))
2319                                 {
2320                                         mwindow->undo->update_undo_before(_("tweek"), LOAD_AUTOMATION);
2321                                         rerender = 1;
2322                                         redraw = 1;
2323                                         redraw_canvas = 1;
2324                                 }
2325                         }
2326                         else
2327                         {
2328                                 bezier_keyframe->center_x = gui->center_x + cursor_x - gui->x_origin;
2329                                 bezier_keyframe->center_y = gui->center_y + cursor_y - gui->y_origin;
2330                                 if(!EQUIV(last_center_x,  bezier_keyframe->center_x) ||
2331                                         !EQUIV(last_center_y, bezier_keyframe->center_y))
2332                                 {
2333                                         mwindow->undo->update_undo_before(_("tweek"), LOAD_AUTOMATION);
2334                                         rerender = 1;
2335                                         redraw = 1;
2336                                 }
2337                         }
2338                 }
2339                 else
2340                 if(gui->current_operation == CWINDOW_CAMERA_CONTROL_IN ||
2341                         gui->current_operation == CWINDOW_PROJECTOR_CONTROL_IN)
2342                 {
2343                         BezierAuto *bezier_keyframe = (BezierAuto*)gui->affected_auto;
2344                         float last_control_in_x = bezier_keyframe->control_in_x;
2345                         float last_control_in_y = bezier_keyframe->control_in_y;
2346                         bezier_keyframe->control_in_x = gui->control_in_x + cursor_x - gui->x_origin;
2347                         bezier_keyframe->control_in_y = gui->control_in_y + cursor_y - gui->y_origin;
2349                         if(!EQUIV(last_control_in_x, bezier_keyframe->control_in_x) ||
2350                                 !EQUIV(last_control_in_y, bezier_keyframe->control_in_y))
2351                         {
2352                                 mwindow->undo->update_undo_before(_("tweek"), LOAD_AUTOMATION);
2353                                 rerender = 1;
2354                                 redraw = 1;
2355                         }
2356                 }
2357                 else
2358                 if(gui->current_operation == CWINDOW_CAMERA_CONTROL_OUT ||
2359                         gui->current_operation == CWINDOW_PROJECTOR_CONTROL_OUT)
2360                 {
2361                         BezierAuto *bezier_keyframe = (BezierAuto*)gui->affected_auto;
2362                         float last_control_out_x = bezier_keyframe->control_out_x;
2363                         float last_control_out_y = bezier_keyframe->control_out_y;
2364                         bezier_keyframe->control_out_x = gui->control_out_x + cursor_x - gui->x_origin;
2365                         bezier_keyframe->control_out_y = gui->control_out_y + cursor_y - gui->y_origin;
2367                         if(!EQUIV(last_control_out_x, bezier_keyframe->control_out_x) ||
2368                                 !EQUIV(last_control_out_y, bezier_keyframe->control_out_y))
2369                         {
2370                                 mwindow->undo->update_undo_before(_("tweek"), LOAD_AUTOMATION);
2371                                 rerender = 1;
2372                                 redraw = 1;
2373                         }
2374                 }
2376                 result = 1;
2377         }
2378         else
2379 // Begin drag operation.  Don't create keyframe here.
2380         {
2381 // Get affected track off of the first recordable video track.
2382 // Calculating based on the alpha channel would require rendering
2383 // each layer and its effects and trapping the result in VirtualVNode before
2384 // compositing onto the output.
2385                 gui->affected_track = gui->cwindow->calculate_affected_track();
2386                 gui->affected_auto = 0;
2388                 if(gui->affected_track)
2389                 {
2390                         BezierAutos *camera_autos = gui->affected_track->automation->camera_autos;
2391                         BezierAutos *projector_autos = gui->affected_track->automation->projector_autos;
2392                         FloatAutos *czoom_autos = gui->affected_track->automation->czoom_autos;
2393                         FloatAutos *pzoom_autos = gui->affected_track->automation->pzoom_autos;
2396                         if(!gui->ctrl_down())
2397                         {
2398                                 gui->current_operation = 
2399                                         mwindow->edl->session->cwindow_operation;
2400                                 gui->affected_auto = 0;
2401                         }
2402                         else
2403                         {
2404 // Get nearest control point
2405                                 if(mwindow->edl->session->cwindow_operation == CWINDOW_CAMERA)
2406                                         gui->affected_auto = 
2407                                                 gui->cwindow->calculate_affected_auto(camera_autos, 0);
2408                                 else
2409                                 if(mwindow->edl->session->cwindow_operation == CWINDOW_PROJECTOR)
2410                                         gui->affected_auto = 
2411                                                 gui->cwindow->calculate_affected_auto(projector_autos, 0);
2413 //printf("CWindowCanvas::test_bezier 1 %d\n", gui->current_operation);
2414                                 int control_point = do_bezier_center(
2415                                         (BezierAuto*)gui->affected_auto, 
2416                                         camera_autos,
2417                                         projector_autos,
2418                                         czoom_autos,
2419                                         pzoom_autos,
2420                                         mwindow->edl->session->cwindow_operation == CWINDOW_CAMERA,
2421                                         0);
2423 //printf("CWindowCanvas::test_bezier 2 %d\n", control_point);
2424                                 if(control_point == 0)
2425                                 {
2426                                         if(mwindow->edl->session->cwindow_operation == CWINDOW_CAMERA)
2427                                                 gui->current_operation = CWINDOW_CAMERA_CONTROL_IN;
2428                                         else
2429                                                 gui->current_operation = CWINDOW_PROJECTOR_CONTROL_IN;
2430                                 }
2431                                 else
2432                                 {
2433                                         if(mwindow->edl->session->cwindow_operation == CWINDOW_CAMERA)
2434                                                 gui->current_operation = CWINDOW_CAMERA_CONTROL_OUT;
2435                                         else
2436                                                 gui->current_operation = CWINDOW_PROJECTOR_CONTROL_OUT;
2437                                 }
2439                                 BezierAuto *keyframe = (BezierAuto*)gui->affected_auto;
2440                                 gui->center_x = keyframe->center_x;
2441                                 gui->center_y = keyframe->center_y;
2442                                 gui->center_z = keyframe->center_z;
2443                                 gui->control_in_x = keyframe->control_in_x;
2444                                 gui->control_in_y = keyframe->control_in_y;
2445                                 gui->control_out_x = keyframe->control_out_x;
2446                                 gui->control_out_y = keyframe->control_out_y;
2447                         }
2450                         result = 1;
2451                 }
2452         }
2453         
2454         return result;
2457 int CWindowCanvas::test_zoom(int &redraw)
2459         int result = 0;
2460         float zoom = get_zoom();
2461         float x;
2462         float y;
2464         if(!mwindow->edl->session->cwindow_scrollbars)
2465         {
2466                 mwindow->edl->session->cwindow_scrollbars = 1;
2467                 zoom = 1.0;
2468                 x = 0;
2469                 y = 0;
2470         }
2471         else
2472         {
2473                 x = get_cursor_x();
2474                 y = get_cursor_y();
2475                 canvas_to_output(mwindow->edl, 
2476                                 0, 
2477                                 x, 
2478                                 y);
2480 //printf("CWindowCanvas::test_zoom 1 %f %f\n", x, y);
2482 // Zoom out
2483                 if(get_buttonpress() == 5 ||
2484                         gui->ctrl_down() || 
2485                         gui->shift_down())
2486                 {
2487                         if(zoom > MIN_ZOOM)
2488                         {
2489                                 zoom /= 2;
2490                                 x -= w_visible * 2 / 2;
2491                                 y -= h_visible * 2 / 2;
2492                         }
2493                         else
2494                         {
2495                                 x -= w_visible / 2;
2496                                 y -= h_visible / 2;
2497                         }
2498                 }
2499                 else
2500 // Zoom in
2501                 {
2502                         if(zoom < MAX_ZOOM)
2503                         {
2504                                 zoom *= 2;
2505                                 x -= w_visible / 2 / 2;
2506                                 y -= h_visible / 2 / 2;
2507                         }
2508                         else
2509                         {
2510                                 x -= w_visible / 2;
2511                                 y -= h_visible / 2;
2512                         }
2513                 }
2514         }
2516         int x_i = (int)x;
2517         int y_i = (int)y;
2518 //      check_boundaries(mwindow->edl, x_i, y_i, zoom);
2520 //printf("CWindowCanvas::test_zoom 2 %d %d\n", x_i, y_i);
2522         update_zoom(x_i, 
2523                         y_i, 
2524                         zoom);
2525         reposition_window(mwindow->edl, 
2526                         mwindow->theme->ccanvas_x,
2527                         mwindow->theme->ccanvas_y,
2528                         mwindow->theme->ccanvas_w,
2529                         mwindow->theme->ccanvas_h);
2530         redraw = 1;
2531         result = 1;
2533         
2534         gui->zoom_panel->update(zoom);
2535         
2536         return result;
2540 void CWindowCanvas::calculate_origin()
2542         gui->x_origin = get_cursor_x();
2543         gui->y_origin = get_cursor_y();
2544 //printf("CWindowCanvas::calculate_origin 1 %f %f\n", gui->x_origin, gui->y_origin);
2545         canvas_to_output(mwindow->edl, 0, gui->x_origin, gui->y_origin);
2546 //printf("CWindowCanvas::calculate_origin 2 %f %f\n", gui->x_origin, gui->y_origin);
2550 int CWindowCanvas::cursor_leave_event()
2552         set_cursor(ARROW_CURSOR);
2553         return 1;
2556 int CWindowCanvas::cursor_enter_event()
2558         int redraw = 0;
2559         switch(mwindow->edl->session->cwindow_operation)
2560         {
2561                 case CWINDOW_CAMERA:
2562                 case CWINDOW_PROJECTOR:
2563                         set_cursor(MOVE_CURSOR);
2564                         break;
2565                 case CWINDOW_ZOOM:
2566                         set_cursor(MOVE_CURSOR);
2567                         break;
2568                 case CWINDOW_CROP:
2569                         test_crop(0, redraw);
2570                         break;
2571                 case CWINDOW_PROTECT:
2572                         set_cursor(ARROW_CURSOR);
2573                         break;
2574                 case CWINDOW_MASK:
2575                         set_cursor(CROSS_CURSOR);
2576                         break;
2577         }
2578         return 1;
2581 int CWindowCanvas::cursor_motion_event()
2583         int redraw = 0, result = 0, rerender = 0, redraw_canvas = 0;
2586         switch(gui->current_operation)
2587         {
2588                 case CWINDOW_SCROLL:
2589                 {
2590                         float zoom = get_zoom();
2591                         float cursor_x = get_cursor_x();
2592                         float cursor_y = get_cursor_y();
2594                         float zoom_x, zoom_y, conformed_w, conformed_h;
2595                         get_zooms(mwindow->edl, 0, zoom_x, zoom_y, conformed_w, conformed_h);
2596                         cursor_x = (float)cursor_x / zoom_x + gui->x_offset;
2597                         cursor_y = (float)cursor_y / zoom_y + gui->y_offset;
2601                         int x = (int)(gui->x_origin - cursor_x + gui->x_offset);
2602                         int y = (int)(gui->y_origin - cursor_y + gui->y_offset);
2605                         update_zoom(x, 
2606                                 y, 
2607                                 zoom);
2608                         update_scrollbars();
2609                         redraw = 1;
2610                         result = 1;
2611                         break;
2612                 }
2614                 case CWINDOW_CAMERA:
2615                 case CWINDOW_CAMERA_CONTROL_IN:
2616                 case CWINDOW_CAMERA_CONTROL_OUT:
2617                         result = test_bezier(0, redraw, redraw_canvas, rerender, 1);
2618                         break;
2620                 case CWINDOW_PROJECTOR:
2621                 case CWINDOW_PROJECTOR_CONTROL_IN:
2622                 case CWINDOW_PROJECTOR_CONTROL_OUT:
2623                         result = test_bezier(0, redraw, redraw_canvas, rerender, 0);
2624                         break;
2627                 case CWINDOW_CROP:
2628 //printf("CWindowCanvas::cursor_motion_event 1 %d %d\n", x, y);
2629                         result = test_crop(0, redraw);
2630                         break;
2632                 case CWINDOW_MASK:
2633                 case CWINDOW_MASK_CONTROL_IN:
2634                 case CWINDOW_MASK_CONTROL_OUT:
2635                 case CWINDOW_MASK_TRANSLATE:
2636                         result = do_mask(redraw, 
2637                                 rerender, 
2638                                 0, 
2639                                 1,
2640                                 0);
2641                         break;
2642         }
2646         if(!result)
2647         {
2648                 switch(mwindow->edl->session->cwindow_operation)
2649                 {
2650                         case CWINDOW_CROP:
2651                                 result = test_crop(0, redraw);
2652                                 break;
2653                 }
2654         }
2657 // If the window is never unlocked before calling send_command the
2658 // display shouldn't get stuck on the old video frame although it will
2659 // flicker between the old video frame and the new video frame.
2661         if(redraw)
2662         {
2663                 draw_refresh();
2664                 gui->update_tool();
2665         }
2667         if(redraw_canvas)
2668         {
2669                 mwindow->gui->lock_window();
2670                 mwindow->gui->canvas->draw_overlays();
2671                 mwindow->gui->canvas->flash();
2672                 mwindow->gui->unlock_window();
2673         }
2675         if(rerender)
2676         {
2677                 mwindow->restart_brender();
2678                 mwindow->sync_parameters(CHANGE_PARAMS);
2679                 gui->cwindow->playback_engine->que->send_command(CURRENT_FRAME, 
2680                         CHANGE_NONE,
2681                         mwindow->edl,
2682                         1);
2683                 if(!redraw) gui->update_tool();
2684         }
2685         return result;
2688 int CWindowCanvas::button_press_event()
2690         int result = 0;
2691         int redraw = 0;
2692         int redraw_canvas = 0;
2693         int rerender = 0;
2695         if(Canvas::button_press_event()) return 1;
2697         gui->translating_zoom = gui->shift_down(); 
2699         calculate_origin();
2700 //printf("CWindowCanvas::button_press_event 2 %f %f\n", gui->x_origin, gui->y_origin, gui->x_origin, gui->y_origin);
2702         float zoom_x, zoom_y, conformed_w, conformed_h;
2703         get_zooms(mwindow->edl, 0, zoom_x, zoom_y, conformed_w, conformed_h);
2704         gui->x_offset = get_x_offset(mwindow->edl, 0, zoom_x, conformed_w, conformed_h);
2705         gui->y_offset = get_y_offset(mwindow->edl, 0, zoom_y, conformed_w, conformed_h);
2707 // Scroll view
2708         if(get_buttonpress() == 2)
2709         {
2710                 gui->current_operation = CWINDOW_SCROLL;
2711                 result = 1;
2712         }
2713         else
2714 // Adjust parameter
2715         {
2716                 switch(mwindow->edl->session->cwindow_operation)
2717                 {
2718                         case CWINDOW_CAMERA:
2719                                 result = test_bezier(1, redraw, redraw_canvas, rerender, 1);
2720                                 break;
2722                         case CWINDOW_PROJECTOR:
2723                                 result = test_bezier(1, redraw, redraw_canvas, rerender, 0);
2724                                 break;
2726                         case CWINDOW_ZOOM:
2727                                 result = test_zoom(redraw);
2728                                 break;
2730                         case CWINDOW_CROP:
2731                                 result = test_crop(1, redraw);
2732                                 break;
2734                         case CWINDOW_MASK:
2735                                 if(get_buttonpress() == 1)
2736                                         result = do_mask(redraw, rerender, 1, 0, 0);
2737                                 break;
2738                 }
2739         }
2741         if(redraw)
2742         {
2743                 draw_refresh();
2744                 gui->update_tool();
2745         }
2746         return result;
2749 int CWindowCanvas::button_release_event()
2751         int result = 0;
2753         switch(gui->current_operation)
2754         {
2755                 case CWINDOW_SCROLL:
2756                         result = 1;
2757                         break;
2758         }
2760         gui->current_operation = CWINDOW_NONE;
2761         mwindow->undo->update_undo_after();
2762 //printf("CWindowCanvas::button_release_event %d\n", result);
2763         return result;
2766 void CWindowCanvas::zoom_resize_window(float percentage)
2768         int canvas_w, canvas_h;
2769         calculate_sizes(mwindow->edl->get_aspect_ratio(), 
2770                 mwindow->edl->calculate_output_w(0), 
2771                 mwindow->edl->calculate_output_h(0), 
2772                 percentage,
2773                 canvas_w,
2774                 canvas_h);
2775         int new_w, new_h;
2776         new_w = canvas_w + (gui->get_w() - mwindow->theme->ccanvas_w);
2777         new_h = canvas_h + (gui->get_h() - mwindow->theme->ccanvas_h);
2778         gui->resize_window(new_w, new_h);
2779         gui->resize_event(new_w, new_h);