half way through keyframes data

This commit is contained in:
itsmattkc
2018-08-19 15:53:35 +10:00
parent dacf0efd9a
commit 859a17dfda
22 changed files with 352 additions and 238 deletions
+2 -2
View File
@@ -24,12 +24,12 @@ void PanEffect::refresh() {}
Effect* PanEffect::copy(Clip* c) {
PanEffect* p = new PanEffect(c);
p->pan_val->set_double_value(pan_val->get_double_value());
copy_field_keyframes(p);
return p;
}
void PanEffect::process_audio(quint8 *samples, int nb_bytes) {
double pval = pan_val->get_double_value();
double pval = pan_val->get_double_value(-1);
if (pval != 0) {
for (int i=0;i<nb_bytes;i+=4) {
qint16 left_sample = (qint16) (((samples[i+1] & 0xFF) << 8) | (samples[i] & 0xFF));
+2 -2
View File
@@ -25,12 +25,12 @@ void VolumeEffect::refresh() {}
Effect* VolumeEffect::copy(Clip* c) {
VolumeEffect* v = new VolumeEffect(c);
v->volume_val->set_double_value(volume_val->get_double_value());
copy_field_keyframes(v);
return v;
}
void VolumeEffect::process_audio(quint8* samples, int nb_bytes) {
double vol_val = volume_val->get_double_value();
double vol_val = volume_val->get_double_value(-1);
if (vol_val != 100) {
for (int i=0;i<nb_bytes;i+=2) {
qint32 samp = (qint16) (((samples[i+1] & 0xFF) << 8) | (samples[i] & 0xFF));
+101 -31
View File
@@ -12,6 +12,7 @@
#include "ui/fontcombobox.h"
#include "ui/checkboxex.h"
#include "project/clip.h"
#include "panels/timeline.h"
#include "effects/video/transformeffect.h"
#include "effects/video/inverteffect.h"
@@ -92,6 +93,16 @@ Effect::~Effect() {
}
}
void Effect::copy_field_keyframes(Effect* e) {
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);
e->rows.at(i)->field(j)->keyframes = field->keyframes;
}
}
}
EffectRow* Effect::add_row(const QString& name) {
EffectRow* row = new EffectRow(this, ui_layout, name, rows.size());
rows.append(row);
@@ -165,34 +176,31 @@ void Effect::save(QXmlStreamWriter* stream) {
stream->writeStartElement("row");
for (int j=0;j<row->fieldCount();j++) {
EffectField* field = row->field(j);
switch (field->type) {
case EFFECT_FIELD_DOUBLE:
stream->writeTextElement("field", QString::number(field->get_double_value()));
break;
case EFFECT_FIELD_COLOR:
stream->writeTextElement("field", field->get_color_value().name());
break;
case EFFECT_FIELD_STRING:
stream->writeTextElement("field", field->get_string_value());
break;
case EFFECT_FIELD_BOOL:
stream->writeTextElement("field", QString::number(field->get_bool_value()));
break;
case EFFECT_FIELD_COMBO:
stream->writeTextElement("field", field->get_combo_string());
break;
case EFFECT_FIELD_FONT:
stream->writeTextElement("field", field->get_font_name());
break;
stream->writeStartElement("field");
for (int k=0;k<field->keyframes.size();k++) {
const EffectKeyframe& key = field->keyframes.at(i);
stream->writeStartElement("key");
stream->writeAttribute("frame", QString::number(key.frame));
stream->writeAttribute("type", QString::number(key.type));
switch (field->type) {
case EFFECT_FIELD_DOUBLE: stream->writeAttribute("value", QString::number(key.data.toDouble())); break;
case EFFECT_FIELD_COLOR: stream->writeAttribute("value", key.data.value<QColor>().name()); break;
case EFFECT_FIELD_STRING: stream->writeAttribute("value", key.data.toString()); break;
case EFFECT_FIELD_BOOL: stream->writeAttribute("value", QString::number(key.data.toBool())); break;
case EFFECT_FIELD_COMBO: stream->writeAttribute("value", key.data.toString()); break;
case EFFECT_FIELD_FONT: stream->writeAttribute("value", key.data.toString()); break;
}
stream->writeEndElement();
}
stream->writeEndElement(); // field
}
stream->writeEndElement(); // row
}
}
Effect* Effect::copy(Clip*) {return NULL;}
void Effect::process_image(QImage&) {}
void Effect::process_gl(QOpenGLShaderProgram&, int*, int*) {}
void Effect::process_image(long, QImage&) {}
void Effect::process_gl(long, QOpenGLShaderProgram&, int*, int*) {}
void Effect::process_audio(uint8_t*, int) {}
/* Effect Row Definitions */
@@ -231,6 +239,11 @@ int EffectRow::fieldCount() {
/* Effect Field Definitions */
EffectField::EffectField(int t) : type(t) {
// DEFAULT KEYFRAME
EffectKeyframe key;
key.frame = -1;
keyframes.append(key);
switch (t) {
case EFFECT_FIELD_DOUBLE:
{
@@ -279,6 +292,62 @@ EffectField::EffectField(int t) : type(t) {
}
}
bool EffectField::is_keyframed(long p) {
return keyframes.size() == 0 || p < 0;
}
QVariant EffectField::get_keyframe_data(long p) {
if (keyframes.size() == 1) {
return keyframes.at(0).data;
}
EffectKeyframe* before = NULL;
EffectKeyframe* after = NULL;
for (int i=1;i<keyframes.size();i++) {
if (keyframes.at(i).frame == p) {
return keyframes.at(i).data;
} else if (keyframes.at(i).frame < p && !(before != NULL && keyframes.at(i).frame <= before->frame)) {
before = &keyframes[i];
} else if (keyframes.at(i).frame > p && !(after != NULL && keyframes.at(i).frame >= after->frame)) {
after = &keyframes[i];
}
}
// interpolate data
if (before != NULL && after != NULL) {
double progress = (p - before->frame)/(after->frame - before->frame);
switch (type) {
case EFFECT_FIELD_DOUBLE:
{
return lerp(before->data.toDouble(), after->data.toDouble(), progress);
}
break;
case EFFECT_FIELD_COLOR:
{
QColor before_color = before->data.value<QColor>();
QColor after_color = after->data.value<QColor>();
QColor interval_color = QColor(
lerp(before_color.red(), after_color.red(), progress),
lerp(before_color.green(), after_color.green(), progress),
lerp(before_color.blue(), after_color.blue(), progress)
);
return QVariant(interval_color);
}
break;
case EFFECT_FIELD_STRING:
case EFFECT_FIELD_BOOL:
case EFFECT_FIELD_COMBO:
case EFFECT_FIELD_FONT:
return before->data;
break;
}
}
// return pre or post data
if (before != NULL) return before->data;
if (after != NULL) return after->data;
}
QWidget* EffectField::get_ui_element() {
return ui_element;
}
@@ -287,11 +356,12 @@ void EffectField::set_enabled(bool e) {
ui_element->setEnabled(e);
}
double EffectField::get_double_value() {
return static_cast<LabelSlider*>(ui_element)->value();
double EffectField::get_double_value(long p) {
return get_keyframe_data(p).toDouble();
}
void EffectField::set_double_value(double v) {
static_cast<LabelSlider*>(ui_element)->set_value(v, false);
}
@@ -311,16 +381,16 @@ void EffectField::add_combo_item(const QString& name, const QVariant& data) {
static_cast<ComboBoxEx*>(ui_element)->addItem(name, data);
}
int EffectField::get_combo_index() {
int EffectField::get_combo_index(long p) {
return static_cast<ComboBoxEx*>(ui_element)->currentIndex();
}
const QVariant EffectField::get_combo_data() {
const QVariant EffectField::get_combo_data(long p) {
return static_cast<ComboBoxEx*>(ui_element)->currentData();
}
const QString EffectField::get_combo_string() {
return static_cast<ComboBoxEx*>(ui_element)->currentText();
const QString EffectField::get_combo_string(long p) {
return static_cast<ComboBoxEx*>(ui_element)->itemText(get_keyframe_data(p).toInt());
}
void EffectField::set_combo_index(int index) {
@@ -331,7 +401,7 @@ void EffectField::set_combo_string(const QString& s) {
static_cast<ComboBoxEx*>(ui_element)->setCurrentTextEx(s);
}
bool EffectField::get_bool_value() {
bool EffectField::get_bool_value(long p) {
return static_cast<QCheckBox*>(ui_element)->isChecked();
}
@@ -339,7 +409,7 @@ void EffectField::set_bool_value(bool b) {
return static_cast<QCheckBox*>(ui_element)->setChecked(b);
}
const QString EffectField::get_string_value() {
const QString EffectField::get_string_value(long p) {
return static_cast<QTextEdit*>(ui_element)->toPlainText();
}
@@ -347,7 +417,7 @@ void EffectField::set_string_value(const QString& s) {
static_cast<QTextEdit*>(ui_element)->setText(s);
}
const QString EffectField::get_font_name() {
const QString EffectField::get_font_name(long p) {
return static_cast<FontCombobox*>(ui_element)->currentText();
}
@@ -355,7 +425,7 @@ void EffectField::set_font_name(const QString& s) {
static_cast<FontCombobox*>(ui_element)->setCurrentText(s);
}
QColor EffectField::get_color_value() {
QColor EffectField::get_color_value(long p) {
return static_cast<ColorButton*>(ui_element)->get_color();
}
+21 -23
View File
@@ -52,17 +52,10 @@ Effect* create_effect(int effect_id, Clip* c);
#define EFFECT_KEYFRAME_HOLD 1
#define EFFECT_KEYFRAME_BEZIER 2
union KeyframeValue {
double d;
QColor c;
bool b;
};
class EffectKeyframe {
public:
struct EffectKeyframe {
long frame;
int type;
KeyframeValue value;
QVariant data;
};
class EffectField : public QObject {
@@ -71,33 +64,37 @@ public:
EffectField(int t);
int type;
double get_double_value();
QVariant get_keyframe_data(long p);
bool is_keyframed(long p);
double get_double_value(long p);
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();
const QString get_string_value(long p);
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();
int get_combo_index(long p);
const QVariant get_combo_data(long p);
const QString get_combo_string(long p);
void set_combo_index(int index);
void set_combo_string(const QString& s);
bool get_bool_value();
bool get_bool_value(long p);
void set_bool_value(bool b);
const QString get_font_name();
const QString get_font_name(long p);
void set_font_name(const QString& s);
QColor get_color_value();
QColor get_color_value(long p);
void set_color_value(QColor color);
QWidget* get_ui_element();
void set_enabled(bool e);
QVector<EffectKeyframe> keyframes;
signals:
void changed();
void toggled(bool);
@@ -112,12 +109,12 @@ public:
EffectField* add_field(int type, int colspan = 1);
EffectField* field(int i);
int fieldCount();
void set_keyframe(int field, long time);
void move_keyframe(int field, long from, long to);
void delete_keyframe(int field, long time);
void set_keyframe(long time);
void move_keyframe(long from, long to);
void delete_keyframe(long time);
QLabel* label;
private:
Effect* parent_effect;
private:
QGridLayout* ui;
QString name;
int ui_row;
@@ -146,6 +143,7 @@ public:
virtual void refresh();
virtual Effect* copy(Clip* c);
void copy_field_keyframes(Effect *e);
void load(QXmlStreamReader* stream);
void save(QXmlStreamWriter* stream);
@@ -155,8 +153,8 @@ public:
const char* ffmpeg_filter;
virtual void process_image(QImage& img);
virtual void process_gl(QOpenGLShaderProgram& shader_prog, int* anchor_x, int* anchor_y);
virtual void process_image(long frame, QImage& img);
virtual void process_gl(long frame, QOpenGLShaderProgram& shader_prog, int* anchor_x, int* anchor_y);
virtual void process_audio(quint8* samples, int nb_bytes);
public slots:
void field_changed();
+7 -12
View File
@@ -19,25 +19,20 @@ InvertEffect::InvertEffect(Clip* c) : Effect(c, EFFECT_TYPE_VIDEO, VIDEO_INVERT_
// set defaults
amount_val->set_double_default_value(100);
connect(amount_val, SIGNAL(changed()), this, SLOT(compile()));
compile();
}
void InvertEffect::compile() {
double value = amount_val->get_double_value()*0.01;
vert_shader.compileSourceCode("varying vec2 vTexCoord; void main() { vTexCoord = gl_MultiTexCoord0; gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex; }");
frag_shader.compileSourceCode("uniform sampler2D myTexture; varying vec2 vTexCoord; void main(void) { vec4 textureColor = texture2D(myTexture, vTexCoord); gl_FragColor = vec4(textureColor.r+((1.0-textureColor.r-textureColor.r)*" + QString::number(value) + "), textureColor.g+((1.0-textureColor.g-textureColor.g)*" + QString::number(value) + "), textureColor.b+((1.0-textureColor.b-textureColor.b)*" + QString::number(value) + "), 1); }");
field_changed();
connect(amount_val, SIGNAL(changed()), this, SLOT(field_changed()));
}
Effect* InvertEffect::copy(Clip* c) {
InvertEffect* i = new InvertEffect(c);
i->amount_val->set_double_value(amount_val->get_double_value());
copy_field_keyframes(i);
return i;
}
void InvertEffect::process_gl(QOpenGLShaderProgram& shader_prog, int* anchor_x, int* anchor_y) {
void InvertEffect::process_gl(long p, QOpenGLShaderProgram& shader_prog, int* anchor_x, int* anchor_y) {
double value = amount_val->get_double_value(p)*0.01;
vert_shader.compileSourceCode("varying vec2 vTexCoord; void main() { vTexCoord = gl_MultiTexCoord0; gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex; }");
frag_shader.compileSourceCode("uniform sampler2D myTexture; varying vec2 vTexCoord; void main(void) { vec4 textureColor = texture2D(myTexture, vTexCoord); gl_FragColor = vec4(textureColor.r+((1.0-textureColor.r-textureColor.r)*" + QString::number(value) + "), textureColor.g+((1.0-textureColor.g-textureColor.g)*" + QString::number(value) + "), textureColor.b+((1.0-textureColor.b-textureColor.b)*" + QString::number(value) + "), 1); }");
shader_prog.addShader(&vert_shader);
shader_prog.addShader(&frag_shader);
}
+1 -3
View File
@@ -9,12 +9,10 @@ class InvertEffect : public Effect {
Q_OBJECT
public:
InvertEffect(Clip* c);
void process_gl(QOpenGLShaderProgram& shader_prog, int *anchor_x, int *anchor_y);
void process_gl(long p, QOpenGLShaderProgram& shader_prog, int *anchor_x, int *anchor_y);
Effect* copy(Clip *c);
EffectField* amount_val;
private slots:
void compile();
private:
QOpenGLShader vert_shader;
QOpenGLShader frag_shader;
+5 -7
View File
@@ -41,7 +41,7 @@ ShakeEffect::ShakeEffect(Clip *c) : Effect(c, EFFECT_TYPE_VIDEO, VIDEO_SHAKE_EFF
void ShakeEffect::refresh() {
if (parent_clip->sequence != NULL) {
shake_limit = qRound(parent_clip->sequence->frame_rate / frequency_val->get_double_value());
shake_limit = qRound(parent_clip->sequence->frame_rate / frequency_val->get_double_value(-1));
shake_progress = shake_limit;
next_x = 0;
next_y = 0;
@@ -51,15 +51,13 @@ void ShakeEffect::refresh() {
Effect* ShakeEffect::copy(Clip* c) {
ShakeEffect* e = new ShakeEffect(c);
e->intensity_val->set_double_value(intensity_val->get_double_value());
e->rotation_val->set_double_value(rotation_val->get_double_value());
e->frequency_val->set_double_value(frequency_val->get_double_value());
copy_field_keyframes(e);
return e;
}
void ShakeEffect::process_gl(QOpenGLShaderProgram&, int*, int*) {
void ShakeEffect::process_gl(long p, QOpenGLShaderProgram&, int*, int*) {
if (shake_progress > shake_limit) {
double ival = intensity_val->get_double_value();
double ival = intensity_val->get_double_value(p);
if ((int)ival > 0) {
prev_x = next_x;
prev_y = next_y;
@@ -89,7 +87,7 @@ void ShakeEffect::process_gl(QOpenGLShaderProgram&, int*, int*) {
offset_x = 0;
offset_y = 0;
}
double rot_val = rotation_val->get_double_value();
double rot_val = rotation_val->get_double_value(p);
if ((int)rot_val > 0) {
prev_rot = next_rot;
next_rot = (qrand() % (int) (rot_val * 2)) - rot_val;
+1 -1
View File
@@ -7,7 +7,7 @@ class ShakeEffect : public Effect {
Q_OBJECT
public:
ShakeEffect(Clip* c);
void process_gl(QOpenGLShaderProgram& shader_prog, int* anchor_x, int* anchor_y);
void process_gl(long p, QOpenGLShaderProgram& shader_prog, int* anchor_x, int* anchor_y);
Effect* copy(Clip *c);
EffectField* intensity_val;
+5 -5
View File
@@ -37,19 +37,19 @@ SolidEffect::SolidEffect(Clip* c) : Effect(c, EFFECT_TYPE_VIDEO, VIDEO_SOLID_EFF
}
void SolidEffect::enable_color() {
solid_color_field->set_enabled(solid_type->get_combo_data() == SOLID_TYPE_COLOR);
solid_color_field->set_enabled(solid_type->get_combo_data(-1) == SOLID_TYPE_COLOR);
}
void SolidEffect::process_image(QImage& img) {
void SolidEffect::process_image(long frame, QImage& img) {
QPainter p(&img);
int width = img.width();
int height = img.height();
switch (solid_type->get_combo_data().toInt()) {
switch (solid_type->get_combo_data(frame).toInt()) {
case SOLID_TYPE_COLOR:
{
QColor brush = solid_color_field->get_color_value();
p.fillRect(0, 0, width, height, QColor(brush.red(), brush.green(), brush.blue(), opacity_field->get_double_value()*2.55));
QColor brush = solid_color_field->get_color_value(frame);
p.fillRect(0, 0, width, height, QColor(brush.red(), brush.green(), brush.blue(), opacity_field->get_double_value(frame)*2.55));
}
break;
case SOLID_TYPE_BARS:
+1 -1
View File
@@ -10,7 +10,7 @@ public:
EffectField* solid_type;
EffectField* solid_color_field;
EffectField* opacity_field;
void process_image(QImage &img);
void process_image(long p, QImage &img);
private slots:
void enable_color();
};
+17 -22
View File
@@ -242,7 +242,7 @@ void blurred2(QImage& result, const QRect& rect, int radius, bool alphaOnly = fa
}
}
void TextEffect::process_image(QImage& img) {
void TextEffect::process_image(long frame, QImage& img) {
QPainter p(&img);
p.setRenderHint(QPainter::Antialiasing);
int width = img.width();
@@ -250,15 +250,15 @@ void TextEffect::process_image(QImage& img) {
// set font
font.setStyleHint(QFont::Helvetica, QFont::PreferAntialias);
font.setFamily(set_font_combobox->get_font_name());
font.setPointSize(size_val->get_double_value());
font.setFamily(set_font_combobox->get_font_name(frame));
font.setPointSize(size_val->get_double_value(frame));
p.setFont(font);
QFontMetrics fm(font);
QStringList lines = text_val->get_string_value().split('\n');
QStringList lines = text_val->get_string_value(frame).split('\n');
// word wrap function
if (word_wrap_field->get_bool_value()) {
if (word_wrap_field->get_bool_value(frame)) {
for (int i=0;i<lines.size();i++) {
const QString& s = lines.at(i);
if (fm.width(s) > width) {
@@ -287,7 +287,7 @@ void TextEffect::process_image(QImage& img) {
for (int i=0;i<lines.size();i++) {
int text_x, text_y;
switch (halign_field->get_combo_data().toInt()) {
switch (halign_field->get_combo_data(frame).toInt()) {
case Qt::AlignLeft: text_x = 0; break;
case Qt::AlignHCenter: text_x = (width/2) - (fm.width(lines.at(i))/2); break;
case Qt::AlignRight: text_x = width - fm.width(lines.at(i)); break;
@@ -316,7 +316,7 @@ void TextEffect::process_image(QImage& img) {
break;
}
switch (valign_field->get_combo_data().toInt()) {
switch (valign_field->get_combo_data(frame).toInt()) {
case Qt::AlignTop: text_y = (fm.height()*i)+fm.ascent(); break;
case Qt::AlignVCenter: text_y = ((height/2) - (text_height/2) - fm.descent()) + (fm.height()*(i+1)); break;
case Qt::AlignBottom: text_y = (height - text_height - fm.descent()) + (fm.height()*(i+1)); break;
@@ -328,43 +328,38 @@ void TextEffect::process_image(QImage& img) {
p.setPen(Qt::NoPen);
// draw shadow
if (shadow_bool->get_bool_value()) {
if (shadow_bool->get_bool_value(frame)) {
QImage shadow(width, height, QImage::Format_ARGB32_Premultiplied);
shadow.fill(Qt::transparent);
QPainter spaint(&shadow);
int shadow_offset = shadow_distance->get_double_value();
QColor col = shadow_color->get_color_value();
col.setAlphaF(shadow_opacity->get_double_value()*0.01);
int shadow_offset = shadow_distance->get_double_value(frame);
QColor col = shadow_color->get_color_value(frame);
col.setAlphaF(shadow_opacity->get_double_value(frame)*0.01);
spaint.setBrush(col);
spaint.drawPath(path);
blurred2(shadow, shadow.rect(), shadow_softness->get_double_value(), false);
blurred2(shadow, shadow.rect(), shadow_softness->get_double_value(frame), false);
p.drawImage(shadow_offset, shadow_offset, shadow);
spaint.end();
}
// draw outline
int outline_width_val = outline_width->get_double_value();
if (outline_bool->get_bool_value() && outline_width_val > 0) {
QPen outline(outline_color->get_color_value());
int outline_width_val = outline_width->get_double_value(frame);
if (outline_bool->get_bool_value(frame) && outline_width_val > 0) {
QPen outline(outline_color->get_color_value(frame));
outline.setWidth(outline_width_val);
p.setPen(outline);
}
// draw "master" text
p.setBrush(set_color_button->get_color_value());
p.setBrush(set_color_button->get_color_value(frame));
p.drawPath(path);
}
Effect* TextEffect::copy(Clip* c) {
TextEffect* e = new TextEffect(c);
e->text_val->set_string_value(text_val->get_string_value());
e->size_val->set_double_value(size_val->get_double_value());
e->set_color_button->set_color_value(set_color_button->get_color_value());
e->set_font_combobox->set_font_name(set_font_combobox->get_font_name());
e->halign_field->set_combo_index(halign_field->get_combo_index());
e->valign_field->set_combo_index(valign_field->get_combo_index());
copy_field_keyframes(e);
return e;
}
+1 -1
View File
@@ -9,7 +9,7 @@ class TextEffect : public Effect {
Q_OBJECT
public:
TextEffect(Clip* c);
void process_image(QImage& img);
void process_image(long frame, QImage& img);
Effect* copy(Clip* c);
EffectField* text_val;
+10 -19
View File
@@ -80,16 +80,7 @@ TransformEffect::TransformEffect(Clip* c) : Effect(c, EFFECT_TYPE_VIDEO, VIDEO_T
Effect* TransformEffect::copy(Clip* c) {
TransformEffect* t = new TransformEffect(c);
t->position_x->set_double_value(position_x->get_double_value());
t->position_y->set_double_value(position_y->get_double_value());
t->scale_x->set_double_value(scale_x->get_double_value());
t->scale_y->set_double_value(scale_y->get_double_value());
t->uniform_scale_field->set_bool_value(uniform_scale_field->get_bool_value());
t->rotation->set_double_value(rotation->get_double_value());
t->anchor_x_box->set_double_value(anchor_x_box->get_double_value());
t->anchor_y_box->set_double_value(anchor_y_box->get_double_value());
t->opacity->set_double_value(opacity->get_double_value());
t->blend_mode_box->set_combo_index(blend_mode_box->get_combo_index());
copy_field_keyframes(t);
return t;
}
@@ -136,24 +127,24 @@ void TransformEffect::toggle_uniform_scale(bool enabled) {
scale_y->set_enabled(!enabled);
}
void TransformEffect::process_gl(QOpenGLShaderProgram&, int* anchor_x, int* anchor_y) {
void TransformEffect::process_gl(long frame, QOpenGLShaderProgram&, int* anchor_x, int* anchor_y) {
// position
glTranslatef(position_x->get_double_value()-(parent_clip->sequence->width/2), position_y->get_double_value()-(parent_clip->sequence->height/2), 0);
glTranslatef(position_x->get_double_value(frame)-(parent_clip->sequence->width/2), position_y->get_double_value(frame)-(parent_clip->sequence->height/2), 0);
// anchor point
*anchor_x += (anchor_x_box->get_double_value()-default_anchor_x);
*anchor_y += (anchor_y_box->get_double_value()-default_anchor_y);
*anchor_x += (anchor_x_box->get_double_value(frame)-default_anchor_x);
*anchor_y += (anchor_y_box->get_double_value(frame)-default_anchor_y);
// rotation
glRotatef(rotation->get_double_value(), 0, 0, 1);
glRotatef(rotation->get_double_value(frame), 0, 0, 1);
// scale
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;
float sx = scale_x->get_double_value(frame)*0.01;
float sy = (uniform_scale_field->get_bool_value(frame)) ? sx : scale_y->get_double_value(frame)*0.01;
glScalef(sx, sy, 1);
// blend mode
switch (blend_mode_box->get_combo_data().toInt()) {
switch (blend_mode_box->get_combo_data(frame).toInt()) {
case BLEND_MODE_NORMAL:
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
break;
@@ -173,5 +164,5 @@ void TransformEffect::process_gl(QOpenGLShaderProgram&, int* anchor_x, int* anch
// opacity
float color[4];
glGetFloatv(GL_CURRENT_COLOR, color);
glColor4f(1.0, 1.0, 1.0, color[3]*(opacity->get_double_value()*0.01));
glColor4f(1.0, 1.0, 1.0, color[3]*(opacity->get_double_value(frame)*0.01));
}
+1 -1
View File
@@ -8,7 +8,7 @@ class TransformEffect : public Effect {
public:
TransformEffect(Clip* c);
void refresh();
void process_gl(QOpenGLShaderProgram& shader_prog, int* anchor_x, int* anchor_y);
void process_gl(long p, QOpenGLShaderProgram& shader_prog, int* anchor_x, int* anchor_y);
Effect* copy(Clip *c);
EffectField* position_x;
+25 -1
View File
@@ -4,6 +4,8 @@
#include <QMenu>
#include <QDebug>
#include <QVBoxLayout>
#include <QResizeEvent>
#include <QScrollBar>
#include "panels/panels.h"
#include "effects/effect.h"
@@ -28,6 +30,12 @@ EffectControls::EffectControls(QWidget *parent) :
init_transitions();
clear_effects(false);
ui->headers->snapping = false;
ui->effects_area->parent_widget = ui->scrollArea;
ui->effects_area->keyframe_area = ui->keyframeView;
ui->effects_area->header = ui->headers;
connect(ui->keyframeScroller->verticalScrollBar(), SIGNAL(valueChanged(int)), ui->scrollArea->verticalScrollBar(), SLOT(setValue(int)));
}
EffectControls::~EffectControls() {
@@ -182,9 +190,18 @@ void EffectControls::load_effects() {
}
connect(container, SIGNAL(deselect_others(QWidget*)), this, SLOT(deselect_all_effects(QWidget*)));
connect(container, SIGNAL(visibleChanged()), ui->keyframeView, SLOT(reload()));
}
}
}
if (selected_clips.size() > 0) {
// ui->scrollArea->setMinimumWidth(ui->effects_area->width());
/*ui->effects_area->layout()->update();
ui->effects_area->layout()->activate();
qDebug() << ui->effects_area->height();
ui->keyframeView->resize(ui->keyframeView->width(), ui->effects_area->height());*/
ui->keyframeView->setMinimumHeight(ui->effects_area->height());
ui->keyframeView->setEnabled(true);
ui->keyframeView->visible_in = effects_in;
ui->keyframeView->visible_out = effects_out;
@@ -266,3 +283,10 @@ bool EffectControls::is_focused() {
}
return false;
}
EffectsArea::EffectsArea(QWidget* parent) : QWidget(parent) {}
void EffectsArea::resizeEvent(QResizeEvent *event) {
parent_widget->setMinimumWidth(sizeHint().width());
keyframe_area->setMinimumHeight(height() - header->height());
}
+11
View File
@@ -8,6 +8,17 @@ struct Clip;
class QMenu;
class Effect;
class TimelineHeader;
class QScrollArea;
class KeyframeView;
class EffectsArea : public QWidget {
public:
EffectsArea(QWidget* parent = 0);
void resizeEvent(QResizeEvent *event);
QScrollArea* parent_widget;
KeyframeView* keyframe_area;
TimelineHeader* header;
};
namespace Ui {
class EffectControls;
+122 -92
View File
@@ -40,44 +40,62 @@
<number>0</number>
</property>
<item>
<widget class="QScrollArea" name="scrollArea">
<property name="widgetResizable">
<bool>true</bool>
<widget class="QSplitter" name="splitter_2">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<widget class="QWidget" name="scrollAreaWidgetContents">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>619</width>
<height>489</height>
</rect>
<property name="childrenCollapsible">
<bool>false</bool>
</property>
<widget class="QScrollArea" name="scrollArea">
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<layout class="QVBoxLayout" name="verticalLayout_8">
<property name="spacing">
<number>0</number>
<property name="frameShape">
<enum>QFrame::NoFrame</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Plain</enum>
</property>
<property name="verticalScrollBarPolicy">
<enum>Qt::ScrollBarAlwaysOff</enum>
</property>
<property name="horizontalScrollBarPolicy">
<enum>Qt::ScrollBarAlwaysOn</enum>
</property>
<property name="widgetResizable">
<bool>true</bool>
</property>
<widget class="QWidget" name="scrollAreaWidgetContents">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>225</width>
<height>477</height>
</rect>
</property>
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QSplitter" name="splitter">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="childrenCollapsible">
<bool>false</bool>
</property>
<widget class="QWidget" name="effects_area" native="true">
<layout class="QHBoxLayout" name="horizontalLayout_3">
<property name="spacing">
<number>0</number>
</property>
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="EffectsArea" name="effects_area" native="true">
<layout class="QVBoxLayout" name="verticalLayout">
<property name="spacing">
<number>0</number>
@@ -399,69 +417,75 @@
</item>
</layout>
</widget>
<widget class="QScrollArea" name="scrollArea_2">
</item>
</layout>
</widget>
</widget>
<widget class="QScrollArea" name="keyframeScroller">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
<horstretch>1</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="verticalScrollBarPolicy">
<enum>Qt::ScrollBarAlwaysOn</enum>
</property>
<property name="horizontalScrollBarPolicy">
<enum>Qt::ScrollBarAlwaysOn</enum>
</property>
<property name="widgetResizable">
<bool>true</bool>
</property>
<widget class="QWidget" name="scrollAreaWidgetContents_2">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>376</width>
<height>475</height>
</rect>
</property>
<layout class="QVBoxLayout" name="verticalLayout_2">
<property name="spacing">
<number>0</number>
</property>
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="TimelineHeader" name="headers" native="true">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
<horstretch>1</horstretch>
<sizepolicy hsizetype="Preferred" vsizetype="Maximum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="widgetResizable">
<bool>true</bool>
<property name="minimumSize">
<size>
<width>0</width>
<height>15</height>
</size>
</property>
<property name="focusPolicy">
<enum>Qt::ClickFocus</enum>
</property>
<widget class="QWidget" name="scrollAreaWidgetContents_2">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>388</width>
<height>487</height>
</rect>
</property>
<layout class="QVBoxLayout" name="verticalLayout_2">
<property name="spacing">
<number>0</number>
</property>
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="TimelineHeader" name="headers" native="true">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Maximum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>0</width>
<height>15</height>
</size>
</property>
<property name="focusPolicy">
<enum>Qt::ClickFocus</enum>
</property>
</widget>
</item>
<item>
<widget class="KeyframeView" name="keyframeView" native="true"/>
</item>
</layout>
</widget>
</widget>
</widget>
</item>
</layout>
</item>
<item>
<widget class="KeyframeView" name="keyframeView" native="true"/>
</item>
</layout>
</widget>
</widget>
</widget>
</item>
@@ -481,6 +505,12 @@
<header>ui/timelineheader.h</header>
<container>1</container>
</customwidget>
<customwidget>
<class>EffectsArea</class>
<extends>QWidget</extends>
<header>panels/effectcontrols.h</header>
<container>1</container>
</customwidget>
</customwidgets>
<resources/>
<connections/>
+1 -1
View File
@@ -394,7 +394,7 @@ void Timeline::delete_selection(bool ripple_delete) {
}
int lerp(int a, int b, double t) {
return ((1.0 - t) * a) + (t * b);
return ((1.0 - t) * a) + (t * b);
}
void Timeline::set_zoom(bool in) {
+3 -2
View File
@@ -76,7 +76,8 @@ void cache_clip(Clip* clip, long playhead, bool write_A, bool write_B, bool rese
void get_clip_frame(Clip* c, long playhead) {
if (c->open) {
long clip_time = refactor_frame_number(playhead - c->timeline_in + c->clip_in, c->sequence->frame_rate, av_q2d(av_guess_frame_rate(c->formatCtx, c->stream, c->frame)));
long sequence_clip_time = playhead - c->timeline_in + c->clip_in;
long clip_time = refactor_frame_number(sequence_clip_time, c->sequence->frame_rate, av_q2d(av_guess_frame_rate(c->formatCtx, c->stream, c->frame)));
// do we need to update the texture?
MediaStream* ms = static_cast<Media*>(c->media)->get_stream_from_file_index(c->media_stream);
@@ -169,7 +170,7 @@ void get_clip_frame(Clip* c, long playhead) {
QImage img(c->comp_frame, current_frame->width, current_frame->height, QImage::Format_RGBA8888);
for (int i=0;i<c->effects.size();i++) {
if (c->effects.at(i)->enable_image) {
c->effects.at(i)->process_image(img);
c->effects.at(i)->process_image(sequence_clip_time, img);
}
}
+12 -7
View File
@@ -16,12 +16,6 @@
KeyframeView::KeyframeView(QWidget *parent) : QWidget(parent), mouseover(false), visible_in(0), visible_out(0) {
setFocusPolicy(Qt::ClickFocus);
setMouseTracking(true);
reload();
}
void KeyframeView::reload() {
enable_reload = true;
update();
}
void KeyframeView::paintEvent(QPaintEvent*) {
@@ -30,6 +24,7 @@ void KeyframeView::paintEvent(QPaintEvent*) {
setMinimumWidth(getScreenPointFromFrame(panel_effect_controls->zoom, visible_out - visible_in));
rowY.clear();
rows.clear();
for (int i=0;i<effects.size();i++) {
Effect* e = effects.at(i);
if (e->container->is_expanded()) {
@@ -39,6 +34,8 @@ void KeyframeView::paintEvent(QPaintEvent*) {
long frame = 20;
int keyframe_y = label->y() + (label->height()>>1) + mapFrom(panel_effect_controls, contents->mapTo(panel_effect_controls, contents->pos())).y() - e->container->title_bar->height();
draw_keyframe(p, getScreenPointFromFrame(panel_effect_controls->zoom, frame), keyframe_y, false);
rows.append(e->row(j));
rowY.append(keyframe_y);
}
}
@@ -51,7 +48,7 @@ void KeyframeView::paintEvent(QPaintEvent*) {
}
if (mouseover && mouseover_row < rowY.size()) {
draw_keyframe(p, getScreenPointFromFrame(panel_effect_controls->zoom, mouseover_frame) - visible_in, rowY.at(mouseover_row), true);
draw_keyframe(p, getScreenPointFromFrame(panel_effect_controls->zoom, mouseover_frame - visible_in), rowY.at(mouseover_row), true);
}
}
@@ -63,6 +60,10 @@ void KeyframeView::draw_keyframe(QPainter &p, int x, int y, bool semiTransparent
p.drawPolygon(points, KEYFRAME_POINT_COUNT);
}
void KeyframeView::mousePressEvent(QMouseEvent *event) {
qDebug() << "create keyframe @ clip frame" << mouseover_frame - visible_in + (rows.at(mouseover_row)->parent_effect->parent_clip->clip_in) << "effect row" << mouseover_row;
}
void KeyframeView::mouseMoveEvent(QMouseEvent* event) {
unsetCursor();
bool new_mo = false;
@@ -80,3 +81,7 @@ void KeyframeView::mouseMoveEvent(QMouseEvent* event) {
}
mouseover = new_mo;
}
void KeyframeView::mouseReleaseEvent(QMouseEvent* event) {
}
+2 -4
View File
@@ -16,14 +16,12 @@ public:
long visible_in;
long visible_out;
public slots:
void reload();
private:
QVector<int> rowY;
QVector<EffectRow*> rows;
void mousePressEvent(QMouseEvent* event);
void mouseMoveEvent(QMouseEvent* event);
/*void mousePressEvent(QMouseEvent* event);
void mouseReleaseEvent(QMouseEvent *event);*/
void mouseReleaseEvent(QMouseEvent *event);
void paintEvent(QPaintEvent *event);
void draw_keyframe(QPainter& p, int x, int y, bool semiTransparent);
bool enable_reload;
+1 -1
View File
@@ -177,7 +177,7 @@ void ViewerWidget::compose_sequence(QVector<Clip*>& nests, bool render_audio) {
QOpenGLShaderProgram shader;
for (int j=0;j<c->effects.size();j++) {
if (c->effects.at(j)->enable_opengl && c->effects.at(j)->is_enabled()) c->effects.at(j)->process_gl(shader, &anchor_x, &anchor_y);
if (c->effects.at(j)->enable_opengl && c->effects.at(j)->is_enabled()) c->effects.at(j)->process_gl(panel_timeline->playhead-c->timeline_in+c->clip_in, shader, &anchor_x, &anchor_y);
}
if (c->opening_transition != NULL) {