keyframes are movable in graph view
This commit is contained in:
+13
-6
@@ -309,18 +309,25 @@ void Clip::refactor_frame_rate(ComboAction* ca, double multiplier, bool change_t
|
|||||||
track);
|
track);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QVector<EffectRow*> key_rows;
|
||||||
|
QVector<int> key_indices;
|
||||||
|
QVector<long> key_old;
|
||||||
|
QVector<long> key_new;
|
||||||
|
|
||||||
for (int i=0;i<effects.size();i++) {
|
for (int i=0;i<effects.size();i++) {
|
||||||
Effect* e = effects.at(i);
|
Effect* e = effects.at(i);
|
||||||
for (int j=0;j<e->row_count();j++) {
|
for (int j=0;j<e->row_count();j++) {
|
||||||
EffectRow* r = e->row(j);
|
EffectRow* r = e->row(j);
|
||||||
for (int k=0;k<r->keyframe_times.size();k++) {
|
for (int k=0;k<r->keyframe_times.size();k++) {
|
||||||
long new_pos = r->keyframe_times.at(k) * multiplier;
|
key_rows.append(r);
|
||||||
KeyframeMove* km = new KeyframeMove();
|
key_indices.at(k);
|
||||||
km->movement = new_pos - r->keyframe_times.at(k);
|
key_old.append(r->keyframe_times.at(k));
|
||||||
km->rows.append(r);
|
key_new.append(r->keyframe_times.at(k) * multiplier);
|
||||||
km->keyframes.append(k);
|
|
||||||
ca->append(km);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (key_rows.size() > 0) {
|
||||||
|
ca->append(new KeyframeMove(key_rows, key_indices, key_old, key_new));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+9
-3
@@ -737,18 +737,24 @@ void MediaRename::redo() {
|
|||||||
mainWindow->setWindowModified(true);
|
mainWindow->setWindowModified(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
KeyframeMove::KeyframeMove() : old_project_changed(mainWindow->isWindowModified()) {}
|
KeyframeMove::KeyframeMove(const QVector<EffectRow*>& irows, const QVector<int>& ikeyframes, const QVector<long>& iold_values, const QVector<long>& inew_values) :
|
||||||
|
rows(irows),
|
||||||
|
keyframes(ikeyframes),
|
||||||
|
old_values(iold_values),
|
||||||
|
new_values(inew_values),
|
||||||
|
old_project_changed(mainWindow->isWindowModified())
|
||||||
|
{}
|
||||||
|
|
||||||
void KeyframeMove::undo() {
|
void KeyframeMove::undo() {
|
||||||
for (int i=0;i<rows.size();i++) {
|
for (int i=0;i<rows.size();i++) {
|
||||||
rows.at(i)->keyframe_times[keyframes.at(i)] -= movement;
|
rows.at(i)->keyframe_times[keyframes.at(i)] = old_values.at(i);
|
||||||
}
|
}
|
||||||
mainWindow->setWindowModified(old_project_changed);
|
mainWindow->setWindowModified(old_project_changed);
|
||||||
}
|
}
|
||||||
|
|
||||||
void KeyframeMove::redo() {
|
void KeyframeMove::redo() {
|
||||||
for (int i=0;i<rows.size();i++) {
|
for (int i=0;i<rows.size();i++) {
|
||||||
rows.at(i)->keyframe_times[keyframes.at(i)] += movement;
|
rows.at(i)->keyframe_times[keyframes.at(i)] = new_values.at(i);
|
||||||
}
|
}
|
||||||
mainWindow->setWindowModified(true);
|
mainWindow->setWindowModified(true);
|
||||||
}
|
}
|
||||||
|
|||||||
+5
-4
@@ -330,13 +330,14 @@ private:
|
|||||||
|
|
||||||
class KeyframeMove : public QUndoCommand {
|
class KeyframeMove : public QUndoCommand {
|
||||||
public:
|
public:
|
||||||
KeyframeMove();
|
KeyframeMove(const QVector<EffectRow*>& rows, const QVector<int>& keyframes, const QVector<long>& old_values, const QVector<long>& new_values);
|
||||||
QVector<EffectRow*> rows;
|
|
||||||
QVector<int> keyframes;
|
|
||||||
long movement;
|
|
||||||
void undo();
|
void undo();
|
||||||
void redo();
|
void redo();
|
||||||
private:
|
private:
|
||||||
|
QVector<EffectRow*> rows;
|
||||||
|
QVector<int> keyframes;
|
||||||
|
QVector<long> old_values;
|
||||||
|
QVector<long> new_values;
|
||||||
bool old_project_changed;
|
bool old_project_changed;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
+57
-2
@@ -10,6 +10,7 @@
|
|||||||
#include "project/effectrow.h"
|
#include "project/effectrow.h"
|
||||||
#include "project/effectfield.h"
|
#include "project/effectfield.h"
|
||||||
#include "ui/keyframedrawing.h"
|
#include "ui/keyframedrawing.h"
|
||||||
|
#include "project/undo.h"
|
||||||
|
|
||||||
#include "debug.h"
|
#include "debug.h"
|
||||||
|
|
||||||
@@ -29,7 +30,8 @@ GraphView::GraphView(QWidget* parent) :
|
|||||||
y_scroll(0),
|
y_scroll(0),
|
||||||
mousedown(false),
|
mousedown(false),
|
||||||
zoom(1.0),
|
zoom(1.0),
|
||||||
row(NULL)
|
row(NULL),
|
||||||
|
moved_keys(false)
|
||||||
{
|
{
|
||||||
setMouseTracking(true);
|
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_x = get_screen_x(row->keyframe_times.at(key_index));
|
||||||
int key_y = get_screen_y(field->keyframe_data.at(key_index).toDouble());
|
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);
|
p.setBrush(Qt::NoBrush);
|
||||||
}
|
}
|
||||||
@@ -140,6 +142,42 @@ void GraphView::mousePressEvent(QMouseEvent *event) {
|
|||||||
mousedown = true;
|
mousedown = true;
|
||||||
start_x = event->pos().x();
|
start_x = event->pos().x();
|
||||||
start_y = event->pos().y();
|
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;i<row->fieldCount();i++) {
|
||||||
|
EffectField* field = row->field(i);
|
||||||
|
if (field->type == EFFECT_FIELD_DOUBLE) {
|
||||||
|
for (int j=0;j<row->keyframe_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;i<selected_keys.size();i++) {
|
||||||
|
selected_keys_old_vals.append(row->keyframe_times.at(selected_keys.at(i)));
|
||||||
|
}
|
||||||
|
|
||||||
|
update();
|
||||||
}
|
}
|
||||||
|
|
||||||
void GraphView::mouseMoveEvent(QMouseEvent *event) {
|
void GraphView::mouseMoveEvent(QMouseEvent *event) {
|
||||||
@@ -150,11 +188,28 @@ void GraphView::mouseMoveEvent(QMouseEvent *event) {
|
|||||||
start_x = event->pos().x();
|
start_x = event->pos().x();
|
||||||
start_y = event->pos().y();
|
start_y = event->pos().y();
|
||||||
update();
|
update();
|
||||||
|
} else {
|
||||||
|
for (int i=0;i<selected_keys.size();i++) {
|
||||||
|
row->keyframe_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) {
|
void GraphView::mouseReleaseEvent(QMouseEvent *event) {
|
||||||
|
if (moved_keys) {
|
||||||
|
QVector<EffectRow*> rows;
|
||||||
|
QVector<long> new_vals;
|
||||||
|
for (int i=0;i<selected_keys.size();i++) {
|
||||||
|
rows.append(row);
|
||||||
|
new_vals.append(row->keyframe_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;
|
mousedown = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+9
-2
@@ -2,6 +2,7 @@
|
|||||||
#define GRAPHVIEW_H
|
#define GRAPHVIEW_H
|
||||||
|
|
||||||
#include <QWidget>
|
#include <QWidget>
|
||||||
|
#include <QVector>
|
||||||
|
|
||||||
class EffectRow;
|
class EffectRow;
|
||||||
|
|
||||||
@@ -10,9 +11,9 @@ QColor get_curve_color(int index, int length);
|
|||||||
class GraphView : public QWidget {
|
class GraphView : public QWidget {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
GraphView(QWidget* parent = 0);
|
GraphView(QWidget* parent = 0);
|
||||||
|
|
||||||
void paintEvent(QPaintEvent *event);
|
void paintEvent(QPaintEvent *event);
|
||||||
void mousePressEvent(QMouseEvent *event);
|
void mousePressEvent(QMouseEvent *event);
|
||||||
void mouseMoveEvent(QMouseEvent *event);
|
void mouseMoveEvent(QMouseEvent *event);
|
||||||
void mouseReleaseEvent(QMouseEvent *event);
|
void mouseReleaseEvent(QMouseEvent *event);
|
||||||
@@ -37,6 +38,12 @@ private:
|
|||||||
int get_screen_x(double);
|
int get_screen_x(double);
|
||||||
int get_screen_y(double);
|
int get_screen_y(double);
|
||||||
|
|
||||||
|
QVector<int> selected_keys;
|
||||||
|
QVector<int> selected_keys_fields;
|
||||||
|
QVector<long> selected_keys_old_vals;
|
||||||
|
|
||||||
|
bool moved_keys;
|
||||||
|
|
||||||
EffectRow* row;
|
EffectRow* row;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
+28
-12
@@ -106,7 +106,6 @@ void KeyframeView::paintEvent(QPaintEvent*) {
|
|||||||
for (int k=0;k<row->keyframe_times.size();k++) {
|
for (int k=0;k<row->keyframe_times.size();k++) {
|
||||||
bool keyframe_selected = keyframeIsSelected(row, k);
|
bool keyframe_selected = keyframeIsSelected(row, k);
|
||||||
long keyframe_frame = adjust_row_keyframe(row, row->keyframe_times.at(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);
|
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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
old_key_vals.clear();
|
||||||
|
|
||||||
int mouse_x = event->x() + x_scroll;
|
int mouse_x = event->x() + x_scroll;
|
||||||
int mouse_y = event->y();
|
int mouse_y = event->y();
|
||||||
int row_index = -1;
|
int row_index = -1;
|
||||||
@@ -241,6 +242,10 @@ void KeyframeView::mousePressEvent(QMouseEvent *event) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (selected_rows.size() > 0) {
|
if (selected_rows.size() > 0) {
|
||||||
|
for (int i=0;i<selected_rows.size();i++) {
|
||||||
|
old_key_vals.append(selected_rows.at(i)->keyframe_times.at(selected_keyframes.at(i)));
|
||||||
|
}
|
||||||
|
|
||||||
keys_selected = true;
|
keys_selected = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -266,14 +271,15 @@ void KeyframeView::mouseMoveEvent(QMouseEvent* event) {
|
|||||||
int mouse_x = event->x() + x_scroll;
|
int mouse_x = event->x() + x_scroll;
|
||||||
if (keys_selected) {
|
if (keys_selected) {
|
||||||
// move keyframes
|
// 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
|
// snapping to playhead
|
||||||
|
panel_timeline->snapped = false;
|
||||||
if (panel_timeline->snapping) {
|
if (panel_timeline->snapping) {
|
||||||
for (int i=0;i<selected_keyframes.size();i++) {
|
for (int i=0;i<selected_keyframes.size();i++) {
|
||||||
EffectRow* row = selected_rows.at(i);
|
EffectRow* row = selected_rows.at(i);
|
||||||
Clip* c = row->parent_effect->parent_clip;
|
Clip* c = row->parent_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;
|
long key_eval = key_time;
|
||||||
if (panel_timeline->snap_to_point(sequence->playhead, &key_eval)) {
|
if (panel_timeline->snap_to_point(sequence->playhead, &key_eval)) {
|
||||||
frame_diff += (key_eval - key_time);
|
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)
|
// validate frame_diff (make sure no keyframes overlap each other)
|
||||||
for (int i=0;i<selected_keyframes.size();i++) {
|
for (int i=0;i<selected_rows.size();i++) {
|
||||||
EffectRow* row = selected_rows.at(i);
|
EffectRow* row = selected_rows.at(i);
|
||||||
long eval_key = row->keyframe_times.at(selected_keyframes.at(i));
|
long eval_key = old_key_vals.at(i);
|
||||||
for (int j=0;j<row->keyframe_times.size();j++) {
|
for (int j=0;j<row->keyframe_times.size();j++) {
|
||||||
while (!keyframeIsSelected(row, j) && row->keyframe_times.at(j) == eval_key + frame_diff) {
|
while (!keyframeIsSelected(row, j) && row->keyframe_times.at(j) == eval_key + frame_diff) {
|
||||||
if (last_frame_diff > frame_diff) {
|
if (last_frame_diff > frame_diff) {
|
||||||
@@ -299,9 +305,17 @@ void KeyframeView::mouseMoveEvent(QMouseEvent* event) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// apply frame_diffs
|
||||||
|
for (int i=0;i<selected_keyframes.size();i++) {
|
||||||
|
EffectRow* row = selected_rows.at(i);
|
||||||
|
row->keyframe_times[selected_keyframes.at(i)] = old_key_vals.at(i) + frame_diff;
|
||||||
|
}
|
||||||
|
|
||||||
last_frame_diff = frame_diff;
|
last_frame_diff = frame_diff;
|
||||||
|
|
||||||
dragging = true;
|
dragging = true;
|
||||||
|
|
||||||
|
update_ui(false);
|
||||||
} else {
|
} else {
|
||||||
// do a rect select
|
// do a rect select
|
||||||
rect_select_w = event->x() - rect_select_x;
|
rect_select_w = event->x() - rect_select_x;
|
||||||
@@ -329,18 +343,20 @@ void KeyframeView::mouseMoveEvent(QMouseEvent* event) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
select_rect = true;
|
select_rect = true;
|
||||||
|
|
||||||
|
update_keys();
|
||||||
}
|
}
|
||||||
update_keys();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void KeyframeView::mouseReleaseEvent(QMouseEvent*) {
|
void KeyframeView::mouseReleaseEvent(QMouseEvent*) {
|
||||||
if (dragging && frame_diff != 0) {
|
if (dragging) {
|
||||||
KeyframeMove* ka = new KeyframeMove();
|
QVector<long> new_key_vals;
|
||||||
ka->movement = frame_diff;
|
for (int i=0;i<selected_rows.size();i++) {
|
||||||
ka->keyframes = selected_keyframes;
|
new_key_vals.append(selected_rows.at(i)->keyframe_times.at(selected_keyframes.at(i)));
|
||||||
ka->rows = selected_rows;
|
}
|
||||||
undo_stack.push(ka);
|
|
||||||
|
undo_stack.push(new KeyframeMove(selected_rows, selected_keyframes, old_key_vals, new_key_vals));
|
||||||
}
|
}
|
||||||
|
|
||||||
select_rect = false;
|
select_rect = false;
|
||||||
|
|||||||
+7
-7
@@ -27,19 +27,19 @@ public slots:
|
|||||||
private:
|
private:
|
||||||
long adjust_row_keyframe(EffectRow* row, long time);
|
long adjust_row_keyframe(EffectRow* row, long time);
|
||||||
QVector<EffectRow*> selected_rows;
|
QVector<EffectRow*> selected_rows;
|
||||||
QVector<int> selected_keyframes;
|
QVector<int> selected_keyframes;
|
||||||
QVector<int> rowY;
|
QVector<int> rowY;
|
||||||
long frame_diff;
|
|
||||||
QVector<EffectRow*> rows;
|
QVector<EffectRow*> rows;
|
||||||
|
QVector<long> old_key_vals;
|
||||||
void mousePressEvent(QMouseEvent* event);
|
void mousePressEvent(QMouseEvent* event);
|
||||||
void mouseMoveEvent(QMouseEvent* event);
|
void mouseMoveEvent(QMouseEvent* event);
|
||||||
void mouseReleaseEvent(QMouseEvent *event);
|
void mouseReleaseEvent(QMouseEvent *event);
|
||||||
void paintEvent(QPaintEvent *event);
|
void paintEvent(QPaintEvent *event);
|
||||||
bool mousedown;
|
bool mousedown;
|
||||||
bool dragging;
|
bool dragging;
|
||||||
bool keys_selected;
|
bool keys_selected;
|
||||||
bool select_rect;
|
bool select_rect;
|
||||||
bool scroll_drag;
|
bool scroll_drag;
|
||||||
|
|
||||||
bool keyframeIsSelected(EffectRow* row, int keyframe);
|
bool keyframeIsSelected(EffectRow* row, int keyframe);
|
||||||
|
|
||||||
@@ -55,8 +55,8 @@ private:
|
|||||||
|
|
||||||
void update_keys();
|
void update_keys();
|
||||||
private slots:
|
private slots:
|
||||||
void show_context_menu(const QPoint& pos);
|
void show_context_menu(const QPoint& pos);
|
||||||
void menu_set_key_type(QAction*);
|
void menu_set_key_type(QAction*);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // KEYFRAMEVIEW_H
|
#endif // KEYFRAMEVIEW_H
|
||||||
|
|||||||
Reference in New Issue
Block a user