Main Page | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Class Members | File Members

cwindowgui.C

Go to the documentation of this file.
00001 #include "automation.h"
00002 #include "autos.h"
00003 #include "bcsignals.h"
00004 #include "canvas.h"
00005 #include "clip.h"
00006 #include "cpanel.h"
00007 #include "cplayback.h"
00008 #include "ctimebar.h"
00009 #include "cursors.h"
00010 #include "cwindowgui.h"
00011 #include "cwindow.h"
00012 #include "cwindowtool.h"
00013 #include "editpanel.h"
00014 #include "edl.h"
00015 #include "edlsession.h"
00016 #include "floatauto.h"
00017 #include "floatautos.h"
00018 #include "language.h"
00019 #include "localsession.h"
00020 #include "mainclock.h"
00021 #include "mainmenu.h"
00022 #include "mainundo.h"
00023 #include "mainsession.h"
00024 #include "maskauto.h"
00025 #include "maskautos.h"
00026 #include "meterpanel.h"
00027 #include "mwindowgui.h"
00028 #include "mwindow.h"
00029 #include "mwindow.h"
00030 #include "playtransport.h"
00031 #include "theme.h"
00032 #include "trackcanvas.h"
00033 #include "tracks.h"
00034 #include "transportque.h"
00035 #include "vtrack.h"
00036 
00037 
00038 static double my_zoom_table[] = 
00039 {
00040         0.25,
00041         0.33,
00042         0.50,
00043         0.75,
00044         1.0,
00045         1.5,
00046         2.0,
00047         3.0,
00048         4.0
00049 };
00050 
00051 static int total_zooms = sizeof(my_zoom_table) / sizeof(double);
00052 
00053 
00054 CWindowGUI::CWindowGUI(MWindow *mwindow, CWindow *cwindow)
00055  : BC_Window(PROGRAM_NAME ": Compositor",
00056         mwindow->session->cwindow_x, 
00057     mwindow->session->cwindow_y, 
00058     mwindow->session->cwindow_w, 
00059     mwindow->session->cwindow_h,
00060     100,
00061     100,
00062     1,
00063     1,
00064     1,
00065         BC_WindowBase::get_resources()->bg_color,
00066         mwindow->edl->session->get_cwindow_display())
00067 {
00068         this->mwindow = mwindow;
00069     this->cwindow = cwindow;
00070         affected_track = 0;
00071         affected_x = 0;
00072         affected_y = 0;
00073         affected_z = 0;
00074         affected_keyframe = 0;
00075         affected_point = 0;
00076         x_offset = 0;
00077         y_offset = 0;
00078         x_origin = 0;
00079         y_origin = 0;
00080         current_operation = CWINDOW_NONE;
00081         tool_panel = 0;
00082         translating_zoom = 0;
00083         active = 0;
00084         inactive = 0;
00085         crop_translate = 0;
00086 }
00087 
00088 CWindowGUI::~CWindowGUI()
00089 {
00090         if(tool_panel) delete tool_panel;
00091         delete meters;
00092         delete composite_panel;
00093         delete canvas;
00094         delete transport;
00095         delete edit_panel;
00096         delete zoom_panel;
00097         delete active;
00098         delete inactive;
00099 }
00100 
00101 int CWindowGUI::create_objects()
00102 {
00103 SET_TRACE
00104         set_icon(mwindow->theme->get_image("cwindow_icon"));
00105 
00106         active = new BC_Pixmap(this, mwindow->theme->get_image("cwindow_active"));
00107         inactive = new BC_Pixmap(this, mwindow->theme->get_image("cwindow_inactive"));
00108 
00109 SET_TRACE
00110         mwindow->theme->get_cwindow_sizes(this, mwindow->session->cwindow_controls);
00111 SET_TRACE
00112         mwindow->theme->draw_cwindow_bg(this);
00113 SET_TRACE
00114         flash();
00115 SET_TRACE
00116 
00117 // Meters required by composite panel
00118         meters = new CWindowMeters(mwindow, 
00119                 this,
00120                 mwindow->theme->cmeter_x,
00121                 mwindow->theme->cmeter_y,
00122                 mwindow->theme->cmeter_h);
00123         meters->create_objects();
00124 SET_TRACE
00125 
00126 
00127         composite_panel = new CPanel(mwindow, 
00128                 this, 
00129                 mwindow->theme->ccomposite_x,
00130                 mwindow->theme->ccomposite_y,
00131                 mwindow->theme->ccomposite_w,
00132                 mwindow->theme->ccomposite_h);
00133         composite_panel->create_objects();
00134 
00135 SET_TRACE
00136         canvas = new CWindowCanvas(mwindow, this);
00137         canvas->create_objects(mwindow->edl);
00138 SET_TRACE
00139 
00140 
00141         add_subwindow(timebar = new CTimeBar(mwindow,
00142                 this,
00143                 mwindow->theme->ctimebar_x,
00144                 mwindow->theme->ctimebar_y,
00145                 mwindow->theme->ctimebar_w, 
00146                 mwindow->theme->ctimebar_h));
00147         timebar->create_objects();
00148 
00149 SET_TRACE
00150         add_subwindow(slider = new CWindowSlider(mwindow, 
00151                 cwindow, 
00152                 mwindow->theme->cslider_x,
00153                 mwindow->theme->cslider_y, 
00154                 mwindow->theme->cslider_w));
00155 
00156         transport = new CWindowTransport(mwindow, 
00157                 this, 
00158                 mwindow->theme->ctransport_x, 
00159                 mwindow->theme->ctransport_y);
00160         transport->create_objects();
00161         transport->set_slider(slider);
00162 
00163 SET_TRACE
00164         edit_panel = new CWindowEditing(mwindow, cwindow);
00165 SET_TRACE
00166         edit_panel->set_meters(meters);
00167 SET_TRACE
00168         edit_panel->create_objects();
00169 SET_TRACE
00170 
00171 //      add_subwindow(clock = new MainClock(mwindow, 
00172 //              mwindow->theme->ctime_x, 
00173 //              mwindow->theme->ctime_y));
00174 
00175         zoom_panel = new CWindowZoom(mwindow, 
00176                 this, 
00177                 mwindow->theme->czoom_x, 
00178                 mwindow->theme->czoom_y);
00179         zoom_panel->create_objects();
00180         zoom_panel->zoom_text->add_item(new BC_MenuItem(AUTO_ZOOM));
00181         if(!mwindow->edl->session->cwindow_scrollbars) zoom_panel->set_text(AUTO_ZOOM);
00182 
00183 //      destination = new CWindowDestination(mwindow, 
00184 //              this, 
00185 //              mwindow->theme->cdest_x,
00186 //              mwindow->theme->cdest_y);
00187 //      destination->create_objects();
00188 
00189 // Must create after meter panel
00190         tool_panel = new CWindowTool(mwindow, this);
00191         tool_panel->Thread::start();
00192         
00193         set_operation(mwindow->edl->session->cwindow_operation);
00194 
00195 
00196         canvas->draw_refresh();
00197 
00198         draw_status();
00199 
00200 SET_TRACE
00201         return 0;
00202 }
00203 
00204 int CWindowGUI::translation_event()
00205 {
00206         mwindow->session->cwindow_x = get_x();
00207         mwindow->session->cwindow_y = get_y();
00208         return 0;
00209 }
00210 
00211 int CWindowGUI::resize_event(int w, int h)
00212 {
00213         mwindow->session->cwindow_x = get_x();
00214         mwindow->session->cwindow_y = get_y();
00215         mwindow->session->cwindow_w = w;
00216         mwindow->session->cwindow_h = h;
00217 
00218         mwindow->theme->get_cwindow_sizes(this, mwindow->session->cwindow_controls);
00219         mwindow->theme->draw_cwindow_bg(this);
00220         flash();
00221 
00222         composite_panel->reposition_buttons(mwindow->theme->ccomposite_x,
00223                 mwindow->theme->ccomposite_y);
00224 
00225         canvas->reposition_window(mwindow->edl,
00226                 mwindow->theme->ccanvas_x,
00227                 mwindow->theme->ccanvas_y,
00228                 mwindow->theme->ccanvas_w,
00229                 mwindow->theme->ccanvas_h);
00230 
00231         timebar->resize_event();
00232 
00233         slider->reposition_window(mwindow->theme->cslider_x,
00234                 mwindow->theme->cslider_y, 
00235                 mwindow->theme->cslider_w);
00236 // Recalibrate pointer motion range
00237         slider->set_position();
00238 
00239         transport->reposition_buttons(mwindow->theme->ctransport_x, 
00240                 mwindow->theme->ctransport_y);
00241 
00242         edit_panel->reposition_buttons(mwindow->theme->cedit_x, 
00243                 mwindow->theme->cedit_y);
00244 
00245 //      clock->reposition_window(mwindow->theme->ctime_x, 
00246 //              mwindow->theme->ctime_y);
00247 
00248         zoom_panel->reposition_window(mwindow->theme->czoom_x, 
00249                 mwindow->theme->czoom_y);
00250 
00251 //      destination->reposition_window(mwindow->theme->cdest_x,
00252 //              mwindow->theme->cdest_y);
00253 
00254         meters->reposition_window(mwindow->theme->cmeter_x,
00255                 mwindow->theme->cmeter_y,
00256                 mwindow->theme->cmeter_h);
00257 
00258         draw_status();
00259 
00260         BC_WindowBase::resize_event(w, h);
00261         return 1;
00262 }
00263 
00264 
00265 void CWindowGUI::draw_status()
00266 {
00267         if(canvas->canvas && 
00268                 canvas->canvas->get_video_on() ||
00269                 canvas->is_processing)
00270                 draw_pixmap(active, 
00271                         mwindow->theme->cstatus_x, 
00272                         mwindow->theme->cstatus_y);
00273         else
00274                 draw_pixmap(inactive, 
00275                         mwindow->theme->cstatus_x, 
00276                         mwindow->theme->cstatus_y);
00277         flash(mwindow->theme->cstatus_x,
00278                 mwindow->theme->cstatus_y,
00279                 active->get_w(),
00280                 active->get_h());
00281 }
00282 
00283 
00284 
00285 // TODO
00286 // Don't refresh the canvas in a load file operation which is going to
00287 // refresh it anyway.
00288 void CWindowGUI::set_operation(int value)
00289 {
00290         mwindow->edl->session->cwindow_operation = value;
00291 
00292         composite_panel->set_operation(value);
00293         edit_panel->update();
00294 
00295         tool_panel->start_tool(value);
00296         canvas->draw_refresh();
00297 }
00298 
00299 void CWindowGUI::update_tool()
00300 {
00301         tool_panel->update_values();
00302 }
00303 
00304 int CWindowGUI::close_event()
00305 {
00306         cwindow->hide_window();
00307         return 1;
00308 }
00309 
00310 
00311 int CWindowGUI::keypress_event()
00312 {
00313         int result = 0;
00314 
00315         switch(get_keypress())
00316         {
00317                 case 'w':
00318                 case 'W':
00319                         close_event();
00320                         result = 1;
00321                         break;
00322                 case '+':
00323                 case '=':
00324                         keyboard_zoomin();
00325                         result = 1;
00326                         break;
00327                 case '-':
00328                         keyboard_zoomout();
00329                         result = 1;
00330                         break;
00331         }
00332 
00333         if(!result) result = transport->keypress_event();
00334 
00335         return result;
00336 }
00337 
00338 
00339 void CWindowGUI::reset_affected()
00340 {
00341         affected_x = 0;
00342         affected_y = 0;
00343         affected_z = 0;
00344 }
00345 
00346 void CWindowGUI::keyboard_zoomin()
00347 {
00348 //      if(mwindow->edl->session->cwindow_scrollbars)
00349 //      {
00350                 zoom_panel->zoom_tumbler->handle_up_event();
00351 //      }
00352 //      else
00353 //      {
00354 //      }
00355 }
00356 
00357 void CWindowGUI::keyboard_zoomout()
00358 {
00359 //      if(mwindow->edl->session->cwindow_scrollbars)
00360 //      {
00361                 zoom_panel->zoom_tumbler->handle_down_event();
00362 //      }
00363 //      else
00364 //      {
00365 //      }
00366 }
00367 
00368 
00369 void CWindowGUI::drag_motion()
00370 {
00371         if(get_hidden()) return;
00372 
00373         if(mwindow->session->current_operation == DRAG_ASSET ||
00374                 mwindow->session->current_operation == DRAG_VTRANSITION ||
00375                 mwindow->session->current_operation == DRAG_VEFFECT)
00376         {
00377                 int old_status = mwindow->session->ccanvas_highlighted;
00378                 int cursor_x = get_relative_cursor_x();
00379                 int cursor_y = get_relative_cursor_y();
00380 
00381                 mwindow->session->ccanvas_highlighted = get_cursor_over_window() &&
00382                         cursor_x >= canvas->x &&
00383                         cursor_x < canvas->x + canvas->w &&
00384                         cursor_y >= canvas->y &&
00385                         cursor_y < canvas->y + canvas->h;
00386 
00387 
00388                 if(old_status != mwindow->session->ccanvas_highlighted)
00389                         canvas->draw_refresh();
00390         }
00391 }
00392 
00393 int CWindowGUI::drag_stop()
00394 {
00395         int result = 0;
00396         if(get_hidden()) return 0;
00397 
00398         if((mwindow->session->current_operation == DRAG_ASSET ||
00399                 mwindow->session->current_operation == DRAG_VTRANSITION ||
00400                 mwindow->session->current_operation == DRAG_VEFFECT) &&
00401                 mwindow->session->ccanvas_highlighted)
00402         {
00403 // Hide highlighting
00404                 mwindow->session->ccanvas_highlighted = 0;
00405                 canvas->draw_refresh();
00406                 result = 1;
00407         }
00408         else
00409                 return 0;
00410 
00411         if(mwindow->session->current_operation == DRAG_ASSET)
00412         {
00413                 if(mwindow->session->drag_assets->total)
00414                 {
00415                         mwindow->gui->lock_window("CWindowGUI::drag_stop 1");
00416                         mwindow->clear(0);
00417                         mwindow->load_assets(mwindow->session->drag_assets, 
00418                                 mwindow->edl->local_session->get_selectionstart(), 
00419                                 LOAD_PASTE,
00420                                 mwindow->session->track_highlighted,
00421                                 0,
00422                                 mwindow->edl->session->labels_follow_edits, 
00423                                 mwindow->edl->session->plugins_follow_edits);
00424                 }
00425 
00426                 if(mwindow->session->drag_clips->total)
00427                 {
00428                         mwindow->gui->lock_window("CWindowGUI::drag_stop 2");
00429                         mwindow->clear(0);
00430                         mwindow->paste_edls(mwindow->session->drag_clips, 
00431                                 LOAD_PASTE, 
00432                                 mwindow->session->track_highlighted,
00433                                 mwindow->edl->local_session->get_selectionstart(),
00434                                 mwindow->edl->session->labels_follow_edits, 
00435                                 mwindow->edl->session->plugins_follow_edits);
00436                 }
00437 
00438                 if(mwindow->session->drag_assets->total ||
00439                         mwindow->session->drag_clips->total)
00440                 {
00441                         mwindow->save_backup();
00442                         mwindow->restart_brender();
00443                         mwindow->gui->update(1, 1, 1, 1, 0, 1, 0);
00444                         mwindow->undo->update_undo(_("insert assets"), LOAD_ALL);
00445                         mwindow->gui->unlock_window();
00446                         mwindow->sync_parameters(LOAD_ALL);
00447                 }
00448         }
00449 
00450         if(mwindow->session->current_operation == DRAG_VEFFECT)
00451         {
00452 //printf("CWindowGUI::drag_stop 1\n");
00453                 Track *affected_track = cwindow->calculate_affected_track();
00454 //printf("CWindowGUI::drag_stop 2\n");
00455 
00456                 mwindow->gui->lock_window("CWindowGUI::drag_stop 3");
00457                 mwindow->insert_effects_cwindow(affected_track);
00458                 mwindow->session->current_operation = NO_OPERATION;
00459                 mwindow->gui->unlock_window();
00460         }
00461 
00462         if(mwindow->session->current_operation == DRAG_VTRANSITION)
00463         {
00464                 Track *affected_track = cwindow->calculate_affected_track();
00465                 mwindow->gui->lock_window("CWindowGUI::drag_stop 4");
00466                 mwindow->paste_transition_cwindow(affected_track);
00467                 mwindow->session->current_operation = NO_OPERATION;
00468                 mwindow->gui->unlock_window();
00469         }
00470 
00471         return result;
00472 }
00473 
00474 
00475 CWindowEditing::CWindowEditing(MWindow *mwindow, CWindow *cwindow)
00476  : EditPanel(mwindow, 
00477                 cwindow->gui, 
00478                 mwindow->theme->cedit_x, 
00479                 mwindow->theme->cedit_y,
00480                 mwindow->edl->session->editing_mode, 
00481                 0,
00482                 1,
00483                 0, 
00484                 0,
00485                 1,
00486                 1,
00487                 1,
00488                 1,
00489                 1,
00490                 0,
00491                 1,
00492                 1,
00493                 1,
00494                 0,
00495                 1)
00496 {
00497         this->mwindow = mwindow;
00498         this->cwindow = cwindow;
00499 }
00500 
00501 void CWindowEditing::set_inpoint()
00502 {
00503         mwindow->set_inpoint(0);
00504 }
00505 
00506 void CWindowEditing::set_outpoint()
00507 {
00508         mwindow->set_outpoint(0);
00509 }
00510 
00511 
00512 
00513 
00514 
00515 CWindowMeters::CWindowMeters(MWindow *mwindow, CWindowGUI *gui, int x, int y, int h)
00516  : MeterPanel(mwindow, 
00517                 gui,
00518                 x,
00519                 y,
00520                 h,
00521                 mwindow->edl->session->audio_channels,
00522                 mwindow->edl->session->cwindow_meter)
00523 {
00524         this->mwindow = mwindow;
00525         this->gui = gui;
00526 }
00527 
00528 CWindowMeters::~CWindowMeters()
00529 {
00530 }
00531 
00532 int CWindowMeters::change_status_event()
00533 {
00534         mwindow->edl->session->cwindow_meter = use_meters;
00535         mwindow->theme->get_cwindow_sizes(gui, mwindow->session->cwindow_controls);
00536         gui->resize_event(gui->get_w(), gui->get_h());
00537         return 1;
00538 }
00539 
00540 
00541 
00542 
00543 CWindowZoom::CWindowZoom(MWindow *mwindow, CWindowGUI *gui, int x, int y)
00544  : ZoomPanel(mwindow, 
00545         gui, 
00546         (double)mwindow->edl->session->cwindow_zoom, 
00547         x, 
00548         y,
00549         80, 
00550         my_zoom_table, 
00551         total_zooms, 
00552         ZOOM_PERCENTAGE)
00553 {
00554         this->mwindow = mwindow;
00555         this->gui = gui;
00556 }
00557 
00558 CWindowZoom::~CWindowZoom()
00559 {
00560 }
00561 
00562 int CWindowZoom::handle_event()
00563 {
00564         if(!strcasecmp(AUTO_ZOOM, get_text()))
00565         {
00566                 mwindow->edl->session->cwindow_scrollbars = 0;
00567         }
00568         else
00569         {
00570                 mwindow->edl->session->cwindow_scrollbars = 1;
00571         }
00572 
00573         float old_zoom = mwindow->edl->session->cwindow_zoom;
00574         float new_zoom = get_value();
00575         float x = gui->canvas->w / 2;
00576         float y = gui->canvas->h / 2;
00577         gui->canvas->canvas_to_output(mwindow->edl, 
00578                                 0, 
00579                                 x, 
00580                                 y);
00581         x -= gui->canvas->w_visible / 2 * old_zoom / new_zoom;
00582         y -= gui->canvas->h_visible / 2 * old_zoom / new_zoom;
00583         gui->canvas->update_zoom((int)x, 
00584                 (int)y, 
00585                 new_zoom);
00586         gui->canvas->reposition_window(mwindow->edl, 
00587                 mwindow->theme->ccanvas_x,
00588                 mwindow->theme->ccanvas_y,
00589                 mwindow->theme->ccanvas_w,
00590                 mwindow->theme->ccanvas_h);
00591         gui->canvas->draw_refresh();
00592         return 1;
00593 }
00594 
00595 
00596 
00597 CWindowSlider::CWindowSlider(MWindow *mwindow, CWindow *cwindow, int x, int y, int pixels)
00598  : BC_PercentageSlider(x, 
00599                         y,
00600                         0,
00601                         pixels, 
00602                         pixels, 
00603                         0, 
00604                         1, 
00605                         0)
00606 {
00607         this->mwindow = mwindow;
00608         this->cwindow = cwindow;
00609         set_precision(0.00001);
00610 }
00611 
00612 CWindowSlider::~CWindowSlider()
00613 {
00614 }
00615 
00616 int CWindowSlider::handle_event()
00617 {
00618         unlock_window();
00619         cwindow->playback_engine->interrupt_playback(1);
00620         lock_window("CWindowSlider::handle_event 1");
00621         
00622         mwindow->gui->lock_window("CWindowSlider::handle_event 2");
00623         mwindow->select_point((double)get_value());
00624         mwindow->gui->unlock_window();
00625         return 1;
00626 }
00627 
00628 void CWindowSlider::set_position()
00629 {
00630         double new_length = mwindow->edl->tracks->total_playable_length();
00631         if(mwindow->edl->local_session->preview_end <= 0 ||
00632                 mwindow->edl->local_session->preview_end > new_length)
00633                 mwindow->edl->local_session->preview_end = new_length;
00634         if(mwindow->edl->local_session->preview_start > 
00635                 mwindow->edl->local_session->preview_end)
00636                 mwindow->edl->local_session->preview_start = 0;
00637 
00638 
00639 
00640         update(mwindow->theme->cslider_w, 
00641                 mwindow->edl->local_session->get_selectionstart(1), 
00642                 mwindow->edl->local_session->preview_start, 
00643                 mwindow->edl->local_session->preview_end);
00644 }
00645 
00646 
00647 int CWindowSlider::increase_value()
00648 {
00649         unlock_window();
00650         cwindow->gui->transport->handle_transport(SINGLE_FRAME_FWD);
00651         lock_window("CWindowSlider::increase_value");
00652         return 1;
00653 }
00654 
00655 int CWindowSlider::decrease_value()
00656 {
00657         unlock_window();
00658         cwindow->gui->transport->handle_transport(SINGLE_FRAME_REWIND);
00659         lock_window("CWindowSlider::decrease_value");
00660         return 1;
00661 }
00662 
00663 
00664 // CWindowDestination::CWindowDestination(MWindow *mwindow, CWindowGUI *cwindow, int x, int y)
00665 //  : BC_PopupTextBox(cwindow, 
00666 //      &cwindow->destinations, 
00667 //      cwindow->destinations.values[cwindow->cwindow->destination]->get_text(),
00668 //      x, 
00669 //      y, 
00670 //      70, 
00671 //      200)
00672 // {
00673 //      this->mwindow = mwindow;
00674 //      this->cwindow = cwindow;
00675 // }
00676 // 
00677 // CWindowDestination::~CWindowDestination()
00678 // {
00679 // }
00680 // 
00681 // int CWindowDestination::handle_event()
00682 // {
00683 //      return 1;
00684 // }
00685 
00686 
00687 CWindowTransport::CWindowTransport(MWindow *mwindow, 
00688         CWindowGUI *gui, 
00689         int x, 
00690         int y)
00691  : PlayTransport(mwindow, 
00692         gui, 
00693         x, 
00694         y)
00695 {
00696         this->gui = gui;
00697 }
00698 
00699 EDL* CWindowTransport::get_edl()
00700 {
00701         return mwindow->edl;
00702 }
00703 
00704 void CWindowTransport::goto_start()
00705 {
00706         gui->unlock_window();
00707         handle_transport(REWIND, 1);
00708 
00709         mwindow->gui->lock_window("CWindowTransport::goto_start 1");
00710         mwindow->goto_start();
00711         mwindow->gui->unlock_window();
00712 
00713         gui->lock_window("CWindowTransport::goto_start 2");
00714 }
00715 
00716 void CWindowTransport::goto_end()
00717 {
00718         gui->unlock_window();
00719         handle_transport(GOTO_END, 1);
00720 
00721         mwindow->gui->lock_window("CWindowTransport::goto_end 1");
00722         mwindow->goto_end();
00723         mwindow->gui->unlock_window();
00724 
00725         gui->lock_window("CWindowTransport::goto_end 2");
00726 }
00727 
00728 
00729 
00730 CWindowCanvas::CWindowCanvas(MWindow *mwindow, CWindowGUI *gui)
00731  : Canvas(gui,
00732                 mwindow->theme->ccanvas_x,
00733                 mwindow->theme->ccanvas_y,
00734                 mwindow->theme->ccanvas_w,
00735                 mwindow->theme->ccanvas_h,
00736                 0,
00737                 0,
00738                 mwindow->edl->session->cwindow_scrollbars,
00739                 1)
00740 {
00741         this->mwindow = mwindow;
00742         this->gui = gui;
00743 }
00744 
00745 void CWindowCanvas::status_event()
00746 {
00747         gui->draw_status();
00748 }
00749 
00750 void CWindowCanvas::update_zoom(int x, int y, float zoom)
00751 {
00752         use_scrollbars = mwindow->edl->session->cwindow_scrollbars;
00753 
00754         mwindow->edl->session->cwindow_xscroll = x;
00755         mwindow->edl->session->cwindow_yscroll = y;
00756         mwindow->edl->session->cwindow_zoom = zoom;
00757 }
00758 
00759 int CWindowCanvas::get_xscroll()
00760 {
00761         return mwindow->edl->session->cwindow_xscroll;
00762 }
00763 
00764 int CWindowCanvas::get_yscroll()
00765 {
00766         return mwindow->edl->session->cwindow_yscroll;
00767 }
00768 
00769 
00770 float CWindowCanvas::get_zoom()
00771 {
00772         return mwindow->edl->session->cwindow_zoom;
00773 }
00774 
00775 void CWindowCanvas::draw_refresh()
00776 {
00777         if(!canvas->video_is_on())
00778         {
00779 //printf("CWindowCanvas::draw_refresh 1 %f\n", mwindow->edl->session->cwindow_zoom);
00780                 canvas->clear_box(0, 0, canvas->get_w(), canvas->get_h());
00781 //printf("CWindowCanvas::draw_refresh 2\n");
00782 
00783                 if(refresh_frame)
00784                 {
00785                         int in_x, in_y, in_w, in_h, out_x, out_y, out_w, out_h;
00786 //printf("CWindowCanvas::draw_refresh 3 %d\n", refresh_frame->get_color_model());
00787                         get_transfers(mwindow->edl, 
00788                                 in_x, 
00789                                 in_y, 
00790                                 in_w, 
00791                                 in_h, 
00792                                 out_x, 
00793                                 out_y, 
00794                                 out_w, 
00795                                 out_h);
00796 
00797 
00798 // printf("CWindowCanvas::draw_refresh %d %d %d %d -> %d %d %d %d\n", 
00799 // in_x, in_y, in_w, in_h, out_x, out_y, out_w, out_h);
00800 //canvas->clear_box(0, 0, canvas->get_w(), canvas->get_h());
00801 
00802 
00803 //printf("CWindowCanvas::draw_refresh 5\n");
00804                         if(out_w > 0 && out_h > 0 && in_w > 0 && in_h > 0)
00805                                 canvas->draw_vframe(refresh_frame,
00806                                                 out_x, 
00807                                                 out_y, 
00808                                                 out_w, 
00809                                                 out_h,
00810                                                 in_x, 
00811                                                 in_y, 
00812                                                 in_w, 
00813                                                 in_h,
00814                                                 0);
00815 //printf("CWindowCanvas::draw_refresh 6\n");
00816                 }
00817                 else
00818                 {
00819 //printf("CWindowCanvas::draw_refresh 7\n");
00820                         canvas->clear_box(0, 0, canvas->get_w(), canvas->get_h());
00821 //printf("CWindowCanvas::draw_refresh 8\n");
00822                 }
00823 
00824 //printf("CWindowCanvas::draw_refresh 9\n");
00825                 draw_overlays();
00826                 canvas->flash();
00827                 canvas->flush();
00828 //printf("CWindowCanvas::draw_refresh 10\n");
00829         }
00830 }
00831 
00832 #define CROPHANDLE_W 10
00833 #define CROPHANDLE_H 10
00834 
00835 void CWindowCanvas::draw_crophandle(int x, int y)
00836 {
00837         canvas->draw_box(x, y, CROPHANDLE_W, CROPHANDLE_H);
00838 }
00839 
00840 #define CONTROL_W 10
00841 #define CONTROL_H 10
00842 #define FIRST_CONTROL_W 20
00843 #define FIRST_CONTROL_H 20
00844 #undef BC_INFINITY
00845 #define BC_INFINITY 65536
00846 #ifndef SQR
00847 #define SQR(x) ((x) * (x))
00848 #endif
00849 
00850 int CWindowCanvas::do_mask(int &redraw, 
00851                 int &rerender, 
00852                 int button_press, 
00853                 int cursor_motion,
00854                 int draw)
00855 {
00856 // Retrieve points from top recordable track
00857 //printf("CWindowCanvas::do_mask 1\n");
00858         Track *track = gui->cwindow->calculate_affected_track();
00859 //printf("CWindowCanvas::do_mask 2\n");
00860 
00861         if(!track) return 0;
00862 //printf("CWindowCanvas::do_mask 3\n");
00863 
00864         MaskAutos *mask_autos = (MaskAutos*)track->automation->autos[AUTOMATION_MASK];
00865         int64_t position = track->to_units(
00866                 mwindow->edl->local_session->get_selectionstart(1),
00867                 0);
00868         ArrayList<MaskPoint*> points;
00869         mask_autos->get_points(&points, mwindow->edl->session->cwindow_mask,
00870                 position, 
00871                 PLAY_FORWARD);
00872 //printf("CWindowCanvas::do_mask 4\n");
00873 
00874 // Projector zooms relative to the center of the track output.
00875         float half_track_w = (float)track->track_w / 2;
00876         float half_track_h = (float)track->track_h / 2;
00877 // Translate mask to projection
00878         float projector_x, projector_y, projector_z;
00879         track->automation->get_projector(&projector_x,
00880                 &projector_y,
00881                 &projector_z,
00882                 position,
00883                 PLAY_FORWARD);
00884 
00885 
00886 // Get position of cursor relative to mask
00887         float mask_cursor_x = get_cursor_x();
00888         float mask_cursor_y = get_cursor_y();
00889         canvas_to_output(mwindow->edl, 0, mask_cursor_x, mask_cursor_y);
00890 
00891         projector_x += mwindow->edl->session->output_w / 2;
00892         projector_y += mwindow->edl->session->output_h / 2;
00893 
00894         mask_cursor_x -= projector_x;
00895         mask_cursor_y -= projector_y;
00896         mask_cursor_x = mask_cursor_x / projector_z + half_track_w;
00897         mask_cursor_y = mask_cursor_y / projector_z + half_track_h;
00898 
00899 // Fix cursor origin
00900         if(button_press)
00901         {
00902                 gui->x_origin = mask_cursor_x;
00903                 gui->y_origin = mask_cursor_y;
00904         }
00905 
00906         int result = 0;
00907 // Points of closest line
00908         int shortest_point1 = -1;
00909         int shortest_point2 = -1;
00910 // Closest point
00911         int shortest_point = -1;
00912 // Distance to closest line
00913         float shortest_line_distance = BC_INFINITY;
00914 // Distance to closest point
00915         float shortest_point_distance = BC_INFINITY;
00916         int selected_point = -1;
00917         int selected_control_point = -1;
00918         float selected_control_point_distance = BC_INFINITY;
00919         ArrayList<int> x_points;
00920         ArrayList<int> y_points;
00921 
00922         if(!cursor_motion)
00923         {
00924                 if(draw)
00925                 {
00926                         canvas->set_color(WHITE);
00927                         canvas->set_inverse();
00928                 }
00929 //printf("CWindowCanvas::do_mask 1 %d\n", points.total);
00930 
00931 // Never draw closed polygon and a closed
00932 // polygon is harder to add points to.
00933                 for(int i = 0; i < points.total && !result; i++)
00934                 {
00935                         MaskPoint *point1 = points.values[i];
00936                         MaskPoint *point2 = (i >= points.total - 1) ? 
00937                                 points.values[0] : 
00938                                 points.values[i + 1];
00939                         float x0, x1, x2, x3;
00940                         float y0, y1, y2, y3;
00941                         float old_x, old_y, x, y;
00942                         int segments = (int)(sqrt(SQR(point1->x - point2->x) + SQR(point1->y - point2->y)));
00943 
00944 //printf("CWindowCanvas::do_mask 1 %f, %f -> %f, %f projectorz=%f\n",
00945 //point1->x, point1->y, point2->x, point2->y, projector_z);
00946                         for(int j = 0; j <= segments && !result; j++)
00947                         {
00948 //printf("CWindowCanvas::do_mask 1 %f, %f -> %f, %f\n", x0, y0, x3, y3);
00949                                 x0 = point1->x;
00950                                 y0 = point1->y;
00951                                 x1 = point1->x + point1->control_x2;
00952                                 y1 = point1->y + point1->control_y2;
00953                                 x2 = point2->x + point2->control_x1;
00954                                 y2 = point2->y + point2->control_y1;
00955                                 x3 = point2->x;
00956                                 y3 = point2->y;
00957 
00958                                 float t = (float)j / segments;
00959                                 float tpow2 = t * t;
00960                                 float tpow3 = t * t * t;
00961                                 float invt = 1 - t;
00962                                 float invtpow2 = invt * invt;
00963                                 float invtpow3 = invt * invt * invt;
00964 
00965                                 x = (        invtpow3 * x0
00966                                         + 3 * t     * invtpow2 * x1
00967                                         + 3 * tpow2 * invt     * x2 
00968                                         +     tpow3            * x3);
00969                                 y = (        invtpow3 * y0 
00970                                         + 3 * t     * invtpow2 * y1
00971                                         + 3 * tpow2 * invt     * y2 
00972                                         +     tpow3            * y3);
00973 
00974                                 x = (x - half_track_w) * projector_z + projector_x;
00975                                 y = (y - half_track_h) * projector_z + projector_y;
00976 
00977 
00978 // Test new point addition
00979                                 if(button_press)
00980                                 {
00981                                         float line_distance = 
00982                                                 sqrt(SQR(x - mask_cursor_x) + SQR(y - mask_cursor_y));
00983 
00984 //printf("CWindowCanvas::do_mask 1 x=%f mask_cursor_x=%f y=%f mask_cursor_y=%f %f %f %d, %d\n", 
00985 //x, mask_cursor_x, y, mask_cursor_y, line_distance, shortest_line_distance, shortest_point1, shortest_point2);
00986                                         if(line_distance < shortest_line_distance || 
00987                                                 shortest_point1 < 0)
00988                                         {
00989                                                 shortest_line_distance = line_distance;
00990                                                 shortest_point1 = i;
00991                                                 shortest_point2 = (i >= points.total - 1) ? 0 : (i + 1);
00992 //printf("CWindowCanvas::do_mask 2 %f %f %d, %d\n", line_distance, shortest_line_distance, shortest_point1, shortest_point2);
00993                                         }
00994 
00995 
00996                                         float point_distance1 = 
00997                                                 sqrt(SQR(point1->x - mask_cursor_x) + SQR(point1->y - mask_cursor_y));
00998                                         float point_distance2 = 
00999                                                 sqrt(SQR(point2->x - mask_cursor_x) + SQR(point2->y - mask_cursor_y));
01000 
01001                                         if(point_distance1 < shortest_point_distance || 
01002                                                 shortest_point < 0)
01003                                         {
01004                                                 shortest_point_distance = point_distance1;
01005                                                 shortest_point = i;
01006                                         }
01007 
01008                                         if(point_distance2 < shortest_point_distance || 
01009                                                 shortest_point < 0)
01010                                         {
01011                                                 shortest_point_distance = point_distance2;
01012                                                 shortest_point = (i >= points.total - 1) ? 0 : (i + 1);
01013                                         }
01014                                 }
01015 
01016                                 output_to_canvas(mwindow->edl, 0, x, y);
01017 
01018 
01019 #define TEST_BOX(cursor_x, cursor_y, target_x, target_y) \
01020         (cursor_x >= target_x - CONTROL_W / 2 && \
01021         cursor_x < target_x + CONTROL_W / 2 && \
01022         cursor_y >= target_y - CONTROL_H / 2 && \
01023         cursor_y < target_y + CONTROL_H / 2)
01024 
01025 // Test existing point selection
01026                                 if(button_press)
01027                                 {
01028                                         float canvas_x = (x0 - half_track_w) * projector_z + projector_x;
01029                                         float canvas_y = (y0 - half_track_h) * projector_z + projector_y;
01030                                         int cursor_x = get_cursor_x();
01031                                         int cursor_y = get_cursor_y();
01032 
01033 // Test first point
01034                                         if(gui->shift_down())
01035                                         {
01036                                                 float control_x = (x1 - half_track_w) * projector_z + projector_x;
01037                                                 float control_y = (y1 - half_track_h) * projector_z + projector_y;
01038                                                 output_to_canvas(mwindow->edl, 0, control_x, control_y);
01039 
01040                                                 float distance = 
01041                                                         sqrt(SQR(control_x - cursor_x) + SQR(control_y - cursor_y));
01042 
01043                                                 if(distance < selected_control_point_distance)
01044                                                 {
01045                                                         selected_point = i;
01046                                                         selected_control_point = 1;
01047                                                         selected_control_point_distance = distance;
01048                                                 }
01049                                         }
01050                                         else
01051                                         {
01052                                                 output_to_canvas(mwindow->edl, 0, canvas_x, canvas_y);
01053                                                 if(!gui->ctrl_down())
01054                                                 {
01055                                                         if(TEST_BOX(cursor_x, cursor_y, canvas_x, canvas_y))
01056                                                         {
01057                                                                 selected_point = i;
01058                                                         }
01059                                                 }
01060                                                 else
01061                                                 {
01062                                                         selected_point = shortest_point;
01063                                                 }
01064                                         }
01065 
01066 // Test second point
01067                                         canvas_x = (x3 - half_track_w) * projector_z + projector_x;
01068                                         canvas_y = (y3 - half_track_h) * projector_z + projector_y;
01069                                         if(gui->shift_down())
01070                                         {
01071                                                 float control_x = (x2 - half_track_w) * projector_z + projector_x;
01072                                                 float control_y = (y2 - half_track_h) * projector_z + projector_y;
01073                                                 output_to_canvas(mwindow->edl, 0, control_x, control_y);
01074 
01075                                                 float distance = 
01076                                                         sqrt(SQR(control_x - cursor_x) + SQR(control_y - cursor_y));
01077 
01078 //printf("CWindowCanvas::do_mask %d %f %f\n", i, distance, selected_control_point_distance);
01079                                                 if(distance < selected_control_point_distance)
01080                                                 {
01081                                                         selected_point = (i < points.total - 1 ? i + 1 : 0);
01082                                                         selected_control_point = 0;
01083                                                         selected_control_point_distance = distance;
01084                                                 }
01085                                         }
01086                                         else
01087                                         if(i < points.total - 1)
01088                                         {
01089                                                 output_to_canvas(mwindow->edl, 0, canvas_x, canvas_y);
01090                                                 if(!gui->ctrl_down())
01091                                                 {
01092                                                         if(TEST_BOX(cursor_x, cursor_y, canvas_x, canvas_y))
01093                                                         {
01094                                                                 selected_point = (i < points.total - 1 ? i + 1 : 0);
01095                                                         }
01096                                                 }
01097                                                 else
01098                                                 {
01099                                                         selected_point = shortest_point;
01100                                                 }
01101                                         }
01102                                 }
01103 
01104 
01105 
01106                                 if(j > 0)
01107                                 {
01108 // Draw joining line
01109                                         if(draw)
01110                                         {
01111                                                 x_points.append((int)x);
01112                                                 y_points.append((int)y);
01113                                         }
01114 
01115                                         if(j == segments)
01116                                         {
01117 
01118 
01119 
01120 
01121                                                 if(draw)
01122                                                 {
01123 // Draw second anchor
01124                                                         if(i < points.total - 1)
01125                                                         {
01126                                                                 if(i == gui->affected_point - 1)
01127                                                                         canvas->draw_disc((int)x - CONTROL_W / 2, 
01128                                                                                 (int)y - CONTROL_W / 2, 
01129                                                                                 CONTROL_W, 
01130                                                                                 CONTROL_W);
01131                                                                 else
01132                                                                         canvas->draw_circle((int)x - CONTROL_W / 2, 
01133                                                                                 (int)y - CONTROL_W / 2, 
01134                                                                                 CONTROL_W, 
01135                                                                                 CONTROL_W);
01136 // char string[BCTEXTLEN];
01137 // sprintf(string, "%d", (i < points.total - 1 ? i + 1 : 0));
01138 // canvas->draw_text((int)x + CONTROL_W, (int)y + CONTROL_W, string);
01139                                                         }
01140 
01141 // Draw second control point.  Discard x2 and y2 after this.
01142                                                         x2 = (x2 - half_track_w) * projector_z + projector_x;
01143                                                         y2 = (y2 - half_track_h) * projector_z + projector_y;
01144                                                         output_to_canvas(mwindow->edl, 0, x2, y2);
01145                                                         canvas->draw_line((int)x, (int)y, (int)x2, (int)y2);
01146                                                         canvas->draw_rectangle((int)x2 - CONTROL_W / 2,
01147                                                                 (int)y2 - CONTROL_H / 2,
01148                                                                 CONTROL_W,
01149                                                                 CONTROL_H);
01150                                                 }
01151                                         }
01152                                 }
01153                                 else
01154                                 {
01155 
01156 
01157 // Draw first anchor
01158                                         if(i == 0 && draw)
01159                                         {
01160                                                 canvas->draw_disc((int)x - FIRST_CONTROL_W / 2, 
01161                                                         (int)y - FIRST_CONTROL_H / 2, 
01162                                                         FIRST_CONTROL_W, 
01163                                                         FIRST_CONTROL_H);
01164                                         }
01165 
01166 // Draw first control point.  Discard x1 and y1 after this.
01167                                         if(draw)
01168                                         {
01169                                                 x1 = (x1 - half_track_w) * projector_z + projector_x;
01170                                                 y1 = (y1 - half_track_h) * projector_z + projector_y;
01171                                                 output_to_canvas(mwindow->edl, 0, x1, y1);
01172                                                 canvas->draw_line((int)x, (int)y, (int)x1, (int)y1);
01173                                                 canvas->draw_rectangle((int)x1 - CONTROL_W / 2,
01174                                                         (int)y1 - CONTROL_H / 2,
01175                                                         CONTROL_W,
01176                                                         CONTROL_H);
01177                                         
01178                                                 x_points.append((int)x);
01179                                                 y_points.append((int)y);
01180                                         }
01181                                 }
01182 //printf("CWindowCanvas::do_mask 1\n");
01183 
01184                                 old_x = x;
01185                                 old_y = y;
01186                         }
01187                 }
01188 //printf("CWindowCanvas::do_mask 1\n");
01189 
01190                 if(draw)
01191                 {
01192                         canvas->draw_polygon(&x_points, &y_points);
01193                         canvas->set_opaque();
01194                 }
01195 //printf("CWindowCanvas::do_mask 1\n");
01196         }
01197 
01198 
01199 
01200 
01201 
01202 
01203 
01204         if(button_press && !result)
01205         {
01206                 gui->affected_track = gui->cwindow->calculate_affected_track();
01207 // Get current keyframe
01208                 if(gui->affected_track)
01209                         gui->affected_keyframe = 
01210                                 gui->cwindow->calculate_affected_auto(
01211                                         gui->affected_track->automation->autos[AUTOMATION_MASK],
01212                                         1);
01213 
01214                 MaskAuto *keyframe = (MaskAuto*)gui->affected_keyframe;
01215                 SubMask *mask = keyframe->get_submask(mwindow->edl->session->cwindow_mask);
01216 
01217 
01218 // Translate entire keyframe
01219                 if(gui->alt_down() && mask->points.total)
01220                 {
01221                         gui->current_operation = CWINDOW_MASK_TRANSLATE;
01222                         gui->affected_point = 0;
01223                 }
01224                 else
01225 // Existing point or control point was selected
01226                 if(selected_point >= 0)
01227                 {
01228                         gui->affected_point = selected_point;
01229 
01230                         if(selected_control_point == 0)
01231                                 gui->current_operation = CWINDOW_MASK_CONTROL_IN;
01232                         else
01233                         if(selected_control_point == 1)
01234                                 gui->current_operation = CWINDOW_MASK_CONTROL_OUT;
01235                         else
01236                                 gui->current_operation = mwindow->edl->session->cwindow_operation;
01237                 }
01238                 else
01239 // No existing point or control point was selected so create a new one
01240                 if(!gui->shift_down() && !gui->alt_down())
01241                 {
01242 // Create the template
01243                         MaskPoint *point = new MaskPoint;
01244                         point->x = mask_cursor_x;
01245                         point->y = mask_cursor_y;
01246                         point->control_x1 = 0;
01247                         point->control_y1 = 0;
01248                         point->control_x2 = 0;
01249                         point->control_y2 = 0;
01250 
01251 
01252                         if(shortest_point2 < shortest_point1)
01253                         {
01254                                 shortest_point2 ^= shortest_point1;
01255                                 shortest_point1 ^= shortest_point2;
01256                                 shortest_point2 ^= shortest_point1;
01257                         }
01258 
01259 
01260 
01261 // printf("CWindowGUI::do_mask 40\n");
01262 // mwindow->edl->dump();
01263 // printf("CWindowGUI::do_mask 50\n");
01264 
01265 
01266 
01267 //printf("CWindowCanvas::do_mask 1 %f %f %d %d\n", 
01268 //      shortest_line_distance, shortest_point_distance, shortest_point1, shortest_point2);
01269 //printf("CWindowCanvas::do_mask %d %d\n", shortest_point1, shortest_point2);
01270 
01271 // Append to end of list
01272                         if(labs(shortest_point1 - shortest_point2) > 1)
01273                         {
01274 // Need to apply the new point to every keyframe
01275                                 for(MaskAuto *current = (MaskAuto*)mask_autos->default_auto;
01276                                         current; )
01277                                 {
01278                                         SubMask *submask = current->get_submask(mwindow->edl->session->cwindow_mask);
01279                                         MaskPoint *new_point = new MaskPoint;
01280                                         submask->points.append(new_point);
01281                                         *new_point = *point;
01282                                         if(current == (MaskAuto*)mask_autos->default_auto)
01283                                                 current = (MaskAuto*)mask_autos->first;
01284                                         else
01285                                                 current = (MaskAuto*)NEXT;
01286                                 }
01287 
01288                                 gui->affected_point = mask->points.total - 1;
01289                                 result = 1;
01290                         }
01291                         else
01292 // Insert between 2 points, shifting back point 2
01293                         if(shortest_point1 >= 0 && shortest_point2 >= 0)
01294                         {
01295                                 for(MaskAuto *current = (MaskAuto*)mask_autos->default_auto;
01296                                         current; )
01297                                 {
01298                                         SubMask *submask = current->get_submask(mwindow->edl->session->cwindow_mask);
01299 // In case the keyframe point count isn't synchronized with the rest of the keyframes,
01300 // avoid a crash.
01301                                         if(submask->points.total >= shortest_point2)
01302                                         {
01303                                                 MaskPoint *new_point = new MaskPoint;
01304                                                 submask->points.append(0);
01305                                                 for(int i = submask->points.total - 1; 
01306                                                         i > shortest_point2; 
01307                                                         i--)
01308                                                         submask->points.values[i] = submask->points.values[i - 1];
01309                                                 submask->points.values[shortest_point2] = new_point;
01310 
01311                                                 *new_point = *point;
01312                                         }
01313 
01314                                         if(current == (MaskAuto*)mask_autos->default_auto)
01315                                                 current = (MaskAuto*)mask_autos->first;
01316                                         else
01317                                                 current = (MaskAuto*)NEXT;
01318                                 }
01319 
01320 
01321                                 gui->affected_point = shortest_point2;
01322                                 result = 1;
01323                         }
01324 
01325 
01326 // printf("CWindowGUI::do_mask 20\n");
01327 // mwindow->edl->dump();
01328 // printf("CWindowGUI::do_mask 30\n");
01329 
01330 
01331 
01332 
01333 // Create the first point.
01334                         if(!result)
01335                         {
01336 //printf("CWindowCanvas::do_mask 1\n");
01337                                 for(MaskAuto *current = (MaskAuto*)mask_autos->default_auto;
01338                                         current; )
01339                                 {
01340                                         SubMask *submask = current->get_submask(mwindow->edl->session->cwindow_mask);
01341                                         MaskPoint *new_point = new MaskPoint;
01342                                         submask->points.append(new_point);
01343                                         *new_point = *point;
01344                                         if(current == (MaskAuto*)mask_autos->default_auto)
01345                                                 current = (MaskAuto*)mask_autos->first;
01346                                         else
01347                                                 current = (MaskAuto*)NEXT;
01348                                 }
01349 
01350 //printf("CWindowCanvas::do_mask 2\n");
01351 // Create a second point if none existed before
01352                                 if(mask->points.total < 2)
01353                                 {
01354                                         for(MaskAuto *current = (MaskAuto*)mask_autos->default_auto;
01355                                                 current; )
01356                                         {
01357                                                 SubMask *submask = current->get_submask(mwindow->edl->session->cwindow_mask);
01358                                                 MaskPoint *new_point = new MaskPoint;
01359                                                 submask->points.append(new_point);
01360                                                 *new_point = *point;
01361                                                 if(current == (MaskAuto*)mask_autos->default_auto)
01362                                                         current = (MaskAuto*)mask_autos->first;
01363                                                 else
01364                                                         current = (MaskAuto*)NEXT;
01365                                         }
01366                                 }
01367                                 gui->affected_point = mask->points.total - 1;
01368 //printf("CWindowCanvas::do_mask 3 %d\n", mask->points.total);
01369                         }
01370 
01371 
01372 
01373                         gui->current_operation = mwindow->edl->session->cwindow_operation;
01374 // Delete the template
01375                         delete point;
01376 //printf("CWindowGUI::do_mask 1\n");
01377                         mwindow->undo->update_undo(_("mask point"), LOAD_AUTOMATION);
01378 //printf("CWindowGUI::do_mask 10\n");
01379 
01380                 }
01381 
01382                 result = 1;
01383                 rerender = 1;
01384                 redraw = 1;
01385         }
01386 
01387         if(button_press && result)
01388         {
01389                 MaskAuto *keyframe = (MaskAuto*)gui->affected_keyframe;
01390                 SubMask *mask = keyframe->get_submask(mwindow->edl->session->cwindow_mask);
01391                 MaskPoint *point = mask->points.values[gui->affected_point];
01392                 gui->center_x = point->x;
01393                 gui->center_y = point->y;
01394                 gui->control_in_x = point->control_x1;
01395                 gui->control_in_y = point->control_y1;
01396                 gui->control_out_x = point->control_x2;
01397                 gui->control_out_y = point->control_y2;
01398         }
01399 
01400 //printf("CWindowCanvas::do_mask 8\n");
01401         if(cursor_motion)
01402         {
01403                 MaskAuto *keyframe = (MaskAuto*)gui->affected_keyframe;
01404                 SubMask *mask = keyframe->get_submask(mwindow->edl->session->cwindow_mask);
01405                 if(gui->affected_point < mask->points.total)
01406                 {
01407                         MaskPoint *point = mask->points.values[gui->affected_point];
01408 //                      float cursor_x = get_cursor_x();
01409 //                      float cursor_y = get_cursor_y();
01410 //                      canvas_to_output(mwindow->edl, 0, cursor_x, cursor_y);
01411                         float cursor_x = mask_cursor_x;
01412                         float cursor_y = mask_cursor_y;
01413 //printf("CWindowCanvas::do_mask 9 %d %d\n", mask->points.total, gui->affected_point);
01414 
01415                         float last_x = point->x;
01416                         float last_y = point->y;
01417                         float last_control_x1 = point->control_x1;
01418                         float last_control_y1 = point->control_y1;
01419                         float last_control_x2 = point->control_x2;
01420                         float last_control_y2 = point->control_y2;
01421 
01422 
01423                         switch(gui->current_operation)
01424                         {
01425                                 case CWINDOW_MASK:
01426                                         point->x = cursor_x - gui->x_origin + gui->center_x;
01427                                         point->y = cursor_y - gui->y_origin + gui->center_y;
01428                                         break;
01429 
01430                                 case CWINDOW_MASK_CONTROL_IN:
01431                                         point->control_x1 = cursor_x - gui->x_origin + gui->control_in_x;
01432                                         point->control_y1 = cursor_y - gui->y_origin + gui->control_in_y;
01433                                         break;
01434 
01435                                 case CWINDOW_MASK_CONTROL_OUT:
01436                                         point->control_x2 = cursor_x - gui->x_origin + gui->control_out_x;
01437                                         point->control_y2 = cursor_y - gui->y_origin + gui->control_out_y;
01438                                         break;
01439 
01440                                 case CWINDOW_MASK_TRANSLATE:
01441                                         for(int i = 0; i < mask->points.total; i++)
01442                                         {
01443                                                 mask->points.values[i]->x += cursor_x - gui->x_origin;
01444                                                 mask->points.values[i]->y += cursor_y - gui->y_origin;
01445                                         }
01446                                         gui->x_origin = cursor_x;
01447                                         gui->y_origin = cursor_y;
01448                                         break;
01449                         }
01450 
01451 
01452                         if( !EQUIV(last_x, point->x) ||
01453                                 !EQUIV(last_y, point->y) ||
01454                                 !EQUIV(last_control_x1, point->control_x1) ||
01455                                 !EQUIV(last_control_y1, point->control_y1) ||
01456                                 !EQUIV(last_control_x2, point->control_x2) ||
01457                                 !EQUIV(last_control_y2, point->control_y2))
01458                         {
01459                                 rerender = 1;
01460                                 redraw = 1;
01461                         }
01462                 }
01463                 result = 1;
01464         }
01465 //printf("CWindowCanvas::do_mask 2 %d %d %d\n", result, rerender, redraw);
01466 
01467         points.remove_all_objects();
01468 //printf("CWindowCanvas::do_mask 20\n");
01469         return result;
01470 }
01471 
01472 
01473 int CWindowCanvas::do_eyedrop(int &rerender, int button_press)
01474 {
01475         int result = 0;
01476         float cursor_x = get_cursor_x();
01477         float cursor_y = get_cursor_y();
01478 
01479 
01480         if(button_press)
01481         {
01482                 gui->current_operation = CWINDOW_EYEDROP;
01483         }
01484 
01485         if(gui->current_operation == CWINDOW_EYEDROP)
01486         {
01487 SET_TRACE
01488                 canvas_to_output(mwindow->edl, 0, cursor_x, cursor_y);
01489 SET_TRACE
01490 
01491 // Get color out of frame.
01492 // Doesn't work during playback because that bypasses the refresh frame.
01493                 if(refresh_frame)
01494                 {
01495                         CLAMP(cursor_x, 0, refresh_frame->get_w() - 1);
01496                         CLAMP(cursor_y, 0, refresh_frame->get_h() - 1);
01497 
01498 // Decompression coefficients straight out of jpeglib
01499 #define V_TO_R    1.40200
01500 #define V_TO_G    -0.71414
01501 
01502 #define U_TO_G    -0.34414
01503 #define U_TO_B    1.77200
01504 
01505 #define GET_COLOR(type, components, max, do_yuv) \
01506 { \
01507         type *row = (type*)(refresh_frame->get_rows()[(int)cursor_y]) + \
01508                 (int)cursor_x * components; \
01509         float red = (float)*row++ / max; \
01510         float green = (float)*row++ / max; \
01511         float blue = (float)*row++ / max; \
01512         if(do_yuv) \
01513         { \
01514                 mwindow->edl->local_session->red = red + V_TO_R * (blue - 0.5); \
01515                 mwindow->edl->local_session->green = red + U_TO_G * (green - 0.5) + V_TO_G * (blue - 0.5); \
01516                 mwindow->edl->local_session->blue = red + U_TO_B * (green - 0.5); \
01517         } \
01518         else \
01519         { \
01520                 mwindow->edl->local_session->red = red; \
01521                 mwindow->edl->local_session->green = green; \
01522                 mwindow->edl->local_session->blue = blue; \
01523         } \
01524 }
01525 
01526 SET_TRACE
01527                         switch(refresh_frame->get_color_model())
01528                         {
01529                                 case BC_YUV888:
01530                                         GET_COLOR(unsigned char, 3, 0xff, 1);
01531                                         break;
01532                                 case BC_YUVA8888:
01533                                         GET_COLOR(unsigned char, 4, 0xff, 1);
01534                                         break;
01535                                 case BC_YUV161616:
01536                                         GET_COLOR(uint16_t, 3, 0xffff, 1);
01537                                         break;
01538                                 case BC_YUVA16161616:
01539                                         GET_COLOR(uint16_t, 4, 0xffff, 1);
01540                                         break;
01541                                 case BC_RGB888:
01542                                         GET_COLOR(unsigned char, 3, 0xff, 0);
01543                                         break;
01544                                 case BC_RGBA8888:
01545                                         GET_COLOR(unsigned char, 4, 0xff, 0);
01546                                         break;
01547                                 case BC_RGB_FLOAT:
01548                                         GET_COLOR(float, 3, 1.0, 0);
01549                                         break;
01550                                 case BC_RGBA_FLOAT:
01551                                         GET_COLOR(float, 4, 1.0, 0);
01552                                         break;
01553                         }
01554 SET_TRACE
01555                 }
01556                 else
01557                 {
01558                         mwindow->edl->local_session->red = 0;
01559                         mwindow->edl->local_session->green = 0;
01560                         mwindow->edl->local_session->blue = 0;
01561                 }
01562 
01563 SET_TRACE
01564 
01565                 gui->update_tool();             
01566 
01567 
01568 SET_TRACE
01569 
01570                 result = 1;
01571 // Can't rerender since the color value is from the output of any effect it
01572 // goes into.
01573 //              rerender = 1;
01574         }
01575 
01576         return result;
01577 }
01578 
01579 void CWindowCanvas::draw_overlays()
01580 {
01581 //printf("CWindowCanvas::draw_overlays 1\n");
01582         if(mwindow->edl->session->safe_regions)
01583         {
01584                 draw_safe_regions();
01585         }
01586 
01587         if(mwindow->edl->session->cwindow_scrollbars)
01588         {
01589 // Always draw output rectangle
01590                 float x1, y1, x2, y2;
01591                 x1 = 0;
01592                 x2 = mwindow->edl->session->output_w;
01593                 y1 = 0;
01594                 y2 = mwindow->edl->session->output_h;
01595                 output_to_canvas(mwindow->edl, 0, x1, y1);
01596                 output_to_canvas(mwindow->edl, 0, x2, y2);
01597 
01598                 canvas->set_inverse();
01599                 canvas->set_color(WHITE);
01600 
01601                 canvas->draw_rectangle((int)x1, 
01602                                 (int)y1, 
01603                                 (int)(x2 - x1), 
01604                                 (int)(y2 - y1));
01605 
01606                 canvas->set_opaque();
01607         }
01608 
01609         if(mwindow->session->ccanvas_highlighted)
01610         {
01611                 canvas->set_color(WHITE);
01612                 canvas->set_inverse();
01613                 canvas->draw_rectangle(0, 0, canvas->get_w(), canvas->get_h());
01614                 canvas->draw_rectangle(1, 1, canvas->get_w() - 2, canvas->get_h() - 2);
01615                 canvas->set_opaque();
01616         }
01617 
01618         int temp1 = 0, temp2 = 0;
01619 //printf("CWindowCanvas::draw_overlays 1 %d\n", mwindow->edl->session->cwindow_operation);
01620         switch(mwindow->edl->session->cwindow_operation)
01621         {
01622                 case CWINDOW_CAMERA:
01623                         draw_bezier(1);
01624                         break;
01625 
01626                 case CWINDOW_PROJECTOR:
01627                         draw_bezier(0);
01628                         break;
01629 
01630                 case CWINDOW_CROP:
01631                         draw_crop();
01632                         break;
01633 
01634                 case CWINDOW_MASK:
01635                         do_mask(temp1, temp2, 0, 0, 1);
01636                         break;
01637         }
01638 //printf("CWindowCanvas::draw_overlays 2\n");
01639 }
01640 
01641 void CWindowCanvas::draw_safe_regions()
01642 {
01643         float action_x1, action_x2, action_y1, action_y2;
01644         float title_x1, title_x2, title_y1, title_y2;
01645 
01646         action_x1 = mwindow->edl->session->output_w / 2 - mwindow->edl->session->output_w / 2 * 0.9;
01647         action_x2 = mwindow->edl->session->output_w / 2 + mwindow->edl->session->output_w / 2 * 0.9;
01648         action_y1 = mwindow->edl->session->output_h / 2 - mwindow->edl->session->output_h / 2 * 0.9;
01649         action_y2 = mwindow->edl->session->output_h / 2 + mwindow->edl->session->output_h / 2 * 0.9;
01650         title_x1 = mwindow->edl->session->output_w / 2 - mwindow->edl->session->output_w / 2 * 0.8;
01651         title_x2 = mwindow->edl->session->output_w / 2 + mwindow->edl->session->output_w / 2 * 0.8;
01652         title_y1 = mwindow->edl->session->output_h / 2 - mwindow->edl->session->output_h / 2 * 0.8;
01653         title_y2 = mwindow->edl->session->output_h / 2 + mwindow->edl->session->output_h / 2 * 0.8;
01654 
01655         output_to_canvas(mwindow->edl, 0, action_x1, action_y1);
01656         output_to_canvas(mwindow->edl, 0, action_x2, action_y2);
01657         output_to_canvas(mwindow->edl, 0, title_x1, title_y1);
01658         output_to_canvas(mwindow->edl, 0, title_x2, title_y2);
01659 
01660         canvas->set_inverse();
01661         canvas->set_color(WHITE);
01662 
01663         canvas->draw_rectangle((int)action_x1, 
01664                         (int)action_y1, 
01665                         (int)(action_x2 - action_x1), 
01666                         (int)(action_y2 - action_y1));
01667         canvas->draw_rectangle((int)title_x1, 
01668                         (int)title_y1, 
01669                         (int)(title_x2 - title_x1), 
01670                         (int)(title_y2 - title_y1));
01671 
01672         canvas->set_opaque();
01673 }
01674 
01675 void CWindowCanvas::reset_keyframe(int do_camera)
01676 {
01677         FloatAuto *x_keyframe = 0;
01678         FloatAuto *y_keyframe = 0;
01679         FloatAuto *z_keyframe = 0;
01680         Track *affected_track = 0;
01681 
01682         affected_track = gui->cwindow->calculate_affected_track();
01683 
01684         if(affected_track)
01685         {
01686                 gui->cwindow->calculate_affected_autos(&x_keyframe,
01687                         &y_keyframe,
01688                         &z_keyframe,
01689                         affected_track,
01690                         do_camera,
01691                         1,
01692                         1,
01693                         1);
01694 
01695                 x_keyframe->value = 0;
01696                 y_keyframe->value = 0;
01697                 z_keyframe->value = 1;
01698 
01699                 mwindow->sync_parameters(CHANGE_PARAMS);
01700                 gui->update_tool();
01701         }
01702 }
01703 
01704 void CWindowCanvas::reset_camera()
01705 {
01706         reset_keyframe(1);
01707 }
01708 
01709 void CWindowCanvas::reset_projector()
01710 {
01711         reset_keyframe(0);
01712 }
01713 
01714 int CWindowCanvas::test_crop(int button_press, int &redraw)
01715 {
01716         int result = 0;
01717         int handle_selected = -1;
01718         float x1 = mwindow->edl->session->crop_x1;
01719         float y1 = mwindow->edl->session->crop_y1;
01720         float x2 = mwindow->edl->session->crop_x2;
01721         float y2 = mwindow->edl->session->crop_y2;
01722         float cursor_x = get_cursor_x();
01723         float cursor_y = get_cursor_y();
01724         float canvas_x1 = x1;
01725         float canvas_y1 = y1;
01726         float canvas_x2 = x2;
01727         float canvas_y2 = y2;
01728         float canvas_cursor_x = cursor_x;
01729         float canvas_cursor_y = cursor_y;
01730 
01731         canvas_to_output(mwindow->edl, 0, cursor_x, cursor_y);
01732 // Use screen normalized coordinates for hot spot tests.
01733         output_to_canvas(mwindow->edl, 0, canvas_x1, canvas_y1);
01734         output_to_canvas(mwindow->edl, 0, canvas_x2, canvas_y2);
01735 
01736 
01737         if(gui->current_operation == CWINDOW_CROP)
01738         {
01739                 handle_selected = gui->crop_handle;
01740         }
01741         else
01742         if(canvas_cursor_x >= canvas_x1 && canvas_cursor_x < canvas_x1 + CROPHANDLE_W &&
01743                 canvas_cursor_y >= canvas_y1 && canvas_cursor_y < canvas_y1 + CROPHANDLE_H)
01744         {
01745                 handle_selected = 0;
01746                 gui->crop_origin_x = x1;
01747                 gui->crop_origin_y = y1;
01748         }
01749         else
01750         if(canvas_cursor_x >= canvas_x2 - CROPHANDLE_W && canvas_cursor_x < canvas_x2 &&
01751                 canvas_cursor_y >= canvas_y1 && canvas_cursor_y < canvas_y1 + CROPHANDLE_H)
01752         {
01753                 handle_selected = 1;
01754                 gui->crop_origin_x = x2;
01755                 gui->crop_origin_y = y1;
01756         }
01757         else
01758         if(canvas_cursor_x >= canvas_x1 && canvas_cursor_x < canvas_x1 + CROPHANDLE_W &&
01759                 canvas_cursor_y >= canvas_y2 - CROPHANDLE_H && canvas_cursor_y < canvas_y2)
01760         {
01761                 handle_selected = 2;
01762                 gui->crop_origin_x = x1;
01763                 gui->crop_origin_y = y2;
01764         }
01765         else
01766         if(canvas_cursor_x >= canvas_x2 - CROPHANDLE_W && canvas_cursor_x < canvas_x2 &&
01767                 canvas_cursor_y >= canvas_y2 - CROPHANDLE_H && canvas_cursor_y < canvas_y2)
01768         {
01769                 handle_selected = 3;
01770                 gui->crop_origin_x = x2;
01771                 gui->crop_origin_y = y2;
01772         }
01773         else
01774 // Start new box
01775         {
01776                 gui->crop_origin_x = cursor_x;
01777                 gui->crop_origin_y = cursor_y;
01778         }
01779 
01780 // printf("test crop %d %d\n", 
01781 //      gui->current_operation,
01782 //      handle_selected);
01783 
01784 // Start dragging.
01785         if(button_press)
01786         {
01787                 if(gui->alt_down())
01788                 {
01789                         gui->crop_translate = 1;
01790                         gui->crop_origin_x1 = x1;
01791                         gui->crop_origin_y1 = y1;
01792                         gui->crop_origin_x2 = x2;
01793                         gui->crop_origin_y2 = y2;
01794                 }
01795                 else
01796                         gui->crop_translate = 0;
01797 
01798                 gui->current_operation = CWINDOW_CROP;
01799                 gui->crop_handle = handle_selected;
01800                 gui->x_origin = cursor_x;
01801                 gui->y_origin = cursor_y;
01802                 result = 1;
01803 
01804                 if(handle_selected < 0 && !gui->crop_translate) 
01805                 {
01806                         x2 = x1 = cursor_x;
01807                         y2 = y1 = cursor_y;
01808                         mwindow->edl->session->crop_x1 = (int)x1;
01809                         mwindow->edl->session->crop_y1 = (int)y1;
01810                         mwindow->edl->session->crop_x2 = (int)x2;
01811                         mwindow->edl->session->crop_y2 = (int)y2;
01812                         redraw = 1;
01813                 }
01814         }
01815     else
01816 // Translate all 4 points
01817         if(gui->current_operation == CWINDOW_CROP && gui->crop_translate)
01818         {
01819                 x1 = cursor_x - gui->x_origin + gui->crop_origin_x1;
01820                 y1 = cursor_y - gui->y_origin + gui->crop_origin_y1;
01821                 x2 = cursor_x - gui->x_origin + gui->crop_origin_x2;
01822                 y2 = cursor_y - gui->y_origin + gui->crop_origin_y2;
01823 
01824                 mwindow->edl->session->crop_x1 = (int)x1;
01825                 mwindow->edl->session->crop_y1 = (int)y1;
01826                 mwindow->edl->session->crop_x2 = (int)x2;
01827                 mwindow->edl->session->crop_y2 = (int)y2;
01828                 result = 1;
01829                 redraw = 1;
01830         }
01831         else
01832 // Update dragging
01833         if(gui->current_operation == CWINDOW_CROP)
01834         {
01835                 switch(gui->crop_handle)
01836                 {
01837                         case -1:
01838                                 x1 = gui->crop_origin_x;
01839                                 y1 = gui->crop_origin_y;
01840                                 x2 = gui->crop_origin_x;
01841                                 y2 = gui->crop_origin_y;
01842                                 if(cursor_x < gui->x_origin)
01843                                 {
01844                                         if(cursor_y < gui->y_origin)
01845                                         {
01846                                                 x1 = cursor_x;
01847                                                 y1 = cursor_y;
01848                                         }
01849                                         else
01850                                         if(cursor_y >= gui->y_origin)
01851                                         {
01852                                                 x1 = cursor_x;
01853                                                 y2 = cursor_y;
01854                                         }
01855                                 }
01856                                 else
01857                                 if(cursor_x  >= gui->x_origin)
01858                                 {
01859                                         if(cursor_y < gui->y_origin)
01860                                         {
01861                                                 y1 = cursor_y;
01862                                                 x2 = cursor_x;
01863                                         }
01864                                         else
01865                                         if(cursor_y >= gui->y_origin)
01866                                         {
01867                                                 x2 = cursor_x;
01868                                                 y2 = cursor_y;
01869                                         }
01870                                 }
01871 
01872 // printf("test crop %d %d %d %d\n", 
01873 //      mwindow->edl->session->crop_x1,
01874 //      mwindow->edl->session->crop_y1,
01875 //      mwindow->edl->session->crop_x2,
01876 //      mwindow->edl->session->crop_y2);
01877                                 break;
01878                         case 0:
01879                                 x1 = cursor_x - gui->x_origin + gui->crop_origin_x;
01880                                 y1 = cursor_y - gui->y_origin + gui->crop_origin_y;
01881                                 break;
01882                         case 1:
01883                                 x2 = cursor_x - gui->x_origin + gui->crop_origin_x;
01884                                 y1 = cursor_y - gui->y_origin + gui->crop_origin_y;
01885                                 break;
01886                         case 2:
01887                                 x1 = cursor_x - gui->x_origin + gui->crop_origin_x;
01888                                 y2 = cursor_y - gui->y_origin + gui->crop_origin_y;
01889                                 break;
01890                         case 3:
01891                                 x2 = cursor_x - gui->x_origin + gui->crop_origin_x;
01892                                 y2 = cursor_y - gui->y_origin + gui->crop_origin_y;
01893                                 break;
01894                 }
01895 
01896                 if(!EQUIV(mwindow->edl->session->crop_x1, x1) ||
01897                         !EQUIV(mwindow->edl->session->crop_x2, x2) ||
01898                         !EQUIV(mwindow->edl->session->crop_y1, y1) ||
01899                         !EQUIV(mwindow->edl->session->crop_y2, y2))
01900                 {
01901                         if (x1 > x2) 
01902                         {
01903                                 float tmp = x1;
01904                                 x1 = x2;
01905                                 x2 = tmp;
01906                                 switch (gui->crop_handle) 
01907                                 {
01908                                         case 0: gui->crop_handle = 1; break;
01909                                         case 1: gui->crop_handle = 0; break;
01910                                         case 2: gui->crop_handle = 3; break;
01911                                         case 3: gui->crop_handle = 2; break;
01912                                         default: break;
01913                                 }
01914 
01915                         }
01916                         if (y1 > y2) 
01917                         {
01918                                 float tmp = y1;
01919                                 y1 = y2;
01920                                 y2 = tmp;
01921                                 switch (gui->crop_handle) 
01922                                 {
01923                                         case 0: gui->crop_handle = 2; break;
01924                                         case 1: gui->crop_handle = 3; break;
01925                                         case 2: gui->crop_handle = 0; break;
01926                                         case 3: gui->crop_handle = 1; break;
01927                                         default: break;
01928                                 }
01929                         }
01930 
01931                         mwindow->edl->session->crop_x1 = (int)x1;
01932                         mwindow->edl->session->crop_y1 = (int)y1;
01933                         mwindow->edl->session->crop_x2 = (int)x2;
01934                         mwindow->edl->session->crop_y2 = (int)y2;
01935                         result = 1;
01936                         redraw = 1;
01937                 }
01938         }
01939         else
01940 // Update cursor font
01941         if(handle_selected >= 0)
01942         {
01943                 switch(handle_selected)
01944                 {
01945                         case 0:
01946                                 set_cursor(UPLEFT_RESIZE);
01947                                 break;
01948                         case 1:
01949                                 set_cursor(UPRIGHT_RESIZE);
01950                                 break;
01951                         case 2:
01952                                 set_cursor(DOWNLEFT_RESIZE);
01953                                 break;
01954                         case 3:
01955                                 set_cursor(DOWNRIGHT_RESIZE);
01956                                 break;
01957                 }
01958                 result = 1;
01959         }
01960         else
01961         {
01962                 set_cursor(ARROW_CURSOR);
01963         }
01964 #define CLAMP(x, y, z) ((x) = ((x) < (y) ? (y) : ((x) > (z) ? (z) : (x))))
01965         
01966         if(redraw)
01967         {
01968                 CLAMP(mwindow->edl->session->crop_x1, 0, mwindow->edl->session->output_w);
01969                 CLAMP(mwindow->edl->session->crop_x2, 0, mwindow->edl->session->output_w);
01970                 CLAMP(mwindow->edl->session->crop_y1, 0, mwindow->edl->session->output_h);
01971                 CLAMP(mwindow->edl->session->crop_y2, 0, mwindow->edl->session->output_h);
01972 // printf("CWindowCanvas::test_crop %d %d %d %d\n", 
01973 //      mwindow->edl->session->crop_x2,
01974 //      mwindow->edl->session->crop_y2,
01975 //      mwindow->edl->calculate_output_w(0), 
01976 //      mwindow->edl->calculate_output_h(0));
01977         }
01978         return result;
01979 }
01980 
01981 
01982 void CWindowCanvas::draw_crop()
01983 {
01984         canvas->set_inverse();
01985         canvas->set_color(WHITE);
01986 
01987         float x1 = mwindow->edl->session->crop_x1;
01988         float y1 = mwindow->edl->session->crop_y1;
01989         float x2 = mwindow->edl->session->crop_x2;
01990         float y2 = mwindow->edl->session->crop_y2;
01991 
01992         output_to_canvas(mwindow->edl, 0, x1, y1);
01993         output_to_canvas(mwindow->edl, 0, x2, y2);
01994 
01995         if(x2 - x1 && y2 - y1)
01996                 canvas->draw_rectangle((int)x1, 
01997                         (int)y1, 
01998                         (int)(x2 - x1), 
01999                         (int)(y2 - y1));
02000 
02001         draw_crophandle((int)x1, (int)y1);
02002         draw_crophandle((int)x2 - CROPHANDLE_W, (int)y1);
02003         draw_crophandle((int)x1, (int)y2 - CROPHANDLE_H);
02004         draw_crophandle((int)x2 - CROPHANDLE_W, (int)y2 - CROPHANDLE_H);
02005         canvas->set_opaque();
02006 }
02007 
02008 
02009 
02010 
02011 
02012 
02013 
02014 
02015 void CWindowCanvas::draw_bezier(int do_camera)
02016 {
02017         Track *track = gui->cwindow->calculate_affected_track();
02018         
02019         if(!track) return;
02020 
02021         float center_x;
02022         float center_y;
02023         float center_z;
02024         int64_t position = track->to_units(
02025                 mwindow->edl->local_session->get_selectionstart(1), 
02026                 0);
02027 
02028         track->automation->get_projector(&center_x, 
02029                 &center_y, 
02030                 &center_z, 
02031                 position,
02032                 PLAY_FORWARD);
02033 
02034 //      center_x += track->track_w / 2;
02035 //      center_y += track->track_h / 2;
02036         center_x += mwindow->edl->session->output_w / 2;
02037         center_y += mwindow->edl->session->output_h / 2;
02038         float track_x1 = center_x - track->track_w / 2 * center_z;
02039         float track_y1 = center_y - track->track_h / 2 * center_z;
02040         float track_x2 = track_x1 + track->track_w * center_z;
02041         float track_y2 = track_y1 + track->track_h * center_z;
02042 
02043         output_to_canvas(mwindow->edl, 0, track_x1, track_y1);
02044         output_to_canvas(mwindow->edl, 0, track_x2, track_y2);
02045 
02046 #define DRAW_PROJECTION(offset) \
02047         canvas->draw_rectangle((int)track_x1 + offset, \
02048                 (int)track_y1 + offset, \
02049                 (int)(track_x2 - track_x1), \
02050                 (int)(track_y2 - track_y1)); \
02051         canvas->draw_line((int)track_x1 + offset,  \
02052                 (int)track_y1 + offset, \
02053                 (int)track_x2 + offset, \
02054                 (int)track_y2 + offset); \
02055         canvas->draw_line((int)track_x2 + offset,  \
02056                 (int)track_y1 + offset, \
02057                 (int)track_x1 + offset, \
02058                 (int)track_y2 + offset); \
02059 
02060 
02061 // Drop shadow
02062         canvas->set_color(BLACK);
02063         DRAW_PROJECTION(1);
02064 
02065 //      canvas->set_inverse();
02066         if(do_camera)
02067                 canvas->set_color(GREEN);
02068         else
02069                 canvas->set_color(RED);
02070 
02071         DRAW_PROJECTION(0);
02072 //      canvas->set_opaque();
02073 
02074 }
02075 
02076 
02077 
02078 int CWindowCanvas::test_bezier(int button_press, 
02079         int &redraw, 
02080         int &redraw_canvas,
02081         int &rerender,
02082         int do_camera)
02083 {
02084         int result = 0;
02085 
02086 // Processing drag operation.
02087 // Create keyframe during first cursor motion.
02088         if(!button_press)
02089         {
02090 
02091                 float cursor_x = get_cursor_x();
02092                 float cursor_y = get_cursor_y();
02093                 canvas_to_output(mwindow->edl, 0, cursor_x, cursor_y);
02094 
02095                 if(gui->current_operation == CWINDOW_CAMERA ||
02096                         gui->current_operation == CWINDOW_PROJECTOR)
02097                 {
02098                         if(!gui->ctrl_down() && gui->shift_down() && !gui->translating_zoom)
02099                         {
02100                                 gui->translating_zoom = 1;
02101                                 gui->reset_affected();
02102                         }
02103                         else
02104                         if(!gui->ctrl_down() && !gui->shift_down() && gui->translating_zoom)
02105                         {
02106                                 gui->translating_zoom = 0;
02107                                 gui->reset_affected();
02108                         }
02109 
02110 // Get target keyframe
02111                         float last_center_x;
02112                         float last_center_y;
02113                         float last_center_z;
02114 
02115 
02116                         if(!gui->affected_x && !gui->affected_y && !gui->affected_z)
02117                         {
02118                                 Autos *affected_x_autos;
02119                                 Autos *affected_y_autos;
02120                                 Autos *affected_z_autos;
02121                                 if(!gui->affected_track) return 0;
02122                                 if(mwindow->edl->session->cwindow_operation == CWINDOW_CAMERA)
02123                                 {
02124                                         affected_x_autos = gui->affected_track->automation->autos[AUTOMATION_CAMERA_X];
02125                                         affected_y_autos = gui->affected_track->automation->autos[AUTOMATION_CAMERA_Y];
02126                                         affected_z_autos = gui->affected_track->automation->autos[AUTOMATION_CAMERA_Z];
02127                                 }
02128                                 else
02129                                 {
02130                                         affected_x_autos = gui->affected_track->automation->autos[AUTOMATION_PROJECTOR_X];
02131                                         affected_y_autos = gui->affected_track->automation->autos[AUTOMATION_PROJECTOR_Y];
02132                                         affected_z_autos = gui->affected_track->automation->autos[AUTOMATION_PROJECTOR_Z];
02133                                 }
02134 
02135                                 if(gui->translating_zoom)
02136                                 {
02137                                         gui->affected_z = 
02138                                                 (FloatAuto*)gui->cwindow->calculate_affected_auto(
02139                                                         affected_z_autos, 1);
02140                                 }
02141                                 else
02142                                 {
02143                                         gui->affected_x = 
02144                                                 (FloatAuto*)gui->cwindow->calculate_affected_auto(
02145                                                         affected_x_autos, 1);
02146                                         gui->affected_y = 
02147                                                 (FloatAuto*)gui->cwindow->calculate_affected_auto(
02148                                                         affected_y_autos, 1);
02149                                 }
02150 
02151                                 calculate_origin();
02152 
02153                                 if(gui->translating_zoom)
02154                                 {
02155                                         gui->center_z = gui->affected_z->value;
02156                                 }
02157                                 else
02158                                 {
02159                                         gui->center_x = gui->affected_x->value;
02160                                         gui->center_y = gui->affected_y->value;
02161                                 }
02162 
02163                                 rerender = 1;
02164                                 redraw = 1;
02165                         }
02166 
02167 
02168                         if(gui->translating_zoom)
02169                         {
02170                                 last_center_z = gui->affected_z->value;
02171                         }
02172                         else
02173                         {
02174                                 last_center_x = gui->affected_x->value;
02175                                 last_center_y = gui->affected_y->value;
02176                         }
02177 
02178                         if(gui->translating_zoom)
02179                         {
02180                                 gui->affected_z->value = gui->center_z + 
02181                                         (cursor_y - gui->y_origin) / 128;
02182                                 if(!EQUIV(last_center_z, gui->affected_z->value))
02183                                 {
02184                                         rerender = 1;
02185                                         redraw = 1;
02186                                         redraw_canvas = 1;
02187                                 }
02188                         }
02189                         else
02190                         {
02191                                 gui->affected_x->value = gui->center_x + cursor_x - gui->x_origin;
02192                                 gui->affected_y->value = gui->center_y + cursor_y - gui->y_origin;
02193                                 if(!EQUIV(last_center_x,  gui->affected_x->value) ||
02194                                         !EQUIV(last_center_y, gui->affected_y->value))
02195                                 {
02196                                         rerender = 1;
02197                                         redraw = 1;
02198                                         redraw_canvas = 1;
02199                                 }
02200                         }
02201                 }
02202 
02203                 result = 1;
02204         }
02205         else
02206 // Begin drag operation.  Don't create keyframe here.
02207         {
02208 // Get affected track off of the first recordable video track.
02209 // Calculating based on the alpha channel would require recording what layer
02210 // each output pixel belongs to as they're rendered and stacked.  Forget it.
02211                 gui->affected_track = gui->cwindow->calculate_affected_track();
02212                 gui->reset_affected();
02213 
02214                 if(gui->affected_track)
02215                 {
02216                         gui->current_operation = 
02217                                 mwindow->edl->session->cwindow_operation;
02218                         result = 1;
02219                 }
02220         }
02221         
02222         return result;
02223 }
02224 
02225 int CWindowCanvas::test_zoom(int &redraw)
02226 {
02227         int result = 0;
02228         float zoom = get_zoom();
02229         float x;
02230         float y;
02231 
02232         if(!mwindow->edl->session->cwindow_scrollbars)
02233         {
02234                 mwindow->edl->session->cwindow_scrollbars = 1;
02235                 zoom = 1.0;
02236                 x = mwindow->edl->session->output_w / 2;
02237                 y = mwindow->edl->session->output_h / 2;
02238         }
02239         else
02240         {
02241                 x = get_cursor_x();
02242                 y = get_cursor_y();
02243                 canvas_to_output(mwindow->edl, 
02244                                 0, 
02245                                 x, 
02246                                 y);
02247 
02248 //printf("CWindowCanvas::test_zoom 1 %f %f\n", x, y);
02249 
02250 // Find current zoom in table
02251                 int current_index = 0;
02252                 for(current_index = 0 ; current_index < total_zooms; current_index++)
02253                         if(EQUIV(my_zoom_table[current_index], zoom)) break;
02254 
02255 
02256 // Zoom out
02257                 if(get_buttonpress() == 5 ||
02258                         gui->ctrl_down() || 
02259                         gui->shift_down())
02260                 {
02261                         current_index--;
02262                 }
02263                 else
02264 // Zoom in
02265                 {
02266                         current_index++;
02267                 }
02268                 CLAMP(current_index, 0, total_zooms - 1);
02269                 zoom = my_zoom_table[current_index];
02270         }
02271 
02272         x = x - w / zoom / 2;
02273         y = y - h / zoom / 2;
02274 
02275 
02276         int x_i = (int)x;
02277         int y_i = (int)y;
02278 //      check_boundaries(mwindow->edl, x_i, y_i, zoom);
02279 
02280 //printf("CWindowCanvas::test_zoom 2 %d %d\n", x_i, y_i);
02281 
02282         update_zoom(x_i, 
02283                         y_i, 
02284                         zoom);
02285         reposition_window(mwindow->edl, 
02286                         mwindow->theme->ccanvas_x,
02287                         mwindow->theme->ccanvas_y,
02288                         mwindow->theme->ccanvas_w,
02289                         mwindow->theme->ccanvas_h);
02290         redraw = 1;
02291         result = 1;
02292 
02293         
02294         gui->zoom_panel->update(zoom);
02295         
02296         return result;
02297 }
02298 
02299 
02300 void CWindowCanvas::calculate_origin()
02301 {
02302         gui->x_origin = get_cursor_x();
02303         gui->y_origin = get_cursor_y();
02304 //printf("CWindowCanvas::calculate_origin 1 %f %f\n", gui->x_origin, gui->y_origin);
02305         canvas_to_output(mwindow->edl, 0, gui->x_origin, gui->y_origin);
02306 //printf("CWindowCanvas::calculate_origin 2 %f %f\n", gui->x_origin, gui->y_origin);
02307 }
02308 
02309 
02310 int CWindowCanvas::cursor_leave_event()
02311 {
02312         set_cursor(ARROW_CURSOR);
02313         return 1;
02314 }
02315 
02316 int CWindowCanvas::cursor_enter_event()
02317 {
02318         int redraw = 0;
02319         switch(mwindow->edl->session->cwindow_operation)
02320         {
02321                 case CWINDOW_CAMERA:
02322                 case CWINDOW_PROJECTOR:
02323                         set_cursor(MOVE_CURSOR);
02324                         break;
02325                 case CWINDOW_ZOOM:
02326                         set_cursor(MOVE_CURSOR);
02327                         break;
02328                 case CWINDOW_CROP:
02329                         test_crop(0, redraw);
02330                         break;
02331                 case CWINDOW_PROTECT:
02332                         set_cursor(ARROW_CURSOR);
02333                         break;
02334                 case CWINDOW_MASK:
02335                         set_cursor(CROSS_CURSOR);
02336                         break;
02337                 case CWINDOW_EYEDROP:
02338                         set_cursor(CROSS_CURSOR);
02339                         break;
02340         }
02341         return 1;
02342 }
02343 
02344 int CWindowCanvas::cursor_motion_event()
02345 {
02346         int redraw = 0, result = 0, rerender = 0, redraw_canvas = 0;
02347 
02348 
02349         switch(gui->current_operation)
02350         {
02351                 case CWINDOW_SCROLL:
02352                 {
02353                         float zoom = get_zoom();
02354                         float cursor_x = get_cursor_x();
02355                         float cursor_y = get_cursor_y();
02356 
02357                         float zoom_x, zoom_y, conformed_w, conformed_h;
02358                         get_zooms(mwindow->edl, 0, zoom_x, zoom_y, conformed_w, conformed_h);
02359                         cursor_x = (float)cursor_x / zoom_x + gui->x_offset;
02360                         cursor_y = (float)cursor_y / zoom_y + gui->y_offset;
02361 
02362 
02363 
02364                         int x = (int)(gui->x_origin - cursor_x + gui->x_offset);
02365                         int y = (int)(gui->y_origin - cursor_y + gui->y_offset);
02366 
02367                         update_zoom(x, 
02368                                 y, 
02369                                 zoom);
02370                         update_scrollbars();
02371                         redraw = 1;
02372                         result = 1;
02373                         break;
02374                 }
02375 
02376                 case CWINDOW_CAMERA:
02377                         result = test_bezier(0, redraw, redraw_canvas, rerender, 1);
02378                         break;
02379 
02380                 case CWINDOW_PROJECTOR:
02381                         result = test_bezier(0, redraw, redraw_canvas, rerender, 0);
02382                         break;
02383 
02384 
02385                 case CWINDOW_CROP:
02386 //printf("CWindowCanvas::cursor_motion_event 1 %d %d\n", x, y);
02387                         result = test_crop(0, redraw);
02388                         break;
02389 
02390                 case CWINDOW_MASK:
02391                 case CWINDOW_MASK_CONTROL_IN:
02392                 case CWINDOW_MASK_CONTROL_OUT:
02393                 case CWINDOW_MASK_TRANSLATE:
02394                         result = do_mask(redraw, 
02395                                 rerender, 
02396                                 0, 
02397                                 1,
02398                                 0);
02399                         break;
02400 
02401                 case CWINDOW_EYEDROP:
02402                         result = do_eyedrop(rerender, 0);
02403                         break;
02404 
02405         }
02406 
02407 
02408 
02409         if(!result)
02410         {
02411                 switch(mwindow->edl->session->cwindow_operation)
02412                 {
02413                         case CWINDOW_CROP:
02414                                 result = test_crop(0, redraw);
02415                                 break;
02416                 }
02417         }
02418 
02419 
02420 // If the window is never unlocked before calling send_command the
02421 // display shouldn't get stuck on the old video frame although it will
02422 // flicker between the old video frame and the new video frame.
02423 
02424         if(redraw)
02425         {
02426                 draw_refresh();
02427                 gui->update_tool();
02428         }
02429 
02430         if(redraw_canvas)
02431         {
02432                 mwindow->gui->lock_window("CWindowCanvas::cursor_motion_event 1");
02433                 mwindow->gui->canvas->draw_overlays();
02434                 mwindow->gui->canvas->flash();
02435                 mwindow->gui->unlock_window();
02436         }
02437 
02438         if(rerender)
02439         {
02440                 mwindow->restart_brender();
02441                 mwindow->sync_parameters(CHANGE_PARAMS);
02442                 gui->cwindow->playback_engine->que->send_command(CURRENT_FRAME, 
02443                         CHANGE_NONE,
02444                         mwindow->edl,
02445                         1);
02446                 if(!redraw) gui->update_tool();
02447         }
02448         return result;
02449 }
02450 
02451 int CWindowCanvas::button_press_event()
02452 {
02453         int result = 0;
02454         int redraw = 0;
02455         int redraw_canvas = 0;
02456         int rerender = 0;
02457 
02458         if(Canvas::button_press_event()) return 1;
02459 
02460         gui->translating_zoom = gui->shift_down(); 
02461 
02462         calculate_origin();
02463 //printf("CWindowCanvas::button_press_event 2 %f %f\n", gui->x_origin, gui->y_origin, gui->x_origin, gui->y_origin);
02464 
02465         float zoom_x, zoom_y, conformed_w, conformed_h;
02466         get_zooms(mwindow->edl, 0, zoom_x, zoom_y, conformed_w, conformed_h);
02467         gui->x_offset = get_x_offset(mwindow->edl, 0, zoom_x, conformed_w, conformed_h);
02468         gui->y_offset = get_y_offset(mwindow->edl, 0, zoom_y, conformed_w, conformed_h);
02469 
02470 // Scroll view
02471         if(get_buttonpress() == 2)
02472         {
02473                 gui->current_operation = CWINDOW_SCROLL;
02474                 result = 1;
02475         }
02476         else
02477 // Adjust parameter
02478         {
02479                 switch(mwindow->edl->session->cwindow_operation)
02480                 {
02481                         case CWINDOW_CAMERA:
02482                                 result = test_bezier(1, redraw, redraw_canvas, rerender, 1);
02483                                 break;
02484 
02485                         case CWINDOW_PROJECTOR:
02486                                 result = test_bezier(1, redraw, redraw_canvas, rerender, 0);
02487                                 break;
02488 
02489                         case CWINDOW_ZOOM:
02490                                 result = test_zoom(redraw);
02491                                 break;
02492 
02493                         case CWINDOW_CROP:
02494                                 result = test_crop(1, redraw);
02495                                 break;
02496 
02497                         case CWINDOW_MASK:
02498                                 if(get_buttonpress() == 1)
02499                                         result = do_mask(redraw, rerender, 1, 0, 0);
02500                                 break;
02501 
02502                         case CWINDOW_EYEDROP:
02503                                 result = do_eyedrop(rerender, 1);
02504                                 break;
02505                 }
02506         }
02507 
02508         if(redraw)
02509         {
02510                 draw_refresh();
02511                 gui->update_tool();
02512         }
02513 
02514 // rerendering can also be caused by press event
02515         if(rerender) 
02516         {
02517                 mwindow->restart_brender();
02518                 mwindow->sync_parameters(CHANGE_PARAMS);
02519                 gui->cwindow->playback_engine->que->send_command(CURRENT_FRAME, 
02520                         CHANGE_NONE,
02521                         mwindow->edl,
02522                         1);
02523                 if(!redraw) gui->update_tool();
02524         }
02525         return result;
02526 }
02527 
02528 int CWindowCanvas::button_release_event()
02529 {
02530         int result = 0;
02531 
02532         switch(gui->current_operation)
02533         {
02534                 case CWINDOW_SCROLL:
02535                         result = 1;
02536                         break;
02537 
02538                 case CWINDOW_CAMERA:
02539                         mwindow->undo->update_undo(_("camera"), LOAD_AUTOMATION);
02540                         break;
02541 
02542                 case CWINDOW_PROJECTOR:
02543                         mwindow->undo->update_undo(_("projector"), LOAD_AUTOMATION);
02544                         break;
02545 
02546                 case CWINDOW_MASK:
02547                 case CWINDOW_MASK_CONTROL_IN:
02548                 case CWINDOW_MASK_CONTROL_OUT:
02549                 case CWINDOW_MASK_TRANSLATE:
02550                         mwindow->undo->update_undo(_("mask point"), LOAD_AUTOMATION);
02551                         break;
02552         }
02553 
02554         gui->current_operation = CWINDOW_NONE;
02555         return result;
02556 }
02557 
02558 void CWindowCanvas::zoom_resize_window(float percentage)
02559 {
02560         int canvas_w, canvas_h;
02561         calculate_sizes(mwindow->edl->get_aspect_ratio(), 
02562                 mwindow->edl->session->output_w, 
02563                 mwindow->edl->session->output_h, 
02564                 percentage,
02565                 canvas_w,
02566                 canvas_h);
02567         int new_w, new_h;
02568         new_w = canvas_w + (gui->get_w() - mwindow->theme->ccanvas_w);
02569         new_h = canvas_h + (gui->get_h() - mwindow->theme->ccanvas_h);
02570         gui->resize_window(new_w, new_h);
02571         gui->resize_event(new_w, new_h);
02572 }
02573 
02574 void CWindowCanvas::toggle_controls()
02575 {
02576         mwindow->session->cwindow_controls = !mwindow->session->cwindow_controls;
02577         gui->resize_event(gui->get_w(), gui->get_h());
02578 }
02579 
02580 int CWindowCanvas::get_cwindow_controls()
02581 {
02582         return mwindow->session->cwindow_controls;
02583 }
02584 
02585 
02586 

Generated on Sun Jan 8 13:38:51 2006 for Cinelerra-svn by  doxygen 1.4.4