implemented full bezier interpolation for keyframes
This commit is contained in:
+201
-68
@@ -11,11 +11,17 @@
|
||||
#include "project/effectfield.h"
|
||||
#include "ui/keyframedrawing.h"
|
||||
#include "project/undo.h"
|
||||
#include "project/effect.h"
|
||||
|
||||
#include "debug.h"
|
||||
|
||||
#define GRAPH_ZOOM_SPEED 0.05
|
||||
#define GRAPH_SIZE 100
|
||||
#define BEZIER_HANDLE_SIZE 3
|
||||
|
||||
#define BEZIER_HANDLE_NONE 1
|
||||
#define BEZIER_HANDLE_PRE 2
|
||||
#define BEZIER_HANDLE_POST 3
|
||||
|
||||
QColor get_curve_color(int index, int length) {
|
||||
QColor c;
|
||||
@@ -31,7 +37,8 @@ GraphView::GraphView(QWidget* parent) :
|
||||
mousedown(false),
|
||||
zoom(1.0),
|
||||
row(NULL),
|
||||
moved_keys(false)
|
||||
moved_keys(false),
|
||||
current_handle(BEZIER_HANDLE_NONE)
|
||||
{
|
||||
setMouseTracking(true);
|
||||
}
|
||||
@@ -40,7 +47,8 @@ void GraphView::paintEvent(QPaintEvent *event) {
|
||||
QPainter p(this);
|
||||
|
||||
if (panel_sequence_viewer->seq != NULL) {
|
||||
// draw lines
|
||||
// draw grid lines
|
||||
|
||||
//int graph_size = GRAPH_SIZE*zoom;
|
||||
bool draw_text = true;//(fontMetrics().height() < graph_size && fontMetrics().width("0000") < graph_size);
|
||||
|
||||
@@ -75,53 +83,100 @@ void GraphView::paintEvent(QPaintEvent *event) {
|
||||
QPen line_pen;
|
||||
line_pen.setWidth(2);
|
||||
|
||||
for (int i=0;i<row->fieldCount();i++) {
|
||||
EffectField* field = row->field(i);
|
||||
for (int i=0;i<row->fieldCount();i++) {
|
||||
EffectField* field = row->field(i);
|
||||
|
||||
if (field->type == EFFECT_FIELD_DOUBLE) {
|
||||
// sort keyframes by time
|
||||
QVector<int> sorted_keys;
|
||||
for (int k=0;k<field->keyframes.size();k++) {
|
||||
bool inserted = false;
|
||||
for (int j=0;j<sorted_keys.size();j++) {
|
||||
if (field->keyframes.at(sorted_keys.at(j)).time > field->keyframes.at(k).time) {
|
||||
sorted_keys.insert(j, k);
|
||||
inserted = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!inserted) {
|
||||
sorted_keys.append(i);
|
||||
}
|
||||
}
|
||||
if (field->type == EFFECT_FIELD_DOUBLE && field_visibility.at(i)) {
|
||||
// sort keyframes by time
|
||||
QVector<int> sorted_keys;
|
||||
for (int k=0;k<field->keyframes.size();k++) {
|
||||
bool inserted = false;
|
||||
for (int j=0;j<sorted_keys.size();j++) {
|
||||
if (field->keyframes.at(sorted_keys.at(j)).time > field->keyframes.at(k).time) {
|
||||
sorted_keys.insert(j, k);
|
||||
inserted = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!inserted) {
|
||||
sorted_keys.append(k);
|
||||
}
|
||||
}
|
||||
|
||||
int last_key_x, last_key_y;
|
||||
int last_key_x, last_key_y;
|
||||
|
||||
// draw lines
|
||||
for (int j=0;j<sorted_keys.size();j++) {
|
||||
// draw lines
|
||||
int key_index = sorted_keys.at(j);
|
||||
const EffectKeyframe& key = field->keyframes.at(sorted_keys.at(j));
|
||||
|
||||
int key_x = get_screen_x(field->keyframes.at(key_index).time);
|
||||
int key_y = get_screen_y(field->keyframes.at(key_index).data.toDouble());
|
||||
int key_x = get_screen_x(key.time);
|
||||
int key_y = get_screen_y(key.data.toDouble());
|
||||
|
||||
line_pen.setColor(get_curve_color(i, row->fieldCount()));
|
||||
p.setPen(line_pen);
|
||||
if (key_index == 0) {
|
||||
if (j == 0) {
|
||||
p.drawLine(0, key_y, key_x, key_y);
|
||||
} else {
|
||||
p.drawLine(last_key_x, last_key_y, key_x, key_y);
|
||||
const EffectKeyframe& last_key = field->keyframes.at(sorted_keys.at(j-1));
|
||||
if (last_key.type == KEYFRAME_TYPE_HOLD) {
|
||||
// hold
|
||||
p.drawLine(last_key_x, last_key_y, key_x, last_key_y);
|
||||
p.drawLine(key_x, last_key_y, key_x, key_y);
|
||||
} else if (last_key.type == KEYFRAME_TYPE_BEZIER || key.type == KEYFRAME_TYPE_BEZIER) {
|
||||
QPainterPath bezier_path;
|
||||
bezier_path.moveTo(last_key_x, last_key_y);
|
||||
if (last_key.type == KEYFRAME_TYPE_BEZIER && key.type == KEYFRAME_TYPE_BEZIER) {
|
||||
// cubic bezier
|
||||
bezier_path.cubicTo(
|
||||
QPointF(last_key_x+last_key.post_handle_x, last_key_y+last_key.post_handle_y),
|
||||
QPointF(key_x+key.pre_handle_x, key_y+key.pre_handle_y),
|
||||
QPointF(key_x, key_y)
|
||||
);
|
||||
} else if (key.type == KEYFRAME_TYPE_LINEAR) { // quadratic bezier
|
||||
// last keyframe is the bezier one
|
||||
bezier_path.quadTo(
|
||||
QPointF(last_key_x+last_key.post_handle_x, last_key_y+last_key.post_handle_y),
|
||||
QPointF(key_x, key_y)
|
||||
);
|
||||
} else {
|
||||
// this keyframe is the bezier one
|
||||
bezier_path.quadTo(
|
||||
QPointF(key_x+key.pre_handle_x, key_y+key.pre_handle_y),
|
||||
QPointF(key_x, key_y)
|
||||
);
|
||||
}
|
||||
p.drawPath(bezier_path);
|
||||
} else {
|
||||
// linear
|
||||
p.drawLine(last_key_x, last_key_y, key_x, key_y);
|
||||
}
|
||||
}
|
||||
last_key_x = key_x;
|
||||
last_key_y = key_y;
|
||||
}
|
||||
|
||||
// draw keys
|
||||
for (int j=0;j<sorted_keys.size();j++) {
|
||||
// draw keys
|
||||
int key_index = sorted_keys.at(j);
|
||||
const EffectKeyframe& key = field->keyframes.at(sorted_keys.at(j));
|
||||
|
||||
int key_x = get_screen_x(field->keyframes.at(key_index).time);
|
||||
int key_y = get_screen_y(field->keyframes.at(key_index).data.toDouble());
|
||||
int key_x = get_screen_x(key.time);
|
||||
int key_y = get_screen_y(key.data.toDouble());
|
||||
|
||||
draw_keyframe(p, field->keyframes.at(key_index).type, key_x, key_y, (selected_keys.contains(key_index) && selected_keys_fields.contains(i)));
|
||||
if (key.type == KEYFRAME_TYPE_BEZIER) {
|
||||
p.setPen(Qt::gray);
|
||||
|
||||
// pre handle line
|
||||
QPointF pre_point(key_x + key.pre_handle_x*zoom, key_y + key.pre_handle_y*zoom);
|
||||
p.drawLine(pre_point, QPointF(key_x, key_y));
|
||||
p.drawEllipse(pre_point, BEZIER_HANDLE_SIZE, BEZIER_HANDLE_SIZE);
|
||||
|
||||
// post handle line
|
||||
QPointF post_point(key_x + key.post_handle_x*zoom, key_y + key.post_handle_y*zoom);
|
||||
p.drawLine(post_point, QPointF(key_x, key_y));
|
||||
p.drawEllipse(post_point, BEZIER_HANDLE_SIZE, BEZIER_HANDLE_SIZE);
|
||||
}
|
||||
|
||||
draw_keyframe(p, key.type, key_x, key_y, (selected_keys.contains(sorted_keys.at(j)) && selected_keys_fields.contains(i)));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -153,13 +208,15 @@ void GraphView::mousePressEvent(QMouseEvent *event) {
|
||||
selected_keys.clear();
|
||||
selected_keys_fields.clear();
|
||||
}
|
||||
current_handle = BEZIER_HANDLE_NONE;
|
||||
if (row != NULL) {
|
||||
for (int i=0;i<row->fieldCount();i++) {
|
||||
EffectField* field = row->field(i);
|
||||
if (field->type == EFFECT_FIELD_DOUBLE) {
|
||||
for (int j=0;j<field->keyframes.size();j++) {
|
||||
int key_x = get_screen_x(field->keyframes.at(j).time);
|
||||
int key_y = get_screen_y(field->keyframes.at(j).data.toDouble());
|
||||
if (field->type == EFFECT_FIELD_DOUBLE && field_visibility.at(i)) {
|
||||
for (int j=0;j<field->keyframes.size();j++) {
|
||||
const EffectKeyframe& key = field->keyframes.at(j);
|
||||
int key_x = get_screen_x(key.time);
|
||||
int key_y = get_screen_y(key.data.toDouble());
|
||||
if (event->pos().x() > key_x-KEYFRAME_SIZE
|
||||
&& event->pos().x() < key_x+KEYFRAME_SIZE
|
||||
&& event->pos().y() > key_y-KEYFRAME_SIZE
|
||||
@@ -167,6 +224,33 @@ void GraphView::mousePressEvent(QMouseEvent *event) {
|
||||
sel_key = j;
|
||||
sel_key_field = i;
|
||||
break;
|
||||
} else {
|
||||
// selecting a handle
|
||||
QPointF pre_point(key_x + key.pre_handle_x*zoom, key_y + key.pre_handle_y*zoom);
|
||||
if (event->pos().x() > pre_point.x()-BEZIER_HANDLE_SIZE
|
||||
&& event->pos().x() < pre_point.x()+BEZIER_HANDLE_SIZE
|
||||
&& event->pos().y() > pre_point.y()-BEZIER_HANDLE_SIZE
|
||||
&& event->pos().y() < pre_point.y()+BEZIER_HANDLE_SIZE) {
|
||||
sel_key = j;
|
||||
sel_key_field = i;
|
||||
old_handle_x = key.pre_handle_x;
|
||||
old_handle_y = key.pre_handle_y;
|
||||
current_handle = BEZIER_HANDLE_PRE;
|
||||
break;
|
||||
} else {
|
||||
QPointF post_point(key_x + key.post_handle_x*zoom, key_y + key.post_handle_y*zoom);
|
||||
if (event->pos().x() > post_point.x()-BEZIER_HANDLE_SIZE
|
||||
&& event->pos().x() < post_point.x()+BEZIER_HANDLE_SIZE
|
||||
&& event->pos().y() > post_point.y()-BEZIER_HANDLE_SIZE
|
||||
&& event->pos().y() < post_point.y()+BEZIER_HANDLE_SIZE) {
|
||||
sel_key = j;
|
||||
sel_key_field = i;
|
||||
old_handle_x = key.post_handle_x;
|
||||
old_handle_y = key.post_handle_y;
|
||||
current_handle = BEZIER_HANDLE_POST;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -179,16 +263,24 @@ void GraphView::mousePressEvent(QMouseEvent *event) {
|
||||
|
||||
selected_keys_old_vals.clear();
|
||||
selected_keys_old_doubles.clear();
|
||||
|
||||
int selected_key_type = -1;
|
||||
|
||||
for (int i=0;i<selected_keys.size();i++) {
|
||||
for (int j=0;j<selected_keys_fields.size();j++) {
|
||||
selected_keys_old_vals.append(row->field(selected_keys_fields.at(j))->keyframes.at(selected_keys.at(i)).time);
|
||||
selected_keys_old_doubles.append(row->field(selected_keys_fields.at(j))->keyframes.at(selected_keys.at(i)).data.toDouble());
|
||||
const EffectKeyframe& key = row->field(selected_keys_fields.at(i))->keyframes.at(selected_keys.at(i));
|
||||
selected_keys_old_vals.append(key.time);
|
||||
selected_keys_old_doubles.append(key.data.toDouble());
|
||||
|
||||
if (selected_key_type == -1) {
|
||||
selected_key_type = key.type;
|
||||
} else if (selected_key_type != key.type) {
|
||||
selected_key_type = -2;
|
||||
}
|
||||
}
|
||||
|
||||
update();
|
||||
|
||||
emit selection_changed(selected_keys.size() > 0);
|
||||
emit selection_changed(selected_keys.size() > 0, selected_key_type);
|
||||
}
|
||||
|
||||
void GraphView::mouseMoveEvent(QMouseEvent *event) {
|
||||
@@ -200,39 +292,60 @@ void GraphView::mouseMoveEvent(QMouseEvent *event) {
|
||||
start_y = event->pos().y();
|
||||
update();
|
||||
} else {
|
||||
for (int i=0;i<selected_keys.size();i++) {
|
||||
for (int j=0;j<selected_keys_fields.size();j++) {
|
||||
int index = (i*selected_keys_fields.size())+j;
|
||||
row->field(selected_keys_fields.at(j))->keyframes[selected_keys.at(i)].time = selected_keys_old_vals.at(index) + (double(event->pos().x() - start_x)/zoom);
|
||||
row->field(selected_keys_fields.at(j))->keyframes[selected_keys.at(i)].data = selected_keys_old_doubles.at(index) + (double(start_y - event->pos().y())/zoom);
|
||||
switch (current_handle) {
|
||||
case BEZIER_HANDLE_NONE:
|
||||
for (int i=0;i<selected_keys.size();i++) {
|
||||
row->field(selected_keys_fields.at(i))->keyframes[selected_keys.at(i)].time = qRound(selected_keys_old_vals.at(i) + (double(event->pos().x() - start_x)/zoom));
|
||||
row->field(selected_keys_fields.at(i))->keyframes[selected_keys.at(i)].data = qRound(selected_keys_old_doubles.at(i) + (double(start_y - event->pos().y())/zoom));
|
||||
}
|
||||
moved_keys = true;
|
||||
update_ui(false);
|
||||
break;
|
||||
case BEZIER_HANDLE_PRE:
|
||||
row->field(selected_keys_fields.last())->keyframes[selected_keys.last()].pre_handle_x = old_handle_x + double(event->pos().x() - start_x)/zoom;
|
||||
row->field(selected_keys_fields.last())->keyframes[selected_keys.last()].pre_handle_y = old_handle_y + double(event->pos().y() - start_y)/zoom;
|
||||
moved_keys = true;
|
||||
update_ui(false);
|
||||
break;
|
||||
case BEZIER_HANDLE_POST:
|
||||
row->field(selected_keys_fields.last())->keyframes[selected_keys.last()].post_handle_x = old_handle_x + double(event->pos().x() - start_x)/zoom;
|
||||
row->field(selected_keys_fields.last())->keyframes[selected_keys.last()].post_handle_y = old_handle_y + double(event->pos().y() - start_y)/zoom;
|
||||
moved_keys = true;
|
||||
update_ui(false);
|
||||
break;
|
||||
}
|
||||
moved_keys = true;
|
||||
update_ui(false);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void GraphView::mouseReleaseEvent(QMouseEvent *event) {
|
||||
if (moved_keys && selected_keys.size() > 0) {
|
||||
/*ComboAction* ca = new ComboAction();
|
||||
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)));
|
||||
|
||||
for (int j=0;j<selected_keys_fields.size();j++) {
|
||||
ca->append(new SetQVariant(&row->field(selected_keys_fields.at(j))->keyframe_data[selected_keys.at(i)],
|
||||
selected_keys_old_doubles.at((i*selected_keys_fields.size())+j),
|
||||
row->field(selected_keys_fields.at(j))->keyframe_data.at(selected_keys.at(i))));
|
||||
ComboAction* ca = new ComboAction();
|
||||
switch (current_handle) {
|
||||
case BEZIER_HANDLE_NONE:
|
||||
for (int i=0;i<selected_keys.size();i++) {
|
||||
EffectKeyframe& key = row->field(selected_keys_fields.at(i))->keyframes[selected_keys.at(i)];
|
||||
ca->append(new SetLong(&key.time, selected_keys_old_vals.at(i), key.time));
|
||||
ca->append(new SetQVariant(&key.data, selected_keys_old_doubles.at(i), key.data));
|
||||
}
|
||||
//ca->append(new KeyframeSet(row, selected_keys.at(i), 0, false));
|
||||
}
|
||||
|
||||
ca->append(new KeyframeMove(rows, selected_keys, selected_keys_old_vals, new_vals));
|
||||
undo_stack.push(ca);*/
|
||||
break;
|
||||
case BEZIER_HANDLE_PRE:
|
||||
{
|
||||
EffectKeyframe& key = row->field(selected_keys_fields.last())->keyframes[selected_keys.last()];
|
||||
ca->append(new SetDouble(&key.pre_handle_x, old_handle_x, key.pre_handle_x));
|
||||
ca->append(new SetDouble(&key.pre_handle_y, old_handle_y, key.pre_handle_y));
|
||||
}
|
||||
break;
|
||||
case BEZIER_HANDLE_POST:
|
||||
{
|
||||
EffectKeyframe& key = row->field(selected_keys_fields.last())->keyframes[selected_keys.last()];
|
||||
ca->append(new SetDouble(&key.post_handle_x, old_handle_x, key.post_handle_x));
|
||||
ca->append(new SetDouble(&key.post_handle_y, old_handle_y, key.post_handle_y));
|
||||
}
|
||||
break;
|
||||
}
|
||||
undo_stack.push(ca);
|
||||
}
|
||||
moved_keys = false;
|
||||
mousedown = false;
|
||||
@@ -269,19 +382,39 @@ void GraphView::set_row(EffectRow *r) {
|
||||
selected_keys_fields.clear();
|
||||
selected_keys_old_vals.clear();
|
||||
selected_keys_old_doubles.clear();
|
||||
emit selection_changed(false);
|
||||
emit selection_changed(false, -1);
|
||||
row = r;
|
||||
if (row != NULL) {
|
||||
field_visibility.resize(row->fieldCount());
|
||||
field_visibility.fill(true);
|
||||
}
|
||||
update();
|
||||
}
|
||||
|
||||
void GraphView::set_selected_keyframe_type(int type) {
|
||||
if (selected_keys.size() > 0) {
|
||||
ComboAction* ca = new ComboAction();
|
||||
for (int i=0;i<selected_keys.size();i++) {
|
||||
EffectKeyframe& key = row->field(selected_keys_fields.at(i))->keyframes[selected_keys.at(i)];
|
||||
ca->append(new SetInt(&key.type, type));
|
||||
}
|
||||
undo_stack.push(ca);
|
||||
update_ui(false);
|
||||
}
|
||||
}
|
||||
|
||||
void GraphView::set_field_visibility(int field, bool b) {
|
||||
field_visibility[field] = b;
|
||||
update();
|
||||
}
|
||||
|
||||
void GraphView::set_scroll_x(int s) {
|
||||
x_scroll = s;//qMax(0, s);
|
||||
dout << x_scroll;
|
||||
x_scroll = s;
|
||||
emit x_scroll_changed(x_scroll);
|
||||
}
|
||||
|
||||
void GraphView::set_scroll_y(int s) {
|
||||
y_scroll = s;//qMax(0, s);
|
||||
y_scroll = s;
|
||||
emit y_scroll_changed(y_scroll);
|
||||
}
|
||||
|
||||
|
||||
+11
-1
@@ -20,11 +20,14 @@ public:
|
||||
void wheelEvent(QWheelEvent *event);
|
||||
|
||||
void set_row(EffectRow* r);
|
||||
|
||||
void set_selected_keyframe_type(int type);
|
||||
void set_field_visibility(int field, bool b);
|
||||
signals:
|
||||
void x_scroll_changed(int);
|
||||
void y_scroll_changed(int);
|
||||
void zoom_changed(double);
|
||||
void selection_changed(bool);
|
||||
void selection_changed(bool, int);
|
||||
private:
|
||||
int x_scroll;
|
||||
int y_scroll;
|
||||
@@ -39,13 +42,20 @@ private:
|
||||
int get_screen_x(double);
|
||||
int get_screen_y(double);
|
||||
|
||||
QVector<bool> field_visibility;
|
||||
|
||||
QVector<int> selected_keys;
|
||||
QVector<int> selected_keys_fields;
|
||||
QVector<long> selected_keys_old_vals;
|
||||
QVector<double> selected_keys_old_doubles;
|
||||
|
||||
double old_handle_x;
|
||||
double old_handle_y;
|
||||
|
||||
bool moved_keys;
|
||||
|
||||
int current_handle;
|
||||
|
||||
EffectRow* row;
|
||||
};
|
||||
|
||||
|
||||
+75
-75
@@ -44,13 +44,13 @@ KeyframeView::KeyframeView(QWidget *parent) :
|
||||
}
|
||||
|
||||
void KeyframeView::show_context_menu(const QPoint& pos) {
|
||||
if (selected_fields.size() > 0) {
|
||||
if (selected_fields.size() > 0) {
|
||||
QMenu menu(this);
|
||||
|
||||
QAction* linear = menu.addAction("Linear");
|
||||
linear->setData(KEYFRAME_TYPE_LINEAR);
|
||||
QAction* smooth = menu.addAction("Smooth");
|
||||
smooth->setData(KEYFRAME_TYPE_BEZIER);
|
||||
QAction* bezier = menu.addAction("Bezier");
|
||||
bezier->setData(KEYFRAME_TYPE_BEZIER);
|
||||
QAction* hold = menu.addAction("Hold");
|
||||
hold->setData(KEYFRAME_TYPE_HOLD);
|
||||
menu.addSeparator();
|
||||
@@ -67,12 +67,12 @@ void KeyframeView::menu_set_key_type(QAction* a) {
|
||||
panel_graph_editor->show();
|
||||
} else {
|
||||
ComboAction* ca = new ComboAction();
|
||||
for (int i=0;i<selected_fields.size();i++) {
|
||||
EffectField* f = selected_fields.at(i);
|
||||
ca->append(new SetInt(&f->keyframes[selected_keyframes.at(i)].type, a->data().toInt()));
|
||||
for (int i=0;i<selected_fields.size();i++) {
|
||||
EffectField* f = selected_fields.at(i);
|
||||
ca->append(new SetInt(&f->keyframes[selected_keyframes.at(i)].type, a->data().toInt()));
|
||||
}
|
||||
undo_stack.push(ca);
|
||||
update_keys();
|
||||
update_ui(false);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -103,19 +103,19 @@ void KeyframeView::paintEvent(QPaintEvent*) {
|
||||
ClickableLabel* label = row->label;
|
||||
QWidget* contents = e->container->contents;
|
||||
|
||||
QVector<long> key_times;
|
||||
QVector<long> key_times;
|
||||
int keyframe_y = label->y() + (label->height()>>1) + mapFrom(panel_effect_controls, contents->mapTo(panel_effect_controls, contents->pos())).y() - e->container->title_bar->height()/* - y_scroll*/;
|
||||
for (int l=0;l<row->fieldCount();l++) {
|
||||
EffectField* f = row->field(l);
|
||||
for (int k=0;k<f->keyframes.size();k++) {
|
||||
if (!key_times.contains(f->keyframes.at(k).time)) {
|
||||
bool keyframe_selected = keyframeIsSelected(f, k);
|
||||
long keyframe_frame = adjust_row_keyframe(row, f->keyframes.at(k).time);
|
||||
draw_keyframe(p, f->keyframes.at(k).type, getScreenPointFromFrame(panel_effect_controls->zoom, keyframe_frame) - x_scroll, keyframe_y, keyframe_selected);
|
||||
key_times.append(f->keyframes.at(k).time);
|
||||
}
|
||||
}
|
||||
}
|
||||
for (int l=0;l<row->fieldCount();l++) {
|
||||
EffectField* f = row->field(l);
|
||||
for (int k=0;k<f->keyframes.size();k++) {
|
||||
if (!key_times.contains(f->keyframes.at(k).time)) {
|
||||
bool keyframe_selected = keyframeIsSelected(f, k);
|
||||
long keyframe_frame = adjust_row_keyframe(row, f->keyframes.at(k).time);
|
||||
draw_keyframe(p, f->keyframes.at(k).type, getScreenPointFromFrame(panel_effect_controls->zoom, keyframe_frame) - x_scroll, keyframe_y, keyframe_selected);
|
||||
key_times.append(f->keyframes.at(k).time);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
rows.append(row);
|
||||
rowY.append(keyframe_y);
|
||||
@@ -150,8 +150,8 @@ void KeyframeView::paintEvent(QPaintEvent*) {
|
||||
}
|
||||
|
||||
bool KeyframeView::keyframeIsSelected(EffectField *field, int keyframe) {
|
||||
for (int i=0;i<selected_fields.size();i++) {
|
||||
if (selected_fields.at(i) == field && selected_keyframes.at(i) == keyframe) {
|
||||
for (int i=0;i<selected_fields.size();i++) {
|
||||
if (selected_fields.at(i) == field && selected_keyframes.at(i) == keyframe) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -164,22 +164,22 @@ void KeyframeView::update_keys() {
|
||||
}
|
||||
|
||||
void KeyframeView::delete_selected_keyframes() {
|
||||
ComboAction* ca = new ComboAction();
|
||||
ComboAction* ca = new ComboAction();
|
||||
bool del = false;
|
||||
for (int i=0;i<selected_keyframes.size();i++) {
|
||||
// TODO these need to be sorted
|
||||
ca->append(new KeyframeDelete(selected_fields.at(i), selected_keyframes.at(i)));
|
||||
// TODO these need to be sorted
|
||||
ca->append(new KeyframeDelete(selected_fields.at(i), selected_keyframes.at(i)));
|
||||
del = true;
|
||||
}
|
||||
if (del) {
|
||||
undo_stack.push(ca);
|
||||
undo_stack.push(ca);
|
||||
|
||||
selected_keyframes.clear();
|
||||
selected_fields.clear();
|
||||
selected_fields.clear();
|
||||
update_keys();
|
||||
panel_sequence_viewer->viewer_widget->update();
|
||||
} else {
|
||||
delete ca;
|
||||
delete ca;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -211,7 +211,7 @@ void KeyframeView::mousePressEvent(QMouseEvent *event) {
|
||||
int mouse_x = event->x() + x_scroll;
|
||||
int mouse_y = event->y();
|
||||
int row_index = -1;
|
||||
int field_index = -1;
|
||||
int field_index = -1;
|
||||
int keyframe_index = -1;
|
||||
long frame_diff = 0;
|
||||
long frame_min = getFrameFromScreenPoint(panel_effect_controls->zoom, mouse_x-KEYFRAME_SIZE);
|
||||
@@ -223,41 +223,41 @@ void KeyframeView::mousePressEvent(QMouseEvent *event) {
|
||||
|
||||
row->focus_row();
|
||||
|
||||
for (int k=0;k<row->fieldCount();k++) {
|
||||
EffectField* f = row->field(k);
|
||||
for (int j=0;j<f->keyframes.size();j++) {
|
||||
long eval_keyframe_time = f->keyframes.at(j).time-row->parent_effect->parent_clip->clip_in+(row->parent_effect->parent_clip->timeline_in-visible_in);
|
||||
if (eval_keyframe_time >= frame_min && eval_keyframe_time <= frame_max) {
|
||||
long eval_frame_diff = qAbs(eval_keyframe_time - drag_frame_start);
|
||||
if (keyframe_index == -1 || eval_frame_diff < frame_diff) {
|
||||
row_index = i;
|
||||
field_index = k;
|
||||
keyframe_index = j;
|
||||
frame_diff = eval_frame_diff;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
for (int k=0;k<row->fieldCount();k++) {
|
||||
EffectField* f = row->field(k);
|
||||
for (int j=0;j<f->keyframes.size();j++) {
|
||||
long eval_keyframe_time = f->keyframes.at(j).time-row->parent_effect->parent_clip->clip_in+(row->parent_effect->parent_clip->timeline_in-visible_in);
|
||||
if (eval_keyframe_time >= frame_min && eval_keyframe_time <= frame_max) {
|
||||
long eval_frame_diff = qAbs(eval_keyframe_time - drag_frame_start);
|
||||
if (keyframe_index == -1 || eval_frame_diff < frame_diff) {
|
||||
row_index = i;
|
||||
field_index = k;
|
||||
keyframe_index = j;
|
||||
frame_diff = eval_frame_diff;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
bool already_selected = false;
|
||||
keys_selected = false;
|
||||
if (keyframe_index > -1) already_selected = keyframeIsSelected(rows.at(row_index)->field(field_index), keyframe_index);
|
||||
if (keyframe_index > -1) already_selected = keyframeIsSelected(rows.at(row_index)->field(field_index), keyframe_index);
|
||||
if (!already_selected) {
|
||||
if (!(event->modifiers() & Qt::ShiftModifier)) {
|
||||
selected_fields.clear();
|
||||
selected_fields.clear();
|
||||
selected_keyframes.clear();
|
||||
}
|
||||
if (keyframe_index > -1) {
|
||||
selected_fields.append(rows.at(row_index)->field(field_index));
|
||||
selected_fields.append(rows.at(row_index)->field(field_index));
|
||||
selected_keyframes.append(keyframe_index);
|
||||
}
|
||||
}
|
||||
|
||||
if (selected_fields.size() > 0) {
|
||||
for (int i=0;i<selected_fields.size();i++) {
|
||||
old_key_vals.append(selected_fields.at(i)->keyframes.at(selected_keyframes.at(i)).time);
|
||||
if (selected_fields.size() > 0) {
|
||||
for (int i=0;i<selected_fields.size();i++) {
|
||||
old_key_vals.append(selected_fields.at(i)->keyframes.at(selected_keyframes.at(i)).time);
|
||||
}
|
||||
|
||||
keys_selected = true;
|
||||
@@ -291,8 +291,8 @@ void KeyframeView::mouseMoveEvent(QMouseEvent* event) {
|
||||
panel_timeline->snapped = false;
|
||||
if (panel_timeline->snapping) {
|
||||
for (int i=0;i<selected_keyframes.size();i++) {
|
||||
EffectField* field = selected_fields.at(i);
|
||||
Clip* c = field->parent_row->parent_effect->parent_clip;
|
||||
EffectField* field = selected_fields.at(i);
|
||||
Clip* c = field->parent_row->parent_effect->parent_clip;
|
||||
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)) {
|
||||
@@ -303,11 +303,11 @@ void KeyframeView::mouseMoveEvent(QMouseEvent* event) {
|
||||
}
|
||||
|
||||
// validate frame_diff (make sure no keyframes overlap each other)
|
||||
for (int i=0;i<selected_fields.size();i++) {
|
||||
EffectField* field = selected_fields.at(i);
|
||||
for (int i=0;i<selected_fields.size();i++) {
|
||||
EffectField* field = selected_fields.at(i);
|
||||
long eval_key = old_key_vals.at(i);
|
||||
for (int j=0;j<field->keyframes.size();j++) {
|
||||
while (!keyframeIsSelected(field, j) && field->keyframes.at(j).time == eval_key + frame_diff) {
|
||||
for (int j=0;j<field->keyframes.size();j++) {
|
||||
while (!keyframeIsSelected(field, j) && field->keyframes.at(j).time == eval_key + frame_diff) {
|
||||
if (last_frame_diff > frame_diff) {
|
||||
frame_diff++;
|
||||
panel_timeline->snapped = false;
|
||||
@@ -321,8 +321,8 @@ void KeyframeView::mouseMoveEvent(QMouseEvent* event) {
|
||||
|
||||
// apply frame_diffs
|
||||
for (int i=0;i<selected_keyframes.size();i++) {
|
||||
EffectField* field = selected_fields.at(i);
|
||||
field->keyframes[selected_keyframes.at(i)].time = old_key_vals.at(i) + frame_diff;
|
||||
EffectField* field = selected_fields.at(i);
|
||||
field->keyframes[selected_keyframes.at(i)].time = old_key_vals.at(i) + frame_diff;
|
||||
}
|
||||
|
||||
last_frame_diff = frame_diff;
|
||||
@@ -346,16 +346,16 @@ void KeyframeView::mouseMoveEvent(QMouseEvent* event) {
|
||||
for (int i=0;i<rowY.size();i++) {
|
||||
if (rowY.at(i) >= min_row && rowY.at(i) <= max_row) {
|
||||
EffectRow* row = rows.at(i);
|
||||
for (int k=0;k<row->fieldCount();k++) {
|
||||
EffectField* field = row->field(k);
|
||||
for (int j=0;j<field->keyframes.size();j++) {
|
||||
long keyframe_frame = adjust_row_keyframe(row, field->keyframes.at(j).time);
|
||||
if (!keyframeIsSelected(field, j) && keyframe_frame >= min_frame && keyframe_frame <= max_frame) {
|
||||
selected_fields.append(field);
|
||||
selected_keyframes.append(j);
|
||||
}
|
||||
}
|
||||
}
|
||||
for (int k=0;k<row->fieldCount();k++) {
|
||||
EffectField* field = row->field(k);
|
||||
for (int j=0;j<field->keyframes.size();j++) {
|
||||
long keyframe_frame = adjust_row_keyframe(row, field->keyframes.at(j).time);
|
||||
if (!keyframeIsSelected(field, j) && keyframe_frame >= min_frame && keyframe_frame <= max_frame) {
|
||||
selected_fields.append(field);
|
||||
selected_keyframes.append(j);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -368,15 +368,15 @@ void KeyframeView::mouseMoveEvent(QMouseEvent* event) {
|
||||
|
||||
void KeyframeView::mouseReleaseEvent(QMouseEvent*) {
|
||||
if (dragging) {
|
||||
ComboAction* ca = new ComboAction();
|
||||
for (int i=0;i<selected_fields.size();i++) {
|
||||
ca->append(new SetLong(
|
||||
&selected_fields.at(i)->keyframes[selected_keyframes.at(i)].time,
|
||||
old_key_vals.at(i),
|
||||
selected_fields.at(i)->keyframes.at(selected_keyframes.at(i)).time
|
||||
));
|
||||
ComboAction* ca = new ComboAction();
|
||||
for (int i=0;i<selected_fields.size();i++) {
|
||||
ca->append(new SetLong(
|
||||
&selected_fields.at(i)->keyframes[selected_keyframes.at(i)].time,
|
||||
old_key_vals.at(i),
|
||||
selected_fields.at(i)->keyframes.at(selected_keyframes.at(i)).time
|
||||
));
|
||||
}
|
||||
undo_stack.push(ca);
|
||||
undo_stack.push(ca);
|
||||
}
|
||||
|
||||
select_rect = false;
|
||||
|
||||
Reference in New Issue
Block a user