file/folder restructuring

This commit is contained in:
itsmattkc
2019-03-13 16:55:49 +11:00
parent d84b5a7f1d
commit 1cd5dabc07
228 changed files with 1269 additions and 1557 deletions
-1
View File
@@ -1 +0,0 @@
Place this folder in the runtime folder of Olive.
+1056
View File
File diff suppressed because it is too large Load Diff
+261
View File
@@ -0,0 +1,261 @@
/***
Olive - Non-Linear Video Editor
Copyright (C) 2019 Olive Team
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
***/
#ifndef EFFECT_H
#define EFFECT_H
#include <memory>
#include <QObject>
#include <QString>
#include <QVector>
#include <QColor>
#include <QOpenGLFunctions>
#include <QOpenGLShaderProgram>
#include <QOpenGLTexture>
#include <QMutex>
#include <QThread>
#include <QLabel>
#include <QWidget>
#include <QGridLayout>
#include <QPushButton>
#include <QMouseEvent>
#include <QXmlStreamReader>
#include <QXmlStreamWriter>
#include <random>
#include "ui/collapsiblewidget.h"
#include "ui/checkboxex.h"
#include "effectfields.h"
#include "effectrow.h"
#include "effectgizmo.h"
class Clip;
class Effect;
using EffectPtr = std::shared_ptr<Effect>;
struct EffectMeta {
QString name;
QString category;
QString filename;
QString path;
QString tooltip;
int internal;
int type;
int subtype;
};
extern QVector<EffectMeta> effects;
double log_volume(double linear);
enum EffectType {
EFFECT_TYPE_INVALID,
EFFECT_TYPE_VIDEO,
EFFECT_TYPE_AUDIO,
EFFECT_TYPE_EFFECT,
EFFECT_TYPE_TRANSITION
};
enum EffectKeyframeType {
EFFECT_KEYFRAME_LINEAR,
EFFECT_KEYFRAME_BEZIER,
EFFECT_KEYFRAME_HOLD
};
enum EffectInternal {
EFFECT_INTERNAL_TRANSFORM,
EFFECT_INTERNAL_TEXT,
EFFECT_INTERNAL_SOLID,
EFFECT_INTERNAL_NOISE,
EFFECT_INTERNAL_VOLUME,
EFFECT_INTERNAL_PAN,
EFFECT_INTERNAL_TONE,
EFFECT_INTERNAL_SHAKE,
EFFECT_INTERNAL_TIMECODE,
EFFECT_INTERNAL_MASK,
EFFECT_INTERNAL_FILLLEFTRIGHT,
EFFECT_INTERNAL_VST,
EFFECT_INTERNAL_CORNERPIN,
EFFECT_INTERNAL_FREI0R,
EFFECT_INTERNAL_COUNT
};
struct GLTextureCoords {
int grid_size;
int vertexTopLeftX;
int vertexTopLeftY;
int vertexTopLeftZ;
int vertexTopRightX;
int vertexTopRightY;
int vertexTopRightZ;
int vertexBottomLeftX;
int vertexBottomLeftY;
int vertexBottomLeftZ;
int vertexBottomRightX;
int vertexBottomRightY;
int vertexBottomRightZ;
float textureTopLeftX;
float textureTopLeftY;
float textureTopLeftQ;
float textureTopRightX;
float textureTopRightY;
float textureTopRightQ;
float textureBottomRightX;
float textureBottomRightY;
float textureBottomRightQ;
float textureBottomLeftX;
float textureBottomLeftY;
float textureBottomLeftQ;
int blendmode;
float opacity;
};
const EffectMeta* get_meta_from_name(const QString& input);
qint16 mix_audio_sample(qint16 a, qint16 b);
class Effect : public QObject {
Q_OBJECT
public:
Effect(Clip *c, const EffectMeta* em);
~Effect();
Clip* parent_clip;
const EffectMeta* meta;
int id;
QString name;
void AddRow(EffectRow* row);
EffectRow* row(int i);
int row_count();
EffectGizmo* add_gizmo(int type);
EffectGizmo* gizmo(int i);
int gizmo_count();
bool IsEnabled();
void SetEnabled(bool b);
virtual void refresh();
virtual EffectPtr copy(Clip* c);
void copy_field_keyframes(EffectPtr e);
virtual void load(QXmlStreamReader& stream);
virtual void custom_load(QXmlStreamReader& stream);
virtual void save(QXmlStreamWriter& stream);
void load_from_string(const QByteArray &s);
QByteArray save_to_string();
// glsl handling
bool is_open();
void open();
void close();
bool is_glsl_linked();
virtual void startEffect();
virtual void endEffect();
enum VideoEffectFlags {
ShaderFlag = 0x1,
CoordsFlag = 0x2,
SuperimposeFlag = 0x4,
ImageFlag = 0x8
};
int Flags();
void SetFlags(int flags);
int getIterations();
void setIterations(int i);
const char* ffmpeg_filter;
virtual void process_image(double timecode, uint8_t* input, uint8_t* output, int size);
virtual void process_shader(double timecode, GLTextureCoords&, int iteration);
virtual void process_coords(double timecode, GLTextureCoords& coords, int data);
virtual GLuint process_superimpose(double timecode);
virtual void process_audio(double timecode_start, double timecode_end, quint8* samples, int nb_bytes, int channel_count);
virtual void gizmo_draw(double timecode, GLTextureCoords& coords);
void gizmo_move(EffectGizmo* sender, int x_movement, int y_movement, double timecode, bool done);
void gizmo_world_to_screen();
bool are_gizmos_enabled();
template <typename T>
T randomNumber()
{
static std::random_device device;
static std::mt19937 generator(device());
static std::uniform_int_distribution<> distribution(std::numeric_limits<T>::min(), std::numeric_limits<T>::max());
return distribution(generator);
}
static EffectPtr Create(Clip *c, const EffectMeta *em);
static const EffectMeta* GetInternalMeta(int internal_id, int type);
public slots:
void FieldChanged();
signals:
void EnabledChanged(bool);
private slots:
void delete_self();
void move_up();
void move_down();
void save_to_file();
void load_from_file();
protected:
// glsl effect
QOpenGLShaderProgram* glslProgram;
QString vertPath;
QString fragPath;
// superimpose effect
QImage img;
QOpenGLTexture* texture;
bool AlwaysUpdate();
void SetAlwaysUpdate(bool b);
private:
bool isOpen;
QVector<EffectRow*> rows;
QVector<EffectGizmo*> gizmos;
bool bound;
int iterations;
bool enabled_;
int flags_;
// enable effect to update constantly
bool enable_always_update_;
// superimpose functions
virtual void redraw(double timecode);
bool valueHasChanged(double timecode);
QVector<QVariant> cachedValues;
void delete_texture();
void validate_meta_path();
};
#endif // EFFECT_H
+403
View File
@@ -0,0 +1,403 @@
/***
Olive - Non-Linear Video Editor
Copyright (C) 2019 Olive Team
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
***/
#include "effectfield.h"
#include <QDateTime>
#include <QtMath>
#include "ui/labelslider.h"
#include "ui/colorbutton.h"
#include "ui/texteditex.h"
#include "ui/checkboxex.h"
#include "ui/comboboxex.h"
#include "ui/fontcombobox.h"
#include "ui/embeddedfilechooser.h"
#include "rendering/renderfunctions.h"
#include "global/config.h"
#include "effects/effectrow.h"
#include "effects/effect.h"
#include "undo/undo.h"
#include "timeline/clip.h"
#include "timeline/sequence.h"
#include "global/math.h"
#include "global/debug.h"
EffectField::EffectField(EffectRow* parent, const QString &i, EffectFieldType t) :
QObject(parent),
type_(t),
id_(i),
enabled_(true),
colspan_(1)
{
// EffectField MUST be created with a parent.
Q_ASSERT(parent != nullptr);
Q_ASSERT(!i.isEmpty() || t == EFFECT_FIELD_UI);
// Add this field to the parent row specified
parent->AddField(this);
// Set a very base default value
SetValueAt(0, 0);
// Connect this field to the effect's changed function
connect(this, SIGNAL(Changed()), parent->GetParentEffect(), SLOT(FieldChanged()));
}
EffectField::~EffectField() {}
EffectRow *EffectField::GetParentRow()
{
return static_cast<EffectRow*>(parent());
}
int EffectField::GetColumnSpan()
{
return colspan_;
}
void EffectField::SetColumnSpan(int i)
{
Q_ASSERT(i >= 1);
colspan_ = i;
}
QVariant EffectField::ConvertStringToValue(const QString &s)
{
return s;
}
QString EffectField::ConvertValueToString(const QVariant &v)
{
return v.toString();
}
QWidget *EffectField::CreateWidget()
{
return new QLabel(tr("(Invalid field)"));
}
void EffectField::UpdateWidgetValue(QWidget *, double) {}
QVariant EffectField::GetValueAt(double timecode)
{
if (HasKeyframes()) {
int before_keyframe;
int after_keyframe;
double progress;
get_keyframe_data(timecode, before_keyframe, after_keyframe, progress);
const QVariant& before_data = keyframes.at(before_keyframe).data;
switch (type_) {
case EFFECT_FIELD_DOUBLE:
{
double value;
if (before_keyframe == after_keyframe) {
value = keyframes.at(before_keyframe).data.toDouble();
} else {
const EffectKeyframe& before_key = keyframes.at(before_keyframe);
const EffectKeyframe& after_key = keyframes.at(after_keyframe);
double before_dbl = before_key.data.toDouble();
double after_dbl = after_key.data.toDouble();
if (before_key.type == EFFECT_KEYFRAME_HOLD) {
// Hold keyframes will always return the previous keyframe with no interpolation
value = before_dbl;
} else if (before_key.type == EFFECT_KEYFRAME_BEZIER || after_key.type == EFFECT_KEYFRAME_BEZIER) {
// bezier interpolation
if (before_key.type == EFFECT_KEYFRAME_BEZIER && after_key.type == EFFECT_KEYFRAME_BEZIER) {
// cubic bezier
double t = cubic_t_from_x(timecodeToFrame(timecode),
before_key.time,
before_key.time+GetValidKeyframeHandlePosition(before_keyframe, true),
after_key.time+GetValidKeyframeHandlePosition(after_keyframe, false),
after_key.time);
value = cubic_from_t(before_dbl,
before_dbl+before_key.post_handle_y,
after_dbl+after_key.pre_handle_y,
after_dbl,
t);
} else if (after_key.type == EFFECT_KEYFRAME_LINEAR) { // quadratic bezier
// last keyframe is the bezier one
double t = quad_t_from_x(timecodeToFrame(timecode),
before_key.time,
before_key.time+GetValidKeyframeHandlePosition(before_keyframe, true),
after_key.time);
value = quad_from_t(before_dbl,
before_dbl+before_key.post_handle_y,
after_dbl,
t);
} else {
// this keyframe is the bezier one
double t = quad_t_from_x(timecodeToFrame(timecode),
before_key.time,
after_key.time+GetValidKeyframeHandlePosition(after_keyframe, false),
after_key.time);
value = quad_from_t(before_dbl,
after_dbl+after_key.pre_handle_y,
after_dbl,
t);
}
} else {
// Linear interpolation (default)
value = double_lerp(before_dbl, after_dbl, progress);
}
}
perpetual_data_ = value;
break;
}
case EFFECT_FIELD_COLOR:
{
QColor value;
if (before_keyframe == after_keyframe) {
value = keyframes.at(before_keyframe).data.value<QColor>();
} else {
QColor before_data = keyframes.at(before_keyframe).data.value<QColor>();
QColor after_data = keyframes.at(after_keyframe).data.value<QColor>();
value = QColor(lerp(before_data.red(), after_data.red(), progress), lerp(before_data.green(), after_data.green(), progress), lerp(before_data.blue(), after_data.blue(), progress));
}
perpetual_data_ = value;
break;
}
case EFFECT_FIELD_STRING:
case EFFECT_FIELD_BOOL:
case EFFECT_FIELD_COMBO:
case EFFECT_FIELD_FONT:
case EFFECT_FIELD_FILE:
perpetual_data_ = before_data;
break;
default:
break;
}
}
return perpetual_data_;
}
void EffectField::SetValueAt(double time, const QVariant &value)
{
if (HasKeyframes()) {
// Create keyframe here
// Convert seconds timecode to frame
long frame_timecode = timecodeToFrame(time);
// Check array if a keyframe at this time already exists
int keyframe_index = -1;
for (int i=0;i<keyframes.size();i++) {
if (keyframes.at(i).time == frame_timecode) {
keyframe_index = i;
break;
}
}
// If keyframe doesn't exist, make it
if (keyframe_index == -1) {
EffectKeyframe key;
key.time = frame_timecode;
key.data = value;
key.type = (keyframes.isEmpty()) ? EFFECT_KEYFRAME_LINEAR : keyframes.last().type;
keyframes.append(key);
} else {
EffectKeyframe& key = keyframes[keyframe_index];
key.data = value;
}
} else {
perpetual_data_ = value;
}
emit Changed();
}
double EffectField::Now()
{
Clip* c = GetParentRow()->GetParentEffect()->parent_clip;
return playhead_to_clip_seconds(c, c->sequence->playhead);
}
long EffectField::NowInFrames()
{
Clip* c = GetParentRow()->GetParentEffect()->parent_clip;
return playhead_to_clip_frame(c, c->sequence->playhead);
}
void EffectField::PrepareDataForKeyframing(bool enabled, ComboAction *ca)
{
if (enabled) {
// Create keyframe from perpetual data
EffectKeyframe key;
key.time = NowInFrames();
key.data = perpetual_data_;
key.type = EFFECT_KEYFRAME_LINEAR;
keyframes.append(key);
ca->append(new KeyframeAdd(this, keyframes.size()-1));
} else {
// Convert keyframes to one "perpetual" keyframe
// Set first keyframe to whatever the data is now
ca->append(new SetQVariant(&perpetual_data_, perpetual_data_, GetValueAt(Now())));
// Delete all keyframes
for (int i=0;i<keyframes.size();i++) {
ca->append(new KeyframeDelete(this, 0));
}
}
}
const EffectField::EffectFieldType &EffectField::type()
{
return type_;
}
const QString &EffectField::id()
{
return id_;
}
double EffectField::GetValidKeyframeHandlePosition(int key, bool post) {
int comp_key = -1;
// find keyframe before or after this one
for (int i=0;i<keyframes.size();i++) {
if (i != key
&& ((keyframes.at(i).time > keyframes.at(key).time) == post)
&& (comp_key == -1
|| ((keyframes.at(i).time < keyframes.at(comp_key).time) == post))) {
// compare with next keyframe for post or previous frame for pre
comp_key = i;
}
}
double adjusted_key = post ? keyframes.at(key).post_handle_x : keyframes.at(key).pre_handle_x;
// if this is the earliest/latest keyframe, no validation is required
if (comp_key == -1) {
return adjusted_key;
}
double comp = keyframes.at(comp_key).time - keyframes.at(key).time;
// if comp keyframe is bezier, validate with its accompanying handle
if (keyframes.at(comp_key).type == EFFECT_KEYFRAME_BEZIER) {
double relative_comp_handle = comp + (post ? keyframes.at(comp_key).pre_handle_x : keyframes.at(comp_key).post_handle_x);
// return an average
if ((post && keyframes.at(key).post_handle_x > relative_comp_handle)
|| (!post && keyframes.at(key).pre_handle_x < relative_comp_handle)) {
adjusted_key = (adjusted_key + relative_comp_handle)*0.5;
}
}
// don't let handle go beyond the compare keyframe's time
if (post == (adjusted_key > comp)) {
return comp;
}
if (post == (adjusted_key < 0)) {
return 0;
}
// original value is valid
return adjusted_key;
}
double EffectField::frameToTimecode(long frame) {
return (double(frame) / GetParentRow()->GetParentEffect()->parent_clip->sequence->frame_rate);
}
long EffectField::timecodeToFrame(double timecode) {
return qRound(timecode * GetParentRow()->GetParentEffect()->parent_clip->sequence->frame_rate);
}
void EffectField::get_keyframe_data(double timecode, int &before, int &after, double &progress) {
int before_keyframe_index = -1;
int after_keyframe_index = -1;
long before_keyframe_time = LONG_MIN;
long after_keyframe_time = LONG_MAX;
long frame = timecodeToFrame(timecode);
for (int i=0;i<keyframes.size();i++) {
long eval_keyframe_time = keyframes.at(i).time;
if (eval_keyframe_time == frame) {
before = i;
after = i;
return;
} else if (eval_keyframe_time < frame && eval_keyframe_time > before_keyframe_time) {
before_keyframe_index = i;
before_keyframe_time = eval_keyframe_time;
} else if (eval_keyframe_time > frame && eval_keyframe_time < after_keyframe_time) {
after_keyframe_index = i;
after_keyframe_time = eval_keyframe_time;
}
}
if ((type_ == EFFECT_FIELD_DOUBLE || type_ == EFFECT_FIELD_COLOR) && (before_keyframe_index > -1 && after_keyframe_index > -1)) {
// interpolate
before = before_keyframe_index;
after = after_keyframe_index;
progress = (timecode-frameToTimecode(before_keyframe_time))/(frameToTimecode(after_keyframe_time)-frameToTimecode(before_keyframe_time));
} else if (before_keyframe_index > -1) {
before = before_keyframe_index;
after = before_keyframe_index;
} else {
before = after_keyframe_index;
after = after_keyframe_index;
}
}
bool EffectField::HasKeyframes() {
return (GetParentRow()->IsKeyframing() && !keyframes.isEmpty());
}
bool EffectField::IsEnabled() {
return enabled_;
}
void EffectField::SetEnabled(bool e) {
enabled_ = e;
emit EnabledChanged(enabled_);
}
+100
View File
@@ -0,0 +1,100 @@
/***
Olive - Non-Linear Video Editor
Copyright (C) 2019 Olive Team
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
***/
#ifndef EFFECTFIELD_H
#define EFFECTFIELD_H
#include <QObject>
#include <QVariant>
#include <QVector>
#include "effects/keyframe.h"
class EffectRow;
class ComboAction;
class EffectField : public QObject {
Q_OBJECT
public:
enum EffectFieldType {
EFFECT_FIELD_DOUBLE,
EFFECT_FIELD_COLOR,
EFFECT_FIELD_STRING,
EFFECT_FIELD_BOOL,
EFFECT_FIELD_COMBO,
EFFECT_FIELD_FONT,
EFFECT_FIELD_FILE,
EFFECT_FIELD_UI
};
EffectField(EffectRow* parent, const QString& i, EffectFieldType t);
~EffectField();
EffectRow* GetParentRow();
const EffectFieldType& type();
const QString& id();
QVariant GetValueAt(double timecode);
void SetValueAt(double time, const QVariant& value);
double Now();
long NowInFrames();
void PrepareDataForKeyframing(bool enabled, ComboAction* ca);
int GetColumnSpan();
void SetColumnSpan(int i);
virtual QVariant ConvertStringToValue(const QString& s);
virtual QString ConvertValueToString(const QVariant& v);
virtual QWidget* CreateWidget();
virtual void UpdateWidgetValue(QWidget* widget, double);
double GetValidKeyframeHandlePosition(int key, bool post);
bool IsEnabled();
void SetEnabled(bool e);
QVector<EffectKeyframe> keyframes;
signals:
void Changed();
void Clicked();
void EnabledChanged(bool);
private:
EffectFieldType type_;
QString id_;
bool HasKeyframes();
double frameToTimecode(long frame);
long timecodeToFrame(double timecode);
void get_keyframe_data(double timecode, int& before, int& after, double& d);
bool enabled_;
int colspan_;
QVariant perpetual_data_;
};
#endif // EFFECTFIELD_H
+14
View File
@@ -0,0 +1,14 @@
#ifndef EFFECTFIELDS_H
#define EFFECTFIELDS_H
#include "fields/boolfield.h"
#include "fields/buttonfield.h"
#include "fields/colorfield.h"
#include "fields/combofield.h"
#include "fields/doublefield.h"
#include "fields/filefield.h"
#include "fields/fontfield.h"
#include "fields/labelfield.h"
#include "fields/stringfield.h"
#endif // EFFECTFIELDS_H
+73
View File
@@ -0,0 +1,73 @@
/***
Olive - Non-Linear Video Editor
Copyright (C) 2019 Olive Team
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
***/
#include "effectgizmo.h"
#include "ui/labelslider.h"
#include "effectfields/doublefield.h"
#include "project/effect.h"
EffectGizmo::EffectGizmo(Effect *parent, int type) :
QObject(parent),
x_field1(nullptr),
x_field_multi1(1.0),
y_field1(nullptr),
y_field_multi1(1.0),
x_field2(nullptr),
x_field_multi2(1.0),
y_field2(nullptr),
y_field_multi2(1.0),
type(type),
cursor(-1)
{
Q_ASSERT(parent != nullptr);
int point_count = (type == GIZMO_TYPE_POLY) ? 4 : 1;
world_pos.resize(point_count);
screen_pos.resize(point_count);
color = Qt::white;
}
void EffectGizmo::set_previous_value() {
// TODO address this
/*
if (x_field1 != nullptr) static_cast<LabelSlider*>(x_field1->ui_element)->set_previous_value();
if (y_field1 != nullptr) static_cast<LabelSlider*>(y_field1->ui_element)->set_previous_value();
if (x_field2 != nullptr) static_cast<LabelSlider*>(x_field2->ui_element)->set_previous_value();
if (y_field2 != nullptr) static_cast<LabelSlider*>(y_field2->ui_element)->set_previous_value();
*/
}
int EffectGizmo::get_point_count() {
return world_pos.size();
}
int EffectGizmo::get_type() {
return type;
}
int EffectGizmo::get_cursor() {
return cursor;
}
void EffectGizmo::set_cursor(int c) {
cursor = c;
}
+74
View File
@@ -0,0 +1,74 @@
/***
Olive - Non-Linear Video Editor
Copyright (C) 2019 Olive Team
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
***/
#ifndef EFFECTGIZMO_H
#define EFFECTGIZMO_H
enum GizmoType {
GIZMO_TYPE_DOT,
GIZMO_TYPE_POLY,
GIZMO_TYPE_TARGET
};
#define GIZMO_DOT_SIZE 2.5
#define GIZMO_TARGET_SIZE 5.0
#include <QObject>
#include <QString>
#include <QRect>
#include <QPoint>
#include <QVector>
#include <QColor>
class DoubleField;
class Effect;
class EffectGizmo : public QObject {
Q_OBJECT
public:
EffectGizmo(Effect* parent, int type);
QVector<QPoint> world_pos;
QVector<QPoint> screen_pos;
DoubleField* x_field1;
double x_field_multi1;
DoubleField* y_field1;
double y_field_multi1;
DoubleField* x_field2;
double x_field_multi2;
DoubleField* y_field2;
double y_field_multi2;
void set_previous_value();
QColor color;
int get_point_count();
int get_type();
int get_cursor();
void set_cursor(int c);
private:
int type;
int cursor;
};
#endif // EFFECTGIZMO_H
+271
View File
@@ -0,0 +1,271 @@
/***
Olive - Non-Linear Video Editor
Copyright (C) 2019 Olive Team
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
***/
#include "effectloaders.h"
#include "effects/effect.h"
#include "effects/transition.h"
#include "global/path.h"
#include "panels/panels.h"
#include "panels/effectcontrols.h"
#include "global/crossplatformlib.h"
#include "global/config.h"
#include <QDir>
#include <QXmlStreamReader>
#include <QDebug>
#ifndef NOFREI0R
#include <frei0r.h>
typedef void (*f0rGetPluginInfo)(f0r_plugin_info_t* info);
#endif
void load_internal_effects() {
if (!olive::CurrentRuntimeConfig.shaders_are_enabled) qWarning() << "Shaders are disabled, some effects may be nonfunctional";
EffectMeta em;
// load internal effects
em.path = ":/internalshaders";
em.type = EFFECT_TYPE_EFFECT;
em.subtype = EFFECT_TYPE_AUDIO;
em.name = "Volume";
em.internal = EFFECT_INTERNAL_VOLUME;
effects.append(em);
em.name = "Pan";
em.internal = EFFECT_INTERNAL_PAN;
effects.append(em);
#ifndef NOVST
em.name = "VST Plugin 2.x";
em.internal = EFFECT_INTERNAL_VST;
effects.append(em);
#endif
em.name = "Tone";
em.internal = EFFECT_INTERNAL_TONE;
effects.append(em);
em.name = "Noise";
em.internal = EFFECT_INTERNAL_NOISE;
effects.append(em);
em.name = "Fill Left/Right";
em.internal = EFFECT_INTERNAL_FILLLEFTRIGHT;
effects.append(em);
em.subtype = EFFECT_TYPE_VIDEO;
em.name = "Transform";
em.category = "Distort";
em.internal = EFFECT_INTERNAL_TRANSFORM;
effects.append(em);
em.name = "Corner Pin";
em.internal = EFFECT_INTERNAL_CORNERPIN;
effects.append(em);
/*em.name = "Mask";
em.internal = EFFECT_INTERNAL_MASK;
effects.append(em);*/
em.name = "Shake";
em.internal = EFFECT_INTERNAL_SHAKE;
effects.append(em);
em.name = "Text";
em.category = "Render";
em.internal = EFFECT_INTERNAL_TEXT;
effects.append(em);
em.name = "Timecode";
em.internal = EFFECT_INTERNAL_TIMECODE;
effects.append(em);
em.name = "Solid";
em.internal = EFFECT_INTERNAL_SOLID;
effects.append(em);
// internal transitions
em.type = EFFECT_TYPE_TRANSITION;
em.category = "";
em.name = "Cross Dissolve";
em.internal = TRANSITION_INTERNAL_CROSSDISSOLVE;
effects.append(em);
em.subtype = EFFECT_TYPE_AUDIO;
em.name = "Linear Fade";
em.internal = TRANSITION_INTERNAL_LINEARFADE;
effects.append(em);
em.name = "Exponential Fade";
em.internal = TRANSITION_INTERNAL_EXPONENTIALFADE;
effects.append(em);
em.name = "Logarithmic Fade";
em.internal = TRANSITION_INTERNAL_LOGARITHMICFADE;
effects.append(em);
}
void load_shader_effects() {
QList<QString> effects_paths = get_effects_paths();
for (int h=0;h<effects_paths.size();h++) {
const QString& effects_path = effects_paths.at(h);
QDir effects_dir(effects_path);
if (effects_dir.exists()) {
QList<QString> entries = effects_dir.entryList(QStringList("*.xml"), QDir::Files);
for (int i=0;i<entries.size();i++) {
QFile file(effects_path + "/" + entries.at(i));
if (!file.open(QIODevice::ReadOnly)) {
qCritical() << "Could not open" << entries.at(i);
return;
}
QXmlStreamReader reader(&file);
while (!reader.atEnd()) {
if (reader.name() == "effect") {
QString effect_name = "";
QString effect_cat = "";
const QXmlStreamAttributes attr = reader.attributes();
for (int j=0;j<attr.size();j++) {
if (attr.at(j).name() == "name") {
effect_name = attr.at(j).value().toString();
} else if (attr.at(j).name() == "category") {
effect_cat = attr.at(j).value().toString();
}
}
if (!effect_name.isEmpty()) {
EffectMeta em;
em.type = EFFECT_TYPE_EFFECT;
em.subtype = EFFECT_TYPE_VIDEO;
em.name = effect_name;
em.category = effect_cat;
em.filename = file.fileName();
em.path = effects_path;
em.internal = -1;
effects.append(em);
} else {
qCritical() << "Invalid effect found in" << entries.at(i);
}
break;
}
reader.readNext();
}
file.close();
}
}
}
}
void init_effects() {
EffectInit* init_thread = new EffectInit();
QObject::connect(init_thread, SIGNAL(finished()), init_thread, SLOT(deleteLater()));
init_thread->start();
}
#ifndef NOFREI0R
void load_frei0r_effects_worker(const QString& dir, EffectMeta& em, QVector<QString>& loaded_names) {
QDir search_dir(dir);
if (search_dir.exists()) {
QList<QString> entry_list = search_dir.entryList(LibFilter(), QDir::AllDirs | QDir::Files | QDir::NoDotAndDotDot);
for (int j=0;j<entry_list.size();j++) {
QString entry_path = search_dir.filePath(entry_list.at(j));
if (QFileInfo(entry_path).isDir()) {
load_frei0r_effects_worker(entry_path, em, loaded_names);
} else {
ModulePtr effect = LibLoad(entry_path);
if (effect != nullptr) {
f0rGetPluginInfo get_info_func = reinterpret_cast<f0rGetPluginInfo>(LibAddress(effect, "f0r_get_plugin_info"));
if (get_info_func != nullptr) {
f0r_plugin_info_t info;
get_info_func(&info);
if (!loaded_names.contains(info.name)
&& info.plugin_type == F0R_PLUGIN_TYPE_FILTER
&& info.color_model == F0R_COLOR_MODEL_RGBA8888) {
em.name = info.name;
em.path = dir;
em.filename = entry_list.at(j);
em.tooltip = QString("%1\n%2\n%3\n%4").arg(em.name, info.author, info.explanation, em.filename);
loaded_names.append(em.name);
effects.append(em);
}
// qDebug() << "Found:" << info.name << "by" << info.author;
}
LibClose(effect);
}
// qDebug() << search_dir.filePath(entry_list.at(j));
}
}
}
}
void load_frei0r_effects() {
QList<QString> effect_dirs = get_effects_paths();
// add defined paths for frei0r plugins on unix
#if defined(__APPLE__) || defined(__linux__) || defined(__HAIKU__)
effect_dirs.prepend("/usr/lib/frei0r-1");
effect_dirs.prepend("/usr/local/lib/frei0r-1");
effect_dirs.prepend(QDir::homePath() + "/.frei0r-1/lib");
#endif
QString env_path(qgetenv("FREI0R_PATH"));
if (!env_path.isEmpty()) effect_dirs.append(env_path);
QVector<QString> loaded_names;
// search for paths
EffectMeta em;
em.category = "Frei0r";
em.type = EFFECT_TYPE_EFFECT;
em.subtype = EFFECT_TYPE_VIDEO;
em.internal = EFFECT_INTERNAL_FREI0R;
for (int i=0;i<effect_dirs.size();i++) {
load_frei0r_effects_worker(effect_dirs.at(i), em, loaded_names);
}
}
#endif
EffectInit::EffectInit() {
panel_effect_controls->effects_loaded.lock();
}
void EffectInit::run() {
qInfo() << "Initializing effects...";
load_internal_effects();
load_shader_effects();
#ifndef NOFREI0R
load_frei0r_effects();
#endif
panel_effect_controls->effects_loaded.unlock();
qInfo() << "Finished initializing effects";
}
+36
View File
@@ -0,0 +1,36 @@
/***
Olive - Non-Linear Video Editor
Copyright (C) 2019 Olive Team
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
***/
#ifndef EFFECTLOADERS_H
#define EFFECTLOADERS_H
#include <QList>
#include <QThread>
void init_effects();
class EffectInit : public QThread {
public:
EffectInit();
protected:
void run();
};
#endif // EFFECTLOADERS_H
+248
View File
@@ -0,0 +1,248 @@
/***
Olive - Non-Linear Video Editor
Copyright (C) 2019 Olive Team
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
***/
#include "effectrow.h"
#include <QHBoxLayout>
#include <QPushButton>
#include <QMessageBox>
#include "undo/undo.h"
#include "timeline/clip.h"
#include "timeline/sequence.h"
#include "panels/panels.h"
#include "panels/effectcontrols.h"
#include "panels/viewer.h"
#include "panels/grapheditor.h"
#include "effect.h"
#include "ui/viewerwidget.h"
#include "ui/keyframenavigator.h"
#include "ui/clickablelabel.h"
EffectRow::EffectRow(Effect *parent, const QString &n, bool savable, bool keyframable) :
QObject(parent),
name_(n),
keyframable_(keyframable),
keyframing_(false),
savable_(savable)
{
Q_ASSERT(parent != nullptr);
parent->AddRow(this);
}
void EffectRow::AddField(EffectField *field)
{
field->setParent(this);
fields_.append(field);
}
bool EffectRow::IsKeyframing() {
return keyframing_;
}
void EffectRow::SetKeyframingInternal(bool b) {
if (GetParentEffect()->meta->type != EFFECT_TYPE_TRANSITION) {
keyframing_ = b;
emit KeyframingSetChanged(keyframing_);
}
}
bool EffectRow::IsSavable()
{
return savable_;
}
void EffectRow::SetKeyframingEnabled(bool enabled) {
if (enabled) {
ComboAction* ca = new ComboAction();
// Enable keyframing setting on this row
ca->append(new SetIsKeyframing(this, true));
// Prepare each field's data to start keyframing
for (int i=0;i<FieldCount();i++) {
Field(i)->PrepareDataForKeyframing(true, ca);
}
olive::UndoStack.push(ca);
} else {
// Confirm with the user whether they really want to disable keyframing
if (QMessageBox::question(panel_effect_controls,
tr("Disable Keyframes"),
tr("Disabling keyframes will delete all current keyframes. "
"Are you sure you want to do this?"),
QMessageBox::Yes, QMessageBox::No) == QMessageBox::Yes) {
ComboAction* ca = new ComboAction();
// Prepare each field's data to stop keyframing
for (int i=0;i<FieldCount();i++) {
Field(i)->PrepareDataForKeyframing(false, ca);
}
// Disable keyframing setting on this row
ca->append(new SetIsKeyframing(this, false));
olive::UndoStack.push(ca);
panel_effect_controls->update_keyframes();
} else {
SetKeyframingInternal(true);
}
}
}
void EffectRow::GoToPreviousKeyframe() {
long key = LONG_MIN;
Clip* c = GetParentEffect()->parent_clip;
long sequence_playhead = c->sequence->playhead;
// Used to convert clip frame number to sequence frame number
long time_adjustment = c->timeline_in() - c->clip_in();
// Loop through all of this row's fields
for (int i=0;i<FieldCount();i++) {
EffectField* f = Field(i);
// Loop through all of this field's keyframes for a keyframe EARLIER than the playhead
for (int j=0;j<f->keyframes.size();j++) {
long comp = f->keyframes.at(j).time + time_adjustment;
// Get the closest keyframe
if (comp < sequence_playhead) {
key = qMax(comp, key);
}
}
}
// If we found a keyframe less than the playhead, jump to it
if (key != LONG_MIN) panel_sequence_viewer->seek(key);
}
void EffectRow::ToggleKeyframe() {
Clip* c = GetParentEffect()->parent_clip;
long sequence_playhead = c->sequence->playhead;
// Used to convert clip frame number to sequence frame number
long time_adjustment = c->timeline_in() - c->clip_in();
QVector<EffectField*> key_fields;
QVector<int> key_field_index;
// See if any keyframes on any fields are at the current time
for (int j=0;j<FieldCount();j++) {
EffectField* f = Field(j);
for (int i=0;i<f->keyframes.size();i++) {
long comp = f->keyframes.at(i).time + time_adjustment;
if (comp == sequence_playhead) {
// Cache the keyframes if they are at the current time
key_fields.append(f);
key_field_index.append(i);
}
}
}
ComboAction* ca = new ComboAction();
if (key_fields.isEmpty()) {
// If we didn't find any current keyframes, create one for each field
SetKeyframeOnAllFields(ca);
} else {
// If we DID find keyframes at this time, delete them
for (int i=0;i<key_fields.size();i++) {
ca->append(new KeyframeDelete(key_fields.at(i), key_field_index.at(i)));
}
}
olive::UndoStack.push(ca);
update_ui(false);
}
void EffectRow::GoToNextKeyframe() {
long key = LONG_MAX;
Clip* c = GetParentEffect()->parent_clip;
for (int i=0;i<FieldCount();i++) {
EffectField* f = Field(i);
for (int j=0;j<f->keyframes.size();j++) {
long comp = f->keyframes.at(j).time - c->clip_in() + c->timeline_in();
if (comp > olive::ActiveSequence->playhead) {
key = qMin(comp, key);
}
}
}
if (key != LONG_MAX) panel_sequence_viewer->seek(key);
}
void EffectRow::FocusRow() {
panel_graph_editor->set_row(this);
}
void EffectRow::SetKeyframeOnAllFields(ComboAction* ca) {
for (int i=0;i<FieldCount();i++) {
EffectField* field = Field(i);
field->SetValueAt(field->Now(), field->GetValueAt(field->Now()));
}
panel_effect_controls->update_keyframes();
}
void EffectRow::delete_keyframe_at_time(ComboAction* ca, long time) {
for (int j=0;j<FieldCount();j++) {
EffectField* f = Field(j);
for (int i=0;i<f->keyframes.size();i++) {
if (f->keyframes.at(i).time == time) {
ca->append(new KeyframeDelete(f, i));
break;
}
}
}
}
Effect *EffectRow::GetParentEffect()
{
return static_cast<Effect*>(parent());
}
const QString &EffectRow::name() {
return name_;
}
EffectField* EffectRow::Field(int i) {
return fields_.at(i);
}
int EffectRow::FieldCount() {
return fields_.size();
}
+78
View File
@@ -0,0 +1,78 @@
/***
Olive - Non-Linear Video Editor
Copyright (C) 2019 Olive Team
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
***/
#ifndef EFFECTROW_H
#define EFFECTROW_H
#include <QObject>
#include <QVector>
class Effect;
class QGridLayout;
class EffectField;
class QLabel;
class QPushButton;
class ComboAction;
class QHBoxLayout;
class KeyframeNavigator;
class ClickableLabel;
#include "effectfields.h"
class EffectRow : public QObject {
Q_OBJECT
public:
EffectRow(Effect* parent, const QString& n, bool savable = true, bool keyframable = true);
void AddField(EffectField* Field);
EffectField* Field(int i);
int FieldCount();
void SetKeyframeOnAllFields(ComboAction *ca);
void delete_keyframe_at_time(ComboAction *ca, long time);
Effect* GetParentEffect();
const QString& name();
bool IsKeyframing();
void SetKeyframingInternal(bool);
bool IsSavable();
public slots:
void GoToPreviousKeyframe();
void ToggleKeyframe();
void GoToNextKeyframe();
void FocusRow();
signals:
void KeyframingSetChanged(bool);
private slots:
void SetKeyframingEnabled(bool);
private:
QString name_;
bool keyframable_;
bool keyframing_;
bool savable_;
QVector<EffectField*> fields_;
};
#endif // EFFECTROW_H
+52
View File
@@ -0,0 +1,52 @@
#include "boolfield.h"
#include <QCheckBox>
BoolField::BoolField(EffectRow *parent, const QString &id) :
EffectField(parent, id, EFFECT_FIELD_BOOL)
{}
bool BoolField::GetBoolAt(double timecode)
{
return GetValueAt(timecode).toBool();
}
QWidget *BoolField::CreateWidget()
{
QCheckBox* cb = new QCheckBox();
connect(cb, SIGNAL(toggled(bool)), this, SLOT(UpdateFromWidget(bool)));
connect(this, SIGNAL(EnabledChanged(bool)), cb, SLOT(setEnabled(bool)));
connect(cb, SIGNAL(toggled(bool)), this, SIGNAL(Toggled(bool)));
return cb;
}
void BoolField::UpdateWidgetValue(QWidget *widget, double timecode)
{
QCheckBox* cb = static_cast<QCheckBox*>(widget);
// Setting the checked state on the checkbox below normally triggers a change() signal that will then trickle back
// to setting a value on this field. Therefore we block its signals while we're setting this.
cb->blockSignals(true);
cb->setChecked(GetBoolAt(timecode));
cb->blockSignals(false);
}
QVariant BoolField::ConvertStringToValue(const QString &s)
{
return (s == "1");
}
QString BoolField::ConvertValueToString(const QVariant &v)
{
return QString::number(v.toBool());
}
void BoolField::UpdateFromWidget(bool b)
{
SetValueAt(Now(), b);
}
+25
View File
@@ -0,0 +1,25 @@
#ifndef BOOLFIELD_H
#define BOOLFIELD_H
#include "../effectfield.h"
class BoolField : public EffectField
{
Q_OBJECT
public:
BoolField(EffectRow* parent, const QString& id);
bool GetBoolAt(double timecode);
virtual QWidget* CreateWidget() override;
virtual void UpdateWidgetValue(QWidget* widget, double timecode) override;
virtual QVariant ConvertStringToValue(const QString& s) override;
virtual QString ConvertValueToString(const QVariant& v) override;
signals:
void Toggled(bool);
private slots:
void UpdateFromWidget(bool b);
};
#endif // BOOLFIELD_H
+36
View File
@@ -0,0 +1,36 @@
#include "buttonfield.h"
#include <QPushButton>
ButtonField::ButtonField(EffectRow *parent, const QString &string) :
EffectField(parent, nullptr, EFFECT_FIELD_UI),
button_text_(string)
{}
void ButtonField::SetCheckable(bool c)
{
checkable_ = c;
}
void ButtonField::SetChecked(bool c)
{
checked_ = c;
emit CheckedChanged(c);
}
QWidget *ButtonField::CreateWidget()
{
QPushButton* button = new QPushButton();
button->setCheckable(checkable_);
button->setEnabled(IsEnabled());
button->setText(button_text_);
connect(this, SIGNAL(CheckedChanged(bool)), button, SLOT(setChecked(bool)));
connect(this, SIGNAL(EnabledChanged(bool)), button, SLOT(setEnabled(bool)));
connect(button, SIGNAL(clicked(bool)), this, SIGNAL(Clicked()));
connect(button, SIGNAL(toggled(bool)), this, SLOT(SetChecked(bool)));
connect(button, SIGNAL(toggled(bool)), this, SIGNAL(Toggled(bool)));
return button;
}
+29
View File
@@ -0,0 +1,29 @@
#ifndef BUTTONFIELD_H
#define BUTTONFIELD_H
#include "../effectfield.h"
class ButtonField : public EffectField
{
Q_OBJECT
public:
ButtonField(EffectRow* parent, const QString& string);
void SetCheckable(bool c);
virtual QWidget* CreateWidget() override;
public slots:
void SetChecked(bool c);
signals:
void CheckedChanged(bool);
void Toggled(bool);
private:
bool checkable_;
bool checked_;
QString button_text_;
};
#endif // BUTTONFIELD_H
+39
View File
@@ -0,0 +1,39 @@
#include "colorfield.h"
#include <QColor>
#include "ui/colorbutton.h"
ColorField::ColorField(EffectRow* parent, const QString& id) :
EffectField(parent, id, EFFECT_FIELD_COLOR)
{}
QColor ColorField::GetColorAt(double timecode)
{
return GetValueAt(timecode).value<QColor>();
}
QWidget *ColorField::CreateWidget()
{
ColorButton* cb = new ColorButton();
connect(cb, SIGNAL(color_changed(const QColor &)), this, SLOT(UpdateFromWidget(const QColor &)));
connect(this, SIGNAL(EnabledChanged(bool)), cb, SLOT(setEnabled(bool)));
return cb;
}
QVariant ColorField::ConvertStringToValue(const QString &s)
{
return QColor(s);
}
QString ColorField::ConvertValueToString(const QVariant &v)
{
return v.value<QColor>().name();
}
void ColorField::UpdateFromWidget(const QColor& c)
{
SetValueAt(Now(), c);
}
+22
View File
@@ -0,0 +1,22 @@
#ifndef COLORFIELD_H
#define COLORFIELD_H
#include "../effectfield.h"
class ColorField : public EffectField
{
Q_OBJECT
public:
ColorField(EffectRow* parent, const QString& id);
QColor GetColorAt(double timecode);
virtual QWidget* CreateWidget() override;
virtual QVariant ConvertStringToValue(const QString& s) override;
virtual QString ConvertValueToString(const QVariant& v) override;
private slots:
void UpdateFromWidget(const QColor &c);
};
#endif // COLORFIELD_H
+38
View File
@@ -0,0 +1,38 @@
#include "combofield.h"
#include "ui/comboboxex.h"
ComboField::ComboField(EffectRow* parent, const QString& id) :
EffectField(parent, id, EFFECT_FIELD_COMBO)
{}
void ComboField::AddItem(const QString &text, const QVariant &data)
{
ComboFieldItem item;
item.name = text;
item.data = data;
items_.append(item);
}
QWidget *ComboField::CreateWidget()
{
ComboBoxEx* cb = new ComboBoxEx();
cb->setScrollingEnabled(false);
for (int i=0;i<items_.size();i++) {
cb->addItem(items_.at(i).name);
}
connect(cb, SIGNAL(activated(int)), this, SLOT(UpdateFromWidget(int)));
connect(this, SIGNAL(EnabledChanged(bool)), cb, SLOT(setEnabled(bool)));
return cb;
}
void ComboField::UpdateFromWidget(int index)
{
SetValueAt(Now(), items_.at(index).data);
}
+31
View File
@@ -0,0 +1,31 @@
#ifndef COMBOFIELD_H
#define COMBOFIELD_H
#include "../effectfield.h"
struct ComboFieldItem {
QString name;
QVariant data;
};
class ComboField : public EffectField
{
Q_OBJECT
public:
ComboField(EffectRow* parent, const QString& id);
void AddItem(const QString& text, const QVariant& data);
virtual QWidget *CreateWidget() override;
signals:
void IndexChanged(int i);
private:
QVector<ComboFieldItem> items_;
private slots:
void UpdateFromWidget(int index);
};
#endif // COMBOFIELD_H
+98
View File
@@ -0,0 +1,98 @@
#include "doublefield.h"
#include <QDebug>
DoubleField::DoubleField(EffectRow* parent, const QString& id) :
EffectField(parent, id, EFFECT_FIELD_DOUBLE),
min_(qSNaN()),
max_(qSNaN()),
default_(0),
display_type_(LabelSlider::Normal),
frame_rate_(30),
value_set_(false)
{
connect(this, SIGNAL(Changed()), this, SLOT(ValueHasBeenSet()), Qt::DirectConnection);
}
double DoubleField::GetDoubleAt(double timecode)
{
return GetValueAt(timecode).toDouble();
}
void DoubleField::SetMinimum(double minimum)
{
min_ = minimum;
}
void DoubleField::SetMaximum(double maximum)
{
max_ = maximum;
}
void DoubleField::SetDefault(double d)
{
default_ = d;
if (!value_set_) {
SetValueAt(0, d);
value_set_ = false;
}
}
void DoubleField::SetDisplayType(LabelSlider::DisplayType type)
{
display_type_ = type;
}
void DoubleField::SetFrameRate(const double &rate)
{
frame_rate_ = rate;
}
QVariant DoubleField::ConvertStringToValue(const QString &s)
{
return s.toDouble();
}
QString DoubleField::ConvertValueToString(const QVariant &v)
{
return QString::number(v.toDouble());
}
QWidget *DoubleField::CreateWidget()
{
LabelSlider* ls = new LabelSlider();
if (!qIsNaN(min_)) {
ls->SetMinimum(min_);
}
ls->SetDefault(default_);
if (!qIsNaN(max_)) {
ls->SetMaximum(max_);
}
ls->SetDisplayType(display_type_);
ls->SetFrameRate(frame_rate_);
ls->setEnabled(IsEnabled());
connect(ls, SIGNAL(valueChanged(double)), this, SLOT(UpdateFromWidget(double)));
connect(ls, SIGNAL(clicked()), this, SIGNAL(Clicked()));
connect(this, SIGNAL(EnabledChanged(bool)), ls, SLOT(setEnabled(bool)));
return ls;
}
void DoubleField::UpdateWidgetValue(QWidget *widget, double timecode)
{
static_cast<LabelSlider*>(widget)->SetValue(GetDoubleAt(timecode));
}
void DoubleField::ValueHasBeenSet()
{
value_set_ = true;
}
void DoubleField::UpdateFromWidget(double d)
{
SetValueAt(Now(), d);
}
+54
View File
@@ -0,0 +1,54 @@
#ifndef DOUBLEFIELD_H
#define DOUBLEFIELD_H
#include "../effectfield.h"
#include "ui/labelslider.h"
class DoubleField : public EffectField
{
Q_OBJECT
public:
DoubleField(EffectRow* parent, const QString& id);
/**
* @brief Get double value at timecode
*
* Convenience function. Equivalent to GetValueAt().toDouble()
*
* @param timecode
*
* Timecode to retrieve value at
*
* @return
*
* Double value at the set timecode
*/
double GetDoubleAt(double timecode);
void SetMinimum(double minimum);
void SetMaximum(double maximum);
void SetDefault(double maximum);
void SetDisplayType(LabelSlider::DisplayType type);
void SetFrameRate(const double& rate);
virtual QVariant ConvertStringToValue(const QString& s);
virtual QString ConvertValueToString(const QVariant& v);
virtual QWidget* CreateWidget() override;
virtual void UpdateWidgetValue(QWidget* widget, double timecode) override;
private:
double min_;
double max_;
double default_;
LabelSlider::DisplayType display_type_;
double frame_rate_;
bool value_set_;
private slots:
void ValueHasBeenSet();
void UpdateFromWidget(double d);
};
#endif // DOUBLEFIELD_H
+29
View File
@@ -0,0 +1,29 @@
#include "filefield.h"
#include "ui/embeddedfilechooser.h"
FileField::FileField(EffectRow* parent, const QString &id) :
EffectField(parent, id, EFFECT_FIELD_FILE)
{
}
QString FileField::GetFileAt(double timecode)
{
return GetValueAt(timecode).toString();
}
QWidget *FileField::CreateWidget()
{
EmbeddedFileChooser* efc = new EmbeddedFileChooser();
connect(efc, SIGNAL(changed(const QString&)), this, SLOT(UpdateFromWidget(const QString&)));
connect(this, SIGNAL(EnabledChanged(bool)), efc, SLOT(setEnabled(bool)));
return efc;
}
void FileField::UpdateFromWidget(const QString &s)
{
SetValueAt(Now(), s);
}
+19
View File
@@ -0,0 +1,19 @@
#ifndef FILEFIELD_H
#define FILEFIELD_H
#include "../effectfield.h"
class FileField : public EffectField
{
Q_OBJECT
public:
FileField(EffectRow* parent, const QString& id);
QString GetFileAt(double timecode);
virtual QWidget* CreateWidget() override;
private slots:
void UpdateFromWidget(const QString &s);
};
#endif // FILEFIELD_H
+37
View File
@@ -0,0 +1,37 @@
#include "fontfield.h"
#include <QFontDatabase>
#include "ui/comboboxex.h"
FontField::FontField(EffectRow* parent, const QString &id) :
EffectField(parent, id, EFFECT_FIELD_FONT)
{
font_list = QFontDatabase().families();
SetValueAt(0, font_list.first());
}
QString FontField::GetFontAt(double timecode)
{
return GetValueAt(timecode).toString();
}
QWidget *FontField::CreateWidget()
{
ComboBoxEx* fcb = new ComboBoxEx();
fcb->setScrollingEnabled(false);
fcb->addItems(font_list);
connect(fcb, SIGNAL(currentTextChanged(const QString &)), this, SLOT(UpdateFromWidget(const QString &)));
connect(this, SIGNAL(EnabledChanged(bool)), fcb, SLOT(setEnabled(bool)));
return fcb;
}
void FontField::UpdateFromWidget(const QString& s)
{
SetValueAt(Now(), s);
}
+20
View File
@@ -0,0 +1,20 @@
#ifndef FONTFIELD_H
#define FONTFIELD_H
#include "../effectfield.h"
class FontField : public EffectField {
Q_OBJECT
public:
FontField(EffectRow* parent, const QString& id);
QString GetFontAt(double timecode);
virtual QWidget *CreateWidget() override;
private:
QStringList font_list;
private slots:
void UpdateFromWidget(const QString& index);
};
#endif // FONTFIELD_H
+18
View File
@@ -0,0 +1,18 @@
#include "labelfield.h"
#include <QLabel>
LabelField::LabelField(EffectRow *parent, const QString &string) :
EffectField(parent, nullptr, EFFECT_FIELD_UI),
label_text_(string)
{}
QWidget *LabelField::CreateWidget()
{
QLabel* label = new QLabel(label_text_);
label->setEnabled(IsEnabled());
connect(this, SIGNAL(EnabledChanged(bool)), label, SLOT(setEnabled(bool)));
return label;
}
+17
View File
@@ -0,0 +1,17 @@
#ifndef LABELFIELD_H
#define LABELFIELD_H
#include "../effectfield.h"
class LabelField : public EffectField
{
Q_OBJECT
public:
LabelField(EffectRow* parent, const QString& string);
virtual QWidget* CreateWidget() override;
private:
QString label_text_;
};
#endif // LABELFIELD_H
+40
View File
@@ -0,0 +1,40 @@
#include "stringfield.h"
#include <QtMath>
#include "ui/texteditex.h"
#include "global/config.h"
StringField::StringField(EffectRow* parent, const QString& id) :
EffectField(parent, id, EFFECT_FIELD_STRING)
{
}
QString StringField::GetStringAt(double timecode)
{
return GetValueAt(timecode).toString();
}
QWidget *StringField::CreateWidget()
{
TextEditEx* text_edit = new TextEditEx();
text_edit->setEnabled(IsEnabled());
text_edit->setUndoRedoEnabled(true);
// the "2" looks like a magic number, but it's just one pixel on the top and the bottom
text_edit->setFixedHeight(qCeil(text_edit->fontMetrics().lineSpacing()*olive::CurrentConfig.effect_textbox_lines
+ text_edit->document()->documentMargin()
+ text_edit->document()->documentMargin() + 2));
connect(text_edit, SIGNAL(textModified(const QString&)), this, SLOT(UpdateFromWidget(const QString&)));
connect(this, SIGNAL(EnabledChanged(bool)), text_edit, SLOT(setEnabled(bool)));
return text_edit;
}
void StringField::UpdateFromWidget(const QString &s)
{
SetValueAt(Now(), s);
}
+19
View File
@@ -0,0 +1,19 @@
#ifndef STRINGFIELD_H
#define STRINGFIELD_H
#include "../effectfield.h"
class StringField : public EffectField
{
Q_OBJECT
public:
StringField(EffectRow* parent, const QString& id);
QString GetStringAt(double timecode);
virtual QWidget *CreateWidget() override;
private slots:
void UpdateFromWidget(const QString& b);
};
#endif // STRINGFIELD_H
+1 -1
View File
@@ -21,7 +21,7 @@
#ifndef AUDIONOISEEFFECT_H
#define AUDIONOISEEFFECT_H
#include "project/effect.h"
#include "effects/effect.h"
class AudioNoiseEffect : public Effect {
Q_OBJECT
+3 -3
View File
@@ -20,9 +20,9 @@
#include "cornerpineffect.h"
#include "io/path.h"
#include "project/clip.h"
#include "debug.h"
#include "global/path.h"
#include "timeline/clip.h"
#include "global/debug.h"
CornerPinEffect::CornerPinEffect(Clip* c, const EffectMeta *em) : Effect(c, em) {
SetFlags(Effect::CoordsFlag & Effect::ShaderFlag);
+1 -1
View File
@@ -21,7 +21,7 @@
#ifndef CORNERPINEFFECT_H
#define CORNERPINEFFECT_H
#include "project/effect.h"
#include "effects/effect.h"
class CornerPinEffect : public Effect {
Q_OBJECT
+1 -1
View File
@@ -21,7 +21,7 @@
#ifndef CROSSDISSOLVETRANSITION_H
#define CROSSDISSOLVETRANSITION_H
#include "project/transition.h"
#include "effects/transition.h"
class CrossDissolveTransition : public Transition {
public:
+1 -1
View File
@@ -21,7 +21,7 @@
#ifndef CUBETRANSITION_H
#define CUBETRANSITION_H
#include "project/transition.h"
#include "effects/transition.h"
class CubeTransition : public Transition {
public:
+2 -2
View File
@@ -21,12 +21,12 @@
#ifndef EXPONENTIALFADETRANSITION_H
#define EXPONENTIALFADETRANSITION_H
#include "project/transition.h"
#include "effects/transition.h"
class ExponentialFadeTransition : public Transition {
public:
ExponentialFadeTransition(Clip* c, Clip* s, const EffectMeta* em);
void process_audio(double timecode_start, double timecode_end, quint8* samples, int nb_bytes, int channel_count);
void process_audio(double timecode_start, double timecode_end, quint8* samples, int nb_bytes, int channel_count);
};
#endif // LINEARFADETRANSITION_H
+1 -1
View File
@@ -21,7 +21,7 @@
#ifndef FILLLEFTRIGHTEFFECT_H
#define FILLLEFTRIGHTEFFECT_H
#include "project/effect.h"
#include "effects/effect.h"
class FillLeftRightEffect : public Effect {
Q_OBJECT
+1 -1
View File
@@ -25,7 +25,7 @@
#include <QMessageBox>
#include <QDir>
#include "project/clip.h"
#include "timeline/clip.h"
typedef f0r_instance_t (*f0rConstructFunc)(unsigned int width, unsigned int height);
typedef int (*f0rInitFunc) ();
+14 -15
View File
@@ -23,32 +23,31 @@
#ifndef NOFREI0R
#include "project/effect.h"
#include <frei0r.h>
#include "io/crossplatformlib.h"
#include "effects/effect.h"
#include "global/crossplatformlib.h"
typedef void (*f0rGetParamInfo)(f0r_param_info_t * info,
int param_index );
int param_index );
class Frei0rEffect : public Effect {
Q_OBJECT
Q_OBJECT
public:
Frei0rEffect(Clip* c, const EffectMeta* em);
~Frei0rEffect();
~Frei0rEffect();
virtual void process_image(double timecode, uint8_t* input, uint8_t* output, int size);
virtual void process_image(double timecode, uint8_t* input, uint8_t* output, int size);
virtual void refresh();
virtual void refresh();
private:
ModulePtr handle;
f0r_instance_t instance;
int param_count;
f0rGetParamInfo get_param_info;
void destruct_module();
void construct_module();
bool open;
ModulePtr handle;
f0r_instance_t instance;
int param_count;
f0rGetParamInfo get_param_info;
void destruct_module();
void construct_module();
bool open;
};
#endif
+2 -2
View File
@@ -21,12 +21,12 @@
#ifndef LINEARFADETRANSITION_H
#define LINEARFADETRANSITION_H
#include "project/transition.h"
#include "effects/transition.h"
class LinearFadeTransition : public Transition {
public:
LinearFadeTransition(Clip* c, Clip* s, const EffectMeta* em);
void process_audio(double timecode_start, double timecode_end, quint8* samples, int nb_bytes, int channel_count);
void process_audio(double timecode_start, double timecode_end, quint8* samples, int nb_bytes, int channel_count);
};
#endif // LINEARFADETRANSITION_H
+2 -2
View File
@@ -21,12 +21,12 @@
#ifndef LOGARITHMICFADETRANSITION_H
#define LOGARITHMICFADETRANSITION_H
#include "project/transition.h"
#include "effects/transition.h"
class LogarithmicFadeTransition : public Transition {
public:
LogarithmicFadeTransition(Clip* c, Clip* s, const EffectMeta* em);
void process_audio(double timecode_start, double timecode_end, quint8* samples, int nb_bytes, int channel_count);
void process_audio(double timecode_start, double timecode_end, quint8* samples, int nb_bytes, int channel_count);
};
#endif // LOGARITHMICFADETRANSITION_H
+1 -1
View File
@@ -21,7 +21,7 @@
#ifndef PANEFFECT_H
#define PANEFFECT_H
#include "project/effect.h"
#include "effects/effect.h"
class PanEffect : public Effect {
Q_OBJECT
+3 -4
View File
@@ -27,11 +27,10 @@
#include "ui/labelslider.h"
#include "ui/collapsiblewidget.h"
#include "project/clip.h"
#include "project/sequence.h"
#include "timeline/clip.h"
#include "timeline/sequence.h"
#include "panels/timeline.h"
#include "debug.h"
#include "global/debug.h"
ShakeEffect::ShakeEffect(Clip* c, const EffectMeta *em) : Effect(c, em) {
SetFlags(Effect::CoordsFlag);
+1 -1
View File
@@ -21,7 +21,7 @@
#ifndef SHAKEEFFECT_H
#define SHAKEEFFECT_H
#include "project/effect.h"
#include "effects/effect.h"
#define RANDOM_VAL_SIZE 30
+2 -2
View File
@@ -27,8 +27,8 @@
#include <QImage>
#include <QComboBox>
#include "project/clip.h"
#include "project/sequence.h"
#include "timeline/clip.h"
#include "timeline/sequence.h"
const int SMPTE_BARS = 7;
const int SMPTE_STRIP_COUNT = 3;
+1 -1
View File
@@ -21,7 +21,7 @@
#ifndef SOLIDEFFECT_H
#define SOLIDEFFECT_H
#include "project/effect.h"
#include "effects/effect.h"
#include <QImage>
+3 -3
View File
@@ -35,12 +35,12 @@
#include "ui/labelslider.h"
#include "ui/collapsiblewidget.h"
#include "project/clip.h"
#include "project/sequence.h"
#include "timeline/clip.h"
#include "timeline/sequence.h"
#include "ui/comboboxex.h"
#include "ui/colorbutton.h"
#include "ui/fontcombobox.h"
#include "io/config.h"
#include "global/config.h"
TextEffect::TextEffect(Clip* c, const EffectMeta* em) :
Effect(c, em)
+1 -1
View File
@@ -21,7 +21,7 @@
#ifndef TEXTEFFECT_H
#define TEXTEFFECT_H
#include "project/effect.h"
#include "effects/effect.h"
#include <QFont>
#include <QImage>
+3 -3
View File
@@ -35,13 +35,13 @@
#include "ui/labelslider.h"
#include "ui/collapsiblewidget.h"
#include "project/clip.h"
#include "project/sequence.h"
#include "timeline/clip.h"
#include "timeline/sequence.h"
#include "panels/viewer.h"
#include "ui/comboboxex.h"
#include "ui/colorbutton.h"
#include "ui/fontcombobox.h"
#include "io/config.h"
#include "global/config.h"
TimecodeEffect::TimecodeEffect(Clip* c, const EffectMeta* em) :
Effect(c, em)
+1 -1
View File
@@ -21,7 +21,7 @@
#ifndef TIMECODEEFFECT_H
#define TIMECODEEFFECT_H
#include "project/effect.h"
#include "effects/effect.h"
#include <QFont>
#include <QImage>
+2 -3
View File
@@ -24,9 +24,8 @@
#define TONE_TYPE_SINE 0
#include "project/clip.h"
#include "project/sequence.h"
#include "debug.h"
#include "timeline/clip.h"
#include "timeline/sequence.h"
ToneEffect::ToneEffect(Clip* c, const EffectMeta *em) : Effect(c, em), sinX(INT_MIN) {
EffectRow* type_row = new EffectRow(this, tr("Type"));
+1 -1
View File
@@ -21,7 +21,7 @@
#ifndef TONEEFFECT_H
#define TONEEFFECT_H
#include "project/effect.h"
#include "effects/effect.h"
class ToneEffect : public Effect {
Q_OBJECT
+4 -4
View File
@@ -30,14 +30,14 @@
#include <QMouseEvent>
#include "ui/collapsiblewidget.h"
#include "project/clip.h"
#include "project/sequence.h"
#include "timeline/clip.h"
#include "timeline/sequence.h"
#include "project/footage.h"
#include "io/math.h"
#include "global/math.h"
#include "ui/labelslider.h"
#include "ui/comboboxex.h"
#include "panels/project.h"
#include "debug.h"
#include "global/debug.h"
#include "panels/panels.h"
#include "panels/viewer.h"
+1 -1
View File
@@ -21,7 +21,7 @@
#ifndef TRANSFORMEFFECT_H
#define TRANSFORMEFFECT_H
#include "project/effect.h"
#include "effects/effect.h"
class TransformEffect : public Effect {
Q_OBJECT
+1 -1
View File
@@ -25,7 +25,7 @@
#include <QFile>
#include "ui/collapsiblewidget.h"
#include "debug.h"
#include "global/debug.h"
VoidEffect::VoidEffect(Clip* c, const QString& n) : Effect(c, nullptr) {
QString display_name;
+1 -1
View File
@@ -27,7 +27,7 @@
* isn't lost if the user saves over the project.
*/
#include "project/effect.h"
#include "effects/effect.h"
class VoidEffect : public Effect {
Q_OBJECT
+1 -1
View File
@@ -34,7 +34,7 @@ VolumeEffect::VolumeEffect(Clip* c, const EffectMeta *em) : Effect(c, em) {
// set defaults
volume_val->SetDefault(1);
volume_val->SetDisplayType(LabelSlider::LABELSLIDER_DECIBEL);
volume_val->SetDisplayType(LabelSlider::Decibel);
}
void VolumeEffect::process_audio(double timecode_start, double timecode_end, quint8* samples, int nb_bytes, int) {
+1 -1
View File
@@ -21,7 +21,7 @@
#ifndef VOLUMEEFFECT_H
#define VOLUMEEFFECT_H
#include "project/effect.h"
#include "effects/effect.h"
class VolumeEffect : public Effect {
Q_OBJECT
+2 -2
View File
@@ -32,8 +32,8 @@
#include <QWindow>
#include "rendering/audio.h"
#include "mainwindow.h"
#include "debug.h"
#include "ui/mainwindow.h"
#include "global/debug.h"
#ifdef __linux__
#include <X11/X.h>
+2 -2
View File
@@ -23,9 +23,9 @@
#ifndef NOVST
#include "project/effect.h"
#include "effects/effect.h"
#include "io/crossplatformlib.h"
#include "global/crossplatformlib.h"
#include "include/vestige.h"
+67
View File
@@ -0,0 +1,67 @@
/***
Olive - Non-Linear Video Editor
Copyright (C) 2019 Olive Team
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
***/
#include "keyframe.h"
#include <QVector>
#include "effectfields.h"
#include "undo/undo.h"
#include "panels/panels.h"
EffectKeyframe::EffectKeyframe()
{
pre_handle_x = -40;
pre_handle_y = 0;
post_handle_x = 40;
post_handle_y = 0;
}
void delete_keyframes(QVector<EffectField *>& selected_key_fields, QVector<int> &selected_keys) {
QVector<EffectField*> fields;
QVector<int> key_indices;
for (int i=0;i<selected_keys.size();i++) {
bool added = false;
for (int j=0;j<key_indices.size();j++) {
if (key_indices.at(j) < selected_keys.at(i)) {
key_indices.insert(j, selected_keys.at(i));
fields.insert(j, selected_key_fields.at(i));
added = true;
break;
}
}
if (!added) {
key_indices.append(selected_keys.at(i));
fields.append(selected_key_fields.at(i));
}
}
if (fields.size() > 0) {
ComboAction* ca = new ComboAction();
for (int i=0;i<key_indices.size();i++) {
ca->append(new KeyframeDelete(fields.at(i), key_indices.at(i)));
}
olive::UndoStack.push(ca);
selected_keys.clear();
selected_key_fields.clear();
update_ui(false);
}
}
+45
View File
@@ -0,0 +1,45 @@
/***
Olive - Non-Linear Video Editor
Copyright (C) 2019 Olive Team
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
***/
#ifndef KEYFRAME_H
#define KEYFRAME_H
#include <QVariant>
class EffectField;
class EffectKeyframe {
public:
EffectKeyframe();
int type;
long time;
QVariant data;
// only for bezier type
double pre_handle_x;
double pre_handle_y;
double post_handle_x;
double post_handle_y;
};
void delete_keyframes(QVector<EffectField *> &selected_key_fields, QVector<int> &selected_keys);
#endif // KEYFRAME_H

Some files were not shown because too many files have changed in this diff Show More