refactored keyframes to fields rather than rows

This commit is contained in:
itsmattkc
2019-01-02 22:30:32 +11:00
parent 05524153ab
commit 37f21d2ff7
10 changed files with 236 additions and 245 deletions
+21 -17
View File
@@ -456,13 +456,11 @@ void Effect::copy_field_keyframes(Effect* e) {
for (int i=0;i<rows.size();i++) {
EffectRow* row = rows.at(i);
EffectRow* copy_row = e->rows.at(i);
copy_row->setKeyframing(row->isKeyframing());
copy_row->keyframe_times = row->keyframe_times;
copy_row->keyframe_types = row->keyframe_types;
copy_row->setKeyframing(row->isKeyframing());
for (int j=0;j<row->fieldCount();j++) {
EffectField* field = row->field(j);
copy_row->field(j)->set_current_data(field->get_current_data());
copy_row->field(j)->keyframe_data = field->keyframe_data;
EffectField* field = row->field(j);
EffectField* copy_field = copy_row->field(j);
copy_field->keyframes = field->keyframes;
}
}
}
@@ -633,8 +631,13 @@ void Effect::load(QXmlStreamReader& stream) {
keyframe_type = attr.value().toInt();
}
}
row->keyframe_times.append(keyframe_frame);
row->keyframe_types.append(keyframe_type);
for (int k=0;k<row->fieldCount();k++) {
EffectField* field = row->field(k);
EffectKeyframe key;
key.time = keyframe_frame;
key.type = keyframe_type;
field->keyframes.append(key);
}
}
stream.readNext();
}
@@ -677,13 +680,15 @@ void Effect::load(QXmlStreamReader& stream) {
}
}
int field_index = 0;
while (!stream.atEnd() && !(stream.name() == "field" && stream.isEndElement())) {
stream.readNext();
// read all keyframes
if (stream.name() == "key" && stream.isStartElement()) {
stream.readNext();
field->keyframe_data.append(load_data_from_string(field->type, stream.text().toString()));
field->keyframes[field_index].data = load_data_from_string(field->type, stream.text().toString());
field_index++;
}
}
} else {
@@ -711,20 +716,19 @@ void Effect::save(QXmlStreamWriter& stream) {
stream.writeStartElement("row"); // row
stream.writeStartElement("keyframes"); // keyframes
stream.writeAttribute("enabled", QString::number(row->isKeyframing()));
for (int j=0;j<row->keyframe_times.size();j++) {
stream.writeStartElement("key"); // key
stream.writeAttribute("frame", QString::number(row->keyframe_times.at(j)));
stream.writeAttribute("type", QString::number(row->keyframe_types.at(j)));
stream.writeEndElement(); // key
}
stream.writeEndElement(); // keyframes
for (int j=0;j<row->fieldCount();j++) {
EffectField* field = row->field(j);
stream.writeStartElement("field"); // field
stream.writeAttribute("id", field->id);
stream.writeAttribute("value", save_data_to_string(field->type, field->get_current_data()));
for (int k=0;k<field->keyframe_data.size();k++) {
stream.writeTextElement("key", save_data_to_string(field->type, field->keyframe_data.at(k)));
for (int k=0;k<field->keyframes.size();k++) {
const EffectKeyframe& key = field->keyframes.at(k);
stream.writeStartElement("key");
stream.writeAttribute("value", save_data_to_string(field->type, key.data));
stream.writeAttribute("frame", QString::number(key.time));
stream.writeAttribute("type", QString::number(key.type));
stream.writeEndElement(); // key
}
stream.writeEndElement(); // field
}
+11 -11
View File
@@ -121,8 +121,8 @@ void EffectField::get_keyframe_data(double timecode, int &before, int &after, do
long after_keyframe_time = LONG_MAX;
long frame = timecodeToFrame(timecode);
for (int i=0;i<parent_row->keyframe_times.size();i++) {
long eval_keyframe_time = parent_row->keyframe_times.at(i);
for (int i=0;i<keyframes.size();i++) {
long eval_keyframe_time = keyframes.at(i).time;
if (eval_keyframe_time == frame) {
before = i;
after = i;
@@ -141,7 +141,7 @@ void EffectField::get_keyframe_data(double timecode, int &before, int &after, do
before = before_keyframe_index;
after = after_keyframe_index;
if (parent_row->keyframe_types.at(before) == KEYFRAME_TYPE_HOLD) {
if (keyframes.at(before).type == KEYFRAME_TYPE_HOLD) {
progress = 0;
} else {
// TODO replace with bezier function
@@ -157,7 +157,7 @@ void EffectField::get_keyframe_data(double timecode, int &before, int &after, do
}
bool EffectField::hasKeyframes() {
return (parent_row->isKeyframing() && keyframe_data.size() > 0);
return (parent_row->isKeyframing() && keyframes.size() > 0);
}
QVariant EffectField::validate_keyframe_data(double timecode, bool async) {
@@ -175,16 +175,16 @@ QVariant EffectField::validate_keyframe_data(double timecode, bool async) {
progress -= 0.01865;
}*/
const QVariant& before_data = keyframe_data.at(before_keyframe);
const QVariant& before_data = keyframes.at(before_keyframe).data;
switch (type) {
case EFFECT_FIELD_DOUBLE:
{
double value;
if (before_keyframe == after_keyframe) {
value = keyframe_data.at(before_keyframe).toDouble();
value = keyframes.at(before_keyframe).data.toDouble();
} else {
double before_dbl = keyframe_data.at(before_keyframe).toDouble();
double after_dbl = keyframe_data.at(after_keyframe).toDouble();
double before_dbl = keyframes.at(before_keyframe).data.toDouble();
double after_dbl = keyframes.at(after_keyframe).data.toDouble();
value = double_lerp(before_dbl, after_dbl, progress);
}
if (async) {
@@ -197,10 +197,10 @@ QVariant EffectField::validate_keyframe_data(double timecode, bool async) {
{
QColor value;
if (before_keyframe == after_keyframe) {
value = keyframe_data.at(before_keyframe).value<QColor>();
value = keyframes.at(before_keyframe).data.value<QColor>();
} else {
QColor before_data = keyframe_data.at(before_keyframe).value<QColor>();
QColor after_data = keyframe_data.at(after_keyframe).value<QColor>();
QColor before_data = keyframes.at(before_keyframe).data.value<QColor>();
QColor after_data = keyframes.at(after_keyframe).data.value<QColor>();
value = QColor(lerp(before_data.red(), after_data.red(), progress), lerp(before_data.green(), after_data.green(), progress), lerp(before_data.blue(), after_data.blue(), progress));
}
if (async) {
+58 -43
View File
@@ -61,12 +61,14 @@ void EffectRow::set_keyframe_enabled(bool enabled) {
} else {
if (QMessageBox::question(panel_effect_controls, "Disable Keyframes", "Disabling keyframes will delete all current keyframes. Are you sure you want to do this?", QMessageBox::Yes, QMessageBox::No) == QMessageBox::Yes) {
// clear
KeyframeDelete* kd = new KeyframeDelete();
for (int i=keyframe_times.size()-1;i>=0;i--) {
delete_keyframe(kd, i);
ComboAction* ca = new ComboAction();
for (int i=0;i<fieldCount();i++) {
EffectField* f = field(i);
for (int j=0;j<f->keyframes.size();j++) {
ca->append(new KeyframeDelete(f, 0));
}
}
kd->disable_keyframes_on_row = this;
undo_stack.push(kd);
undo_stack.push(ca);
panel_effect_controls->update_keyframes();
} else {
setKeyframing(true);
@@ -77,49 +79,61 @@ void EffectRow::set_keyframe_enabled(bool enabled) {
void EffectRow::goto_previous_key() {
long key = LONG_MIN;
Clip* c = parent_effect->parent_clip;
for (int i=0;i<keyframe_times.size();i++) {
long comp = keyframe_times.at(i) - c->clip_in + c->timeline_in;
if (comp < sequence->playhead) {
key = qMax(comp, key);
for (int i=0;i<fieldCount();i++) {
EffectField* f = field(i);
for (int j=0;j<f->keyframes.size();j++) {
long comp = f->keyframes.at(i).time - c->clip_in + c->timeline_in;
if (comp < sequence->playhead) {
key = qMax(comp, key);
}
}
}
if (key != LONG_MIN) panel_sequence_viewer->seek(key);
}
void EffectRow::toggle_key() {
int index = -1;
QVector<EffectField*> key_fields;
QVector<int> key_field_index;
Clip* c = parent_effect->parent_clip;
for (int i=0;i<keyframe_times.size();i++) {
long comp = c->timeline_in - c->clip_in + keyframe_times.at(i);
if (comp == sequence->playhead) {
index = i;
break;
for (int j=0;j<fieldCount();j++) {
EffectField* f = field(j);
for (int i=0;i<f->keyframes.size();i++) {
long comp = c->timeline_in - c->clip_in + f->keyframes.at(i).time;
if (comp == sequence->playhead) {
key_fields.append(f);
key_field_index.append(i);
}
}
}
if (index < 0) {
ComboAction* ca = new ComboAction();
if (key_fields.size() == 0) {
// keyframe doesn't exist, set one
ComboAction* ca = new ComboAction();
set_keyframe_now(ca);
undo_stack.push(ca);
} else {
KeyframeDelete* kd = new KeyframeDelete();
delete_keyframe(kd, index);
undo_stack.push(kd);
panel_effect_controls->update_keyframes();
panel_sequence_viewer->viewer_widget->update();
for (int i=0;i<key_fields.size();i++) {
// TODO: these values must be sorted to work correctly
ca->append(new KeyframeDelete(key_fields.at(i), key_field_index.at(i)));
}
}
undo_stack.push(ca);
panel_effect_controls->update_keyframes();
panel_sequence_viewer->viewer_widget->update();
}
void EffectRow::goto_next_key() {
long key = LONG_MAX;
Clip* c = parent_effect->parent_clip;
for (int i=0;i<keyframe_times.size();i++) {
long comp = c->timeline_in - c->clip_in + keyframe_times.at(i);
if (comp > sequence->playhead) {
key = qMin(comp, key);
for (int i=0;i<fieldCount();i++) {
EffectField* f = field(i);
for (int j=0;j<f->keyframes.size();j++) {
long comp = f->keyframes.at(i).time - c->clip_in + c->timeline_in;
if (comp > sequence->playhead) {
key = qMax(comp, key);
}
}
}
if (key != LONG_MAX) panel_sequence_viewer->seek(key);
if (key != LONG_MAX) panel_sequence_viewer->seek(key);
}
void EffectRow::focus_row() {
@@ -145,10 +159,13 @@ EffectRow::~EffectRow() {
void EffectRow::set_keyframe_now(ComboAction* ca) {
int index = -1;
long time = sequence->playhead-parent_effect->parent_clip->timeline_in+parent_effect->parent_clip->clip_in;
for (int i=0;i<keyframe_times.size();i++) {
if (keyframe_times.at(i) == time) {
index = i;
break;
for (int j=0;j<fieldCount();j++) {
EffectField* f = field(j);
for (int i=0;i<f->keyframes.size();i++) {
if (f->keyframes.at(i).time == time) {
index = i;
break;
}
}
}
@@ -166,24 +183,22 @@ void EffectRow::set_keyframe_now(ComboAction* ca) {
panel_effect_controls->update_keyframes();
}
void EffectRow::delete_keyframe_at_time(KeyframeDelete* kd, long time) {
for (int i=0;i<keyframe_times.size();i++) {
if (keyframe_times.at(i) == time) {
delete_keyframe(kd, i);
break;
void EffectRow::delete_keyframe_at_time(ComboAction* ca, long time) {
for (int j=0;j<fieldCount();j++) {
EffectField* f = field(j);
for (int i=0;i<f->keyframes.size();i++) {
if (f->keyframes.at(i).time == time) {
ca->append(new KeyframeDelete(f, i));
break;
}
}
}
}
}
const QString &EffectRow::get_name() {
return name;
}
void EffectRow::delete_keyframe(KeyframeDelete* kd, int index) {
kd->rows.append(this);
kd->keyframes.append(index);
}
EffectField* EffectRow::field(int i) {
return fields.at(i);
}
+2 -3
View File
@@ -23,9 +23,8 @@ public:
EffectField* add_field(int type, const QString &id, int colspan = 1);
EffectField* field(int i);
int fieldCount();
void set_keyframe_now(ComboAction *ca);
void delete_keyframe(KeyframeDelete *kd, int index);
void delete_keyframe_at_time(KeyframeDelete* kd, long time);
void set_keyframe_now(ComboAction *ca);
void delete_keyframe_at_time(ComboAction *ca, long time);
ClickableLabel* label;
Effect* parent_effect;
bool savable;
+19 -70
View File
@@ -737,69 +737,21 @@ void MediaRename::redo() {
mainWindow->setWindowModified(true);
}
KeyframeDelete::KeyframeDelete() :
disable_keyframes_on_row(NULL),
old_project_changed(mainWindow->isWindowModified()),
sorted(false)
KeyframeDelete::KeyframeDelete(EffectField *ifield, int iindex) :
field(ifield),
index(iindex),
old_project_changed(mainWindow->isWindowModified())
{}
void KeyframeDelete::undo() {
if (disable_keyframes_on_row != NULL) disable_keyframes_on_row->setKeyframing(true);
int data_index = deleted_keyframe_data.size()-1;
for (int i=rows.size()-1;i>=0;i--) {
EffectRow* row = rows.at(i);
int keyframe_index = keyframes.at(i);
row->keyframe_times.insert(keyframe_index, deleted_keyframe_times.at(i));
row->keyframe_types.insert(keyframe_index, deleted_keyframe_types.at(i));
for (int j=row->fieldCount()-1;j>=0;j--) {
row->field(j)->keyframe_data.insert(keyframe_index, deleted_keyframe_data.at(data_index));
data_index--;
}
}
field->keyframes.insert(index, deleted_key);
mainWindow->setWindowModified(old_project_changed);
}
void KeyframeDelete::redo() {
if (!sorted) {
deleted_keyframe_times.resize(rows.size());
deleted_keyframe_types.resize(rows.size());
deleted_keyframe_data.clear();
}
for (int i=0;i<keyframes.size();i++) {
EffectRow* row = rows.at(i);
int keyframe_index = keyframes.at(i);
if (!sorted) {
deleted_keyframe_times[i] = (row->keyframe_times.at(keyframe_index));
deleted_keyframe_types[i] = (row->keyframe_types.at(keyframe_index));
}
row->keyframe_times.removeAt(keyframe_index);
row->keyframe_types.removeAt(keyframe_index);
for (int j=0;j<row->fieldCount();j++) {
if (!sorted) deleted_keyframe_data.append(row->field(j)->keyframe_data.at(keyframe_index));
row->field(j)->keyframe_data.removeAt(keyframe_index);
}
// correct following indices
if (!sorted) {
for (int j=i+1;j<keyframes.size();j++) {
if (rows.at(j) == row && keyframes.at(j) > keyframe_index) {
keyframes[j]--;
}
}
}
}
if (disable_keyframes_on_row != NULL) disable_keyframes_on_row->setKeyframing(false);
mainWindow->setWindowModified(true);
sorted = true;
deleted_key = field->keyframes.at(index);
field->keyframes.removeAt(index);
mainWindow->setWindowModified(true);
}
KeyframeSet::KeyframeSet(EffectRow* r, int i, long t, bool justMadeKeyframe) :
@@ -819,7 +771,7 @@ KeyframeSet::KeyframeSet(EffectRow* r, int i, long t, bool justMadeKeyframe) :
if (field->type == EFFECT_FIELD_DOUBLE) {
old_values[i] = static_cast<LabelSlider*>(field->ui_element)->getPreviousValue();
} else {
old_values[i] = field->keyframe_data.at(index);
old_values[i] = field->keyframes.at(index).data;
}
}
new_values[i] = field->get_current_data();
@@ -829,16 +781,12 @@ KeyframeSet::KeyframeSet(EffectRow* r, int i, long t, bool justMadeKeyframe) :
void KeyframeSet::undo() {
if (enable_keyframes) row->setKeyframing(false);
bool append = (index == -1 || just_made_keyframe);
if (append) {
row->keyframe_times.removeLast();
row->keyframe_types.removeLast();
}
bool append = (index == -1 || just_made_keyframe);
for (int i=0;i<row->fieldCount();i++) {
if (append) {
row->field(i)->keyframe_data.removeLast();
row->field(i)->keyframes.removeLast();
} else {
row->field(i)->keyframe_data[index] = old_values.at(i);
row->field(i)->keyframes[index].data = old_values.at(i);
}
}
@@ -848,15 +796,16 @@ void KeyframeSet::undo() {
void KeyframeSet::redo() {
bool append = (index == -1 || (just_made_keyframe && !done));
if (append) {
row->keyframe_times.append(time);
row->keyframe_types.append((row->keyframe_types.size() > 0) ? row->keyframe_types.last() : EFFECT_KEYFRAME_LINEAR);
}
for (int i=0;i<row->fieldCount();i++) {
EffectField* f = row->field(i);
if (append) {
row->field(i)->keyframe_data.append(new_values.at(i));
EffectKeyframe k;
k.data = new_values.at(i);
k.time = time;
k.type = (f->keyframes.size() > 0) ? f->keyframes.last().type : EFFECT_KEYFRAME_LINEAR;
f->keyframes.append(k);
} else {
row->field(i)->keyframe_data[index] = new_values.at(i);
f->keyframes[index].data = new_values.at(i);
}
}
row->setKeyframing(true);
+7 -8
View File
@@ -331,22 +331,21 @@ private:
class KeyframeDelete : public QUndoCommand {
public:
KeyframeDelete();
QVector<EffectRow*> rows;
EffectRow* disable_keyframes_on_row;
QVector<int> keyframes;
KeyframeDelete(EffectField* ifield, int iindex);
void undo();
void redo();
private:
bool old_project_changed;
QVector<EffectKeyframe> deleted_keyframe_times;
bool sorted;
EffectField* field;
int index;
bool done;
EffectKeyframe deleted_key;
bool old_project_changed;
};
class KeyframeSet : public QUndoCommand {
public:
KeyframeSet(EffectRow* r, int i, long t, bool justMadeKeyframe);
KeyframeSet(EffectRow* r, int i, long t, bool justMadeKeyframe);
void undo();
void redo();
QVector<QVariant> old_values;
+40 -38
View File
@@ -75,31 +75,34 @@ void GraphView::paintEvent(QPaintEvent *event) {
QPen line_pen;
line_pen.setWidth(2);
// sort keyframes by time
QVector<int> sorted_keys;
for (int i=0;i<row->keyframe_times.size();i++) {
bool inserted = false;
for (int j=0;j<sorted_keys.size();j++) {
if (row->keyframe_times.at(sorted_keys.at(j)) > row->keyframe_times.at(i)) {
sorted_keys.insert(j, i);
inserted = true;
break;
}
}
if (!inserted) {
sorted_keys.append(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);
}
}
int last_key_x, last_key_y;
int last_key_x, last_key_y;
for (int i=0;i<row->fieldCount();i++) {
EffectField* field = row->field(i);
if (field->type == EFFECT_FIELD_DOUBLE) {
for (int j=0;j<sorted_keys.size();j++) {
// draw lines
int key_index = sorted_keys.at(j);
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_x = get_screen_x(field->keyframes.at(key_index).time);
int key_y = get_screen_y(field->keyframes.at(key_index).data.toDouble());
line_pen.setColor(get_curve_color(i, row->fieldCount()));
p.setPen(line_pen);
@@ -112,14 +115,14 @@ void GraphView::paintEvent(QPaintEvent *event) {
last_key_y = key_y;
}
for (int j=0;j<sorted_keys.size();j++) {
// draw keys
int key_index = sorted_keys.at(j);
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_x = get_screen_x(field->keyframes.at(key_index).time);
int key_y = get_screen_y(field->keyframes.at(key_index).data.toDouble());
draw_keyframe(p, row->keyframe_types.at(key_index), key_x, key_y, (selected_keys.contains(key_index) && selected_keys_fields.contains(i)));
draw_keyframe(p, field->keyframes.at(key_index).type, key_x, key_y, (selected_keys.contains(key_index) && selected_keys_fields.contains(i)));
}
p.setBrush(Qt::NoBrush);
}
}
}
@@ -154,9 +157,9 @@ void GraphView::mousePressEvent(QMouseEvent *event) {
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());
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 (event->pos().x() > key_x-KEYFRAME_SIZE
&& event->pos().x() < key_x+KEYFRAME_SIZE
&& event->pos().y() > key_y-KEYFRAME_SIZE
@@ -177,10 +180,9 @@ void GraphView::mousePressEvent(QMouseEvent *event) {
selected_keys_old_vals.clear();
selected_keys_old_doubles.clear();
for (int i=0;i<selected_keys.size();i++) {
selected_keys_old_vals.append(row->keyframe_times.at(selected_keys.at(i)));
for (int j=0;j<selected_keys_fields.size();j++) {
selected_keys_old_doubles.append(row->field(selected_keys_fields.at(j))->keyframe_data.at(selected_keys.at(i)).toDouble());
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());
}
}
@@ -199,10 +201,10 @@ void GraphView::mouseMoveEvent(QMouseEvent *event) {
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);
for (int j=0;j<selected_keys_fields.size();j++) {
row->field(selected_keys_fields.at(j))->keyframe_data[selected_keys.at(i)] = selected_keys_old_doubles.at((i*selected_keys_fields.size())+j) + (double(start_y - event->pos().y())/zoom);
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);
}
}
moved_keys = true;
@@ -213,11 +215,11 @@ void GraphView::mouseMoveEvent(QMouseEvent *event) {
void GraphView::mouseReleaseEvent(QMouseEvent *event) {
if (moved_keys && selected_keys.size() > 0) {
ComboAction* ca = new ComboAction();
/*ComboAction* ca = new ComboAction();
QVector<EffectRow*> rows;
QVector<long> new_vals;
for (int i=0;i<selected_keys.size();i++) {
for (int i=0;i<selected_keys.size();i++) {
rows.append(row);
new_vals.append(row->keyframe_times.at(selected_keys.at(i)));
@@ -227,10 +229,10 @@ void GraphView::mouseReleaseEvent(QMouseEvent *event) {
row->field(selected_keys_fields.at(j))->keyframe_data.at(selected_keys.at(i))));
}
//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);
undo_stack.push(ca);*/
}
moved_keys = false;
mousedown = false;
+2
View File
@@ -23,4 +23,6 @@ void draw_keyframe(QPainter &p, int type, int x, int y, bool darker) {
p.drawRect(QRect(x - KEYFRAME_SIZE, y - KEYFRAME_SIZE, KEYFRAME_SIZE*2, KEYFRAME_SIZE*2));
break;
}
p.setBrush(Qt::NoBrush);
}
+73 -53
View File
@@ -44,7 +44,7 @@ KeyframeView::KeyframeView(QWidget *parent) :
}
void KeyframeView::show_context_menu(const QPoint& pos) {
if (selected_rows.size() > 0) {
if (selected_fields.size() > 0) {
QMenu menu(this);
QAction* linear = menu.addAction("Linear");
@@ -67,8 +67,9 @@ void KeyframeView::menu_set_key_type(QAction* a) {
panel_graph_editor->show();
} else {
ComboAction* ca = new ComboAction();
for (int i=0;i<selected_rows.size();i++) {
ca->append(new SetInt(&selected_rows.at(i)->keyframe_types[selected_keyframes.at(i)], 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();
@@ -102,12 +103,19 @@ void KeyframeView::paintEvent(QPaintEvent*) {
ClickableLabel* label = row->label;
QWidget* contents = e->container->contents;
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 k=0;k<row->keyframe_times.size();k++) {
bool keyframe_selected = keyframeIsSelected(row, k);
long keyframe_frame = adjust_row_keyframe(row, row->keyframe_times.at(k));
draw_keyframe(p, row->keyframe_types.at(k), getScreenPointFromFrame(panel_effect_controls->zoom, keyframe_frame) - x_scroll, keyframe_y, keyframe_selected);
}
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);
@@ -141,9 +149,9 @@ void KeyframeView::paintEvent(QPaintEvent*) {
}*/
}
bool KeyframeView::keyframeIsSelected(EffectRow *row, int keyframe) {
for (int i=0;i<selected_rows.size();i++) {
if (selected_rows.at(i) == row && selected_keyframes.at(i) == keyframe) {
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) {
return true;
}
}
@@ -156,21 +164,22 @@ void KeyframeView::update_keys() {
}
void KeyframeView::delete_selected_keyframes() {
KeyframeDelete* kd = new KeyframeDelete();
ComboAction* ca = new ComboAction();
bool del = false;
for (int i=0;i<selected_keyframes.size();i++) {
selected_rows.at(i)->delete_keyframe(kd, 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(kd);
undo_stack.push(ca);
selected_keyframes.clear();
selected_rows.clear();
selected_fields.clear();
update_keys();
panel_sequence_viewer->viewer_widget->update();
} else {
delete kd;
delete ca;
}
}
@@ -202,6 +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 keyframe_index = -1;
long frame_diff = 0;
long frame_min = getFrameFromScreenPoint(panel_effect_controls->zoom, mouse_x-KEYFRAME_SIZE);
@@ -213,37 +223,41 @@ void KeyframeView::mousePressEvent(QMouseEvent *event) {
row->focus_row();
for (int j=0;j<row->keyframe_times.size();j++) {
long eval_keyframe_time = row->keyframe_times.at(j)-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;
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), 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_rows.clear();
selected_fields.clear();
selected_keyframes.clear();
}
if (keyframe_index > -1) {
selected_rows.append(rows.at(row_index));
selected_fields.append(rows.at(row_index)->field(field_index));
selected_keyframes.append(keyframe_index);
}
}
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)));
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;
@@ -277,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++) {
EffectRow* row = selected_rows.at(i);
Clip* c = 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)) {
@@ -289,11 +303,11 @@ void KeyframeView::mouseMoveEvent(QMouseEvent* event) {
}
// validate frame_diff (make sure no keyframes overlap each other)
for (int i=0;i<selected_rows.size();i++) {
EffectRow* row = selected_rows.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<row->keyframe_times.size();j++) {
while (!keyframeIsSelected(row, j) && row->keyframe_times.at(j) == 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;
@@ -307,8 +321,8 @@ 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;
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;
@@ -332,13 +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 j=0;j<row->keyframe_times.size();j++) {
long keyframe_frame = adjust_row_keyframe(row, row->keyframe_times.at(j));
if (!keyframeIsSelected(row, j) && keyframe_frame >= min_frame && keyframe_frame <= max_frame) {
selected_rows.append(rows.at(i));
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);
}
}
}
}
}
@@ -351,12 +368,15 @@ void KeyframeView::mouseMoveEvent(QMouseEvent* event) {
void KeyframeView::mouseReleaseEvent(QMouseEvent*) {
if (dragging) {
QVector<long> new_key_vals;
for (int i=0;i<selected_rows.size();i++) {
new_key_vals.append(selected_rows.at(i)->keyframe_times.at(selected_keyframes.at(i)));
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(new KeyframeMove(selected_rows, selected_keyframes, old_key_vals, new_key_vals));
undo_stack.push(ca);
}
select_rect = false;
+3 -2
View File
@@ -7,6 +7,7 @@
struct Clip;
class Effect;
class EffectRow;
class EffectField;
class TimelineHeader;
class KeyframeView : public QWidget {
@@ -26,7 +27,7 @@ public slots:
void resize_move(double d);
private:
long adjust_row_keyframe(EffectRow* row, long time);
QVector<EffectRow*> selected_rows;
QVector<EffectField*> selected_fields;
QVector<int> selected_keyframes;
QVector<int> rowY;
QVector<EffectRow*> rows;
@@ -41,7 +42,7 @@ private:
bool select_rect;
bool scroll_drag;
bool keyframeIsSelected(EffectRow* row, int keyframe);
bool keyframeIsSelected(EffectField *field, int keyframe);
long drag_frame_start;
long last_frame_diff;