From d549586761f31a37841687a65f6bebc92ae8fc2c Mon Sep 17 00:00:00 2001 From: itsmattkc Date: Tue, 14 Aug 2018 15:50:16 +1000 Subject: [PATCH] sweeping vfx rewrite --- effects/effects.h | 71 ++++++-------- effects/inverteffect.cpp | 38 ++------ effects/paneffect.cpp | 37 +++---- effects/shakeeffect.cpp | 79 +++++---------- effects/texteffect.cpp | 104 +++++--------------- effects/transformeffect.cpp | 188 ++++++++++-------------------------- effects/volumeeffect.cpp | 37 +++---- olive.pro | 6 +- project/clip.cpp | 2 +- project/effect.cpp | 168 +++++++++++++++++++++++++++++++- project/effect.h | 85 ++++++++++++++-- ui/fontcombobox.cpp | 22 +++++ ui/fontcombobox.h | 13 +++ ui/timelinewidget.cpp | 2 +- 14 files changed, 446 insertions(+), 406 deletions(-) create mode 100644 ui/fontcombobox.cpp create mode 100644 ui/fontcombobox.h diff --git a/effects/effects.h b/effects/effects.h index cbbdf5613..b867c1b37 100644 --- a/effects/effects.h +++ b/effects/effects.h @@ -41,22 +41,19 @@ class TransformEffect : public Effect { Q_OBJECT public: TransformEffect(Clip* c); - void init(); + void refresh(); void process_gl(int* anchor_x, int* anchor_y); - Effect* copy(Clip* c); - void load(QXmlStreamReader* stream); - void save(QXmlStreamWriter* stream); - LabelSlider* position_x; - LabelSlider* position_y; - LabelSlider* scale_x; - LabelSlider* scale_y; - QCheckBox* uniform_scale_box; - LabelSlider* rotation; - LabelSlider* anchor_x_box; - LabelSlider* anchor_y_box; - LabelSlider* opacity; - ComboBoxEx* blend_mode_box; + EffectField* position_x; + EffectField* position_y; + EffectField* scale_x; + EffectField* scale_y; + EffectField* uniform_scale_field; + EffectField* rotation; + EffectField* anchor_x_box; + EffectField* anchor_y_box; + EffectField* opacity; + EffectField* blend_mode_box; public slots: void toggle_uniform_scale(bool enabled); private: @@ -69,15 +66,13 @@ class ShakeEffect : public Effect { public: ShakeEffect(Clip* c); void process_gl(int* anchor_x, int* anchor_y); - Effect* copy(Clip *c); - void load(QXmlStreamReader* stream); - void save(QXmlStreamWriter* stream); + Effect* copy(Clip *c); - LabelSlider* intensity_val; - LabelSlider* rotation_val; - LabelSlider* frequency_val; + EffectField* intensity_val; + EffectField* rotation_val; + EffectField* frequency_val; public slots: - void init(); + void refresh(); private: int shake_progress; int shake_limit; @@ -102,13 +97,12 @@ public: TextEffect(Clip* c); ~TextEffect(); void post_gl(); - Effect* copy(Clip* c); - void load(QXmlStreamReader* stream); - void save(QXmlStreamWriter* stream); - QTextEdit* text_val; - LabelSlider* size_val; - ColorButton* set_color_button; - ComboBoxEx* set_font_combobox; + Effect* copy(Clip* c); + + EffectField* text_val; + EffectField* size_val; + EffectField* set_color_button; + EffectField* set_font_combobox; private slots: void update_texture(); private: @@ -135,38 +129,31 @@ class InvertEffect : public Effect { Q_OBJECT public: InvertEffect(Clip* c); - void init(); void process_gl(int *anchor_x, int *anchor_y); Effect* copy(Clip *c); - void load(QXmlStreamReader* stream); - void save(QXmlStreamWriter* stream); - LabelSlider* amount_val; + EffectField* amount_val; }; // audio effects class VolumeEffect : public Effect { public: VolumeEffect(Clip* c); - void init(); + void refresh(); void process_audio(quint8* samples, int nb_bytes); - Effect* copy(Clip* c); - void load(QXmlStreamReader* stream); - void save(QXmlStreamWriter* stream); + Effect* copy(Clip* c); - LabelSlider* volume_val; + EffectField* volume_val; }; class PanEffect : public Effect { public: PanEffect(Clip* c); - void init(); + void refresh(); void process_audio(quint8* samples, int nb_bytes); - Effect* copy(Clip* c); - void load(QXmlStreamReader* stream); - void save(QXmlStreamWriter* stream); + Effect* copy(Clip* c); - LabelSlider* pan_val; + EffectField* pan_val; }; #endif // EFFECTS_H diff --git a/effects/inverteffect.cpp b/effects/inverteffect.cpp index 4f399f44f..43aca2796 100644 --- a/effects/inverteffect.cpp +++ b/effects/inverteffect.cpp @@ -9,40 +9,20 @@ #include InvertEffect::InvertEffect(Clip* c) : Effect(c, EFFECT_TYPE_VIDEO, VIDEO_INVERT_EFFECT) { - ui_layout->addWidget(new QLabel("Amount:"), 0, 0); - amount_val = new LabelSlider(); - ui_layout->addWidget(amount_val, 0, 1); + EffectRow* amount_row = add_row("Amount:"); + amount_val = amount_row->add_field(EFFECT_FIELD_DOUBLE); + amount_val->set_double_minimum_value(0); + amount_val->set_double_maximum_value(100); - // set defaults - amount_val->set_minimum_value(0); - amount_val->set_maximum_value(100); - init(); - - connect(amount_val, SIGNAL(valueChanged()), this, SLOT(field_changed())); -} - -void InvertEffect::init() { - amount_val->set_default_value(100); + // set defaults + amount_val->set_double_default_value(100); } Effect* InvertEffect::copy(Clip* c) { - InvertEffect* i = new InvertEffect(c); + /*InvertEffect* i = new InvertEffect(c); i->amount_val->set_value(amount_val->value()); - return i; -} - -void InvertEffect::load(QXmlStreamReader *stream) { - const QXmlStreamAttributes& attr = stream->attributes(); - for (int i=0;iset_value(a.value().toDouble()); - } - } -} - -void InvertEffect::save(QXmlStreamWriter *stream) { - stream->writeAttribute("amount", QString::number(amount_val->value())); + return i;*/ + return NULL; } void InvertEffect::process_gl(int* anchor_x, int* anchor_y) { diff --git a/effects/paneffect.cpp b/effects/paneffect.cpp index 7fc09b09c..6a446e673 100644 --- a/effects/paneffect.cpp +++ b/effects/paneffect.cpp @@ -9,45 +9,32 @@ #include "ui/collapsiblewidget.h" PanEffect::PanEffect(Clip* c) : Effect(c, EFFECT_TYPE_AUDIO, AUDIO_PAN_EFFECT) { - ui_layout->addWidget(new QLabel("Pan:"), 0, 0); - pan_val = new LabelSlider(); - pan_val->set_minimum_value(-100); - pan_val->set_maximum_value(100); - ui_layout->addWidget(pan_val, 0, 1); + EffectRow* pan_row = add_row("Pan:"); + pan_val = pan_row->add_field(EFFECT_FIELD_DOUBLE); + pan_val->set_double_minimum_value(-100); + pan_val->set_double_maximum_value(100); // set defaults - pan_val->set_value(0); + pan_val->set_double_default_value(0); } -void PanEffect::init() {} +void PanEffect::refresh() {} Effect* PanEffect::copy(Clip* c) { - PanEffect* p = new PanEffect(c); + /*PanEffect* p = new PanEffect(c); p->pan_val->set_value(pan_val->value()); - return p; -} - -void PanEffect::load(QXmlStreamReader *stream) { - while (!(stream->isEndElement() && stream->name() == "effect") && !stream->atEnd()) { - stream->readNext(); - if (stream->isStartElement() && stream->name() == "pan") { - stream->readNext(); - pan_val->set_value(stream->text().toDouble()); - } - } -} - -void PanEffect::save(QXmlStreamWriter *stream) { - stream->writeTextElement("pan", QString::number(pan_val->value())); + return p;*/ + return NULL; } void PanEffect::process_audio(quint8 *samples, int nb_bytes) { - if (pan_val->value() != 0) { + double pval = pan_val->get_double_value(); + if (pval != 0) { for (int i=0;ivalue()*0.01, 3); + double val = qPow(pval*0.01, 3); if (val < 0) { // affect right channel right_sample *= (1-std::abs(val)); diff --git a/effects/shakeeffect.cpp b/effects/shakeeffect.cpp index f5e1b4207..7e98d4b45 100644 --- a/effects/shakeeffect.cpp +++ b/effects/shakeeffect.cpp @@ -13,39 +13,29 @@ #include "panels/timeline.h" ShakeEffect::ShakeEffect(Clip *c) : Effect(c, EFFECT_TYPE_VIDEO, VIDEO_SHAKE_EFFECT), inside(false) { - ui_layout->addWidget(new QLabel("Intensity:"), 0, 0); - intensity_val = new LabelSlider(); - intensity_val->set_minimum_value(0); - ui_layout->addWidget(intensity_val, 0, 1); + EffectRow* intensity_row = add_row("Intensity:"); + intensity_val = intensity_row->add_field(EFFECT_FIELD_DOUBLE); + intensity_val->set_double_minimum_value(0); - ui_layout->addWidget(new QLabel("Rotation:"), 1, 0); - rotation_val = new LabelSlider(); - rotation_val->set_minimum_value(0); - ui_layout->addWidget(rotation_val, 1, 1); + EffectRow* rotation_row = add_row("Rotation:"); + rotation_val = rotation_row->add_field(EFFECT_FIELD_DOUBLE); + rotation_val->set_double_minimum_value(0); - ui_layout->addWidget(new QLabel("Frequency:"), 2, 0); - frequency_val = new LabelSlider(); - frequency_val->set_minimum_value(0); - ui_layout->addWidget(frequency_val, 2, 1); + EffectRow* frequency_row = add_row("Frequency:"); + frequency_val = frequency_row->add_field(EFFECT_FIELD_DOUBLE); + frequency_val->set_double_minimum_value(0); // set defaults - intensity_val->set_value(50); - rotation_val->set_value(0); - frequency_val->set_value(10); + intensity_val->set_double_default_value(50); + rotation_val->set_double_default_value(0); + frequency_val->set_double_default_value(10); - init(); - - connect(intensity_val, SIGNAL(valueChanged()), this, SLOT(field_changed())); - connect(rotation_val, SIGNAL(valueChanged()), this, SLOT(field_changed())); - connect(frequency_val, SIGNAL(valueChanged()), this, SLOT(field_changed())); - connect(intensity_val, SIGNAL(valueChanged()), this, SLOT(init())); - connect(rotation_val, SIGNAL(valueChanged()), this, SLOT(init())); - connect(frequency_val, SIGNAL(valueChanged()), this, SLOT(init())); + refresh(); } -void ShakeEffect::init() { +void ShakeEffect::refresh() { if (parent_clip->sequence != NULL) { - shake_limit = qRound(parent_clip->sequence->frame_rate / frequency_val->value()); + shake_limit = qRound(parent_clip->sequence->frame_rate / frequency_val->get_double_value()); shake_progress = shake_limit; next_x = 0; next_y = 0; @@ -54,40 +44,22 @@ void ShakeEffect::init() { } Effect* ShakeEffect::copy(Clip* c) { - ShakeEffect* e = new ShakeEffect(c); + /*ShakeEffect* e = new ShakeEffect(c); e->intensity_val->set_value(intensity_val->value()); e->rotation_val->set_value(rotation_val->value()); - e->frequency_val->set_value(frequency_val->value()); - return e; -} - -void ShakeEffect::load(QXmlStreamReader* reader) { - const QXmlStreamAttributes& attr = reader->attributes(); - for (int i=0;iset_value(a.value().toDouble()); - } else if (a.name() == "rotation") { - rotation_val->set_value(a.value().toDouble()); - } else if (a.name() == "frequency") { - frequency_val->set_value(a.value().toDouble()); - } - } -} - -void ShakeEffect::save(QXmlStreamWriter* stream) { - stream->writeAttribute("intensity", QString::number(intensity_val->value())); - stream->writeAttribute("rotation", QString::number(rotation_val->value())); - stream->writeAttribute("frequency", QString::number(frequency_val->value())); + e->frequency_val->set_value(frequency_val->value()); + return e;*/ + return NULL; } void ShakeEffect::process_gl(int*, int*) { if (shake_progress > shake_limit) { - if ((int)intensity_val->value() > 0) { + double ival = intensity_val->get_double_value(); + if ((int)ival > 0) { prev_x = next_x; prev_y = next_y; - next_x = (qrand() % (int) (intensity_val->value() * 2)) - intensity_val->value(); - next_y = (qrand() % (int) (intensity_val->value() * 2)) - intensity_val->value(); + next_x = (qrand() % (int) (ival * 2)) - ival; + next_y = (qrand() % (int) (ival * 2)) - ival; // find perpendicular slope that passes through (mid_x, mid_y) int mid_x = (prev_x + next_x) / 2; @@ -112,9 +84,10 @@ void ShakeEffect::process_gl(int*, int*) { offset_x = 0; offset_y = 0; } - if ((int)rotation_val->value() > 0) { + double rot_val = rotation_val->get_double_value(); + if ((int)rot_val > 0) { prev_rot = next_rot; - next_rot = (qrand() % (int) (rotation_val->value() * 2)) - rotation_val->value(); + next_rot = (qrand() % (int) (rot_val * 2)) - rot_val; } else { prev_rot = 0; next_rot = 0; diff --git a/effects/texteffect.cpp b/effects/texteffect.cpp index 07fd6c7ab..b07a24768 100644 --- a/effects/texteffect.cpp +++ b/effects/texteffect.cpp @@ -17,26 +17,7 @@ #include "project/sequence.h" #include "ui/comboboxex.h" #include "ui/colorbutton.h" - -class FontCombobox : public ComboBoxEx { -public: - FontCombobox(QWidget* parent = 0) : ComboBoxEx(parent) {} -protected: - void showPopup() { - QString current = currentText(); - clear(); - QStringList fonts = QFontDatabase().families(); - bool found = false; - for (int i=0;iaddWidget(new QLabel("Text:"), 0, 0); - text_val = new QTextEdit(); - text_val->setUndoRedoEnabled(true); - ui_layout->addWidget(text_val, 0, 1); + EffectRow* text_row = add_row("Text:"); + text_val = text_row->add_field(EFFECT_FIELD_STRING); - ui_layout->addWidget(new QLabel("Font:"), 1, 0); - set_font_combobox = new FontCombobox(); - ui_layout->addWidget(set_font_combobox, 1, 1); + EffectRow* font_row = add_row("Font:"); + set_font_combobox = font_row->add_field(EFFECT_FIELD_FONT); - ui_layout->addWidget(new QLabel("Size:"), 2, 0); - size_val = new LabelSlider(); - size_val->set_minimum_value(0); - ui_layout->addWidget(size_val, 2, 1); + EffectRow* size_row = add_row("Size:"); + size_val = size_row->add_field(EFFECT_FIELD_DOUBLE); + size_val->set_double_minimum_value(0); - ui_layout->addWidget(new QLabel("Color:"), 3, 0); - set_color_button = new ColorButton(); - ui_layout->addWidget(set_color_button, 3, 1); + EffectRow* color_row = add_row("Color:"); + set_color_button = color_row->add_field(EFFECT_FIELD_COLOR); - set_font_combobox->addItem(font.family()); + connect(static_cast(text_val->get_ui_element()), SIGNAL(textChanged()), this, SLOT(update_texture())); + connect(static_cast(size_val->get_ui_element()), SIGNAL(valueChanged()), this, SLOT(update_texture())); + connect(static_cast(set_color_button->get_ui_element()), SIGNAL(color_changed()), this, SLOT(update_texture())); + connect(static_cast(set_font_combobox->get_ui_element()), SIGNAL(currentTextChanged(QString)), this, SLOT(update_texture())); - connect(text_val, SIGNAL(textChanged()), this, SLOT(update_texture())); - connect(size_val, SIGNAL(valueChanged()), this, SLOT(update_texture())); - connect(set_color_button, SIGNAL(color_changed()), this, SLOT(update_texture())); - connect(set_font_combobox, SIGNAL(currentTextChanged(QString)), this, SLOT(update_texture())); - - size_val->set_value(24); - text_val->setText("Sample Text"); + size_val->set_double_default_value(24); + text_val->set_string_value("Sample Text"); } TextEffect::~TextEffect() { @@ -93,13 +67,13 @@ void TextEffect::update_texture() { p.setRenderHint(QPainter::TextAntialiasing, true); // set font - font.setFamily(set_font_combobox->currentText()); - font.setPointSize(size_val->value()); + font.setFamily(set_font_combobox->get_font_name()); + font.setPointSize(size_val->get_double_value()); font.setStyleHint(QFont::Helvetica, QFont::PreferAntialias); p.setFont(font); - p.setPen(set_color_button->get_color()); - p.drawText(QRect(0, 0, width, height), Qt::AlignCenter | Qt::TextWordWrap, text_val->toPlainText()); + p.setPen(set_color_button->get_color_value()); + p.drawText(QRect(0, 0, width, height), Qt::AlignCenter | Qt::TextWordWrap, text_val->get_string_value()); if (texture == NULL) { texture = new QOpenGLTexture(pixmap); @@ -137,40 +111,10 @@ void TextEffect::post_gl() { } Effect* TextEffect::copy(Clip* c) { - TextEffect* e = new TextEffect(c); + /*TextEffect* e = new TextEffect(c); e->text_val->setPlainText(text_val->toPlainText()); e->size_val->set_value(size_val->value()); - e->set_color_button->set_color(set_color_button->get_color()); - return e; -} - -void TextEffect::load(QXmlStreamReader* stream) { - const QXmlStreamAttributes& attr = stream->attributes(); - for (int i=0;iset_value(a.value().toDouble()); - } else if (a.name() == "r") { - set_color_button->get_color().setRed(a.value().toInt()); - } else if (a.name() == "g") { - set_color_button->get_color().setGreen(a.value().toInt()); - } else if (a.name() == "b") { - set_color_button->get_color().setBlue(a.value().toInt()); - } - } - while (!(stream->name() == "effect" && stream->isEndElement())) { - stream->readNext(); - if (stream->name() == "text" && stream->isStartElement()) { - stream->readNext(); - text_val->setPlainText(stream->text().toString()); - } - } -} - -void TextEffect::save(QXmlStreamWriter* stream) { - stream->writeAttribute("size", QString::number(size_val->value())); - stream->writeAttribute("r", QString::number(set_color_button->get_color().red())); - stream->writeAttribute("g", QString::number(set_color_button->get_color().green())); - stream->writeAttribute("b", QString::number(set_color_button->get_color().blue())); - stream->writeTextElement("text", text_val->toPlainText()); + e->set_color_button->set_color(set_color_button->get_color()); + return e;*/ + return NULL; } diff --git a/effects/transformeffect.cpp b/effects/transformeffect.cpp index 073b201ef..5df39dc42 100644 --- a/effects/transformeffect.cpp +++ b/effects/transformeffect.cpp @@ -23,80 +23,59 @@ #define BLEND_MODE_OVERLAY 3 TransformEffect::TransformEffect(Clip* c) : Effect(c, EFFECT_TYPE_VIDEO, VIDEO_TRANSFORM_EFFECT) { - ui_layout->addWidget(new QLabel("Position:"), 0, 0); - position_x = new LabelSlider(); - ui_layout->addWidget(position_x, 0, 1); + EffectRow* position_row = add_row("Position:"); + position_x = position_row->add_field(EFFECT_FIELD_DOUBLE); // position X + position_y = position_row->add_field(EFFECT_FIELD_DOUBLE); // position Y - position_y = new LabelSlider(); - ui_layout->addWidget(position_y, 0, 2); + EffectRow* scale_row = add_row("Scale:"); + scale_x = scale_row->add_field(EFFECT_FIELD_DOUBLE); // scale X (and Y is uniform scale is selected) + scale_x->set_double_minimum_value(0); + scale_x->set_double_maximum_value(3000); + scale_y = scale_row->add_field(EFFECT_FIELD_DOUBLE); // scale Y (disabled if uniform scale is selected) + scale_y->set_double_minimum_value(0); + scale_y->set_double_maximum_value(3000); - ui_layout->addWidget(new QLabel("Scale:"), 1, 0); - scale_x = new LabelSlider(); - scale_x->set_minimum_value(0); - scale_x->set_maximum_value(3000); - ui_layout->addWidget(scale_x, 1, 1); - scale_y = new LabelSlider(); - scale_y->set_minimum_value(0); - scale_y->set_maximum_value(3000); - ui_layout->addWidget(scale_y, 1, 2); + EffectRow* uniform_scale_row = add_row("Uniform Scale:"); + uniform_scale_field = uniform_scale_row->add_field(EFFECT_FIELD_BOOL); // uniform scale option - uniform_scale_box = new QCheckBox(); - uniform_scale_box->setText("Uniform Scale"); - ui_layout->addWidget(uniform_scale_box, 2, 1); + EffectRow* rotation_row = add_row("Rotation:"); + rotation = rotation_row->add_field(EFFECT_FIELD_DOUBLE); - ui_layout->addWidget(new QLabel("Rotation:"), 3, 0); - rotation = new LabelSlider(); - ui_layout->addWidget(rotation, 3, 1); + EffectRow* anchor_point_row = add_row("Anchor Point:"); + anchor_x_box = anchor_point_row->add_field(EFFECT_FIELD_DOUBLE); // anchor point X + anchor_y_box = anchor_point_row->add_field(EFFECT_FIELD_DOUBLE); // anchor point Y - ui_layout->addWidget(new QLabel("Anchor Point:"), 4, 0); - anchor_x_box = new LabelSlider(); - ui_layout->addWidget(anchor_x_box, 4, 1); - anchor_y_box = new LabelSlider(); - ui_layout->addWidget(anchor_y_box, 4, 2); + EffectRow* opacity_row = add_row("Opacity:"); + opacity = opacity_row->add_field(EFFECT_FIELD_DOUBLE); // opacity + opacity->set_double_minimum_value(0); + opacity->set_double_maximum_value(100); - ui_layout->addWidget(new QLabel("Opacity:"), 5, 0); - opacity = new LabelSlider(); - opacity->set_minimum_value(0); - opacity->set_maximum_value(100); - ui_layout->addWidget(opacity, 5, 1); - - ui_layout->addWidget(new QLabel("Blend Mode:"), 6, 0); - blend_mode_box = new ComboBoxEx(); - blend_mode_box->addItem("Normal", BLEND_MODE_NORMAL); - blend_mode_box->addItem("Overlay", BLEND_MODE_OVERLAY); - blend_mode_box->addItem("Screen", BLEND_MODE_SCREEN); - blend_mode_box->addItem("Multiply", BLEND_MODE_MULTIPLY); - ui_layout->addWidget(blend_mode_box, 6, 1); + EffectRow* blend_mode_row = add_row("Blend Mode:"); + blend_mode_box = blend_mode_row->add_field(EFFECT_FIELD_COMBO); // blend mode + blend_mode_box->add_combo_item("Normal", BLEND_MODE_NORMAL); + blend_mode_box->add_combo_item("Overlay", BLEND_MODE_OVERLAY); + blend_mode_box->add_combo_item("Screen", BLEND_MODE_SCREEN); + blend_mode_box->add_combo_item("Multiply", BLEND_MODE_MULTIPLY); // set defaults - scale_y->setEnabled(false); - uniform_scale_box->setChecked(true); - blend_mode_box->setCurrentIndex(0); - init(); + QCheckBox* uniform_scale_box = static_cast(uniform_scale_field->get_ui_element()); + scale_y->set_enabled(false); + uniform_scale_field->set_bool_value(true); + blend_mode_box->set_combo_index(0); + refresh(); - connect(position_x, SIGNAL(valueChanged()), this, SLOT(field_changed())); - connect(position_y, SIGNAL(valueChanged()), this, SLOT(field_changed())); - connect(rotation, SIGNAL(valueChanged()), this, SLOT(field_changed())); - connect(scale_x, SIGNAL(valueChanged()), this, SLOT(field_changed())); - connect(scale_y, SIGNAL(valueChanged()), this, SLOT(field_changed())); - connect(anchor_x_box, SIGNAL(valueChanged()), this, SLOT(field_changed())); - connect(anchor_y_box, SIGNAL(valueChanged()), this, SLOT(field_changed())); - connect(opacity, SIGNAL(valueChanged()), this, SLOT(field_changed())); connect(uniform_scale_box, SIGNAL(toggled(bool)), this, SLOT(toggle_uniform_scale(bool))); - connect(uniform_scale_box, SIGNAL(toggled(bool)), this, SLOT(field_changed())); - connect(uniform_scale_box, SIGNAL(clicked(bool)), this, SLOT(checkbox_command())); - connect(blend_mode_box, SIGNAL(currentIndexChanged(int)), this, SLOT(field_changed())); } -void TransformEffect::init() { - if (parent_clip->sequence != NULL) { +void TransformEffect::refresh() { + if (parent_clip->sequence != NULL) { double default_pos_x = parent_clip->sequence->width/2; double default_pos_y = parent_clip->sequence->height/2; - position_x->set_default_value(default_pos_x); - position_y->set_default_value(default_pos_y); - scale_x->set_default_value(100); - scale_y->set_default_value(100); + position_x->set_double_default_value(default_pos_x); + position_y->set_double_default_value(default_pos_y); + scale_x->set_double_default_value(100); + scale_y->set_double_default_value(100); default_anchor_x = default_pos_x; default_anchor_y = default_pos_y; @@ -121,99 +100,34 @@ void TransformEffect::init() { } } - anchor_x_box->set_default_value(default_anchor_x); - anchor_y_box->set_default_value(default_anchor_y); - opacity->set_default_value(100); - } -} - -Effect* TransformEffect::copy(Clip* c) { - TransformEffect* t = new TransformEffect(c); - t->position_x->set_value(position_x->value()); - t->position_y->set_value(position_y->value()); - t->scale_x->set_value(scale_x->value()); - t->scale_y->set_value(scale_y->value()); - t->uniform_scale_box->setChecked(uniform_scale_box->isChecked()); - t->rotation->set_value(rotation->value()); - t->anchor_x_box->set_value(anchor_x_box->value()); - t->anchor_y_box->set_value(anchor_y_box->value()); - t->opacity->set_value(opacity->value()); - t->blend_mode_box->setCurrentIndex(blend_mode_box->currentIndex()); - return t; -} - -void TransformEffect::load(QXmlStreamReader *stream) { - while (!(stream->isEndElement() && stream->name() == "effect") && !stream->atEnd()) { - stream->readNext(); - if (stream->isStartElement() && stream->name() == "posx") { - stream->readNext(); - position_x->set_value(stream->text().toDouble()); - } else if (stream->isStartElement() && stream->name() == "posy") { - stream->readNext(); - position_y->set_value(stream->text().toDouble()); - } else if (stream->isStartElement() && stream->name() == "scalex") { - stream->readNext(); - scale_x->set_value(stream->text().toDouble()); - } else if (stream->isStartElement() && stream->name() == "scaley") { - stream->readNext(); - scale_y->set_value(stream->text().toDouble()); - } else if (stream->isStartElement() && stream->name() == "uniformscale") { - stream->readNext(); - uniform_scale_box->setChecked(stream->text() == "1"); - } else if (stream->isStartElement() && stream->name() == "rotation") { - stream->readNext(); - rotation->set_value(stream->text().toDouble()); - } else if (stream->isStartElement() && stream->name() == "anchorx") { - stream->readNext(); - anchor_x_box->set_value(stream->text().toDouble()); - } else if (stream->isStartElement() && stream->name() == "anchory") { - stream->readNext(); - anchor_y_box->set_value(stream->text().toDouble()); - } else if (stream->isStartElement() && stream->name() == "opacity") { - stream->readNext(); - opacity->set_value(stream->text().toDouble()); - } else if (stream->isStartElement() && stream->name() == "blendmode") { - stream->readNext(); - blend_mode_box->setCurrentIndex(stream->text().toInt()); - } - } -} - -void TransformEffect::save(QXmlStreamWriter *stream) { - stream->writeTextElement("posx", QString::number(position_x->value())); - stream->writeTextElement("posy", QString::number(position_y->value())); - stream->writeTextElement("scalex", QString::number(scale_x->value())); - stream->writeTextElement("scaley", QString::number(scale_y->value())); - stream->writeTextElement("uniformscale", QString::number(uniform_scale_box->isChecked())); - stream->writeTextElement("rotation", QString::number(rotation->value())); - stream->writeTextElement("anchorx", QString::number(anchor_x_box->value())); - stream->writeTextElement("anchory", QString::number(anchor_y_box->value())); - stream->writeTextElement("opacity", QString::number(opacity->value())); - stream->writeTextElement("blendmode", QString::number(blend_mode_box->currentIndex())); + anchor_x_box->set_double_default_value(default_anchor_x); + anchor_y_box->set_double_default_value(default_anchor_y); + opacity->set_double_default_value(100); + } } void TransformEffect::toggle_uniform_scale(bool enabled) { - scale_y->setEnabled(!enabled); + scale_y->set_enabled(!enabled); } void TransformEffect::process_gl(int* anchor_x, int* anchor_y) { // position - glTranslatef(position_x->value()-(parent_clip->sequence->width/2), position_y->value()-(parent_clip->sequence->height/2), 0); + glTranslatef(position_x->get_double_value()-(parent_clip->sequence->width/2), position_y->get_double_value()-(parent_clip->sequence->height/2), 0); // anchor point - *anchor_x += (anchor_x_box->value()-default_anchor_x); - *anchor_y += (anchor_y_box->value()-default_anchor_y); + *anchor_x += (anchor_x_box->get_double_value()-default_anchor_x); + *anchor_y += (anchor_y_box->get_double_value()-default_anchor_y); // rotation - glRotatef(rotation->value(), 0, 0, 1); + glRotatef(rotation->get_double_value(), 0, 0, 1); // scale - float sx = scale_x->value()*0.01; - float sy = (uniform_scale_box->isChecked()) ? sx : scale_y->value()*0.01; + float sx = scale_x->get_double_value()*0.01; + float sy = (uniform_scale_field->get_bool_value()) ? sx : scale_y->get_double_value()*0.01; glScalef(sx, sy, 1); // blend mode - switch (blend_mode_box->currentData().toInt()) { + switch (blend_mode_box->get_combo_data().toInt()) { case BLEND_MODE_NORMAL: glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); break; @@ -233,5 +147,5 @@ void TransformEffect::process_gl(int* anchor_x, int* anchor_y) { // opacity float color[4]; glGetFloatv(GL_CURRENT_COLOR, color); - glColor4f(1.0, 1.0, 1.0, color[3]*(opacity->value()*0.01)); + glColor4f(1.0, 1.0, 1.0, color[3]*(opacity->get_double_value()*0.01)); } diff --git a/effects/volumeeffect.cpp b/effects/volumeeffect.cpp index 62d63c067..7df68cdbd 100644 --- a/effects/volumeeffect.cpp +++ b/effects/volumeeffect.cpp @@ -10,43 +10,30 @@ #include "ui/collapsiblewidget.h" VolumeEffect::VolumeEffect(Clip* c) : Effect(c, EFFECT_TYPE_AUDIO, AUDIO_VOLUME_EFFECT) { - ui_layout->addWidget(new QLabel("Volume:"), 0, 0); - volume_val = new LabelSlider(); - volume_val->set_minimum_value(0); - volume_val->set_maximum_value(400); - ui_layout->addWidget(volume_val, 0, 1); + EffectRow* volume_row = add_row("Volume:"); + volume_val = volume_row->add_field(EFFECT_FIELD_DOUBLE); + volume_val->set_double_minimum_value(0); + volume_val->set_double_maximum_value(400); // set defaults - volume_val->set_value(100); + volume_val->set_double_default_value(100); } -void VolumeEffect::init() {} +void VolumeEffect::refresh() {} Effect* VolumeEffect::copy(Clip* c) { - VolumeEffect* v = new VolumeEffect(c); + /*VolumeEffect* v = new VolumeEffect(c); v->volume_val->set_value(volume_val->value()); - return v; -} - -void VolumeEffect::load(QXmlStreamReader* stream) { - while (!(stream->isEndElement() && stream->name() == "effect") && !stream->atEnd()) { - stream->readNext(); - if (stream->isStartElement() && stream->name() == "volume") { - stream->readNext(); - volume_val->set_value(stream->text().toDouble()); - } - } -} - -void VolumeEffect::save(QXmlStreamWriter* stream) { - stream->writeTextElement("volume", QString::number(volume_val->value())); + return v;*/ + return NULL; } void VolumeEffect::process_audio(quint8* samples, int nb_bytes) { - if (volume_val->value() != 100) { + double vol_val = volume_val->get_double_value(); + if (vol_val != 100) { for (int i=0;ivalue()*0.01, 3); + double val = qPow(vol_val*0.01, 3); samp *= val; if (samp > INT16_MAX) { samp = INT16_MAX; diff --git a/olive.pro b/olive.pro index 9dbd02ddf..583759478 100644 --- a/olive.pro +++ b/olive.pro @@ -68,7 +68,8 @@ SOURCES += \ effects/solideffect.cpp \ dialogs/replaceclipmediadialog.cpp \ effects/inverteffect.cpp \ - effects/linearfadetransition.cpp + effects/linearfadetransition.cpp \ + ui/fontcombobox.cpp HEADERS += \ mainwindow.h \ @@ -106,7 +107,8 @@ HEADERS += \ ui/scrollarea.h \ ui/comboboxex.h \ ui/colorbutton.h \ - dialogs/replaceclipmediadialog.h + dialogs/replaceclipmediadialog.h \ + ui/fontcombobox.h FORMS += \ mainwindow.ui \ diff --git a/project/clip.cpp b/project/clip.cpp index d454e37b5..546f86fab 100644 --- a/project/clip.cpp +++ b/project/clip.cpp @@ -116,7 +116,7 @@ void Clip::refresh() { // reinitializes all effects... just in case for (int i=0;iinit(); + effects.at(i)->refresh(); } } diff --git a/project/effect.cpp b/project/effect.cpp index cc6b5c99a..a765e6ceb 100644 --- a/project/effect.cpp +++ b/project/effect.cpp @@ -7,9 +7,14 @@ #include "effects/effects.h" #include "panels/project.h" #include "project/undo.h" +#include "ui/labelslider.h" +#include "ui/colorbutton.h" +#include "ui/comboboxex.h" +#include "ui/fontcombobox.h" #include #include +#include Effect::Effect(Clip* c, int t, int i) : parent_clip(c), type(t), id(i) { container = new CollapsibleWidget(); @@ -24,10 +29,26 @@ Effect::Effect(Clip* c, int t, int i) : parent_clip(c), type(t), id(i) { ui_layout = new QGridLayout(); ui->setLayout(ui_layout); - container->setContents(ui); + container->setContents(ui); } -void Effect::init() { +Effect::~Effect() { + for (int i=0;iaddWidget(new QLabel(name), row, 0); +} + +EffectField* EffectRow::add_field(int type) { + EffectField* field = new EffectField(parent_effect, type); + fields.append(field); + QWidget* element = field->get_ui_element(); + ui->addWidget(element, ui_row, fields.size()); + return field; +} + +EffectRow::~EffectRow() { + for (int i=0;isetUndoRedoEnabled(true); + ui_element = edit; + } + break; + case EFFECT_FIELD_BOOL: + { + QCheckBox* cb = new QCheckBox(); + ui_element = cb; + QObject::connect(cb, SIGNAL(toggled(bool)), parent, SLOT(field_changed())); + QObject::connect(cb, SIGNAL(clicked(bool)), parent, SLOT(checkbox_command())); + } + break; + case EFFECT_FIELD_COMBO: + { + ui_element = new ComboBoxEx(); + } + break; + case EFFECT_FIELD_FONT: + { + ui_element = new FontCombobox(); + } + break; + } +} + +QWidget* EffectField::get_ui_element() { + return ui_element; +} + +void EffectField::set_enabled(bool e) { + switch (type) { + case EFFECT_FIELD_DOUBLE: static_cast(ui_element)->setEnabled(e); break; + case EFFECT_FIELD_COLOR: static_cast(ui_element)->setEnabled(e); break; + case EFFECT_FIELD_STRING: static_cast(ui_element)->setEnabled(e); break; + case EFFECT_FIELD_BOOL: static_cast(ui_element)->setEnabled(e); break; + case EFFECT_FIELD_COMBO: static_cast(ui_element)->setEnabled(e); break; + case EFFECT_FIELD_FONT: static_cast(ui_element)->setEnabled(e); break; + } +} + +double EffectField::get_double_value() { + return static_cast(ui_element)->value(); +} + +void EffectField::set_double_value(double v) { + static_cast(ui_element)->set_value(v); +} + +void EffectField::set_double_default_value(double v) { + static_cast(ui_element)->set_default_value(v); +} + +void EffectField::set_double_minimum_value(double v) { + static_cast(ui_element)->set_minimum_value(v); +} + +void EffectField::set_double_maximum_value(double v) { + static_cast(ui_element)->set_maximum_value(v); +} + +void EffectField::add_combo_item(const QString& name, const QVariant& data) { + static_cast(ui_element)->addItem(name, data); +} + +int EffectField::get_combo_index() { + return static_cast(ui_element)->currentIndex(); +} + +const QVariant EffectField::get_combo_data() { + return static_cast(ui_element)->currentData(); +} + +const QString EffectField::get_combo_string() { + return static_cast(ui_element)->currentText(); +} + +void EffectField::set_combo_index(int index) { + static_cast(ui_element)->setCurrentIndex(index); +} + +bool EffectField::get_bool_value() { + return static_cast(ui_element)->isChecked(); +} + +void EffectField::set_bool_value(bool b) { + return static_cast(ui_element)->setChecked(b); +} + +const QString EffectField::get_string_value() { + return static_cast(ui_element)->toPlainText(); +} + +void EffectField::set_string_value(const QString& s) { + static_cast(ui_element)->setText(s); +} + +const QString EffectField::get_font_name() { + return static_cast(ui_element)->currentText(); +} + +QColor EffectField::get_color_value() { + return static_cast(ui_element)->get_color(); +} diff --git a/project/effect.h b/project/effect.h index f348699b5..39a58cf8c 100644 --- a/project/effect.h +++ b/project/effect.h @@ -3,6 +3,7 @@ #include #include +#include class QWidget; class CollapsibleWidget; class QGridLayout; @@ -10,30 +11,92 @@ class QGridLayout; struct Clip; class QXmlStreamReader; class QXmlStreamWriter; +class Effect; -enum EffectTypes { EFFECT_TYPE_INVALID, EFFECT_TYPE_VIDEO, EFFECT_TYPE_AUDIO }; +#define EFFECT_TYPE_INVALID 0 +#define EFFECT_TYPE_VIDEO 1 +#define EFFECT_TYPE_AUDIO 2 -class Effect : public QObject -{ +#define EFFECT_FIELD_DOUBLE 0 +#define EFFECT_FIELD_COLOR 1 +#define EFFECT_FIELD_STRING 2 +#define EFFECT_FIELD_BOOL 3 +#define EFFECT_FIELD_COMBO 4 +#define EFFECT_FIELD_FONT 5 + +class EffectField : QObject { Q_OBJECT public: - Effect(Clip* c, int t, int i); // default constructor + EffectField(Effect* parent, int t); + int type; + + double get_double_value(); + void set_double_value(double v); + void set_double_default_value(double v); + void set_double_minimum_value(double v); + void set_double_maximum_value(double v); + + const QString get_string_value(); + void set_string_value(const QString &s); + + void add_combo_item(const QString& name, const QVariant &data); + int get_combo_index(); + const QVariant get_combo_data(); + const QString get_combo_string(); + void set_combo_index(int index); + + bool get_bool_value(); + void set_bool_value(bool b); + + const QString get_font_name(); + + QColor get_color_value(); + + QWidget* get_ui_element(); + void set_enabled(bool e); +private: + QWidget* ui_element; +}; + +class EffectRow { +public: + EffectRow(Effect* parent, QGridLayout* uilayout, const QString& n, int row); + ~EffectRow(); + EffectField* add_field(int type); + EffectField* field(int i); + void set_keyframe(int field, long time); + void move_keyframe(int field, long from, long to); + void delete_keyframe(int field, long time); +private: + Effect* parent_effect; + QGridLayout* ui; + QString name; + int ui_row; + QVector fields; +}; + +class Effect : public QObject { + Q_OBJECT +public: + Effect(Clip* c, int t, int i); + ~Effect(); Clip* parent_clip; int type; int id; QString name; CollapsibleWidget* container; - QGridLayout* ui_layout; - QWidget* ui; + + EffectRow* add_row(const QString &name); + EffectRow* row(int i); bool is_enabled(); - virtual void init(); + virtual void refresh(); virtual Effect* copy(Clip* c); - virtual void load(QXmlStreamReader* stream); - virtual void save(QXmlStreamWriter* stream); + void load(QXmlStreamReader* stream); + void save(QXmlStreamWriter* stream); virtual void process_gl(int* anchor_x, int* anchor_y); virtual void post_gl(); @@ -41,6 +104,10 @@ public: public slots: void field_changed(); void checkbox_command(); +private: + QVector rows; + QGridLayout* ui_layout; + QWidget* ui; }; #endif // EFFECT_H diff --git a/ui/fontcombobox.cpp b/ui/fontcombobox.cpp new file mode 100644 index 000000000..62ec3462b --- /dev/null +++ b/ui/fontcombobox.cpp @@ -0,0 +1,22 @@ +#include "fontcombobox.h" + +#include + +FontCombobox::FontCombobox(QWidget* parent) : ComboBoxEx(parent) { + addItem(QFont().family()); +} + +void FontCombobox::showPopup() { + QString current = currentText(); + clear(); + QStringList fonts = QFontDatabase().families(); + bool found = false; + for (int i=0;isplit_tracks.at(i)); p.setPen(QColor(64, 64, 64)); - p.drawLine(cursor_x, cursor_y, cursor_x, cursor_y + panel_timeline->calculate_track_height(panel_timeline->cursor_track, -1)); + p.drawLine(cursor_x, cursor_y, cursor_x, cursor_y + panel_timeline->calculate_track_height(panel_timeline->split_tracks.at(i), -1)); } } }