sweeping vfx rewrite

This commit is contained in:
itsmattkc
2018-08-14 15:50:16 +10:00
parent 8fc4053d5f
commit d549586761
14 changed files with 446 additions and 406 deletions
+29 -42
View File
@@ -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
+9 -29
View File
@@ -9,40 +9,20 @@
#include <QXmlStreamAttributes>
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;i<attr.size();i++) {
const QXmlStreamAttribute& a = attr.at(i);
if (a.name() == "amount") {
amount_val->set_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) {
+12 -25
View File
@@ -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;i<nb_bytes;i+=4) {
qint16 left_sample = (qint16) (((samples[i+1] & 0xFF) << 8) | (samples[i] & 0xFF));
qint16 right_sample = (qint16) (((samples[i+3] & 0xFF) << 8) | (samples[i+2] & 0xFF));
double val = qPow(pan_val->value()*0.01, 3);
double val = qPow(pval*0.01, 3);
if (val < 0) {
// affect right channel
right_sample *= (1-std::abs(val));
+26 -53
View File
@@ -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;i<attr.size();i++) {
const QXmlStreamAttribute& a = attr.at(i);
if (a.name() == "intensity") {
intensity_val->set_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;
+24 -80
View File
@@ -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;i<fonts.size();i++) {
addItem(fonts.at(i));
if (!found && fonts.at(i) == current) {
setCurrentIndex(i);
found = true;
}
}
QComboBox::showPopup();
}
};
#include "ui/fontcombobox.h"
TextEffect::TextEffect(Clip *c) :
Effect(c, EFFECT_TYPE_VIDEO, VIDEO_TEXT_EFFECT),
@@ -44,33 +25,26 @@ TextEffect::TextEffect(Clip *c) :
width(0),
height(0)
{
ui_layout->addWidget(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<QTextEdit*>(text_val->get_ui_element()), SIGNAL(textChanged()), this, SLOT(update_texture()));
connect(static_cast<LabelSlider*>(size_val->get_ui_element()), SIGNAL(valueChanged()), this, SLOT(update_texture()));
connect(static_cast<ColorButton*>(set_color_button->get_ui_element()), SIGNAL(color_changed()), this, SLOT(update_texture()));
connect(static_cast<FontCombobox*>(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;i<attr.size();i++) {
const QXmlStreamAttribute& a = attr.at(i);
if (a.name() == "size") {
size_val->set_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;
}
+51 -137
View File
@@ -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<QCheckBox*>(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));
}
+12 -25
View File
@@ -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;i<nb_bytes;i+=2) {
qint32 samp = (qint16) (((samples[i+1] & 0xFF) << 8) | (samples[i] & 0xFF));
double val = qPow(volume_val->value()*0.01, 3);
double val = qPow(vol_val*0.01, 3);
samp *= val;
if (samp > INT16_MAX) {
samp = INT16_MAX;
+4 -2
View File
@@ -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 \
+1 -1
View File
@@ -116,7 +116,7 @@ void Clip::refresh() {
// reinitializes all effects... just in case
for (int i=0;i<effects.size();i++) {
effects.at(i)->init();
effects.at(i)->refresh();
}
}
+166 -2
View File
@@ -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 <QCheckBox>
#include <QGridLayout>
#include <QTextEdit>
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;i<rows.size();i++) {
delete rows.at(i);
}
}
EffectRow* Effect::add_row(const QString& name) {
EffectRow* row = new EffectRow(this, ui_layout, name, rows.size());
rows.append(row);
return row;
}
EffectRow* Effect::row(int i) {
return rows.at(i);
}
void Effect::refresh() {
qDebug() << "[WARNING] Tried to init base Effect class - type:" << type << "- id:" << id;
}
@@ -50,3 +71,146 @@ void Effect::save(QXmlStreamWriter*) {}
void Effect::process_gl(int*, int*) {}
void Effect::post_gl() {}
void Effect::process_audio(uint8_t*, int) {}
/* Effect Row Definitions */
EffectRow::EffectRow(Effect *parent, QGridLayout *uilayout, const QString &n, int row) : parent_effect(parent), ui(uilayout), name(n), ui_row(row) {
ui->addWidget(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;i<fields.size();i++) {
delete fields.at(i);
}
}
/* Effect Field Definitions */
EffectField::EffectField(Effect *parent, int t) : type(t) {
switch (t) {
case EFFECT_FIELD_DOUBLE:
{
LabelSlider* ls = new LabelSlider();
ui_element = ls;
QObject::connect(ls, SIGNAL(valueChanged()), parent, SLOT(field_changed()));
}
break;
case EFFECT_FIELD_COLOR:
{
ui_element = new ColorButton();
}
break;
case EFFECT_FIELD_STRING:
{
QTextEdit* edit = new QTextEdit();
edit->setUndoRedoEnabled(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<LabelSlider*>(ui_element)->setEnabled(e); break;
case EFFECT_FIELD_COLOR: static_cast<ColorButton*>(ui_element)->setEnabled(e); break;
case EFFECT_FIELD_STRING: static_cast<QTextEdit*>(ui_element)->setEnabled(e); break;
case EFFECT_FIELD_BOOL: static_cast<QCheckBox*>(ui_element)->setEnabled(e); break;
case EFFECT_FIELD_COMBO: static_cast<ComboBoxEx*>(ui_element)->setEnabled(e); break;
case EFFECT_FIELD_FONT: static_cast<FontCombobox*>(ui_element)->setEnabled(e); break;
}
}
double EffectField::get_double_value() {
return static_cast<LabelSlider*>(ui_element)->value();
}
void EffectField::set_double_value(double v) {
static_cast<LabelSlider*>(ui_element)->set_value(v);
}
void EffectField::set_double_default_value(double v) {
static_cast<LabelSlider*>(ui_element)->set_default_value(v);
}
void EffectField::set_double_minimum_value(double v) {
static_cast<LabelSlider*>(ui_element)->set_minimum_value(v);
}
void EffectField::set_double_maximum_value(double v) {
static_cast<LabelSlider*>(ui_element)->set_maximum_value(v);
}
void EffectField::add_combo_item(const QString& name, const QVariant& data) {
static_cast<QComboBox*>(ui_element)->addItem(name, data);
}
int EffectField::get_combo_index() {
return static_cast<QComboBox*>(ui_element)->currentIndex();
}
const QVariant EffectField::get_combo_data() {
return static_cast<QComboBox*>(ui_element)->currentData();
}
const QString EffectField::get_combo_string() {
return static_cast<QComboBox*>(ui_element)->currentText();
}
void EffectField::set_combo_index(int index) {
static_cast<QComboBox*>(ui_element)->setCurrentIndex(index);
}
bool EffectField::get_bool_value() {
return static_cast<QCheckBox*>(ui_element)->isChecked();
}
void EffectField::set_bool_value(bool b) {
return static_cast<QCheckBox*>(ui_element)->setChecked(b);
}
const QString EffectField::get_string_value() {
return static_cast<QTextEdit*>(ui_element)->toPlainText();
}
void EffectField::set_string_value(const QString& s) {
static_cast<QTextEdit*>(ui_element)->setText(s);
}
const QString EffectField::get_font_name() {
return static_cast<FontCombobox*>(ui_element)->currentText();
}
QColor EffectField::get_color_value() {
return static_cast<ColorButton*>(ui_element)->get_color();
}
+76 -9
View File
@@ -3,6 +3,7 @@
#include <QObject>
#include <QString>
#include <QVector>
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<EffectField*> 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<EffectRow*> rows;
QGridLayout* ui_layout;
QWidget* ui;
};
#endif // EFFECT_H
+22
View File
@@ -0,0 +1,22 @@
#include "fontcombobox.h"
#include <QFontDatabase>
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;i<fonts.size();i++) {
addItem(fonts.at(i));
if (!found && fonts.at(i) == current) {
setCurrentIndex(i);
found = true;
}
}
QComboBox::showPopup();
}
+13
View File
@@ -0,0 +1,13 @@
#ifndef FONTCOMBOBOX_H
#define FONTCOMBOBOX_H
#include "comboboxex.h"
class FontCombobox : public ComboBoxEx {
public:
FontCombobox(QWidget* parent = 0);
protected:
void showPopup();
};
#endif // FONTCOMBOBOX_H
+1 -1
View File
@@ -1825,7 +1825,7 @@ void TimelineWidget::paintEvent(QPaintEvent*) {
int cursor_y = getScreenPointFromTrack(panel_timeline->split_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));
}
}
}