// curve_mode is ignored, no recalculations
}
+// exactly equals
+int FloatAuto::equals(FloatAuto *that)
+{
+ return this->value == that->value &&
+ this->control_in_value == that->control_in_value &&
+ this->control_out_value == that->control_out_value &&
+ this->control_in_position == that->control_in_position &&
+ this->control_out_position == that->control_out_position &&
+ this->curve_mode == that->curve_mode;
+}
+
+
/* Note: the following is essentially display-code and has been moved to:
* TrackCanvas::value_to_percentage(float auto_value, int autogrouptype)
*
int operator==(Auto &that);
int operator==(FloatAuto &that);
int identical(FloatAuto *src);
+ int equals(FloatAuto *src);
void copy_from(Auto *that);
void copy_from(FloatAuto *that);
int interpolate_from(Auto *a1, Auto *a2, int64_t pos, Auto *templ=0); // bezier interpolation
length += start;
start = 0;
}
- int64_t end = start + length;
- double value = 0, track_length = track->get_length();
- int64_t pos = start, len = track->to_units(track_length,0);
- if( end > len ) end = len;
+ double value = 0;
+ int64_t pos = start, len = length, end = pos + len;
while( pos < end ) {
- int64_t prev_pos = 0, next_pos = len;
+ int64_t prev_pos = 0, next_pos = end;
Auto *zprev = 0, *znext = 0;
FloatAuto *prev = (FloatAuto*)get_prev_auto(pos, direction, zprev, 0);
if( prev ) prev_pos = prev->position;
return value + 1e-6;
}
+int64_t FloatAutos::speed_position(double pos)
+{
+ double length = track->get_length();
+ int64_t l = -1, r = track->to_units(length, 1);
+ if( r < 1 ) r = 1;
+ for( int i=32; --i >= 0 && automation_integral(0,r,PLAY_FORWARD) <= pos; r*=2 );
+ for( int i=64; --i >= 0 && (r-l)>1; ) {
+ int64_t m = (l + r) / 2;
+ double t = automation_integral(0,m,PLAY_FORWARD) - pos;
+ *(t >= 0 ? &r : &l) = m;
+ }
+ return r;
+}
+
void set_automation_mode(int64_t start, int64_t end, int mode);
void set_proxy(int orig_scale, int new_scale);
double automation_integral(int64_t start, int64_t length, int direction);
+ int64_t speed_position(double pos);
void dump();
Auto* new_auto();
key_speed_patch->mwindow->get_float_auto(key_speed_patch->patch, AUTOMATION_SPEED)->get_value())
{
this->key_speed_patch = key_speed_patch;
+ key_speed_patch->mwindow->speed_before();
set_precision(0.01);
}
int KeySpeedValue::button_release_event()
{
BC_FSlider::button_release_event();
+ key_speed_patch->mwindow->speed_after(1);
+ key_speed_patch->mwindow->resync_guis();
return 0;
}
mwindow->undo->update_undo_before(_("speed"), need_undo ? 0 : this);
FloatAuto *current = (FloatAuto*)speed_autos->get_auto_for_editing(position);
current->set_value(get_value());
- mwindow->undo->update_undo_after(_("speed"), LOAD_AUTOMATION);
+ mwindow->undo->update_undo_after(_("speed"), LOAD_AUTOMATION+LOAD_EDITS);
}
int KeySpeedValue::handle_event()
restart_status = 0;
screens = 1;
in_destructor = 0;
+ speed_edl = 0;
}
commit_commercial();
if( commercials && !commercials->remove_user() ) commercials = 0;
close_mixers();
-
+ if( speed_edl ) { speed_edl->remove_user(); speed_edl = 0; }
// Save defaults for open plugins
plugin_gui_lock->lock("MWindow::~MWindow");
for(int i = 0; i < plugin_guis->size(); i++) {
static Commercials *commercials;
int commercial_active;
int has_commercials();
+// copy of edl created in speed_before, used in speed_after to normalize_speed
+ EDL *speed_edl;
// Menu items
ArrayList<ColormodelItem*> colormodels;
void commit_commercial();
void undo_commercial();
void cut_commercials();
+ void update_gui(int changed_edl);
int paste_subtitle_text(char *text, double start, double end);
void init_error();
void init_commercials();
static void add_plugins(ArrayList<PluginServer*> &plugins);
static void delete_plugins();
+ void speed_before();
+ int speed_after(int done);
+ int normalize_speed(EDL *old_edl, EDL *new_edl);
//
void clean_indexes();
// TimeBomb timebomb;
}
}
+void MWindow::update_gui(int changed_edl)
+{
+ restart_brender();
+ update_plugin_guis();
+ if( changed_edl ) {
+ gui->update(1, 2, 1, 1, 1, 1, 0);
+ cwindow->update(1, 0, 0, 0, 1);
+ cwindow->refresh_frame(CHANGE_EDL);
+ }
+ else {
+ gui->draw_overlays(1);
+ sync_parameters(CHANGE_PARAMS);
+ gui->update_patchbay();
+ cwindow->update(1, 0, 0);
+ }
+}
+
void MWindow::set_automation_mode(int mode)
{
undo->update_undo_before();
+ speed_before();
edl->tracks->set_automation_mode(
edl->local_session->get_selectionstart(),
edl->local_session->get_selectionend(),
mode);
+ int changed_edl = speed_after(1);
save_backup();
char string[BCSTRLEN];
sprintf(string,"set %s", FloatAuto::curve_name(mode));
undo->update_undo_after(string, LOAD_AUTOMATION);
-
- restart_brender();
- update_plugin_guis();
- gui->draw_overlays(1);
- sync_parameters(CHANGE_PARAMS);
- gui->update_patchbay();
- cwindow->update(1, 0, 0);
+ update_gui(changed_edl);
}
void MWindow::clear_automation()
{
undo->update_undo_before();
+ speed_before();
edl->tracks->clear_automation(edl->local_session->get_selectionstart(),
edl->local_session->get_selectionend());
+ int changed_edl = speed_after(1);
save_backup();
undo->update_undo_after(_("clear keyframes"), LOAD_AUTOMATION);
-
- restart_brender();
- update_plugin_guis();
- gui->draw_overlays(1);
- sync_parameters(CHANGE_PARAMS);
- gui->update_patchbay();
- cwindow->update(1, 0, 0);
+ update_gui(changed_edl);
}
int MWindow::clear_default_keyframe()
{
undo->update_undo_before();
+ speed_before();
edl->tracks->clear_default_keyframe();
+ int changed_edl = speed_after(1);
save_backup();
undo->update_undo_after(_("clear default keyframe"), LOAD_AUTOMATION);
-
- restart_brender();
- gui->draw_overlays(1);
- sync_parameters(CHANGE_PARAMS);
- gui->update_patchbay();
- cwindow->update(1, 0, 0);
-
+ update_gui(changed_edl);
return 0;
}
int MWindow::cut_automation()
{
undo->update_undo_before();
-
+ speed_before();
copy_automation();
-
edl->tracks->clear_automation(edl->local_session->get_selectionstart(),
edl->local_session->get_selectionend());
+ int changed_edl = speed_after(1);
save_backup();
undo->update_undo_after(_("cut keyframes"), LOAD_AUTOMATION);
-
-
- restart_brender();
- update_plugin_guis();
- gui->draw_overlays(1);
- sync_parameters(CHANGE_PARAMS);
- gui->update_patchbay();
- cwindow->update(1, 0, 0);
+ update_gui(changed_edl);
return 0;
}
{
undo->update_undo_before();
+ speed_before();
copy_default_keyframe();
edl->tracks->clear_default_keyframe();
- undo->update_undo_after(_("cut default keyframe"), LOAD_AUTOMATION);
-
- restart_brender();
- gui->draw_overlays(1);
- sync_parameters(CHANGE_PARAMS);
- gui->update_patchbay();
- cwindow->update(1, 0, 0);
+ int changed_edl = speed_after(1);
save_backup();
-
-
+ undo->update_undo_after(_("cut default keyframe"), LOAD_AUTOMATION);
+ update_gui(changed_edl);
return 0;
}
if( len ) {
undo->update_undo_before();
+ speed_before();
char *string = new char[len];
gui->from_clipboard(string, len, BC_PRIMARY_SELECTION);
FileXML file;
edl->tracks->clear_automation(start, end);
edl->tracks->paste_automation(start, &file, 0, 1,
edl->session->typeless_keyframes);
+ int changed_edl = speed_after(1);
save_backup();
undo->update_undo_after(_("paste keyframes"), LOAD_AUTOMATION);
delete [] string;
-
- restart_brender();
- update_plugin_guis();
- gui->draw_overlays(1);
- sync_parameters(CHANGE_PARAMS);
- gui->update_patchbay();
- cwindow->update(1, 0, 0);
+ update_gui(changed_edl);
}
return 0;
if( len ) {
undo->update_undo_before();
+ speed_before();
char *string = new char[len];
gui->from_clipboard(string, len, BC_PRIMARY_SELECTION);
FileXML file;
edl->session->typeless_keyframes);
// edl->tracks->paste_default_keyframe(&file);
undo->update_undo_after(_("paste default keyframe"), LOAD_AUTOMATION);
-
- restart_brender();
- update_plugin_guis();
- gui->draw_overlays(1);
- sync_parameters(CHANGE_PARAMS);
- gui->update_patchbay();
- cwindow->update(1, 0, 0);
- delete [] string;
+ int changed_edl = speed_after(1);
save_backup();
+ delete [] string;
+ update_gui(changed_edl);
}
return 0;
cwindow->refresh_frame(CHANGE_EDL);
}
+int MWindow::normalize_speed(EDL *old_edl, EDL *new_edl)
+{
+ int result = 0;
+ Track *old_track = old_edl->tracks->first;
+ Track *new_track = new_edl->tracks->first;
+ for( ; old_track && new_track; old_track=old_track->next, new_track=new_track->next ) {
+ if( old_track->data_type != new_track->data_type ) continue;
+ FloatAutos *old_speeds = (FloatAutos *)old_track->automation->autos[AUTOMATION_SPEED];
+ FloatAutos *new_speeds = (FloatAutos *)new_track->automation->autos[AUTOMATION_SPEED];
+ if( !old_speeds || !new_speeds ) continue;
+ FloatAuto *old_speed = (FloatAuto *)old_speeds->first;
+ FloatAuto *new_speed = (FloatAuto *)new_speeds->first;
+ while( old_speed && new_speed && old_speed->equals(new_speed) ) {
+ old_speed = (FloatAuto *)old_speed->next;
+ new_speed = (FloatAuto *)new_speed->next;
+ }
+ Edit *old_edit = old_track->edits->first;
+ Edit *new_edit = new_track->edits->first;
+ for( ; old_edit && new_edit; old_edit=old_edit->next, new_edit=new_edit->next ) {
+ int64_t edit_start = old_edit->startproject, edit_end = edit_start + old_edit->length;
+ if( old_speed || new_speed ) {
+ double orig_start = old_speeds->automation_integral(0, edit_start, PLAY_FORWARD);
+ double orig_end = old_speeds->automation_integral(0, edit_end, PLAY_FORWARD);
+ edit_start = new_speeds->speed_position(orig_start);
+ edit_end = new_speeds->speed_position(orig_end);
+ result = 1;
+ }
+ new_edit->startproject = edit_start;
+ new_edit->length = edit_end - edit_start;
+ }
+ }
+ return result;
+}
+
+void MWindow::speed_before()
+{
+ if( !speed_edl ) {
+ speed_edl = new EDL;
+ speed_edl->create_objects();
+ }
+ speed_edl->copy_all(edl);
+}
+
+int MWindow::speed_after(int done)
+{
+ int result = 0;
+ if( speed_edl && done >= 0 )
+ result = normalize_speed(speed_edl, edl);
+ if( done ) {
+ speed_edl->remove_user();
+ speed_edl = 0;
+ }
+ return result;
+}
case Autos::AUTOMATION_TYPE_FLOAT: {
Automation automation(0, track);
int grouptype = automation.autogrouptype(i, track);
+ if( buttonpress && i == AUTOMATION_SPEED ) {
+ mwindow->speed_before();
+ }
+
if(draw) // Do dropshadow
result = do_float_autos(track, autos,
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, GWindowGUI::auto_colors[i],
auto_keyframe, grouptype);
+
+ if( !result && buttonpress && i == AUTOMATION_SPEED )
+ mwindow->speed_after(-1);
+ int current_grouptype = mwindow->edl->local_session->zoombar_showautotype;
+ if( result && buttonpress && grouptype != current_grouptype ) {
+ mwindow->edl->local_session->zoombar_showautotype = grouptype;
+ mwindow->gui->zoombar->update_autozoom();
+ }
break; }
case Autos::AUTOMATION_TYPE_INT: {
-int TrackCanvas::cursor_motion_event()
+int TrackCanvas::cursor_update(int in_motion)
{
int result = 0;
int cursor_x = 0;
int new_cursor = 0;
int rerender = 0;
double position = 0.;
-//printf("TrackCanvas::cursor_motion_event %d\n", __LINE__);
+//printf("TrackCanvas::cursor_update %d\n", __LINE__);
// Default cursor
switch(mwindow->edl->session->editing_mode)
case DRAG_PROJECTOR_Z:
if(active) rerender = update_overlay =
update_drag_floatauto(get_cursor_x(), get_cursor_y());
+ if( rerender && mwindow->session->current_operation == DRAG_SPEED )
+ mwindow->speed_after(!in_motion ? 1 : 0);
break;
case DRAG_PLAY:
start != mwindow->edl->local_session->get_selectionstart(1) ? 1 :
end != mwindow->edl->local_session->get_selectionend(1) ? -1 : 0;
mwindow->cwindow->update(dir, 0, 0, 0, 1);
- gui->lock_window("TrackCanvas::cursor_motion_event 1");
+ gui->lock_window("TrackCanvas::cursor_update 1");
// Update the faders
mwindow->update_plugin_guis();
gui->update_patchbay();
for(int i = 0; i < TOTAL_PANES; i++)
if(gui->pane[i]) gui->pane[i]->canvas->timebar_position = position;
-//printf("TrackCanvas::cursor_motion_event %d %d %p %p\n", __LINE__, pane->number, pane, pane->timebar);
+//printf("TrackCanvas::cursor_update %d %d %p %p\n", __LINE__, pane->number, pane, pane->timebar);
gui->update_timebar(0);
// Update cursor
if(do_transitions(get_cursor_x(), get_cursor_y(),
break;
}
-//printf("TrackCanvas::cursor_motion_event 1\n");
+//printf("TrackCanvas::cursor_update 1\n");
if(update_cursor && new_cursor != get_cursor())
{
set_cursor(new_cursor, 0, 1);
}
-//printf("TrackCanvas::cursor_motion_event 1 %d\n", rerender);
+//printf("TrackCanvas::cursor_update 1 %d\n", rerender);
if(rerender && render_timer->get_difference() > 0.25 ) {
render_timer->update();
mwindow->restart_brender();
mwindow->update_plugin_guis();
gui->unlock_window();
mwindow->cwindow->update(1, 0, 0, 0, 1);
- gui->lock_window("TrackCanvas::cursor_motion_event 2");
+ gui->lock_window("TrackCanvas::cursor_update 2");
}
if(rerender) {
// Update faders
gui->draw_overlays(1);
}
-//printf("TrackCanvas::cursor_motion_event %d\n", __LINE__);
+//printf("TrackCanvas::cursor_update %d\n", __LINE__);
return result;
}
+int TrackCanvas::cursor_motion_event()
+{
+ return cursor_update(1);
+}
+
void TrackCanvas::start_dragscroll()
{
if(!drag_scroll) {
int TrackCanvas::button_release_event()
{
- int redraw = 0, update_overlay = 0, result = 0;
+ int redraw = -1, update_overlay = 0;
+ int result = 0, load_flags = 0;
// printf("TrackCanvas::button_release_event %d\n",
// mwindow->session->current_operation);
result = 1;
break;
- case DRAG_FADE:
case DRAG_SPEED:
+ redraw = FORCE_REDRAW;
+ load_flags |= LOAD_EDITS;
+ case DRAG_FADE:
// delete the drag_auto_gang first and remove out of order keys
synchronize_autos(0, 0, 0, -1);
case DRAG_CZOOM:
case DRAG_PROJECTOR_Y:
case DRAG_PROJECTOR_Z:
case DRAG_PLUGINKEY:
+ load_flags |= LOAD_AUTOMATION;
mwindow->session->current_operation = NO_OPERATION;
mwindow->session->drag_handle = 0;
// Remove any out-of-order keyframe
update_overlay = 1;
}
-
- mwindow->undo->update_undo_after(_("keyframe"), LOAD_AUTOMATION);
+ mwindow->undo->update_undo_after(_("keyframe"), load_flags);
result = 1;
break;
}
if (result)
- cursor_motion_event();
+ cursor_update(0);
if(update_overlay) {
gui->draw_overlays(1);
}
- if(redraw) {
- gui->draw_canvas(NORMAL_DRAW, 0);
+ if(redraw >= 0) {
+ gui->draw_canvas(redraw, 0);
+ gui->flash_canvas(1);
}
return result;
}
int max_y);
int button_press_event();
int button_release_event();
+ int cursor_update(int in_motion);
int cursor_motion_event();
int activate();
int deactivate();
double selection_midpoint; // division between current ends
int snapped; // drag handle snapping
+ EDL *speed_edl; // drag speed handle start edl
};
#endif