decoupled ui from effect row
This commit is contained in:
+2
-2
@@ -442,8 +442,8 @@ void Clip::refactor_frame_rate(ComboAction* ca, double multiplier, bool change_t
|
||||
EffectPtr e = effects.at(i);
|
||||
for (int j=0;j<e->row_count();j++) {
|
||||
EffectRow* r = e->row(j);
|
||||
for (int l=0;l<r->fieldCount();l++) {
|
||||
EffectField* f = r->field(l);
|
||||
for (int l=0;l<r->FieldCount();l++) {
|
||||
EffectField* f = r->Field(l);
|
||||
for (int k=0;k<f->keyframes.size();k++) {
|
||||
ca->append(new SetLong(&f->keyframes[k].time, f->keyframes[k].time, qRound(f->keyframes[k].time * multiplier)));
|
||||
}
|
||||
|
||||
+52
-61
@@ -153,7 +153,7 @@ Effect::Effect(Clip* c, const EffectMeta *em) :
|
||||
}
|
||||
}
|
||||
if (!row_name.isEmpty()) {
|
||||
EffectRow* row = add_row(row_name);
|
||||
EffectRow* row = new EffectRow(this, row_name);
|
||||
while (!reader.atEnd() && !(reader.name() == "row" && reader.isEndElement())) {
|
||||
reader.readNext();
|
||||
if (reader.name() == "field" && reader.isStartElement()) {
|
||||
@@ -356,9 +356,6 @@ Effect::~Effect() {
|
||||
|
||||
delete container;
|
||||
|
||||
for (int i=0;i<rows.size();i++) {
|
||||
delete rows.at(i);
|
||||
}
|
||||
for (int i=0;i<gizmos.size();i++) {
|
||||
delete gizmos.at(i);
|
||||
}
|
||||
@@ -368,13 +365,13 @@ void Effect::copy_field_keyframes(EffectPtr 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());
|
||||
for (int j=0;j<row->fieldCount();j++) {
|
||||
copy_row->SetKeyframing(row->IsKeyframing());
|
||||
for (int j=0;j<row->FieldCount();j++) {
|
||||
// Get field from this (the source) effect
|
||||
EffectField* field = row->field(j);
|
||||
EffectField* field = row->Field(j);
|
||||
|
||||
// Get field from the destination effect
|
||||
EffectField* copy_field = copy_row->field(j);
|
||||
EffectField* copy_field = copy_row->Field(j);
|
||||
|
||||
// Copy keyframes between effects
|
||||
copy_field->keyframes = field->keyframes;
|
||||
@@ -382,12 +379,6 @@ void Effect::copy_field_keyframes(EffectPtr e) {
|
||||
}
|
||||
}
|
||||
|
||||
EffectRow* Effect::add_row(const QString& name, bool savable, bool keyframable) {
|
||||
EffectRow* row = new EffectRow(this, savable, ui_layout, name, rows.size(), keyframable);
|
||||
rows.append(row);
|
||||
return row;
|
||||
}
|
||||
|
||||
EffectRow* Effect::row(int i) {
|
||||
return rows.at(i);
|
||||
}
|
||||
@@ -575,30 +566,30 @@ void Effect::load(QXmlStreamReader& stream) {
|
||||
if (stream.name() == "row" && stream.isStartElement()) {
|
||||
if (row_count < rows.size()) {
|
||||
EffectRow* row = rows.at(row_count);
|
||||
int field_count = 0;
|
||||
|
||||
while (!stream.atEnd() && !(stream.name() == "row" && stream.isEndElement())) {
|
||||
stream.readNext();
|
||||
|
||||
// read field
|
||||
if (stream.name() == "field" && stream.isStartElement()) {
|
||||
if (field_count < row->fieldCount()) {
|
||||
// match field using ID
|
||||
int field_number = field_count;
|
||||
for (int k=0;k<stream.attributes().size();k++) {
|
||||
const QXmlStreamAttribute& attr = stream.attributes().at(k);
|
||||
if (attr.name() == "id") {
|
||||
for (int l=0;l<row->fieldCount();l++) {
|
||||
if (row->field(l)->id() == attr.value()) {
|
||||
field_number = l;
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
int field_number = -1;
|
||||
|
||||
EffectField* field = row->field(field_number);
|
||||
// match field using ID
|
||||
for (int k=0;k<stream.attributes().size();k++) {
|
||||
const QXmlStreamAttribute& attr = stream.attributes().at(k);
|
||||
if (attr.name() == "id") {
|
||||
for (int l=0;l<row->FieldCount();l++) {
|
||||
if (row->Field(l)->id() == attr.value()) {
|
||||
field_number = l;
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (field_number > -1) {
|
||||
EffectField* field = row->Field(field_number);
|
||||
|
||||
// get current field value
|
||||
/*
|
||||
@@ -616,7 +607,7 @@ void Effect::load(QXmlStreamReader& stream) {
|
||||
|
||||
// read keyframes
|
||||
if (stream.name() == "key" && stream.isStartElement()) {
|
||||
row->setKeyframing(true);
|
||||
row->SetKeyframing(true);
|
||||
|
||||
EffectKeyframe key;
|
||||
for (int k=0;k<stream.attributes().size();k++) {
|
||||
@@ -640,10 +631,7 @@ void Effect::load(QXmlStreamReader& stream) {
|
||||
field->keyframes.append(key);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
qCritical() << "Too many fields for effect" << id << "row" << row_count << ". Project might be corrupt. (Got" << field_count << ", expected <" << row->fieldCount()-1 << ")";
|
||||
}
|
||||
field_count++;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -665,25 +653,28 @@ void Effect::save(QXmlStreamWriter& stream) {
|
||||
|
||||
for (int i=0;i<rows.size();i++) {
|
||||
EffectRow* row = rows.at(i);
|
||||
if (row->savable) {
|
||||
if (row->IsSavable()) {
|
||||
stream.writeStartElement("row"); // row
|
||||
for (int j=0;j<row->fieldCount();j++) {
|
||||
EffectField* field = row->field(j);
|
||||
stream.writeStartElement("field"); // field
|
||||
stream.writeAttribute("id", field->id());
|
||||
for (int k=0;k<field->keyframes.size();k++) {
|
||||
const EffectKeyframe& key = field->keyframes.at(k);
|
||||
stream.writeStartElement("key");
|
||||
stream.writeAttribute("value", field->ConvertValueToString(key.data));
|
||||
stream.writeAttribute("frame", QString::number(key.time));
|
||||
stream.writeAttribute("type", QString::number(key.type));
|
||||
stream.writeAttribute("prehx", QString::number(key.pre_handle_x));
|
||||
stream.writeAttribute("prehy", QString::number(key.pre_handle_y));
|
||||
stream.writeAttribute("posthx", QString::number(key.post_handle_x));
|
||||
stream.writeAttribute("posthy", QString::number(key.post_handle_y));
|
||||
stream.writeEndElement(); // key
|
||||
for (int j=0;j<row->FieldCount();j++) {
|
||||
EffectField* field = row->Field(j);
|
||||
|
||||
if (field->id().isEmpty()) {
|
||||
stream.writeStartElement("field"); // field
|
||||
stream.writeAttribute("id", field->id());
|
||||
for (int k=0;k<field->keyframes.size();k++) {
|
||||
const EffectKeyframe& key = field->keyframes.at(k);
|
||||
stream.writeStartElement("key");
|
||||
stream.writeAttribute("value", field->ConvertValueToString(key.data));
|
||||
stream.writeAttribute("frame", QString::number(key.time));
|
||||
stream.writeAttribute("type", QString::number(key.type));
|
||||
stream.writeAttribute("prehx", QString::number(key.pre_handle_x));
|
||||
stream.writeAttribute("prehy", QString::number(key.pre_handle_y));
|
||||
stream.writeAttribute("posthx", QString::number(key.post_handle_x));
|
||||
stream.writeAttribute("posthy", QString::number(key.post_handle_y));
|
||||
stream.writeEndElement(); // key
|
||||
}
|
||||
stream.writeEndElement(); // field
|
||||
}
|
||||
stream.writeEndElement(); // field
|
||||
}
|
||||
stream.writeEndElement(); // row
|
||||
}
|
||||
@@ -694,9 +685,9 @@ void Effect::load_from_string(const QByteArray &s) {
|
||||
// clear existing keyframe data
|
||||
for (int i=0;i<rows.size();i++) {
|
||||
EffectRow* row = rows.at(i);
|
||||
row->setKeyframing(false);
|
||||
for (int j=0;j<row->fieldCount();j++) {
|
||||
EffectField* field = row->field(j);
|
||||
row->SetKeyframing(false);
|
||||
for (int j=0;j<row->FieldCount();j++) {
|
||||
EffectField* field = row->Field(j);
|
||||
field->keyframes.clear();
|
||||
}
|
||||
}
|
||||
@@ -884,8 +875,8 @@ void Effect::process_shader(double timecode, GLTextureCoords&, int iteration) {
|
||||
|
||||
for (int i=0;i<rows.size();i++) {
|
||||
EffectRow* row = rows.at(i);
|
||||
for (int j=0;j<row->fieldCount();j++) {
|
||||
EffectField* field = row->field(j);
|
||||
for (int j=0;j<row->FieldCount();j++) {
|
||||
EffectField* field = row->Field(j);
|
||||
if (!field->id().isEmpty()) {
|
||||
switch (field->type()) {
|
||||
case EffectField::EFFECT_FIELD_DOUBLE:
|
||||
@@ -1070,8 +1061,8 @@ bool Effect::valueHasChanged(double timecode) {
|
||||
|
||||
for (int i=0;i<row_count();i++) {
|
||||
EffectRow* crow = row(i);
|
||||
for (int j=0;j<crow->fieldCount();j++) {
|
||||
cachedValues.append(crow->field(j)->GetValueAt(timecode));
|
||||
for (int j=0;j<crow->FieldCount();j++) {
|
||||
cachedValues.append(crow->Field(j)->GetValueAt(timecode));
|
||||
}
|
||||
}
|
||||
return true;
|
||||
@@ -1082,8 +1073,8 @@ bool Effect::valueHasChanged(double timecode) {
|
||||
int index = 0;
|
||||
for (int i=0;i<row_count();i++) {
|
||||
EffectRow* crow = row(i);
|
||||
for (int j=0;j<crow->fieldCount();j++) {
|
||||
EffectField* field = crow->field(j);
|
||||
for (int j=0;j<crow->FieldCount();j++) {
|
||||
EffectField* field = crow->Field(j);
|
||||
if (cachedValues.at(index) != field->GetValueAt(timecode)) {
|
||||
changed = true;
|
||||
}
|
||||
|
||||
@@ -145,7 +145,6 @@ public:
|
||||
QString name;
|
||||
CollapsibleWidget* container;
|
||||
|
||||
EffectRow* add_row(const QString &name, bool savable = true, bool keyframable = true);
|
||||
EffectRow* row(int i);
|
||||
int row_count();
|
||||
|
||||
|
||||
@@ -2,11 +2,13 @@
|
||||
#define EFFECTFIELDS_H
|
||||
|
||||
#include "effectfields/boolfield.h"
|
||||
#include "effectfields/buttonfield.h"
|
||||
#include "effectfields/colorfield.h"
|
||||
#include "effectfields/combofield.h"
|
||||
#include "effectfields/doublefield.h"
|
||||
#include "effectfields/filefield.h"
|
||||
#include "effectfields/fontfield.h"
|
||||
#include "effectfields/labelfield.h"
|
||||
#include "effectfields/stringfield.h"
|
||||
|
||||
#endif // EFFECTFIELDS_H
|
||||
|
||||
@@ -11,8 +11,8 @@ public:
|
||||
|
||||
bool GetBoolAt(double timecode);
|
||||
|
||||
virtual QVariant ConvertStringToValue(const QString& s);
|
||||
virtual QString ConvertValueToString(const QVariant& v);
|
||||
virtual QVariant ConvertStringToValue(const QString& s) override;
|
||||
virtual QString ConvertValueToString(const QVariant& v) override;
|
||||
};
|
||||
|
||||
#endif // BOOLFIELD_H
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
#include "buttonfield.h"
|
||||
|
||||
ButtonField::ButtonField(EffectRow *parent, const QString &string) :
|
||||
EffectField(parent, nullptr, EFFECT_FIELD_UI)
|
||||
{
|
||||
SetValueAt(0, string);
|
||||
}
|
||||
|
||||
void ButtonField::SetCheckable(bool c)
|
||||
{
|
||||
checkable_ = c;
|
||||
}
|
||||
|
||||
void ButtonField::SetChecked(bool c)
|
||||
{
|
||||
checked_ = c;
|
||||
emit CheckedChanged(c);
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
#ifndef BUTTONFIELD_H
|
||||
#define BUTTONFIELD_H
|
||||
|
||||
#include "effectfield.h"
|
||||
|
||||
class ButtonField : public EffectField
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
ButtonField(EffectRow* parent, const QString& string);
|
||||
|
||||
void SetCheckable(bool c);
|
||||
void SetChecked(bool c);
|
||||
signals:
|
||||
void CheckedChanged(bool);
|
||||
private:
|
||||
bool checkable_;
|
||||
bool checked_;
|
||||
};
|
||||
|
||||
#endif // BUTTONFIELD_H
|
||||
@@ -11,8 +11,8 @@ public:
|
||||
|
||||
QColor GetColorAt(double timecode);
|
||||
|
||||
virtual QVariant ConvertStringToValue(const QString& s);
|
||||
virtual QString ConvertValueToString(const QVariant& v);
|
||||
virtual QVariant ConvertStringToValue(const QString& s) override;
|
||||
virtual QString ConvertValueToString(const QVariant& v) override;
|
||||
};
|
||||
|
||||
#endif // COLORFIELD_H
|
||||
|
||||
@@ -13,13 +13,3 @@ void ComboField::AddItem(const QString &text, const QVariant &data)
|
||||
|
||||
items_.append(item);
|
||||
}
|
||||
|
||||
QVariant ComboField::ConvertStringToValue(const QString &s)
|
||||
{
|
||||
return s;
|
||||
}
|
||||
|
||||
QString ComboField::ConvertValueToString(const QVariant &v)
|
||||
{
|
||||
return v.toString();
|
||||
}
|
||||
|
||||
@@ -16,9 +16,6 @@ public:
|
||||
|
||||
void AddItem(const QString& text, const QVariant& data);
|
||||
|
||||
virtual QVariant ConvertStringToValue(const QString& s);
|
||||
virtual QString ConvertValueToString(const QVariant& v);
|
||||
|
||||
signals:
|
||||
void IndexChanged(int i);
|
||||
|
||||
|
||||
@@ -52,7 +52,7 @@ EffectField::EffectField(EffectRow* parent, const QString &i, EffectFieldType t)
|
||||
{
|
||||
// EffectField MUST be created with a parent.
|
||||
Q_ASSERT(parent != nullptr);
|
||||
Q_ASSERT(!i.isEmpty());
|
||||
Q_ASSERT(!i.isEmpty() || t == EFFECT_FIELD_UI);
|
||||
|
||||
parent->AddField(this);
|
||||
/*
|
||||
@@ -141,6 +141,16 @@ void EffectField::SetColumnSpan(int i)
|
||||
colspan_ = i;
|
||||
}
|
||||
|
||||
QVariant EffectField::ConvertStringToValue(const QString &s)
|
||||
{
|
||||
return s;
|
||||
}
|
||||
|
||||
QString EffectField::ConvertValueToString(const QVariant &v)
|
||||
{
|
||||
return v.toString();
|
||||
}
|
||||
|
||||
QVariant EffectField::GetValueAt(double timecode)
|
||||
{
|
||||
Q_ASSERT(!keyframes.isEmpty());
|
||||
@@ -172,15 +182,15 @@ QVariant EffectField::GetValueAt(double timecode)
|
||||
// bezier interpolation
|
||||
if (before_key.type == EFFECT_KEYFRAME_BEZIER && after_key.type == EFFECT_KEYFRAME_BEZIER) {
|
||||
// cubic bezier
|
||||
double t = cubic_t_from_x(timecode*GetParentRow()->parent_effect->parent_clip->sequence->frame_rate, before_key.time, before_key.time+GetValidKeyframeHandlePosition(before_keyframe, true), after_key.time+GetValidKeyframeHandlePosition(after_keyframe, false), after_key.time);
|
||||
double t = cubic_t_from_x(timecode*GetParentRow()->GetParentEffect()->parent_clip->sequence->frame_rate, before_key.time, before_key.time+GetValidKeyframeHandlePosition(before_keyframe, true), after_key.time+GetValidKeyframeHandlePosition(after_keyframe, false), after_key.time);
|
||||
value = cubic_from_t(before_dbl, before_dbl+before_key.post_handle_y, after_dbl+after_key.pre_handle_y, after_dbl, t);
|
||||
} else if (after_key.type == EFFECT_KEYFRAME_LINEAR) { // quadratic bezier
|
||||
// last keyframe is the bezier one
|
||||
double t = quad_t_from_x(timecode*GetParentRow()->parent_effect->parent_clip->sequence->frame_rate, before_key.time, before_key.time+GetValidKeyframeHandlePosition(before_keyframe, true), after_key.time);
|
||||
double t = quad_t_from_x(timecode*GetParentRow()->GetParentEffect()->parent_clip->sequence->frame_rate, before_key.time, before_key.time+GetValidKeyframeHandlePosition(before_keyframe, true), after_key.time);
|
||||
value = quad_from_t(before_dbl, before_dbl+before_key.post_handle_y, after_dbl, t);
|
||||
} else {
|
||||
// this keyframe is the bezier one
|
||||
double t = quad_t_from_x(timecode*GetParentRow()->parent_effect->parent_clip->sequence->frame_rate, before_key.time, after_key.time+GetValidKeyframeHandlePosition(after_keyframe, false), after_key.time);
|
||||
double t = quad_t_from_x(timecode*GetParentRow()->GetParentEffect()->parent_clip->sequence->frame_rate, before_key.time, after_key.time+GetValidKeyframeHandlePosition(after_keyframe, false), after_key.time);
|
||||
value = quad_from_t(before_dbl, after_dbl+after_key.pre_handle_y, after_dbl, t);
|
||||
}
|
||||
} else {
|
||||
@@ -223,7 +233,7 @@ void EffectField::SetValueAt(double timecode, const QVariant &value)
|
||||
return;
|
||||
}
|
||||
|
||||
if (GetParentRow()->isKeyframing()) {
|
||||
if (GetParentRow()->IsKeyframing()) {
|
||||
// create keyframe here
|
||||
} else {
|
||||
keyframes.first().data = value;
|
||||
@@ -289,11 +299,11 @@ double EffectField::GetValidKeyframeHandlePosition(int key, bool post) {
|
||||
}
|
||||
|
||||
double EffectField::frameToTimecode(long frame) {
|
||||
return (double(frame) / GetParentRow()->parent_effect->parent_clip->sequence->frame_rate);
|
||||
return (double(frame) / GetParentRow()->GetParentEffect()->parent_clip->sequence->frame_rate);
|
||||
}
|
||||
|
||||
long EffectField::timecodeToFrame(double timecode) {
|
||||
return qRound(timecode * GetParentRow()->parent_effect->parent_clip->sequence->frame_rate);
|
||||
return qRound(timecode * GetParentRow()->GetParentEffect()->parent_clip->sequence->frame_rate);
|
||||
}
|
||||
|
||||
void EffectField::get_keyframe_data(double timecode, int &before, int &after, double &progress) {
|
||||
@@ -333,7 +343,7 @@ void EffectField::get_keyframe_data(double timecode, int &before, int &after, do
|
||||
}
|
||||
|
||||
bool EffectField::HasKeyframes() {
|
||||
return (GetParentRow()->isKeyframing() && keyframes.size() > 1);
|
||||
return (GetParentRow()->IsKeyframing() && keyframes.size() > 1);
|
||||
}
|
||||
|
||||
void EffectField::ui_element_change() {
|
||||
|
||||
@@ -40,7 +40,8 @@ public:
|
||||
EFFECT_FIELD_BOOL,
|
||||
EFFECT_FIELD_COMBO,
|
||||
EFFECT_FIELD_FONT,
|
||||
EFFECT_FIELD_FILE
|
||||
EFFECT_FIELD_FILE,
|
||||
EFFECT_FIELD_UI
|
||||
};
|
||||
|
||||
EffectField(EffectRow* parent, const QString& i, EffectFieldType t);
|
||||
@@ -57,8 +58,8 @@ public:
|
||||
int GetColumnSpan();
|
||||
void SetColumnSpan(int i);
|
||||
|
||||
virtual QVariant ConvertStringToValue(const QString& s) = 0;
|
||||
virtual QString ConvertValueToString(const QVariant& v) = 0;
|
||||
virtual QVariant ConvertStringToValue(const QString& s);
|
||||
virtual QString ConvertValueToString(const QVariant& v);
|
||||
|
||||
double GetValidKeyframeHandlePosition(int key, bool post);
|
||||
|
||||
|
||||
@@ -10,13 +10,3 @@ QString FileField::GetFileAt(double timecode)
|
||||
{
|
||||
return GetValueAt(timecode).toString();
|
||||
}
|
||||
|
||||
QVariant FileField::ConvertStringToValue(const QString &s)
|
||||
{
|
||||
return s;
|
||||
}
|
||||
|
||||
QString FileField::ConvertValueToString(const QVariant &v)
|
||||
{
|
||||
return v.toString();
|
||||
}
|
||||
|
||||
@@ -10,9 +10,6 @@ public:
|
||||
FileField(EffectRow* parent, const QString& id);
|
||||
|
||||
QString GetFileAt(double timecode);
|
||||
|
||||
virtual QVariant ConvertStringToValue(const QString& s);
|
||||
virtual QString ConvertValueToString(const QVariant& v);
|
||||
};
|
||||
|
||||
#endif // FILEFIELD_H
|
||||
|
||||
@@ -10,13 +10,3 @@ QString FontField::GetFontAt(double timecode)
|
||||
{
|
||||
return GetValueAt(timecode).toString();
|
||||
}
|
||||
|
||||
QVariant FontField::ConvertStringToValue(const QString &s)
|
||||
{
|
||||
return s;
|
||||
}
|
||||
|
||||
QString FontField::ConvertValueToString(const QVariant &v)
|
||||
{
|
||||
return v.toString();
|
||||
}
|
||||
|
||||
@@ -9,9 +9,6 @@ public:
|
||||
FontField(EffectRow* parent, const QString& id);
|
||||
|
||||
QString GetFontAt(double timecode);
|
||||
|
||||
virtual QVariant ConvertStringToValue(const QString& s);
|
||||
virtual QString ConvertValueToString(const QVariant& v);
|
||||
};
|
||||
|
||||
#endif // FONTFIELD_H
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
#include "labelfield.h"
|
||||
|
||||
LabelField::LabelField(EffectRow *parent, const QString &string) :
|
||||
EffectField(parent, nullptr, EFFECT_FIELD_UI)
|
||||
{
|
||||
SetValueAt(0, string);
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
#ifndef LABELFIELD_H
|
||||
#define LABELFIELD_H
|
||||
|
||||
#include "effectfield.h"
|
||||
|
||||
class LabelField : public EffectField
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
LabelField(EffectRow* parent, const QString& string);
|
||||
};
|
||||
|
||||
#endif // LABELFIELD_H
|
||||
@@ -10,13 +10,3 @@ QString StringField::GetStringAt(double timecode)
|
||||
{
|
||||
return GetValueAt(timecode).toString();
|
||||
}
|
||||
|
||||
QVariant StringField::ConvertStringToValue(const QString &s)
|
||||
{
|
||||
return s;
|
||||
}
|
||||
|
||||
QString StringField::ConvertValueToString(const QVariant &v)
|
||||
{
|
||||
return v.toString();
|
||||
}
|
||||
|
||||
@@ -10,9 +10,6 @@ public:
|
||||
StringField(EffectRow* parent, const QString& id);
|
||||
|
||||
QString GetStringAt(double timecode);
|
||||
|
||||
virtual QVariant ConvertStringToValue(const QString& s);
|
||||
virtual QString ConvertValueToString(const QVariant& v);
|
||||
};
|
||||
|
||||
#endif // STRINGFIELD_H
|
||||
|
||||
+43
-81
@@ -36,41 +36,14 @@
|
||||
#include "ui/keyframenavigator.h"
|
||||
#include "ui/clickablelabel.h"
|
||||
|
||||
EffectRow::EffectRow(Effect *parent, bool save, QGridLayout *uilayout, const QString &n, int row, bool keyframable) :
|
||||
parent_effect(parent),
|
||||
savable(save),
|
||||
keyframing(false),
|
||||
ui(uilayout),
|
||||
EffectRow::EffectRow(Effect *parent, const QString &n, bool savable, bool keyframable) :
|
||||
QObject(parent),
|
||||
name_(n),
|
||||
ui_row(row),
|
||||
just_made_unsafe_keyframe(false)
|
||||
keyframable_(keyframable),
|
||||
keyframing_(false),
|
||||
savable_(savable)
|
||||
{
|
||||
label = new ClickableLabel(name_ + ":");
|
||||
|
||||
ui->addWidget(label, row, 0);
|
||||
|
||||
column_count = 1;
|
||||
|
||||
keyframe_nav = nullptr;
|
||||
if (parent_effect->meta != nullptr
|
||||
&& parent_effect->meta->type != EFFECT_TYPE_TRANSITION
|
||||
&& keyframable) {
|
||||
connect(label, SIGNAL(clicked()), this, SLOT(FocusRow()));
|
||||
|
||||
keyframe_nav = new KeyframeNavigator();
|
||||
connect(keyframe_nav, SIGNAL(GoToPreviousKeyframe()), this, SLOT(GoToPreviousKeyframe()));
|
||||
connect(keyframe_nav, SIGNAL(ToggleKeyframe()), this, SLOT(ToggleKeyframe()));
|
||||
connect(keyframe_nav, SIGNAL(GoToNextKeyframe()), this, SLOT(GoToNextKeyframe()));
|
||||
connect(keyframe_nav, SIGNAL(keyframe_enabled_changed(bool)), this, SLOT(SetKeyframingEnabled(bool)));
|
||||
connect(keyframe_nav, SIGNAL(clicked()), this, SLOT(FocusRow()));
|
||||
ui->addWidget(keyframe_nav, row, 6);
|
||||
}
|
||||
}
|
||||
|
||||
EffectRow::~EffectRow() {
|
||||
for (int i=0;i<fields_.size();i++) {
|
||||
delete fields_.at(i);
|
||||
}
|
||||
Q_ASSERT(parent != nullptr);
|
||||
}
|
||||
|
||||
void EffectRow::AddField(EffectField *field)
|
||||
@@ -79,52 +52,55 @@ void EffectRow::AddField(EffectField *field)
|
||||
fields_.append(field);
|
||||
}
|
||||
|
||||
bool EffectRow::isKeyframing() {
|
||||
return keyframing;
|
||||
bool EffectRow::IsKeyframing() {
|
||||
return keyframing_;
|
||||
}
|
||||
|
||||
void EffectRow::setKeyframing(bool b) {
|
||||
if (parent_effect->meta->type != EFFECT_TYPE_TRANSITION) {
|
||||
keyframing = b;
|
||||
if (keyframe_nav != nullptr) {
|
||||
keyframe_nav->enable_keyframes(b);
|
||||
}
|
||||
void EffectRow::SetKeyframing(bool b) {
|
||||
if (GetParentEffect()->meta->type != EFFECT_TYPE_TRANSITION) {
|
||||
keyframing_ = b;
|
||||
emit KeyframingSetChanged(keyframing_);
|
||||
}
|
||||
}
|
||||
|
||||
bool EffectRow::IsSavable()
|
||||
{
|
||||
return savable_;
|
||||
}
|
||||
|
||||
void EffectRow::SetKeyframingEnabled(bool enabled) {
|
||||
if (enabled) {
|
||||
ComboAction* ca = new ComboAction();
|
||||
ca->append(new SetKeyframing(this, true));
|
||||
ca->append(new SetIsKeyframing(this, true));
|
||||
set_keyframe_now(ca);
|
||||
olive::UndoStack.push(ca);
|
||||
} else {
|
||||
if (QMessageBox::question(panel_effect_controls,
|
||||
tr("Disable Keyframes"),
|
||||
tr("Disabling keyframes will delete all current keyframes. Are you sure you want to do this?"),
|
||||
QMessageBox::Yes, QMessageBox::No) == QMessageBox::Yes) {
|
||||
tr("Disable Keyframes"),
|
||||
tr("Disabling keyframes will delete all current keyframes. Are you sure you want to do this?"),
|
||||
QMessageBox::Yes, QMessageBox::No) == QMessageBox::Yes) {
|
||||
// clear
|
||||
ComboAction* ca = new ComboAction();
|
||||
for (int i=0;i<fieldCount();i++) {
|
||||
EffectField* f = field(i);
|
||||
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));
|
||||
}
|
||||
}
|
||||
ca->append(new SetKeyframing(this, false));
|
||||
ca->append(new SetIsKeyframing(this, false));
|
||||
olive::UndoStack.push(ca);
|
||||
panel_effect_controls->update_keyframes();
|
||||
} else {
|
||||
setKeyframing(true);
|
||||
SetKeyframing(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void EffectRow::GoToPreviousKeyframe() {
|
||||
long key = LONG_MIN;
|
||||
Clip* c = parent_effect->parent_clip;
|
||||
for (int i=0;i<fieldCount();i++) {
|
||||
EffectField* f = field(i);
|
||||
Clip* c = GetParentEffect()->parent_clip;
|
||||
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(j).time - c->clip_in() + c->timeline_in();
|
||||
if (comp < olive::ActiveSequence->playhead) {
|
||||
@@ -138,9 +114,9 @@ void EffectRow::GoToPreviousKeyframe() {
|
||||
void EffectRow::ToggleKeyframe() {
|
||||
QVector<EffectField*> key_fields;
|
||||
QVector<int> key_field_index;
|
||||
Clip* c = parent_effect->parent_clip;
|
||||
for (int j=0;j<fieldCount();j++) {
|
||||
EffectField* f = field(j);
|
||||
Clip* c = GetParentEffect()->parent_clip;
|
||||
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 == olive::ActiveSequence->playhead) {
|
||||
@@ -165,9 +141,9 @@ void EffectRow::ToggleKeyframe() {
|
||||
|
||||
void EffectRow::GoToNextKeyframe() {
|
||||
long key = LONG_MAX;
|
||||
Clip* c = parent_effect->parent_clip;
|
||||
for (int i=0;i<fieldCount();i++) {
|
||||
EffectField* f = field(i);
|
||||
Clip* c = GetParentEffect()->parent_clip;
|
||||
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(j).time - c->clip_in() + c->timeline_in();
|
||||
if (comp > olive::ActiveSequence->playhead) {
|
||||
@@ -182,25 +158,6 @@ void EffectRow::FocusRow() {
|
||||
panel_graph_editor->set_row(this);
|
||||
}
|
||||
|
||||
/*
|
||||
EffectField* EffectRow::add_field(int type, const QString& id, int colspan) {
|
||||
EffectField* field = new EffectField(this, type, id);
|
||||
if (parent_effect->meta->type != EFFECT_TYPE_TRANSITION) connect(field, SIGNAL(clicked()), this, SLOT(focus_row()));
|
||||
fields_.append(field);
|
||||
QWidget* element = field->get_ui_element();
|
||||
ui->addWidget(element, ui_row, column_count, 1, colspan);
|
||||
column_count++;
|
||||
connect(field, SIGNAL(changed()), parent_effect, SLOT(field_changed()));
|
||||
return field;
|
||||
}
|
||||
*/
|
||||
|
||||
void EffectRow::add_widget(QWidget* w) {
|
||||
widgets.append(w);
|
||||
ui->addWidget(w, ui_row, column_count);
|
||||
column_count++;
|
||||
}
|
||||
|
||||
void EffectRow::set_keyframe_now(ComboAction* ca) {
|
||||
// TODO address this...
|
||||
/*
|
||||
@@ -263,8 +220,8 @@ void EffectRow::set_keyframe_now(ComboAction* ca) {
|
||||
}
|
||||
|
||||
void EffectRow::delete_keyframe_at_time(ComboAction* ca, long time) {
|
||||
for (int j=0;j<fieldCount();j++) {
|
||||
EffectField* f = field(j);
|
||||
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));
|
||||
@@ -274,14 +231,19 @@ void EffectRow::delete_keyframe_at_time(ComboAction* ca, long time) {
|
||||
}
|
||||
}
|
||||
|
||||
Effect *EffectRow::GetParentEffect()
|
||||
{
|
||||
return static_cast<Effect*>(parent());
|
||||
}
|
||||
|
||||
const QString &EffectRow::name() {
|
||||
return name_;
|
||||
}
|
||||
|
||||
EffectField* EffectRow::field(int i) {
|
||||
EffectField* EffectRow::Field(int i) {
|
||||
return fields_.at(i);
|
||||
}
|
||||
|
||||
int EffectRow::fieldCount() {
|
||||
int EffectRow::FieldCount() {
|
||||
return fields_.size();
|
||||
}
|
||||
|
||||
+18
-24
@@ -39,46 +39,40 @@ class ClickableLabel;
|
||||
class EffectRow : public QObject {
|
||||
Q_OBJECT
|
||||
public:
|
||||
EffectRow(Effect* parent, bool save, QGridLayout* uilayout, const QString& n, int row, bool keyframable = true);
|
||||
~EffectRow();
|
||||
EffectRow(Effect* parent, const QString& n, bool savable = true, bool keyframable = true);
|
||||
|
||||
void AddField(EffectField* field);
|
||||
void AddField(EffectField* Field);
|
||||
|
||||
void add_widget(QWidget *w);
|
||||
EffectField* field(int i);
|
||||
int fieldCount();
|
||||
EffectField* Field(int i);
|
||||
int FieldCount();
|
||||
void set_keyframe_now(ComboAction *ca);
|
||||
void delete_keyframe_at_time(ComboAction *ca, long time);
|
||||
ClickableLabel* label;
|
||||
Effect* parent_effect;
|
||||
bool savable;
|
||||
|
||||
Effect* GetParentEffect();
|
||||
|
||||
const QString& name();
|
||||
|
||||
bool isKeyframing();
|
||||
void setKeyframing(bool);
|
||||
bool IsKeyframing();
|
||||
void SetKeyframing(bool);
|
||||
|
||||
bool IsSavable();
|
||||
public slots:
|
||||
void GoToPreviousKeyframe();
|
||||
void ToggleKeyframe();
|
||||
void GoToNextKeyframe();
|
||||
void FocusRow();
|
||||
signals:
|
||||
void KeyframingSetChanged(bool);
|
||||
private slots:
|
||||
void SetKeyframingEnabled(bool);
|
||||
private:
|
||||
bool keyframing;
|
||||
QGridLayout* ui;
|
||||
QString name_;
|
||||
int ui_row;
|
||||
|
||||
bool keyframable_;
|
||||
bool keyframing_;
|
||||
bool savable_;
|
||||
|
||||
QVector<EffectField*> fields_;
|
||||
QVector<QWidget*> widgets;
|
||||
|
||||
KeyframeNavigator* keyframe_nav;
|
||||
|
||||
bool just_made_unsafe_keyframe;
|
||||
QVector<int> unsafe_keys;
|
||||
QVector<QVariant> unsafe_old_data;
|
||||
QVector<bool> key_is_new;
|
||||
|
||||
int column_count;
|
||||
};
|
||||
|
||||
#endif // EFFECTROW_H
|
||||
|
||||
@@ -45,7 +45,7 @@ Transition::Transition(Clip *c, Clip *s, const EffectMeta* em) :
|
||||
Effect(c, em),
|
||||
secondary_clip(s)
|
||||
{
|
||||
EffectRow* length_row = add_row(tr("Length"), false, false);
|
||||
EffectRow* length_row = new EffectRow(this, tr("Length"), false, false);
|
||||
length_field = new DoubleField(length_row, "length");
|
||||
length_field->SetDefault(30);
|
||||
length_field->SetMinimum(0);
|
||||
|
||||
+5
-5
@@ -1136,17 +1136,17 @@ void KeyframeFieldSet::doRedo() {
|
||||
done = true;
|
||||
}
|
||||
|
||||
SetKeyframing::SetKeyframing(EffectRow *irow, bool ib) {
|
||||
SetIsKeyframing::SetIsKeyframing(EffectRow *irow, bool ib) {
|
||||
row = irow;
|
||||
b = ib;
|
||||
}
|
||||
|
||||
void SetKeyframing::doUndo() {
|
||||
row->setKeyframing(!b);
|
||||
void SetIsKeyframing::doUndo() {
|
||||
row->SetKeyframing(!b);
|
||||
}
|
||||
|
||||
void SetKeyframing::doRedo() {
|
||||
row->setKeyframing(b);
|
||||
void SetIsKeyframing::doRedo() {
|
||||
row->SetKeyframing(b);
|
||||
}
|
||||
|
||||
RefreshClips::RefreshClips(Media *m) {
|
||||
|
||||
+2
-2
@@ -600,9 +600,9 @@ private:
|
||||
QVariant new_val;
|
||||
};
|
||||
|
||||
class SetKeyframing : public OliveAction {
|
||||
class SetIsKeyframing : public OliveAction {
|
||||
public:
|
||||
SetKeyframing(EffectRow* irow, bool ib);
|
||||
SetIsKeyframing(EffectRow* irow, bool ib);
|
||||
virtual void doUndo() override;
|
||||
virtual void doRedo() override;
|
||||
private:
|
||||
|
||||
Reference in New Issue
Block a user