diff --git a/project/effect.cpp b/project/effect.cpp index 0f75405b2..1be29a308 100644 --- a/project/effect.cpp +++ b/project/effect.cpp @@ -456,13 +456,11 @@ void Effect::copy_field_keyframes(Effect* e) { for (int i=0;irows.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;jfieldCount();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;kfieldCount();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;jkeyframe_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;jfieldCount();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;kkeyframe_data.size();k++) { - stream.writeTextElement("key", save_data_to_string(field->type, field->keyframe_data.at(k))); + for (int k=0;kkeyframes.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 } diff --git a/project/effectfield.cpp b/project/effectfield.cpp index f465e5e27..00435b91d 100644 --- a/project/effectfield.cpp +++ b/project/effectfield.cpp @@ -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;ikeyframe_times.size();i++) { - long eval_keyframe_time = parent_row->keyframe_times.at(i); + for (int i=0;ikeyframe_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(); + value = keyframes.at(before_keyframe).data.value(); } else { - QColor before_data = keyframe_data.at(before_keyframe).value(); - QColor after_data = keyframe_data.at(after_keyframe).value(); + QColor before_data = keyframes.at(before_keyframe).data.value(); + QColor after_data = keyframes.at(after_keyframe).data.value(); 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) { diff --git a/project/effectrow.cpp b/project/effectrow.cpp index 28d4cfaeb..db86e75f3 100644 --- a/project/effectrow.cpp +++ b/project/effectrow.cpp @@ -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;ikeyframes.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;iclip_in + c->timeline_in; - if (comp < sequence->playhead) { - key = qMax(comp, key); + for (int i=0;ikeyframes.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 key_fields; + QVector key_field_index; Clip* c = parent_effect->parent_clip; - for (int i=0;itimeline_in - c->clip_in + keyframe_times.at(i); - if (comp == sequence->playhead) { - index = i; - break; + for (int j=0;jkeyframes.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;iappend(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;itimeline_in - c->clip_in + keyframe_times.at(i); - if (comp > sequence->playhead) { - key = qMin(comp, key); + for (int i=0;ikeyframes.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;ikeyframes.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;ikeyframes.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); } diff --git a/project/effectrow.h b/project/effectrow.h index 672c00b16..a91171545 100644 --- a/project/effectrow.h +++ b/project/effectrow.h @@ -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; diff --git a/project/undo.cpp b/project/undo.cpp index b1a7caf04..5187d2a6e 100644 --- a/project/undo.cpp +++ b/project/undo.cpp @@ -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;ikeyframe_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;jfieldCount();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 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(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;ifieldCount();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;ifieldCount();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); diff --git a/project/undo.h b/project/undo.h index 1e9fde486..9ef3a1e3b 100644 --- a/project/undo.h +++ b/project/undo.h @@ -331,22 +331,21 @@ private: class KeyframeDelete : public QUndoCommand { public: - KeyframeDelete(); - QVector rows; - EffectRow* disable_keyframes_on_row; - QVector keyframes; + KeyframeDelete(EffectField* ifield, int iindex); void undo(); void redo(); private: - bool old_project_changed; - QVector 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 old_values; diff --git a/ui/graphview.cpp b/ui/graphview.cpp index 4fc859645..5accaacad 100644 --- a/ui/graphview.cpp +++ b/ui/graphview.cpp @@ -75,31 +75,34 @@ void GraphView::paintEvent(QPaintEvent *event) { QPen line_pen; line_pen.setWidth(2); - // sort keyframes by time - QVector sorted_keys; - for (int i=0;ikeyframe_times.size();i++) { - bool inserted = false; - for (int j=0;jkeyframe_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;ifieldCount();i++) { + EffectField* field = row->field(i); + + if (field->type == EFFECT_FIELD_DOUBLE) { + // sort keyframes by time + QVector sorted_keys; + for (int k=0;kkeyframes.size();k++) { + bool inserted = false; + for (int j=0;jkeyframes.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;ifieldCount();i++) { - EffectField* field = row->field(i); - if (field->type == EFFECT_FIELD_DOUBLE) { for (int j=0;jkeyframe_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;jkeyframe_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;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()); + for (int j=0;jkeyframes.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;ikeyframe_times.at(selected_keys.at(i))); - for (int j=0;jfield(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;ikeyframe_times[selected_keys.at(i)] = selected_keys_old_vals.at(i) + (double(event->pos().x() - start_x)/zoom); - for (int j=0;jfield(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 rows; QVector new_vals; - for (int i=0;ikeyframe_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; diff --git a/ui/keyframedrawing.cpp b/ui/keyframedrawing.cpp index 693a4e299..07d515957 100644 --- a/ui/keyframedrawing.cpp +++ b/ui/keyframedrawing.cpp @@ -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); } diff --git a/ui/keyframeview.cpp b/ui/keyframeview.cpp index b37f71b17..7518c4575 100644 --- a/ui/keyframeview.cpp +++ b/ui/keyframeview.cpp @@ -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;iappend(new SetInt(&selected_rows.at(i)->keyframe_types[selected_keyframes.at(i)], a->data().toInt())); + for (int i=0;iappend(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 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;kkeyframe_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;lfieldCount();l++) { + EffectField* f = row->field(l); + for (int k=0;kkeyframes.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;idelete_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;jkeyframe_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;kfieldCount();k++) { + EffectField* f = row->field(k); + for (int j=0;jkeyframes.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;ikeyframe_times.at(selected_keyframes.at(i))); + if (selected_fields.size() > 0) { + for (int i=0;ikeyframes.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;iparent_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;ikeyframe_times.size();j++) { - while (!keyframeIsSelected(row, j) && row->keyframe_times.at(j) == eval_key + frame_diff) { + for (int j=0;jkeyframes.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;ikeyframe_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= min_row && rowY.at(i) <= max_row) { EffectRow* row = rows.at(i); - for (int j=0;jkeyframe_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;kfieldCount();k++) { + EffectField* field = row->field(k); + for (int j=0;jkeyframes.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 new_key_vals; - for (int i=0;ikeyframe_times.at(selected_keyframes.at(i))); + ComboAction* ca = new ComboAction(); + for (int i=0;iappend(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; diff --git a/ui/keyframeview.h b/ui/keyframeview.h index 990bdef9e..59a328ed9 100644 --- a/ui/keyframeview.h +++ b/ui/keyframeview.h @@ -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 selected_rows; + QVector selected_fields; QVector selected_keyframes; QVector rowY; QVector 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;