diff --git a/project/clip.cpp b/project/clip.cpp index 213a53858..88258441f 100644 --- a/project/clip.cpp +++ b/project/clip.cpp @@ -309,18 +309,25 @@ void Clip::refactor_frame_rate(ComboAction* ca, double multiplier, bool change_t track); } + QVector key_rows; + QVector key_indices; + QVector key_old; + QVector key_new; + for (int i=0;irow_count();j++) { EffectRow* r = e->row(j); for (int k=0;kkeyframe_times.size();k++) { - long new_pos = r->keyframe_times.at(k) * multiplier; - KeyframeMove* km = new KeyframeMove(); - km->movement = new_pos - r->keyframe_times.at(k); - km->rows.append(r); - km->keyframes.append(k); - ca->append(km); + key_rows.append(r); + key_indices.at(k); + key_old.append(r->keyframe_times.at(k)); + key_new.append(r->keyframe_times.at(k) * multiplier); } } } + + if (key_rows.size() > 0) { + ca->append(new KeyframeMove(key_rows, key_indices, key_old, key_new)); + } } diff --git a/project/undo.cpp b/project/undo.cpp index e67c38941..fc9f77d92 100644 --- a/project/undo.cpp +++ b/project/undo.cpp @@ -737,18 +737,24 @@ void MediaRename::redo() { mainWindow->setWindowModified(true); } -KeyframeMove::KeyframeMove() : old_project_changed(mainWindow->isWindowModified()) {} +KeyframeMove::KeyframeMove(const QVector& irows, const QVector& ikeyframes, const QVector& iold_values, const QVector& inew_values) : + rows(irows), + keyframes(ikeyframes), + old_values(iold_values), + new_values(inew_values), + old_project_changed(mainWindow->isWindowModified()) +{} void KeyframeMove::undo() { for (int i=0;ikeyframe_times[keyframes.at(i)] -= movement; + rows.at(i)->keyframe_times[keyframes.at(i)] = old_values.at(i); } mainWindow->setWindowModified(old_project_changed); } void KeyframeMove::redo() { for (int i=0;ikeyframe_times[keyframes.at(i)] += movement; + rows.at(i)->keyframe_times[keyframes.at(i)] = new_values.at(i); } mainWindow->setWindowModified(true); } diff --git a/project/undo.h b/project/undo.h index a1f79212f..f7aae7626 100644 --- a/project/undo.h +++ b/project/undo.h @@ -330,13 +330,14 @@ private: class KeyframeMove : public QUndoCommand { public: - KeyframeMove(); - QVector rows; - QVector keyframes; - long movement; + KeyframeMove(const QVector& rows, const QVector& keyframes, const QVector& old_values, const QVector& new_values); void undo(); void redo(); private: + QVector rows; + QVector keyframes; + QVector old_values; + QVector new_values; bool old_project_changed; }; diff --git a/ui/graphview.cpp b/ui/graphview.cpp index 4a62ed8fd..4c26a081e 100644 --- a/ui/graphview.cpp +++ b/ui/graphview.cpp @@ -10,6 +10,7 @@ #include "project/effectrow.h" #include "project/effectfield.h" #include "ui/keyframedrawing.h" +#include "project/undo.h" #include "debug.h" @@ -29,7 +30,8 @@ GraphView::GraphView(QWidget* parent) : y_scroll(0), mousedown(false), zoom(1.0), - row(NULL) + row(NULL), + moved_keys(false) { setMouseTracking(true); } @@ -115,7 +117,7 @@ void GraphView::paintEvent(QPaintEvent *event) { int key_x = get_screen_x(row->keyframe_times.at(key_index)); int key_y = get_screen_y(field->keyframe_data.at(key_index).toDouble()); - draw_keyframe(p, row->keyframe_types.at(key_index), key_x, key_y, false); + draw_keyframe(p, row->keyframe_types.at(key_index), key_x, key_y, (selected_keys.contains(key_index) && selected_keys_fields.contains(i))); } p.setBrush(Qt::NoBrush); } @@ -140,6 +142,42 @@ void GraphView::mousePressEvent(QMouseEvent *event) { mousedown = true; start_x = event->pos().x(); start_y = event->pos().y(); + + // selecting + int sel_key = -1; + int sel_key_field = -1; + if (!(event->modifiers() & Qt::ShiftModifier)) { + selected_keys.clear(); + selected_keys_fields.clear(); + } + for (int i=0;ifieldCount();i++) { + EffectField* field = row->field(i); + if (field->type == EFFECT_FIELD_DOUBLE) { + for (int j=0;jkeyframe_times.size();j++) { + int key_x = get_screen_x(row->keyframe_times.at(j)); + int key_y = get_screen_y(field->keyframe_data.at(j).toDouble()); + if (event->pos().x() > key_x-KEYFRAME_SIZE + && event->pos().x() < key_x+KEYFRAME_SIZE + && event->pos().y() > key_y-KEYFRAME_SIZE + && event->pos().y() < key_y+KEYFRAME_SIZE) { + sel_key = j; + sel_key_field = i; + break; + } + } + } + } + if (sel_key > -1) { + selected_keys.append(sel_key); + selected_keys_fields.append(sel_key_field); + } + + selected_keys_old_vals.clear(); + for (int i=0;ikeyframe_times.at(selected_keys.at(i))); + } + + update(); } void GraphView::mouseMoveEvent(QMouseEvent *event) { @@ -150,11 +188,28 @@ void GraphView::mouseMoveEvent(QMouseEvent *event) { start_x = event->pos().x(); start_y = event->pos().y(); update(); + } else { + for (int i=0;ikeyframe_times[selected_keys.at(i)] = selected_keys_old_vals.at(i) + (double(event->pos().x() - start_x)/zoom); + } + moved_keys = true; + update_ui(false); } } } void GraphView::mouseReleaseEvent(QMouseEvent *event) { + if (moved_keys) { + QVector rows; + QVector new_vals; + for (int i=0;ikeyframe_times.at(selected_keys.at(i))); + } + + undo_stack.push(new KeyframeMove(rows, selected_keys, selected_keys_old_vals, new_vals)); + } + moved_keys = false; mousedown = false; } diff --git a/ui/graphview.h b/ui/graphview.h index ca1404c94..5706b48a6 100644 --- a/ui/graphview.h +++ b/ui/graphview.h @@ -2,6 +2,7 @@ #define GRAPHVIEW_H #include +#include class EffectRow; @@ -10,9 +11,9 @@ QColor get_curve_color(int index, int length); class GraphView : public QWidget { Q_OBJECT public: - GraphView(QWidget* parent = 0); + GraphView(QWidget* parent = 0); - void paintEvent(QPaintEvent *event); + void paintEvent(QPaintEvent *event); void mousePressEvent(QMouseEvent *event); void mouseMoveEvent(QMouseEvent *event); void mouseReleaseEvent(QMouseEvent *event); @@ -37,6 +38,12 @@ private: int get_screen_x(double); int get_screen_y(double); + QVector selected_keys; + QVector selected_keys_fields; + QVector selected_keys_old_vals; + + bool moved_keys; + EffectRow* row; }; diff --git a/ui/keyframeview.cpp b/ui/keyframeview.cpp index e12feb4f7..b37f71b17 100644 --- a/ui/keyframeview.cpp +++ b/ui/keyframeview.cpp @@ -106,7 +106,6 @@ void KeyframeView::paintEvent(QPaintEvent*) { for (int k=0;kkeyframe_times.size();k++) { bool keyframe_selected = keyframeIsSelected(row, k); long keyframe_frame = adjust_row_keyframe(row, row->keyframe_times.at(k)); - if (dragging && keyframe_selected) keyframe_frame += frame_diff; draw_keyframe(p, row->keyframe_types.at(k), getScreenPointFromFrame(panel_effect_controls->zoom, keyframe_frame) - x_scroll, keyframe_y, keyframe_selected); } @@ -198,6 +197,8 @@ void KeyframeView::mousePressEvent(QMouseEvent *event) { return; } + old_key_vals.clear(); + int mouse_x = event->x() + x_scroll; int mouse_y = event->y(); int row_index = -1; @@ -241,6 +242,10 @@ void KeyframeView::mousePressEvent(QMouseEvent *event) { } if (selected_rows.size() > 0) { + for (int i=0;ikeyframe_times.at(selected_keyframes.at(i))); + } + keys_selected = true; } @@ -266,14 +271,15 @@ void KeyframeView::mouseMoveEvent(QMouseEvent* event) { int mouse_x = event->x() + x_scroll; if (keys_selected) { // move keyframes - frame_diff = getFrameFromScreenPoint(panel_effect_controls->zoom, mouse_x) - drag_frame_start; + long frame_diff = getFrameFromScreenPoint(panel_effect_controls->zoom, mouse_x) - drag_frame_start; // snapping to playhead + panel_timeline->snapped = false; if (panel_timeline->snapping) { for (int i=0;iparent_effect->parent_clip; - long key_time = row->keyframe_times.at(selected_keyframes.at(i)) + frame_diff - c->clip_in + c->timeline_in; + long key_time = old_key_vals.at(i) + frame_diff - c->clip_in + c->timeline_in; long key_eval = key_time; if (panel_timeline->snap_to_point(sequence->playhead, &key_eval)) { frame_diff += (key_eval - key_time); @@ -283,9 +289,9 @@ void KeyframeView::mouseMoveEvent(QMouseEvent* event) { } // validate frame_diff (make sure no keyframes overlap each other) - for (int i=0;ikeyframe_times.at(selected_keyframes.at(i)); + long eval_key = old_key_vals.at(i); for (int j=0;jkeyframe_times.size();j++) { while (!keyframeIsSelected(row, j) && row->keyframe_times.at(j) == eval_key + frame_diff) { if (last_frame_diff > frame_diff) { @@ -299,9 +305,17 @@ void KeyframeView::mouseMoveEvent(QMouseEvent* event) { } } + // apply frame_diffs + for (int i=0;ikeyframe_times[selected_keyframes.at(i)] = old_key_vals.at(i) + frame_diff; + } + last_frame_diff = frame_diff; dragging = true; + + update_ui(false); } else { // do a rect select rect_select_w = event->x() - rect_select_x; @@ -329,18 +343,20 @@ void KeyframeView::mouseMoveEvent(QMouseEvent* event) { } select_rect = true; + + update_keys(); } - update_keys(); } } void KeyframeView::mouseReleaseEvent(QMouseEvent*) { - if (dragging && frame_diff != 0) { - KeyframeMove* ka = new KeyframeMove(); - ka->movement = frame_diff; - ka->keyframes = selected_keyframes; - ka->rows = selected_rows; - undo_stack.push(ka); + if (dragging) { + QVector new_key_vals; + for (int i=0;ikeyframe_times.at(selected_keyframes.at(i))); + } + + undo_stack.push(new KeyframeMove(selected_rows, selected_keyframes, old_key_vals, new_key_vals)); } select_rect = false; diff --git a/ui/keyframeview.h b/ui/keyframeview.h index c81186683..990bdef9e 100644 --- a/ui/keyframeview.h +++ b/ui/keyframeview.h @@ -27,19 +27,19 @@ public slots: private: long adjust_row_keyframe(EffectRow* row, long time); QVector selected_rows; - QVector selected_keyframes; + QVector selected_keyframes; QVector rowY; - long frame_diff; QVector rows; + QVector old_key_vals; void mousePressEvent(QMouseEvent* event); void mouseMoveEvent(QMouseEvent* event); void mouseReleaseEvent(QMouseEvent *event); void paintEvent(QPaintEvent *event); - bool mousedown; + bool mousedown; bool dragging; bool keys_selected; - bool select_rect; - bool scroll_drag; + bool select_rect; + bool scroll_drag; bool keyframeIsSelected(EffectRow* row, int keyframe); @@ -55,8 +55,8 @@ private: void update_keys(); private slots: - void show_context_menu(const QPoint& pos); - void menu_set_key_type(QAction*); + void show_context_menu(const QPoint& pos); + void menu_set_key_type(QAction*); }; #endif // KEYFRAMEVIEW_H