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;