X-Git-Url: http://git.cinelerra-gg.org/git/?p=goodguy%2Fhistory.git;a=blobdiff_plain;f=cinelerra-5.1%2Fcinelerra%2Ftrackcanvas.C;h=35c773b084501bf451c3da5b05dcde58b60efcc2;hp=3a5bdadeeb22e17f599c3562c862e3498b625d9d;hb=60f8df69db9ddd8148bfc41a17bb0955b52a45e6;hpb=30bdb85eb33a8ee7ba675038a86c6be59c43d7bd diff --git a/cinelerra-5.1/cinelerra/trackcanvas.C b/cinelerra-5.1/cinelerra/trackcanvas.C index 3a5bdade..35c773b0 100644 --- a/cinelerra-5.1/cinelerra/trackcanvas.C +++ b/cinelerra-5.1/cinelerra/trackcanvas.C @@ -26,7 +26,7 @@ #include "bcsignals.h" #include "bctimer.h" #include "clip.h" -#include "colors.h" +#include "bccolors.h" #include "cplayback.h" #include "cursors.h" #include "cwindowgui.h" @@ -38,6 +38,7 @@ #include "edlsession.h" #include "floatauto.h" #include "floatautos.h" +#include "gwindowgui.h" #include "indexstate.h" #include "intauto.h" #include "intautos.h" @@ -45,6 +46,7 @@ #include "keyframepopup.h" #include "keyframes.h" #include "keys.h" +#include "labels.h" #include "localsession.h" #include "mainclock.h" #include "maincursor.h" @@ -108,6 +110,7 @@ TrackCanvas::TrackCanvas(MWindow *mwindow, render_timer = new Timer; hourglass_enabled = 0; timebar_position = -1; + snapped = 0; } TrackCanvas::~TrackCanvas() @@ -185,7 +188,7 @@ int TrackCanvas::drag_motion(Track **over_track, int cursor_y = get_relative_cursor_y(); if( get_cursor_over_window() && - cursor_x >= 0 && cursor_y >= 0 && + cursor_x >= 0 && cursor_y >= 0 && cursor_x < get_w() && cursor_y < get_h() ) { //printf("TrackCanvas::drag_motion %d %d\n", __LINE__, pane->number); @@ -203,15 +206,24 @@ int TrackCanvas::drag_motion(Track **over_track, { int64_t edit_x, edit_y, edit_w, edit_h; edit_dimensions(edit, edit_x, edit_y, edit_w, edit_h); - - if(cursor_x >= edit_x && - cursor_y >= edit_y && - cursor_x < edit_x + edit_w && - cursor_y < edit_y + edit_h) - { + if( cursor_y < edit_y || cursor_y >= edit_y + edit_h ) continue; + if( cursor_x >= edit_x && cursor_x < edit_x + edit_w ) { *over_edit = edit; break; } + if( edit != track->edits->last ) continue; + if( mwindow->session->current_operation != DRAG_ATRANSITION && + mwindow->session->current_operation != DRAG_VTRANSITION ) continue; + if( !edit->silence() ) { + // add silence to allow drag transition past last edit + // will be deleted by Edits::optimize if not used + double length = mwindow->edl->session->default_transition_length; + int64_t start = edit->startproject+edit->length; + int64_t units = track->to_units(length, 1); + track->edits->create_silence(start, start+units); + continue; + } + if( cursor_x >= edit_x ) { *over_edit = edit; break; } } for(int i = 0; i < track->plugin_set.total; i++) @@ -244,7 +256,7 @@ int TrackCanvas::drag_motion(Track **over_track, } if( !*over_track ) - *over_track = pane->is_over_patchbay(); + *over_track = pane->over_patchbay(); return 0; } @@ -272,7 +284,7 @@ int TrackCanvas::drag_stop(int *redraw) (cursor_y = get_relative_cursor_y()) >= 0 && cursor_y < get_h() ) over_window = 1; else { - Track *track = pane->is_over_patchbay(); + Track *track = pane->over_patchbay(); if( track && mwindow->session->track_highlighted == track ) over_window = 1; } @@ -319,16 +331,28 @@ int TrackCanvas::drag_stop(int *redraw) if( hi_plugin_set && hi_plugin_set->track == drag_plugin->track ) { //printf("TrackCanvas::drag_stop 6\n"); drop_position = drop_plugin_position(hi_plugin_set, drag_plugin); - if( drop_position >= 0 ) - mwindow->move_effect(drag_plugin, hi_plugin_set, drop_position); + if( drop_position < 0 ) { + result = 1; + break; // Do not do anything + } + + Track *track = mwindow->session->track_highlighted; + drop_position = track->frame_align(drop_position, 0); + mwindow->move_effect(drag_plugin, hi_plugin_set, drop_position); result = 1; } else if( hi_track ) { // Put it in a new plugin set determined by an edit boundary, or at the start of the track Edit *hi_edit = mwindow->session->edit_highlighted; drop_position = hi_edit ? hi_edit->startproject : 0; - if( drop_position >= 0 ) - mwindow->move_effect(drag_plugin, hi_track, drop_position); + if( drop_position < 0 ) { + result = 1; + break; // Do not do anything + } + + Track *track = mwindow->session->track_highlighted; + drop_position = track->frame_align(drop_position, 0); + mwindow->move_effect(drag_plugin, hi_track, drop_position); result = 1; } } @@ -370,7 +394,7 @@ int TrackCanvas::drag_stop(int *redraw) length = mwindow->session->track_highlighted->from_units( mwindow->session->edit_highlighted->length); } - + start = mwindow->edl->align_to_frame(start, 0); mwindow->insert_effects_canvas(start, length); *redraw = 1; } @@ -382,8 +406,7 @@ int TrackCanvas::drag_stop(int *redraw) if(mwindow->session->track_highlighted) { double asset_duration = 0; int64_t asset_length_units = 0; - int64_t position = 0; - + if(mwindow->session->current_operation == DRAG_ASSET && mwindow->session->drag_assets->total) { Indexable *indexable = mwindow->session->drag_assets->values[0]; @@ -395,8 +418,8 @@ int TrackCanvas::drag_stop(int *redraw) if (video_length < 0) { if(mwindow->edl->session->si_useduration) video_length = mwindow->edl->session->si_duration; - else - video_length = 1.0 / mwindow->edl->session->frame_rate ; + else + video_length = 1.0 / mwindow->edl->session->frame_rate ; } asset_duration = video_length / indexable->get_frame_rate(); } @@ -418,25 +441,26 @@ int TrackCanvas::drag_stop(int *redraw) else { printf("DRAG_ASSET error: Asset dropped, but both drag_clips and drag_assets total is zero\n"); } - + asset_length_units = mwindow->session->track_highlighted->to_units(asset_duration, 1); - position = drop_edit_position (&insertion, NULL, asset_length_units); - if( position == -1 ) { + int64_t drop_position = drop_edit_position (&insertion, NULL, asset_length_units); + if( drop_position < 0 ) { result = 1; break; // Do not do anything } - - double position_f = mwindow->session->track_highlighted->from_units(position); + Track *track = mwindow->session->track_highlighted; + double track_position = track->from_units(drop_position); + track_position = mwindow->edl->align_to_frame(track_position, 0); // if (!insertion) { // // FIXME, we should create an mwindow/EDL method that overwrites, without clearing the keyframes and autos // // Unfortunately, this is _a lot_ of work to do right // printf("Problematic insertion\n"); -// mwindow->edl->tracks->clear(position_f, -// position_f + asset_duration, 0); +// mwindow->edl->tracks->clear(track_position, +// track_position + asset_duration, 0); // } - mwindow->paste_assets(position_f, track, !insertion); + mwindow->paste_assets(track_position, track, !insertion); result = 1; // need to be one no matter what, since we have track highlited so we have to cleanup.... } break; @@ -446,19 +470,18 @@ int TrackCanvas::drag_stop(int *redraw) if(mwindow->session->track_highlighted) { if( mwindow->session->track_highlighted->data_type == mwindow->session->drag_edit->track->data_type) { - int64_t position = 0; - position = drop_edit_position(&insertion, + int64_t drop_position = drop_edit_position(&insertion, mwindow->session->drag_edit, mwindow->session->drag_edit->length); - if (position == -1) { + if( drop_position < 0 ) { result = 1; break; // Do not do anything } - - double position_f = mwindow->session->track_highlighted->from_units(position); Track *track = mwindow->session->track_highlighted; + double track_position = track->from_units(drop_position); + track_position = mwindow->edl->align_to_frame(track_position, 0); mwindow->move_edits(mwindow->session->drag_edits, - track, position_f, !insertion); + track, track_position, !insertion); } result = 1; @@ -499,68 +522,67 @@ int64_t TrackCanvas::drop_edit_position(int *is_insertion, Edit *moved_edit, int Track *track = mwindow->session->track_highlighted; int cursor_x = get_relative_cursor_x(); double zoom_scale = (double)mwindow->edl->session->sample_rate / mwindow->edl->local_session->zoom_sample; - double drop_time = (cursor_x + mwindow->edl->local_session->view_start[pane->number]) / zoom_scale; - // we use cursor position for affinity calculations - int64_t cursor_position = track->to_units(drop_time, 0); - if( cursor_position <= 0 ) { + double cur_pos = (cursor_x + mwindow->edl->local_session->view_start[pane->number]) / zoom_scale; + double position = mwindow->edl->align_to_frame(cur_pos, 1); + if( position <= 0 ) { *is_insertion = 1; return 0; } - if( moved_edit ) // relative cursor position depends upon drop point - drop_time -= mwindow->session->drag_position - moved_edit->track->from_units(moved_edit->startproject); - int64_t drop_position = track->to_units(drop_time, 1); + double cursor_position = position; + int64_t drop_position = track->to_units(cursor_position, 1); + if( moved_edit ) { // relative cursor position depends upon drop point + double moved_edit_start = moved_edit->track->from_units(moved_edit->startproject); + position -= mwindow->session->drag_position - moved_edit_start; + } + int64_t edit_position = track->to_units(position, 1); + int64_t grab_position = edit_position; if( !moved_edit ) // for clips and assets acts as they were grabbed in the middle - drop_position -= moved_edit_length / 2; + grab_position -= moved_edit_length / 2; Edit *last_edit = track->edits->last; - if( !last_edit || drop_position > last_edit->startproject+last_edit->length ) { + if( !last_edit || edit_position >= (last_edit->startproject+last_edit->length) ) { *is_insertion = 0; - return drop_position; + return grab_position; } - int64_t drop_x0 = 0, drop_x1 = 0; // drop zone boundries - for( Edit *edit = track->edits->first; edit; ) { - int64_t edit_x0 = edit->startproject, edit_x1 = edit_x0 + edit->length; - if( Units::round(labs(edit_x0-cursor_position)*zoom_scale) < HANDLE_W ) { + int64_t drop_start = 0, drop_end = 0; // drop zone boundries + Edit *next_edit = track->edits->first; + while( next_edit ) { + Edit *edit = next_edit; next_edit = (Edit *)edit->next; + int64_t edit_start = edit->startproject; + int64_t edit_end = edit_start + edit->length; + double edit_start_pos = edit->track->from_units(edit_start); + if( (fabs(edit_start_pos-cursor_position)*zoom_scale) < HANDLE_W ) { *is_insertion = 1; // cursor is close to the beginning of an edit -> insertion - return edit->startproject; + return edit_start; } - if( Units::round(labs(edit_x1-cursor_position)*zoom_scale) < HANDLE_W ) { + double edit_end_pos = edit->track->from_units(edit_end); + if( (fabs(edit_end_pos-cursor_position)*zoom_scale) < HANDLE_W ) { *is_insertion = 1; // cursor is close to the end of an edit -> insertion - return edit->startproject + edit->length; + return edit_end; } if( edit != moved_edit && !edit->silence() ) - drop_x0 = edit_x1; // reset drop zone - if( (edit=edit->next) != 0 ) { - if( edit == moved_edit || edit->silence() ) continue; - drop_x1 = edit_x1; + drop_start = edit_end; // reset drop zone + if( next_edit ) { + if( next_edit == moved_edit || next_edit->silence() ) continue; + drop_end = edit_end; } else - drop_x1 = INT64_MAX; -//printf("drop cursor=%jd, x0=%jd, x1=%jd\n", cursor_position, drop_x0, drop_x1); - if( drop_position >= drop_x0 && drop_position+moved_edit_length < drop_x1 ) { + drop_end = INT64_MAX; + if( edit_position >= drop_start && + edit_position+moved_edit_length < drop_end ) { *is_insertion = 0; // fits in the zone -//printf("into %jd\n", drop_position); - return drop_position; + return edit_position; } - if( cursor_position < drop_x1 ) { // drop in the zone - if( (drop_x1-drop_x0) >= moved_edit_length ) { + if( drop_position < drop_end ) { // drop in the zone + if( (drop_end - drop_start) >= moved_edit_length ) { *is_insertion = 0; // fits in the zone, but over the edge - int64_t dx0 = llabs(cursor_position-drop_x0); - int64_t dx1 = llabs(cursor_position-drop_x1); -//printf("onto %jd\n", dx0 < dx1 ? drop_x0 : drop_x1 - moved_edit_length); - return dx0 < dx1 ? drop_x0 : drop_x1 - moved_edit_length; - } - int edit_center = (edit_x0+edit_x1) / 2; - if( cursor_position < edit_center ) { - *is_insertion = 1; -//printf("snap left %jd\n", drop_x0); - return drop_x0; // snap left - } - else { - *is_insertion = 1; -//printf("snap right %jd\n", drop_x1); - return drop_x1; // snap right + int64_t dx0 = llabs(drop_position - drop_start); + int64_t dx1 = llabs(drop_position - drop_end); + return dx0 < dx1 ? drop_start : drop_end - moved_edit_length; } + *is_insertion = 1; + int64_t edit_center = (edit_start + edit_end) / 2; + return position < edit_center ? drop_start : drop_end; } } @@ -572,39 +594,47 @@ int64_t TrackCanvas::drop_plugin_position(PluginSet *plugin_set, Plugin *moved_p { // get the canvas/track position Track *track = plugin_set->track; + double moved_plugin_length = moved_plugin->track->from_units(moved_plugin->length); + int64_t track_plugin_length = track->to_units(moved_plugin_length, 0); int cursor_x = get_relative_cursor_x(); double zoom_scale = (double)mwindow->edl->session->sample_rate / mwindow->edl->local_session->zoom_sample; - double drop_time = (cursor_x + mwindow->edl->local_session->view_start[pane->number]) / zoom_scale; - // we use cursor position for affinity calculations - int64_t cursor_position = track->to_units(drop_time, 0); - if( cursor_position <= 0 ) return 0; - drop_time -= mwindow->session->drag_position - moved_plugin->track->from_units(moved_plugin->startproject); - int64_t drop_position = track->to_units(drop_time, 1); + double cur_pos = (cursor_x + mwindow->edl->local_session->view_start[pane->number]) / zoom_scale; + double position = mwindow->edl->align_to_frame(cur_pos, 1); + if( position <= 0 ) return 0; + int64_t drop_position = track->to_units(position, 1); Plugin *last_plugin = (Plugin *)plugin_set->last; - if( !last_plugin || drop_position > last_plugin->startproject+last_plugin->length ) { - return drop_position; - } - - int64_t drop_x0 = 0, drop_x1 = 0; // drop zone boundries - for( Plugin *plugin = (Plugin *)plugin_set->first; plugin; ) { - int64_t plugin_x0 = plugin->startproject, plugin_x1 = plugin_x0 + plugin->length; + if( !last_plugin ) return drop_position; + double plugin_set_end = last_plugin->track->from_units(last_plugin->startproject+last_plugin->length); + if( position >= plugin_set_end ) return drop_position; + double moved_plugin_start = moved_plugin->track->from_units(moved_plugin->startproject); + position -= mwindow->session->drag_position - moved_plugin_start; + int64_t plugin_position = track->to_units(position, 1); + + int64_t drop_start = 0, drop_end = 0; // drop zone boundries + Plugin *next_plugin = (Plugin *)plugin_set->first; + while( next_plugin ) { + Plugin *plugin = next_plugin; next_plugin = (Plugin *)plugin->next; + int64_t plugin_start = plugin->startproject; + int64_t plugin_end = plugin_start + plugin->length; + double plugin_end_pos = plugin->track->from_units(plugin_end); + int64_t track_plugin_end = track->to_units(plugin_end_pos, 0); if( plugin != moved_plugin && !plugin->silence() ) - drop_x0 = plugin_x1; - if( (plugin=(Plugin *)plugin->next) != 0 ) { - if( plugin == moved_plugin || plugin->silence() ) continue; - drop_x1 = plugin_x1; + drop_start = track_plugin_end; + if( next_plugin ) { + if( next_plugin == moved_plugin || next_plugin->silence() ) continue; + drop_end = track_plugin_end; } else - drop_x1 = INT64_MAX; - if( drop_position >= drop_x0 && // fits in the zone - drop_position+moved_plugin->length < drop_x1 ) { - return drop_position; + drop_end = INT64_MAX; + if( plugin_position >= drop_start && // fits in the zone + plugin_position+track_plugin_length < drop_end ) { + return plugin_position; } - if( cursor_position < drop_x1 ) { // drop in the zone - if( (drop_x1-drop_x0) >= moved_plugin->length ) { - int64_t dx0 = llabs(cursor_position-drop_x0); - int64_t dx1 = llabs(cursor_position-drop_x1); - return dx0 < dx1 ? drop_x0 : drop_x1 - moved_plugin->length; + if( drop_position < drop_end ) { // drop in the zone + if( (drop_end - drop_start) >= track_plugin_length ) { + int64_t dx0 = llabs(drop_position - drop_start); + int64_t dx1 = llabs(drop_position - drop_end); + return dx0 < dx1 ? drop_start : drop_end - track_plugin_length; } } } @@ -619,12 +649,12 @@ void TrackCanvas::draw(int mode, int hide_cursor) // Swap pixmap layers - if(get_w() != background_pixmap->get_w() || - get_h() != background_pixmap->get_h()) - { - delete background_pixmap; - background_pixmap = new BC_Pixmap(this, get_w(), get_h()); - } + if(get_w() != background_pixmap->get_w() || + get_h() != background_pixmap->get_h()) + { + delete background_pixmap; + background_pixmap = new BC_Pixmap(this, get_w(), get_h()); + } // Cursor disappears after resize when this is called. // Cursor doesn't redraw after editing when this isn't called. @@ -662,17 +692,11 @@ void TrackCanvas::test_timer() void TrackCanvas::draw_indexes(Indexable *indexable) { + IndexState *index_state = indexable->index_state; // Don't redraw raw samples - IndexState *index_state = 0; - index_state = indexable->index_state; - - if(index_state->index_zoom > mwindow->edl->local_session->zoom_sample) return; - - draw_resources(0, 1, indexable); - draw_overlays(); flash(0); } @@ -1013,7 +1037,7 @@ void TrackCanvas::draw_paste_destination() int has_audio = 0, has_video = 0; double paste_audio_length = 0, paste_video_length = 0; - double paste_audio_position = -1, paste_video_position = -1; + double paste_audio_position = -1, paste_video_position = -1; if( indexable ) { has_audio = indexable->have_audio(); @@ -1088,9 +1112,9 @@ void TrackCanvas::draw_paste_destination() } // Get the x coordinate - x = Units::to_int64(position * + x = Units::to_int64(position * mwindow->edl->session->sample_rate / - mwindow->edl->local_session->zoom_sample) - + mwindow->edl->local_session->zoom_sample) - mwindow->edl->local_session->view_start[pane->number]; double paste_position = -1.; @@ -1124,6 +1148,7 @@ void TrackCanvas::draw_paste_destination() from_units(drop_edit_position(&insertion, mwindow->session->drag_edit, mwindow->session->drag_edit->length)); + current_aedit++; } } if( paste_position >= 0 ) { @@ -1166,6 +1191,7 @@ void TrackCanvas::draw_paste_destination() from_units(drop_edit_position(&insertion, mwindow->session->drag_edit, mwindow->session->drag_edit->length)); + current_vedit++; } } if( paste_position >= 0 ) { @@ -1187,10 +1213,6 @@ void TrackCanvas::draw_paste_destination() int h = dest->vertical_span(mwindow->theme); //printf("TrackCanvas::draw_paste_destination 2 %d %d %d %d\n", x, y, w, h); - if (insertion) - draw_highlight_insertion(x, y, w, h); - else - draw_highlight_rectangle(x, y, w, h); if(x < -BC_INFINITY) { w -= -BC_INFINITY - x; x += -BC_INFINITY - x; @@ -1199,7 +1221,10 @@ void TrackCanvas::draw_paste_destination() // if(pane->number == TOP_RIGHT_PANE) // printf("TrackCanvas::draw_paste_destination %d %d %d %d %d\n", // __LINE__, x, y, w, h); - draw_highlight_rectangle(x, y, w, h); + if (insertion) + draw_highlight_insertion(x, y, w, h); + else + draw_highlight_rectangle(x, y, w, h); } } } @@ -1267,7 +1292,7 @@ void TrackCanvas::draw_highlight_rectangle(int x, int y, int w, int h) h = MIN(h, get_h() + 20); if(w > 0 && h > 0) { - set_color(WHITE); + set_color(mwindow->preferences->highlight_inverse); set_inverse(); //draw_rectangle(x, y, w, h); draw_rectangle(x + 1, y + 1, w - 2, h - 2); @@ -1329,7 +1354,7 @@ void TrackCanvas::draw_highlight_insertion(int x, int y, int w, int h) } w = MIN(w, get_w() + 20); h = MIN(h, get_h() + 20); - set_color(WHITE); + set_color(mwindow->preferences->highlight_inverse); set_inverse(); draw_rectangle(x, y, w, h); draw_rectangle(x + 1, y + 1, w - 2, h - 2); @@ -1584,7 +1609,7 @@ void TrackCanvas::draw_plugins() char string[BCTEXTLEN]; int current_on = 0; int current_show = 0; - + int current_preset = 0; // if(!mwindow->edl->session->show_assets) goto done; @@ -1592,6 +1617,8 @@ void TrackCanvas::draw_plugins() plugin_on_toggles.values[i]->in_use = 0; for(int i = 0; i < plugin_show_toggles.total; i++) plugin_show_toggles.values[i]->in_use = 0; + for(int i = 0; i < preset_edit_buttons.total; i++) + plugin_show_toggles.values[i]->in_use = 0; for(Track *track = mwindow->edl->tracks->first; @@ -1699,9 +1726,21 @@ void TrackCanvas::draw_plugins() } current_show++; } - - - + toggle_x -= PluginPresetEdit::calculate_w(mwindow) + 10; + if(toggle_x > min_x) + { + if(current_preset >= preset_edit_buttons.total) + { + PluginPresetEdit *preset_edit = new PluginPresetEdit(mwindow, toggle_x, toggle_y, plugin); + add_subwindow(preset_edit); + preset_edit_buttons.append(preset_edit); + } + else + { + preset_edit_buttons.values[current_preset]->update(toggle_x, toggle_y, plugin); + } + current_preset++; + } } } } @@ -1711,6 +1750,10 @@ void TrackCanvas::draw_plugins() // Remove unused toggles + while(current_preset < preset_edit_buttons.total) + { + preset_edit_buttons.remove_object_number(current_preset); + } while(current_show < plugin_show_toggles.total) { plugin_show_toggles.remove_object_number(current_show); @@ -1720,7 +1763,6 @@ void TrackCanvas::draw_plugins() { plugin_on_toggles.remove_object_number(current_on); } - } void TrackCanvas::refresh_plugintoggles() @@ -1735,6 +1777,41 @@ void TrackCanvas::refresh_plugintoggles() PluginShow *show = plugin_show_toggles.values[i]; show->reposition_window(show->get_x(), show->get_y()); } + for(int i = 0; i < preset_edit_buttons.total; i++) + { + PluginPresetEdit *preset_edit = preset_edit_buttons.values[i]; + preset_edit->reposition_window(preset_edit->get_x(), preset_edit->get_y()); + } +} + +void TrackCanvas::draw_hard_edges() +{ + int64_t x, y, w, h; + +// if(!mwindow->edl->session->show_assets) return; + + for(Track *track = mwindow->edl->tracks->first; track; track = track->next) { + for(Edit *edit = track->edits->first; edit; edit = edit->next) { + if( !edit->hard_left && !edit->hard_right ) continue; + edit_dimensions(edit, x, y, w, h); + set_color(GREEN); + set_opaque(); int y1 = y+h-1; + if( edit->hard_left ) { + ArrayList xpt, ypt; + xpt.append(x); ypt.append(y1); + xpt.append(x+HANDLE_W); ypt.append(y1); + xpt.append(x); ypt.append(y1-HANDLE_H); + fill_polygon(&xpt, &ypt); + } + if( edit->hard_right ) { + ArrayList xpt, ypt; int x1 = x+w-1; + xpt.append(x1); ypt.append(y1); + xpt.append(x1-HANDLE_W); ypt.append(y1); + xpt.append(x1); ypt.append(y1-HANDLE_H); + fill_polygon(&xpt, &ypt); + } + } + } } void TrackCanvas::draw_inout_points() @@ -1753,7 +1830,7 @@ void TrackCanvas::draw_drag_handle() mwindow->edl->local_session->zoom_sample - mwindow->edl->local_session->view_start[pane->number]); //printf("TrackCanvas::draw_drag_handle 2 %d %jd\n", pane->number, pixel1); - set_color(GREEN); + set_color(!snapped ? GREEN : (snapped=0, YELLOW)); set_inverse(); //printf("TrackCanvas::draw_drag_handle 3\n"); draw_line(pixel1, 0, pixel1, get_h()); @@ -1842,41 +1919,36 @@ void TrackCanvas::draw_loop_points() //printf("TrackCanvas::draw_loop_points 7\n"); } -void TrackCanvas::draw_brender_start() +void TrackCanvas::draw_brender_range() { - if(mwindow->preferences->use_brender) + if( !mwindow->preferences->use_brender || !mwindow->brender_active ) return; + if( mwindow->edl->session->brender_start >= mwindow->edl->session->brender_end ) return; + if( mwindow->edl->session->brender_end > 0 ) { - int64_t x = Units::round(mwindow->edl->session->brender_start * + int64_t x1 = Units::round(mwindow->edl->session->brender_start * + mwindow->edl->session->sample_rate / + mwindow->edl->local_session->zoom_sample - + mwindow->edl->local_session->view_start[pane->number]); + if(MWindowGUI::visible(x1, x1 + 1, 0, get_w())) + { + set_color(RED); + draw_line(x1, 0, x1, get_h()); + } + int64_t x2 = Units::round(mwindow->edl->session->brender_end * mwindow->edl->session->sample_rate / mwindow->edl->local_session->zoom_sample - mwindow->edl->local_session->view_start[pane->number]); - if(MWindowGUI::visible(x, x + 1, 0, get_w())) + if(MWindowGUI::visible(x2, x2 + 1, 0, get_w())) { set_color(RED); - draw_line(x, 0, x, get_h()); + draw_line(x2, 0, x2, get_h()); } } } -static int auto_colors[AUTOMATION_TOTAL] = -{ - BLUE, - RED, - GREEN, - BLUE, - RED, - GREEN, - BLUE, - WHITE, - 0, - 0, - 0, - WHITE -}; - // The operations which correspond to each automation type -static int auto_operations[AUTOMATION_TOTAL] = +int TrackCanvas::auto_operations[AUTOMATION_TOTAL] = { DRAG_MUTE, DRAG_CAMERA_X, @@ -1940,7 +2012,7 @@ int TrackCanvas::do_keyframes(int cursor_x, for(Track *track = mwindow->edl->tracks->first; track && !result; track = track->next) { - Auto *auto_keyframe = 0; + Auto *auto_keyframe = 0; Automation *automation = track->automation; @@ -1976,25 +2048,25 @@ int TrackCanvas::do_keyframes(int cursor_x, int grouptype = automation.autogrouptype(i, track); if(draw) // Do dropshadow result = do_float_autos(track, autos, - cursor_x, cursor_y, draw, + cursor_x, cursor_y, draw, buttonpress, 1, 1, MDGREY, auto_keyframe, grouptype); result = do_float_autos(track, autos, - cursor_x, cursor_y, draw, - buttonpress, 0, 0, auto_colors[i], + cursor_x, cursor_y, draw, buttonpress, + 0, 0, GWindowGUI::auto_colors[i], auto_keyframe, grouptype); break; } case Autos::AUTOMATION_TYPE_INT: { if(draw) // Do dropshadow result = do_int_autos(track, autos, - cursor_x, cursor_y, draw, + cursor_x, cursor_y, draw, buttonpress, 1, 1, MDGREY, auto_keyframe); result = do_int_autos(track, autos, - cursor_x, cursor_y, draw, - buttonpress, 0, 0, auto_colors[i], + cursor_x, cursor_y, draw, buttonpress, + 0, 0, GWindowGUI::auto_colors[i], auto_keyframe); break; } } @@ -2014,7 +2086,7 @@ int TrackCanvas::do_keyframes(int cursor_x, { if (buttonpress != 3) { - if(i == AUTOMATION_FADE) + if(i == AUTOMATION_FADE || i == AUTOMATION_SPEED) synchronize_autos(0, track, (FloatAuto*)mwindow->session->drag_auto, @@ -2031,6 +2103,12 @@ int TrackCanvas::do_keyframes(int cursor_x, gui->keyframe_menu->activate_menu(); rerender = 1; // the position changes } + else if( autos ) + { + gui->keyframe_hide->update(autos); + gui->keyframe_hide->activate_menu(); + rerender = 1; // the position changes + } if(buttonpress == 1 && ctrl_down() && AUTOMATION_TYPE_FLOAT == autos->get_type()) rerender = 1; // special case: curve mode changed @@ -2085,6 +2163,45 @@ int TrackCanvas::do_keyframes(int cursor_x, return result; } +void TrackCanvas::draw_keyframe_reticle() +{ + int keyframe_hairline = mwindow->preferences->keyframe_reticle; + if( keyframe_hairline == HAIRLINE_NEVER ) return; + + int current_op = mwindow->session->current_operation, dragging = 0; + for( int i=0; !dragging && isession->drag_auto && get_buttonpress() == 1 ) { + draw_hairline(mwindow->session->drag_auto, RED); + return; + } + } + + if( keyframe_hairline == HAIRLINE_ALWAYS || ( get_buttonpress() == 2 && + keyframe_hairline == HAIRLINE_DRAGGING && dragging ) ) { + for( Track *track = mwindow->edl->tracks->first; track; + track=track->next ) { + Automation *automation = track->automation; + for( int i=0; iedl->session->auto_conf->autos[i] ) continue; + // automation visible + Autos *autos = automation->autos[i]; + if( !autos ) continue; + for( Auto *auto_keyframe=autos->first; auto_keyframe; + auto_keyframe = auto_keyframe->next ) { + draw_hairline(auto_keyframe, BLUE); + } + } + + if( dragging && mwindow->session->drag_auto ) { + draw_hairline(mwindow->session->drag_auto, RED); + } + } + } +} + void TrackCanvas::draw_auto(Auto *current, int x, int y, @@ -2152,14 +2269,14 @@ void TrackCanvas::draw_cropped_line(int x1, } -void TrackCanvas::draw_floatauto(FloatAuto *current, - int x, - int y, - int in_x, - int in_y, - int out_x, - int out_y, - int center_pixel, +void TrackCanvas::draw_floatauto(FloatAuto *current, + int x, + int y, + int in_x, + int in_y, + int out_x, + int out_y, + int center_pixel, int zoom_track, int color) { @@ -2180,7 +2297,7 @@ void TrackCanvas::draw_floatauto(FloatAuto *current, draw_box(x1, y1, x2 - x1, y2 - y1); } -// show bezier control points (only) if this +// show bezier control points (only) if this // floatauto doesn't adjust it's tangents automatically if(current->curve_mode != FloatAuto::FREE && current->curve_mode != FloatAuto::TFREE) @@ -2208,22 +2325,22 @@ inline void TrackCanvas::draw_floatauto_ctrlpoint( y += center_pixel; cp_y += center_pixel; - + // drawing the tangent as a dashed line... int const dash = HANDLE_W; int const gap = HANDLE_W / 2; float sx = 3 * (cp_x - x) / 4.; float ex = 0; - + // q is the x displacement for a unit line of slope float q = (sx > 0 ? 1 : -1) / sqrt(1 + slope * slope); - + float dist = 1/q * sx; if( dist > dash ) ex = sx - q * dash; - + set_color(color); - do { + do { float sy = slope * sx, ey = slope * ex; draw_line(quantize(sx + x), quantize(sy + y), quantize(ex + x), quantize(ey + y)); sx = ex - q * gap; @@ -2306,13 +2423,12 @@ inline float test_curve_line( int x0, int y0, int ctrl_x, int ctrl_y, } -inline +inline float levered_position(float position, float ref_pos) { - if( 1e-6 > fabs(ref_pos) || isnan(ref_pos)) + if( 1e-6 > fabs(ref_pos) || isnan(ref_pos)) return 0.0; - else - return ref_pos / position; + return ref_pos / position; } @@ -2324,16 +2440,15 @@ float TrackCanvas::value_to_percentage(float auto_value, int autogrouptype) float automation_min = mwindow->edl->local_session->automation_mins[autogrouptype]; float automation_max = mwindow->edl->local_session->automation_maxs[autogrouptype]; float automation_range = automation_max - automation_min; - if(0 == automation_range || isnan(auto_value) || isinf(auto_value)) + if( 0 >= automation_range || isnan(auto_value) || isinf(auto_value) ) return 0; - else - return (auto_value - automation_min) / automation_range; + return (auto_value - automation_min) / automation_range; } int TrackCanvas::test_floatauto(FloatAuto *current, int x, int y, int in_x, - int in_y, int out_x, int out_y, int center_pixel, int zoom_track, + int in_y, int out_x, int out_y, int center_pixel, int zoom_track, int cursor_x, int cursor_y, int buttonpress, int autogrouptype) { int result = 0; @@ -2384,7 +2499,7 @@ int TrackCanvas::test_floatauto(FloatAuto *current, int x, int y, int in_x, if( WITHIN(x1,x2,y1,y2)) { // cursor hits node result = 1; - + if(buttonpress && (buttonpress != 3)) { INIT_DRAG(current->position, value_to_percentage(current->get_value(), autogrouptype)) @@ -2401,13 +2516,13 @@ int TrackCanvas::test_floatauto(FloatAuto *current, int x, int y, int in_x, // could be ctrl-click or ctrl-drag // click would cycle through tangent modes ((FloatAuto*)current)->toggle_curve_mode(); - + // drag will start dragging the tangent, if applicable INIT_DRAG(current->position, value_to_percentage(current->get_value(), autogrouptype)) mwindow->session->drag_handle = 0; } } - + float lever = 0.0; // we use the tangent as a draggable lever. 1.0 is at the ctrl point // Test in control @@ -2456,15 +2571,15 @@ int TrackCanvas::test_floatauto(FloatAuto *current, int x, int y, int in_x, #undef WITHIN #undef INIT_DRAG -// if(buttonpress) -// printf("TrackCanvas::test_floatauto 2 drag_handle=%d ctrl_down=%d cursor_x=%d cursor_y=%d x1=%d x2=%d y1=%d y2=%d\n", +// if(buttonpress) +// printf("TrackCanvas::test_floatauto 2 drag_handle=%d ctrl_down=%d cursor_x=%d cursor_y=%d x1=%d x2=%d y1=%d y2=%d\n", // mwindow->session->drag_handle, // ctrl_down(), // cursor_x, // cursor_y, // x1, x2, y1, y2); if(buttonpress && (buttonpress != 3) && result) - { + { mwindow->undo->update_undo_before(); } @@ -2508,7 +2623,7 @@ void TrackCanvas::draw_floatline(int center_pixel, // Not using slope intercept x1 = MAX(0, x1); - int prev_y = y1; + int prev_y = y1 + center_pixel; // Call by reference fails for some reason here @@ -2531,6 +2646,7 @@ void TrackCanvas::draw_floatline(int center_pixel, // (int)(center_pixel - yscale / 2), // (int)(center_pixel + yscale / 2 - 1)); +//printf("draw_line(%d,%d, %d,%d)\n", x - 1, prev_y , x, y); draw_line(x - 1, prev_y , x, y ); } prev_y = y; @@ -2580,7 +2696,10 @@ int TrackCanvas::test_floatline(int center_pixel, { Auto *current; mwindow->undo->update_undo_before(); - current = mwindow->session->drag_auto = autos->insert_auto(position1); + double position = autos->track->from_units(position1); + position = mwindow->edl->align_to_frame(position, 0); + int64_t new_position = autos->track->to_units(position,0); + current = mwindow->session->drag_auto = autos->insert_auto(new_position); ((FloatAuto*)current)->set_value(value); mwindow->session->drag_start_percentage = value_to_percentage(value, autogrouptype); mwindow->session->drag_start_position = current->position; @@ -2596,71 +2715,62 @@ int TrackCanvas::test_floatline(int center_pixel, void TrackCanvas::synchronize_autos(float change, - Track *skip, - FloatAuto *fauto, - int fill_gangs) + Track *skip, FloatAuto *fauto, int fill_gangs) { // Handles the special case of modifying a fadeauto // when there are ganged faders on several tracks // (skip and fauto may be NULL if fill_gangs==-1) - if (fill_gangs == 1 && skip->gang) - { - for(Track *current = mwindow->edl->tracks->first; - current; - current = NEXT) - { - if(current->data_type == skip->data_type && - current->gang && - current->record && - current != skip) - { - FloatAutos *fade_autos = (FloatAutos*)current->automation->autos[AUTOMATION_FADE]; - double position = skip->from_units(fauto->position); - FloatAuto *previous = 0, *next = 0; - - float init_value = fade_autos->get_value(fauto->position, PLAY_FORWARD, previous, next); - FloatAuto *keyframe; - keyframe = (FloatAuto*)fade_autos->get_auto_at_position(position); - if (!keyframe) - { + if( fill_gangs > 0 && skip->gang ) { + double position = skip->from_units(fauto->position); + int autoidx = fauto->autos->autoidx; + + for(Track *current = mwindow->edl->tracks->first; current; current = NEXT) { + if( (current->data_type == skip->data_type || get_double_click()) && + current->gang && current->record && current != skip ) { + int64_t current_position = current->to_units(position, 1); + FloatAutos *fade_autos = (FloatAutos*)current->automation->autos[autoidx]; + float auto_min = mwindow->edl->local_session->automation_mins[fade_autos->autogrouptype]; + float auto_max = mwindow->edl->local_session->automation_maxs[fade_autos->autogrouptype]; + FloatAuto *previous = 0, *next = 0; + FloatAuto *keyframe = (FloatAuto*)fade_autos->get_auto_at_position(current_position); + if( !keyframe ) { // create keyframe on neighbouring track at the point in time given by fauto - keyframe = (FloatAuto*)fade_autos->insert_auto(fauto->position); - keyframe->set_value(init_value + change); + float init_value = fade_autos->get_value(current_position, PLAY_FORWARD, previous, next); + float new_value = init_value + change; + CLAMP(new_value, auto_min, auto_max); + keyframe = (FloatAuto*)fade_autos->insert_auto(current_position); + keyframe->set_value(new_value); } - else - { + else { // keyframe exists, just change it - keyframe->adjust_to_new_coordinates(fauto->position, keyframe->get_value() + change); + float new_value = keyframe->get_value() + change; + CLAMP(new_value, auto_min, auto_max); + keyframe->adjust_to_new_coordinates(current_position, new_value); // need to (re)set the position, as the existing node could be on a "equivalent" position (within half a frame) } mwindow->session->drag_auto_gang->append((Auto *)keyframe); } } - } else -// move the gangs - if (fill_gangs == 0) - { -// Move the gang! - for (int i = 0; i < mwindow->session->drag_auto_gang->total; i++) - { + } + else if( !fill_gangs ) { + double position = skip->from_units(fauto->position); +// Move the gangs + for (int i = 0; i < mwindow->session->drag_auto_gang->total; i++) { FloatAuto *keyframe = (FloatAuto *)mwindow->session->drag_auto_gang->values[i]; - + int64_t keyframe_position = keyframe->autos->track->to_units(position, 1); float new_value = keyframe->get_value() + change; CLAMP(new_value, mwindow->edl->local_session->automation_mins[keyframe->autos->autogrouptype], mwindow->edl->local_session->automation_maxs[keyframe->autos->autogrouptype]); - keyframe->adjust_to_new_coordinates(fauto->position, new_value); + keyframe->adjust_to_new_coordinates(keyframe_position, new_value); } } - else + else { // remove the gangs - if (fill_gangs == -1) - { - for (int i = 0; i < mwindow->session->drag_auto_gang->total; i++) - { + for (int i = 0; i < mwindow->session->drag_auto_gang->total; i++) { FloatAuto *keyframe = (FloatAuto *)mwindow->session->drag_auto_gang->values[i]; keyframe->autos->remove_nonsequential( keyframe); @@ -2842,7 +2952,6 @@ int TrackCanvas::do_float_autos(Track *track, Autos *autos, int cursor_x, int cu double view_start, unit_start; double view_end, unit_end, yscale; double zoom_sample, zoom_units; - double ax, ay, ax2, ay2, ax0, ay0; double in_x2, in_y2, out_x2, out_y2; double slope; //int skip = 0; @@ -2857,25 +2966,24 @@ int TrackCanvas::do_float_autos(Track *track, Autos *autos, int cursor_x, int cu // Get first auto before start Auto *current = 0, *previous = 0; - ax0 = ay0 = -1; for( current = autos->last; current && current->position >= unit_start; current = PREVIOUS ) ; - if( !current ) { - current = autos->first ? autos->first : autos->default_auto; - ax0 = 0; - } - if( current ) { + Auto *first_auto = current ? current : + autos->first ? autos->first : autos->default_auto; + + double ax = 0, ay = 0, ax2 = 0, ay2 = 0; + if( first_auto ) { calculate_auto_position(&ax, &ay, 0, 0, 0, 0, - current, unit_start, zoom_units, yscale, autogrouptype); - if( ax0 < 0 ) current = NEXT; + first_auto, unit_start, zoom_units, yscale, autogrouptype); + } + if( current ) + current = NEXT; + else { + current = autos->first; + ax = 0; } - else - ay0 = 0; - - if( ax0 >= 0 ) ax = ax0; - if( ay0 >= 0 ) ay = ay0; do { //skip = 0; @@ -2891,17 +2999,15 @@ int TrackCanvas::do_float_autos(Track *track, Autos *autos, int cursor_x, int cu //skip = 1; } - slope = (ay2 - ay) / (ax2 - ax); + slope = ax2 > ax ? (ay2 - ay) / (ax2 - ax) : 0; - if(ax2 > get_w()) - { + if(ax2 > get_w()) { draw_auto = 0; ax2 = get_w(); ay2 = ay + slope * (get_w() - ax); } - if(ax < 0) - { + if(ax < 0) { ay = ay + slope * (0 - ax); ax = 0; } @@ -2954,7 +3060,7 @@ int TrackCanvas::do_float_autos(Track *track, Autos *autos, int cursor_x, int cu (int)ax, (int)ax2, cursor_x, cursor_y, buttonpress, autogrouptype); } - if( draw ) + if( draw ) draw_floatline(center_pixel, (FloatAuto*)previous, (FloatAuto*)current, (FloatAutos*)autos, unit_start, zoom_units, yscale, @@ -3336,6 +3442,28 @@ int TrackCanvas::do_plugin_autos(Track *track, int cursor_x, int cursor_y, return result; } +int TrackCanvas::draw_hairline(Auto *auto_keyframe, int color) +{ + Track *track = auto_keyframe->autos->track; + int autogrouptype = auto_keyframe->autos->get_type(); + + int center_pixel; + double view_start, unit_start; + double view_end, unit_end, yscale; + double zoom_sample, zoom_units; + + calculate_viewport(track, view_start, unit_start, view_end, unit_end, + yscale, center_pixel, zoom_sample, zoom_units); + + double ax = 0, ay = 0; + calculate_auto_position(&ax, &ay, 0, 0, 0, 0, + auto_keyframe, unit_start, zoom_units, yscale, autogrouptype); + + set_color(color); + draw_line(ax, 0, ax, get_h()); + return 0; +} + void TrackCanvas::draw_overlays() { int new_cursor, update_cursor, rerender; @@ -3357,10 +3485,11 @@ void TrackCanvas::draw_overlays() // Plugins draw_plugins(); + draw_hard_edges(); // Loop points draw_loop_points(); - draw_brender_start(); + draw_brender_range(); // Highlighted areas draw_highlighting(); @@ -3377,6 +3506,8 @@ void TrackCanvas::draw_overlays() // Playback cursor draw_playback_cursor(); + draw_keyframe_reticle(); + show_window(0); } @@ -3409,15 +3540,46 @@ int TrackCanvas::deactivate() void TrackCanvas::update_drag_handle() { double new_position; + int cursor_x = get_cursor_x(); new_position = - (double)(get_cursor_x() + + (double)(cursor_x + mwindow->edl->local_session->view_start[pane->number]) * mwindow->edl->local_session->zoom_sample / mwindow->edl->session->sample_rate; + new_position = mwindow->edl->align_to_frame(new_position, 0); + if( ctrl_down() && alt_down() ) { +#define snapper(v) do { \ + double pos = (v); \ + if( pos < 0 ) break; \ + double dist = fabs(new_position - pos); \ + if( dist >= snap_min ) break; \ + snap_position = pos; snap_min = dist; \ +} while(0) + double snap_position = new_position; + double snap_min = DBL_MAX; + if( mwindow->edl->local_session->inpoint_valid() ) + snapper(mwindow->edl->local_session->get_inpoint()); + if( mwindow->edl->local_session->outpoint_valid() ) + snapper(mwindow->edl->local_session->get_outpoint()); + snapper(mwindow->edl->prev_edit(new_position)); + snapper(mwindow->edl->next_edit(new_position)); + Label *prev_label = mwindow->edl->labels->prev_label(new_position); + if( prev_label ) snapper(prev_label->position); + Label *next_label = mwindow->edl->labels->next_label(new_position); + if( next_label ) snapper(next_label->position); + int snap_x = snap_position * mwindow->edl->session->sample_rate / + mwindow->edl->local_session->zoom_sample - + mwindow->edl->local_session->view_start[pane->number]; + if( abs(snap_x - cursor_x) < HANDLE_W ) { + snapped = 1; + new_position = snap_position; + } +#undef snapper + } if(new_position != mwindow->session->drag_position) { @@ -3489,36 +3651,22 @@ int TrackCanvas::get_drag_values(float *percentage, #define UPDATE_DRAG_HEAD(do_clamp) \ - int result = 0; \ + int result = 0, center_pixel; \ if(!current->autos->track->record) return 0; \ - double view_start; \ - double unit_start; \ - double view_end; \ - double unit_end; \ - double yscale; \ - int center_pixel; \ - double zoom_sample; \ - double zoom_units; \ + double view_start, unit_start, view_end, unit_end; \ + double yscale, zoom_sample, zoom_units; \ \ calculate_viewport(current->autos->track, \ - view_start, \ - unit_start, \ - view_end, \ - unit_end, \ - yscale, \ - center_pixel, \ - zoom_sample, \ - zoom_units); \ + view_start, unit_start, view_end, unit_end, \ + yscale, center_pixel, zoom_sample, zoom_units); \ \ float percentage = (float)(mwindow->session->drag_origin_y - cursor_y) / \ - yscale + \ - mwindow->session->drag_start_percentage; \ + yscale + mwindow->session->drag_start_percentage; \ if(do_clamp) CLAMP(percentage, 0, 1); \ \ int64_t position = Units::to_int64(zoom_units * \ (cursor_x - mwindow->session->drag_origin_x) + \ mwindow->session->drag_start_position); \ - \ if((do_clamp) && position < 0) position = 0; @@ -3527,119 +3675,99 @@ int TrackCanvas::update_drag_floatauto(int cursor_x, int cursor_y) FloatAuto *current = (FloatAuto*)mwindow->session->drag_auto; UPDATE_DRAG_HEAD(mwindow->session->drag_handle == 0); - int x = cursor_x - mwindow->session->drag_origin_x; \ - int y = cursor_y - mwindow->session->drag_origin_y; \ - - float value; - float old_value; + int x = cursor_x - mwindow->session->drag_origin_x; + int y = cursor_y - mwindow->session->drag_origin_y; + float value, old_value; + + if( mwindow->session->drag_handle == 0 && (ctrl_down() && !shift_down()) ) { +// not really editing the node, rather start editing the curve +// tangent is editable and drag movement is significant + if( (FloatAuto::FREE == current->curve_mode || + FloatAuto::TFREE==current->curve_mode) && + (fabs(x) > HANDLE_W / 2 || fabs(y) > HANDLE_W / 2)) + mwindow->session->drag_handle = x < 0 ? 1 : 2; + } - switch(mwindow->session->drag_handle) - { -// Center - case 0: - if(ctrl_down()) - // not really editing the node, rather start editing the curve - { - // tangent is editable and drag movement is significant - if( (FloatAuto::FREE == current->curve_mode || - FloatAuto::TFREE==current->curve_mode) && - (fabs(x) > HANDLE_W / 2 || fabs(y) > HANDLE_W / 2)) - mwindow->session->drag_handle = x < 0 ? 1 : 2; - break; - } + switch(mwindow->session->drag_handle) { + case 0: // Center // Snap to nearby values - old_value = current->get_value(); - if(shift_down()) - { - double value1; - double distance1; - double value2; - double distance2; - - if(current->previous) - { - int autogrouptype = current->previous->autos->autogrouptype; - value = percentage_to_value(percentage, 0, 0, autogrouptype); - value1 = ((FloatAuto*)current->previous)->get_value(); - distance1 = fabs(value - value1); - current->set_value(value1); - } + old_value = current->get_value(); + if(shift_down()) { + double value1, value2, distance1, distance2; - if(current->next) - { - int autogrouptype = current->next->autos->autogrouptype; - value = percentage_to_value(percentage, 0, 0, autogrouptype); - value2 = ((FloatAuto*)current->next)->get_value(); - distance2 = fabs(value - value2); - if(!current->previous || distance2 < distance1) - { - current->set_value(value2); - } - } + if(current->previous) { + int autogrouptype = current->previous->autos->autogrouptype; + value = percentage_to_value(percentage, 0, 0, autogrouptype); + value1 = ((FloatAuto*)current->previous)->get_value(); + distance1 = fabs(value - value1); + current->set_value(value1); + } - if(!current->previous && !current->next) - { - current->set_value( ((FloatAutos*)current->autos)->default_); + if(current->next) { + int autogrouptype = current->next->autos->autogrouptype; + value = percentage_to_value(percentage, 0, 0, autogrouptype); + value2 = ((FloatAuto*)current->next)->get_value(); + distance2 = fabs(value - value2); + if(!current->previous || distance2 < distance1) { + current->set_value(value2); } - value = current->get_value(); } - else - { - int autogrouptype = current->autos->autogrouptype; - value = percentage_to_value(percentage, 0, 0, autogrouptype); + + if(!current->previous && !current->next) { + current->set_value( ((FloatAutos*)current->autos)->default_); } + value = current->get_value(); + } + else { + int autogrouptype = current->autos->autogrouptype; + value = percentage_to_value(percentage, 0, 0, autogrouptype); + } - if(alt_down()) + if(alt_down() && !shift_down()) // ALT constrains movement: fixed position, only changing the value - position = mwindow->session->drag_start_position; + position = mwindow->session->drag_start_position; - if(value != old_value || position != current->position) - { - result = 1; - float change = value - old_value; - current->adjust_to_new_coordinates(position, value); - synchronize_autos(change, current->autos->track, current, 0); - show_message(current, 1,", %.2f", current->get_value()); - } - break; + if(value != old_value || position != current->position) { + result = 1; + float change = value - old_value; + current->adjust_to_new_coordinates(position, value); + synchronize_autos(change, current->autos->track, current, 0); + show_message(current, 1,", %.2f", current->get_value()); + } + break; // In control - case 1: + case 1: { + int autogrouptype = current->autos->autogrouptype; + value = percentage_to_value(percentage, 0, current, autogrouptype); + if(value != current->get_control_in_value()) { - int autogrouptype = current->autos->autogrouptype; - value = percentage_to_value(percentage, 0, current, autogrouptype); - if(value != current->get_control_in_value()) - { - result = 1; - // note: (position,value) need not be at the location of the ctrl point, - // but could be somewhere in between on the curve (or even outward or - // on the opposit side). We set the new control point such as - // to point the curve through (position,value) - current->set_control_in_value( - value * levered_position(position - current->position, - current->get_control_in_position())); - synchronize_autos(0, current->autos->track, current, 0); - show_message(current, 1,", %.2f", current->get_control_in_value()); - } + result = 1; + // note: (position,value) need not be at the location of the ctrl point, + // but could be somewhere in between on the curve (or even outward or + // on the opposit side). We set the new control point such as + // to point the curve through (position,value) + current->set_control_in_value( + value * levered_position(position - current->position, + current->get_control_in_position())); + synchronize_autos(0, current->autos->track, current, 0); + show_message(current, 1,", %.2f", current->get_control_in_value()); } - break; + break; } // Out control - case 2: - { - int autogrouptype = current->autos->autogrouptype; - value = percentage_to_value(percentage, 0, current, autogrouptype); - if(value != current->get_control_out_value()) - { - result = 1; - current->set_control_out_value( - value * levered_position(position - current->position, - current->get_control_out_position())); - synchronize_autos(0, current->autos->track, current, 0); - show_message(current, 1,", %.2f", current->get_control_out_value()); - } + case 2: { + int autogrouptype = current->autos->autogrouptype; + value = percentage_to_value(percentage, 0, current, autogrouptype); + if(value != current->get_control_out_value()) { + result = 1; + current->set_control_out_value( + value * levered_position(position - current->position, + current->get_control_out_position())); + synchronize_autos(0, current->autos->track, current, 0); + show_message(current, 1,", %.2f", current->get_control_out_value()); } - break; + break; } } return result; @@ -3678,7 +3806,7 @@ int TrackCanvas::update_drag_auto(int cursor_x, int cursor_y) double position_f = current->autos->track->from_units(current->position); double center_f = (mwindow->edl->local_session->get_selectionstart(1) + - mwindow->edl->local_session->get_selectionend(1)) / + mwindow->edl->local_session->get_selectionend(1)) / 2; if(!shift_down()) { @@ -3710,7 +3838,7 @@ int TrackCanvas::update_drag_pluginauto(int cursor_x, int cursor_y) //PluginAutos *pluginautos = (PluginAutos *)current->autos; PluginSet *pluginset; Plugin *plugin = 0; -// figure out the correct pluginset & correct plugin +// figure out the correct pluginset & correct plugin int found = 0; for(int i = 0; i < track->plugin_set.total; i++) { @@ -3722,16 +3850,16 @@ int TrackCanvas::update_drag_pluginauto(int cursor_x, int cursor_y) currentkeyframe; currentkeyframe = (KeyFrame *) currentkeyframe->next) { - if (currentkeyframe == current) + if (currentkeyframe == current) { found = 1; break; } - + } - if (found) break; + if (found) break; } - if (found) break; + if (found) break; } mwindow->session->plugin_highlighted = plugin; @@ -3742,7 +3870,7 @@ int TrackCanvas::update_drag_pluginauto(int cursor_x, int cursor_y) double position_f = current->autos->track->from_units(current->position); double center_f = (mwindow->edl->local_session->get_selectionstart(1) + - mwindow->edl->local_session->get_selectionend(1)) / + mwindow->edl->local_session->get_selectionend(1)) / 2; if(!shift_down()) { @@ -3767,7 +3895,7 @@ void TrackCanvas::update_drag_caption() switch(mwindow->session->current_operation) { case DRAG_FADE: - + break; } } @@ -4217,53 +4345,58 @@ int TrackCanvas::do_edit_handles(int cursor_x, int cursor_y, int button_press, int &rerender, int &update_overlay, int &new_cursor, int &update_cursor) { Edit *edit_result = 0; - int handle_result = 0; + int handle_result = -1; int result = 0; - if(!mwindow->edl->session->show_assets) return 0; + if( !mwindow->edl->session->show_assets ) return 0; - for(Track *track = mwindow->edl->tracks->first; - track && !result; - track = track->next) { - for(Edit *edit = track->edits->first; - edit && !result; - edit = edit->next) { + for( Track *track=mwindow->edl->tracks->first; track && !result; track=track->next) { + for( Edit *edit=track->edits->first; edit && !result; edit=edit->next ) { int64_t edit_x, edit_y, edit_w, edit_h; edit_dimensions(edit, edit_x, edit_y, edit_w, edit_h); - if(cursor_x >= edit_x && cursor_x <= edit_x + edit_w && - cursor_y >= edit_y && cursor_y < edit_y + edit_h) { - if(cursor_x < edit_x + HANDLE_W) { + if( cursor_x >= edit_x && cursor_x <= edit_x + edit_w && + cursor_y >= edit_y && cursor_y < edit_y + edit_h ) { + if( cursor_x < edit_x + HANDLE_W ) { edit_result = edit; handle_result = 0; - result = 1; + if( cursor_y >= edit_y+edit_h - HANDLE_W ) { + new_cursor = DOWNLEFT_RESIZE; + if( button_press == LEFT_BUTTON ) + result = -1; + } + else + result = 1; } - else if(cursor_x >= edit_x + edit_w - HANDLE_W) { + else if( cursor_x >= edit_x + edit_w - HANDLE_W ) { edit_result = edit; handle_result = 1; - result = 1; - } - else { - result = 0; + if( cursor_y >= edit_y+edit_h - HANDLE_W ) { + new_cursor = DOWNRIGHT_RESIZE; + if( button_press == LEFT_BUTTON ) + result = -1; + } + else + result = 1; } } } } update_cursor = 1; - if(result) { + if( result > 0 ) { double position = 0; - if(handle_result == 0) { + if( handle_result == 0 ) { position = edit_result->track->from_units(edit_result->startproject); new_cursor = LEFT_CURSOR; } - else if(handle_result == 1) { + else if( handle_result == 1 ) { position = edit_result->track->from_units(edit_result->startproject + edit_result->length); new_cursor = RIGHT_CURSOR; } // Reposition cursor - if(button_press) { + if( button_press ) { mwindow->session->drag_edit = edit_result; mwindow->session->drag_handle = handle_result; mwindow->session->drag_button = get_buttonpress() - 1; @@ -4277,6 +4410,49 @@ int TrackCanvas::do_edit_handles(int cursor_x, int cursor_y, int button_press, update_overlay = 1; } } + else if( result < 0) { + mwindow->undo->update_undo_before(); + if( !shift_down() ) { + if( handle_result == 0 ) + edit_result->hard_left = !edit_result->hard_left; + else if( handle_result == 1 ) + edit_result->hard_right = !edit_result->hard_right; + } + else { + int status = handle_result == 0 ? edit_result->hard_left : + handle_result == 1 ? edit_result->hard_right : 0; + int new_status = !status; + int64_t edit_edge = edit_result->startproject; + if( handle_result == 1 ) edit_edge += edit_result->length; + double edge_position = edit_result->track->from_units(edit_edge); + for( Track *track=mwindow->edl->tracks->first; track!=0; track=track->next ) { + int64_t track_position = track->to_units(edge_position, 1); + Edit *left_edit = track->edits->editof(track_position, PLAY_FORWARD, 0); + if( left_edit ) { + int64_t left_edge = left_edit->startproject; + double left_position = track->from_units(left_edge); + if( EQUIV(edge_position, left_position) ) { + left_edit->hard_left = new_status; + if( left_edit->previous ) + left_edit->previous->hard_right = new_status; + } + } + Edit *right_edit = track->edits->editof(track_position, PLAY_REVERSE, 0); + if( right_edit ) { + int64_t right_edge = right_edit->startproject + right_edit->length; + double right_position = track->from_units(right_edge); + if( EQUIV(edge_position, right_position) ) { + right_edit->hard_right = new_status; + if( right_edit->next ) + right_edit->next->hard_left = new_status; + } + } + } + } + rerender = update_overlay = 1; + mwindow->undo->update_undo_after(_("hard_edge"), LOAD_EDITS); + result = 1; + } return result; } @@ -4369,7 +4545,7 @@ int TrackCanvas::do_tracks(int cursor_x, int cursor_y, int button_press) int64_t track_x, track_y, track_w, track_h; track_dimensions(track, track_x, track_y, track_w, track_h); - if(button_press && get_buttonpress() == 3 && + if(button_press && get_buttonpress() == RIGHT_BUTTON && cursor_y >= track_y && cursor_y < track_y + track_h) { gui->edit_menu->update(track, 0); gui->edit_menu->activate_menu(); @@ -4445,10 +4621,10 @@ int TrackCanvas::do_edits(int cursor_x, int cursor_y, int button_press, int drag mwindow->edl->local_session->zoom_sample / mwindow->edl->session->sample_rate; + int cx, cy; + get_abs_cursor(cx, cy); gui->drag_popup = new BC_DragWindow(gui, - mwindow->theme->get_image("clip_icon") /*, - get_abs_cursor_x(0) - mwindow->theme->get_image("clip_icon")->get_w() / 2, - get_abs_cursor_y(0) - mwindow->theme->get_image("clip_icon")->get_h() / 2 */); + mwindow->theme->get_image("clip_icon"), cx, cy); result = 1; } @@ -4557,19 +4733,18 @@ int TrackCanvas::do_plugins(int cursor_x, int cursor_y, int drag_start, frame = mwindow->theme->get_image("veffect_icon"); } } - - gui->drag_popup = new BC_DragWindow(gui, frame /*, - get_abs_cursor_x(0) - frame->get_w() / 2, - get_abs_cursor_y(0) - frame->get_h() / 2 */); + int cx, cy; + get_abs_cursor(cx, cy); + gui->drag_popup = new BC_DragWindow(gui, frame, cx, cy); break; } case PLUGIN_SHAREDPLUGIN: - case PLUGIN_SHAREDMODULE: - gui->drag_popup = new BC_DragWindow(gui, - mwindow->theme->get_image("clip_icon") /*, - get_abs_cursor_x(0) - mwindow->theme->get_image("clip_icon")->get_w() / 2, - get_abs_cursor_y(0) - mwindow->theme->get_image("clip_icon")->get_h() / 2 */); - break; + case PLUGIN_SHAREDMODULE: { + VFrame *frame = mwindow->theme->get_image("clip_icon"); + int cx, cy; + get_abs_cursor(cx, cy); + gui->drag_popup = new BC_DragWindow(gui, frame, cx, cy); + break; } } result = 1; @@ -4648,9 +4823,7 @@ int TrackCanvas::button_press_event() } if( get_buttonpress() == LEFT_BUTTON ) { - gui->unlock_window(); - gui->mbuttons->transport->handle_transport(STOP, 1, 0, 0); - gui->lock_window("TrackCanvas::button_press_event"); + gui->stop_transport("TrackCanvas::button_press_event"); } int update_overlay = 0, update_cursor = 0, rerender = 0; @@ -4691,8 +4864,7 @@ int TrackCanvas::button_press_event() switch(mwindow->edl->session->editing_mode) { // Test handles and resource boundaries and highlight a track case EDITING_ARROW: { - if( mwindow->edl->session->auto_conf->transitions && - do_transitions(cursor_x, cursor_y, + if( do_transitions(cursor_x, cursor_y, 1, new_cursor, update_cursor) ) break; if( do_keyframes(cursor_x, cursor_y, @@ -4731,8 +4903,7 @@ int TrackCanvas::button_press_event() mwindow->edl->session->sample_rate; //printf("TrackCanvas::button_press_event %d\n", position); - if(mwindow->edl->session->auto_conf->transitions && - do_transitions(cursor_x, cursor_y, + if( do_transitions(cursor_x, cursor_y, 1, new_cursor, update_cursor)) break; if(do_keyframes(cursor_x, cursor_y, 0, get_buttonpress(), new_cursor, @@ -4754,6 +4925,7 @@ int TrackCanvas::button_press_event() if( do_tracks(cursor_x, cursor_y, 1) ) break; // Highlight selection + if( get_buttonpress() != LEFT_BUTTON ) break; rerender = start_selection(position); mwindow->session->current_operation = SELECT_REGION; update_cursor = 1; @@ -4773,31 +4945,32 @@ int TrackCanvas::button_press_event() if( update_overlay ) { gui->draw_overlays(1); } - - if( update_cursor > 0 ) { + if( update_cursor < 0 ) { +// double_click edit + gui->swindow->update_selection(); + } + if( update_cursor ) { gui->update_timebar(0); gui->hide_cursor(0); gui->show_cursor(1); gui->zoombar->update(); gui->flash_canvas(1); } - else if(update_cursor < 0) { - gui->swindow->update_selection(); - } } + return result; } int TrackCanvas::start_selection(double position) { int rerender = 0; - position = mwindow->edl->align_to_frame(position, 0); + position = mwindow->edl->align_to_frame(position, 1); // Extend a border if(shift_down()) { - double midpoint = (mwindow->edl->local_session->get_selectionstart(1) + + double midpoint = (mwindow->edl->local_session->get_selectionstart(1) + mwindow->edl->local_session->get_selectionend(1)) / 2; if(position < midpoint) @@ -4824,7 +4997,7 @@ int TrackCanvas::start_selection(double position) // Que the CWindow rerender = 1; } - + return rerender; } @@ -4841,8 +5014,8 @@ void TrackCanvas::end_pluginhandle_selection() double TrackCanvas::time_visible() { - return (double)get_w() * - mwindow->edl->local_session->zoom_sample / + return (double)get_w() * + mwindow->edl->local_session->zoom_sample / mwindow->edl->session->sample_rate; } @@ -4856,7 +5029,7 @@ void TrackCanvas::show_message(Auto *current, int show_curve_type, const char *f FloatAuto::curve_name(((FloatAuto*)current)->curve_mode)); } char string2[BCTEXTLEN]; - Units::totext(string2, + Units::totext(string2, current->autos->track->from_units(current->position), mwindow->edl->session->time_format, mwindow->edl->session->sample_rate, @@ -4884,7 +5057,7 @@ void TrackCanvas::show_message(Auto *current, int show_curve_type, const char *f // else // return gui->pane[BOTTOM_LEFT_PANE]->patchbay; // } -// +// // return 0; // }