refactored some classes
This commit is contained in:
@@ -33,7 +33,7 @@
|
||||
#include "panels/timeline.h"
|
||||
#include "undo/undo.h"
|
||||
#include "undo/undostack.h"
|
||||
#include "nodes/node.h"
|
||||
#include "nodes/oldeffectnode.h"
|
||||
#include "project/media.h"
|
||||
|
||||
SpeedDialog::SpeedDialog(QWidget *parent, QVector<Clip*> clips) : QDialog(parent) {
|
||||
|
||||
@@ -26,15 +26,15 @@
|
||||
#include "rendering/renderfunctions.h"
|
||||
#include "global/config.h"
|
||||
#include "global/timing.h"
|
||||
#include "effects/effectrow.h"
|
||||
#include "nodes/node.h"
|
||||
#include "nodes/nodeio.h"
|
||||
#include "nodes/oldeffectnode.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, EffectFieldType t) :
|
||||
EffectField::EffectField(NodeIO* parent, EffectFieldType t) :
|
||||
QObject(parent),
|
||||
type_(t),
|
||||
enabled_(true)
|
||||
@@ -49,9 +49,9 @@ EffectField::EffectField(EffectRow* parent, EffectFieldType t) :
|
||||
connect(this, SIGNAL(Changed()), parent->GetParentEffect(), SLOT(FieldChanged()));
|
||||
}
|
||||
|
||||
EffectRow *EffectField::GetParentRow()
|
||||
NodeIO *EffectField::GetParentRow()
|
||||
{
|
||||
return static_cast<EffectRow*>(parent());
|
||||
return static_cast<NodeIO*>(parent());
|
||||
}
|
||||
|
||||
QVariant EffectField::ConvertStringToValue(const QString &s)
|
||||
|
||||
@@ -29,7 +29,7 @@
|
||||
#include "undo/undostack.h"
|
||||
#include "nodes/nodedatatypes.h"
|
||||
|
||||
class EffectRow;
|
||||
class NodeIO;
|
||||
class ComboAction;
|
||||
|
||||
/**
|
||||
@@ -106,7 +106,7 @@ public:
|
||||
*
|
||||
* The type of data contained within this field. This is expected to be filled by a derived class.
|
||||
*/
|
||||
EffectField(EffectRow* parent, EffectFieldType t);
|
||||
EffectField(NodeIO* parent, EffectFieldType t);
|
||||
|
||||
/**
|
||||
* @brief Get the EffectRow that this field is a member of.
|
||||
@@ -117,7 +117,7 @@ public:
|
||||
*
|
||||
* The EffectRow that this field is a member of.
|
||||
*/
|
||||
EffectRow* GetParentRow();
|
||||
NodeIO* GetParentRow();
|
||||
|
||||
/**
|
||||
* @brief Get the type of data to expect from this field
|
||||
|
||||
@@ -22,9 +22,9 @@
|
||||
|
||||
#include "ui/labelslider.h"
|
||||
#include "effects/fields/doublefield.h"
|
||||
#include "nodes/node.h"
|
||||
#include "nodes/oldeffectnode.h"
|
||||
|
||||
EffectGizmo::EffectGizmo(Node *parent, int type) :
|
||||
EffectGizmo::EffectGizmo(OldEffectNode *parent, int type) :
|
||||
QObject(parent),
|
||||
x_field1(nullptr),
|
||||
x_field_multi1(1.0),
|
||||
|
||||
@@ -39,12 +39,12 @@ enum GizmoType {
|
||||
#include <QColor>
|
||||
|
||||
class DoubleField;
|
||||
class Node;
|
||||
class OldEffectNode;
|
||||
|
||||
class EffectGizmo : public QObject {
|
||||
Q_OBJECT
|
||||
public:
|
||||
EffectGizmo(Node* parent, int type);
|
||||
EffectGizmo(OldEffectNode* parent, int type);
|
||||
|
||||
QVector<QVector3D> world_pos;
|
||||
QVector<QPoint> screen_pos;
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
#include <QXmlStreamReader>
|
||||
#include <QDebug>
|
||||
|
||||
#include "nodes/node.h"
|
||||
#include "nodes/oldeffectnode.h"
|
||||
#include "effects/transition.h"
|
||||
#include "global/path.h"
|
||||
#include "panels/panels.h"
|
||||
|
||||
@@ -22,10 +22,10 @@
|
||||
|
||||
#include <QCheckBox>
|
||||
|
||||
#include "nodes/node.h"
|
||||
#include "nodes/oldeffectnode.h"
|
||||
#include "undo/undo.h"
|
||||
|
||||
BoolField::BoolField(EffectRow *parent) :
|
||||
BoolField::BoolField(NodeIO *parent) :
|
||||
EffectField(parent, EffectField::EFFECT_FIELD_BOOL)
|
||||
{}
|
||||
|
||||
|
||||
@@ -35,7 +35,7 @@ public:
|
||||
/**
|
||||
* @brief Reimplementation of EffectField::EffectField().
|
||||
*/
|
||||
BoolField(EffectRow* parent);
|
||||
BoolField(NodeIO* parent);
|
||||
|
||||
/**
|
||||
* @brief Get the boolean value at a given timecode
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
|
||||
#include <QPushButton>
|
||||
|
||||
ButtonField::ButtonField(EffectRow *parent, const QString &string) :
|
||||
ButtonField::ButtonField(NodeIO *parent, const QString &string) :
|
||||
EffectField(parent, EffectField::EFFECT_FIELD_UI),
|
||||
button_text_(string)
|
||||
{}
|
||||
|
||||
@@ -42,7 +42,7 @@ public:
|
||||
/**
|
||||
* @brief Reimplementation of EffectField::EffectField().
|
||||
*/
|
||||
ButtonField(EffectRow* parent, const QString& string);
|
||||
ButtonField(NodeIO* parent, const QString& string);
|
||||
|
||||
/**
|
||||
* @brief Set whether this pushbutton is checkable
|
||||
|
||||
@@ -23,10 +23,10 @@
|
||||
#include <QColor>
|
||||
|
||||
#include "ui/colorbutton.h"
|
||||
#include "nodes/node.h"
|
||||
#include "nodes/oldeffectnode.h"
|
||||
#include "undo/undo.h"
|
||||
|
||||
ColorField::ColorField(EffectRow* parent) :
|
||||
ColorField::ColorField(NodeIO* parent) :
|
||||
EffectField(parent, EffectField::EFFECT_FIELD_COLOR)
|
||||
{}
|
||||
|
||||
|
||||
@@ -35,7 +35,7 @@ public:
|
||||
/**
|
||||
* @brief Reimplementation of EffectField::EffectField().
|
||||
*/
|
||||
ColorField(EffectRow* parent);
|
||||
ColorField(NodeIO* parent);
|
||||
|
||||
/**
|
||||
* @brief Get the color value at a given timecode
|
||||
|
||||
@@ -22,11 +22,11 @@
|
||||
|
||||
#include <QDebug>
|
||||
|
||||
#include "nodes/node.h"
|
||||
#include "nodes/oldeffectnode.h"
|
||||
#include "ui/comboboxex.h"
|
||||
#include "undo/undo.h"
|
||||
|
||||
ComboField::ComboField(EffectRow* parent) :
|
||||
ComboField::ComboField(NodeIO* parent) :
|
||||
EffectField(parent, EffectField::EFFECT_FIELD_COMBO)
|
||||
{}
|
||||
|
||||
|
||||
@@ -48,7 +48,7 @@ public:
|
||||
/**
|
||||
* @brief Reimplementation of EffectField::EffectField().
|
||||
*/
|
||||
ComboField(EffectRow* parent);
|
||||
ComboField(NodeIO* parent);
|
||||
|
||||
/**
|
||||
* @brief Add an item to this ComboField
|
||||
|
||||
@@ -20,10 +20,10 @@
|
||||
|
||||
#include "doublefield.h"
|
||||
|
||||
#include "nodes/node.h"
|
||||
#include "nodes/oldeffectnode.h"
|
||||
#include "undo/undo.h"
|
||||
|
||||
DoubleField::DoubleField(EffectRow* parent) :
|
||||
DoubleField::DoubleField(NodeIO* parent) :
|
||||
EffectField(parent, EffectField::EFFECT_FIELD_DOUBLE),
|
||||
min_(qSNaN()),
|
||||
max_(qSNaN()),
|
||||
|
||||
@@ -39,7 +39,7 @@ public:
|
||||
/**
|
||||
* @brief Reimplementation of EffectField::EffectField().
|
||||
*/
|
||||
DoubleField(EffectRow* parent);
|
||||
DoubleField(NodeIO* parent);
|
||||
|
||||
/**
|
||||
* @brief Get double value at timecode
|
||||
|
||||
@@ -23,10 +23,10 @@
|
||||
#include <QDebug>
|
||||
|
||||
#include "ui/embeddedfilechooser.h"
|
||||
#include "nodes/node.h"
|
||||
#include "nodes/oldeffectnode.h"
|
||||
#include "undo/undo.h"
|
||||
|
||||
FileField::FileField(EffectRow* parent) :
|
||||
FileField::FileField(NodeIO* parent) :
|
||||
EffectField(parent, EffectField::EFFECT_FIELD_FILE)
|
||||
{
|
||||
// Set default value to an empty string
|
||||
|
||||
@@ -36,7 +36,7 @@ public:
|
||||
/**
|
||||
* @brief Reimplementation of EffectField::EffectField().
|
||||
*/
|
||||
FileField(EffectRow* parent);
|
||||
FileField(NodeIO* parent);
|
||||
|
||||
/**
|
||||
* @brief Get the filename at the given timecode
|
||||
|
||||
@@ -24,12 +24,12 @@
|
||||
#include <QDebug>
|
||||
|
||||
#include "ui/comboboxex.h"
|
||||
#include "nodes/node.h"
|
||||
#include "nodes/oldeffectnode.h"
|
||||
#include "undo/undo.h"
|
||||
|
||||
// NOTE/TODO: This shares a lot of similarity with ComboInput, and could probably be a derived class of it
|
||||
|
||||
FontField::FontField(EffectRow* parent) :
|
||||
FontField::FontField(NodeIO* parent) :
|
||||
EffectField(parent, EffectField::EFFECT_FIELD_FONT)
|
||||
{
|
||||
font_list = QFontDatabase().families();
|
||||
|
||||
@@ -37,7 +37,7 @@ public:
|
||||
/**
|
||||
* @brief Reimplementation of EffectField::EffectField().
|
||||
*/
|
||||
FontField(EffectRow* parent);
|
||||
FontField(NodeIO* parent);
|
||||
|
||||
/**
|
||||
* @brief Get the font family name at the given timecode
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
|
||||
#include <QLabel>
|
||||
|
||||
LabelField::LabelField(EffectRow *parent, const QString &string) :
|
||||
LabelField::LabelField(NodeIO *parent, const QString &string) :
|
||||
EffectField(parent, EffectField::EFFECT_FIELD_UI),
|
||||
label_text_(string)
|
||||
{}
|
||||
|
||||
@@ -37,7 +37,7 @@ public:
|
||||
/**
|
||||
* @brief Reimplementation of EffectField::EffectField().
|
||||
*/
|
||||
LabelField(EffectRow* parent, const QString& string);
|
||||
LabelField(NodeIO* parent, const QString& string);
|
||||
|
||||
/**
|
||||
* @brief Reimplementation of EffectField::CreateWidget()
|
||||
|
||||
@@ -23,12 +23,12 @@
|
||||
#include <QtMath>
|
||||
#include <QDebug>
|
||||
|
||||
#include "nodes/node.h"
|
||||
#include "nodes/oldeffectnode.h"
|
||||
#include "ui/texteditex.h"
|
||||
#include "global/config.h"
|
||||
#include "undo/undo.h"
|
||||
|
||||
StringField::StringField(EffectRow* parent, bool rich_text) :
|
||||
StringField::StringField(NodeIO* parent, bool rich_text) :
|
||||
EffectField(parent, EffectField::EFFECT_FIELD_STRING),
|
||||
rich_text_(rich_text)
|
||||
{
|
||||
|
||||
@@ -39,7 +39,7 @@ public:
|
||||
* Provides a setting for whether this StringField - and its attached TextEditEx objects - should operate in rich
|
||||
* text or plain text mode, defaulting to rich text mode.
|
||||
*/
|
||||
StringField(EffectRow* parent, bool rich_text = true);
|
||||
StringField(NodeIO* parent, bool rich_text = true);
|
||||
|
||||
/**
|
||||
* @brief Get the string at the given timecode
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
#include <QDateTime>
|
||||
#include <QtMath>
|
||||
|
||||
AudioNoiseEffect::AudioNoiseEffect(Clip* c) : Node(c) {
|
||||
AudioNoiseEffect::AudioNoiseEffect(Clip* c) : OldEffectNode(c) {
|
||||
amount_val = new DoubleInput(this, "amount", tr("Amount"));
|
||||
amount_val->SetMinimum(0);
|
||||
amount_val->SetDefault(20);
|
||||
@@ -58,7 +58,7 @@ olive::TrackType AudioNoiseEffect::subtype()
|
||||
return olive::kTypeAudio;
|
||||
}
|
||||
|
||||
NodePtr AudioNoiseEffect::Create(Clip *c)
|
||||
OldEffectNodePtr AudioNoiseEffect::Create(Clip *c)
|
||||
{
|
||||
return std::make_shared<AudioNoiseEffect>(c);
|
||||
}
|
||||
|
||||
@@ -21,9 +21,9 @@
|
||||
#ifndef AUDIONOISEEFFECT_H
|
||||
#define AUDIONOISEEFFECT_H
|
||||
|
||||
#include "nodes/node.h"
|
||||
#include "nodes/oldeffectnode.h"
|
||||
|
||||
class AudioNoiseEffect : public Node {
|
||||
class AudioNoiseEffect : public OldEffectNode {
|
||||
Q_OBJECT
|
||||
public:
|
||||
AudioNoiseEffect(Clip* c);
|
||||
@@ -33,7 +33,7 @@ public:
|
||||
virtual QString description() override;
|
||||
virtual EffectType type() override;
|
||||
virtual olive::TrackType subtype() override;
|
||||
virtual NodePtr Create(Clip *c) override;
|
||||
virtual OldEffectNodePtr Create(Clip *c) override;
|
||||
|
||||
virtual void process_audio(double timecode_start,
|
||||
double timecode_end,
|
||||
|
||||
@@ -24,8 +24,8 @@
|
||||
#include "timeline/clip.h"
|
||||
#include "global/debug.h"
|
||||
|
||||
CornerPinEffect::CornerPinEffect(Clip* c) : Node(c) {
|
||||
SetFlags(Node::CoordsFlag | Node::ShaderFlag);
|
||||
CornerPinEffect::CornerPinEffect(Clip* c) : OldEffectNode(c) {
|
||||
SetFlags(OldEffectNode::CoordsFlag | OldEffectNode::ShaderFlag);
|
||||
|
||||
top_left = new Vec2Input(this, "topleft", tr("Top Left"));
|
||||
|
||||
@@ -88,7 +88,7 @@ olive::TrackType CornerPinEffect::subtype()
|
||||
return olive::kTypeVideo;
|
||||
}
|
||||
|
||||
NodePtr CornerPinEffect::Create(Clip *c)
|
||||
OldEffectNodePtr CornerPinEffect::Create(Clip *c)
|
||||
{
|
||||
return std::make_shared<CornerPinEffect>(c);
|
||||
}
|
||||
|
||||
@@ -21,9 +21,9 @@
|
||||
#ifndef CORNERPINEFFECT_H
|
||||
#define CORNERPINEFFECT_H
|
||||
|
||||
#include "nodes/node.h"
|
||||
#include "nodes/oldeffectnode.h"
|
||||
|
||||
class CornerPinEffect : public Node {
|
||||
class CornerPinEffect : public OldEffectNode {
|
||||
Q_OBJECT
|
||||
public:
|
||||
CornerPinEffect(Clip* c);
|
||||
@@ -34,7 +34,7 @@ public:
|
||||
virtual QString description() override;
|
||||
virtual EffectType type() override;
|
||||
virtual olive::TrackType subtype() override;
|
||||
virtual NodePtr Create(Clip *c) override;
|
||||
virtual OldEffectNodePtr Create(Clip *c) override;
|
||||
|
||||
void process_coords(double timecode, GLTextureCoords& coords, int data);
|
||||
void process_shader(double timecode, GLTextureCoords& coords, int iterations);
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
#include <QOpenGLFunctions>
|
||||
|
||||
CrossDissolveTransition::CrossDissolveTransition(Clip* c) : Transition(c) {
|
||||
SetFlags(Node::CoordsFlag);
|
||||
SetFlags(OldEffectNode::CoordsFlag);
|
||||
}
|
||||
|
||||
QString CrossDissolveTransition::name()
|
||||
@@ -56,7 +56,7 @@ olive::TrackType CrossDissolveTransition::subtype()
|
||||
return olive::kTypeVideo;
|
||||
}
|
||||
|
||||
NodePtr CrossDissolveTransition::Create(Clip *c)
|
||||
OldEffectNodePtr CrossDissolveTransition::Create(Clip *c)
|
||||
{
|
||||
return std::make_shared<CrossDissolveTransition>(c);
|
||||
}
|
||||
|
||||
@@ -33,7 +33,7 @@ public:
|
||||
virtual QString description() override;
|
||||
virtual EffectType type() override;
|
||||
virtual olive::TrackType subtype() override;
|
||||
virtual NodePtr Create(Clip *c) override;
|
||||
virtual OldEffectNodePtr Create(Clip *c) override;
|
||||
|
||||
virtual void process_coords(double timecode, GLTextureCoords &, int data) override;
|
||||
};
|
||||
|
||||
@@ -52,7 +52,7 @@ olive::TrackType ExponentialFadeTransition::subtype()
|
||||
return olive::kTypeAudio;
|
||||
}
|
||||
|
||||
NodePtr ExponentialFadeTransition::Create(Clip *c)
|
||||
OldEffectNodePtr ExponentialFadeTransition::Create(Clip *c)
|
||||
{
|
||||
return std::make_shared<ExponentialFadeTransition>(c);
|
||||
}
|
||||
|
||||
@@ -32,7 +32,7 @@ public:
|
||||
virtual QString description() override;
|
||||
virtual EffectType type() override;
|
||||
virtual olive::TrackType subtype() override;
|
||||
virtual NodePtr Create(Clip *c) override;
|
||||
virtual OldEffectNodePtr Create(Clip *c) override;
|
||||
|
||||
virtual void process_audio(double timecode_start,
|
||||
double timecode_end,
|
||||
|
||||
@@ -25,7 +25,7 @@ enum FillType {
|
||||
FILL_TYPE_RIGHT
|
||||
};
|
||||
|
||||
FillLeftRightEffect::FillLeftRightEffect(Clip* c) : Node(c) {
|
||||
FillLeftRightEffect::FillLeftRightEffect(Clip* c) : OldEffectNode(c) {
|
||||
fill_type = new ComboInput(this, "type", tr("Type"));
|
||||
fill_type->AddItem(tr("Fill Left with Right"), FILL_TYPE_LEFT);
|
||||
fill_type->AddItem(tr("Fill Right with Left"), FILL_TYPE_RIGHT);
|
||||
@@ -56,7 +56,7 @@ olive::TrackType FillLeftRightEffect::subtype()
|
||||
return olive::kTypeAudio;
|
||||
}
|
||||
|
||||
NodePtr FillLeftRightEffect::Create(Clip *c)
|
||||
OldEffectNodePtr FillLeftRightEffect::Create(Clip *c)
|
||||
{
|
||||
return std::make_shared<FillLeftRightEffect>(c);
|
||||
}
|
||||
|
||||
@@ -21,9 +21,9 @@
|
||||
#ifndef FILLLEFTRIGHTEFFECT_H
|
||||
#define FILLLEFTRIGHTEFFECT_H
|
||||
|
||||
#include "nodes/node.h"
|
||||
#include "nodes/oldeffectnode.h"
|
||||
|
||||
class FillLeftRightEffect : public Node {
|
||||
class FillLeftRightEffect : public OldEffectNode {
|
||||
Q_OBJECT
|
||||
public:
|
||||
FillLeftRightEffect(Clip* c);
|
||||
@@ -33,7 +33,7 @@ public:
|
||||
virtual QString description() override;
|
||||
virtual EffectType type() override;
|
||||
virtual olive::TrackType subtype() override;
|
||||
virtual NodePtr Create(Clip *c) override;
|
||||
virtual OldEffectNodePtr Create(Clip *c) override;
|
||||
|
||||
virtual void process_audio(double timecode_start,
|
||||
double timecode_end,
|
||||
|
||||
@@ -47,7 +47,7 @@ olive::TrackType LinearFadeTransition::subtype()
|
||||
return olive::kTypeAudio;
|
||||
}
|
||||
|
||||
NodePtr LinearFadeTransition::Create(Clip *c)
|
||||
OldEffectNodePtr LinearFadeTransition::Create(Clip *c)
|
||||
{
|
||||
return std::make_shared<LinearFadeTransition>(c);
|
||||
}
|
||||
|
||||
@@ -32,7 +32,7 @@ public:
|
||||
virtual QString description() override;
|
||||
virtual EffectType type() override;
|
||||
virtual olive::TrackType subtype() override;
|
||||
virtual NodePtr Create(Clip *c) override;
|
||||
virtual OldEffectNodePtr Create(Clip *c) override;
|
||||
|
||||
virtual void process_audio(double timecode_start,
|
||||
double timecode_end,
|
||||
|
||||
@@ -52,7 +52,7 @@ olive::TrackType LogarithmicFadeTransition::subtype()
|
||||
return olive::kTypeAudio;
|
||||
}
|
||||
|
||||
NodePtr LogarithmicFadeTransition::Create(Clip *c)
|
||||
OldEffectNodePtr LogarithmicFadeTransition::Create(Clip *c)
|
||||
{
|
||||
return std::make_shared<LogarithmicFadeTransition>(c);
|
||||
}
|
||||
|
||||
@@ -32,7 +32,7 @@ public:
|
||||
virtual QString description() override;
|
||||
virtual EffectType type() override;
|
||||
virtual olive::TrackType subtype() override;
|
||||
virtual NodePtr Create(Clip* c) override;
|
||||
virtual OldEffectNodePtr Create(Clip* c) override;
|
||||
|
||||
virtual void process_audio(double timecode_start,
|
||||
double timecode_end,
|
||||
|
||||
@@ -28,7 +28,7 @@
|
||||
#include "ui/labelslider.h"
|
||||
#include "ui/collapsiblewidget.h"
|
||||
|
||||
PanEffect::PanEffect(Clip* c) : Node(c) {
|
||||
PanEffect::PanEffect(Clip* c) : OldEffectNode(c) {
|
||||
pan_val = new DoubleInput(this, "pan", tr("Pan"));
|
||||
pan_val->SetMinimum(-100);
|
||||
pan_val->SetDefault(0);
|
||||
@@ -60,7 +60,7 @@ olive::TrackType PanEffect::subtype()
|
||||
return olive::kTypeAudio;
|
||||
}
|
||||
|
||||
NodePtr PanEffect::Create(Clip *c)
|
||||
OldEffectNodePtr PanEffect::Create(Clip *c)
|
||||
{
|
||||
return std::make_shared<PanEffect>(c);
|
||||
}
|
||||
|
||||
@@ -21,9 +21,9 @@
|
||||
#ifndef PANEFFECT_H
|
||||
#define PANEFFECT_H
|
||||
|
||||
#include "nodes/node.h"
|
||||
#include "nodes/oldeffectnode.h"
|
||||
|
||||
class PanEffect : public Node {
|
||||
class PanEffect : public OldEffectNode {
|
||||
Q_OBJECT
|
||||
public:
|
||||
PanEffect(Clip* c);
|
||||
@@ -33,7 +33,7 @@ public:
|
||||
virtual QString description() override;
|
||||
virtual EffectType type() override;
|
||||
virtual olive::TrackType subtype() override;
|
||||
virtual NodePtr Create(Clip *c) override;
|
||||
virtual OldEffectNodePtr Create(Clip *c) override;
|
||||
|
||||
virtual void process_audio(double timecode_start,
|
||||
double timecode_end,
|
||||
|
||||
@@ -35,9 +35,9 @@ enum AutoscrollDirection {
|
||||
};
|
||||
|
||||
RichTextEffect::RichTextEffect(Clip *c) :
|
||||
Node(c)
|
||||
OldEffectNode(c)
|
||||
{
|
||||
SetFlags(Node::SuperimposeFlag);
|
||||
SetFlags(OldEffectNode::SuperimposeFlag);
|
||||
|
||||
text_val = new StringInput(this, "text", tr("Text"));
|
||||
|
||||
@@ -112,7 +112,7 @@ olive::TrackType RichTextEffect::subtype()
|
||||
return olive::kTypeVideo;
|
||||
}
|
||||
|
||||
NodePtr RichTextEffect::Create(Clip *c)
|
||||
OldEffectNodePtr RichTextEffect::Create(Clip *c)
|
||||
{
|
||||
return std::make_shared<RichTextEffect>(c);
|
||||
}
|
||||
|
||||
@@ -21,9 +21,9 @@
|
||||
#ifndef RICHTEXTEFFECT_H
|
||||
#define RICHTEXTEFFECT_H
|
||||
|
||||
#include "nodes/node.h"
|
||||
#include "nodes/oldeffectnode.h"
|
||||
|
||||
class RichTextEffect : public Node {
|
||||
class RichTextEffect : public OldEffectNode {
|
||||
Q_OBJECT
|
||||
public:
|
||||
RichTextEffect(Clip* c);
|
||||
@@ -34,7 +34,7 @@ public:
|
||||
virtual QString description() override;
|
||||
virtual EffectType type() override;
|
||||
virtual olive::TrackType subtype() override;
|
||||
virtual NodePtr Create(Clip *c) override;
|
||||
virtual OldEffectNodePtr Create(Clip *c) override;
|
||||
|
||||
virtual void redraw(double timecode) override;
|
||||
|
||||
|
||||
@@ -32,8 +32,8 @@
|
||||
#include "panels/timeline.h"
|
||||
#include "global/debug.h"
|
||||
|
||||
ShakeEffect::ShakeEffect(Clip* c) : Node(c) {
|
||||
SetFlags(Node::CoordsFlag);
|
||||
ShakeEffect::ShakeEffect(Clip* c) : OldEffectNode(c) {
|
||||
SetFlags(OldEffectNode::CoordsFlag);
|
||||
|
||||
intensity_val = new DoubleInput(this, "intensity", tr("Intensity"));
|
||||
intensity_val->SetMinimum(0);
|
||||
@@ -110,7 +110,7 @@ olive::TrackType ShakeEffect::subtype()
|
||||
return olive::kTypeVideo;
|
||||
}
|
||||
|
||||
NodePtr ShakeEffect::Create(Clip *c)
|
||||
OldEffectNodePtr ShakeEffect::Create(Clip *c)
|
||||
{
|
||||
return std::make_shared<ShakeEffect>(c);
|
||||
}
|
||||
|
||||
@@ -21,11 +21,11 @@
|
||||
#ifndef SHAKEEFFECT_H
|
||||
#define SHAKEEFFECT_H
|
||||
|
||||
#include "nodes/node.h"
|
||||
#include "nodes/oldeffectnode.h"
|
||||
|
||||
#define RANDOM_VAL_SIZE 30
|
||||
|
||||
class ShakeEffect : public Node {
|
||||
class ShakeEffect : public OldEffectNode {
|
||||
Q_OBJECT
|
||||
public:
|
||||
ShakeEffect(Clip* c);
|
||||
@@ -37,7 +37,7 @@ public:
|
||||
virtual QString description() override;
|
||||
virtual EffectType type() override;
|
||||
virtual olive::TrackType subtype() override;
|
||||
virtual NodePtr Create(Clip *c) override;
|
||||
virtual OldEffectNodePtr Create(Clip *c) override;
|
||||
|
||||
DoubleInput* intensity_val;
|
||||
DoubleInput* rotation_val;
|
||||
|
||||
@@ -35,9 +35,9 @@ const int SMPTE_STRIP_COUNT = 3;
|
||||
const int SMPTE_LOWER_BARS = 4;
|
||||
|
||||
SolidEffect::SolidEffect(Clip* c) :
|
||||
Node(c)
|
||||
OldEffectNode(c)
|
||||
{
|
||||
SetFlags(Node::SuperimposeFlag);
|
||||
SetFlags(OldEffectNode::SuperimposeFlag);
|
||||
|
||||
// Field for solid type
|
||||
solid_type = new ComboInput(this, "type", tr("Type"));
|
||||
@@ -99,7 +99,7 @@ olive::TrackType SolidEffect::subtype()
|
||||
return olive::kTypeVideo;
|
||||
}
|
||||
|
||||
NodePtr SolidEffect::Create(Clip *c)
|
||||
OldEffectNodePtr SolidEffect::Create(Clip *c)
|
||||
{
|
||||
return std::make_shared<SolidEffect>(c);
|
||||
}
|
||||
|
||||
@@ -21,11 +21,11 @@
|
||||
#ifndef SOLIDEFFECT_H
|
||||
#define SOLIDEFFECT_H
|
||||
|
||||
#include "nodes/node.h"
|
||||
#include "nodes/oldeffectnode.h"
|
||||
|
||||
#include <QImage>
|
||||
|
||||
class SolidEffect : public Node {
|
||||
class SolidEffect : public OldEffectNode {
|
||||
Q_OBJECT
|
||||
public:
|
||||
enum SolidType {
|
||||
@@ -42,7 +42,7 @@ public:
|
||||
virtual QString description() override;
|
||||
virtual EffectType type() override;
|
||||
virtual olive::TrackType subtype() override;
|
||||
virtual NodePtr Create(Clip *c) override;
|
||||
virtual OldEffectNodePtr Create(Clip *c) override;
|
||||
|
||||
virtual void redraw(double timecode) override;
|
||||
|
||||
|
||||
@@ -43,9 +43,9 @@
|
||||
#include "global/config.h"
|
||||
|
||||
TextEffect::TextEffect(Clip* c) :
|
||||
Node(c)
|
||||
OldEffectNode(c)
|
||||
{
|
||||
SetFlags(Node::SuperimposeFlag);
|
||||
SetFlags(OldEffectNode::SuperimposeFlag);
|
||||
|
||||
text_val = new StringInput(this, "text", tr("Text"), false);
|
||||
|
||||
@@ -151,7 +151,7 @@ olive::TrackType TextEffect::subtype()
|
||||
return olive::kTypeVideo;
|
||||
}
|
||||
|
||||
NodePtr TextEffect::Create(Clip *c)
|
||||
OldEffectNodePtr TextEffect::Create(Clip *c)
|
||||
{
|
||||
return std::make_shared<TextEffect>(c);
|
||||
}
|
||||
|
||||
@@ -21,12 +21,12 @@
|
||||
#ifndef TEXTEFFECT_H
|
||||
#define TEXTEFFECT_H
|
||||
|
||||
#include "nodes/node.h"
|
||||
#include "nodes/oldeffectnode.h"
|
||||
|
||||
#include <QFont>
|
||||
#include <QImage>
|
||||
|
||||
class TextEffect : public Node {
|
||||
class TextEffect : public OldEffectNode {
|
||||
Q_OBJECT
|
||||
public:
|
||||
TextEffect(Clip* c);
|
||||
@@ -37,7 +37,7 @@ public:
|
||||
virtual QString description() override;
|
||||
virtual EffectType type() override;
|
||||
virtual olive::TrackType subtype() override;
|
||||
virtual NodePtr Create(Clip *c) override;
|
||||
virtual OldEffectNodePtr Create(Clip *c) override;
|
||||
|
||||
virtual void redraw(double timecode) override;
|
||||
private slots:
|
||||
|
||||
@@ -43,9 +43,9 @@
|
||||
#include "global/config.h"
|
||||
|
||||
TimecodeEffect::TimecodeEffect(Clip* c) :
|
||||
Node(c)
|
||||
OldEffectNode(c)
|
||||
{
|
||||
SetFlags(Node::SuperimposeFlag);
|
||||
SetFlags(OldEffectNode::SuperimposeFlag);
|
||||
|
||||
tc_select = new ComboInput(this, "tc_selector", tr("Timecode"));
|
||||
tc_select->AddItem(tr("Sequence"), true);
|
||||
@@ -104,7 +104,7 @@ olive::TrackType TimecodeEffect::subtype()
|
||||
return olive::kTypeVideo;
|
||||
}
|
||||
|
||||
NodePtr TimecodeEffect::Create(Clip *c)
|
||||
OldEffectNodePtr TimecodeEffect::Create(Clip *c)
|
||||
{
|
||||
return std::make_shared<TimecodeEffect>(c);
|
||||
}
|
||||
|
||||
@@ -21,12 +21,12 @@
|
||||
#ifndef TIMECODEEFFECT_H
|
||||
#define TIMECODEEFFECT_H
|
||||
|
||||
#include "nodes/node.h"
|
||||
#include "nodes/oldeffectnode.h"
|
||||
|
||||
#include <QFont>
|
||||
#include <QImage>
|
||||
|
||||
class TimecodeEffect : public Node {
|
||||
class TimecodeEffect : public OldEffectNode {
|
||||
Q_OBJECT
|
||||
public:
|
||||
TimecodeEffect(Clip* c);
|
||||
@@ -37,7 +37,7 @@ public:
|
||||
virtual QString description() override;
|
||||
virtual EffectType type() override;
|
||||
virtual olive::TrackType subtype() override;
|
||||
virtual NodePtr Create(Clip *c) override;
|
||||
virtual OldEffectNodePtr Create(Clip *c) override;
|
||||
|
||||
virtual void redraw(double timecode) override;
|
||||
DoubleInput* scale_val;
|
||||
|
||||
@@ -27,7 +27,7 @@
|
||||
#include "timeline/clip.h"
|
||||
#include "timeline/sequence.h"
|
||||
|
||||
ToneEffect::ToneEffect(Clip* c) : Node(c), sinX(INT_MIN) {
|
||||
ToneEffect::ToneEffect(Clip* c) : OldEffectNode(c), sinX(INT_MIN) {
|
||||
type_val = new ComboInput(this, "type", tr("Type"));
|
||||
type_val->AddItem(tr("Sine"), TONE_TYPE_SINE);
|
||||
|
||||
@@ -70,7 +70,7 @@ olive::TrackType ToneEffect::subtype()
|
||||
return olive::kTypeAudio;
|
||||
}
|
||||
|
||||
NodePtr ToneEffect::Create(Clip *c)
|
||||
OldEffectNodePtr ToneEffect::Create(Clip *c)
|
||||
{
|
||||
return std::make_shared<ToneEffect>(c);
|
||||
}
|
||||
|
||||
@@ -21,9 +21,9 @@
|
||||
#ifndef TONEEFFECT_H
|
||||
#define TONEEFFECT_H
|
||||
|
||||
#include "nodes/node.h"
|
||||
#include "nodes/oldeffectnode.h"
|
||||
|
||||
class ToneEffect : public Node {
|
||||
class ToneEffect : public OldEffectNode {
|
||||
Q_OBJECT
|
||||
public:
|
||||
ToneEffect(Clip* c);
|
||||
@@ -33,7 +33,7 @@ public:
|
||||
virtual QString description() override;
|
||||
virtual EffectType type() override;
|
||||
virtual olive::TrackType subtype() override;
|
||||
virtual NodePtr Create(Clip *c) override;
|
||||
virtual OldEffectNodePtr Create(Clip *c) override;
|
||||
|
||||
virtual void process_audio(double timecode_start,
|
||||
double timecode_end,
|
||||
|
||||
@@ -43,8 +43,8 @@
|
||||
#include "panels/viewer.h"
|
||||
#include "ui/viewerwidget.h"
|
||||
|
||||
TransformEffect::TransformEffect(Clip* c) : Node(c) {
|
||||
SetFlags(Node::CoordsFlag);
|
||||
TransformEffect::TransformEffect(Clip* c) : OldEffectNode(c) {
|
||||
SetFlags(OldEffectNode::CoordsFlag);
|
||||
|
||||
position = new Vec2Input(this, "pos", tr("Position"));
|
||||
|
||||
@@ -68,7 +68,7 @@ TransformEffect::TransformEffect(Clip* c) : Node(c) {
|
||||
opacity->SetDefault(100);
|
||||
|
||||
// TEMP - Create matrix output
|
||||
EffectRow* matrix_output = new EffectRow(this, "matrix", "Matrix", false, false);
|
||||
NodeIO* matrix_output = new NodeIO(this, "matrix", "Matrix", false, false);
|
||||
matrix_output->SetOutputDataType(olive::nodes::kMatrix);
|
||||
|
||||
// set up gizmos
|
||||
@@ -155,7 +155,7 @@ olive::TrackType TransformEffect::subtype()
|
||||
return olive::kTypeVideo;
|
||||
}
|
||||
|
||||
NodePtr TransformEffect::Create(Clip *c)
|
||||
OldEffectNodePtr TransformEffect::Create(Clip *c)
|
||||
{
|
||||
return std::make_shared<TransformEffect>(c);
|
||||
}
|
||||
|
||||
@@ -21,9 +21,9 @@
|
||||
#ifndef TRANSFORMEFFECT_H
|
||||
#define TRANSFORMEFFECT_H
|
||||
|
||||
#include "nodes/node.h"
|
||||
#include "nodes/oldeffectnode.h"
|
||||
|
||||
class TransformEffect : public Node {
|
||||
class TransformEffect : public OldEffectNode {
|
||||
Q_OBJECT
|
||||
public:
|
||||
TransformEffect(Clip* c);
|
||||
@@ -34,7 +34,7 @@ public:
|
||||
virtual QString description() override;
|
||||
virtual EffectType type() override;
|
||||
virtual olive::TrackType subtype() override;
|
||||
virtual NodePtr Create(Clip *c) override;
|
||||
virtual OldEffectNodePtr Create(Clip *c) override;
|
||||
|
||||
virtual void refresh() override;
|
||||
virtual void process_coords(double timecode, GLTextureCoords& coords, int data) override;
|
||||
|
||||
@@ -28,7 +28,7 @@
|
||||
#include "global/debug.h"
|
||||
|
||||
VoidEffect::VoidEffect(Clip* c, const QString& n, const QString& id) :
|
||||
Node(c),
|
||||
OldEffectNode(c),
|
||||
display_name_(n),
|
||||
id_(id)
|
||||
{
|
||||
@@ -69,13 +69,13 @@ bool VoidEffect::IsCreatable()
|
||||
return false;
|
||||
}
|
||||
|
||||
NodePtr VoidEffect::Create(Clip *)
|
||||
OldEffectNodePtr VoidEffect::Create(Clip *)
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
NodePtr VoidEffect::copy(Clip* c) {
|
||||
NodePtr copy = std::make_shared<VoidEffect>(c, display_name_, id_);
|
||||
OldEffectNodePtr VoidEffect::copy(Clip* c) {
|
||||
OldEffectNodePtr copy = std::make_shared<VoidEffect>(c, display_name_, id_);
|
||||
copy->SetEnabled(IsEnabled());
|
||||
copy_field_keyframes(copy);
|
||||
return copy;
|
||||
|
||||
@@ -27,9 +27,9 @@
|
||||
* isn't lost if the user saves over the project.
|
||||
*/
|
||||
|
||||
#include "nodes/node.h"
|
||||
#include "nodes/oldeffectnode.h"
|
||||
|
||||
class VoidEffect : public Node {
|
||||
class VoidEffect : public OldEffectNode {
|
||||
Q_OBJECT
|
||||
public:
|
||||
VoidEffect(Clip* c, const QString& n, const QString &id);
|
||||
@@ -40,8 +40,8 @@ public:
|
||||
virtual EffectType type() override;
|
||||
virtual olive::TrackType subtype() override;
|
||||
virtual bool IsCreatable() override;
|
||||
virtual NodePtr Create(Clip *c) override;
|
||||
virtual NodePtr copy(Clip* c) override;
|
||||
virtual OldEffectNodePtr Create(Clip *c) override;
|
||||
virtual OldEffectNodePtr copy(Clip* c) override;
|
||||
|
||||
virtual void load(QXmlStreamReader &stream) override;
|
||||
virtual void save(QXmlStreamWriter &stream) override;
|
||||
|
||||
@@ -28,7 +28,7 @@
|
||||
#include "ui/labelslider.h"
|
||||
#include "ui/collapsiblewidget.h"
|
||||
|
||||
VolumeEffect::VolumeEffect(Clip* c) : Node(c) {
|
||||
VolumeEffect::VolumeEffect(Clip* c) : OldEffectNode(c) {
|
||||
volume_val = new DoubleInput(this, "volume", tr("Volume"));
|
||||
|
||||
// set defaults
|
||||
@@ -61,7 +61,7 @@ olive::TrackType VolumeEffect::subtype()
|
||||
return olive::kTypeAudio;
|
||||
}
|
||||
|
||||
NodePtr VolumeEffect::Create(Clip *c)
|
||||
OldEffectNodePtr VolumeEffect::Create(Clip *c)
|
||||
{
|
||||
return std::make_shared<VolumeEffect>(c);
|
||||
}
|
||||
|
||||
@@ -21,9 +21,9 @@
|
||||
#ifndef VOLUMEEFFECT_H
|
||||
#define VOLUMEEFFECT_H
|
||||
|
||||
#include "nodes/node.h"
|
||||
#include "nodes/oldeffectnode.h"
|
||||
|
||||
class VolumeEffect : public Node {
|
||||
class VolumeEffect : public OldEffectNode {
|
||||
Q_OBJECT
|
||||
public:
|
||||
VolumeEffect(Clip* c);
|
||||
@@ -33,7 +33,7 @@ public:
|
||||
virtual QString description() override;
|
||||
virtual EffectType type() override;
|
||||
virtual olive::TrackType subtype() override;
|
||||
virtual NodePtr Create(Clip *c) override;
|
||||
virtual OldEffectNodePtr Create(Clip *c) override;
|
||||
|
||||
virtual void process_audio(double timecode_start,
|
||||
double timecode_end,
|
||||
|
||||
@@ -228,7 +228,7 @@ void VSTHost::send_data_cache_to_plugin()
|
||||
}
|
||||
|
||||
VSTHost::VSTHost(Clip* c) :
|
||||
Node(c),
|
||||
OldEffectNode(c),
|
||||
plugin(nullptr),
|
||||
dialog(nullptr),
|
||||
input_cache(BLOCK_SIZE),
|
||||
@@ -274,7 +274,7 @@ olive::TrackType VSTHost::subtype()
|
||||
return olive::kTypeAudio;
|
||||
}
|
||||
|
||||
NodePtr VSTHost::Create(Clip *c)
|
||||
OldEffectNodePtr VSTHost::Create(Clip *c)
|
||||
{
|
||||
return std::make_shared<VSTHost>(c);
|
||||
}
|
||||
@@ -321,7 +321,7 @@ void VSTHost::custom_load(QXmlStreamReader &stream) {
|
||||
}
|
||||
|
||||
void VSTHost::save(QXmlStreamWriter &stream) {
|
||||
Node::save(stream);
|
||||
OldEffectNode::save(stream);
|
||||
if (plugin != nullptr) {
|
||||
char* p = nullptr;
|
||||
int32_t length = int32_t(dispatcher(plugin, effGetChunk, 0, 0, &p, 0));
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
#include <QDialog>
|
||||
#include <QLibrary>
|
||||
|
||||
#include "nodes/node.h"
|
||||
#include "nodes/oldeffectnode.h"
|
||||
#include "include/vestige.h"
|
||||
|
||||
// Plugin's dispatcher function
|
||||
@@ -46,7 +46,7 @@ private:
|
||||
void destroy();
|
||||
};
|
||||
|
||||
class VSTHost : public Node {
|
||||
class VSTHost : public OldEffectNode {
|
||||
Q_OBJECT
|
||||
public:
|
||||
VSTHost(Clip* c);
|
||||
@@ -57,7 +57,7 @@ public:
|
||||
virtual QString description() override;
|
||||
virtual EffectType type() override;
|
||||
virtual olive::TrackType subtype() override;
|
||||
virtual NodePtr Create(Clip *c) override;
|
||||
virtual OldEffectNodePtr Create(Clip *c) override;
|
||||
|
||||
virtual void process_audio(double timecode_start,
|
||||
double timecode_end,
|
||||
|
||||
@@ -41,7 +41,7 @@
|
||||
#include <QCoreApplication>
|
||||
|
||||
Transition::Transition(Clip *c) :
|
||||
Node(c),
|
||||
OldEffectNode(c),
|
||||
secondary_clip(nullptr)
|
||||
{
|
||||
length_field = new DoubleInput(this, "length", tr("Length"), false, false);
|
||||
@@ -57,8 +57,8 @@ Transition::Transition(Clip *c) :
|
||||
connect(length_field, SIGNAL(Changed()), this, SLOT(UpdateMaximumLength()));
|
||||
}
|
||||
|
||||
NodePtr Transition::copy(Clip *c) {
|
||||
NodePtr node = Node::copy(c);
|
||||
OldEffectNodePtr Transition::copy(Clip *c) {
|
||||
OldEffectNodePtr node = OldEffectNode::copy(c);
|
||||
|
||||
static_cast<Transition*>(node.get())->set_length(get_true_length());
|
||||
|
||||
@@ -67,7 +67,7 @@ NodePtr Transition::copy(Clip *c) {
|
||||
|
||||
void Transition::save(QXmlStreamWriter &stream) {
|
||||
stream.writeAttribute("length", QString::number(get_true_length()));
|
||||
Node::save(stream);
|
||||
OldEffectNode::save(stream);
|
||||
}
|
||||
|
||||
void Transition::set_length(int l) {
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
#ifndef TRANSITION_H
|
||||
#define TRANSITION_H
|
||||
|
||||
#include "nodes/node.h"
|
||||
#include "nodes/oldeffectnode.h"
|
||||
#include "nodes/inputs.h"
|
||||
|
||||
enum TransitionType {
|
||||
@@ -33,12 +33,12 @@ enum TransitionType {
|
||||
class Transition;
|
||||
using TransitionPtr = std::shared_ptr<Transition>;
|
||||
|
||||
class Transition : public Node {
|
||||
class Transition : public OldEffectNode {
|
||||
Q_OBJECT
|
||||
public:
|
||||
Transition(Clip* c);
|
||||
|
||||
virtual NodePtr copy(Clip* c) override;
|
||||
virtual OldEffectNodePtr copy(Clip* c) override;
|
||||
|
||||
Clip* secondary_clip;
|
||||
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
#include "clipboard.h"
|
||||
|
||||
#include "timeline/clip.h"
|
||||
#include "nodes/node.h"
|
||||
#include "nodes/oldeffectnode.h"
|
||||
#include "effects/transition.h"
|
||||
#include "undo/undo.h"
|
||||
|
||||
|
||||
+4
-4
@@ -69,7 +69,7 @@ OliveGlobal::OliveGlobal() :
|
||||
version_id = QString(" | %1").arg(GITHASH);
|
||||
#endif
|
||||
|
||||
olive::AppName = QString("Olive (April 2019 | Alpha%1)").arg(version_id);
|
||||
olive::AppName = QString("Olive (May 2019 | Alpha%1)").arg(version_id);
|
||||
|
||||
// set the file filter used in all file dialogs pertaining to Olive project files.
|
||||
project_file_filter = tr("Olive Project %1").arg("(*.ove)");
|
||||
@@ -391,7 +391,7 @@ void OliveGlobal::PasteInternal(Sequence *s, bool insert)
|
||||
Clip* c = selected_clips.at(i);
|
||||
|
||||
for (int j=0;j<olive::clipboard.Count();j++) {
|
||||
NodePtr e = std::static_pointer_cast<Node>(olive::clipboard.Get(j));
|
||||
OldEffectNodePtr e = std::static_pointer_cast<OldEffectNode>(olive::clipboard.Get(j));
|
||||
if (c->type() == e->subtype()) {
|
||||
int found = -1;
|
||||
if (ask_conflict) {
|
||||
@@ -457,7 +457,7 @@ void OliveGlobal::EffectMenuAction(QAction *q)
|
||||
ComboAction* ca = new ComboAction();
|
||||
|
||||
NodeType node_type = static_cast<NodeType>(q->data().toInt());
|
||||
Node* n = olive::node_library[node_type].get();
|
||||
OldEffectNode* n = olive::node_library[node_type].get();
|
||||
|
||||
for (int i=0;i<effect_menu_selected_clips.size();i++) {
|
||||
Clip* c = effect_menu_selected_clips.at(i);
|
||||
@@ -691,7 +691,7 @@ void OliveGlobal::ShowEffectMenu(EffectType type, olive::TrackType subtype, cons
|
||||
|
||||
for (int i=0;i<olive::node_library.size();i++) {
|
||||
|
||||
NodePtr node = olive::node_library.at(i);
|
||||
OldEffectNodePtr node = olive::node_library.at(i);
|
||||
|
||||
if (node != nullptr && node->type() == type && node->subtype() == subtype) {
|
||||
QAction* action = new QAction(&effects_menu);
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#include "boolinput.h"
|
||||
|
||||
BoolInput::BoolInput(Node* parent, const QString& id, const QString& name, bool savable, bool keyframable) :
|
||||
EffectRow(parent, id, name, savable, keyframable)
|
||||
BoolInput::BoolInput(OldEffectNode* parent, const QString& id, const QString& name, bool savable, bool keyframable) :
|
||||
NodeIO(parent, id, name, savable, keyframable)
|
||||
{
|
||||
BoolField* bool_field = new BoolField(this);
|
||||
connect(bool_field, SIGNAL(Toggled(bool)), this, SIGNAL(Toggled(bool)));
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
#ifndef BOOLINPUT_H
|
||||
#define BOOLINPUT_H
|
||||
|
||||
#include "effects/effectrow.h"
|
||||
#include "nodes/nodeio.h"
|
||||
|
||||
class BoolInput : public EffectRow
|
||||
class BoolInput : public NodeIO
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
BoolInput(Node* parent, const QString& id, const QString& name, bool savable = true, bool keyframable = true);
|
||||
BoolInput(OldEffectNode* parent, const QString& id, const QString& name, bool savable = true, bool keyframable = true);
|
||||
|
||||
/**
|
||||
* @brief Get the boolean value at a given timecode
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#include "colorinput.h"
|
||||
|
||||
ColorInput::ColorInput(Node* parent, const QString& id, const QString& name, bool savable, bool keyframable) :
|
||||
EffectRow(parent, id, name, savable, keyframable)
|
||||
ColorInput::ColorInput(OldEffectNode* parent, const QString& id, const QString& name, bool savable, bool keyframable) :
|
||||
NodeIO(parent, id, name, savable, keyframable)
|
||||
{
|
||||
AddField(new ColorField(this));
|
||||
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
#ifndef COLORINPUT_H
|
||||
#define COLORINPUT_H
|
||||
|
||||
#include "effects/effectrow.h"
|
||||
#include "nodes/nodeio.h"
|
||||
|
||||
class ColorInput : public EffectRow
|
||||
class ColorInput : public NodeIO
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
ColorInput(Node* parent, const QString& id, const QString& name, bool savable = true, bool keyframable = true);
|
||||
ColorInput(OldEffectNode* parent, const QString& id, const QString& name, bool savable = true, bool keyframable = true);
|
||||
|
||||
/**
|
||||
* @brief Get the color value at a given timecode
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#include "comboinput.h"
|
||||
|
||||
ComboInput::ComboInput(Node* parent, const QString& id, const QString& name, bool savable, bool keyframable) :
|
||||
EffectRow(parent, id, name, savable, keyframable)
|
||||
ComboInput::ComboInput(OldEffectNode* parent, const QString& id, const QString& name, bool savable, bool keyframable) :
|
||||
NodeIO(parent, id, name, savable, keyframable)
|
||||
{
|
||||
ComboField* combo_field = new ComboField(this);
|
||||
connect(combo_field, SIGNAL(DataChanged(const QVariant&)), this, SIGNAL(DataChanged(const QVariant&)));
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
#ifndef COMBOINPUT_H
|
||||
#define COMBOINPUT_H
|
||||
|
||||
#include "effects/effectrow.h"
|
||||
#include "nodes/nodeio.h"
|
||||
|
||||
class ComboInput : public EffectRow
|
||||
class ComboInput : public NodeIO
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
ComboInput(Node* parent, const QString& id, const QString& name, bool savable = true, bool keyframable = true);
|
||||
ComboInput(OldEffectNode* parent, const QString& id, const QString& name, bool savable = true, bool keyframable = true);
|
||||
|
||||
/**
|
||||
* @brief Add an item to this ComboInput
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#include "fileinput.h"
|
||||
|
||||
FileInput::FileInput(Node* parent, const QString& id, const QString& name, bool savable, bool keyframable) :
|
||||
EffectRow(parent, id, name, savable, keyframable)
|
||||
FileInput::FileInput(OldEffectNode* parent, const QString& id, const QString& name, bool savable, bool keyframable) :
|
||||
NodeIO(parent, id, name, savable, keyframable)
|
||||
{
|
||||
AddField(new FileField(this));
|
||||
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
#ifndef FILEINPUT_H
|
||||
#define FILEINPUT_H
|
||||
|
||||
#include "effects/effectrow.h"
|
||||
#include "nodes/nodeio.h"
|
||||
|
||||
class FileInput : public EffectRow
|
||||
class FileInput : public NodeIO
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
FileInput(Node* parent, const QString& id, const QString& name, bool savable = true, bool keyframable = true);
|
||||
FileInput(OldEffectNode* parent, const QString& id, const QString& name, bool savable = true, bool keyframable = true);
|
||||
|
||||
/**
|
||||
* @brief Get the filename at the given timecode
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#include "fontinput.h"
|
||||
|
||||
FontInput::FontInput(Node* parent, const QString& id, const QString& name, bool savable, bool keyframable) :
|
||||
EffectRow(parent, id, name, savable, keyframable)
|
||||
FontInput::FontInput(OldEffectNode* parent, const QString& id, const QString& name, bool savable, bool keyframable) :
|
||||
NodeIO(parent, id, name, savable, keyframable)
|
||||
{
|
||||
AddField(new FontField(this));
|
||||
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
#ifndef FONTINPUT_H
|
||||
#define FONTINPUT_H
|
||||
|
||||
#include "effects/effectrow.h"
|
||||
#include "nodes/nodeio.h"
|
||||
|
||||
class FontInput : public EffectRow
|
||||
class FontInput : public NodeIO
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
FontInput(Node* parent, const QString& id, const QString& name, bool savable = true, bool keyframable = true);
|
||||
FontInput(OldEffectNode* parent, const QString& id, const QString& name, bool savable = true, bool keyframable = true);
|
||||
|
||||
/**
|
||||
* @brief Get the font family name at the given timecode
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#include "stringinput.h"
|
||||
|
||||
StringInput::StringInput(Node* parent, const QString& id, const QString& name, bool rich_text, bool savable, bool keyframable) :
|
||||
EffectRow(parent, id, name, savable, keyframable)
|
||||
StringInput::StringInput(OldEffectNode* parent, const QString& id, const QString& name, bool rich_text, bool savable, bool keyframable) :
|
||||
NodeIO(parent, id, name, savable, keyframable)
|
||||
{
|
||||
AddField(new StringField(this, rich_text));
|
||||
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
#ifndef STRINGINPUT_H
|
||||
#define STRINGINPUT_H
|
||||
|
||||
#include "effects/effectrow.h"
|
||||
#include "nodes/nodeio.h"
|
||||
|
||||
class StringInput : public EffectRow
|
||||
class StringInput : public NodeIO
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
StringInput(Node* parent,
|
||||
StringInput(OldEffectNode* parent,
|
||||
const QString& id,
|
||||
const QString& name,
|
||||
bool rich_text = true,
|
||||
|
||||
@@ -4,8 +4,8 @@
|
||||
#include <QVector4D>
|
||||
#include <QDebug>
|
||||
|
||||
VecInput::VecInput(Node* parent, const QString& id, const QString& name, int values, bool savable, bool keyframable) :
|
||||
EffectRow(parent, id, name, savable, keyframable),
|
||||
VecInput::VecInput(OldEffectNode* parent, const QString& id, const QString& name, int values, bool savable, bool keyframable) :
|
||||
NodeIO(parent, id, name, savable, keyframable),
|
||||
single_value_mode_(false),
|
||||
values_(values)
|
||||
{
|
||||
@@ -79,7 +79,7 @@ void VecInput::SetSingleValueMode(bool on)
|
||||
}
|
||||
}
|
||||
|
||||
DoubleInput::DoubleInput(Node *parent, const QString &id, const QString &name, bool savable, bool keyframable) :
|
||||
DoubleInput::DoubleInput(OldEffectNode *parent, const QString &id, const QString &name, bool savable, bool keyframable) :
|
||||
VecInput(parent, id, name, 1, savable, keyframable)
|
||||
{
|
||||
}
|
||||
@@ -89,7 +89,7 @@ double DoubleInput::GetDoubleAt(double timecode)
|
||||
return static_cast<DoubleField*>(Field(0))->GetDoubleAt(timecode);
|
||||
}
|
||||
|
||||
Vec2Input::Vec2Input(Node *parent, const QString &id, const QString &name, bool savable, bool keyframable) :
|
||||
Vec2Input::Vec2Input(OldEffectNode *parent, const QString &id, const QString &name, bool savable, bool keyframable) :
|
||||
VecInput(parent, id, name, 2, savable, keyframable)
|
||||
{
|
||||
}
|
||||
@@ -121,7 +121,7 @@ void Vec2Input::SetValueAt(double timecode, const QVariant &value)
|
||||
static_cast<DoubleField*>(Field(1))->SetValueAt(timecode, vec2.y());
|
||||
}
|
||||
|
||||
Vec3Input::Vec3Input(Node *parent, const QString &id, const QString &name, bool savable, bool keyframable) :
|
||||
Vec3Input::Vec3Input(OldEffectNode *parent, const QString &id, const QString &name, bool savable, bool keyframable) :
|
||||
VecInput(parent, id, name, 3, savable, keyframable)
|
||||
{
|
||||
}
|
||||
@@ -156,7 +156,7 @@ void Vec3Input::SetValueAt(double timecode, const QVariant &value)
|
||||
static_cast<DoubleField*>(Field(2))->SetValueAt(timecode, vec3.z());
|
||||
}
|
||||
|
||||
Vec4Input::Vec4Input(Node *parent, const QString &id, const QString &name, bool savable, bool keyframable) :
|
||||
Vec4Input::Vec4Input(OldEffectNode *parent, const QString &id, const QString &name, bool savable, bool keyframable) :
|
||||
VecInput(parent, id, name, 4, savable, keyframable)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -3,13 +3,13 @@
|
||||
|
||||
#include <QVector2D>
|
||||
|
||||
#include "effects/effectrow.h"
|
||||
#include "nodes/nodeio.h"
|
||||
|
||||
class VecInput : public EffectRow
|
||||
class VecInput : public NodeIO
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
VecInput(Node* parent, const QString& id, const QString& name, int values, bool savable = true, bool keyframable = true);
|
||||
VecInput(OldEffectNode* parent, const QString& id, const QString& name, int values, bool savable = true, bool keyframable = true);
|
||||
|
||||
void SetMinimum(double minimum);
|
||||
void SetMaximum(double maximum);
|
||||
@@ -43,14 +43,14 @@ private:
|
||||
class DoubleInput : public VecInput
|
||||
{
|
||||
public:
|
||||
DoubleInput(Node* parent, const QString& id, const QString& name, bool savable = true, bool keyframable = true);
|
||||
DoubleInput(OldEffectNode* parent, const QString& id, const QString& name, bool savable = true, bool keyframable = true);
|
||||
|
||||
double GetDoubleAt(double timecode);
|
||||
};
|
||||
|
||||
class Vec2Input : public VecInput {
|
||||
public:
|
||||
Vec2Input(Node* parent, const QString& id, const QString& name, bool savable = true, bool keyframable = true);
|
||||
Vec2Input(OldEffectNode* parent, const QString& id, const QString& name, bool savable = true, bool keyframable = true);
|
||||
|
||||
QVector2D GetVector2DAt(double timecode);
|
||||
virtual QVariant GetValueAt(double timecode) override;
|
||||
@@ -59,7 +59,7 @@ public:
|
||||
|
||||
class Vec3Input : public VecInput {
|
||||
public:
|
||||
Vec3Input(Node* parent, const QString& id, const QString& name, bool savable = true, bool keyframable = true);
|
||||
Vec3Input(OldEffectNode* parent, const QString& id, const QString& name, bool savable = true, bool keyframable = true);
|
||||
|
||||
QVector3D GetVector3DAt(double timecode);
|
||||
virtual QVariant GetValueAt(double timecode) override;
|
||||
@@ -68,7 +68,7 @@ public:
|
||||
|
||||
class Vec4Input : public VecInput {
|
||||
public:
|
||||
Vec4Input(Node* parent, const QString& id, const QString& name, bool savable = true, bool keyframable = true);
|
||||
Vec4Input(OldEffectNode* parent, const QString& id, const QString& name, bool savable = true, bool keyframable = true);
|
||||
|
||||
QVector4D GetVector4DAt(double timecode);
|
||||
virtual QVariant GetValueAt(double timecode) override;
|
||||
|
||||
+6
-943
@@ -1,943 +1,6 @@
|
||||
/***
|
||||
|
||||
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 "node.h"
|
||||
|
||||
#include <QCheckBox>
|
||||
#include <QGridLayout>
|
||||
#include <QXmlStreamReader>
|
||||
#include <QXmlStreamWriter>
|
||||
#include <QMessageBox>
|
||||
#include <QOpenGLContext>
|
||||
#include <QDir>
|
||||
#include <QPainter>
|
||||
#include <QtMath>
|
||||
#include <QMenu>
|
||||
#include <QApplication>
|
||||
#include <QFileDialog>
|
||||
|
||||
#include "panels/panels.h"
|
||||
#include "panels/viewer.h"
|
||||
#include "ui/viewerwidget.h"
|
||||
#include "ui/collapsiblewidget.h"
|
||||
#include "panels/project.h"
|
||||
#include "undo/undo.h"
|
||||
#include "timeline/sequence.h"
|
||||
#include "timeline/clip.h"
|
||||
#include "panels/timeline.h"
|
||||
#include "panels/effectcontrols.h"
|
||||
#include "panels/grapheditor.h"
|
||||
#include "global/debug.h"
|
||||
#include "global/path.h"
|
||||
#include "ui/mainwindow.h"
|
||||
#include "ui/menu.h"
|
||||
#include "global/math.h"
|
||||
#include "global/clipboard.h"
|
||||
#include "global/config.h"
|
||||
#include "effects/transition.h"
|
||||
#include "undo/undostack.h"
|
||||
#include "rendering/shadergenerators.h"
|
||||
#include "global/timing.h"
|
||||
#include "nodes/nodes.h"
|
||||
#include "effects/effectloaders.h"
|
||||
|
||||
QVector<NodePtr> olive::node_library;
|
||||
|
||||
Node::Node(Clip* c) :
|
||||
parent_clip(c),
|
||||
flags_(0),
|
||||
shader_program_(nullptr),
|
||||
texture(0),
|
||||
tex_width_(0),
|
||||
tex_height_(0),
|
||||
isOpen(false),
|
||||
bound(false),
|
||||
iterations(1),
|
||||
enabled_(true),
|
||||
expanded_(true),
|
||||
texture_ctx(nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
Node::~Node() {
|
||||
if (isOpen) {
|
||||
close();
|
||||
}
|
||||
|
||||
// Clear graph editor if it's using one of these rows
|
||||
if (panel_graph_editor != nullptr) {
|
||||
for (int i=0;i<row_count();i++) {
|
||||
if (row(i) == panel_graph_editor->get_row()) {
|
||||
panel_graph_editor->set_row(nullptr);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
QString Node::category()
|
||||
{
|
||||
return QString();
|
||||
}
|
||||
|
||||
bool Node::IsCreatable()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
void Node::AddRow(EffectRow *row)
|
||||
{
|
||||
row->setParent(this);
|
||||
rows.append(row);
|
||||
}
|
||||
|
||||
int Node::IndexOfRow(EffectRow *row)
|
||||
{
|
||||
return rows.indexOf(row);
|
||||
}
|
||||
|
||||
void Node::copy_field_keyframes(NodePtr e) {
|
||||
for (int i=0;i<rows.size();i++) {
|
||||
EffectRow* row = rows.at(i);
|
||||
EffectRow* copy_row = e->rows.at(i);
|
||||
copy_row->SetKeyframingInternal(row->IsKeyframing());
|
||||
for (int j=0;j<row->FieldCount();j++) {
|
||||
// Get field from this (the source) effect
|
||||
EffectField* field = row->Field(j);
|
||||
|
||||
// Get field from the destination effect
|
||||
EffectField* copy_field = copy_row->Field(j);
|
||||
|
||||
// Copy keyframes between effects
|
||||
copy_field->keyframes = field->keyframes;
|
||||
|
||||
// Copy persistet data between effects
|
||||
copy_field->persistent_data_ = field->persistent_data_;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
EffectRow* Node::row(int i) {
|
||||
return rows.at(i);
|
||||
}
|
||||
|
||||
int Node::row_count() {
|
||||
return rows.size();
|
||||
}
|
||||
|
||||
EffectGizmo *Node::add_gizmo(int type) {
|
||||
EffectGizmo* gizmo = new EffectGizmo(this, type);
|
||||
gizmos.append(gizmo);
|
||||
return gizmo;
|
||||
}
|
||||
|
||||
EffectGizmo *Node::gizmo(int i) {
|
||||
return gizmos.at(i);
|
||||
}
|
||||
|
||||
int Node::gizmo_count() {
|
||||
return gizmos.size();
|
||||
}
|
||||
|
||||
QVector<NodeEdgePtr> Node::GetAllEdges()
|
||||
{
|
||||
QVector<NodeEdgePtr> edges;
|
||||
|
||||
for (int i=0;i<row_count();i++) {
|
||||
edges.append(row(i)->edges());
|
||||
}
|
||||
|
||||
return edges;
|
||||
}
|
||||
|
||||
void Node::refresh() {}
|
||||
|
||||
void Node::FieldChanged() {
|
||||
// Update the UI if a field has been modified, but don't both if this effect is inactive
|
||||
if (parent_clip != nullptr) {
|
||||
update_ui(false);
|
||||
}
|
||||
}
|
||||
|
||||
void Node::delete_self() {
|
||||
olive::undo_stack.push(new EffectDeleteCommand(this));
|
||||
update_ui(true);
|
||||
}
|
||||
|
||||
void Node::move_up() {
|
||||
int index_of_effect = parent_clip->IndexOfEffect(this);
|
||||
if (index_of_effect == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
MoveEffectCommand* command = new MoveEffectCommand();
|
||||
command->clip = parent_clip;
|
||||
command->from = index_of_effect;
|
||||
command->to = command->from - 1;
|
||||
olive::undo_stack.push(command);
|
||||
panel_effect_controls->Reload();
|
||||
panel_sequence_viewer->viewer_widget()->frame_update();
|
||||
}
|
||||
|
||||
void Node::move_down() {
|
||||
int index_of_effect = parent_clip->IndexOfEffect(this);
|
||||
if (index_of_effect == parent_clip->effects.size()-1) {
|
||||
return;
|
||||
}
|
||||
|
||||
MoveEffectCommand* command = new MoveEffectCommand();
|
||||
command->clip = parent_clip;
|
||||
command->from = index_of_effect;
|
||||
command->to = command->from + 1;
|
||||
olive::undo_stack.push(command);
|
||||
panel_effect_controls->Reload();
|
||||
panel_sequence_viewer->viewer_widget()->frame_update();
|
||||
}
|
||||
|
||||
void Node::save_to_file() {
|
||||
// save effect settings to file
|
||||
QString file = QFileDialog::getSaveFileName(olive::MainWindow,
|
||||
tr("Save Effect Settings"),
|
||||
QString(),
|
||||
tr("Effect XML Settings %1").arg("(*.xml)"));
|
||||
|
||||
// if the user picked a file
|
||||
if (!file.isEmpty()) {
|
||||
|
||||
// ensure file ends with .xml extension
|
||||
if (!file.endsWith(".xml", Qt::CaseInsensitive)) {
|
||||
file.append(".xml");
|
||||
}
|
||||
|
||||
QFile file_handle(file);
|
||||
if (file_handle.open(QFile::WriteOnly)) {
|
||||
|
||||
file_handle.write(save_to_string());
|
||||
|
||||
file_handle.close();
|
||||
} else {
|
||||
QMessageBox::critical(olive::MainWindow,
|
||||
tr("Save Settings Failed"),
|
||||
tr("Failed to open \"%1\" for writing.").arg(file),
|
||||
QMessageBox::Ok);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Node::load_from_file() {
|
||||
// load effect settings from file
|
||||
QString file = QFileDialog::getOpenFileName(olive::MainWindow,
|
||||
tr("Load Effect Settings"),
|
||||
QString(),
|
||||
tr("Effect XML Settings %1").arg("(*.xml)"));
|
||||
|
||||
// if the user picked a file
|
||||
if (!file.isEmpty()) {
|
||||
QFile file_handle(file);
|
||||
if (file_handle.open(QFile::ReadOnly)) {
|
||||
|
||||
olive::undo_stack.push(new SetEffectData(this, file_handle.readAll()));
|
||||
|
||||
file_handle.close();
|
||||
|
||||
update_ui(false);
|
||||
} else {
|
||||
QMessageBox::critical(olive::MainWindow,
|
||||
tr("Load Settings Failed"),
|
||||
tr("Failed to open \"%1\" for reading.").arg(file),
|
||||
QMessageBox::Ok);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool Node::AlwaysUpdate()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Node::IsEnabled() {
|
||||
return enabled_;
|
||||
}
|
||||
|
||||
bool Node::IsExpanded()
|
||||
{
|
||||
return expanded_;
|
||||
}
|
||||
|
||||
void Node::SetExpanded(bool e)
|
||||
{
|
||||
expanded_ = e;
|
||||
}
|
||||
|
||||
void Node::SetPos(const QPointF &pos)
|
||||
{
|
||||
pos_ = pos;
|
||||
}
|
||||
|
||||
void Node::SetEnabled(bool b) {
|
||||
enabled_ = b;
|
||||
emit EnabledChanged(b);
|
||||
}
|
||||
|
||||
void Node::load(QXmlStreamReader& stream) {
|
||||
/*
|
||||
int row_count = 0;
|
||||
|
||||
QString tag = stream.name().toString();
|
||||
|
||||
while (!stream.atEnd() && !(stream.name() == tag && stream.isEndElement())) {
|
||||
stream.readNext();
|
||||
if (stream.name() == "row" && stream.isStartElement()) {
|
||||
if (row_count < rows.size()) {
|
||||
EffectRow* row = rows.at(row_count);
|
||||
|
||||
while (!stream.atEnd() && !(stream.name() == "row" && stream.isEndElement())) {
|
||||
stream.readNext();
|
||||
|
||||
// read field
|
||||
if (stream.name() == "field" && stream.isStartElement()) {
|
||||
int field_number = -1;
|
||||
|
||||
// match field using ID
|
||||
for (int k=0;k<stream.attributes().size();k++) {
|
||||
const QXmlStreamAttribute& attr = stream.attributes().at(k);
|
||||
if (attr.name() == "id") {
|
||||
for (int l=0;l<row->FieldCount();l++) {
|
||||
if (row->Field(l)->id() == attr.value()) {
|
||||
field_number = l;
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (field_number > -1) {
|
||||
EffectField* field = row->Field(field_number);
|
||||
|
||||
// get current field value
|
||||
for (int k=0;k<stream.attributes().size();k++) {
|
||||
const QXmlStreamAttribute& attr = stream.attributes().at(k);
|
||||
if (attr.name() == "value") {
|
||||
field->persistent_data_ = field->ConvertStringToValue(attr.value().toString());
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
while (!stream.atEnd() && !(stream.name() == "field" && stream.isEndElement())) {
|
||||
stream.readNext();
|
||||
|
||||
// read keyframes
|
||||
if (stream.name() == "key" && stream.isStartElement()) {
|
||||
row->SetKeyframingInternal(true);
|
||||
|
||||
EffectKeyframe key;
|
||||
for (int k=0;k<stream.attributes().size();k++) {
|
||||
const QXmlStreamAttribute& attr = stream.attributes().at(k);
|
||||
if (attr.name() == "value") {
|
||||
key.data = field->ConvertStringToValue(attr.value().toString());
|
||||
} else if (attr.name() == "frame") {
|
||||
key.time = attr.value().toLong();
|
||||
} else if (attr.name() == "type") {
|
||||
key.type = attr.value().toInt();
|
||||
} else if (attr.name() == "prehx") {
|
||||
key.pre_handle_x = attr.value().toDouble();
|
||||
} else if (attr.name() == "prehy") {
|
||||
key.pre_handle_y = attr.value().toDouble();
|
||||
} else if (attr.name() == "posthx") {
|
||||
key.post_handle_x = attr.value().toDouble();
|
||||
} else if (attr.name() == "posthy") {
|
||||
key.post_handle_y = attr.value().toDouble();
|
||||
}
|
||||
}
|
||||
field->keyframes.append(key);
|
||||
}
|
||||
}
|
||||
|
||||
field->Changed();
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
qCritical() << "Too many rows for effect" << id << ". Project might be corrupt. (Got" << row_count << ", expected <" << rows.size()-1 << ")";
|
||||
}
|
||||
row_count++;
|
||||
} else if (stream.isStartElement()) {
|
||||
custom_load(stream);
|
||||
}
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
void Node::custom_load(QXmlStreamReader &) {}
|
||||
|
||||
void Node::save(QXmlStreamWriter& stream) {
|
||||
/*
|
||||
stream.writeAttribute("name", meta->category + "/" + meta->name);
|
||||
stream.writeAttribute("enabled", QString::number(IsEnabled()));
|
||||
|
||||
for (int i=0;i<rows.size();i++) {
|
||||
EffectRow* row = rows.at(i);
|
||||
if (row->IsSavable()) {
|
||||
stream.writeStartElement("row"); // row
|
||||
for (int j=0;j<row->FieldCount();j++) {
|
||||
EffectField* field = row->Field(j);
|
||||
|
||||
if (!field->id().isEmpty()) {
|
||||
stream.writeStartElement("field"); // field
|
||||
stream.writeAttribute("id", field->id());
|
||||
stream.writeAttribute("value", field->ConvertValueToString(field->persistent_data_));
|
||||
for (int k=0;k<field->keyframes.size();k++) {
|
||||
const EffectKeyframe& key = field->keyframes.at(k);
|
||||
stream.writeStartElement("key");
|
||||
stream.writeAttribute("value", field->ConvertValueToString(key.data));
|
||||
stream.writeAttribute("frame", QString::number(key.time));
|
||||
stream.writeAttribute("type", QString::number(key.type));
|
||||
stream.writeAttribute("prehx", QString::number(key.pre_handle_x));
|
||||
stream.writeAttribute("prehy", QString::number(key.pre_handle_y));
|
||||
stream.writeAttribute("posthx", QString::number(key.post_handle_x));
|
||||
stream.writeAttribute("posthy", QString::number(key.post_handle_y));
|
||||
stream.writeEndElement(); // key
|
||||
}
|
||||
stream.writeEndElement(); // field
|
||||
}
|
||||
}
|
||||
stream.writeEndElement(); // row
|
||||
}
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
void Node::load_from_string(const QByteArray &s) {
|
||||
// clear existing keyframe data
|
||||
for (int i=0;i<rows.size();i++) {
|
||||
EffectRow* row = rows.at(i);
|
||||
row->SetKeyframingInternal(false);
|
||||
for (int j=0;j<row->FieldCount();j++) {
|
||||
EffectField* field = row->Field(j);
|
||||
field->keyframes.clear();
|
||||
}
|
||||
}
|
||||
|
||||
// write settings with xml writer
|
||||
QXmlStreamReader stream(s);
|
||||
|
||||
bool found_id = false;
|
||||
|
||||
while (!stream.atEnd()) {
|
||||
stream.readNext();
|
||||
|
||||
// find the effect opening tag
|
||||
if (stream.name() == "effect" && stream.isStartElement()) {
|
||||
|
||||
// check the name to see if it matches this effect
|
||||
const QXmlStreamAttributes& attributes = stream.attributes();
|
||||
for (int i=0;i<attributes.size();i++) {
|
||||
const QXmlStreamAttribute& attr = attributes.at(i);
|
||||
if (attr.name() == "id") {
|
||||
load(stream);
|
||||
found_id = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// we've found what we're looking for
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!found_id) {
|
||||
QMessageBox::critical(olive::MainWindow,
|
||||
tr("Load Settings Failed"),
|
||||
tr("This settings file doesn't match this effect."),
|
||||
QMessageBox::Ok);
|
||||
}
|
||||
}
|
||||
|
||||
QByteArray Node::save_to_string() {
|
||||
QByteArray save_data;
|
||||
|
||||
// write settings to string with xml writer
|
||||
QXmlStreamWriter stream(&save_data);
|
||||
|
||||
stream.writeStartDocument();
|
||||
|
||||
stream.writeStartElement("effect");
|
||||
|
||||
// pass off to standard saving function
|
||||
save(stream);
|
||||
|
||||
stream.writeEndElement(); // effect
|
||||
|
||||
stream.writeEndDocument();
|
||||
|
||||
return save_data;
|
||||
}
|
||||
|
||||
bool Node::is_open() {
|
||||
return isOpen;
|
||||
}
|
||||
|
||||
void Node::validate_meta_path() {
|
||||
/*
|
||||
if (!meta->path.isEmpty() || (shader_vert_path_.isEmpty() && shader_frag_path_.isEmpty())) return;
|
||||
QList<QString> effects_paths = get_effects_paths();
|
||||
const QString& test_fn = shader_vert_path_.isEmpty() ? shader_frag_path_ : shader_vert_path_;
|
||||
for (int i=0;i<effects_paths.size();i++) {
|
||||
if (QFileInfo::exists(effects_paths.at(i) + "/" + test_fn)) {
|
||||
for (int j=0;j<olive::effects.size();j++) {
|
||||
if (&olive::effects.at(j) == meta) {
|
||||
olive::effects[j].path = effects_paths.at(i);
|
||||
return;
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
void Node::open() {
|
||||
/*
|
||||
if (isOpen) {
|
||||
qWarning() << "Tried to open an effect that was already open";
|
||||
close();
|
||||
}
|
||||
if (olive::runtime_config.shaders_are_enabled && (Flags() & ShaderFlag)) {
|
||||
if (QOpenGLContext::currentContext() == nullptr) {
|
||||
qWarning() << "No current context to create a shader program for - will retry next repaint";
|
||||
} else {
|
||||
validate_meta_path();
|
||||
|
||||
QString frag_shader_str;
|
||||
QString frag_file_url = QDir(file).filePath(shader_frag_path_);
|
||||
QFile frag_file(frag_file_url);
|
||||
if (frag_file.open(QFile::ReadOnly)) {
|
||||
frag_shader_str = frag_file.readAll();
|
||||
frag_file.close();
|
||||
} else {
|
||||
qWarning() << "Failed to open" << frag_file_url;
|
||||
}
|
||||
|
||||
if (!frag_shader_str.isEmpty()) {
|
||||
|
||||
QString shader_func;
|
||||
|
||||
if (!shader_function_name_.isEmpty()) {
|
||||
shader_func = shader_function_name_;
|
||||
} else {
|
||||
shader_func = "process";
|
||||
}
|
||||
|
||||
shader_program_ = olive::shader::GetPipeline(shader_func, frag_shader_str);
|
||||
|
||||
}
|
||||
isOpen = true;
|
||||
}
|
||||
} else {
|
||||
isOpen = true;
|
||||
}
|
||||
*/
|
||||
isOpen = true;
|
||||
}
|
||||
|
||||
void Node::close() {
|
||||
if (!isOpen) {
|
||||
qWarning() << "Tried to close an effect that was already closed";
|
||||
}
|
||||
delete_texture();
|
||||
shader_program_ = nullptr;
|
||||
isOpen = false;
|
||||
}
|
||||
|
||||
bool Node::is_shader_linked() {
|
||||
return shader_program_ != nullptr && shader_program_->isLinked();
|
||||
}
|
||||
|
||||
QOpenGLShaderProgram *Node::GetShaderPipeline()
|
||||
{
|
||||
return shader_program_.get();
|
||||
}
|
||||
|
||||
int Node::Flags()
|
||||
{
|
||||
return flags_;
|
||||
}
|
||||
|
||||
void Node::SetFlags(int flags)
|
||||
{
|
||||
flags_ = flags;
|
||||
}
|
||||
|
||||
int Node::getIterations() {
|
||||
return iterations;
|
||||
}
|
||||
|
||||
void Node::setIterations(int i) {
|
||||
iterations = i;
|
||||
}
|
||||
|
||||
const QPointF &Node::pos()
|
||||
{
|
||||
return pos_;
|
||||
}
|
||||
|
||||
void Node::process_image(double, uint8_t *, uint8_t *, int){}
|
||||
|
||||
NodePtr Node::copy(Clip *c) {
|
||||
NodePtr copy = Create(c);
|
||||
copy->SetEnabled(IsEnabled());
|
||||
copy_field_keyframes(copy);
|
||||
return copy;
|
||||
}
|
||||
|
||||
void Node::process_shader(double timecode, GLTextureCoords&, int iteration) {
|
||||
/*
|
||||
shader_program_->bind();
|
||||
|
||||
shader_program_->setUniformValue("resolution", parent_clip->media_width(), parent_clip->media_height());
|
||||
shader_program_->setUniformValue("time", GLfloat(timecode));
|
||||
shader_program_->setUniformValue("iteration", iteration);
|
||||
|
||||
for (int i=0;i<rows.size();i++) {
|
||||
EffectRow* row = rows.at(i);
|
||||
|
||||
for (int j=0;j<row->FieldCount();j++) {
|
||||
EffectField* field = row->Field(j);
|
||||
if (!field->id().isEmpty()) {
|
||||
switch (field->type()) {
|
||||
case EffectField::EFFECT_FIELD_DOUBLE:
|
||||
{
|
||||
DoubleField* double_field = static_cast<DoubleField*>(field);
|
||||
shader_program_->setUniformValue(double_field->id().toUtf8().constData(),
|
||||
GLfloat(double_field->GetDoubleAt(timecode)));
|
||||
}
|
||||
break;
|
||||
case EffectField::EFFECT_FIELD_COLOR:
|
||||
{
|
||||
ColorField* color_field = static_cast<ColorField *>(field);
|
||||
shader_program_->setUniformValue(
|
||||
color_field->id().toUtf8().constData(),
|
||||
GLfloat(color_field->GetColorAt(timecode).redF()),
|
||||
GLfloat(color_field->GetColorAt(timecode).greenF()),
|
||||
GLfloat(color_field->GetColorAt(timecode).blueF())
|
||||
);
|
||||
}
|
||||
break;
|
||||
case EffectField::EFFECT_FIELD_BOOL:
|
||||
shader_program_->setUniformValue(field->id().toUtf8().constData(), field->GetValueAt(timecode).toBool());
|
||||
break;
|
||||
case EffectField::EFFECT_FIELD_COMBO:
|
||||
shader_program_->setUniformValue(field->id().toUtf8().constData(), field->GetValueAt(timecode).toInt());
|
||||
break;
|
||||
|
||||
// can you even send a string to a uniform value?
|
||||
case EffectField::EFFECT_FIELD_STRING:
|
||||
case EffectField::EFFECT_FIELD_FONT:
|
||||
case EffectField::EFFECT_FIELD_FILE:
|
||||
case EffectField::EFFECT_FIELD_UI:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
shader_program_->release();
|
||||
*/
|
||||
}
|
||||
|
||||
void Node::process_coords(double, GLTextureCoords&, int) {}
|
||||
|
||||
GLuint Node::process_superimpose(QOpenGLContext* ctx, double timecode) {
|
||||
bool dimensions_changed = false;
|
||||
bool redrew_image = false;
|
||||
|
||||
int width = parent_clip->media_width();
|
||||
int height = parent_clip->media_height();
|
||||
|
||||
if (width != img.width() || height != img.height()) {
|
||||
img = QImage(width, height, QImage::Format_RGBA8888_Premultiplied);
|
||||
dimensions_changed = true;
|
||||
}
|
||||
|
||||
if (valueHasChanged(timecode) || dimensions_changed || AlwaysUpdate()) {
|
||||
redraw(timecode);
|
||||
redrew_image = true;
|
||||
}
|
||||
|
||||
QOpenGLFunctions* f = ctx->functions();
|
||||
|
||||
if (texture == 0 || tex_width_ != img.width() || tex_height_ != img.height()) {
|
||||
delete_texture();
|
||||
|
||||
tex_width_ = img.width();
|
||||
tex_height_ = img.height();
|
||||
|
||||
// create texture object
|
||||
f->glGenTextures(1, &texture);
|
||||
|
||||
f->glBindTexture(GL_TEXTURE_2D, texture);
|
||||
|
||||
// set texture filtering to bilinear
|
||||
f->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
f->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
|
||||
f->glTexImage2D(
|
||||
GL_TEXTURE_2D, 0, GL_RGBA8, tex_width_, tex_height_, 0, GL_RGBA, GL_UNSIGNED_BYTE, img.constBits()
|
||||
);
|
||||
|
||||
f->glBindTexture(GL_TEXTURE_2D, 0);
|
||||
|
||||
redrew_image = false;
|
||||
}
|
||||
|
||||
if (redrew_image) {
|
||||
f->glBindTexture(GL_TEXTURE_2D, texture);
|
||||
|
||||
f->glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, tex_width_, tex_height_, GL_RGBA, GL_UNSIGNED_BYTE, img.constBits());
|
||||
|
||||
f->glBindTexture(GL_TEXTURE_2D, 0);
|
||||
}
|
||||
|
||||
return texture;
|
||||
}
|
||||
|
||||
void Node::process_audio(double, double, float **, int, int, int) {}
|
||||
|
||||
void Node::gizmo_draw(double, GLTextureCoords &) {}
|
||||
|
||||
void Node::gizmo_move(EffectGizmo* gizmo, int x_movement, int y_movement, double timecode, bool done) {
|
||||
// Loop through each gizmo to find `gizmo`
|
||||
for (int i=0;i<gizmos.size();i++) {
|
||||
|
||||
if (gizmos.at(i) == gizmo) {
|
||||
|
||||
// If (!done && gizmo_dragging_actions_.isEmpty()), that means the drag just started and we're going to save
|
||||
// the current state of the attach fields' keyframes in KeyframeDataChange objects to make the changes undoable
|
||||
// by the user later.
|
||||
if (!done && gizmo_dragging_actions_.isEmpty()) {
|
||||
if (gizmo->x_field1 != nullptr) {
|
||||
gizmo_dragging_actions_.append(new KeyframeDataChange(gizmo->x_field1));
|
||||
}
|
||||
if (gizmo->y_field1 != nullptr) {
|
||||
gizmo_dragging_actions_.append(new KeyframeDataChange(gizmo->y_field1));
|
||||
}
|
||||
if (gizmo->x_field2 != nullptr) {
|
||||
gizmo_dragging_actions_.append(new KeyframeDataChange(gizmo->x_field2));
|
||||
}
|
||||
if (gizmo->y_field2 != nullptr) {
|
||||
gizmo_dragging_actions_.append(new KeyframeDataChange(gizmo->y_field2));
|
||||
}
|
||||
}
|
||||
|
||||
// Update the field values
|
||||
if (gizmo->x_field1 != nullptr) {
|
||||
gizmo->x_field1->SetValueAt(timecode,
|
||||
gizmo->x_field1->GetDoubleAt(timecode) + x_movement*gizmo->x_field_multi1);
|
||||
}
|
||||
if (gizmo->y_field1 != nullptr) {
|
||||
gizmo->y_field1->SetValueAt(timecode,
|
||||
gizmo->y_field1->GetDoubleAt(timecode) + y_movement*gizmo->y_field_multi1);
|
||||
}
|
||||
if (gizmo->x_field2 != nullptr) {
|
||||
gizmo->x_field2->SetValueAt(timecode,
|
||||
gizmo->x_field2->GetDoubleAt(timecode) + x_movement*gizmo->x_field_multi2);
|
||||
}
|
||||
if (gizmo->y_field2 != nullptr) {
|
||||
gizmo->y_field2->SetValueAt(timecode,
|
||||
gizmo->y_field2->GetDoubleAt(timecode) + y_movement*gizmo->y_field_multi2);
|
||||
}
|
||||
|
||||
// If (done && !gizmo_dragging_actions_.isEmpty()), that means the drag just ended and we're going to save
|
||||
// the new state of the attach fields' keyframes in KeyframeDataChange objects to make the changes undoable
|
||||
// by the user later.
|
||||
if (done && !gizmo_dragging_actions_.isEmpty()) {
|
||||
|
||||
// Store all the KeyframeDataChange objects into a ComboAction to send to the undo stack (makes them all
|
||||
// undoable together rather than having to be undone individually).
|
||||
ComboAction* ca = new ComboAction();
|
||||
|
||||
for (int j=0;j<gizmo_dragging_actions_.size();j++) {
|
||||
// Set the current state of the keyframes as the "new" keyframes (the old values were set earlier when the
|
||||
// KeyframeDataChange object was constructed).
|
||||
gizmo_dragging_actions_.at(j)->SetNewKeyframes();
|
||||
|
||||
// Add this KeyframeDataChange object to the ComboAction
|
||||
ca->append(gizmo_dragging_actions_.at(j));
|
||||
}
|
||||
|
||||
olive::undo_stack.push(ca);
|
||||
|
||||
gizmo_dragging_actions_.clear();
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Node::gizmo_world_to_screen(const QMatrix4x4& matrix, const QMatrix4x4& projection) {
|
||||
for (int i=0;i<gizmos.size();i++) {
|
||||
EffectGizmo* g = gizmos.at(i);
|
||||
|
||||
for (int j=0;j<g->get_point_count();j++) {
|
||||
|
||||
// Convert the world point from the gizmo into a screen point relative to the sequence's dimensions
|
||||
|
||||
QVector3D screen_pos = g->world_pos.at(j).project(matrix,
|
||||
projection,
|
||||
QRect(0,
|
||||
0,
|
||||
parent_clip->track()->sequence()->width,
|
||||
parent_clip->track()->sequence()->height));
|
||||
|
||||
g->screen_pos[j] = QPoint(screen_pos.x(), parent_clip->track()->sequence()->height-screen_pos.y());
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool Node::are_gizmos_enabled() {
|
||||
return (gizmos.size() > 0);
|
||||
}
|
||||
|
||||
double Node::Now()
|
||||
{
|
||||
return playhead_to_clip_seconds(parent_clip, parent_clip->track()->sequence()->playhead);
|
||||
}
|
||||
|
||||
long Node::NowInFrames()
|
||||
{
|
||||
return playhead_to_clip_frame(parent_clip, parent_clip->track()->sequence()->playhead);
|
||||
}
|
||||
|
||||
void Node::redraw(double) {
|
||||
/*
|
||||
// run javascript
|
||||
QPainter p(&img);
|
||||
painter_wrapper.img = &img;
|
||||
painter_wrapper.painter = &p;
|
||||
|
||||
jsEngine.globalObject().setProperty("painter", wrapper_obj);
|
||||
jsEngine.globalObject().setProperty("width", parent_clip->media_width());
|
||||
jsEngine.globalObject().setProperty("height", parent_clip->media_height());
|
||||
|
||||
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);
|
||||
if (!field->id.isEmpty()) {
|
||||
switch (field->type) {
|
||||
case EffectField::EFFECT_FIELD_DOUBLE:
|
||||
jsEngine.globalObject().setProperty(field->id, field->get_double_value(timecode));
|
||||
break;
|
||||
case EffectField::EFFECT_FIELD_COLOR:
|
||||
jsEngine.globalObject().setProperty(field->id, field->get_color_value(timecode).name());
|
||||
break;
|
||||
case EffectField::EFFECT_FIELD_STRING:
|
||||
jsEngine.globalObject().setProperty(field->id, field->get_string_value(timecode));
|
||||
break;
|
||||
case EffectField::EFFECT_FIELD_BOOL:
|
||||
jsEngine.globalObject().setProperty(field->id, field->get_bool_value(timecode));
|
||||
break;
|
||||
case EffectField::EFFECT_FIELD_COMBO:
|
||||
jsEngine.globalObject().setProperty(field->id, field->get_combo_index(timecode));
|
||||
break;
|
||||
case EffectField::EFFECT_FIELD_FONT:
|
||||
jsEngine.globalObject().setProperty(field->id, field->get_font_name(timecode));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
jsEngine.evaluate(script);
|
||||
*/
|
||||
}
|
||||
|
||||
bool Node::valueHasChanged(double timecode) {
|
||||
if (cachedValues.isEmpty()) {
|
||||
|
||||
for (int i=0;i<row_count();i++) {
|
||||
EffectRow* crow = row(i);
|
||||
for (int j=0;j<crow->FieldCount();j++) {
|
||||
cachedValues.append(crow->Field(j)->GetValueAt(timecode));
|
||||
}
|
||||
}
|
||||
return true;
|
||||
|
||||
} else {
|
||||
|
||||
bool changed = false;
|
||||
int index = 0;
|
||||
for (int i=0;i<row_count();i++) {
|
||||
EffectRow* crow = row(i);
|
||||
for (int j=0;j<crow->FieldCount();j++) {
|
||||
EffectField* field = crow->Field(j);
|
||||
if (cachedValues.at(index) != field->GetValueAt(timecode)) {
|
||||
changed = true;
|
||||
}
|
||||
cachedValues[index] = field->GetValueAt(timecode);
|
||||
index++;
|
||||
}
|
||||
}
|
||||
return changed;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
void Node::delete_texture() {
|
||||
if (texture_ctx != nullptr) {
|
||||
texture_ctx->functions()->glDeleteTextures(1, &texture);
|
||||
texture = 0;
|
||||
texture_ctx = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
int GetNodeLibraryIndexFromId(const QString& id) {
|
||||
for (int i=0;i<olive::node_library.size();i++) {
|
||||
if (olive::node_library.at(i)->id() == id) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
const EffectMeta* Node::GetMetaFromName(const QString& input) {
|
||||
int split_index = input.indexOf('/');
|
||||
QString category;
|
||||
if (split_index > -1) {
|
||||
category = input.left(split_index);
|
||||
}
|
||||
QString name = input.mid(split_index + 1);
|
||||
|
||||
for (int j=0;j<olive::effects.size();j++) {
|
||||
if (olive::effects.at(j).name == name
|
||||
&& (olive::effects.at(j).category == category
|
||||
|| category.isEmpty())) {
|
||||
return &olive::effects.at(j);
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
*/
|
||||
#include "node.h"
|
||||
|
||||
Node::Node(NodeGraph *graph)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
+20
-286
@@ -1,286 +1,20 @@
|
||||
/***
|
||||
|
||||
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 "timeline/tracktypes.h"
|
||||
#include "rendering/qopenglshaderprogramptr.h"
|
||||
#include "inputs.h"
|
||||
#include "effects/effectgizmo.h"
|
||||
|
||||
class EffectGizmo;
|
||||
class KeyframeDataChange;
|
||||
|
||||
class Clip;
|
||||
using ClipPtr = std::shared_ptr<Clip>;
|
||||
|
||||
class Node;
|
||||
using NodePtr = std::shared_ptr<Node>;
|
||||
|
||||
enum NodeType {
|
||||
kTransformEffect,
|
||||
kTextInput,
|
||||
kSolidInput,
|
||||
kNoiseInput,
|
||||
kVolumeEffect,
|
||||
kPanEffect,
|
||||
kToneInput,
|
||||
kShakeEffect,
|
||||
kTimecodeEffect,
|
||||
kMaskEffect,
|
||||
kFillLeftRightEffect,
|
||||
kVstEffect,
|
||||
kCornerPinEffect,
|
||||
kRichTextInput,
|
||||
kMediaInput,
|
||||
kShaderEffect,
|
||||
kImageOutput,
|
||||
kCrossDissolveTransition,
|
||||
kLinearFadeTransition,
|
||||
kExponentialFadeTransition,
|
||||
kLogarithmicFadeTransition,
|
||||
kInvalidNode
|
||||
};
|
||||
|
||||
double log_volume(double linear);
|
||||
|
||||
enum EffectType {
|
||||
EFFECT_TYPE_INVALID,
|
||||
EFFECT_TYPE_EFFECT,
|
||||
EFFECT_TYPE_TRANSITION
|
||||
};
|
||||
|
||||
enum EffectKeyframeType {
|
||||
EFFECT_KEYFRAME_LINEAR,
|
||||
EFFECT_KEYFRAME_BEZIER,
|
||||
EFFECT_KEYFRAME_HOLD
|
||||
};
|
||||
|
||||
struct GLTextureCoords {
|
||||
QMatrix4x4 matrix;
|
||||
|
||||
QVector3D vertex_top_left;
|
||||
QVector3D vertex_top_right;
|
||||
QVector3D vertex_bottom_left;
|
||||
QVector3D vertex_bottom_right;
|
||||
|
||||
QVector2D texture_top_left;
|
||||
QVector2D texture_top_right;
|
||||
QVector2D texture_bottom_left;
|
||||
QVector2D texture_bottom_right;
|
||||
|
||||
float opacity;
|
||||
};
|
||||
|
||||
class Node : public QObject {
|
||||
Q_OBJECT
|
||||
public:
|
||||
Node(Clip *c);
|
||||
~Node();
|
||||
|
||||
Clip* parent_clip;
|
||||
|
||||
virtual QString name() = 0;
|
||||
virtual QString id() = 0;
|
||||
virtual QString category();
|
||||
virtual QString description() = 0;
|
||||
virtual EffectType type() = 0;
|
||||
virtual olive::TrackType subtype() = 0;
|
||||
virtual bool IsCreatable();
|
||||
virtual NodePtr Create(Clip *c) = 0;
|
||||
|
||||
void AddRow(EffectRow* row);
|
||||
int IndexOfRow(EffectRow* row);
|
||||
EffectRow* row(int i);
|
||||
int row_count();
|
||||
|
||||
EffectGizmo* add_gizmo(int type);
|
||||
EffectGizmo* gizmo(int i);
|
||||
int gizmo_count();
|
||||
|
||||
QVector<NodeEdgePtr> GetAllEdges();
|
||||
|
||||
bool IsEnabled();
|
||||
bool IsExpanded();
|
||||
|
||||
virtual void refresh();
|
||||
|
||||
virtual NodePtr copy(Clip* c);
|
||||
void copy_field_keyframes(NodePtr 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_shader_linked();
|
||||
QOpenGLShaderProgram* GetShaderPipeline();
|
||||
|
||||
enum VideoEffectFlags {
|
||||
ShaderFlag = 0x1,
|
||||
CoordsFlag = 0x2,
|
||||
SuperimposeFlag = 0x4
|
||||
};
|
||||
int Flags();
|
||||
void SetFlags(int flags);
|
||||
|
||||
int getIterations();
|
||||
void setIterations(int i);
|
||||
|
||||
const QPointF& pos();
|
||||
|
||||
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(QOpenGLContext *ctx, double timecode);
|
||||
virtual void process_audio(double timecode_start, double timecode_end, float **samples, int nb_samples, int nb_channels, int type);
|
||||
|
||||
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(const QMatrix4x4 &matrix, const QMatrix4x4 &projection);
|
||||
bool are_gizmos_enabled();
|
||||
|
||||
/**
|
||||
* @brief Get the current clip/media time
|
||||
*
|
||||
* A convenience function that can be plugged into GetValueAt() to get the value wherever the appropriate Sequence's
|
||||
* playhead it.
|
||||
*
|
||||
* @return
|
||||
*
|
||||
* Current clip/media time in seconds.
|
||||
*/
|
||||
double Now();
|
||||
|
||||
/**
|
||||
* @brief Retrieve the current clip as a frame number
|
||||
*
|
||||
* Same as Now() but retrieves the value as a frame number (in the appropriate Sequence's frame rate) instead of
|
||||
* seconds.
|
||||
*
|
||||
* @return
|
||||
*
|
||||
* The current clip time in frames
|
||||
*/
|
||||
long NowInFrames();
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
T randomFloat()
|
||||
{
|
||||
static std::random_device device;
|
||||
static std::mt19937 generator(device());
|
||||
static std::uniform_int_distribution<> distribution(-1.0, 1.0);
|
||||
return distribution(generator);
|
||||
}
|
||||
|
||||
public slots:
|
||||
void FieldChanged();
|
||||
void SetEnabled(bool b);
|
||||
void SetExpanded(bool e);
|
||||
void SetPos(const QPointF& pos);
|
||||
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
|
||||
QOpenGLShaderProgramPtr shader_program_;
|
||||
QString shader_vert_path_;
|
||||
QString shader_frag_path_;
|
||||
QString shader_function_name_;
|
||||
|
||||
// superimpose effect
|
||||
QImage img;
|
||||
GLuint texture;
|
||||
QOpenGLContext* texture_ctx;
|
||||
int tex_width_;
|
||||
int tex_height_;
|
||||
|
||||
// enable effect to update constantly
|
||||
virtual bool AlwaysUpdate();
|
||||
|
||||
private:
|
||||
bool isOpen;
|
||||
QVector<EffectRow*> rows;
|
||||
QVector<EffectGizmo*> gizmos;
|
||||
bool bound;
|
||||
int iterations;
|
||||
|
||||
bool enabled_;
|
||||
bool expanded_;
|
||||
|
||||
int flags_;
|
||||
|
||||
QVector<KeyframeDataChange*> gizmo_dragging_actions_;
|
||||
|
||||
QPointF pos_;
|
||||
|
||||
// superimpose functions
|
||||
virtual void redraw(double timecode);
|
||||
bool valueHasChanged(double timecode);
|
||||
QVector<QVariant> cachedValues;
|
||||
void delete_texture();
|
||||
void validate_meta_path();
|
||||
};
|
||||
|
||||
namespace olive {
|
||||
extern QVector<NodePtr> node_library;
|
||||
}
|
||||
|
||||
#endif // EFFECT_H
|
||||
#ifndef NODE_H
|
||||
#define NODE_H
|
||||
|
||||
#include <memory>
|
||||
|
||||
class NodeGraph;
|
||||
|
||||
class Node;
|
||||
using NodePtr = std::shared_ptr<Node>;
|
||||
|
||||
class Node
|
||||
{
|
||||
public:
|
||||
Node(NodeGraph* parent);
|
||||
|
||||
private:
|
||||
NodeGraph* parent_;
|
||||
};
|
||||
|
||||
#endif // NODE_H
|
||||
|
||||
+4
-4
@@ -2,20 +2,20 @@
|
||||
|
||||
#include <QDebug>
|
||||
|
||||
#include "effects/effectrow.h"
|
||||
#include "nodes/nodeio.h"
|
||||
|
||||
NodeEdge::NodeEdge(EffectRow *output, EffectRow *input) :
|
||||
NodeEdge::NodeEdge(NodeIO *output, NodeIO *input) :
|
||||
output_(output),
|
||||
input_(input)
|
||||
{
|
||||
}
|
||||
|
||||
EffectRow *NodeEdge::output()
|
||||
NodeIO *NodeEdge::output()
|
||||
{
|
||||
return output_;
|
||||
}
|
||||
|
||||
EffectRow *NodeEdge::input()
|
||||
NodeIO *NodeEdge::input()
|
||||
{
|
||||
return input_;
|
||||
}
|
||||
|
||||
+6
-6
@@ -3,7 +3,7 @@
|
||||
|
||||
#include <memory>
|
||||
|
||||
class EffectRow;
|
||||
class NodeIO;
|
||||
|
||||
class NodeEdge;
|
||||
using NodeEdgePtr = std::shared_ptr<NodeEdge>;
|
||||
@@ -26,14 +26,14 @@ public:
|
||||
*
|
||||
* Input/to EffectRow that this edge "ends" at
|
||||
*/
|
||||
NodeEdge(EffectRow* output, EffectRow* input);
|
||||
NodeEdge(NodeIO* output, NodeIO* input);
|
||||
|
||||
EffectRow* output();
|
||||
EffectRow* input();
|
||||
NodeIO* output();
|
||||
NodeIO* input();
|
||||
|
||||
private:
|
||||
EffectRow* output_;
|
||||
EffectRow* input_;
|
||||
NodeIO* output_;
|
||||
NodeIO* input_;
|
||||
};
|
||||
|
||||
#endif // NODEEDGE_H
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
#ifndef NODEGRAPH_H
|
||||
#define NODEGRAPH_H
|
||||
|
||||
#include <QVector>
|
||||
|
||||
#include "nodes/node.h"
|
||||
|
||||
class NodeGraph
|
||||
@@ -48,6 +50,8 @@ public:
|
||||
|
||||
private:
|
||||
NodePtr output_node_;
|
||||
|
||||
QVector<NodePtr> nodes_;
|
||||
};
|
||||
|
||||
#endif // NODEGRAPH_H
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
|
||||
***/
|
||||
|
||||
#include "effectrow.h"
|
||||
#include "nodeio.h"
|
||||
|
||||
#include <QHBoxLayout>
|
||||
#include <QPushButton>
|
||||
@@ -32,12 +32,12 @@
|
||||
#include "panels/effectcontrols.h"
|
||||
#include "panels/viewer.h"
|
||||
#include "panels/grapheditor.h"
|
||||
#include "nodes/node.h"
|
||||
#include "nodes/oldeffectnode.h"
|
||||
#include "ui/viewerwidget.h"
|
||||
#include "ui/keyframenavigator.h"
|
||||
#include "ui/clickablelabel.h"
|
||||
|
||||
EffectRow::EffectRow(Node *parent,
|
||||
NodeIO::NodeIO(OldEffectNode *parent,
|
||||
const QString &id,
|
||||
const QString &name,
|
||||
bool savable,
|
||||
@@ -55,7 +55,7 @@ EffectRow::EffectRow(Node *parent,
|
||||
parent->AddRow(this);
|
||||
}
|
||||
|
||||
void EffectRow::AddField(EffectField *field)
|
||||
void NodeIO::AddField(EffectField *field)
|
||||
{
|
||||
field->setParent(this);
|
||||
|
||||
@@ -65,21 +65,21 @@ void EffectRow::AddField(EffectField *field)
|
||||
fields_.append(field);
|
||||
}
|
||||
|
||||
void EffectRow::AddAcceptedNodeInput(olive::nodes::DataType type)
|
||||
void NodeIO::AddAcceptedNodeInput(olive::nodes::DataType type)
|
||||
{
|
||||
Q_ASSERT(output_type_ == olive::nodes::kInvalid);
|
||||
|
||||
accepted_inputs_.append(type);
|
||||
}
|
||||
|
||||
void EffectRow::ConnectEdge(EffectRow *output, EffectRow *input)
|
||||
void NodeIO::ConnectEdge(NodeIO *output, NodeIO *input)
|
||||
{
|
||||
// Make sure one is an output and one is an input
|
||||
Q_ASSERT(output->IsNodeInput() != input->IsNodeInput());
|
||||
|
||||
// Swap them if necessary
|
||||
if (input->IsNodeOutput()) {
|
||||
EffectRow* temp = output;
|
||||
NodeIO* temp = output;
|
||||
output = input;
|
||||
input = temp;
|
||||
}
|
||||
@@ -97,10 +97,10 @@ void EffectRow::ConnectEdge(EffectRow *output, EffectRow *input)
|
||||
emit output->EdgesChanged();
|
||||
}
|
||||
|
||||
void EffectRow::DisconnectEdge(NodeEdgePtr edge)
|
||||
void NodeIO::DisconnectEdge(NodeEdgePtr edge)
|
||||
{
|
||||
EffectRow* output = edge->output();
|
||||
EffectRow* input = edge->input();
|
||||
NodeIO* output = edge->output();
|
||||
NodeIO* input = edge->input();
|
||||
|
||||
output->node_edges_.removeAll(edge);
|
||||
input->node_edges_.removeAll(edge);
|
||||
@@ -108,61 +108,61 @@ void EffectRow::DisconnectEdge(NodeEdgePtr edge)
|
||||
emit output->EdgesChanged();
|
||||
}
|
||||
|
||||
QVector<NodeEdgePtr> EffectRow::edges()
|
||||
QVector<NodeEdgePtr> NodeIO::edges()
|
||||
{
|
||||
return node_edges_;
|
||||
}
|
||||
|
||||
bool EffectRow::IsKeyframing() {
|
||||
bool NodeIO::IsKeyframing() {
|
||||
return keyframing_;
|
||||
}
|
||||
|
||||
void EffectRow::SetKeyframingInternal(bool b) {
|
||||
void NodeIO::SetKeyframingInternal(bool b) {
|
||||
if (GetParentEffect()->type() != EFFECT_TYPE_TRANSITION) {
|
||||
keyframing_ = b;
|
||||
emit KeyframingSetChanged(keyframing_);
|
||||
}
|
||||
}
|
||||
|
||||
bool EffectRow::IsSavable()
|
||||
bool NodeIO::IsSavable()
|
||||
{
|
||||
return savable_;
|
||||
}
|
||||
|
||||
bool EffectRow::IsKeyframable()
|
||||
bool NodeIO::IsKeyframable()
|
||||
{
|
||||
return keyframable_;
|
||||
}
|
||||
|
||||
QVariant EffectRow::GetValueAt(double timecode)
|
||||
QVariant NodeIO::GetValueAt(double timecode)
|
||||
{
|
||||
Q_ASSERT(FieldCount() == 1);
|
||||
|
||||
return Field(0)->GetValueAt(timecode);
|
||||
}
|
||||
|
||||
void EffectRow::SetValueAt(double timecode, const QVariant &value)
|
||||
void NodeIO::SetValueAt(double timecode, const QVariant &value)
|
||||
{
|
||||
Q_ASSERT(FieldCount() == 1);
|
||||
|
||||
Field(0)->SetValueAt(timecode, value);
|
||||
}
|
||||
|
||||
void EffectRow::SetEnabled(bool enabled)
|
||||
void NodeIO::SetEnabled(bool enabled)
|
||||
{
|
||||
for (int i=0;i<FieldCount();i++) {
|
||||
Field(i)->SetEnabled(enabled);
|
||||
}
|
||||
}
|
||||
|
||||
void EffectRow::SetOutputDataType(olive::nodes::DataType type)
|
||||
void NodeIO::SetOutputDataType(olive::nodes::DataType type)
|
||||
{
|
||||
Q_ASSERT(accepted_inputs_.isEmpty());
|
||||
|
||||
output_type_ = type;
|
||||
}
|
||||
|
||||
bool EffectRow::CanAcceptDataType(olive::nodes::DataType type)
|
||||
bool NodeIO::CanAcceptDataType(olive::nodes::DataType type)
|
||||
{
|
||||
if (!IsNodeInput()) {
|
||||
return false;
|
||||
@@ -171,22 +171,22 @@ bool EffectRow::CanAcceptDataType(olive::nodes::DataType type)
|
||||
return accepted_inputs_.contains(type);
|
||||
}
|
||||
|
||||
olive::nodes::DataType EffectRow::OutputDataType()
|
||||
olive::nodes::DataType NodeIO::OutputDataType()
|
||||
{
|
||||
return output_type_;
|
||||
}
|
||||
|
||||
bool EffectRow::IsNodeInput()
|
||||
bool NodeIO::IsNodeInput()
|
||||
{
|
||||
return !accepted_inputs_.isEmpty();
|
||||
}
|
||||
|
||||
bool EffectRow::IsNodeOutput()
|
||||
bool NodeIO::IsNodeOutput()
|
||||
{
|
||||
return output_type_ != olive::nodes::kInvalid;
|
||||
}
|
||||
|
||||
void EffectRow::SetKeyframingEnabled(bool enabled) {
|
||||
void NodeIO::SetKeyframingEnabled(bool enabled) {
|
||||
if (enabled == keyframing_) {
|
||||
return;
|
||||
}
|
||||
@@ -238,7 +238,7 @@ void EffectRow::SetKeyframingEnabled(bool enabled) {
|
||||
}
|
||||
}
|
||||
|
||||
void EffectRow::GoToPreviousKeyframe() {
|
||||
void NodeIO::GoToPreviousKeyframe() {
|
||||
long key = LONG_MIN;
|
||||
Clip* c = GetParentEffect()->parent_clip;
|
||||
long sequence_playhead = c->track()->sequence()->playhead;
|
||||
@@ -266,7 +266,7 @@ void EffectRow::GoToPreviousKeyframe() {
|
||||
if (key != LONG_MIN) panel_sequence_viewer->seek(key);
|
||||
}
|
||||
|
||||
void EffectRow::ToggleKeyframe() {
|
||||
void NodeIO::ToggleKeyframe() {
|
||||
Clip* c = GetParentEffect()->parent_clip;
|
||||
long sequence_playhead = c->track()->sequence()->playhead;
|
||||
|
||||
@@ -336,7 +336,7 @@ void EffectRow::ToggleKeyframe() {
|
||||
update_ui(false);
|
||||
}
|
||||
|
||||
void EffectRow::GoToNextKeyframe() {
|
||||
void NodeIO::GoToNextKeyframe() {
|
||||
long key = LONG_MAX;
|
||||
Clip* c = GetParentEffect()->parent_clip;
|
||||
for (int i=0;i<FieldCount();i++) {
|
||||
@@ -351,11 +351,11 @@ void EffectRow::GoToNextKeyframe() {
|
||||
if (key != LONG_MAX) panel_sequence_viewer->seek(key);
|
||||
}
|
||||
|
||||
void EffectRow::FocusRow() {
|
||||
void NodeIO::FocusRow() {
|
||||
panel_graph_editor->set_row(this);
|
||||
}
|
||||
|
||||
void EffectRow::SetKeyframeOnAllFields(ComboAction* ca) {
|
||||
void NodeIO::SetKeyframeOnAllFields(ComboAction* ca) {
|
||||
for (int i=0;i<FieldCount();i++) {
|
||||
EffectField* field = Field(i);
|
||||
|
||||
@@ -370,19 +370,19 @@ void EffectRow::SetKeyframeOnAllFields(ComboAction* ca) {
|
||||
panel_effect_controls->update_keyframes();
|
||||
}
|
||||
|
||||
Node *EffectRow::GetParentEffect()
|
||||
OldEffectNode *NodeIO::GetParentEffect()
|
||||
{
|
||||
return static_cast<Node*>(parent());
|
||||
return static_cast<OldEffectNode*>(parent());
|
||||
}
|
||||
|
||||
const QString &EffectRow::name() {
|
||||
const QString &NodeIO::name() {
|
||||
return name_;
|
||||
}
|
||||
|
||||
EffectField* EffectRow::Field(int i) {
|
||||
EffectField* NodeIO::Field(int i) {
|
||||
return fields_.at(i);
|
||||
}
|
||||
|
||||
int EffectRow::FieldCount() {
|
||||
int NodeIO::FieldCount() {
|
||||
return fields_.size();
|
||||
}
|
||||
@@ -24,7 +24,7 @@
|
||||
#include <QObject>
|
||||
#include <QVector>
|
||||
|
||||
class Node;
|
||||
class OldEffectNode;
|
||||
class QGridLayout;
|
||||
class EffectField;
|
||||
class QLabel;
|
||||
@@ -34,7 +34,7 @@ class QHBoxLayout;
|
||||
class KeyframeNavigator;
|
||||
class ClickableLabel;
|
||||
|
||||
#include "effectfields.h"
|
||||
#include "effects/effectfields.h"
|
||||
#include "nodes/nodeedge.h"
|
||||
|
||||
/**
|
||||
@@ -49,7 +49,7 @@ class ClickableLabel;
|
||||
* Unlike EffectField, there's no reason to derive from EffectRow as it's simply a container of fields and a few
|
||||
* keyframe functions.
|
||||
*/
|
||||
class EffectRow : public QObject {
|
||||
class NodeIO : public QObject {
|
||||
Q_OBJECT
|
||||
public:
|
||||
|
||||
@@ -84,7 +84,7 @@ public:
|
||||
* Whether keyframing can be enabled on this row or not. This is true by default. Some values you may want to prevent
|
||||
* the user from keyframing (e.g. the filename of a VST plugin), which can be done by setting this to false.
|
||||
*/
|
||||
EffectRow(Node* parent,
|
||||
NodeIO(OldEffectNode* parent,
|
||||
const QString& id,
|
||||
const QString& name,
|
||||
bool savable = true,
|
||||
@@ -127,7 +127,7 @@ public:
|
||||
*
|
||||
* @return The parent Effect object that this row is attached to.
|
||||
*/
|
||||
Node* GetParentEffect();
|
||||
OldEffectNode* GetParentEffect();
|
||||
|
||||
/**
|
||||
* @brief Return the row's name
|
||||
@@ -286,7 +286,7 @@ public:
|
||||
*
|
||||
* The edge to add (output) or replace the current edge (input).
|
||||
*/
|
||||
static void ConnectEdge(EffectRow* output, EffectRow* input);
|
||||
static void ConnectEdge(NodeIO* output, NodeIO* input);
|
||||
|
||||
/**
|
||||
* @brief Disconnect an edge
|
||||
@@ -0,0 +1,7 @@
|
||||
#include "nodeclip.h"
|
||||
|
||||
NodeClip::NodeClip(NodeGraph *graph) :
|
||||
Node(graph)
|
||||
{
|
||||
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
#ifndef NODECLIP_H
|
||||
#define NODECLIP_H
|
||||
|
||||
#include "nodes/node.h"
|
||||
|
||||
class NodeClip : public Node
|
||||
{
|
||||
public:
|
||||
NodeClip(NodeGraph* graph);
|
||||
|
||||
long in();
|
||||
long out();
|
||||
long clip_in();
|
||||
|
||||
void set_in(long in);
|
||||
void set_out(long out);
|
||||
void set_clip_in(long clip_in);
|
||||
|
||||
private:
|
||||
long in_;
|
||||
long out_;
|
||||
long clip_in_;
|
||||
};
|
||||
|
||||
#endif // NODECLIP_H
|
||||
@@ -1,9 +1,9 @@
|
||||
#include "nodeimageoutput.h"
|
||||
|
||||
NodeImageOutput::NodeImageOutput(Clip *c) :
|
||||
Node(c)
|
||||
OldEffectNode(c)
|
||||
{
|
||||
EffectRow* input_texture = new EffectRow(this, "texture", tr("Texture"), true, false);
|
||||
NodeIO* input_texture = new NodeIO(this, "texture", tr("Texture"), true, false);
|
||||
input_texture->AddAcceptedNodeInput(olive::nodes::kTexture);
|
||||
}
|
||||
|
||||
@@ -37,7 +37,7 @@ olive::TrackType NodeImageOutput::subtype()
|
||||
return olive::kTypeVideo;
|
||||
}
|
||||
|
||||
NodePtr NodeImageOutput::Create(Clip *c)
|
||||
OldEffectNodePtr NodeImageOutput::Create(Clip *c)
|
||||
{
|
||||
return std::make_shared<NodeImageOutput>(c);
|
||||
}
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
#ifndef NODEIMAGEOUTPUT_H
|
||||
#define NODEIMAGEOUTPUT_H
|
||||
|
||||
#include "nodes/node.h"
|
||||
#include "nodes/oldeffectnode.h"
|
||||
|
||||
class NodeImageOutput : public Node
|
||||
class NodeImageOutput : public OldEffectNode
|
||||
{
|
||||
public:
|
||||
NodeImageOutput(Clip* c);
|
||||
@@ -14,7 +14,7 @@ public:
|
||||
virtual QString description() override;
|
||||
virtual EffectType type() override;
|
||||
virtual olive::TrackType subtype() override;
|
||||
virtual NodePtr Create(Clip *c) override;
|
||||
virtual OldEffectNodePtr Create(Clip *c) override;
|
||||
};
|
||||
|
||||
#endif // NODEIMAGEOUTPUT_H
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
#include "nodemedia.h"
|
||||
|
||||
NodeMedia::NodeMedia(Clip* c) :
|
||||
Node(c)
|
||||
OldEffectNode(c)
|
||||
{
|
||||
EffectRow* matrix_input = new EffectRow(this, "matrix", tr("Matrix"), true, false);
|
||||
NodeIO* matrix_input = new NodeIO(this, "matrix", tr("Matrix"), true, false);
|
||||
matrix_input->AddAcceptedNodeInput(olive::nodes::kMatrix);
|
||||
|
||||
EffectRow* texture_output = new EffectRow(this, "texture", tr("Texture"), true, false);
|
||||
NodeIO* texture_output = new NodeIO(this, "texture", tr("Texture"), true, false);
|
||||
texture_output->SetOutputDataType(olive::nodes::kTexture);
|
||||
}
|
||||
|
||||
@@ -40,7 +40,7 @@ olive::TrackType NodeMedia::subtype()
|
||||
return olive::kTypeVideo;
|
||||
}
|
||||
|
||||
NodePtr NodeMedia::Create(Clip *c)
|
||||
OldEffectNodePtr NodeMedia::Create(Clip *c)
|
||||
{
|
||||
return std::make_shared<NodeMedia>(c);
|
||||
}
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
#ifndef MEDIANODE_H
|
||||
#define MEDIANODE_H
|
||||
|
||||
#include "nodes/node.h"
|
||||
#include "nodes/oldeffectnode.h"
|
||||
|
||||
class NodeMedia : public Node
|
||||
class NodeMedia : public OldEffectNode
|
||||
{
|
||||
public:
|
||||
NodeMedia(Clip *c);
|
||||
@@ -14,7 +14,7 @@ public:
|
||||
virtual QString description() override;
|
||||
virtual EffectType type() override;
|
||||
virtual olive::TrackType subtype() override;
|
||||
virtual NodePtr Create(Clip *c) override;
|
||||
virtual OldEffectNodePtr Create(Clip *c) override;
|
||||
};
|
||||
|
||||
#endif // MEDIANODE_H
|
||||
|
||||
@@ -5,7 +5,7 @@ NodeShader::NodeShader(Clip* c,
|
||||
const QString &id,
|
||||
const QString &category,
|
||||
const QString &filename) :
|
||||
Node(c),
|
||||
OldEffectNode(c),
|
||||
name_(name),
|
||||
id_(id),
|
||||
category_(category),
|
||||
@@ -39,7 +39,7 @@ NodeShader::NodeShader(Clip* c,
|
||||
if (id.isEmpty() || name.isEmpty() || type == olive::nodes::kInvalid) {
|
||||
qCritical() << "Couldn't load field from" << filename_ << "- ID, type, and name cannot be empty.";
|
||||
} else {
|
||||
EffectRow* field = nullptr;
|
||||
NodeIO* field = nullptr;
|
||||
|
||||
switch (type) {
|
||||
case olive::nodes::kFloat:
|
||||
@@ -215,7 +215,7 @@ bool NodeShader::IsCreatable()
|
||||
return !filename_.isEmpty();
|
||||
}
|
||||
|
||||
NodePtr NodeShader::Create(Clip *)
|
||||
OldEffectNodePtr NodeShader::Create(Clip *)
|
||||
{
|
||||
Q_ASSERT(false);
|
||||
return nullptr;
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
#ifndef NODESHADER_H
|
||||
#define NODESHADER_H
|
||||
|
||||
#include "nodes/node.h"
|
||||
#include "nodes/oldeffectnode.h"
|
||||
|
||||
class NodeShader : public Node {
|
||||
class NodeShader : public OldEffectNode {
|
||||
Q_OBJECT
|
||||
public:
|
||||
NodeShader(Clip *c,
|
||||
@@ -19,7 +19,7 @@ public:
|
||||
virtual EffectType type() override;
|
||||
virtual olive::TrackType subtype() override;
|
||||
virtual bool IsCreatable() override;
|
||||
virtual NodePtr Create(Clip *c) override;
|
||||
virtual OldEffectNodePtr Create(Clip *c) override;
|
||||
|
||||
private:
|
||||
QString name_;
|
||||
|
||||
@@ -0,0 +1,948 @@
|
||||
/***
|
||||
|
||||
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 "oldeffectnode.h"
|
||||
|
||||
#include <QCheckBox>
|
||||
#include <QGridLayout>
|
||||
#include <QXmlStreamReader>
|
||||
#include <QXmlStreamWriter>
|
||||
#include <QMessageBox>
|
||||
#include <QOpenGLContext>
|
||||
#include <QDir>
|
||||
#include <QPainter>
|
||||
#include <QtMath>
|
||||
#include <QMenu>
|
||||
#include <QApplication>
|
||||
#include <QFileDialog>
|
||||
|
||||
#include "panels/panels.h"
|
||||
#include "panels/viewer.h"
|
||||
#include "ui/viewerwidget.h"
|
||||
#include "ui/collapsiblewidget.h"
|
||||
#include "panels/project.h"
|
||||
#include "undo/undo.h"
|
||||
#include "timeline/sequence.h"
|
||||
#include "timeline/clip.h"
|
||||
#include "panels/timeline.h"
|
||||
#include "panels/effectcontrols.h"
|
||||
#include "panels/grapheditor.h"
|
||||
#include "global/debug.h"
|
||||
#include "global/path.h"
|
||||
#include "ui/mainwindow.h"
|
||||
#include "ui/menu.h"
|
||||
#include "global/math.h"
|
||||
#include "global/clipboard.h"
|
||||
#include "global/config.h"
|
||||
#include "effects/transition.h"
|
||||
#include "undo/undostack.h"
|
||||
#include "rendering/shadergenerators.h"
|
||||
#include "global/timing.h"
|
||||
#include "nodes/nodes.h"
|
||||
#include "effects/effectloaders.h"
|
||||
|
||||
QVector<OldEffectNodePtr> olive::node_library;
|
||||
|
||||
OldEffectNode::OldEffectNode(Clip* c) :
|
||||
parent_clip(c),
|
||||
flags_(0),
|
||||
shader_program_(nullptr),
|
||||
texture(0),
|
||||
tex_width_(0),
|
||||
tex_height_(0),
|
||||
isOpen(false),
|
||||
bound(false),
|
||||
iterations(1),
|
||||
enabled_(true),
|
||||
expanded_(true),
|
||||
texture_ctx(nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
OldEffectNode::~OldEffectNode() {
|
||||
if (isOpen) {
|
||||
close();
|
||||
}
|
||||
|
||||
// Clear graph editor if it's using one of these rows
|
||||
if (panel_graph_editor != nullptr) {
|
||||
for (int i=0;i<row_count();i++) {
|
||||
if (row(i) == panel_graph_editor->get_row()) {
|
||||
panel_graph_editor->set_row(nullptr);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
QString OldEffectNode::category()
|
||||
{
|
||||
return QString();
|
||||
}
|
||||
|
||||
QString OldEffectNode::description()
|
||||
{
|
||||
return QString();
|
||||
}
|
||||
|
||||
bool OldEffectNode::IsCreatable()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
void OldEffectNode::AddRow(NodeIO *row)
|
||||
{
|
||||
row->setParent(this);
|
||||
rows.append(row);
|
||||
}
|
||||
|
||||
int OldEffectNode::IndexOfRow(NodeIO *row)
|
||||
{
|
||||
return rows.indexOf(row);
|
||||
}
|
||||
|
||||
void OldEffectNode::copy_field_keyframes(OldEffectNodePtr e) {
|
||||
for (int i=0;i<rows.size();i++) {
|
||||
NodeIO* row = rows.at(i);
|
||||
NodeIO* copy_row = e->rows.at(i);
|
||||
copy_row->SetKeyframingInternal(row->IsKeyframing());
|
||||
for (int j=0;j<row->FieldCount();j++) {
|
||||
// Get field from this (the source) effect
|
||||
EffectField* field = row->Field(j);
|
||||
|
||||
// Get field from the destination effect
|
||||
EffectField* copy_field = copy_row->Field(j);
|
||||
|
||||
// Copy keyframes between effects
|
||||
copy_field->keyframes = field->keyframes;
|
||||
|
||||
// Copy persistet data between effects
|
||||
copy_field->persistent_data_ = field->persistent_data_;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
NodeIO* OldEffectNode::row(int i) {
|
||||
return rows.at(i);
|
||||
}
|
||||
|
||||
int OldEffectNode::row_count() {
|
||||
return rows.size();
|
||||
}
|
||||
|
||||
EffectGizmo *OldEffectNode::add_gizmo(int type) {
|
||||
EffectGizmo* gizmo = new EffectGizmo(this, type);
|
||||
gizmos.append(gizmo);
|
||||
return gizmo;
|
||||
}
|
||||
|
||||
EffectGizmo *OldEffectNode::gizmo(int i) {
|
||||
return gizmos.at(i);
|
||||
}
|
||||
|
||||
int OldEffectNode::gizmo_count() {
|
||||
return gizmos.size();
|
||||
}
|
||||
|
||||
QVector<NodeEdgePtr> OldEffectNode::GetAllEdges()
|
||||
{
|
||||
QVector<NodeEdgePtr> edges;
|
||||
|
||||
for (int i=0;i<row_count();i++) {
|
||||
edges.append(row(i)->edges());
|
||||
}
|
||||
|
||||
return edges;
|
||||
}
|
||||
|
||||
void OldEffectNode::refresh() {}
|
||||
|
||||
void OldEffectNode::FieldChanged() {
|
||||
// Update the UI if a field has been modified, but don't both if this effect is inactive
|
||||
if (parent_clip != nullptr) {
|
||||
update_ui(false);
|
||||
}
|
||||
}
|
||||
|
||||
void OldEffectNode::delete_self() {
|
||||
olive::undo_stack.push(new EffectDeleteCommand(this));
|
||||
update_ui(true);
|
||||
}
|
||||
|
||||
void OldEffectNode::move_up() {
|
||||
int index_of_effect = parent_clip->IndexOfEffect(this);
|
||||
if (index_of_effect == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
MoveEffectCommand* command = new MoveEffectCommand();
|
||||
command->clip = parent_clip;
|
||||
command->from = index_of_effect;
|
||||
command->to = command->from - 1;
|
||||
olive::undo_stack.push(command);
|
||||
panel_effect_controls->Reload();
|
||||
panel_sequence_viewer->viewer_widget()->frame_update();
|
||||
}
|
||||
|
||||
void OldEffectNode::move_down() {
|
||||
int index_of_effect = parent_clip->IndexOfEffect(this);
|
||||
if (index_of_effect == parent_clip->effects.size()-1) {
|
||||
return;
|
||||
}
|
||||
|
||||
MoveEffectCommand* command = new MoveEffectCommand();
|
||||
command->clip = parent_clip;
|
||||
command->from = index_of_effect;
|
||||
command->to = command->from + 1;
|
||||
olive::undo_stack.push(command);
|
||||
panel_effect_controls->Reload();
|
||||
panel_sequence_viewer->viewer_widget()->frame_update();
|
||||
}
|
||||
|
||||
void OldEffectNode::save_to_file() {
|
||||
// save effect settings to file
|
||||
QString file = QFileDialog::getSaveFileName(olive::MainWindow,
|
||||
tr("Save Effect Settings"),
|
||||
QString(),
|
||||
tr("Effect XML Settings %1").arg("(*.xml)"));
|
||||
|
||||
// if the user picked a file
|
||||
if (!file.isEmpty()) {
|
||||
|
||||
// ensure file ends with .xml extension
|
||||
if (!file.endsWith(".xml", Qt::CaseInsensitive)) {
|
||||
file.append(".xml");
|
||||
}
|
||||
|
||||
QFile file_handle(file);
|
||||
if (file_handle.open(QFile::WriteOnly)) {
|
||||
|
||||
file_handle.write(save_to_string());
|
||||
|
||||
file_handle.close();
|
||||
} else {
|
||||
QMessageBox::critical(olive::MainWindow,
|
||||
tr("Save Settings Failed"),
|
||||
tr("Failed to open \"%1\" for writing.").arg(file),
|
||||
QMessageBox::Ok);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void OldEffectNode::load_from_file() {
|
||||
// load effect settings from file
|
||||
QString file = QFileDialog::getOpenFileName(olive::MainWindow,
|
||||
tr("Load Effect Settings"),
|
||||
QString(),
|
||||
tr("Effect XML Settings %1").arg("(*.xml)"));
|
||||
|
||||
// if the user picked a file
|
||||
if (!file.isEmpty()) {
|
||||
QFile file_handle(file);
|
||||
if (file_handle.open(QFile::ReadOnly)) {
|
||||
|
||||
olive::undo_stack.push(new SetEffectData(this, file_handle.readAll()));
|
||||
|
||||
file_handle.close();
|
||||
|
||||
update_ui(false);
|
||||
} else {
|
||||
QMessageBox::critical(olive::MainWindow,
|
||||
tr("Load Settings Failed"),
|
||||
tr("Failed to open \"%1\" for reading.").arg(file),
|
||||
QMessageBox::Ok);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool OldEffectNode::AlwaysUpdate()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool OldEffectNode::IsEnabled() {
|
||||
return enabled_;
|
||||
}
|
||||
|
||||
bool OldEffectNode::IsExpanded()
|
||||
{
|
||||
return expanded_;
|
||||
}
|
||||
|
||||
void OldEffectNode::SetExpanded(bool e)
|
||||
{
|
||||
expanded_ = e;
|
||||
}
|
||||
|
||||
void OldEffectNode::SetPos(const QPointF &pos)
|
||||
{
|
||||
pos_ = pos;
|
||||
}
|
||||
|
||||
void OldEffectNode::SetEnabled(bool b) {
|
||||
enabled_ = b;
|
||||
emit EnabledChanged(b);
|
||||
}
|
||||
|
||||
void OldEffectNode::load(QXmlStreamReader& stream) {
|
||||
/*
|
||||
int row_count = 0;
|
||||
|
||||
QString tag = stream.name().toString();
|
||||
|
||||
while (!stream.atEnd() && !(stream.name() == tag && stream.isEndElement())) {
|
||||
stream.readNext();
|
||||
if (stream.name() == "row" && stream.isStartElement()) {
|
||||
if (row_count < rows.size()) {
|
||||
EffectRow* row = rows.at(row_count);
|
||||
|
||||
while (!stream.atEnd() && !(stream.name() == "row" && stream.isEndElement())) {
|
||||
stream.readNext();
|
||||
|
||||
// read field
|
||||
if (stream.name() == "field" && stream.isStartElement()) {
|
||||
int field_number = -1;
|
||||
|
||||
// match field using ID
|
||||
for (int k=0;k<stream.attributes().size();k++) {
|
||||
const QXmlStreamAttribute& attr = stream.attributes().at(k);
|
||||
if (attr.name() == "id") {
|
||||
for (int l=0;l<row->FieldCount();l++) {
|
||||
if (row->Field(l)->id() == attr.value()) {
|
||||
field_number = l;
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (field_number > -1) {
|
||||
EffectField* field = row->Field(field_number);
|
||||
|
||||
// get current field value
|
||||
for (int k=0;k<stream.attributes().size();k++) {
|
||||
const QXmlStreamAttribute& attr = stream.attributes().at(k);
|
||||
if (attr.name() == "value") {
|
||||
field->persistent_data_ = field->ConvertStringToValue(attr.value().toString());
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
while (!stream.atEnd() && !(stream.name() == "field" && stream.isEndElement())) {
|
||||
stream.readNext();
|
||||
|
||||
// read keyframes
|
||||
if (stream.name() == "key" && stream.isStartElement()) {
|
||||
row->SetKeyframingInternal(true);
|
||||
|
||||
EffectKeyframe key;
|
||||
for (int k=0;k<stream.attributes().size();k++) {
|
||||
const QXmlStreamAttribute& attr = stream.attributes().at(k);
|
||||
if (attr.name() == "value") {
|
||||
key.data = field->ConvertStringToValue(attr.value().toString());
|
||||
} else if (attr.name() == "frame") {
|
||||
key.time = attr.value().toLong();
|
||||
} else if (attr.name() == "type") {
|
||||
key.type = attr.value().toInt();
|
||||
} else if (attr.name() == "prehx") {
|
||||
key.pre_handle_x = attr.value().toDouble();
|
||||
} else if (attr.name() == "prehy") {
|
||||
key.pre_handle_y = attr.value().toDouble();
|
||||
} else if (attr.name() == "posthx") {
|
||||
key.post_handle_x = attr.value().toDouble();
|
||||
} else if (attr.name() == "posthy") {
|
||||
key.post_handle_y = attr.value().toDouble();
|
||||
}
|
||||
}
|
||||
field->keyframes.append(key);
|
||||
}
|
||||
}
|
||||
|
||||
field->Changed();
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
qCritical() << "Too many rows for effect" << id << ". Project might be corrupt. (Got" << row_count << ", expected <" << rows.size()-1 << ")";
|
||||
}
|
||||
row_count++;
|
||||
} else if (stream.isStartElement()) {
|
||||
custom_load(stream);
|
||||
}
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
void OldEffectNode::custom_load(QXmlStreamReader &) {}
|
||||
|
||||
void OldEffectNode::save(QXmlStreamWriter& stream) {
|
||||
/*
|
||||
stream.writeAttribute("name", meta->category + "/" + meta->name);
|
||||
stream.writeAttribute("enabled", QString::number(IsEnabled()));
|
||||
|
||||
for (int i=0;i<rows.size();i++) {
|
||||
EffectRow* row = rows.at(i);
|
||||
if (row->IsSavable()) {
|
||||
stream.writeStartElement("row"); // row
|
||||
for (int j=0;j<row->FieldCount();j++) {
|
||||
EffectField* field = row->Field(j);
|
||||
|
||||
if (!field->id().isEmpty()) {
|
||||
stream.writeStartElement("field"); // field
|
||||
stream.writeAttribute("id", field->id());
|
||||
stream.writeAttribute("value", field->ConvertValueToString(field->persistent_data_));
|
||||
for (int k=0;k<field->keyframes.size();k++) {
|
||||
const EffectKeyframe& key = field->keyframes.at(k);
|
||||
stream.writeStartElement("key");
|
||||
stream.writeAttribute("value", field->ConvertValueToString(key.data));
|
||||
stream.writeAttribute("frame", QString::number(key.time));
|
||||
stream.writeAttribute("type", QString::number(key.type));
|
||||
stream.writeAttribute("prehx", QString::number(key.pre_handle_x));
|
||||
stream.writeAttribute("prehy", QString::number(key.pre_handle_y));
|
||||
stream.writeAttribute("posthx", QString::number(key.post_handle_x));
|
||||
stream.writeAttribute("posthy", QString::number(key.post_handle_y));
|
||||
stream.writeEndElement(); // key
|
||||
}
|
||||
stream.writeEndElement(); // field
|
||||
}
|
||||
}
|
||||
stream.writeEndElement(); // row
|
||||
}
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
void OldEffectNode::load_from_string(const QByteArray &s) {
|
||||
// clear existing keyframe data
|
||||
for (int i=0;i<rows.size();i++) {
|
||||
NodeIO* row = rows.at(i);
|
||||
row->SetKeyframingInternal(false);
|
||||
for (int j=0;j<row->FieldCount();j++) {
|
||||
EffectField* field = row->Field(j);
|
||||
field->keyframes.clear();
|
||||
}
|
||||
}
|
||||
|
||||
// write settings with xml writer
|
||||
QXmlStreamReader stream(s);
|
||||
|
||||
bool found_id = false;
|
||||
|
||||
while (!stream.atEnd()) {
|
||||
stream.readNext();
|
||||
|
||||
// find the effect opening tag
|
||||
if (stream.name() == "effect" && stream.isStartElement()) {
|
||||
|
||||
// check the name to see if it matches this effect
|
||||
const QXmlStreamAttributes& attributes = stream.attributes();
|
||||
for (int i=0;i<attributes.size();i++) {
|
||||
const QXmlStreamAttribute& attr = attributes.at(i);
|
||||
if (attr.name() == "id") {
|
||||
load(stream);
|
||||
found_id = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// we've found what we're looking for
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!found_id) {
|
||||
QMessageBox::critical(olive::MainWindow,
|
||||
tr("Load Settings Failed"),
|
||||
tr("This settings file doesn't match this effect."),
|
||||
QMessageBox::Ok);
|
||||
}
|
||||
}
|
||||
|
||||
QByteArray OldEffectNode::save_to_string() {
|
||||
QByteArray save_data;
|
||||
|
||||
// write settings to string with xml writer
|
||||
QXmlStreamWriter stream(&save_data);
|
||||
|
||||
stream.writeStartDocument();
|
||||
|
||||
stream.writeStartElement("effect");
|
||||
|
||||
// pass off to standard saving function
|
||||
save(stream);
|
||||
|
||||
stream.writeEndElement(); // effect
|
||||
|
||||
stream.writeEndDocument();
|
||||
|
||||
return save_data;
|
||||
}
|
||||
|
||||
bool OldEffectNode::is_open() {
|
||||
return isOpen;
|
||||
}
|
||||
|
||||
void OldEffectNode::validate_meta_path() {
|
||||
/*
|
||||
if (!meta->path.isEmpty() || (shader_vert_path_.isEmpty() && shader_frag_path_.isEmpty())) return;
|
||||
QList<QString> effects_paths = get_effects_paths();
|
||||
const QString& test_fn = shader_vert_path_.isEmpty() ? shader_frag_path_ : shader_vert_path_;
|
||||
for (int i=0;i<effects_paths.size();i++) {
|
||||
if (QFileInfo::exists(effects_paths.at(i) + "/" + test_fn)) {
|
||||
for (int j=0;j<olive::effects.size();j++) {
|
||||
if (&olive::effects.at(j) == meta) {
|
||||
olive::effects[j].path = effects_paths.at(i);
|
||||
return;
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
void OldEffectNode::open() {
|
||||
/*
|
||||
if (isOpen) {
|
||||
qWarning() << "Tried to open an effect that was already open";
|
||||
close();
|
||||
}
|
||||
if (olive::runtime_config.shaders_are_enabled && (Flags() & ShaderFlag)) {
|
||||
if (QOpenGLContext::currentContext() == nullptr) {
|
||||
qWarning() << "No current context to create a shader program for - will retry next repaint";
|
||||
} else {
|
||||
validate_meta_path();
|
||||
|
||||
QString frag_shader_str;
|
||||
QString frag_file_url = QDir(file).filePath(shader_frag_path_);
|
||||
QFile frag_file(frag_file_url);
|
||||
if (frag_file.open(QFile::ReadOnly)) {
|
||||
frag_shader_str = frag_file.readAll();
|
||||
frag_file.close();
|
||||
} else {
|
||||
qWarning() << "Failed to open" << frag_file_url;
|
||||
}
|
||||
|
||||
if (!frag_shader_str.isEmpty()) {
|
||||
|
||||
QString shader_func;
|
||||
|
||||
if (!shader_function_name_.isEmpty()) {
|
||||
shader_func = shader_function_name_;
|
||||
} else {
|
||||
shader_func = "process";
|
||||
}
|
||||
|
||||
shader_program_ = olive::shader::GetPipeline(shader_func, frag_shader_str);
|
||||
|
||||
}
|
||||
isOpen = true;
|
||||
}
|
||||
} else {
|
||||
isOpen = true;
|
||||
}
|
||||
*/
|
||||
isOpen = true;
|
||||
}
|
||||
|
||||
void OldEffectNode::close() {
|
||||
if (!isOpen) {
|
||||
qWarning() << "Tried to close an effect that was already closed";
|
||||
}
|
||||
delete_texture();
|
||||
shader_program_ = nullptr;
|
||||
isOpen = false;
|
||||
}
|
||||
|
||||
bool OldEffectNode::is_shader_linked() {
|
||||
return shader_program_ != nullptr && shader_program_->isLinked();
|
||||
}
|
||||
|
||||
QOpenGLShaderProgram *OldEffectNode::GetShaderPipeline()
|
||||
{
|
||||
return shader_program_.get();
|
||||
}
|
||||
|
||||
int OldEffectNode::Flags()
|
||||
{
|
||||
return flags_;
|
||||
}
|
||||
|
||||
void OldEffectNode::SetFlags(int flags)
|
||||
{
|
||||
flags_ = flags;
|
||||
}
|
||||
|
||||
int OldEffectNode::getIterations() {
|
||||
return iterations;
|
||||
}
|
||||
|
||||
void OldEffectNode::setIterations(int i) {
|
||||
iterations = i;
|
||||
}
|
||||
|
||||
const QPointF &OldEffectNode::pos()
|
||||
{
|
||||
return pos_;
|
||||
}
|
||||
|
||||
void OldEffectNode::process_image(double, uint8_t *, uint8_t *, int){}
|
||||
|
||||
OldEffectNodePtr OldEffectNode::copy(Clip *c) {
|
||||
OldEffectNodePtr copy = Create(c);
|
||||
copy->SetEnabled(IsEnabled());
|
||||
copy_field_keyframes(copy);
|
||||
return copy;
|
||||
}
|
||||
|
||||
void OldEffectNode::process_shader(double timecode, GLTextureCoords&, int iteration) {
|
||||
/*
|
||||
shader_program_->bind();
|
||||
|
||||
shader_program_->setUniformValue("resolution", parent_clip->media_width(), parent_clip->media_height());
|
||||
shader_program_->setUniformValue("time", GLfloat(timecode));
|
||||
shader_program_->setUniformValue("iteration", iteration);
|
||||
|
||||
for (int i=0;i<rows.size();i++) {
|
||||
EffectRow* row = rows.at(i);
|
||||
|
||||
for (int j=0;j<row->FieldCount();j++) {
|
||||
EffectField* field = row->Field(j);
|
||||
if (!field->id().isEmpty()) {
|
||||
switch (field->type()) {
|
||||
case EffectField::EFFECT_FIELD_DOUBLE:
|
||||
{
|
||||
DoubleField* double_field = static_cast<DoubleField*>(field);
|
||||
shader_program_->setUniformValue(double_field->id().toUtf8().constData(),
|
||||
GLfloat(double_field->GetDoubleAt(timecode)));
|
||||
}
|
||||
break;
|
||||
case EffectField::EFFECT_FIELD_COLOR:
|
||||
{
|
||||
ColorField* color_field = static_cast<ColorField *>(field);
|
||||
shader_program_->setUniformValue(
|
||||
color_field->id().toUtf8().constData(),
|
||||
GLfloat(color_field->GetColorAt(timecode).redF()),
|
||||
GLfloat(color_field->GetColorAt(timecode).greenF()),
|
||||
GLfloat(color_field->GetColorAt(timecode).blueF())
|
||||
);
|
||||
}
|
||||
break;
|
||||
case EffectField::EFFECT_FIELD_BOOL:
|
||||
shader_program_->setUniformValue(field->id().toUtf8().constData(), field->GetValueAt(timecode).toBool());
|
||||
break;
|
||||
case EffectField::EFFECT_FIELD_COMBO:
|
||||
shader_program_->setUniformValue(field->id().toUtf8().constData(), field->GetValueAt(timecode).toInt());
|
||||
break;
|
||||
|
||||
// can you even send a string to a uniform value?
|
||||
case EffectField::EFFECT_FIELD_STRING:
|
||||
case EffectField::EFFECT_FIELD_FONT:
|
||||
case EffectField::EFFECT_FIELD_FILE:
|
||||
case EffectField::EFFECT_FIELD_UI:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
shader_program_->release();
|
||||
*/
|
||||
}
|
||||
|
||||
void OldEffectNode::process_coords(double, GLTextureCoords&, int) {}
|
||||
|
||||
GLuint OldEffectNode::process_superimpose(QOpenGLContext* ctx, double timecode) {
|
||||
bool dimensions_changed = false;
|
||||
bool redrew_image = false;
|
||||
|
||||
int width = parent_clip->media_width();
|
||||
int height = parent_clip->media_height();
|
||||
|
||||
if (width != img.width() || height != img.height()) {
|
||||
img = QImage(width, height, QImage::Format_RGBA8888_Premultiplied);
|
||||
dimensions_changed = true;
|
||||
}
|
||||
|
||||
if (valueHasChanged(timecode) || dimensions_changed || AlwaysUpdate()) {
|
||||
redraw(timecode);
|
||||
redrew_image = true;
|
||||
}
|
||||
|
||||
QOpenGLFunctions* f = ctx->functions();
|
||||
|
||||
if (texture == 0 || tex_width_ != img.width() || tex_height_ != img.height()) {
|
||||
delete_texture();
|
||||
|
||||
tex_width_ = img.width();
|
||||
tex_height_ = img.height();
|
||||
|
||||
// create texture object
|
||||
f->glGenTextures(1, &texture);
|
||||
|
||||
f->glBindTexture(GL_TEXTURE_2D, texture);
|
||||
|
||||
// set texture filtering to bilinear
|
||||
f->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
f->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
|
||||
f->glTexImage2D(
|
||||
GL_TEXTURE_2D, 0, GL_RGBA8, tex_width_, tex_height_, 0, GL_RGBA, GL_UNSIGNED_BYTE, img.constBits()
|
||||
);
|
||||
|
||||
f->glBindTexture(GL_TEXTURE_2D, 0);
|
||||
|
||||
redrew_image = false;
|
||||
}
|
||||
|
||||
if (redrew_image) {
|
||||
f->glBindTexture(GL_TEXTURE_2D, texture);
|
||||
|
||||
f->glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, tex_width_, tex_height_, GL_RGBA, GL_UNSIGNED_BYTE, img.constBits());
|
||||
|
||||
f->glBindTexture(GL_TEXTURE_2D, 0);
|
||||
}
|
||||
|
||||
return texture;
|
||||
}
|
||||
|
||||
void OldEffectNode::process_audio(double, double, float **, int, int, int) {}
|
||||
|
||||
void OldEffectNode::gizmo_draw(double, GLTextureCoords &) {}
|
||||
|
||||
void OldEffectNode::gizmo_move(EffectGizmo* gizmo, int x_movement, int y_movement, double timecode, bool done) {
|
||||
// Loop through each gizmo to find `gizmo`
|
||||
for (int i=0;i<gizmos.size();i++) {
|
||||
|
||||
if (gizmos.at(i) == gizmo) {
|
||||
|
||||
// If (!done && gizmo_dragging_actions_.isEmpty()), that means the drag just started and we're going to save
|
||||
// the current state of the attach fields' keyframes in KeyframeDataChange objects to make the changes undoable
|
||||
// by the user later.
|
||||
if (!done && gizmo_dragging_actions_.isEmpty()) {
|
||||
if (gizmo->x_field1 != nullptr) {
|
||||
gizmo_dragging_actions_.append(new KeyframeDataChange(gizmo->x_field1));
|
||||
}
|
||||
if (gizmo->y_field1 != nullptr) {
|
||||
gizmo_dragging_actions_.append(new KeyframeDataChange(gizmo->y_field1));
|
||||
}
|
||||
if (gizmo->x_field2 != nullptr) {
|
||||
gizmo_dragging_actions_.append(new KeyframeDataChange(gizmo->x_field2));
|
||||
}
|
||||
if (gizmo->y_field2 != nullptr) {
|
||||
gizmo_dragging_actions_.append(new KeyframeDataChange(gizmo->y_field2));
|
||||
}
|
||||
}
|
||||
|
||||
// Update the field values
|
||||
if (gizmo->x_field1 != nullptr) {
|
||||
gizmo->x_field1->SetValueAt(timecode,
|
||||
gizmo->x_field1->GetDoubleAt(timecode) + x_movement*gizmo->x_field_multi1);
|
||||
}
|
||||
if (gizmo->y_field1 != nullptr) {
|
||||
gizmo->y_field1->SetValueAt(timecode,
|
||||
gizmo->y_field1->GetDoubleAt(timecode) + y_movement*gizmo->y_field_multi1);
|
||||
}
|
||||
if (gizmo->x_field2 != nullptr) {
|
||||
gizmo->x_field2->SetValueAt(timecode,
|
||||
gizmo->x_field2->GetDoubleAt(timecode) + x_movement*gizmo->x_field_multi2);
|
||||
}
|
||||
if (gizmo->y_field2 != nullptr) {
|
||||
gizmo->y_field2->SetValueAt(timecode,
|
||||
gizmo->y_field2->GetDoubleAt(timecode) + y_movement*gizmo->y_field_multi2);
|
||||
}
|
||||
|
||||
// If (done && !gizmo_dragging_actions_.isEmpty()), that means the drag just ended and we're going to save
|
||||
// the new state of the attach fields' keyframes in KeyframeDataChange objects to make the changes undoable
|
||||
// by the user later.
|
||||
if (done && !gizmo_dragging_actions_.isEmpty()) {
|
||||
|
||||
// Store all the KeyframeDataChange objects into a ComboAction to send to the undo stack (makes them all
|
||||
// undoable together rather than having to be undone individually).
|
||||
ComboAction* ca = new ComboAction();
|
||||
|
||||
for (int j=0;j<gizmo_dragging_actions_.size();j++) {
|
||||
// Set the current state of the keyframes as the "new" keyframes (the old values were set earlier when the
|
||||
// KeyframeDataChange object was constructed).
|
||||
gizmo_dragging_actions_.at(j)->SetNewKeyframes();
|
||||
|
||||
// Add this KeyframeDataChange object to the ComboAction
|
||||
ca->append(gizmo_dragging_actions_.at(j));
|
||||
}
|
||||
|
||||
olive::undo_stack.push(ca);
|
||||
|
||||
gizmo_dragging_actions_.clear();
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void OldEffectNode::gizmo_world_to_screen(const QMatrix4x4& matrix, const QMatrix4x4& projection) {
|
||||
for (int i=0;i<gizmos.size();i++) {
|
||||
EffectGizmo* g = gizmos.at(i);
|
||||
|
||||
for (int j=0;j<g->get_point_count();j++) {
|
||||
|
||||
// Convert the world point from the gizmo into a screen point relative to the sequence's dimensions
|
||||
|
||||
QVector3D screen_pos = g->world_pos.at(j).project(matrix,
|
||||
projection,
|
||||
QRect(0,
|
||||
0,
|
||||
parent_clip->track()->sequence()->width,
|
||||
parent_clip->track()->sequence()->height));
|
||||
|
||||
g->screen_pos[j] = QPoint(screen_pos.x(), parent_clip->track()->sequence()->height-screen_pos.y());
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool OldEffectNode::are_gizmos_enabled() {
|
||||
return (gizmos.size() > 0);
|
||||
}
|
||||
|
||||
double OldEffectNode::Now()
|
||||
{
|
||||
return playhead_to_clip_seconds(parent_clip, parent_clip->track()->sequence()->playhead);
|
||||
}
|
||||
|
||||
long OldEffectNode::NowInFrames()
|
||||
{
|
||||
return playhead_to_clip_frame(parent_clip, parent_clip->track()->sequence()->playhead);
|
||||
}
|
||||
|
||||
void OldEffectNode::redraw(double) {
|
||||
/*
|
||||
// run javascript
|
||||
QPainter p(&img);
|
||||
painter_wrapper.img = &img;
|
||||
painter_wrapper.painter = &p;
|
||||
|
||||
jsEngine.globalObject().setProperty("painter", wrapper_obj);
|
||||
jsEngine.globalObject().setProperty("width", parent_clip->media_width());
|
||||
jsEngine.globalObject().setProperty("height", parent_clip->media_height());
|
||||
|
||||
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);
|
||||
if (!field->id.isEmpty()) {
|
||||
switch (field->type) {
|
||||
case EffectField::EFFECT_FIELD_DOUBLE:
|
||||
jsEngine.globalObject().setProperty(field->id, field->get_double_value(timecode));
|
||||
break;
|
||||
case EffectField::EFFECT_FIELD_COLOR:
|
||||
jsEngine.globalObject().setProperty(field->id, field->get_color_value(timecode).name());
|
||||
break;
|
||||
case EffectField::EFFECT_FIELD_STRING:
|
||||
jsEngine.globalObject().setProperty(field->id, field->get_string_value(timecode));
|
||||
break;
|
||||
case EffectField::EFFECT_FIELD_BOOL:
|
||||
jsEngine.globalObject().setProperty(field->id, field->get_bool_value(timecode));
|
||||
break;
|
||||
case EffectField::EFFECT_FIELD_COMBO:
|
||||
jsEngine.globalObject().setProperty(field->id, field->get_combo_index(timecode));
|
||||
break;
|
||||
case EffectField::EFFECT_FIELD_FONT:
|
||||
jsEngine.globalObject().setProperty(field->id, field->get_font_name(timecode));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
jsEngine.evaluate(script);
|
||||
*/
|
||||
}
|
||||
|
||||
bool OldEffectNode::valueHasChanged(double timecode) {
|
||||
if (cachedValues.isEmpty()) {
|
||||
|
||||
for (int i=0;i<row_count();i++) {
|
||||
NodeIO* crow = row(i);
|
||||
for (int j=0;j<crow->FieldCount();j++) {
|
||||
cachedValues.append(crow->Field(j)->GetValueAt(timecode));
|
||||
}
|
||||
}
|
||||
return true;
|
||||
|
||||
} else {
|
||||
|
||||
bool changed = false;
|
||||
int index = 0;
|
||||
for (int i=0;i<row_count();i++) {
|
||||
NodeIO* crow = row(i);
|
||||
for (int j=0;j<crow->FieldCount();j++) {
|
||||
EffectField* field = crow->Field(j);
|
||||
if (cachedValues.at(index) != field->GetValueAt(timecode)) {
|
||||
changed = true;
|
||||
}
|
||||
cachedValues[index] = field->GetValueAt(timecode);
|
||||
index++;
|
||||
}
|
||||
}
|
||||
return changed;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
void OldEffectNode::delete_texture() {
|
||||
if (texture_ctx != nullptr) {
|
||||
texture_ctx->functions()->glDeleteTextures(1, &texture);
|
||||
texture = 0;
|
||||
texture_ctx = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
int GetNodeLibraryIndexFromId(const QString& id) {
|
||||
for (int i=0;i<olive::node_library.size();i++) {
|
||||
if (olive::node_library.at(i)->id() == id) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
const EffectMeta* Node::GetMetaFromName(const QString& input) {
|
||||
int split_index = input.indexOf('/');
|
||||
QString category;
|
||||
if (split_index > -1) {
|
||||
category = input.left(split_index);
|
||||
}
|
||||
QString name = input.mid(split_index + 1);
|
||||
|
||||
for (int j=0;j<olive::effects.size();j++) {
|
||||
if (olive::effects.at(j).name == name
|
||||
&& (olive::effects.at(j).category == category
|
||||
|| category.isEmpty())) {
|
||||
return &olive::effects.at(j);
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
*/
|
||||
@@ -0,0 +1,286 @@
|
||||
/***
|
||||
|
||||
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 "timeline/tracktypes.h"
|
||||
#include "rendering/qopenglshaderprogramptr.h"
|
||||
#include "inputs.h"
|
||||
#include "effects/effectgizmo.h"
|
||||
|
||||
class EffectGizmo;
|
||||
class KeyframeDataChange;
|
||||
|
||||
class Clip;
|
||||
using ClipPtr = std::shared_ptr<Clip>;
|
||||
|
||||
class OldEffectNode;
|
||||
using OldEffectNodePtr = std::shared_ptr<OldEffectNode>;
|
||||
|
||||
enum NodeType {
|
||||
kTransformEffect,
|
||||
kTextInput,
|
||||
kSolidInput,
|
||||
kNoiseInput,
|
||||
kVolumeEffect,
|
||||
kPanEffect,
|
||||
kToneInput,
|
||||
kShakeEffect,
|
||||
kTimecodeEffect,
|
||||
kMaskEffect,
|
||||
kFillLeftRightEffect,
|
||||
kVstEffect,
|
||||
kCornerPinEffect,
|
||||
kRichTextInput,
|
||||
kMediaInput,
|
||||
kShaderEffect,
|
||||
kImageOutput,
|
||||
kCrossDissolveTransition,
|
||||
kLinearFadeTransition,
|
||||
kExponentialFadeTransition,
|
||||
kLogarithmicFadeTransition,
|
||||
kInvalidNode
|
||||
};
|
||||
|
||||
double log_volume(double linear);
|
||||
|
||||
enum EffectType {
|
||||
EFFECT_TYPE_INVALID,
|
||||
EFFECT_TYPE_EFFECT,
|
||||
EFFECT_TYPE_TRANSITION
|
||||
};
|
||||
|
||||
enum EffectKeyframeType {
|
||||
EFFECT_KEYFRAME_LINEAR,
|
||||
EFFECT_KEYFRAME_BEZIER,
|
||||
EFFECT_KEYFRAME_HOLD
|
||||
};
|
||||
|
||||
struct GLTextureCoords {
|
||||
QMatrix4x4 matrix;
|
||||
|
||||
QVector3D vertex_top_left;
|
||||
QVector3D vertex_top_right;
|
||||
QVector3D vertex_bottom_left;
|
||||
QVector3D vertex_bottom_right;
|
||||
|
||||
QVector2D texture_top_left;
|
||||
QVector2D texture_top_right;
|
||||
QVector2D texture_bottom_left;
|
||||
QVector2D texture_bottom_right;
|
||||
|
||||
float opacity;
|
||||
};
|
||||
|
||||
class OldEffectNode : public QObject {
|
||||
Q_OBJECT
|
||||
public:
|
||||
OldEffectNode(Clip *c);
|
||||
~OldEffectNode();
|
||||
|
||||
Clip* parent_clip;
|
||||
|
||||
virtual QString name() = 0;
|
||||
virtual QString id() = 0;
|
||||
virtual QString category();
|
||||
virtual QString description();
|
||||
virtual EffectType type() = 0;
|
||||
virtual olive::TrackType subtype() = 0;
|
||||
virtual bool IsCreatable();
|
||||
virtual OldEffectNodePtr Create(Clip *c) = 0;
|
||||
|
||||
void AddRow(NodeIO* row);
|
||||
int IndexOfRow(NodeIO* row);
|
||||
NodeIO* row(int i);
|
||||
int row_count();
|
||||
|
||||
EffectGizmo* add_gizmo(int type);
|
||||
EffectGizmo* gizmo(int i);
|
||||
int gizmo_count();
|
||||
|
||||
QVector<NodeEdgePtr> GetAllEdges();
|
||||
|
||||
bool IsEnabled();
|
||||
bool IsExpanded();
|
||||
|
||||
virtual void refresh();
|
||||
|
||||
virtual OldEffectNodePtr copy(Clip* c);
|
||||
void copy_field_keyframes(OldEffectNodePtr 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_shader_linked();
|
||||
QOpenGLShaderProgram* GetShaderPipeline();
|
||||
|
||||
enum VideoEffectFlags {
|
||||
ShaderFlag = 0x1,
|
||||
CoordsFlag = 0x2,
|
||||
SuperimposeFlag = 0x4
|
||||
};
|
||||
int Flags();
|
||||
void SetFlags(int flags);
|
||||
|
||||
int getIterations();
|
||||
void setIterations(int i);
|
||||
|
||||
const QPointF& pos();
|
||||
|
||||
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(QOpenGLContext *ctx, double timecode);
|
||||
virtual void process_audio(double timecode_start, double timecode_end, float **samples, int nb_samples, int nb_channels, int type);
|
||||
|
||||
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(const QMatrix4x4 &matrix, const QMatrix4x4 &projection);
|
||||
bool are_gizmos_enabled();
|
||||
|
||||
/**
|
||||
* @brief Get the current clip/media time
|
||||
*
|
||||
* A convenience function that can be plugged into GetValueAt() to get the value wherever the appropriate Sequence's
|
||||
* playhead it.
|
||||
*
|
||||
* @return
|
||||
*
|
||||
* Current clip/media time in seconds.
|
||||
*/
|
||||
double Now();
|
||||
|
||||
/**
|
||||
* @brief Retrieve the current clip as a frame number
|
||||
*
|
||||
* Same as Now() but retrieves the value as a frame number (in the appropriate Sequence's frame rate) instead of
|
||||
* seconds.
|
||||
*
|
||||
* @return
|
||||
*
|
||||
* The current clip time in frames
|
||||
*/
|
||||
long NowInFrames();
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
T randomFloat()
|
||||
{
|
||||
static std::random_device device;
|
||||
static std::mt19937 generator(device());
|
||||
static std::uniform_int_distribution<> distribution(-1.0, 1.0);
|
||||
return distribution(generator);
|
||||
}
|
||||
|
||||
public slots:
|
||||
void FieldChanged();
|
||||
void SetEnabled(bool b);
|
||||
void SetExpanded(bool e);
|
||||
void SetPos(const QPointF& pos);
|
||||
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
|
||||
QOpenGLShaderProgramPtr shader_program_;
|
||||
QString shader_vert_path_;
|
||||
QString shader_frag_path_;
|
||||
QString shader_function_name_;
|
||||
|
||||
// superimpose effect
|
||||
QImage img;
|
||||
GLuint texture;
|
||||
QOpenGLContext* texture_ctx;
|
||||
int tex_width_;
|
||||
int tex_height_;
|
||||
|
||||
// enable effect to update constantly
|
||||
virtual bool AlwaysUpdate();
|
||||
|
||||
private:
|
||||
bool isOpen;
|
||||
QVector<NodeIO*> rows;
|
||||
QVector<EffectGizmo*> gizmos;
|
||||
bool bound;
|
||||
int iterations;
|
||||
|
||||
bool enabled_;
|
||||
bool expanded_;
|
||||
|
||||
int flags_;
|
||||
|
||||
QVector<KeyframeDataChange*> gizmo_dragging_actions_;
|
||||
|
||||
QPointF pos_;
|
||||
|
||||
// superimpose functions
|
||||
virtual void redraw(double timecode);
|
||||
bool valueHasChanged(double timecode);
|
||||
QVector<QVariant> cachedValues;
|
||||
void delete_texture();
|
||||
void validate_meta_path();
|
||||
};
|
||||
|
||||
namespace olive {
|
||||
extern QVector<OldEffectNodePtr> node_library;
|
||||
}
|
||||
|
||||
#endif // EFFECT_H
|
||||
@@ -1,7 +1,7 @@
|
||||
#include "buttonwidget.h"
|
||||
|
||||
ButtonWidget::ButtonWidget(Node* parent, const QString& name, const QString& text) :
|
||||
EffectRow(parent, nullptr, name, false, false)
|
||||
ButtonWidget::ButtonWidget(OldEffectNode* parent, const QString& name, const QString& text) :
|
||||
NodeIO(parent, nullptr, name, false, false)
|
||||
{
|
||||
ButtonField* button_field = new ButtonField(this, text);
|
||||
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
#ifndef BUTTONWIDGET_H
|
||||
#define BUTTONWIDGET_H
|
||||
|
||||
#include "effects/effectrow.h"
|
||||
#include "nodes/nodeio.h"
|
||||
|
||||
class ButtonWidget : public EffectRow
|
||||
class ButtonWidget : public NodeIO
|
||||
{
|
||||
public:
|
||||
ButtonWidget(Node* parent, const QString& name, const QString& text);
|
||||
ButtonWidget(OldEffectNode* parent, const QString& name, const QString& text);
|
||||
|
||||
/**
|
||||
* @brief Wrapper for ButtonField::SetCheckable.
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#include "labelwidget.h"
|
||||
|
||||
LabelWidget::LabelWidget(Node *parent, const QString &name, const QString &text) :
|
||||
EffectRow(parent, nullptr, name, false, false)
|
||||
LabelWidget::LabelWidget(OldEffectNode *parent, const QString &name, const QString &text) :
|
||||
NodeIO(parent, nullptr, name, false, false)
|
||||
{
|
||||
AddField(new LabelField(this, text));
|
||||
}
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
#ifndef LABELWIDGET_H
|
||||
#define LABELWIDGET_H
|
||||
|
||||
#include "effects/effectrow.h"
|
||||
#include "nodes/nodeio.h"
|
||||
|
||||
class LabelWidget : public EffectRow
|
||||
class LabelWidget : public NodeIO
|
||||
{
|
||||
public:
|
||||
LabelWidget(Node* parent, const QString& name, const QString& text);
|
||||
LabelWidget(OldEffectNode* parent, const QString& name, const QString& text);
|
||||
};
|
||||
|
||||
#endif // LABELWIDGET_H
|
||||
|
||||
@@ -52,6 +52,10 @@ gcc:QMAKE_CXXFLAGS += -Wno-reorder
|
||||
|
||||
SOURCES += \
|
||||
main.cpp \
|
||||
nodes/node.cpp \
|
||||
nodes/nodeio.cpp \
|
||||
nodes/nodes/nodeclip.cpp \
|
||||
nodes/oldeffectnode.cpp \
|
||||
ui/mainwindow.cpp \
|
||||
panels/project.cpp \
|
||||
panels/effectcontrols.cpp \
|
||||
@@ -106,7 +110,6 @@ SOURCES += \
|
||||
effects/internal/logarithmicfadetransition.cpp \
|
||||
effects/internal/cornerpineffect.cpp \
|
||||
global/math.cpp \
|
||||
effects/effectrow.cpp \
|
||||
effects/effectgizmo.cpp \
|
||||
ui/resizablescrollbar.cpp \
|
||||
ui/sourceiconview.cpp \
|
||||
@@ -206,11 +209,14 @@ SOURCES += \
|
||||
nodes/nodes/nodeshader.cpp \
|
||||
decoders/ffmpegdecoder.cpp \
|
||||
decoders/decoder.cpp \
|
||||
nodes/node.cpp \
|
||||
nodes/nodeedge.cpp \
|
||||
ui/nodeedgeui.cpp
|
||||
|
||||
HEADERS += \
|
||||
nodes/node.h \
|
||||
nodes/nodeio.h \
|
||||
nodes/nodes/nodeclip.h \
|
||||
nodes/oldeffectnode.h \
|
||||
ui/mainwindow.h \
|
||||
panels/project.h \
|
||||
panels/effectcontrols.h \
|
||||
@@ -266,7 +272,6 @@ HEADERS += \
|
||||
effects/internal/logarithmicfadetransition.h \
|
||||
effects/internal/cornerpineffect.h \
|
||||
global/math.h \
|
||||
effects/effectrow.h \
|
||||
effects/internal/cubetransition.h \
|
||||
effects/effectgizmo.h \
|
||||
ui/resizablescrollbar.h \
|
||||
@@ -371,7 +376,6 @@ HEADERS += \
|
||||
nodes/nodes.h \
|
||||
decoders/ffmpegdecoder.h \
|
||||
decoders/decoder.h \
|
||||
nodes/node.h \
|
||||
timeline/tracktypes.h \
|
||||
nodes/nodeedge.h \
|
||||
ui/nodeedgeui.h
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user