refactored keyframes to fields rather than rows
This commit is contained in:
+21
-17
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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;
|
||||
|
||||
@@ -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
@@ -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
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user