diff --git a/dialogs/autocutsilencedialog.cpp b/dialogs/autocutsilencedialog.cpp index 3659cde2c..e5176bcb2 100644 --- a/dialogs/autocutsilencedialog.cpp +++ b/dialogs/autocutsilencedialog.cpp @@ -127,7 +127,7 @@ void AutoCutSilenceDialog::cut_silence() { Clip* clip = clips_.at(j); // Check if this clip is an audio footage clip - if (clip->type() == Track::kTypeAudio + if (clip->type() == olive::kTypeAudio && clip->media() != nullptr && clip->media_stream()->preview_done) { // TODO provide warning for preview not being done diff --git a/dialogs/speeddialog.cpp b/dialogs/speeddialog.cpp index b1482e2eb..9b7cad23e 100644 --- a/dialogs/speeddialog.cpp +++ b/dialogs/speeddialog.cpp @@ -33,7 +33,7 @@ #include "panels/timeline.h" #include "undo/undo.h" #include "undo/undostack.h" -#include "effects/effect.h" +#include "nodes/node.h" #include "project/media.h" SpeedDialog::SpeedDialog(QWidget *parent, QVector clips) : QDialog(parent) { @@ -103,7 +103,7 @@ int SpeedDialog::exec() { // get default frame rate/percentage clip_percent = c->speed().value; - if (c->type() == Track::kTypeVideo) { + if (c->type() == olive::kTypeVideo) { bool process_video = true; if (c->media() != nullptr && c->media()->get_type() == MEDIA_TYPE_FOOTAGE) { FootageStream* ms = c->media_stream(); @@ -131,7 +131,7 @@ int SpeedDialog::exec() { enable_frame_rate = true; } - } else if (c->type() == Track::kTypeAudio) { + } else if (c->type() == olive::kTypeAudio) { maintain_pitch->setEnabled(true); if (!multiple_audio) { @@ -192,7 +192,7 @@ void SpeedDialog::percent_update() { Clip* c = clips_.at(i); // get frame rate - if (frame_rate->isEnabled() && c->type() == Track::kTypeVideo) { + if (frame_rate->isEnabled() && c->type() == olive::kTypeVideo) { double clip_fr = c->media_frame_rate() * percent->value(); if (got_fr) { if (!qIsNaN(fr_val) && !qFuzzyCompare(fr_val, clip_fr)) { @@ -236,7 +236,7 @@ void SpeedDialog::duration_update() { } // get frame rate - if (frame_rate->isEnabled() && c->type() == Track::kTypeVideo) { + if (frame_rate->isEnabled() && c->type() == olive::kTypeVideo) { double clip_fr = c->media_frame_rate() * clip_pc; if (got_fr) { if (!qIsNaN(fr_val) && !qFuzzyCompare(fr_val, clip_fr)) { @@ -276,7 +276,7 @@ void SpeedDialog::frame_rate_update() { old_pc_val = qSNaN(); } - if (c->type() == Track::kTypeVideo) { + if (c->type() == olive::kTypeVideo) { // what would the new speed be based on this frame rate double new_clip_speed = frame_rate->value() / c->media_frame_rate(); if (!got_pc_val) { @@ -301,7 +301,7 @@ void SpeedDialog::frame_rate_update() { for (int i=0;itype() == Track::kTypeAudio) { + if (c->type() == olive::kTypeAudio) { long new_clip_len = (qIsNaN(old_pc_val) || qIsNaN(pc_val)) ? c->length() : qRound((c->length() * c->speed().value) / pc_val); @@ -376,7 +376,7 @@ void SpeedDialog::accept() { } // set maintain audio pitch if the user made a selection - if (c->type() == Track::kTypeAudio + if (c->type() == olive::kTypeAudio && maintain_pitch->checkState() != Qt::PartiallyChecked && c->speed().maintain_audio_pitch != maintain_pitch->isChecked()) { audio_pitch_action->AddSetting(c, maintain_pitch->isChecked()); @@ -418,7 +418,7 @@ void SpeedDialog::accept() { if (i > 0 && !qFuzzyCompare(cached_speed, c->speed().value)) { can_change_all = false; } - if (c->type() == Track::kTypeVideo) { + if (c->type() == olive::kTypeVideo) { if (qIsNaN(cached_fr)) { cached_fr = c->media_frame_rate(); } else if (!qFuzzyCompare(cached_fr, c->media_frame_rate())) { @@ -431,7 +431,7 @@ void SpeedDialog::accept() { // make changes for (int i=0;itype() == Track::kTypeVideo) { + if (c->type() == olive::kTypeVideo) { set_speed(ca, c, frame_rate->value() / c->media_frame_rate(), ripple->isChecked(), earliest_point, longest_ripple); } else if (can_change_all) { set_speed(ca, c, frame_rate->value() / cached_fr, ripple->isChecked(), earliest_point, longest_ripple); diff --git a/effects/effectfield.cpp b/effects/effectfield.cpp index c636e3a61..5968d7577 100644 --- a/effects/effectfield.cpp +++ b/effects/effectfield.cpp @@ -27,7 +27,7 @@ #include "global/config.h" #include "global/timing.h" #include "effects/effectrow.h" -#include "effects/effect.h" +#include "nodes/node.h" #include "undo/undo.h" #include "timeline/clip.h" #include "timeline/sequence.h" diff --git a/effects/effectfield.h b/effects/effectfield.h index 890a5fed8..e72e3d685 100644 --- a/effects/effectfield.h +++ b/effects/effectfield.h @@ -26,7 +26,6 @@ #include #include "effects/keyframe.h" -#include "undo/undo.h" #include "undo/undostack.h" #include "nodes/nodedatatypes.h" diff --git a/effects/effectgizmo.cpp b/effects/effectgizmo.cpp index cac508a4a..db810016c 100644 --- a/effects/effectgizmo.cpp +++ b/effects/effectgizmo.cpp @@ -22,9 +22,9 @@ #include "ui/labelslider.h" #include "effects/fields/doublefield.h" -#include "effects/effect.h" +#include "nodes/node.h" -EffectGizmo::EffectGizmo(Effect *parent, int type) : +EffectGizmo::EffectGizmo(Node *parent, int type) : QObject(parent), x_field1(nullptr), x_field_multi1(1.0), diff --git a/effects/effectgizmo.h b/effects/effectgizmo.h index 371b5aea9..aea73fcf2 100644 --- a/effects/effectgizmo.h +++ b/effects/effectgizmo.h @@ -39,12 +39,12 @@ enum GizmoType { #include class DoubleField; -class Effect; +class Node; class EffectGizmo : public QObject { Q_OBJECT public: - EffectGizmo(Effect* parent, int type); + EffectGizmo(Node* parent, int type); QVector world_pos; QVector screen_pos; diff --git a/effects/effectloaders.cpp b/effects/effectloaders.cpp index ebb840fbd..ae04cce81 100644 --- a/effects/effectloaders.cpp +++ b/effects/effectloaders.cpp @@ -24,13 +24,36 @@ #include #include -#include "effects/effect.h" +#include "nodes/node.h" #include "effects/transition.h" #include "global/path.h" #include "panels/panels.h" #include "panels/effectcontrols.h" #include "global/config.h" +#include "effects/internal/transformeffect.h" +#include "effects/internal/texteffect.h" +#include "effects/internal/timecodeeffect.h" +#include "effects/internal/solideffect.h" +#include "effects/internal/audionoiseeffect.h" +#include "effects/internal/toneeffect.h" +#include "effects/internal/volumeeffect.h" +#include "effects/internal/paneffect.h" +#include "effects/internal/shakeeffect.h" +#include "effects/internal/cornerpineffect.h" +#include "effects/internal/vsthost.h" +#include "effects/internal/fillleftrighteffect.h" +#include "effects/internal/richtexteffect.h" + +#include "effects/internal/crossdissolvetransition.h" +#include "effects/internal/linearfadetransition.h" +#include "effects/internal/logarithmicfadetransition.h" +#include "effects/internal/exponentialfadetransition.h" + +#include "nodes/nodes/nodemedia.h" +#include "nodes/nodes/nodeimageoutput.h" +#include "nodes/nodes/nodeshader.h" + QMutex olive::effects_loaded; void load_internal_effects() { @@ -38,103 +61,35 @@ void load_internal_effects() { qWarning() << "Shaders are disabled, some effects may be nonfunctional"; } - EffectMeta em; + olive::node_library.resize(kInvalidNode); + olive::node_library.fill(nullptr); - // load internal effects - em.path = ":/internalshaders"; - - em.type = EFFECT_TYPE_EFFECT; - em.subtype = Track::kTypeAudio; - - em.name = "Volume"; - em.internal = EFFECT_INTERNAL_VOLUME; - olive::effects.append(em); - - em.name = "Pan"; - em.internal = EFFECT_INTERNAL_PAN; - olive::effects.append(em); - - em.name = "VST Plugin 2.x"; - em.internal = EFFECT_INTERNAL_VST; - olive::effects.append(em); - - em.name = "Tone"; - em.internal = EFFECT_INTERNAL_TONE; - olive::effects.append(em); - - em.name = "Noise"; - em.internal = EFFECT_INTERNAL_NOISE; - olive::effects.append(em); - - em.name = "Fill Left/Right"; - em.internal = EFFECT_INTERNAL_FILLLEFTRIGHT; - olive::effects.append(em); - - em.subtype = Track::kTypeVideo; - - em.name = "Transform"; - em.category = "Distort"; - em.internal = EFFECT_INTERNAL_TRANSFORM; - olive::effects.append(em); - - em.name = "Corner Pin"; - em.internal = EFFECT_INTERNAL_CORNERPIN; - olive::effects.append(em); - - /*em.name = "Mask"; - em.internal = EFFECT_INTERNAL_MASK; - olive::effects.append(em);*/ - - em.name = "Shake"; - em.internal = EFFECT_INTERNAL_SHAKE; - olive::effects.append(em); - - em.name = "Text"; - em.category = "Render"; - em.internal = EFFECT_INTERNAL_TEXT; - olive::effects.append(em); - - em.name = "Rich Text"; - em.category = "Render"; - em.internal = EFFECT_INTERNAL_RICHTEXT; - olive::effects.append(em); - - em.name = "Timecode"; - em.internal = EFFECT_INTERNAL_TIMECODE; - olive::effects.append(em); - - em.name = "Solid"; - em.internal = EFFECT_INTERNAL_SOLID; - olive::effects.append(em); - - // internal transitions - em.type = EFFECT_TYPE_TRANSITION; - em.category = ""; - - em.name = "Cross Dissolve"; - em.internal = TRANSITION_INTERNAL_CROSSDISSOLVE; - olive::effects.append(em); - - em.subtype = Track::kTypeAudio; - - em.name = "Linear Fade"; - em.internal = TRANSITION_INTERNAL_LINEARFADE; - olive::effects.append(em); - - em.name = "Exponential Fade"; - em.internal = TRANSITION_INTERNAL_EXPONENTIALFADE; - olive::effects.append(em); - - em.name = "Logarithmic Fade"; - em.internal = TRANSITION_INTERNAL_LOGARITHMICFADE; - olive::effects.append(em); + olive::node_library[kTransformEffect] = std::make_shared(nullptr); + olive::node_library[kTextInput] = std::make_shared(nullptr); + olive::node_library[kSolidInput] = std::make_shared(nullptr); + olive::node_library[kNoiseInput] = std::make_shared(nullptr); + olive::node_library[kVolumeEffect] = std::make_shared(nullptr); + olive::node_library[kPanEffect] = std::make_shared(nullptr); + olive::node_library[kToneInput] = std::make_shared(nullptr); + olive::node_library[kShakeEffect] = std::make_shared(nullptr); + olive::node_library[kTimecodeEffect] = std::make_shared(nullptr); + olive::node_library[kFillLeftRightEffect] = std::make_shared(nullptr); + olive::node_library[kVstEffect] = std::make_shared(nullptr); + olive::node_library[kCornerPinEffect] = std::make_shared(nullptr); + olive::node_library[kRichTextInput] = std::make_shared(nullptr); + olive::node_library[kMediaInput] = std::make_shared(nullptr); + olive::node_library[kImageOutput] = std::make_shared(nullptr); + olive::node_library[kCrossDissolveTransition] = std::make_shared(nullptr); + olive::node_library[kLinearFadeTransition] = std::make_shared(nullptr); + olive::node_library[kExponentialFadeTransition] = std::make_shared(nullptr); + olive::node_library[kLogarithmicFadeTransition] = std::make_shared(nullptr); } void load_shader_effects_worker(const QString& effects_path) { QDir effects_dir(effects_path); if (effects_dir.exists()) { - QList entries = effects_dir.entryList({"*.xml", "*.blend"}, + QList entries = effects_dir.entryList({"*.xml"}, QDir::AllDirs | QDir::Files | QDir::NoDotAndDotDot); for (int i=0;i blend_mode_entries = effects_dir.entryList(QStringList("*.blend"), QDir::Files); - for (int i=0;i(nullptr, + effect_name, + effect_id, + effect_cat, + file_url)); + } else { + qCritical() << "Invalid effect found in" << entries.at(i); + } + break; + } + reader.readNext(); + } + + file.close(); } } } diff --git a/effects/effectrow.cpp b/effects/effectrow.cpp index b96349cc0..7e2abaa7c 100644 --- a/effects/effectrow.cpp +++ b/effects/effectrow.cpp @@ -32,12 +32,12 @@ #include "panels/effectcontrols.h" #include "panels/viewer.h" #include "panels/grapheditor.h" -#include "effect.h" +#include "nodes/node.h" #include "ui/viewerwidget.h" #include "ui/keyframenavigator.h" #include "ui/clickablelabel.h" -EffectRow::EffectRow(Effect *parent, +EffectRow::EffectRow(Node *parent, const QString &id, const QString &name, bool savable, @@ -77,7 +77,7 @@ bool EffectRow::IsKeyframing() { } void EffectRow::SetKeyframingInternal(bool b) { - if (GetParentEffect()->meta->type != EFFECT_TYPE_TRANSITION) { + if (GetParentEffect()->type() != EFFECT_TYPE_TRANSITION) { keyframing_ = b; emit KeyframingSetChanged(keyframing_); } @@ -315,9 +315,9 @@ void EffectRow::SetKeyframeOnAllFields(ComboAction* ca) { panel_effect_controls->update_keyframes(); } -Effect *EffectRow::GetParentEffect() +Node *EffectRow::GetParentEffect() { - return static_cast(parent()); + return static_cast(parent()); } const QString &EffectRow::name() { diff --git a/effects/effectrow.h b/effects/effectrow.h index 1afc6dfa4..cbdf2256b 100644 --- a/effects/effectrow.h +++ b/effects/effectrow.h @@ -24,7 +24,7 @@ #include #include -class Effect; +class Node; class QGridLayout; class EffectField; class QLabel; @@ -83,7 +83,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(Effect* parent, + EffectRow(Node* parent, const QString& id, const QString& name, bool savable = true, @@ -126,7 +126,7 @@ public: * * @return The parent Effect object that this row is attached to. */ - Effect* GetParentEffect(); + Node* GetParentEffect(); /** * @brief Return the row's name diff --git a/effects/fields/boolfield.cpp b/effects/fields/boolfield.cpp index f706bc08a..ac3be8ea6 100644 --- a/effects/fields/boolfield.cpp +++ b/effects/fields/boolfield.cpp @@ -22,7 +22,8 @@ #include -#include "effects/effect.h" +#include "nodes/node.h" +#include "undo/undo.h" BoolField::BoolField(EffectRow *parent) : EffectField(parent, EffectField::EFFECT_FIELD_BOOL) diff --git a/effects/fields/colorfield.cpp b/effects/fields/colorfield.cpp index 1797681a4..5702b4582 100644 --- a/effects/fields/colorfield.cpp +++ b/effects/fields/colorfield.cpp @@ -23,7 +23,8 @@ #include #include "ui/colorbutton.h" -#include "effects/effect.h" +#include "nodes/node.h" +#include "undo/undo.h" ColorField::ColorField(EffectRow* parent) : EffectField(parent, EffectField::EFFECT_FIELD_COLOR) diff --git a/effects/fields/combofield.cpp b/effects/fields/combofield.cpp index 7471f7e16..c9542a000 100644 --- a/effects/fields/combofield.cpp +++ b/effects/fields/combofield.cpp @@ -22,8 +22,9 @@ #include -#include "effects/effect.h" +#include "nodes/node.h" #include "ui/comboboxex.h" +#include "undo/undo.h" ComboField::ComboField(EffectRow* parent) : EffectField(parent, EffectField::EFFECT_FIELD_COMBO) diff --git a/effects/fields/doublefield.cpp b/effects/fields/doublefield.cpp index 9f70bf033..14ef3ec15 100644 --- a/effects/fields/doublefield.cpp +++ b/effects/fields/doublefield.cpp @@ -20,7 +20,8 @@ #include "doublefield.h" -#include "effects/effect.h" +#include "nodes/node.h" +#include "undo/undo.h" DoubleField::DoubleField(EffectRow* parent) : EffectField(parent, EffectField::EFFECT_FIELD_DOUBLE), diff --git a/effects/fields/doublefield.h b/effects/fields/doublefield.h index 7c1b962e2..11734244e 100644 --- a/effects/fields/doublefield.h +++ b/effects/fields/doublefield.h @@ -24,6 +24,8 @@ #include "../effectfield.h" #include "ui/labelslider.h" +class KeyframeDataChange; + /** * @brief The DoubleField class * diff --git a/effects/fields/filefield.cpp b/effects/fields/filefield.cpp index b38a035c4..cc7f7a244 100644 --- a/effects/fields/filefield.cpp +++ b/effects/fields/filefield.cpp @@ -23,7 +23,8 @@ #include #include "ui/embeddedfilechooser.h" -#include "effects/effect.h" +#include "nodes/node.h" +#include "undo/undo.h" FileField::FileField(EffectRow* parent) : EffectField(parent, EffectField::EFFECT_FIELD_FILE) diff --git a/effects/fields/fontfield.cpp b/effects/fields/fontfield.cpp index 7738f9bc5..24e51615a 100644 --- a/effects/fields/fontfield.cpp +++ b/effects/fields/fontfield.cpp @@ -24,7 +24,8 @@ #include #include "ui/comboboxex.h" -#include "effects/effect.h" +#include "nodes/node.h" +#include "undo/undo.h" // NOTE/TODO: This shares a lot of similarity with ComboInput, and could probably be a derived class of it diff --git a/effects/fields/stringfield.cpp b/effects/fields/stringfield.cpp index 6c2720113..6da53cd93 100644 --- a/effects/fields/stringfield.cpp +++ b/effects/fields/stringfield.cpp @@ -23,9 +23,10 @@ #include #include -#include "effects/effect.h" +#include "nodes/node.h" #include "ui/texteditex.h" #include "global/config.h" +#include "undo/undo.h" StringField::StringField(EffectRow* parent, bool rich_text) : EffectField(parent, EffectField::EFFECT_FIELD_STRING), diff --git a/effects/internal/audionoiseeffect.cpp b/effects/internal/audionoiseeffect.cpp index a1323c0f6..128921978 100644 --- a/effects/internal/audionoiseeffect.cpp +++ b/effects/internal/audionoiseeffect.cpp @@ -23,7 +23,7 @@ #include #include -AudioNoiseEffect::AudioNoiseEffect(Clip* c, const EffectMeta *em) : Effect(c, em) { +AudioNoiseEffect::AudioNoiseEffect(Clip* c) : Node(c) { amount_val = new DoubleInput(this, "amount", tr("Amount")); amount_val->SetMinimum(0); amount_val->SetDefault(20); @@ -33,6 +33,36 @@ AudioNoiseEffect::AudioNoiseEffect(Clip* c, const EffectMeta *em) : Effect(c, em mix_val->SetValueAt(0, true); } +QString AudioNoiseEffect::name() +{ + return tr("Noise"); +} + +QString AudioNoiseEffect::id() +{ + return "org.olivevideoeditor.Olive.noise"; +} + +QString AudioNoiseEffect::description() +{ + return tr("Generate audio noise that can be mixed with this clip."); +} + +EffectType AudioNoiseEffect::type() +{ + return EFFECT_TYPE_EFFECT; +} + +olive::TrackType AudioNoiseEffect::subtype() +{ + return olive::kTypeAudio; +} + +NodePtr AudioNoiseEffect::Create(Clip *c) +{ + return std::make_shared(c); +} + void AudioNoiseEffect::process_audio(double timecode_start, double timecode_end, float **samples, diff --git a/effects/internal/audionoiseeffect.h b/effects/internal/audionoiseeffect.h index 4e1c173ad..d950080b5 100644 --- a/effects/internal/audionoiseeffect.h +++ b/effects/internal/audionoiseeffect.h @@ -21,12 +21,20 @@ #ifndef AUDIONOISEEFFECT_H #define AUDIONOISEEFFECT_H -#include "effects/effect.h" +#include "nodes/node.h" -class AudioNoiseEffect : public Effect { +class AudioNoiseEffect : public Node { Q_OBJECT public: - AudioNoiseEffect(Clip* c, const EffectMeta* em); + AudioNoiseEffect(Clip* c); + + virtual QString name() override; + virtual QString id() override; + virtual QString description() override; + virtual EffectType type() override; + virtual olive::TrackType subtype() override; + virtual NodePtr Create(Clip *c) override; + virtual void process_audio(double timecode_start, double timecode_end, float **samples, diff --git a/effects/internal/cornerpineffect.cpp b/effects/internal/cornerpineffect.cpp index 14bd4f4ba..2e5f93281 100644 --- a/effects/internal/cornerpineffect.cpp +++ b/effects/internal/cornerpineffect.cpp @@ -24,8 +24,8 @@ #include "timeline/clip.h" #include "global/debug.h" -CornerPinEffect::CornerPinEffect(Clip* c, const EffectMeta *em) : Effect(c, em) { - SetFlags(Effect::CoordsFlag | Effect::ShaderFlag); +CornerPinEffect::CornerPinEffect(Clip* c) : Node(c) { + SetFlags(Node::CoordsFlag | Node::ShaderFlag); top_left = new Vec2Input(this, "topleft", tr("Top Left")); @@ -58,6 +58,41 @@ CornerPinEffect::CornerPinEffect(Clip* c, const EffectMeta *em) : Effect(c, em) shader_frag_path_ = "cornerpin.frag"; } +QString CornerPinEffect::name() +{ + return tr("Corner Pin"); +} + +QString CornerPinEffect::id() +{ + return "org.olivevideoeditor.Olive.cornerpin"; +} + +QString CornerPinEffect::category() +{ + return tr("Distort"); +} + +QString CornerPinEffect::description() +{ + return tr("Distort/warp this clip by pinning each of its four corners."); +} + +EffectType CornerPinEffect::type() +{ + return EFFECT_TYPE_EFFECT; +} + +olive::TrackType CornerPinEffect::subtype() +{ + return olive::kTypeVideo; +} + +NodePtr CornerPinEffect::Create(Clip *c) +{ + return std::make_shared(c); +} + void CornerPinEffect::process_coords(double timecode, GLTextureCoords &coords, int) { coords.vertex_top_left += top_left->GetVector2DAt(timecode); coords.vertex_top_right += top_right->GetVector2DAt(timecode); diff --git a/effects/internal/cornerpineffect.h b/effects/internal/cornerpineffect.h index 573164254..9226d7c40 100644 --- a/effects/internal/cornerpineffect.h +++ b/effects/internal/cornerpineffect.h @@ -21,12 +21,21 @@ #ifndef CORNERPINEFFECT_H #define CORNERPINEFFECT_H -#include "effects/effect.h" +#include "nodes/node.h" -class CornerPinEffect : public Effect { +class CornerPinEffect : public Node { Q_OBJECT public: - CornerPinEffect(Clip* c, const EffectMeta* em); + CornerPinEffect(Clip* c); + + virtual QString name() override; + virtual QString id() override; + virtual QString category() override; + virtual QString description() override; + virtual EffectType type() override; + virtual olive::TrackType subtype() override; + virtual NodePtr Create(Clip *c) override; + void process_coords(double timecode, GLTextureCoords& coords, int data); void process_shader(double timecode, GLTextureCoords& coords, int iterations); void gizmo_draw(double timecode, GLTextureCoords& coords); diff --git a/effects/internal/crossdissolvetransition.cpp b/effects/internal/crossdissolvetransition.cpp index c5c35f12c..dc895acea 100644 --- a/effects/internal/crossdissolvetransition.cpp +++ b/effects/internal/crossdissolvetransition.cpp @@ -22,8 +22,43 @@ #include -CrossDissolveTransition::CrossDissolveTransition(Clip* c, Clip* s, const EffectMeta* em) : Transition(c, s, em) { - SetFlags(Effect::CoordsFlag); +CrossDissolveTransition::CrossDissolveTransition(Clip* c) : Transition(c) { + SetFlags(Node::CoordsFlag); +} + +QString CrossDissolveTransition::name() +{ + return tr("Cross Dissolve"); +} + +QString CrossDissolveTransition::id() +{ + return "org.olivevideoeditor.Olive.crossdissolve"; +} + +QString CrossDissolveTransition::category() +{ + return tr("Dissolves"); +} + +QString CrossDissolveTransition::description() +{ + return tr("Dissolve clips evenly."); +} + +EffectType CrossDissolveTransition::type() +{ + return EFFECT_TYPE_TRANSITION; +} + +olive::TrackType CrossDissolveTransition::subtype() +{ + return olive::kTypeVideo; +} + +NodePtr CrossDissolveTransition::Create(Clip *c) +{ + return std::make_shared(c); } void CrossDissolveTransition::process_coords(double progress, GLTextureCoords& coords, int data) { diff --git a/effects/internal/crossdissolvetransition.h b/effects/internal/crossdissolvetransition.h index 42afc7b93..153665def 100644 --- a/effects/internal/crossdissolvetransition.h +++ b/effects/internal/crossdissolvetransition.h @@ -25,8 +25,17 @@ class CrossDissolveTransition : public Transition { public: - CrossDissolveTransition(Clip *c, Clip *s, const EffectMeta* em); - void process_coords(double timecode, GLTextureCoords &, int data); + CrossDissolveTransition(Clip *c); + + virtual QString name() override; + virtual QString id() override; + virtual QString category() override; + virtual QString description() override; + virtual EffectType type() override; + virtual olive::TrackType subtype() override; + virtual NodePtr Create(Clip *c) override; + + virtual void process_coords(double timecode, GLTextureCoords &, int data) override; }; #endif // CROSSDISSOLVETRANSITION_H diff --git a/effects/internal/cubetransition.h b/effects/internal/cubetransition.h index a2c4da552..b1dbe0607 100644 --- a/effects/internal/cubetransition.h +++ b/effects/internal/cubetransition.h @@ -25,7 +25,7 @@ class CubeTransition : public Transition { public: - CubeTransition(Clip* c, Clip* s, const EffectMeta* em); + CubeTransition(Clip* c, Clip* s); void process_coords(double timecode, GLTextureCoords &, int data); }; diff --git a/effects/internal/exponentialfadetransition.cpp b/effects/internal/exponentialfadetransition.cpp index 292384b4d..8c5aae400 100644 --- a/effects/internal/exponentialfadetransition.cpp +++ b/effects/internal/exponentialfadetransition.cpp @@ -22,7 +22,40 @@ #include -ExponentialFadeTransition::ExponentialFadeTransition(Clip* c, Clip* s, const EffectMeta* em) : Transition(c, s, em) {} +ExponentialFadeTransition::ExponentialFadeTransition(Clip* c) : + Transition(c) +{ +} + +QString ExponentialFadeTransition::name() +{ + return tr("Exponential Fade"); +} + +QString ExponentialFadeTransition::id() +{ + return "org.olivevideoeditor.Olive.exponentialfade"; +} + +QString ExponentialFadeTransition::description() +{ + return tr("An exponential audio fade that starts slow and ends fast."); +} + +EffectType ExponentialFadeTransition::type() +{ + return EFFECT_TYPE_TRANSITION; +} + +olive::TrackType ExponentialFadeTransition::subtype() +{ + return olive::kTypeAudio; +} + +NodePtr ExponentialFadeTransition::Create(Clip *c) +{ + return std::make_shared(c); +} void ExponentialFadeTransition::process_audio(double timecode_start, double timecode_end, diff --git a/effects/internal/exponentialfadetransition.h b/effects/internal/exponentialfadetransition.h index a9201f5dc..19e326a06 100644 --- a/effects/internal/exponentialfadetransition.h +++ b/effects/internal/exponentialfadetransition.h @@ -25,7 +25,15 @@ class ExponentialFadeTransition : public Transition { public: - ExponentialFadeTransition(Clip* c, Clip* s, const EffectMeta* em); + ExponentialFadeTransition(Clip* c); + + virtual QString name() override; + virtual QString id() override; + virtual QString description() override; + virtual EffectType type() override; + virtual olive::TrackType subtype() override; + virtual NodePtr Create(Clip *c) override; + virtual void process_audio(double timecode_start, double timecode_end, float **samples, diff --git a/effects/internal/fillleftrighteffect.cpp b/effects/internal/fillleftrighteffect.cpp index bbc04285e..141583124 100644 --- a/effects/internal/fillleftrighteffect.cpp +++ b/effects/internal/fillleftrighteffect.cpp @@ -25,12 +25,42 @@ enum FillType { FILL_TYPE_RIGHT }; -FillLeftRightEffect::FillLeftRightEffect(Clip* c, const EffectMeta *em) : Effect(c, em) { +FillLeftRightEffect::FillLeftRightEffect(Clip* c) : Node(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); } +QString FillLeftRightEffect::name() +{ + return tr("Fill Left/Right"); +} + +QString FillLeftRightEffect::id() +{ + return "org.olivevideoeditor.Olive.fillleftright"; +} + +QString FillLeftRightEffect::description() +{ + return tr("Replaces either the left or right channel with the other"); +} + +EffectType FillLeftRightEffect::type() +{ + return EFFECT_TYPE_EFFECT; +} + +olive::TrackType FillLeftRightEffect::subtype() +{ + return olive::kTypeAudio; +} + +NodePtr FillLeftRightEffect::Create(Clip *c) +{ + return std::make_shared(c); +} + void FillLeftRightEffect::process_audio(double timecode_start, double timecode_end, float **samples, diff --git a/effects/internal/fillleftrighteffect.h b/effects/internal/fillleftrighteffect.h index a80ae0227..1acd1de54 100644 --- a/effects/internal/fillleftrighteffect.h +++ b/effects/internal/fillleftrighteffect.h @@ -21,12 +21,20 @@ #ifndef FILLLEFTRIGHTEFFECT_H #define FILLLEFTRIGHTEFFECT_H -#include "effects/effect.h" +#include "nodes/node.h" -class FillLeftRightEffect : public Effect { +class FillLeftRightEffect : public Node { Q_OBJECT public: - FillLeftRightEffect(Clip* c, const EffectMeta* em); + FillLeftRightEffect(Clip* c); + + virtual QString name() override; + virtual QString id() override; + virtual QString description() override; + virtual EffectType type() override; + virtual olive::TrackType subtype() override; + virtual NodePtr Create(Clip *c) override; + virtual void process_audio(double timecode_start, double timecode_end, float **samples, diff --git a/effects/internal/linearfadetransition.cpp b/effects/internal/linearfadetransition.cpp index ddb89d0af..e89e311dc 100644 --- a/effects/internal/linearfadetransition.cpp +++ b/effects/internal/linearfadetransition.cpp @@ -20,7 +20,37 @@ #include "linearfadetransition.h" -LinearFadeTransition::LinearFadeTransition(Clip* c, Clip* s, const EffectMeta* em) : Transition(c, s, em) {} +LinearFadeTransition::LinearFadeTransition(Clip* c) : Transition(c) {} + +QString LinearFadeTransition::name() +{ + return tr("Linear Fade"); +} + +QString LinearFadeTransition::id() +{ + return "org.olivevideoeditor.Olive.linearfade"; +} + +QString LinearFadeTransition::description() +{ + return tr("An linear audio fade that fades evenly at a constant rate."); +} + +EffectType LinearFadeTransition::type() +{ + return EFFECT_TYPE_TRANSITION; +} + +olive::TrackType LinearFadeTransition::subtype() +{ + return olive::kTypeAudio; +} + +NodePtr LinearFadeTransition::Create(Clip *c) +{ + return std::make_shared(c); +} void LinearFadeTransition::process_audio(double timecode_start, double timecode_end, diff --git a/effects/internal/linearfadetransition.h b/effects/internal/linearfadetransition.h index abc5b7383..b2add8670 100644 --- a/effects/internal/linearfadetransition.h +++ b/effects/internal/linearfadetransition.h @@ -25,7 +25,15 @@ class LinearFadeTransition : public Transition { public: - LinearFadeTransition(Clip* c, Clip* s, const EffectMeta* em); + LinearFadeTransition(Clip* c); + + virtual QString name() override; + virtual QString id() override; + virtual QString description() override; + virtual EffectType type() override; + virtual olive::TrackType subtype() override; + virtual NodePtr Create(Clip *c) override; + virtual void process_audio(double timecode_start, double timecode_end, float **samples, diff --git a/effects/internal/logarithmicfadetransition.cpp b/effects/internal/logarithmicfadetransition.cpp index fe2f444ff..79fc82875 100644 --- a/effects/internal/logarithmicfadetransition.cpp +++ b/effects/internal/logarithmicfadetransition.cpp @@ -22,7 +22,40 @@ #include -LogarithmicFadeTransition::LogarithmicFadeTransition(Clip* c, Clip* s, const EffectMeta* em) : Transition(c, s, em) {} +LogarithmicFadeTransition::LogarithmicFadeTransition(Clip* c) : + Transition(c) +{ +} + +QString LogarithmicFadeTransition::name() +{ + return tr("Logarithmic Fade"); +} + +QString LogarithmicFadeTransition::id() +{ + return "org.olivevideoeditor.Olive.logarithmicfade"; +} + +QString LogarithmicFadeTransition::description() +{ + return tr("An logarithmic audio fade that starts fast and ends slow."); +} + +EffectType LogarithmicFadeTransition::type() +{ + return EFFECT_TYPE_TRANSITION; +} + +olive::TrackType LogarithmicFadeTransition::subtype() +{ + return olive::kTypeAudio; +} + +NodePtr LogarithmicFadeTransition::Create(Clip *c) +{ + return std::make_shared(c); +} void LogarithmicFadeTransition::process_audio(double timecode_start, double timecode_end, diff --git a/effects/internal/logarithmicfadetransition.h b/effects/internal/logarithmicfadetransition.h index 5cd03f57a..0d3d2cbd1 100644 --- a/effects/internal/logarithmicfadetransition.h +++ b/effects/internal/logarithmicfadetransition.h @@ -25,7 +25,15 @@ class LogarithmicFadeTransition : public Transition { public: - LogarithmicFadeTransition(Clip* c, Clip* s, const EffectMeta* em); + LogarithmicFadeTransition(Clip* c); + + virtual QString name() override; + virtual QString id() override; + virtual QString description() override; + virtual EffectType type() override; + virtual olive::TrackType subtype() override; + virtual NodePtr Create(Clip* c) override; + virtual void process_audio(double timecode_start, double timecode_end, float **samples, diff --git a/effects/internal/paneffect.cpp b/effects/internal/paneffect.cpp index 57b55074b..223933f8a 100644 --- a/effects/internal/paneffect.cpp +++ b/effects/internal/paneffect.cpp @@ -28,13 +28,43 @@ #include "ui/labelslider.h" #include "ui/collapsiblewidget.h" -PanEffect::PanEffect(Clip* c, const EffectMeta *em) : Effect(c, em) { +PanEffect::PanEffect(Clip* c) : Node(c) { pan_val = new DoubleInput(this, "pan", tr("Pan")); pan_val->SetMinimum(-100); pan_val->SetDefault(0); pan_val->SetMaximum(100); } +QString PanEffect::name() +{ + return tr("Pan"); +} + +QString PanEffect::id() +{ + return "org.olivevideoeditor.Olive.pan"; +} + +QString PanEffect::description() +{ + return tr("Modifying the panning on a stereo audio clip."); +} + +EffectType PanEffect::type() +{ + return EFFECT_TYPE_EFFECT; +} + +olive::TrackType PanEffect::subtype() +{ + return olive::kTypeAudio; +} + +NodePtr PanEffect::Create(Clip *c) +{ + return std::make_shared(c); +} + void PanEffect::process_audio(double timecode_start, double timecode_end, float **samples, diff --git a/effects/internal/paneffect.h b/effects/internal/paneffect.h index f0765ba24..ac6ea6034 100644 --- a/effects/internal/paneffect.h +++ b/effects/internal/paneffect.h @@ -21,12 +21,20 @@ #ifndef PANEFFECT_H #define PANEFFECT_H -#include "effects/effect.h" +#include "nodes/node.h" -class PanEffect : public Effect { +class PanEffect : public Node { Q_OBJECT public: - PanEffect(Clip* c, const EffectMeta* em); + PanEffect(Clip* c); + + virtual QString name() override; + virtual QString id() override; + virtual QString description() override; + virtual EffectType type() override; + virtual olive::TrackType subtype() override; + virtual NodePtr Create(Clip *c) override; + virtual void process_audio(double timecode_start, double timecode_end, float **samples, diff --git a/effects/internal/richtexteffect.cpp b/effects/internal/richtexteffect.cpp index b773048a8..43d7ec399 100644 --- a/effects/internal/richtexteffect.cpp +++ b/effects/internal/richtexteffect.cpp @@ -34,10 +34,10 @@ enum AutoscrollDirection { SCROLL_RIGHT, }; -RichTextEffect::RichTextEffect(Clip *c, const EffectMeta *em) : - Effect(c, em) +RichTextEffect::RichTextEffect(Clip *c) : + Node(c) { - SetFlags(Effect::SuperimposeFlag); + SetFlags(Node::SuperimposeFlag); text_val = new StringInput(this, "text", tr("Text")); @@ -82,6 +82,41 @@ RichTextEffect::RichTextEffect(Clip *c, const EffectMeta *em) : ""); } +QString RichTextEffect::name() +{ + return tr("Rich Text"); +} + +QString RichTextEffect::id() +{ + return "org.olivevideoeditor.Olive.richtext"; +} + +QString RichTextEffect::category() +{ + return tr("Render"); +} + +QString RichTextEffect::description() +{ + return tr("Render formatted rich text over a clip."); +} + +EffectType RichTextEffect::type() +{ + return EFFECT_TYPE_EFFECT; +} + +olive::TrackType RichTextEffect::subtype() +{ + return olive::kTypeVideo; +} + +NodePtr RichTextEffect::Create(Clip *c) +{ + return std::make_shared(c); +} + void RichTextEffect::redraw(double timecode) { QPainter p(&img); diff --git a/effects/internal/richtexteffect.h b/effects/internal/richtexteffect.h index 3853d07ac..8944d802c 100644 --- a/effects/internal/richtexteffect.h +++ b/effects/internal/richtexteffect.h @@ -21,13 +21,23 @@ #ifndef RICHTEXTEFFECT_H #define RICHTEXTEFFECT_H -#include "effects/effect.h" +#include "nodes/node.h" -class RichTextEffect : public Effect { +class RichTextEffect : public Node { Q_OBJECT public: - RichTextEffect(Clip* c, const EffectMeta *em); + RichTextEffect(Clip* c); + + virtual QString name() override; + virtual QString id() override; + virtual QString category() override; + virtual QString description() override; + virtual EffectType type() override; + virtual olive::TrackType subtype() override; + virtual NodePtr Create(Clip *c) override; + virtual void redraw(double timecode) override; + protected: virtual bool AlwaysUpdate() override; private: diff --git a/effects/internal/shakeeffect.cpp b/effects/internal/shakeeffect.cpp index 786812e9d..7d623dd19 100644 --- a/effects/internal/shakeeffect.cpp +++ b/effects/internal/shakeeffect.cpp @@ -32,8 +32,8 @@ #include "panels/timeline.h" #include "global/debug.h" -ShakeEffect::ShakeEffect(Clip* c, const EffectMeta *em) : Effect(c, em) { - SetFlags(Effect::CoordsFlag); +ShakeEffect::ShakeEffect(Clip* c) : Node(c) { + SetFlags(Node::CoordsFlag); intensity_val = new DoubleInput(this, "intensity", tr("Intensity")); intensity_val->SetMinimum(0); @@ -79,3 +79,38 @@ void ShakeEffect::process_coords(double timecode, GLTextureCoords& coords, int) coords.matrix.rotate(QQuaternion::fromEulerAngles(0.0f, 0.0f, rotoff)); } + +QString ShakeEffect::name() +{ + return tr("Shake"); +} + +QString ShakeEffect::id() +{ + return "org.olivevideoeditor.Olive.shake"; +} + +QString ShakeEffect::category() +{ + return tr("Distort"); +} + +QString ShakeEffect::description() +{ + return tr("Simulate a camera shake movement."); +} + +EffectType ShakeEffect::type() +{ + return EFFECT_TYPE_EFFECT; +} + +olive::TrackType ShakeEffect::subtype() +{ + return olive::kTypeVideo; +} + +NodePtr ShakeEffect::Create(Clip *c) +{ + return std::make_shared(c); +} diff --git a/effects/internal/shakeeffect.h b/effects/internal/shakeeffect.h index e0bea64fc..a9e6e9829 100644 --- a/effects/internal/shakeeffect.h +++ b/effects/internal/shakeeffect.h @@ -21,16 +21,24 @@ #ifndef SHAKEEFFECT_H #define SHAKEEFFECT_H -#include "effects/effect.h" +#include "nodes/node.h" #define RANDOM_VAL_SIZE 30 -class ShakeEffect : public Effect { +class ShakeEffect : public Node { Q_OBJECT public: - ShakeEffect(Clip* c, const EffectMeta* em); + ShakeEffect(Clip* c); virtual void process_coords(double timecode, GLTextureCoords& coords, int data) override; + virtual QString name() override; + virtual QString id() override; + virtual QString category() override; + virtual QString description() override; + virtual EffectType type() override; + virtual olive::TrackType subtype() override; + virtual NodePtr Create(Clip *c) override; + DoubleInput* intensity_val; DoubleInput* rotation_val; DoubleInput* frequency_val; diff --git a/effects/internal/solideffect.cpp b/effects/internal/solideffect.cpp index 1fb51f51b..452ea1e93 100644 --- a/effects/internal/solideffect.cpp +++ b/effects/internal/solideffect.cpp @@ -34,10 +34,10 @@ const int SMPTE_BARS = 7; const int SMPTE_STRIP_COUNT = 3; const int SMPTE_LOWER_BARS = 4; -SolidEffect::SolidEffect(Clip* c, const EffectMeta* em) : - Effect(c, em) +SolidEffect::SolidEffect(Clip* c) : + Node(c) { - SetFlags(Effect::SuperimposeFlag); + SetFlags(Node::SuperimposeFlag); // Field for solid type solid_type = new ComboInput(this, "type", tr("Type")); @@ -69,6 +69,41 @@ SolidEffect::SolidEffect(Clip* c, const EffectMeta* em) : fragPath = ":/shaders/solideffect.frag";*/ } +QString SolidEffect::name() +{ + return tr("Solid"); +} + +QString SolidEffect::id() +{ + return "org.olivevideoeditor.Olive.solid"; +} + +QString SolidEffect::category() +{ + return tr("Render"); +} + +QString SolidEffect::description() +{ + return tr("Render a solid color over this clip."); +} + +EffectType SolidEffect::type() +{ + return EFFECT_TYPE_EFFECT; +} + +olive::TrackType SolidEffect::subtype() +{ + return olive::kTypeVideo; +} + +NodePtr SolidEffect::Create(Clip *c) +{ + return std::make_shared(c); +} + void SolidEffect::redraw(double timecode) { int w = img.width(); int h = img.height(); diff --git a/effects/internal/solideffect.h b/effects/internal/solideffect.h index 26ca04351..f1bd50c1a 100644 --- a/effects/internal/solideffect.h +++ b/effects/internal/solideffect.h @@ -21,11 +21,11 @@ #ifndef SOLIDEFFECT_H #define SOLIDEFFECT_H -#include "effects/effect.h" +#include "nodes/node.h" #include -class SolidEffect : public Effect { +class SolidEffect : public Node { Q_OBJECT public: enum SolidType { @@ -34,7 +34,16 @@ public: SOLID_TYPE_CHECKERBOARD }; - SolidEffect(Clip* c, const EffectMeta *em); + SolidEffect(Clip* c); + + virtual QString name() override; + virtual QString id() override; + virtual QString category() override; + virtual QString description() override; + virtual EffectType type() override; + virtual olive::TrackType subtype() override; + virtual NodePtr Create(Clip *c) override; + virtual void redraw(double timecode) override; void SetType(SolidType type); diff --git a/effects/internal/texteffect.cpp b/effects/internal/texteffect.cpp index 458ee4d4a..14515ad68 100644 --- a/effects/internal/texteffect.cpp +++ b/effects/internal/texteffect.cpp @@ -42,10 +42,10 @@ #include "ui/blur.h" #include "global/config.h" -TextEffect::TextEffect(Clip* c, const EffectMeta* em) : - Effect(c, em) +TextEffect::TextEffect(Clip* c) : + Node(c) { - SetFlags(Effect::SuperimposeFlag); + SetFlags(Node::SuperimposeFlag); text_val = new StringInput(this, "text", tr("Text"), false); @@ -121,6 +121,41 @@ TextEffect::TextEffect(Clip* c, const EffectMeta* em) : shader_frag_path_ = "dropshadow.frag"; } +QString TextEffect::name() +{ + return tr("Text"); +} + +QString TextEffect::id() +{ + return "org.olivevideoeditor.Olive.text"; +} + +QString TextEffect::category() +{ + return tr("Render"); +} + +QString TextEffect::description() +{ + return tr("Generate simple text over this clip"); +} + +EffectType TextEffect::type() +{ + return EFFECT_TYPE_EFFECT; +} + +olive::TrackType TextEffect::subtype() +{ + return olive::kTypeVideo; +} + +NodePtr TextEffect::Create(Clip *c) +{ + return std::make_shared(c); +} + void TextEffect::redraw(double timecode) { QColor bkg = set_color_button->GetColorAt(timecode); bkg.setAlpha(0); diff --git a/effects/internal/texteffect.h b/effects/internal/texteffect.h index 37a71f7bb..de4076616 100644 --- a/effects/internal/texteffect.h +++ b/effects/internal/texteffect.h @@ -21,15 +21,24 @@ #ifndef TEXTEFFECT_H #define TEXTEFFECT_H -#include "effects/effect.h" +#include "nodes/node.h" #include #include -class TextEffect : public Effect { +class TextEffect : public Node { Q_OBJECT public: - TextEffect(Clip* c, const EffectMeta *em); + TextEffect(Clip* c); + + virtual QString name() override; + virtual QString id() override; + virtual QString category() override; + virtual QString description() override; + virtual EffectType type() override; + virtual olive::TrackType subtype() override; + virtual NodePtr Create(Clip *c) override; + virtual void redraw(double timecode) override; private slots: void outline_enable(bool); diff --git a/effects/internal/timecodeeffect.cpp b/effects/internal/timecodeeffect.cpp index 3353057e3..32a892cdf 100644 --- a/effects/internal/timecodeeffect.cpp +++ b/effects/internal/timecodeeffect.cpp @@ -42,10 +42,10 @@ #include "ui/colorbutton.h" #include "global/config.h" -TimecodeEffect::TimecodeEffect(Clip* c, const EffectMeta* em) : - Effect(c, em) +TimecodeEffect::TimecodeEffect(Clip* c) : + Node(c) { - SetFlags(Effect::SuperimposeFlag); + SetFlags(Node::SuperimposeFlag); tc_select = new ComboInput(this, "tc_selector", tr("Timecode")); tc_select->AddItem(tr("Sequence"), true); @@ -74,6 +74,41 @@ TimecodeEffect::TimecodeEffect(Clip* c, const EffectMeta* em) : prepend_text = new StringInput(this, "prepend", tr("Prepend"), false); } +QString TimecodeEffect::name() +{ + return tr("Timecode"); +} + +QString TimecodeEffect::id() +{ + return "org.olivevideoeditor.Olive.timecode"; +} + +QString TimecodeEffect::category() +{ + return tr("Render"); +} + +QString TimecodeEffect::description() +{ + return tr("Render the media or sequence timecode on this clip."); +} + +EffectType TimecodeEffect::type() +{ + return EFFECT_TYPE_EFFECT; +} + +olive::TrackType TimecodeEffect::subtype() +{ + return olive::kTypeVideo; +} + +NodePtr TimecodeEffect::Create(Clip *c) +{ + return std::make_shared(c); +} + void TimecodeEffect::redraw(double timecode) { Sequence* sequence = parent_clip->track()->sequence(); diff --git a/effects/internal/timecodeeffect.h b/effects/internal/timecodeeffect.h index 693452d06..71051d421 100644 --- a/effects/internal/timecodeeffect.h +++ b/effects/internal/timecodeeffect.h @@ -21,15 +21,24 @@ #ifndef TIMECODEEFFECT_H #define TIMECODEEFFECT_H -#include "effects/effect.h" +#include "nodes/node.h" #include #include -class TimecodeEffect : public Effect { +class TimecodeEffect : public Node { Q_OBJECT public: - TimecodeEffect(Clip* c, const EffectMeta *em); + TimecodeEffect(Clip* c); + + virtual QString name() override; + virtual QString id() override; + virtual QString category() override; + virtual QString description() override; + virtual EffectType type() override; + virtual olive::TrackType subtype() override; + virtual NodePtr Create(Clip *c) override; + virtual void redraw(double timecode) override; DoubleInput* scale_val; ColorInput* color_val; diff --git a/effects/internal/toneeffect.cpp b/effects/internal/toneeffect.cpp index c207f76bb..b0b66fa46 100644 --- a/effects/internal/toneeffect.cpp +++ b/effects/internal/toneeffect.cpp @@ -27,7 +27,7 @@ #include "timeline/clip.h" #include "timeline/sequence.h" -ToneEffect::ToneEffect(Clip* c, const EffectMeta *em) : Effect(c, em), sinX(INT_MIN) { +ToneEffect::ToneEffect(Clip* c) : Node(c), sinX(INT_MIN) { type_val = new ComboInput(this, "type", tr("Type")); type_val->AddItem(tr("Sine"), TONE_TYPE_SINE); @@ -45,6 +45,36 @@ ToneEffect::ToneEffect(Clip* c, const EffectMeta *em) : Effect(c, em), sinX(INT_ mix_val->SetValueAt(0, true); } +QString ToneEffect::name() +{ + return tr("Tone"); +} + +QString ToneEffect::id() +{ + return "org.olivevideoeditor.Olive.tone"; +} + +QString ToneEffect::description() +{ + return tr("Generate a sine wave tone to mix into this clip's audio."); +} + +EffectType ToneEffect::type() +{ + return EFFECT_TYPE_EFFECT; +} + +olive::TrackType ToneEffect::subtype() +{ + return olive::kTypeAudio; +} + +NodePtr ToneEffect::Create(Clip *c) +{ + return std::make_shared(c); +} + void ToneEffect::process_audio(double timecode_start, double timecode_end, float **samples, diff --git a/effects/internal/toneeffect.h b/effects/internal/toneeffect.h index 4420fbbb1..ddb723d79 100644 --- a/effects/internal/toneeffect.h +++ b/effects/internal/toneeffect.h @@ -21,12 +21,20 @@ #ifndef TONEEFFECT_H #define TONEEFFECT_H -#include "effects/effect.h" +#include "nodes/node.h" -class ToneEffect : public Effect { +class ToneEffect : public Node { Q_OBJECT public: - ToneEffect(Clip* c, const EffectMeta* em); + ToneEffect(Clip* c); + + virtual QString name() override; + virtual QString id() override; + virtual QString description() override; + virtual EffectType type() override; + virtual olive::TrackType subtype() override; + virtual NodePtr Create(Clip *c) override; + virtual void process_audio(double timecode_start, double timecode_end, float **samples, @@ -34,11 +42,12 @@ public: int channel_count, int type) override; +private: ComboInput* type_val; DoubleInput* freq_val; DoubleInput* amount_val; BoolInput* mix_val; -private: + int sinX; }; diff --git a/effects/internal/transformeffect.cpp b/effects/internal/transformeffect.cpp index c769b63e5..07dd64898 100644 --- a/effects/internal/transformeffect.cpp +++ b/effects/internal/transformeffect.cpp @@ -43,8 +43,8 @@ #include "panels/viewer.h" #include "ui/viewerwidget.h" -TransformEffect::TransformEffect(Clip* c, const EffectMeta* em) : Effect(c, em) { - SetFlags(Effect::CoordsFlag); +TransformEffect::TransformEffect(Clip* c) : Node(c) { + SetFlags(Node::CoordsFlag); position = new Vec2Input(this, "pos", tr("Position")); @@ -125,6 +125,41 @@ TransformEffect::TransformEffect(Clip* c, const EffectMeta* em) : Effect(c, em) refresh(); } +QString TransformEffect::name() +{ + return tr("Transform"); +} + +QString TransformEffect::id() +{ + return "org.olivevideoeditor.Olive.transform"; +} + +QString TransformEffect::category() +{ + return tr("Distort"); +} + +QString TransformEffect::description() +{ + return tr("Transform the position, scale, and rotation of this clip."); +} + +EffectType TransformEffect::type() +{ + return EFFECT_TYPE_EFFECT; +} + +olive::TrackType TransformEffect::subtype() +{ + return olive::kTypeVideo; +} + +NodePtr TransformEffect::Create(Clip *c) +{ + return std::make_shared(c); +} + void TransformEffect::refresh() { if (parent_clip != nullptr && parent_clip->track()->sequence() != nullptr) { diff --git a/effects/internal/transformeffect.h b/effects/internal/transformeffect.h index 19c856c28..2ead33e31 100644 --- a/effects/internal/transformeffect.h +++ b/effects/internal/transformeffect.h @@ -21,12 +21,21 @@ #ifndef TRANSFORMEFFECT_H #define TRANSFORMEFFECT_H -#include "effects/effect.h" +#include "nodes/node.h" -class TransformEffect : public Effect { +class TransformEffect : public Node { Q_OBJECT public: - TransformEffect(Clip* c, const EffectMeta* em); + TransformEffect(Clip* c); + + virtual QString name() override; + virtual QString id() override; + virtual QString category() override; + virtual QString description() override; + virtual EffectType type() override; + virtual olive::TrackType subtype() override; + virtual NodePtr Create(Clip *c) override; + virtual void refresh() override; virtual void process_coords(double timecode, GLTextureCoords& coords, int data) override; diff --git a/effects/internal/voideffect.cpp b/effects/internal/voideffect.cpp index a82aaffdd..f5eb5a8d2 100644 --- a/effects/internal/voideffect.cpp +++ b/effects/internal/voideffect.cpp @@ -27,24 +27,55 @@ #include "ui/collapsiblewidget.h" #include "global/debug.h" -VoidEffect::VoidEffect(Clip* c, const QString& n) : Effect(c, nullptr) { - QString display_name; - if (n.isEmpty()) { - display_name = tr("(unknown)"); - } else { - display_name = n; +VoidEffect::VoidEffect(Clip* c, const QString& n, const QString& id) : + Node(c), + display_name_(n), + id_(id) +{ + if (display_name_.isEmpty()) { + display_name_ = tr("(unknown)"); } - new LabelWidget(this, tr("Missing Effect"), display_name); - - name = display_name; - - void_meta.type = EFFECT_TYPE_EFFECT; - meta = &void_meta; + new LabelWidget(this, tr("Missing Effect"), display_name_); } -EffectPtr VoidEffect::copy(Clip* c) { - EffectPtr copy = std::make_shared(c, name); +QString VoidEffect::name() +{ + return display_name_; +} + +QString VoidEffect::id() +{ + return id_; +} + +QString VoidEffect::description() +{ + return QString(); +} + +EffectType VoidEffect::type() +{ + return EFFECT_TYPE_EFFECT; +} + +olive::TrackType VoidEffect::subtype() +{ + return olive::kTypeVideo; +} + +bool VoidEffect::IsCreatable() +{ + return false; +} + +NodePtr VoidEffect::Create(Clip *) +{ + return nullptr; +} + +NodePtr VoidEffect::copy(Clip* c) { + NodePtr copy = std::make_shared(c, display_name_, id_); copy->SetEnabled(IsEnabled()); copy_field_keyframes(copy); return copy; @@ -53,7 +84,7 @@ EffectPtr VoidEffect::copy(Clip* c) { void VoidEffect::load(QXmlStreamReader &stream) { QString tag = stream.name().toString(); - QXmlStreamWriter writer(&bytes); + QXmlStreamWriter writer(&bytes_); // copy XML from reader to writer while (!stream.atEnd() && !(stream.name() == tag && stream.isEndElement())) { @@ -75,18 +106,18 @@ void VoidEffect::load(QXmlStreamReader &stream) { } void VoidEffect::save(QXmlStreamWriter &stream) { - if (!name.isEmpty()) { - stream.writeAttribute("name", name); + if (!display_name_.isEmpty()) { + stream.writeAttribute("name", display_name_); stream.writeAttribute("enabled", QString::number(IsEnabled())); // force xml writer to expand tag, ignored when loading stream.writeStartElement("void"); stream.writeEndElement(); - if (!bytes.isEmpty()) { + if (!bytes_.isEmpty()) { // write stored data QIODevice* device = stream.device(); - device->write(bytes); + device->write(bytes_); } } } diff --git a/effects/internal/voideffect.h b/effects/internal/voideffect.h index cfd93141a..e551f4ae0 100644 --- a/effects/internal/voideffect.h +++ b/effects/internal/voideffect.h @@ -27,19 +27,28 @@ * isn't lost if the user saves over the project. */ -#include "effects/effect.h" +#include "nodes/node.h" -class VoidEffect : public Effect { +class VoidEffect : public Node { Q_OBJECT public: - VoidEffect(Clip* c, const QString& n); + VoidEffect(Clip* c, const QString& n, const QString &id); + + virtual QString name() override; + virtual QString id() override; + virtual QString description() override; + 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 EffectPtr copy(Clip* c) override; virtual void load(QXmlStreamReader &stream) override; virtual void save(QXmlStreamWriter &stream) override; private: - QByteArray bytes; - EffectMeta void_meta; + QByteArray bytes_; + QString display_name_; + QString id_; }; #endif // VOIDEFFECT_H diff --git a/effects/internal/volumeeffect.cpp b/effects/internal/volumeeffect.cpp index c400ff89b..96c66b676 100644 --- a/effects/internal/volumeeffect.cpp +++ b/effects/internal/volumeeffect.cpp @@ -28,7 +28,7 @@ #include "ui/labelslider.h" #include "ui/collapsiblewidget.h" -VolumeEffect::VolumeEffect(Clip* c, const EffectMeta *em) : Effect(c, em) { +VolumeEffect::VolumeEffect(Clip* c) : Node(c) { volume_val = new DoubleInput(this, "volume", tr("Volume")); // set defaults @@ -36,6 +36,36 @@ VolumeEffect::VolumeEffect(Clip* c, const EffectMeta *em) : Effect(c, em) { volume_val->SetDisplayType(LabelSlider::Decibel); } +QString VolumeEffect::name() +{ + return tr("Volume"); +} + +QString VolumeEffect::id() +{ + return "org.olivevideoeditor.Olive.volume"; +} + +QString VolumeEffect::description() +{ + return tr("Adjust the volume of this clip's audio"); +} + +EffectType VolumeEffect::type() +{ + return EFFECT_TYPE_EFFECT; +} + +olive::TrackType VolumeEffect::subtype() +{ + return olive::kTypeAudio; +} + +NodePtr VolumeEffect::Create(Clip *c) +{ + return std::make_shared(c); +} + void VolumeEffect::process_audio(double timecode_start, double timecode_end, float **samples, diff --git a/effects/internal/volumeeffect.h b/effects/internal/volumeeffect.h index 19c855217..d8cdbf81f 100644 --- a/effects/internal/volumeeffect.h +++ b/effects/internal/volumeeffect.h @@ -21,12 +21,20 @@ #ifndef VOLUMEEFFECT_H #define VOLUMEEFFECT_H -#include "effects/effect.h" +#include "nodes/node.h" -class VolumeEffect : public Effect { +class VolumeEffect : public Node { Q_OBJECT public: - VolumeEffect(Clip* c, const EffectMeta* em); + VolumeEffect(Clip* c); + + virtual QString name() override; + virtual QString id() override; + virtual QString description() override; + virtual EffectType type() override; + virtual olive::TrackType subtype() override; + virtual NodePtr Create(Clip *c) override; + virtual void process_audio(double timecode_start, double timecode_end, float **samples, @@ -34,6 +42,7 @@ public: int channel_count, int type) override; +private: DoubleInput* volume_val; }; diff --git a/effects/internal/vsthost.cpp b/effects/internal/vsthost.cpp index 954f658c0..c4d9f2aff 100644 --- a/effects/internal/vsthost.cpp +++ b/effects/internal/vsthost.cpp @@ -227,8 +227,8 @@ void VSTHost::send_data_cache_to_plugin() dispatcher(plugin, effSetChunk, 0, int32_t(data_cache.size()), static_cast(data_cache.data()), 0); } -VSTHost::VSTHost(Clip* c, const EffectMeta *em) : - Effect(c, em), +VSTHost::VSTHost(Clip* c) : + Node(c), plugin(nullptr), dialog(nullptr), input_cache(BLOCK_SIZE), @@ -249,6 +249,36 @@ VSTHost::~VSTHost() { freePlugin(); } +QString VSTHost::name() +{ + return tr("VST Plugin 2.x"); +} + +QString VSTHost::id() +{ + return "org.olivevideoeditor.Olive.vst2x"; +} + +QString VSTHost::description() +{ + return tr("Use a VST 2.x plugin on this clip's audio."); +} + +EffectType VSTHost::type() +{ + return EFFECT_TYPE_EFFECT; +} + +olive::TrackType VSTHost::subtype() +{ + return olive::kTypeAudio; +} + +NodePtr VSTHost::Create(Clip *c) +{ + return std::make_shared(c); +} + void VSTHost::process_audio(double timecode_start, double timecode_end, float **samples, @@ -291,7 +321,7 @@ void VSTHost::custom_load(QXmlStreamReader &stream) { } void VSTHost::save(QXmlStreamWriter &stream) { - Effect::save(stream); + Node::save(stream); if (plugin != nullptr) { char* p = nullptr; int32_t length = int32_t(dispatcher(plugin, effGetChunk, 0, 0, &p, 0)); diff --git a/effects/internal/vsthost.h b/effects/internal/vsthost.h index 301d2ef89..39c0be1fd 100644 --- a/effects/internal/vsthost.h +++ b/effects/internal/vsthost.h @@ -24,7 +24,7 @@ #include #include -#include "effects/effect.h" +#include "nodes/node.h" #include "include/vestige.h" // Plugin's dispatcher function @@ -46,11 +46,19 @@ private: void destroy(); }; -class VSTHost : public Effect { +class VSTHost : public Node { Q_OBJECT public: - VSTHost(Clip* c, const EffectMeta* em); - ~VSTHost(); + VSTHost(Clip* c); + virtual ~VSTHost() override; + + virtual QString name() override; + virtual QString id() override; + virtual QString description() override; + virtual EffectType type() override; + virtual olive::TrackType subtype() override; + virtual NodePtr Create(Clip *c) override; + virtual void process_audio(double timecode_start, double timecode_end, float **samples, diff --git a/effects/transition.cpp b/effects/transition.cpp index 5c1809d97..af25547ad 100644 --- a/effects/transition.cpp +++ b/effects/transition.cpp @@ -40,27 +40,34 @@ #include #include -Transition::Transition(Clip *c, Clip *s, const EffectMeta* em) : - Effect(c, em), - secondary_clip(s) +Transition::Transition(Clip *c) : + Node(c), + secondary_clip(nullptr) { length_field = new DoubleInput(this, "length", tr("Length"), false, false); length_field->SetDefault(30); length_field->SetMinimum(1); length_field->SetDisplayType(LabelSlider::FrameNumber); - length_field->SetFrameRate(parent_clip->track()->sequence() == nullptr ? - parent_clip->cached_frame_rate() : parent_clip->track()->sequence()->frame_rate); + + if (parent_clip != nullptr) { + length_field->SetFrameRate(parent_clip->track()->sequence() == nullptr ? + parent_clip->cached_frame_rate() : parent_clip->track()->sequence()->frame_rate); + } connect(length_field, SIGNAL(Changed()), this, SLOT(UpdateMaximumLength())); } -TransitionPtr Transition::copy(Clip *c, Clip *s) { - return Transition::Create(c, s, meta, get_true_length()); +NodePtr Transition::copy(Clip *c) { + NodePtr node = Node::copy(c); + + static_cast(node.get())->set_length(get_true_length()); + + return node; } void Transition::save(QXmlStreamWriter &stream) { stream.writeAttribute("length", QString::number(get_true_length())); - Effect::save(stream); + Node::save(stream); } void Transition::set_length(int l) { @@ -96,17 +103,18 @@ Clip* Transition::get_closed_clip() { return nullptr; } -TransitionPtr Transition::CreateFromMeta(Clip* c, Clip* s, const EffectMeta* em) { +/* +TransitionPtr Transition::CreateFromMeta(Clip* c, Clip* s) { if (!em->filename.isEmpty()) { // load effect from file return TransitionPtr(new Transition(c, s, em)); } else if (em->internal >= 0 && em->internal < TRANSITION_INTERNAL_COUNT) { // must be an internal effect switch (em->internal) { - case TRANSITION_INTERNAL_CROSSDISSOLVE: return TransitionPtr(new CrossDissolveTransition(c, s, em)); - case TRANSITION_INTERNAL_LINEARFADE: return TransitionPtr(new LinearFadeTransition(c, s, em)); - case TRANSITION_INTERNAL_EXPONENTIALFADE: return TransitionPtr(new ExponentialFadeTransition(c, s, em)); - case TRANSITION_INTERNAL_LOGARITHMICFADE: return TransitionPtr(new LogarithmicFadeTransition(c, s, em)); + case kCrossDissolveTransition: return TransitionPtr(new CrossDissolveTransition(c, s, em)); + case kLinearFadeTransition: return TransitionPtr(new LinearFadeTransition(c, s, em)); + case kExponentialFadeTransition: return TransitionPtr(new ExponentialFadeTransition(c, s, em)); + case kLogarithmicFadeTransition: return TransitionPtr(new LogarithmicFadeTransition(c, s, em)); //case TRANSITION_INTERNAL_CUBE: return TransitionPtr(new CubeTransition(c, s, em)); } } else { @@ -118,6 +126,7 @@ TransitionPtr Transition::CreateFromMeta(Clip* c, Clip* s, const EffectMeta* em) } return nullptr; } +*/ void Transition::UpdateMaximumLength() { @@ -154,14 +163,3 @@ long Transition::GetMaximumEmptySpaceOnClip(Clip *c) return maximum_transition_length; } - -TransitionPtr Transition::Create(Clip* c, Clip* s, const EffectMeta* em, long length) { - TransitionPtr t(CreateFromMeta(c, s, em)); - if (t != nullptr) { - if (length > 0) { - t->set_length(length); - } - return t; - } - return nullptr; -} diff --git a/effects/transition.h b/effects/transition.h index 20adde1ba..7be393c5c 100644 --- a/effects/transition.h +++ b/effects/transition.h @@ -21,7 +21,8 @@ #ifndef TRANSITION_H #define TRANSITION_H -#include "effect.h" +#include "nodes/node.h" +#include "nodes/inputs.h" enum TransitionType { kTransitionNone, @@ -29,23 +30,16 @@ enum TransitionType { kTransitionClosing }; -enum TransitionInternal { - TRANSITION_INTERNAL_CROSSDISSOLVE, - TRANSITION_INTERNAL_LINEARFADE, - TRANSITION_INTERNAL_EXPONENTIALFADE, - TRANSITION_INTERNAL_LOGARITHMICFADE, - //TRANSITION_INTERNAL_CUBE, - TRANSITION_INTERNAL_COUNT -}; - class Transition; using TransitionPtr = std::shared_ptr; -class Transition : public Effect { +class Transition : public Node { Q_OBJECT public: - Transition(Clip* c, Clip* s, const EffectMeta* em); - virtual TransitionPtr copy(Clip* c, Clip* s); + Transition(Clip* c); + + virtual NodePtr copy(Clip* c) override; + Clip* secondary_clip; virtual void save(QXmlStreamWriter& stream) override; @@ -57,8 +51,6 @@ public: Clip* get_opened_clip(); Clip* get_closed_clip(); - static TransitionPtr Create(Clip* c, Clip* s, const EffectMeta* em, long length = 0); - static TransitionPtr CreateFromMeta(Clip *c, Clip *s, const EffectMeta* em); private: DoubleInput* length_field; diff --git a/global/clipboard.cpp b/global/clipboard.cpp index c2157ba22..22d1c4bfc 100644 --- a/global/clipboard.cpp +++ b/global/clipboard.cpp @@ -21,8 +21,9 @@ #include "clipboard.h" #include "timeline/clip.h" -#include "effects/effect.h" +#include "nodes/node.h" #include "effects/transition.h" +#include "undo/undo.h" Clipboard::Clipboard() : type_(CLIPBOARD_TYPE_CLIP) diff --git a/global/clipboard.h b/global/clipboard.h index 9a2366256..be3190c2d 100644 --- a/global/clipboard.h +++ b/global/clipboard.h @@ -24,6 +24,7 @@ #include #include "effects/transition.h" +#include "project/media.h" using VoidPtr = std::shared_ptr; diff --git a/global/global.cpp b/global/global.cpp index 6b3dfc238..a98e82772 100644 --- a/global/global.cpp +++ b/global/global.cpp @@ -389,15 +389,15 @@ void OliveGlobal::PasteInternal(Sequence *s, bool insert) Clip* c = selected_clips.at(i); for (int j=0;j(olive::clipboard.Get(j)); - if (c->type() == e->meta->subtype) { + NodePtr e = std::static_pointer_cast(olive::clipboard.Get(j)); + if (c->type() == e->subtype()) { int found = -1; if (ask_conflict) { replace = false; skip = false; } for (int k=0;keffects.size();k++) { - if (c->effects.at(k)->meta == e->meta) { + if (c->effects.at(k)->id() == e->id()) { found = k; break; } @@ -407,7 +407,7 @@ void OliveGlobal::PasteInternal(Sequence *s, bool insert) box.setWindowTitle(tr("Effect already exists")); box.setText(tr("Clip '%1' already contains a '%2' effect. " "Would you like to replace it with the pasted one or add it as a separate effect?") - .arg(c->name(), e->meta->name)); + .arg(c->name(), e->name())); box.setIcon(QMessageBox::Icon::Question); box.addButton(tr("Add"), QMessageBox::YesRole); @@ -432,9 +432,9 @@ void OliveGlobal::PasteInternal(Sequence *s, bool insert) } else if (found >= 0 && replace) { ca->append(new EffectDeleteCommand(c->effects.at(found).get())); - ca->append(new AddEffectCommand(c, e->copy(c), nullptr, found)); + ca->append(new AddEffectCommand(c, e->copy(c), kInvalidNode, found)); } else { - ca->append(new AddEffectCommand(c, e->copy(c), nullptr)); + ca->append(new AddEffectCommand(c, e->copy(c), kInvalidNode)); } } } diff --git a/nodes/inputs/boolinput.cpp b/nodes/inputs/boolinput.cpp index 9ef9a32ae..ff58c005a 100644 --- a/nodes/inputs/boolinput.cpp +++ b/nodes/inputs/boolinput.cpp @@ -1,6 +1,6 @@ #include "boolinput.h" -BoolInput::BoolInput(Effect* parent, const QString& id, const QString& name, bool savable, bool keyframable) : +BoolInput::BoolInput(Node* parent, const QString& id, const QString& name, bool savable, bool keyframable) : EffectRow(parent, id, name, savable, keyframable) { BoolField* bool_field = new BoolField(this); diff --git a/nodes/inputs/boolinput.h b/nodes/inputs/boolinput.h index d04c89a6f..e10660fb3 100644 --- a/nodes/inputs/boolinput.h +++ b/nodes/inputs/boolinput.h @@ -7,7 +7,7 @@ class BoolInput : public EffectRow { Q_OBJECT public: - BoolInput(Effect* parent, const QString& id, const QString& name, bool savable = true, bool keyframable = true); + BoolInput(Node* parent, const QString& id, const QString& name, bool savable = true, bool keyframable = true); /** * @brief Get the boolean value at a given timecode diff --git a/nodes/inputs/colorinput.cpp b/nodes/inputs/colorinput.cpp index c23d3a83d..6c12129d6 100644 --- a/nodes/inputs/colorinput.cpp +++ b/nodes/inputs/colorinput.cpp @@ -1,6 +1,6 @@ #include "colorinput.h" -ColorInput::ColorInput(Effect* parent, const QString& id, const QString& name, bool savable, bool keyframable) : +ColorInput::ColorInput(Node* parent, const QString& id, const QString& name, bool savable, bool keyframable) : EffectRow(parent, id, name, savable, keyframable) { AddField(new ColorField(this)); @@ -10,5 +10,5 @@ ColorInput::ColorInput(Effect* parent, const QString& id, const QString& name, b QColor ColorInput::GetColorAt(double timecode) { - static_cast(Field(0))->GetColorAt(timecode); + return static_cast(Field(0))->GetColorAt(timecode); } diff --git a/nodes/inputs/colorinput.h b/nodes/inputs/colorinput.h index d46acfd38..486f18e2e 100644 --- a/nodes/inputs/colorinput.h +++ b/nodes/inputs/colorinput.h @@ -7,7 +7,7 @@ class ColorInput : public EffectRow { Q_OBJECT public: - ColorInput(Effect* parent, const QString& id, const QString& name, bool savable = true, bool keyframable = true); + ColorInput(Node* parent, const QString& id, const QString& name, bool savable = true, bool keyframable = true); /** * @brief Get the color value at a given timecode diff --git a/nodes/inputs/comboinput.cpp b/nodes/inputs/comboinput.cpp index d34ea7d88..b257ea66e 100644 --- a/nodes/inputs/comboinput.cpp +++ b/nodes/inputs/comboinput.cpp @@ -1,6 +1,6 @@ #include "comboinput.h" -ComboInput::ComboInput(Effect* parent, const QString& id, const QString& name, bool savable, bool keyframable) : +ComboInput::ComboInput(Node* parent, const QString& id, const QString& name, bool savable, bool keyframable) : EffectRow(parent, id, name, savable, keyframable) { ComboField* combo_field = new ComboField(this); diff --git a/nodes/inputs/comboinput.h b/nodes/inputs/comboinput.h index d48eae16d..25dbc4e91 100644 --- a/nodes/inputs/comboinput.h +++ b/nodes/inputs/comboinput.h @@ -7,7 +7,7 @@ class ComboInput : public EffectRow { Q_OBJECT public: - ComboInput(Effect* parent, const QString& id, const QString& name, bool savable = true, bool keyframable = true); + ComboInput(Node* parent, const QString& id, const QString& name, bool savable = true, bool keyframable = true); /** * @brief Add an item to this ComboInput diff --git a/nodes/inputs/fileinput.cpp b/nodes/inputs/fileinput.cpp index 65d872ef7..77d2406bf 100644 --- a/nodes/inputs/fileinput.cpp +++ b/nodes/inputs/fileinput.cpp @@ -1,6 +1,6 @@ #include "fileinput.h" -FileInput::FileInput(Effect* parent, const QString& id, const QString& name, bool savable, bool keyframable) : +FileInput::FileInput(Node* parent, const QString& id, const QString& name, bool savable, bool keyframable) : EffectRow(parent, id, name, savable, keyframable) { AddField(new FileField(this)); diff --git a/nodes/inputs/fileinput.h b/nodes/inputs/fileinput.h index 9473a9c13..1793e5b97 100644 --- a/nodes/inputs/fileinput.h +++ b/nodes/inputs/fileinput.h @@ -7,7 +7,7 @@ class FileInput : public EffectRow { Q_OBJECT public: - FileInput(Effect* parent, const QString& id, const QString& name, bool savable = true, bool keyframable = true); + FileInput(Node* parent, const QString& id, const QString& name, bool savable = true, bool keyframable = true); /** * @brief Get the filename at the given timecode diff --git a/nodes/inputs/fontinput.cpp b/nodes/inputs/fontinput.cpp index 506a402d9..c5a901c7e 100644 --- a/nodes/inputs/fontinput.cpp +++ b/nodes/inputs/fontinput.cpp @@ -1,6 +1,6 @@ #include "fontinput.h" -FontInput::FontInput(Effect* parent, const QString& id, const QString& name, bool savable, bool keyframable) : +FontInput::FontInput(Node* parent, const QString& id, const QString& name, bool savable, bool keyframable) : EffectRow(parent, id, name, savable, keyframable) { AddField(new FontField(this)); diff --git a/nodes/inputs/fontinput.h b/nodes/inputs/fontinput.h index b1ac07979..cfcb34c55 100644 --- a/nodes/inputs/fontinput.h +++ b/nodes/inputs/fontinput.h @@ -7,7 +7,7 @@ class FontInput : public EffectRow { Q_OBJECT public: - FontInput(Effect* parent, const QString& id, const QString& name, bool savable = true, bool keyframable = true); + FontInput(Node* parent, const QString& id, const QString& name, bool savable = true, bool keyframable = true); /** * @brief Get the font family name at the given timecode diff --git a/nodes/inputs/stringinput.cpp b/nodes/inputs/stringinput.cpp index ea840992c..0cdfa6922 100644 --- a/nodes/inputs/stringinput.cpp +++ b/nodes/inputs/stringinput.cpp @@ -1,6 +1,6 @@ #include "stringinput.h" -StringInput::StringInput(Effect* parent, const QString& id, const QString& name, bool rich_text, bool savable, bool keyframable) : +StringInput::StringInput(Node* parent, const QString& id, const QString& name, bool rich_text, bool savable, bool keyframable) : EffectRow(parent, id, name, savable, keyframable) { AddField(new StringField(this, rich_text)); diff --git a/nodes/inputs/stringinput.h b/nodes/inputs/stringinput.h index 4498bbae9..d738d2fe3 100644 --- a/nodes/inputs/stringinput.h +++ b/nodes/inputs/stringinput.h @@ -7,7 +7,7 @@ class StringInput : public EffectRow { Q_OBJECT public: - StringInput(Effect* parent, + StringInput(Node* parent, const QString& id, const QString& name, bool rich_text = true, diff --git a/nodes/inputs/vecinput.cpp b/nodes/inputs/vecinput.cpp index 7cdf7d01b..2626720f0 100644 --- a/nodes/inputs/vecinput.cpp +++ b/nodes/inputs/vecinput.cpp @@ -4,7 +4,7 @@ #include #include -VecInput::VecInput(Effect* parent, const QString& id, const QString& name, int values, bool savable, bool keyframable) : +VecInput::VecInput(Node* parent, const QString& id, const QString& name, int values, bool savable, bool keyframable) : EffectRow(parent, id, name, savable, keyframable), single_value_mode_(false), values_(values) @@ -79,7 +79,7 @@ void VecInput::SetSingleValueMode(bool on) } } -DoubleInput::DoubleInput(Effect *parent, const QString &id, const QString &name, bool savable, bool keyframable) : +DoubleInput::DoubleInput(Node *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(Field(0))->GetDoubleAt(timecode); } -Vec2Input::Vec2Input(Effect *parent, const QString &id, const QString &name, bool savable, bool keyframable) : +Vec2Input::Vec2Input(Node *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(Field(1))->SetValueAt(timecode, vec2.y()); } -Vec3Input::Vec3Input(Effect *parent, const QString &id, const QString &name, bool savable, bool keyframable) : +Vec3Input::Vec3Input(Node *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(Field(2))->SetValueAt(timecode, vec3.z()); } -Vec4Input::Vec4Input(Effect *parent, const QString &id, const QString &name, bool savable, bool keyframable) : +Vec4Input::Vec4Input(Node *parent, const QString &id, const QString &name, bool savable, bool keyframable) : VecInput(parent, id, name, 4, savable, keyframable) { } diff --git a/nodes/inputs/vecinput.h b/nodes/inputs/vecinput.h index 9698308d1..7fda0aaca 100644 --- a/nodes/inputs/vecinput.h +++ b/nodes/inputs/vecinput.h @@ -9,7 +9,7 @@ class VecInput : public EffectRow { Q_OBJECT public: - VecInput(Effect* parent, const QString& id, const QString& name, int values, bool savable = true, bool keyframable = true); + VecInput(Node* 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(Effect* parent, const QString& id, const QString& name, bool savable = true, bool keyframable = true); + DoubleInput(Node* parent, const QString& id, const QString& name, bool savable = true, bool keyframable = true); double GetDoubleAt(double timecode); }; class Vec2Input : public VecInput { public: - Vec2Input(Effect* parent, const QString& id, const QString& name, bool savable = true, bool keyframable = true); + Vec2Input(Node* 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(Effect* parent, const QString& id, const QString& name, bool savable = true, bool keyframable = true); + Vec3Input(Node* 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(Effect* parent, const QString& id, const QString& name, bool savable = true, bool keyframable = true); + Vec4Input(Node* parent, const QString& id, const QString& name, bool savable = true, bool keyframable = true); QVector4D GetVector4DAt(double timecode); virtual QVariant GetValueAt(double timecode) override; diff --git a/effects/effect.cpp b/nodes/node.cpp similarity index 77% rename from effects/effect.cpp rename to nodes/node.cpp index db02e443c..efb3146e3 100644 --- a/effects/effect.cpp +++ b/nodes/node.cpp @@ -18,7 +18,7 @@ ***/ -#include "effect.h" +#include "node.h" #include #include @@ -50,61 +50,47 @@ #include "global/math.h" #include "global/clipboard.h" #include "global/config.h" -#include "transition.h" +#include "effects/transition.h" #include "undo/undostack.h" #include "rendering/shadergenerators.h" #include "global/timing.h" #include "nodes/nodes.h" -#include "effects/internal/transformeffect.h" -#include "effects/internal/texteffect.h" -#include "effects/internal/timecodeeffect.h" -#include "effects/internal/solideffect.h" -#include "effects/internal/audionoiseeffect.h" -#include "effects/internal/toneeffect.h" -#include "effects/internal/volumeeffect.h" -#include "effects/internal/paneffect.h" -#include "effects/internal/shakeeffect.h" -#include "effects/internal/cornerpineffect.h" -#include "effects/internal/vsthost.h" -#include "effects/internal/fillleftrighteffect.h" -#include "effects/internal/richtexteffect.h" +QVector olive::node_library; -QVector olive::effects; -QVector olive::blend_modes; -QString olive::generated_blending_shader; - -EffectPtr Effect::Create(Clip* c, const EffectMeta* em) { - if (em->internal >= 0 && em->internal < EFFECT_INTERNAL_COUNT) { - // must be an internal effect - switch (em->internal) { - case EFFECT_INTERNAL_TRANSFORM: return std::make_shared(c, em); - case EFFECT_INTERNAL_TEXT: return std::make_shared(c, em); - case EFFECT_INTERNAL_TIMECODE: return std::make_shared(c, em); - case EFFECT_INTERNAL_SOLID: return std::make_shared(c, em); - case EFFECT_INTERNAL_NOISE: return std::make_shared(c, em); - case EFFECT_INTERNAL_VOLUME: return std::make_shared(c, em); - case EFFECT_INTERNAL_PAN: return std::make_shared(c, em); - case EFFECT_INTERNAL_TONE: return std::make_shared(c, em); - case EFFECT_INTERNAL_SHAKE: return std::make_shared(c, em); - case EFFECT_INTERNAL_CORNERPIN: return std::make_shared(c, em); - case EFFECT_INTERNAL_FILLLEFTRIGHT: return std::make_shared(c, em); - case EFFECT_INTERNAL_VST: return std::make_shared(c, em); - case EFFECT_INTERNAL_RICHTEXT: return std::make_shared(c, em); - } - } else if (!em->filename.isEmpty()) { - // load effect from file - return std::make_shared(c, em); - } else { +/* +NodePtr Node::Create(Clip* c) { + // must be an internal effect + switch (em->internal) { + case kTransformEffect: return std::make_shared(c, em); + case kTextInput: return std::make_shared(c, em); + case kTimecodeEffect: return std::make_shared(c, em); + case kSolidInput: return std::make_shared(c, em); + case kNoiseInput: return std::make_shared(c, em); + case kVolumeEffect: return std::make_shared(c, em); + case kPanEffect: return std::make_shared(c, em); + case kToneInput: return std::make_shared(c, em); + case kShakeEffect: return std::make_shared(c, em); + case kCornerPinEffect: return std::make_shared(c, em); + case kFillLeftRightEffect: return std::make_shared(c, em); + case kVstEffect: return std::make_shared(c, em); + case kRichTextInput: return std::make_shared(c, em); + case kMediaInput: return std::make_shared(c, em); + case kShaderEffect: return std::make_shared(c, em); + case kImageOutput: return std::make_shared(c, em); + default: qCritical() << "Invalid effect data"; QMessageBox::critical(olive::MainWindow, QCoreApplication::translate("Effect", "Invalid effect"), - QCoreApplication::translate("Effect", "No candidate for effect '%1'. This effect may be corrupt. Try reinstalling it or Olive.").arg(em->name)); + QCoreApplication::translate("Effect", "No candidate for effect '%1'. This effect may be " + "corrupt. Try reinstalling it or Olive.").arg(em->name)); + return nullptr; } - return nullptr; } +*/ -const EffectMeta* Effect::GetInternalMeta(int internal_id, int type) { +/* +const EffectMeta* Node::GetInternalMeta(int internal_id, int type) { for (int i=0;iname; - } +{ } -Effect::~Effect() { +Node::~Node() { if (isOpen) { close(); } @@ -150,13 +132,23 @@ Effect::~Effect() { } } -void Effect::AddRow(EffectRow *row) +QString Node::category() +{ + return QString(); +} + +bool Node::IsCreatable() +{ + return true; +} + +void Node::AddRow(EffectRow *row) { row->setParent(this); rows.append(row); } -void Effect::copy_field_keyframes(EffectPtr e) { +void Node::copy_field_keyframes(NodePtr e) { for (int i=0;irows.at(i); @@ -177,40 +169,43 @@ void Effect::copy_field_keyframes(EffectPtr e) { } } -EffectRow* Effect::row(int i) { +EffectRow* Node::row(int i) { return rows.at(i); } -int Effect::row_count() { +int Node::row_count() { return rows.size(); } -EffectGizmo *Effect::add_gizmo(int type) { +EffectGizmo *Node::add_gizmo(int type) { EffectGizmo* gizmo = new EffectGizmo(this, type); gizmos.append(gizmo); return gizmo; } -EffectGizmo *Effect::gizmo(int i) { +EffectGizmo *Node::gizmo(int i) { return gizmos.at(i); } -int Effect::gizmo_count() { +int Node::gizmo_count() { return gizmos.size(); } -void Effect::refresh() {} +void Node::refresh() {} -void Effect::FieldChanged() { - update_ui(false); +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 Effect::delete_self() { +void Node::delete_self() { olive::undo_stack.push(new EffectDeleteCommand(this)); update_ui(true); } -void Effect::move_up() { +void Node::move_up() { int index_of_effect = parent_clip->IndexOfEffect(this); if (index_of_effect == 0) { return; @@ -225,7 +220,7 @@ void Effect::move_up() { panel_sequence_viewer->viewer_widget()->frame_update(); } -void Effect::move_down() { +void Node::move_down() { int index_of_effect = parent_clip->IndexOfEffect(this); if (index_of_effect == parent_clip->effects.size()-1) { return; @@ -240,7 +235,7 @@ void Effect::move_down() { panel_sequence_viewer->viewer_widget()->frame_update(); } -void Effect::save_to_file() { +void Node::save_to_file() { // save effect settings to file QString file = QFileDialog::getSaveFileName(olive::MainWindow, tr("Save Effect Settings"), @@ -270,7 +265,7 @@ void Effect::save_to_file() { } } -void Effect::load_from_file() { +void Node::load_from_file() { // load effect settings from file QString file = QFileDialog::getOpenFileName(olive::MainWindow, tr("Load Effect Settings"), @@ -296,31 +291,31 @@ void Effect::load_from_file() { } } -bool Effect::AlwaysUpdate() +bool Node::AlwaysUpdate() { return false; } -bool Effect::IsEnabled() { +bool Node::IsEnabled() { return enabled_; } -bool Effect::IsExpanded() +bool Node::IsExpanded() { return expanded_; } -void Effect::SetExpanded(bool e) +void Node::SetExpanded(bool e) { expanded_ = e; } -void Effect::SetEnabled(bool b) { +void Node::SetEnabled(bool b) { enabled_ = b; emit EnabledChanged(b); } -void Effect::load(QXmlStreamReader& stream) { +void Node::load(QXmlStreamReader& stream) { /* int row_count = 0; @@ -412,9 +407,9 @@ void Effect::load(QXmlStreamReader& stream) { */ } -void Effect::custom_load(QXmlStreamReader &) {} +void Node::custom_load(QXmlStreamReader &) {} -void Effect::save(QXmlStreamWriter& stream) { +void Node::save(QXmlStreamWriter& stream) { /* stream.writeAttribute("name", meta->category + "/" + meta->name); stream.writeAttribute("enabled", QString::number(IsEnabled())); @@ -451,7 +446,7 @@ void Effect::save(QXmlStreamWriter& stream) { */ } -void Effect::load_from_string(const QByteArray &s) { +void Node::load_from_string(const QByteArray &s) { // clear existing keyframe data for (int i=0;ipath.isEmpty() || (shader_vert_path_.isEmpty() && shader_frag_path_.isEmpty())) return; QList effects_paths = get_effects_paths(); const QString& test_fn = shader_vert_path_.isEmpty() ? shader_frag_path_ : shader_vert_path_; @@ -534,9 +532,11 @@ void Effect::validate_meta_path() { return; } } + */ } -void Effect::open() { +void Node::open() { + /* if (isOpen) { qWarning() << "Tried to open an effect that was already open"; close(); @@ -548,7 +548,7 @@ void Effect::open() { validate_meta_path(); QString frag_shader_str; - QString frag_file_url = QDir(meta->path).filePath(shader_frag_path_); + 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(); @@ -570,41 +570,16 @@ void Effect::open() { shader_program_ = olive::shader::GetPipeline(shader_func, frag_shader_str); } - - /* - bool shader_compiled = true; - if (!shader_vert_path_.isEmpty()) { - if (shader_program_->addShaderFromSourceFile(QOpenGLShader::Vertex, meta->path + "/" + shader_vert_path_)) { - qInfo() << "Vertex shader added successfully"; - } else { - shader_compiled = false; - qWarning() << "Vertex shader could not be added"; - } - } - if (!shader_frag_path_.isEmpty()) { - if (shader_program_->addShaderFromSourceFile(QOpenGLShader::Fragment, meta->path + "/" + shader_frag_path_)) { - qInfo() << "Fragment shader added successfully"; - } else { - shader_compiled = false; - qWarning() << "Fragment shader could not be added"; - } - } - if (shader_compiled) { - if (shader_program_->link()) { - qInfo() << "Shader program linked successfully"; - } else { - qWarning() << "Shader program failed to link"; - } - } - */ isOpen = true; } } else { isOpen = true; } + */ + isOpen = true; } -void Effect::close() { +void Node::close() { if (!isOpen) { qWarning() << "Tried to close an effect that was already closed"; } @@ -613,43 +588,43 @@ void Effect::close() { isOpen = false; } -bool Effect::is_shader_linked() { +bool Node::is_shader_linked() { return shader_program_ != nullptr && shader_program_->isLinked(); } -QOpenGLShaderProgram *Effect::GetShaderPipeline() +QOpenGLShaderProgram *Node::GetShaderPipeline() { return shader_program_.get(); } -int Effect::Flags() +int Node::Flags() { return flags_; } -void Effect::SetFlags(int flags) +void Node::SetFlags(int flags) { flags_ = flags; } -int Effect::getIterations() { +int Node::getIterations() { return iterations; } -void Effect::setIterations(int i) { +void Node::setIterations(int i) { iterations = i; } -void Effect::process_image(double, uint8_t *, uint8_t *, int){} +void Node::process_image(double, uint8_t *, uint8_t *, int){} -EffectPtr Effect::copy(Clip *c) { - EffectPtr copy = Effect::Create(c, meta); +NodePtr Node::copy(Clip *c) { + NodePtr copy = Create(c); copy->SetEnabled(IsEnabled()); copy_field_keyframes(copy); return copy; } -void Effect::process_shader(double timecode, GLTextureCoords&, int iteration) { +void Node::process_shader(double timecode, GLTextureCoords&, int iteration) { /* shader_program_->bind(); @@ -704,9 +679,9 @@ void Effect::process_shader(double timecode, GLTextureCoords&, int iteration) { */ } -void Effect::process_coords(double, GLTextureCoords&, int) {} +void Node::process_coords(double, GLTextureCoords&, int) {} -GLuint Effect::process_superimpose(QOpenGLContext* ctx, double timecode) { +GLuint Node::process_superimpose(QOpenGLContext* ctx, double timecode) { bool dimensions_changed = false; bool redrew_image = false; @@ -760,11 +735,11 @@ GLuint Effect::process_superimpose(QOpenGLContext* ctx, double timecode) { return texture; } -void Effect::process_audio(double, double, float **, int, int, int) {} +void Node::process_audio(double, double, float **, int, int, int) {} -void Effect::gizmo_draw(double, GLTextureCoords &) {} +void Node::gizmo_draw(double, GLTextureCoords &) {} -void Effect::gizmo_move(EffectGizmo* gizmo, int x_movement, int y_movement, double timecode, bool done) { +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 0); } -double Effect::Now() +double Node::Now() { return playhead_to_clip_seconds(parent_clip, parent_clip->track()->sequence()->playhead); } -long Effect::NowInFrames() +long Node::NowInFrames() { return playhead_to_clip_frame(parent_clip, parent_clip->track()->sequence()->playhead); } -void Effect::redraw(double) { +void Node::redraw(double) { /* // run javascript QPainter p(&img); @@ -912,7 +887,7 @@ void Effect::redraw(double) { */ } -bool Effect::valueHasChanged(double timecode) { +bool Node::valueHasChanged(double timecode) { if (cachedValues.isEmpty()) { for (int i=0;ifunctions()->glDeleteTextures(1, &texture); texture = 0; @@ -951,7 +926,18 @@ void Effect::delete_texture() { } } -const EffectMeta* Effect::GetMetaFromName(const QString& input) { +int GetNodeLibraryIndexFromId(const QString& id) { + for (int i=0;iid() == id) { + return i; + } + } + + return -1; +} + +/* +const EffectMeta* Node::GetMetaFromName(const QString& input) { int split_index = input.indexOf('/'); QString category; if (split_index > -1) { @@ -968,3 +954,4 @@ const EffectMeta* Effect::GetMetaFromName(const QString& input) { } return nullptr; } +*/ diff --git a/effects/effect.h b/nodes/node.h similarity index 76% rename from effects/effect.h rename to nodes/node.h index ec1ebca23..c67a317af 100644 --- a/effects/effect.h +++ b/nodes/node.h @@ -40,44 +40,45 @@ #include #include -#include "ui/collapsiblewidget.h" -#include "effectrow.h" -#include "effectgizmo.h" +#include "timeline/tracktypes.h" #include "rendering/qopenglshaderprogramptr.h" -#include "nodes/inputs.h" +#include "inputs.h" +#include "effects/effectgizmo.h" + +class EffectGizmo; +class KeyframeDataChange; class Clip; +using ClipPtr = std::shared_ptr; -class Effect; -using EffectPtr = std::shared_ptr; +class Node; +using NodePtr = std::shared_ptr; -struct EffectMeta { - QString name; - QString category; - QString filename; - QString path; - QString tooltip; - int internal; - int type; - int subtype; +enum NodeType { + kTransformEffect, + kTextInput, + kSolidInput, + kNoiseInput, + kVolumeEffect, + kPanEffect, + kToneInput, + kShakeEffect, + kTimecodeEffect, + kMaskEffect, + kFillLeftRightEffect, + kVstEffect, + kCornerPinEffect, + kRichTextInput, + kMediaInput, + kShaderEffect, + kImageOutput, + kCrossDissolveTransition, + kLinearFadeTransition, + kExponentialFadeTransition, + kLogarithmicFadeTransition, + kInvalidNode }; -struct BlendMode { - QString name; - QString url; - QString function_name; - - bool loaded; -}; - -namespace olive { - extern QVector effects; - extern QVector blend_modes; - - // TODO weird place to put this? - extern QString generated_blending_shader; -} - double log_volume(double linear); enum EffectType { @@ -92,24 +93,6 @@ enum EffectKeyframeType { EFFECT_KEYFRAME_HOLD }; -enum EffectInternal { - EFFECT_INTERNAL_TRANSFORM, - EFFECT_INTERNAL_TEXT, - EFFECT_INTERNAL_SOLID, - EFFECT_INTERNAL_NOISE, - EFFECT_INTERNAL_VOLUME, - EFFECT_INTERNAL_PAN, - EFFECT_INTERNAL_TONE, - EFFECT_INTERNAL_SHAKE, - EFFECT_INTERNAL_TIMECODE, - EFFECT_INTERNAL_MASK, - EFFECT_INTERNAL_FILLLEFTRIGHT, - EFFECT_INTERNAL_VST, - EFFECT_INTERNAL_CORNERPIN, - EFFECT_INTERNAL_RICHTEXT, - EFFECT_INTERNAL_COUNT -}; - struct GLTextureCoords { QMatrix4x4 matrix; @@ -123,20 +106,25 @@ struct GLTextureCoords { QVector2D texture_bottom_left; QVector2D texture_bottom_right; - int blendmode; float opacity; }; -class Effect : public QObject { +class Node : public QObject { Q_OBJECT public: - Effect(Clip *c, const EffectMeta* em); - ~Effect(); + Node(Clip *c); + ~Node(); Clip* parent_clip; - const EffectMeta* meta; - int id; - QString name; + + 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); @@ -152,8 +140,8 @@ public: virtual void refresh(); - virtual EffectPtr copy(Clip* c); - void copy_field_keyframes(EffectPtr e); + virtual NodePtr copy(Clip* c); + void copy_field_keyframes(NodePtr e); virtual void load(QXmlStreamReader& stream); virtual void custom_load(QXmlStreamReader& stream); @@ -233,9 +221,6 @@ public: return distribution(generator); } - static EffectPtr Create(Clip *c, const EffectMeta *em); - static const EffectMeta* GetInternalMeta(int internal_id, int type); - static const EffectMeta* GetMetaFromName(const QString& input); public slots: void FieldChanged(); void SetEnabled(bool b); @@ -287,4 +272,8 @@ private: void validate_meta_path(); }; +namespace olive { + extern QVector node_library; +} + #endif // EFFECT_H diff --git a/nodes/nodegraph.cpp b/nodes/nodegraph.cpp index 381bd53cd..c2d912821 100644 --- a/nodes/nodegraph.cpp +++ b/nodes/nodegraph.cpp @@ -8,7 +8,7 @@ NodeGraph::NodeGraph() : } -Effect *NodeGraph::OutputNode() +Node *NodeGraph::OutputNode() { return output_node_.get(); } diff --git a/nodes/nodegraph.h b/nodes/nodegraph.h index a450abf16..4ce08b030 100644 --- a/nodes/nodegraph.h +++ b/nodes/nodegraph.h @@ -1,7 +1,7 @@ #ifndef NODEGRAPH_H #define NODEGRAPH_H -#include "effects/effect.h" +#include "nodes/node.h" class NodeGraph { @@ -15,7 +15,7 @@ public: * * @param node */ - void AddNode(EffectPtr node); + void AddNode(NodePtr node); /** * @brief Process the graph @@ -39,15 +39,15 @@ public: * * The node to set as the output node. The graph takes ownership of the node and the user cannot delete it. */ - void SetOutputNode(EffectPtr node); + void SetOutputNode(NodePtr node); /** * @brief Returns the currently set output node */ - Effect* OutputNode(); + Node* OutputNode(); private: - EffectPtr output_node_; + NodePtr output_node_; }; #endif // NODEGRAPH_H diff --git a/nodes/nodes/nodeimageoutput.cpp b/nodes/nodes/nodeimageoutput.cpp index b8b23c2fa..a6b2502c9 100644 --- a/nodes/nodes/nodeimageoutput.cpp +++ b/nodes/nodes/nodeimageoutput.cpp @@ -1,6 +1,42 @@ #include "nodeimageoutput.h" -NodeImageOutput::NodeImageOutput() +NodeImageOutput::NodeImageOutput(Clip *c) : + Node(c) { } + +QString NodeImageOutput::name() +{ + return tr("Image Output"); +} + +QString NodeImageOutput::id() +{ + return "org.olivevideoeditor.Olive.imageoutput"; +} + +QString NodeImageOutput::category() +{ + return tr("Outputs"); +} + +QString NodeImageOutput::description() +{ + return tr("Used for outputting images outside of the node graph."); +} + +EffectType NodeImageOutput::type() +{ + return EFFECT_TYPE_EFFECT; +} + +olive::TrackType NodeImageOutput::subtype() +{ + return olive::kTypeVideo; +} + +NodePtr NodeImageOutput::Create(Clip *c) +{ + return std::make_shared(c); +} diff --git a/nodes/nodes/nodeimageoutput.h b/nodes/nodes/nodeimageoutput.h index 69fc8ddea..c4ebd2798 100644 --- a/nodes/nodes/nodeimageoutput.h +++ b/nodes/nodes/nodeimageoutput.h @@ -1,11 +1,20 @@ #ifndef NODEIMAGEOUTPUT_H #define NODEIMAGEOUTPUT_H +#include "nodes/node.h" -class NodeImageOutput +class NodeImageOutput : public Node { public: - NodeImageOutput(); + NodeImageOutput(Clip* c); + + virtual QString name() override; + virtual QString id() override; + virtual QString category() override; + virtual QString description() override; + virtual EffectType type() override; + virtual olive::TrackType subtype() override; + virtual NodePtr Create(Clip *c) override; }; -#endif // NODEIMAGEOUTPUT_H \ No newline at end of file +#endif // NODEIMAGEOUTPUT_H diff --git a/nodes/nodes/nodemedia.cpp b/nodes/nodes/nodemedia.cpp index 7e62aaaae..0035e900c 100644 --- a/nodes/nodes/nodemedia.cpp +++ b/nodes/nodes/nodemedia.cpp @@ -1,6 +1,41 @@ #include "nodemedia.h" -NodeMedia::NodeMedia() +NodeMedia::NodeMedia(Clip* c) : + Node(c) { +} +QString NodeMedia::name() +{ + return tr("Media"); +} + +QString NodeMedia::id() +{ + return "org.olivevideoeditor.Olive.media"; +} + +QString NodeMedia::category() +{ + return tr("Inputs"); +} + +QString NodeMedia::description() +{ + return tr("Retrieve frames from a media source."); +} + +EffectType NodeMedia::type() +{ + return EFFECT_TYPE_EFFECT; +} + +olive::TrackType NodeMedia::subtype() +{ + return olive::kTypeVideo; +} + +NodePtr NodeMedia::Create(Clip *c) +{ + return std::make_shared(c); } diff --git a/nodes/nodes/nodemedia.h b/nodes/nodes/nodemedia.h index 9e7d87cf3..4d97716ca 100644 --- a/nodes/nodes/nodemedia.h +++ b/nodes/nodes/nodemedia.h @@ -1,10 +1,20 @@ #ifndef MEDIANODE_H #define MEDIANODE_H -class NodeMedia +#include "nodes/node.h" + +class NodeMedia : public Node { public: - NodeMedia(); + NodeMedia(Clip *c); + + virtual QString name() override; + virtual QString id() override; + virtual QString category() override; + virtual QString description() override; + virtual EffectType type() override; + virtual olive::TrackType subtype() override; + virtual NodePtr Create(Clip *c) override; }; #endif // MEDIANODE_H diff --git a/nodes/nodes/nodeshader.cpp b/nodes/nodes/nodeshader.cpp index 64bc64155..c71a3e1a1 100644 --- a/nodes/nodes/nodeshader.cpp +++ b/nodes/nodes/nodeshader.cpp @@ -1,10 +1,18 @@ #include "nodeshader.h" -NodeShader::NodeShader(Clip* c, const EffectMeta *em) : - Effect(c, em) +NodeShader::NodeShader(Clip* c, + const QString &name, + const QString &id, + const QString &category, + const QString &filename) : + Node(c), + name_(name), + id_(id), + category_(category), + filename_(filename) { - if (em != nullptr && !em->filename.isEmpty() && em->internal == -1) { - QFile effect_file(em->filename); + if (!filename_.isEmpty()) { + QFile effect_file(filename_); if (effect_file.open(QFile::ReadOnly)) { QXmlStreamReader reader(&effect_file); @@ -29,7 +37,7 @@ NodeShader::NodeShader(Clip* c, const EffectMeta *em) : } if (id.isEmpty() || name.isEmpty() || type == olive::nodes::kInvalid) { - qCritical() << "Couldn't load field from" << em->filename << "- ID, type, and name cannot be empty."; + qCritical() << "Couldn't load field from" << filename_ << "- ID, type, and name cannot be empty."; } else { EffectRow* field = nullptr; @@ -158,29 +166,56 @@ NodeShader::NodeShader(Clip* c, const EffectMeta *em) : shader_function_name_ = attr.value().toString(); } } - }/* else if (reader.name() == "superimpose" && reader.isStartElement()) { - enable_superimpose = true; - const QXmlStreamAttributes& attributes = reader.attributes(); - for (int i=0;ifilename; - enable_superimpose = false; - } - break; - } - } - }*/ + } else if (reader.name() == "description" && reader.isStartElement()) { + reader.readNext(); + description_ = reader.text().toString(); + } reader.readNext(); } effect_file.close(); } else { - qCritical() << "Failed to open effect file" << em->filename; + qCritical() << "Failed to open effect file" << filename; } } } + +QString NodeShader::name() +{ + return name_; +} + +QString NodeShader::id() +{ + return id_; +} + +QString NodeShader::category() +{ + return category_; +} + +QString NodeShader::description() +{ + return description_; +} + +EffectType NodeShader::type() +{ + return EFFECT_TYPE_EFFECT; +} + +olive::TrackType NodeShader::subtype() +{ + return olive::kTypeVideo; +} + +bool NodeShader::IsCreatable() +{ + return !filename_.isEmpty(); +} + +NodePtr NodeShader::Create(Clip *) +{ + Q_ASSERT(false); +} diff --git a/nodes/nodes/nodeshader.h b/nodes/nodes/nodeshader.h index 298e495cc..a9f401bbd 100644 --- a/nodes/nodes/nodeshader.h +++ b/nodes/nodes/nodeshader.h @@ -1,12 +1,32 @@ #ifndef NODESHADER_H #define NODESHADER_H -#include "effects/effect.h" +#include "nodes/node.h" -class NodeShader : public Effect { +class NodeShader : public Node { Q_OBJECT public: - NodeShader(Clip *c, const EffectMeta *em); + NodeShader(Clip *c, + const QString& name, + const QString& id, + const QString& category, + const QString& filename); + + virtual QString name() override; + virtual QString id() override; + virtual QString category() override; + virtual QString description() override; + virtual EffectType type() override; + virtual olive::TrackType subtype() override; + virtual bool IsCreatable() override; + virtual NodePtr Create(Clip *c) override; + +private: + QString name_; + QString id_; + QString category_; + QString description_; + QString filename_; }; #endif // NODESHADER_H diff --git a/nodes/widgets/buttonwidget.cpp b/nodes/widgets/buttonwidget.cpp index bde083736..c4e8f3690 100644 --- a/nodes/widgets/buttonwidget.cpp +++ b/nodes/widgets/buttonwidget.cpp @@ -1,6 +1,6 @@ #include "buttonwidget.h" -ButtonWidget::ButtonWidget(Effect* parent, const QString& name, const QString& text) : +ButtonWidget::ButtonWidget(Node* parent, const QString& name, const QString& text) : EffectRow(parent, nullptr, name, false, false) { ButtonField* button_field = new ButtonField(this, text); diff --git a/nodes/widgets/buttonwidget.h b/nodes/widgets/buttonwidget.h index e7e068f24..cd35ba7a9 100644 --- a/nodes/widgets/buttonwidget.h +++ b/nodes/widgets/buttonwidget.h @@ -6,7 +6,7 @@ class ButtonWidget : public EffectRow { public: - ButtonWidget(Effect* parent, const QString& name, const QString& text); + ButtonWidget(Node* parent, const QString& name, const QString& text); /** * @brief Wrapper for ButtonField::SetCheckable. diff --git a/nodes/widgets/labelwidget.cpp b/nodes/widgets/labelwidget.cpp index 02396436c..6d22601c8 100644 --- a/nodes/widgets/labelwidget.cpp +++ b/nodes/widgets/labelwidget.cpp @@ -1,6 +1,6 @@ #include "labelwidget.h" -LabelWidget::LabelWidget(Effect *parent, const QString &name, const QString &text) : +LabelWidget::LabelWidget(Node *parent, const QString &name, const QString &text) : EffectRow(parent, nullptr, name, false, false) { AddField(new LabelField(this, text)); diff --git a/nodes/widgets/labelwidget.h b/nodes/widgets/labelwidget.h index af066f9a4..97e86d158 100644 --- a/nodes/widgets/labelwidget.h +++ b/nodes/widgets/labelwidget.h @@ -6,7 +6,7 @@ class LabelWidget : public EffectRow { public: - LabelWidget(Effect* parent, const QString& name, const QString& text); + LabelWidget(Node* parent, const QString& name, const QString& text); }; #endif // LABELWIDGET_H diff --git a/olive.pro b/olive.pro index f737408d5..9d4b6542d 100644 --- a/olive.pro +++ b/olive.pro @@ -106,7 +106,6 @@ SOURCES += \ effects/internal/logarithmicfadetransition.cpp \ effects/internal/cornerpineffect.cpp \ global/math.cpp \ - effects/effect.cpp \ effects/effectrow.cpp \ effects/effectgizmo.cpp \ ui/resizablescrollbar.cpp \ @@ -207,7 +206,8 @@ SOURCES += \ nodes/nodes/nodemedia.cpp \ nodes/nodes/nodeshader.cpp \ decoders/ffmpegdecoder.cpp \ - decoders/decoder.cpp + decoders/decoder.cpp \ + nodes/node.cpp HEADERS += \ ui/mainwindow.h \ @@ -265,7 +265,6 @@ HEADERS += \ effects/internal/logarithmicfadetransition.h \ effects/internal/cornerpineffect.h \ global/math.h \ - effects/effect.h \ effects/effectrow.h \ effects/internal/cubetransition.h \ effects/effectgizmo.h \ @@ -371,7 +370,9 @@ HEADERS += \ nodes/nodes/nodeshader.h \ nodes/nodes.h \ decoders/ffmpegdecoder.h \ - decoders/decoder.h + decoders/decoder.h \ + nodes/node.h \ + timeline/tracktypes.h FORMS += diff --git a/panels/effectcontrols.cpp b/panels/effectcontrols.cpp index 1c92954f8..bc81c16a2 100644 --- a/panels/effectcontrols.cpp +++ b/panels/effectcontrols.cpp @@ -32,7 +32,7 @@ #include #include "panels/panels.h" -#include "effects/effect.h" +#include "nodes/node.h" #include "effects/effectloaders.h" #include "effects/transition.h" #include "timeline/clip.h" @@ -95,24 +95,24 @@ void EffectControls::menu_select(QAction* q) { for (int i=0;itype() == effect_menu_subtype) { - const EffectMeta* meta = reinterpret_cast(q->data().value()); + NodeType node_type = static_cast(q->data().toInt()); if (effect_menu_type == EFFECT_TYPE_TRANSITION) { if (c->opening_transition == nullptr) { ca->append(new AddTransitionCommand(c, nullptr, nullptr, - meta, + node_type, olive::config.default_transition_length)); } if (c->closing_transition == nullptr) { ca->append(new AddTransitionCommand(nullptr, c, nullptr, - meta, + node_type, olive::config.default_transition_length)); } } else { - ca->append(new AddEffectCommand(c, nullptr, meta)); + ca->append(new AddEffectCommand(c, nullptr, node_type)); } } } @@ -138,7 +138,7 @@ void EffectControls::scroll_to_frame(long frame) { scroll_to_frame_internal(horizontalScrollBar, frame - keyframeView->visible_in, zoom, keyframeView->width()); } -void EffectControls::show_effect_menu(int type, Track::Type subtype) { +void EffectControls::show_effect_menu(EffectType type, olive::TrackType subtype) { effect_menu_type = type; effect_menu_subtype = subtype; @@ -147,24 +147,25 @@ void EffectControls::show_effect_menu(int type, Track::Type subtype) { Menu effects_menu(this); effects_menu.setToolTipsVisible(true); - for (int i=0;itype() == type && node->subtype() == subtype) { QAction* action = new QAction(&effects_menu); - action->setText(em.name); - action->setData(reinterpret_cast(&em)); - if (!em.tooltip.isEmpty()) { - action->setToolTip(em.tooltip); + action->setText(node->name()); + action->setData(i); + if (!node->description().isEmpty()) { + action->setToolTip(node->description()); } QMenu* parent = &effects_menu; - if (!em.category.isEmpty()) { + if (!node->category().isEmpty()) { bool found = false; for (int j=0;jmenu() != nullptr) { - if (action->menu()->title() == em.category) { + if (action->menu()->title() == node->category()) { parent = action->menu(); found = true; break; @@ -174,12 +175,12 @@ void EffectControls::show_effect_menu(int type, Track::Type subtype) { if (!found) { parent = new Menu(&effects_menu); parent->setToolTipsVisible(true); - parent->setTitle(em.category); + parent->setTitle(node->category()); bool found = false; for (int i=0;itext() > em.category) { + if (comp_action->text() > node->category()) { effects_menu.insertMenu(comp_action, parent); found = true; break; @@ -444,19 +445,19 @@ bool EffectControls::focused() } void EffectControls::video_effect_click() { - show_effect_menu(EFFECT_TYPE_EFFECT, Track::kTypeVideo); + show_effect_menu(EFFECT_TYPE_EFFECT, olive::kTypeVideo); } void EffectControls::audio_effect_click() { - show_effect_menu(EFFECT_TYPE_EFFECT, Track::kTypeAudio); + show_effect_menu(EFFECT_TYPE_EFFECT, olive::kTypeAudio); } void EffectControls::video_transition_click() { - show_effect_menu(EFFECT_TYPE_TRANSITION, Track::kTypeVideo); + show_effect_menu(EFFECT_TYPE_TRANSITION, olive::kTypeVideo); } void EffectControls::audio_transition_click() { - show_effect_menu(EFFECT_TYPE_TRANSITION, Track::kTypeAudio); + show_effect_menu(EFFECT_TYPE_TRANSITION, olive::kTypeAudio); } void EffectControls::resizeEvent(QResizeEvent*) { @@ -491,12 +492,12 @@ void EffectControls::LoadEvent() QVBoxLayout* layout = nullptr; EffectUI* container = open_effects_.at(i); - Effect* e = open_effects_.at(i)->GetEffect(); + Node* e = open_effects_.at(i)->GetEffect(); - if (e->meta->subtype == Track::kTypeVideo) { + if (e->subtype() == olive::kTypeVideo) { vcontainer->setVisible(true); layout = video_effect_layout; - } else if (e->meta->subtype == Track::kTypeAudio) { + } else if (e->subtype() == olive::kTypeAudio) { acontainer->setVisible(true); layout = audio_effect_layout; } diff --git a/panels/effectcontrols.h b/panels/effectcontrols.h index fabe93116..1387744f4 100644 --- a/panels/effectcontrols.h +++ b/panels/effectcontrols.h @@ -94,14 +94,14 @@ protected: virtual void ClearEvent() override; virtual void LoadEvent() override; private: - void show_effect_menu(int type, Track::Type subtype); + void show_effect_menu(EffectType type, olive::TrackType subtype); void load_keyframes(); void UpdateTitle(); void setup_ui(); int effect_menu_type; - Track::Type effect_menu_subtype; + olive::TrackType effect_menu_subtype; QString panel_name; QWidget* video_effect_area; diff --git a/panels/effectspanel.cpp b/panels/effectspanel.cpp index cd99fc6d9..3c76db66b 100644 --- a/panels/effectspanel.cpp +++ b/panels/effectspanel.cpp @@ -76,7 +76,7 @@ void EffectsPanel::Load() { Clip* c = selected_clips_.at(i); // Create a list of the effects we'll open - QVector effects_to_open; + QVector effects_to_open; // Determine based on the current selections whether to load all effects or just the transitions bool whole_clip_is_selected = c->IsSelected(); @@ -100,7 +100,7 @@ void EffectsPanel::Load() { // Check if we've already opened an effect of this type before bool already_opened = false; for (int k=0;kGetEffect()->meta == effects_to_open.at(j)->meta + if (open_effects_.at(k)->GetEffect()->id() == effects_to_open.at(j)->id() && !open_effects_.at(k)->IsAttachedToClip(c)) { open_effects_.at(k)->AddAdditionalEffect(effects_to_open.at(j)); @@ -137,7 +137,7 @@ void EffectsPanel::Load() { LoadEvent(); } -bool EffectsPanel::IsEffectSelected(Effect *e) +bool EffectsPanel::IsEffectSelected(Node *e) { for (int i=0;iGetEffect() == e && open_effects_.at(i)->IsSelected()) { @@ -174,9 +174,9 @@ void EffectsPanel::copy(bool del) { for (int i=0;iIsSelected()) { - Effect* e = open_effects_.at(i)->GetEffect(); + Node* e = open_effects_.at(i)->GetEffect(); - if (e->meta->type == EFFECT_TYPE_EFFECT) { + if (e->type() == EFFECT_TYPE_EFFECT) { if (!cleared) { olive::clipboard.Clear(); @@ -205,12 +205,12 @@ void EffectsPanel::copy(bool del) { } } -void EffectsPanel::DeleteEffect(ComboAction* ca, Effect* effect_ref) { - if (effect_ref->meta->type == EFFECT_TYPE_EFFECT) { +void EffectsPanel::DeleteEffect(ComboAction* ca, Node* effect_ref) { + if (effect_ref->type() == EFFECT_TYPE_EFFECT) { ca->append(new EffectDeleteCommand(effect_ref)); - } else if (effect_ref->meta->type == EFFECT_TYPE_TRANSITION) { + } else if (effect_ref->type() == EFFECT_TYPE_TRANSITION) { // Retrieve shared ptr for this transition @@ -258,7 +258,7 @@ void EffectsPanel::DeleteSelectedEffects() { } } -void EffectsPanel::open_effect(Effect* e) { +void EffectsPanel::open_effect(Node* e) { EffectUI* container = new EffectUI(e); connect(container, SIGNAL(CutRequested()), this, SLOT(cut())); diff --git a/panels/effectspanel.h b/panels/effectspanel.h index cb1617b7a..e3d52bd5e 100644 --- a/panels/effectspanel.h +++ b/panels/effectspanel.h @@ -18,7 +18,7 @@ public: virtual bool focused() override; - bool IsEffectSelected(Effect* e); + bool IsEffectSelected(Node* e); void DeleteSelectedEffects(); public slots: @@ -32,8 +32,8 @@ protected: QVector open_effects_; private: void Load(); - void open_effect(Effect *e); - void DeleteEffect(ComboAction* ca, Effect* effect_ref); + void open_effect(Node *e); + void DeleteEffect(ComboAction* ca, Node* effect_ref); private slots: void deselect_all_effects(QWidget*); }; diff --git a/panels/grapheditor.cpp b/panels/grapheditor.cpp index 370a0cb09..9622a5831 100644 --- a/panels/grapheditor.cpp +++ b/panels/grapheditor.cpp @@ -30,7 +30,7 @@ #include "timeline/timelinetools.h" #include "ui/labelslider.h" #include "ui/graphview.h" -#include "effects/effect.h" +#include "nodes/node.h" #include "effects/effectfields.h" #include "effects/effectrow.h" #include "timeline/clip.h" @@ -210,7 +210,7 @@ void GraphEditor::set_row(EffectRow *r) { if (found_vals) { row = r; current_row_desc->setText(row->GetParentEffect()->parent_clip->name() - + " :: " + row->GetParentEffect()->meta->name + + " :: " + row->GetParentEffect()->name() + " :: " + row->name()); header->set_visible_in(r->GetParentEffect()->parent_clip->timeline_in()); diff --git a/panels/timeline.cpp b/panels/timeline.cpp index bc3b8774a..e23f7e125 100644 --- a/panels/timeline.cpp +++ b/panels/timeline.cpp @@ -221,10 +221,10 @@ void Timeline::SetSequence(SequencePtr sequence) return; } - sequence_ = sequence; + sequence_ = sequence; update_sequence(); - video_area->SetTrackList(sequence_.get(), Track::kTypeVideo); - audio_area->SetTrackList(sequence_.get(), Track::kTypeAudio); + video_area->SetTrackList(sequence_.get(), olive::kTypeVideo); + audio_area->SetTrackList(sequence_.get(), olive::kTypeAudio); repaint_timeline(); emit SequenceChanged(sequence_); @@ -276,14 +276,14 @@ void Timeline::add_transition() { for (int i=0;itype() == Track::kTypeVideo) ? TRANSITION_INTERNAL_CROSSDISSOLVE - : TRANSITION_INTERNAL_LINEARFADE; + NodeType transition_to_add = (c->type() == olive::kTypeVideo) ? kCrossDissolveTransition + : kLinearFadeTransition; if (c->opening_transition == nullptr) { ca->append(new AddTransitionCommand(c, nullptr, nullptr, - Effect::GetInternalMeta(transition_to_add, EFFECT_TYPE_TRANSITION), + transition_to_add, olive::config.default_transition_length)); adding = true; } @@ -292,7 +292,7 @@ void Timeline::add_transition() { ca->append(new AddTransitionCommand(nullptr, c, nullptr, - Effect::GetInternalMeta(transition_to_add, EFFECT_TYPE_TRANSITION), + transition_to_add, olive::config.default_transition_length)); adding = true; } @@ -873,23 +873,23 @@ void Timeline::transition_tool_click() { Menu transition_menu(this); - for (int i=0;itype() == EFFECT_TYPE_TRANSITION && node->subtype() == olive::kTypeVideo) { + QAction* a = transition_menu.addAction(node->name()); a->setObjectName("v"); - a->setData(reinterpret_cast(&em)); + a->setData(i); } } transition_menu.addSeparator(); - for (int i=0;itype() == EFFECT_TYPE_TRANSITION && node->subtype() == olive::kTypeVideo) { + QAction* a = transition_menu.addAction(node->name()); a->setObjectName("a"); - a->setData(reinterpret_cast(&em)); + a->setData(i); } } @@ -901,12 +901,12 @@ void Timeline::transition_tool_click() { } void Timeline::transition_menu_select(QAction* a) { - transition_tool_meta = reinterpret_cast(a->data().value()); + transition_tool_meta = static_cast(a->data().toInt()); if (a->objectName() == "v") { - transition_tool_side = Track::kTypeVideo; + transition_tool_side = olive::kTypeVideo; } else { - transition_tool_side = Track::kTypeAudio; + transition_tool_side = olive::kTypeAudio; } timeline_area->setCursor(Qt::CrossCursor); diff --git a/panels/timeline.h b/panels/timeline.h index 0606aef06..ba47ca69d 100644 --- a/panels/timeline.h +++ b/panels/timeline.h @@ -114,8 +114,8 @@ public: bool transition_tool_proc; Clip* transition_tool_open_clip; Clip* transition_tool_close_clip; - const EffectMeta* transition_tool_meta; - Track::Type transition_tool_side; + NodeType transition_tool_meta; + olive::TrackType transition_tool_side; // hand tool variables bool hand_moving; diff --git a/panels/viewer.cpp b/panels/viewer.cpp index 79ec033bd..f0c6756a5 100644 --- a/panels/viewer.cpp +++ b/panels/viewer.cpp @@ -752,7 +752,7 @@ void Viewer::set_media(Media* m) { new_sequence->frame_rate = video_stream.video_frame_rate * footage->speed; } - ClipPtr c = std::make_shared(new_sequence->GetTrackList(Track::kTypeVideo)->First()); + ClipPtr c = std::make_shared(new_sequence->GetTrackList(olive::kTypeVideo)->First()); c->set_media(media, video_stream.file_index); c->set_timeline_in(0); c->set_timeline_out(footage->get_length_in_frames(new_sequence->frame_rate)); @@ -760,7 +760,7 @@ void Viewer::set_media(Media* m) { // FIXME: Move this magic number to Config c->set_timeline_out(150); } - Track* track = new_sequence->GetTrackList(Track::kTypeVideo)->First(); + Track* track = new_sequence->GetTrackList(olive::kTypeVideo)->First(); c->set_track(track); c->set_clip_in(0); c->refresh(); @@ -774,7 +774,7 @@ void Viewer::set_media(Media* m) { const FootageStream& audio_stream = footage->audio_tracks.at(0); new_sequence->audio_frequency = audio_stream.audio_frequency; - Track* track = new_sequence->GetTrackList(Track::kTypeAudio)->First(); + Track* track = new_sequence->GetTrackList(olive::kTypeAudio)->First(); ClipPtr c = std::make_shared(track); c->set_media(media, audio_stream.file_index); c->set_timeline_in(0); diff --git a/project/loadthread.cpp b/project/loadthread.cpp index a6a82ea64..dee719ecc 100644 --- a/project/loadthread.cpp +++ b/project/loadthread.cpp @@ -60,7 +60,7 @@ void LoadThread::load_effect(QXmlStreamReader& stream, Clip* c) { QString tag = stream.name().toString(); // variables to store effect metadata in - int effect_id = -1; + QString effect_id; QString effect_name; bool effect_enabled = true; long effect_length = -1; @@ -68,10 +68,10 @@ void LoadThread::load_effect(QXmlStreamReader& stream, Clip* c) { // loop through attributes for effect metadata for (int j=0;jid() == effect_id) { + type = static_cast(i); + break; + } + } } olive::effects_loaded.unlock(); - int type; + TransitionType ttype; if (tag == "opening") { - type = kTransitionOpening; + ttype = kTransitionOpening; } else if (tag == "closing") { - type = kTransitionClosing; + ttype = kTransitionClosing; } else { - type = kTransitionNone; + ttype = kTransitionNone; } // effect construction if (cancelled_) return; - if (type == kTransitionNone) { - if (meta == nullptr) { + if (ttype == kTransitionNone) { + if (type == kInvalidNode) { // create void effect - EffectPtr ve(new VoidEffect(c, effect_name)); + NodePtr ve = std::make_shared(c, effect_name, effect_id); ve->SetEnabled(effect_enabled); ve->load(stream); @@ -147,7 +152,7 @@ void LoadThread::load_effect(QXmlStreamReader& stream, Clip* c) { c->effects.append(ve); } else { - EffectPtr e(Effect::Create(c, meta)); + NodePtr e = olive::node_library[type]->Create(c); e->SetEnabled(effect_enabled); e->load(stream); @@ -156,14 +161,16 @@ void LoadThread::load_effect(QXmlStreamReader& stream, Clip* c) { c->effects.append(e); } } else { - TransitionPtr t = Transition::Create(c, nullptr, meta); - if (effect_length > -1) t->set_length(effect_length); + TransitionPtr t = std::static_pointer_cast(olive::node_library[type]->Create(c)); + if (effect_length > -1) { + t->set_length(effect_length); + } t->SetEnabled(effect_enabled); t->load(stream); t->moveToThread(QApplication::instance()->thread()); - if (type == kTransitionOpening) { + if (ttype == kTransitionOpening) { c->opening_transition = t; } else { c->closing_transition = t; diff --git a/rendering/cacher.cpp b/rendering/cacher.cpp index ed1c770cc..61abd3292 100644 --- a/rendering/cacher.cpp +++ b/rendering/cacher.cpp @@ -62,7 +62,7 @@ void apply_audio_effects(Clip* clip, double timecode_start, AVFrame* frame, int timecode_end = timecode_start + samples_to_seconds(nb_samples, frame->channels, frame->sample_rate); for (int j=0;jeffects.size();j++) { - Effect* e = clip->effects.at(j).get(); + Node* e = clip->effects.at(j).get(); if (e->IsEnabled()) { e->process_audio(timecode_start, timecode_end, reinterpret_cast(frame->data), nb_samples, nb_channels, kTransitionNone); } @@ -805,7 +805,7 @@ void Cacher::CacheVideoWorker() { void Cacher::Reset() { // if we seek to a whole other place in the timeline, we'll need to reset the cache with new values if (clip->media() == nullptr) { - if (clip->type() == Track::kTypeAudio) { + if (clip->type() == olive::kTypeAudio) { // a null-media audio clip is usually an auto-generated sound clip such as Tone or Noise reached_end = false; audio_target_frame = playhead_; @@ -871,7 +871,7 @@ Cacher::Cacher(Clip* c) : void Cacher::OpenWorker() { // set some defaults for the audio cacher - if (clip->type() == Track::kTypeAudio) { + if (clip->type() == olive::kTypeAudio) { audio_reset_ = false; frame_sample_index_ = -1; audio_buffer_write = 0; @@ -879,7 +879,7 @@ void Cacher::OpenWorker() { reached_end = false; if (clip->media() == nullptr) { - if (clip->type() == Track::kTypeAudio) { + if (clip->type() == olive::kTypeAudio) { frame_ = av_frame_alloc(); frame_->format = kDestSampleFmt; frame_->channel_layout = clip->track()->sequence()->audio_layout; @@ -1127,7 +1127,7 @@ void Cacher::OpenWorker() { } void Cacher::CacheWorker() { - if (clip->type() == Track::kTypeVideo) { + if (clip->type() == olive::kTypeVideo) { // clip is a video track, start caching video CacheVideoWorker(); } else { @@ -1218,7 +1218,7 @@ void Cacher::Open() caching_ = true; queued_ = false; - start((clip->type() == Track::kTypeVideo) ? QThread::HighPriority : QThread::TimeCriticalPriority); + start((clip->type() == olive::kTypeVideo) ? QThread::HighPriority : QThread::TimeCriticalPriority); } void Cacher::Cache(long playhead, bool scrubbing, QVector& nests, int playback_speed) diff --git a/rendering/renderfunctions.cpp b/rendering/renderfunctions.cpp index 054a41f2e..ba1e94778 100644 --- a/rendering/renderfunctions.cpp +++ b/rendering/renderfunctions.cpp @@ -34,7 +34,7 @@ extern "C" { #include "timeline/clip.h" #include "timeline/sequence.h" #include "project/media.h" -#include "effects/effect.h" +#include "nodes/node.h" #include "project/footage.h" #include "effects/transition.h" #include "ui/collapsiblewidget.h" @@ -110,7 +110,6 @@ void olive::rendering::Blit(QOpenGLShaderProgram* pipeline, bool flipped, QMatri pipeline->setUniformValue("mvp_matrix", matrix); pipeline->setUniformValue("texture", 0); - GLuint vertex_location = pipeline->attributeLocation("a_position"); m_vbo.bind(); func->glEnableVertexAttribArray(vertex_location); @@ -176,7 +175,7 @@ GLuint draw_clip(QOpenGLContext* ctx, void process_effect(QOpenGLContext* ctx, QOpenGLShaderProgram* pipeline, Clip* c, - Effect* e, + Node* e, double timecode, GLTextureCoords& coords, GLuint& composite_texture, @@ -184,11 +183,11 @@ void process_effect(QOpenGLContext* ctx, bool& texture_failed, int data) { if (e->IsEnabled()) { - if (e->Flags() & Effect::CoordsFlag) { + if (e->Flags() & Node::CoordsFlag) { e->process_coords(timecode, coords, data); } - bool can_process_shaders = ((e->Flags() & Effect::ShaderFlag) && olive::runtime_config.shaders_are_enabled); - if (can_process_shaders || (e->Flags() & Effect::SuperimposeFlag)) { + bool can_process_shaders = ((e->Flags() & Node::ShaderFlag) && olive::runtime_config.shaders_are_enabled); + if (can_process_shaders || (e->Flags() & Node::SuperimposeFlag)) { if (!e->is_open()) { e->open(); @@ -201,7 +200,7 @@ void process_effect(QOpenGLContext* ctx, fbo_switcher = !fbo_switcher; } } - if (e->Flags() & Effect::SuperimposeFlag) { + if (e->Flags() & Node::SuperimposeFlag) { GLuint superimpose_texture = e->process_superimpose(ctx, timecode); if (superimpose_texture == 0) { @@ -227,7 +226,7 @@ void process_effect(QOpenGLContext* ctx, } GLuint olive::rendering::compose_sequence(ComposeSequenceParams ¶ms) { - GLuint final_fbo = params.type == Track::kTypeVideo ? params.main_buffer->buffer() : 0; + GLuint final_fbo = params.type == olive::kTypeVideo ? params.main_buffer->buffer() : 0; Sequence* s = params.seq; long playhead = s->playhead; @@ -240,7 +239,7 @@ GLuint olive::rendering::compose_sequence(ComposeSequenceParams ¶ms) { playhead = rescale_frame_number(playhead, params.nests.at(i)->track()->sequence()->frame_rate, s->frame_rate); } - if (params.type == Track::kTypeVideo && !params.nests.last()->fbo.isEmpty()) { + if (params.type == olive::kTypeVideo && !params.nests.last()->fbo.isEmpty()) { params.nests.last()->fbo.at(0).BindBuffer(); params.ctx->functions()->glClear(GL_COLOR_BUFFER_BIT); final_fbo = params.nests.last()->fbo.at(0).buffer(); @@ -270,7 +269,7 @@ GLuint olive::rendering::compose_sequence(ComposeSequenceParams ¶ms) { Footage* m = c->media()->to_footage(); // does the clip have a valid media source? - if (!m->invalid && !(c->type() == Track::kTypeAudio && !is_audio_device_set())) { + if (!m->invalid && !(c->type() == olive::kTypeAudio && !is_audio_device_set())) { // is the media process and ready? if (m->ready) { @@ -287,7 +286,7 @@ GLuint olive::rendering::compose_sequence(ComposeSequenceParams ¶ms) { clip_is_active = true; // increment audio track count - if (c->type() == Track::kTypeAudio) audio_track_count++; + if (c->type() == olive::kTypeAudio) audio_track_count++; } else if (c->IsOpen()) { @@ -321,7 +320,7 @@ GLuint olive::rendering::compose_sequence(ComposeSequenceParams ¶ms) { // track sorting is only necessary for video clips // audio clips are mixed equally, so we skip sorting for those - if (params.type == Track::kTypeVideo) { + if (params.type == olive::kTypeVideo) { // insertion sort by track for (int j=0;jfunctions()->glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA); @@ -370,7 +369,7 @@ GLuint olive::rendering::compose_sequence(ComposeSequenceParams ¶ms) { if (got_mutex && c->IsOpen()) { // if clip is a video clip - if (c->type() == Track::kTypeVideo) { + if (c->type() == olive::kTypeVideo) { // textureID variable contains texture to be drawn on screen at the end GLuint textureID = 0; @@ -504,7 +503,6 @@ GLuint olive::rendering::compose_sequence(ComposeSequenceParams ¶ms) { coords.texture_top_right = QVector2D(1.0f, 0.0f); coords.texture_bottom_left = QVector2D(0.0f, 1.0f); coords.texture_bottom_right = QVector2D(1.0f, 1.0f); - coords.blendmode = -1; coords.opacity = 1.0; // == EFFECT CODE START == @@ -515,7 +513,7 @@ GLuint olive::rendering::compose_sequence(ComposeSequenceParams ¶ms) { // run through all of the clip's effects for (int j=0;jeffects.size();j++) { - Effect* e = c->effects.at(j).get(); + Node* e = c->effects.at(j).get(); process_effect(params.ctx, params.pipeline, c, e, timecode, coords, textureID, fbo_switcher, params.texture_failed, kTransitionNone); } @@ -685,9 +683,11 @@ GLuint olive::rendering::compose_sequence(ComposeSequenceParams ¶ms) { // copy front buffer to back buffer (only if we're using a blending mode) + /* if (coords.blendmode >= 0) { draw_clip(params.ctx, params.pipeline, back_buffer_2, comp_texture, true); } + */ @@ -700,7 +700,7 @@ GLuint olive::rendering::compose_sequence(ComposeSequenceParams ¶ms) { params.ctx->functions()->glBindFramebuffer(GL_DRAW_FRAMEBUFFER, final_fbo); // Check if we're using a blend mode (< 0 means no blend mode) - if (coords.blendmode < 0) { + //if (coords.blendmode < 0) { params.ctx->functions()->glBindTexture(GL_TEXTURE_2D, backend_tex_1); @@ -708,7 +708,9 @@ GLuint olive::rendering::compose_sequence(ComposeSequenceParams ¶ms) { params.ctx->functions()->glBindTexture(GL_TEXTURE_2D, 0); - } else { + //} else { + + /* // load background texture into texture unit 0 params.ctx->functions()->glActiveTexture(GL_TEXTURE0 + 0); // Texture unit 0 @@ -739,7 +741,9 @@ GLuint olive::rendering::compose_sequence(ComposeSequenceParams ¶ms) { params.ctx->functions()->glActiveTexture(GL_TEXTURE0 + 0); // Texture unit 0 params.ctx->functions()->glBindTexture(GL_TEXTURE_2D, 0); - } + */ + + //} // unbind framebuffer params.ctx->functions()->glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); @@ -750,7 +754,7 @@ GLuint olive::rendering::compose_sequence(ComposeSequenceParams ¶ms) { // == END FINAL DRAW ON SEQUENCE BUFFER == } } - } else if (c->type() == Track::kTypeAudio) { + } else if (c->type() == olive::kTypeAudio) { if (c->media() != nullptr && c->media()->get_type() == MEDIA_TYPE_SEQUENCE) { params.nests.append(c); compose_sequence(params); @@ -795,11 +799,10 @@ void olive::rendering::compose_audio(Viewer* viewer, Sequence* seq, int playback params.viewer = viewer; params.ctx = nullptr; params.seq = seq; - params.type = Track::kTypeAudio; + params.type = olive::kTypeAudio; params.gizmos = nullptr; params.wait_for_mutexes = wait_for_mutexes; params.playback_speed = playback_speed; - params.blend_mode_program = nullptr; compose_sequence(params); } diff --git a/rendering/renderfunctions.h b/rendering/renderfunctions.h index e38ee8bb6..658ecc422 100644 --- a/rendering/renderfunctions.h +++ b/rendering/renderfunctions.h @@ -28,7 +28,7 @@ namespace OCIO = OCIO_NAMESPACE::v1; #include "timeline/sequence.h" -#include "effects/effect.h" +#include "nodes/node.h" #include "panels/viewer.h" /** @@ -80,16 +80,16 @@ struct ComposeSequenceParams { /** * @brief Set compose mode to video or audio * - * Accepts Track::kTypeVideo to render video, Track::kTypeAudio if this function should render audio. + * Accepts olive::kTypeVideo to render video, olive::kTypeAudio if this function should render audio. */ - Track::Type type; + olive::TrackType type; /** * @brief Set to the Effect whose gizmos were chosen to be drawn on screen * * The currently active Effect that compose_sequence() will update the gizmos of. */ - Effect* gizmos; + Node* gizmos; /** * @brief A variable that compose_sequence() will set to **TRUE** if any of the clips couldn't be shown. @@ -138,19 +138,6 @@ struct ComposeSequenceParams { */ int playback_speed; - /** - * @brief Blending mode shader - * - * Used only for video rendering. Never accessed with audio rendering. - * - * A program containing the current active - * blending mode shader that can be bound during rendering. Must be compiled and linked beforehand. See - * RenderThread::blend_mode_program for how this is properly set up. - * - * \see ComposeSequenceParams::video - */ - QOpenGLShaderProgram* blend_mode_program; - /** * @brief Premultiply alpha shader * diff --git a/rendering/renderthread.cpp b/rendering/renderthread.cpp index c92b323bd..ea6f9dacd 100644 --- a/rendering/renderthread.cpp +++ b/rendering/renderthread.cpp @@ -40,7 +40,6 @@ RenderThread::RenderThread() : gizmos(nullptr), share_ctx(nullptr), ctx(nullptr), - blend_mode_program(nullptr), seq(nullptr), tex_width(-1), tex_height(-1), @@ -50,7 +49,8 @@ RenderThread::RenderThread() : ocio_shader(nullptr), running(true), ocio_config_date(0), - front_buffer_switcher(false) + front_buffer_switcher(false), + pipeline_program(nullptr) { surface.create(); } @@ -101,17 +101,10 @@ void RenderThread::run() { back_buffer_2.Create(ctx, seq->width, seq->height); } - // If there's no blending mode shader, create it now - if (blend_mode_program == nullptr) { + // If there's no pipeline shader, create it now + if (pipeline_program == nullptr) { delete_shaders(); - blend_mode_program = std::make_shared(); - blend_mode_program->addShaderFromSourceFile(QOpenGLShader::Vertex, ":/internalshaders/common.vert"); - olive::effects_loaded.lock(); - blend_mode_program->addShaderFromSourceCode(QOpenGLShader::Fragment, olive::generated_blending_shader); - olive::effects_loaded.unlock(); - blend_mode_program->link(); - pipeline_program = olive::shader::GetPipeline(); } @@ -206,11 +199,10 @@ void RenderThread::paint() { params.viewer = nullptr; params.ctx = ctx; params.seq = seq; - params.type = Track::kTypeVideo; + params.type = olive::kTypeVideo; params.texture_failed = false; params.wait_for_mutexes = true; params.playback_speed = playback_speed_; - params.blend_mode_program = blend_mode_program.get(); params.pipeline = pipeline_program.get(); params.backend_buffer1 = &back_buffer_1; params.backend_buffer2 = &back_buffer_2; @@ -380,7 +372,6 @@ void RenderThread::delete_buffers() { } void RenderThread::delete_shaders() { - blend_mode_program = nullptr; pipeline_program = nullptr; } diff --git a/rendering/renderthread.h b/rendering/renderthread.h index 89e33f521..cea0a7099 100644 --- a/rendering/renderthread.h +++ b/rendering/renderthread.h @@ -30,7 +30,7 @@ #include #include "timeline/sequence.h" -#include "effects/effect.h" +#include "nodes/node.h" #include "rendering/framebufferobject.h" #include "qopenglshaderprogramptr.h" @@ -44,7 +44,7 @@ public: QMutex* get_texture_mutex(); const GLuint& get_texture(); - Effect* gizmos; + Node* gizmos; void paint(); void start_render(QOpenGLContext* share, Sequence *s, @@ -94,7 +94,6 @@ private: QOffscreenSurface surface; QOpenGLContext* share_ctx; QOpenGLContext* ctx; - QOpenGLShaderProgramPtr blend_mode_program; QOpenGLShaderProgramPtr pipeline_program; FramebufferObject back_buffer_1; diff --git a/timeline/clip.cpp b/timeline/clip.cpp index 2dcdd9f76..57e705fb3 100644 --- a/timeline/clip.cpp +++ b/timeline/clip.cpp @@ -22,7 +22,7 @@ #include -#include "effects/effect.h" +#include "nodes/node.h" #include "effects/transition.h" #include "project/footage.h" #include "global/config.h" @@ -116,7 +116,7 @@ Selection Clip::ToSelection() return Selection(timeline_in(), timeline_out(), track()); } -Track::Type Clip::type() +olive::TrackType Clip::type() { return track()->type(); } @@ -147,7 +147,7 @@ FootageStream *Clip::media_stream() { if (media() != nullptr && media()->get_type() == MEDIA_TYPE_FOOTAGE) { - return media()->to_footage()->get_stream_from_file_index(type() == Track::kTypeVideo, media_stream_index()); + return media()->to_footage()->get_stream_from_file_index(type() == olive::kTypeVideo, media_stream_index()); } return nullptr; @@ -199,9 +199,9 @@ void Clip::refresh() { if (replaced && media() != nullptr && media()->get_type() == MEDIA_TYPE_FOOTAGE) { Footage* m = media()->to_footage(); - if (type() == Track::kTypeVideo && m->video_tracks.size() > 0) { + if (type() == olive::kTypeVideo && m->video_tracks.size() > 0) { set_media(media(), m->video_tracks.at(0).file_index); - } else if (type() == Track::kTypeAudio && m->audio_tracks.size() > 0) { + } else if (type() == olive::kTypeAudio && m->audio_tracks.size() > 0) { set_media(media(), m->audio_tracks.at(0).file_index); } } @@ -220,7 +220,7 @@ QVector &Clip::get_markers() { return markers; } -int Clip::IndexOfEffect(Effect *e) +int Clip::IndexOfEffect(Node *e) { for (int i=0;iget_frame_rate(media_stream_index()); if (!qIsNaN(rate)) return rate; @@ -449,7 +449,7 @@ long Clip::media_length() { case MEDIA_TYPE_FOOTAGE: { Footage* m = media_->to_footage(); - const FootageStream* ms = m->get_stream_from_file_index(type() == Track::kTypeVideo, media_stream_index()); + const FootageStream* ms = m->get_stream_from_file_index(type() == olive::kTypeVideo, media_stream_index()); if (ms != nullptr && ms->infinite_length) { return LONG_MAX; } else { @@ -517,7 +517,7 @@ void Clip::refactor_frame_rate(ComboAction* ca, double multiplier, bool change_t // move keyframes for (int i=0;irow_count();j++) { EffectRow* r = e->row(j); for (int l=0;lFieldCount();l++) { @@ -710,7 +710,7 @@ bool Clip::Retrieve() bool Clip::UsesCacher() { - return type() == Track::kTypeAudio || (media() != nullptr && media()->get_type() == MEDIA_TYPE_FOOTAGE); + return type() == olive::kTypeAudio || (media() != nullptr && media()->get_type() == MEDIA_TYPE_FOOTAGE); } ClipSpeed::ClipSpeed() : diff --git a/timeline/clip.h b/timeline/clip.h index b0614535d..30ea217ce 100644 --- a/timeline/clip.h +++ b/timeline/clip.h @@ -30,15 +30,17 @@ #include "rendering/cacher.h" -#include "effects/effect.h" +#include "nodes/node.h" #include "effects/transition.h" #include "undo/comboaction.h" #include "project/media.h" #include "project/footage.h" #include "rendering/framebufferobject.h" #include "marker.h" -#include "track.h" #include "nodes/nodegraph.h" +#include "selection.h" + +class Track; struct ClipSpeed { ClipSpeed(); @@ -46,8 +48,6 @@ struct ClipSpeed { bool maintain_audio_pitch; }; -using ClipPtr = std::shared_ptr; - class Clip { public: Clip(Track *s); @@ -62,7 +62,7 @@ public: Selection ToSelection(); - Track::Type type(); + olive::TrackType type(); const QColor& color(); void set_color(int r, int g, int b); @@ -129,8 +129,8 @@ public: QVector& get_markers(); // other variables (should be deep copied/duplicated in copy()) - int IndexOfEffect(Effect* e); - QList effects; + int IndexOfEffect(Node* e); + QList effects; QVector linked; TransitionPtr opening_transition; TransitionPtr closing_transition; diff --git a/timeline/ghost.h b/timeline/ghost.h index f95314fe3..14ee4b131 100644 --- a/timeline/ghost.h +++ b/timeline/ghost.h @@ -3,6 +3,7 @@ #include "effects/transition.h" #include "track.h" +#include "project/media.h" namespace olive { namespace timeline { diff --git a/timeline/sequence.cpp b/timeline/sequence.cpp index 1a1d17fe3..75340e974 100644 --- a/timeline/sequence.cpp +++ b/timeline/sequence.cpp @@ -36,10 +36,10 @@ Sequence::Sequence() : wrapper_sequence(false) { // Set up tracks - track_lists_.resize(Track::kTypeCount); + track_lists_.resize(olive::kTypeCount); for (int i=0;i(i)); + track_lists_[i] = new TrackList(this, static_cast(i)); } } @@ -133,7 +133,7 @@ QVector Sequence::GetAllClips() return all_clips; } -TrackList *Sequence::GetTrackList(Track::Type type) +TrackList *Sequence::GetTrackList(olive::TrackType type) { return track_lists_.at(type); } @@ -230,13 +230,13 @@ void Sequence::AddClipsFromGhosts(ComboAction* ca, const QVector& ghosts) } if (olive::config.add_default_effects_to_clips) { - if (c->type() == Track::kTypeVideo) { + if (c->type() == olive::kTypeVideo) { // add default video effects - c->effects.append(Effect::Create(c.get(), Effect::GetInternalMeta(EFFECT_INTERNAL_TRANSFORM, EFFECT_TYPE_EFFECT))); - } else if (c->type() == Track::kTypeAudio) { + c->effects.append(olive::node_library[kTransformEffect]->Create(c.get())); + } else if (c->type() == olive::kTypeAudio) { // add default audio effects - c->effects.append(Effect::Create(c.get(), Effect::GetInternalMeta(EFFECT_INTERNAL_VOLUME, EFFECT_TYPE_EFFECT))); - c->effects.append(Effect::Create(c.get(), Effect::GetInternalMeta(EFFECT_INTERNAL_PAN, EFFECT_TYPE_EFFECT))); + c->effects.append(olive::node_library[kVolumeEffect]->Create(c.get())); + c->effects.append(olive::node_library[kPanEffect]->Create(c.get())); } } } @@ -265,7 +265,7 @@ void Sequence::MoveClip(Clip *c, ComboAction *ca, long iin, long iout, long icli ca->append(new AddTransitionCommand(nullptr, c->opening_transition->secondary_clip, c->opening_transition, - nullptr, + kInvalidNode, 0)); } @@ -277,7 +277,7 @@ void Sequence::MoveClip(Clip *c, ComboAction *ca, long iin, long iout, long icli ca->append(new AddTransitionCommand(nullptr, c, c->closing_transition, - nullptr, + kInvalidNode, 0)); } } @@ -905,9 +905,9 @@ void Sequence::RippleDeleteArea(ComboAction* ca, long ripple_point, long ripple_ } -Effect *Sequence::GetSelectedGizmo() +Node *Sequence::GetSelectedGizmo() { - Effect* gizmo_ptr = nullptr; + Node* gizmo_ptr = nullptr; QVector clips = GetAllClips(); @@ -923,7 +923,7 @@ Effect *Sequence::GetSelectedGizmo() // none selected for (int j=0;jeffects.size();j++) { - Effect* e = c->effects.at(j).get(); + Node* e = c->effects.at(j).get(); // retrieve gizmo data from effect if (e->are_gizmos_enabled()) { @@ -1156,7 +1156,7 @@ ClipPtr Sequence::SplitClip(ComboAction *ca, bool transitions, Clip* pre, long f ca->append(new AddTransitionCommand(nullptr, pre->opening_transition->secondary_clip, pre->opening_transition, - nullptr, + kInvalidNode, 0) ); diff --git a/timeline/sequence.h b/timeline/sequence.h index 41c2cfbb7..94051ae83 100644 --- a/timeline/sequence.h +++ b/timeline/sequence.h @@ -47,7 +47,7 @@ public: long GetEndFrame(); QVector GetAllClips(); - TrackList* GetTrackList(Track::Type type); + TrackList* GetTrackList(olive::TrackType type); /** * @brief Close all open clips in a Sequence @@ -97,7 +97,7 @@ public: void RippleDeleteEmptySpace(ComboAction *ca, Track *track, long point); void RippleDeleteArea(ComboAction* ca, long ripple_point, long ripple_length); - Effect* GetSelectedGizmo(); + Node* GetSelectedGizmo(); bool IsClipSelected(Clip* clip, bool containing = true); bool IsTransitionSelected(Transition* t); diff --git a/timeline/timelinefunctions.cpp b/timeline/timelinefunctions.cpp index beaf69929..fbbd1985b 100644 --- a/timeline/timelinefunctions.cpp +++ b/timeline/timelinefunctions.cpp @@ -119,7 +119,7 @@ QVector olive::timeline::CreateGhostsFromMedia(Sequence *seq, || import_data.type() == olive::timeline::kImportBoth) { for (int j=0;jaudio_tracks.size();j++) { if (m->audio_tracks.at(j).enabled) { - g.track = seq->GetTrackList(Track::kTypeAudio)->TrackAt(j); + g.track = seq->GetTrackList(olive::kTypeAudio)->TrackAt(j); g.media_stream = m->audio_tracks.at(j).file_index; ghosts.append(g); } @@ -130,7 +130,7 @@ QVector olive::timeline::CreateGhostsFromMedia(Sequence *seq, || import_data.type() == olive::timeline::kImportBoth) { for (int j=0;jvideo_tracks.size();j++) { if (m->video_tracks.at(j).enabled) { - g.track = seq->GetTrackList(Track::kTypeVideo)->TrackAt(j); + g.track = seq->GetTrackList(olive::kTypeVideo)->TrackAt(j); g.media_stream = m->video_tracks.at(j).file_index; ghosts.append(g); } @@ -146,13 +146,13 @@ QVector olive::timeline::CreateGhostsFromMedia(Sequence *seq, if (import_data.type() == olive::timeline::kImportVideoOnly || import_data.type() == olive::timeline::kImportBoth) { - g.track = seq->GetTrackList(Track::kTypeVideo)->First(); + g.track = seq->GetTrackList(olive::kTypeVideo)->First(); ghosts.append(g); } if (import_data.type() == olive::timeline::kImportAudioOnly || import_data.type() == olive::timeline::kImportBoth) { - g.track = seq->GetTrackList(Track::kTypeAudio)->First(); + g.track = seq->GetTrackList(olive::kTypeAudio)->First(); ghosts.append(g); } diff --git a/timeline/track.cpp b/timeline/track.cpp index 37cbc7a91..9273b67ed 100644 --- a/timeline/track.cpp +++ b/timeline/track.cpp @@ -9,7 +9,7 @@ int olive::timeline::kTrackDefaultHeight = 40; int olive::timeline::kTrackMinHeight = 30; int olive::timeline::kTrackHeightIncrement = 10; -Track::Track(TrackList* parent, Type type) : +Track::Track(TrackList* parent, olive::TrackType type) : parent_(parent), type_(type), muted_(false), @@ -58,7 +58,7 @@ void Track::Save(QXmlStreamWriter &stream) stream.writeEndElement(); // track } -Track::Type Track::type() +olive::TrackType Track::type() { return type_; } @@ -80,11 +80,11 @@ QString Track::name() int display_index = Index() + 1; switch (type_) { - case kTypeVideo: + case olive::kTypeVideo: return tr("Video %1").arg(display_index); - case kTypeAudio: + case olive::kTypeAudio: return tr("Audio %1").arg(display_index); - case kTypeSubtitle: + case olive::kTypeSubtitle: return tr("Subtitle %1").arg(display_index); default: return tr("Unknown %1").arg(display_index); diff --git a/timeline/track.h b/timeline/track.h index 847f27415..310cd69e9 100644 --- a/timeline/track.h +++ b/timeline/track.h @@ -4,7 +4,13 @@ #include #include -#include "effects/effect.h" +#include "nodes/node.h" +#include "tracktypes.h" +#include "undo/comboaction.h" +#include "timeline/selection.h" + +class Sequence; +class Transition; namespace olive { namespace timeline { @@ -35,14 +41,7 @@ class Track : public QObject { Q_OBJECT public: - enum Type { - kTypeVideo, - kTypeAudio, - kTypeSubtitle, - kTypeCount - }; - - Track(TrackList* parent, Type type); + Track(TrackList* parent, olive::TrackType type); Track* copy(TrackList* parent); Sequence* sequence(); @@ -50,7 +49,7 @@ public: void Save(QXmlStreamWriter& stream); - Type type(); + olive::TrackType type(); int height(); void set_height(int h); @@ -110,10 +109,10 @@ private: void ResizeClipArray(int new_size); TrackList* parent_; - Type type_; + olive::TrackType type_; int height_; QVector clips_; - QVector effects_; + QVector effects_; QVector selections_; bool muted_; diff --git a/timeline/tracklist.cpp b/timeline/tracklist.cpp index 5dbb3ac52..a735750b2 100644 --- a/timeline/tracklist.cpp +++ b/timeline/tracklist.cpp @@ -2,7 +2,7 @@ #include "timeline/sequence.h" -TrackList::TrackList(Sequence *parent, Track::Type type) : +TrackList::TrackList(Sequence *parent, olive::TrackType type) : QObject(parent), type_(type) { @@ -91,7 +91,7 @@ QVector TrackList::tracks() return tracks_; } -Track::Type TrackList::type() +olive::TrackType TrackList::type() { return type_; } diff --git a/timeline/tracklist.h b/timeline/tracklist.h index 4186cf84b..5b657aa06 100644 --- a/timeline/tracklist.h +++ b/timeline/tracklist.h @@ -7,7 +7,7 @@ class TrackList : public QObject { Q_OBJECT public: - TrackList(Sequence* parent, Track::Type type); + TrackList(Sequence* parent, olive::TrackType type); TrackList* copy(Sequence* parent); void Save(QXmlStreamWriter& stream); @@ -21,7 +21,7 @@ public: Track* TrackAt(int i); QVector tracks(); - Track::Type type(); + olive::TrackType type(); Sequence* GetParent(); @@ -31,7 +31,7 @@ signals: private: void ResizeTrackArray(int i); - Track::Type type_; + olive::TrackType type_; QVector tracks_; }; diff --git a/timeline/tracktypes.h b/timeline/tracktypes.h new file mode 100644 index 000000000..c49b049a7 --- /dev/null +++ b/timeline/tracktypes.h @@ -0,0 +1,13 @@ +#ifndef TRACKTYPES_H +#define TRACKTYPES_H + +namespace olive { + enum TrackType { + kTypeVideo, + kTypeAudio, + kTypeSubtitle, + kTypeCount + }; +}; + +#endif // TRACKTYPES_H diff --git a/ui/effectui.cpp b/ui/effectui.cpp index bdfbeb813..62a1cdb35 100644 --- a/ui/effectui.cpp +++ b/ui/effectui.cpp @@ -29,7 +29,7 @@ #include "ui/menu.h" #include "panels/panels.h" -EffectUI::EffectUI(Effect* e) : +EffectUI::EffectUI(Node* e) : effect_(e), node_parent_(nullptr) { @@ -38,7 +38,7 @@ EffectUI::EffectUI(Effect* e) : QString effect_name; // If this effect is actually a transition - if (e->meta->type == EFFECT_TYPE_TRANSITION) { + if (e->type() == EFFECT_TYPE_TRANSITION) { Transition* t = static_cast(e); @@ -70,17 +70,17 @@ EffectUI::EffectUI(Effect* e) : // See if the transition is the clip's opening or closing transition and label it accordingly if (both_selected) { - effect_name = t->name; + effect_name = t->name(); } else if (selected_clip->opening_transition.get() == t) { - effect_name = tr("%1 (Opening)").arg(t->name); + effect_name = tr("%1 (Opening)").arg(t->name()); } else { - effect_name = tr("%1 (Closing)").arg(t->name); + effect_name = tr("%1 (Closing)").arg(t->name()); } } else { // Otherwise just set the title normally - effect_name = e->name; + effect_name = e->name(); } @@ -166,10 +166,10 @@ EffectUI::EffectUI(Effect* e) : connect(enabled_check, SIGNAL(toggled(bool)), e, SLOT(FieldChanged())); } -void EffectUI::AddAdditionalEffect(Effect *e) +void EffectUI::AddAdditionalEffect(Node *e) { // Ensure this is the same kind of effect and will be fully compatible - Q_ASSERT(e->meta == effect_->meta); + Q_ASSERT(e->id() == effect_->id()); // Add multiple modifer to header label (but only once) if (additional_effects_.isEmpty()) { @@ -199,7 +199,7 @@ void EffectUI::AddAdditionalEffect(Effect *e) } } -Effect *EffectUI::GetEffect() +Node *EffectUI::GetEffect() { return effect_; } @@ -228,7 +228,7 @@ int EffectUI::GetRowY(int row, QWidget* mapToWidget) { void EffectUI::UpdateFromEffect() { - Effect* effect = GetEffect(); + Node* effect = GetEffect(); for (int j=0;jrow_count();j++) { @@ -327,7 +327,7 @@ void EffectUI::AttachKeyframeNavigationToRow(EffectRow *row, KeyframeNavigator * } void EffectUI::show_context_menu(const QPoint& pos) { - if (effect_->meta->type == EFFECT_TYPE_EFFECT) { + if (effect_->type() == EFFECT_TYPE_EFFECT) { Menu menu; Clip* c = effect_->parent_clip; diff --git a/ui/effectui.h b/ui/effectui.h index 2888c04aa..9eb12201c 100644 --- a/ui/effectui.h +++ b/ui/effectui.h @@ -22,8 +22,9 @@ #define EFFECTUI_H #include "collapsiblewidget.h" -#include "effects/effect.h" +#include "nodes/node.h" #include "ui/nodeui.h" +#include "ui/keyframenavigator.h" /** * @brief The EffectUI class @@ -49,7 +50,7 @@ public: * * The Effect to make a UI of. It must be a valid object. */ - EffectUI(Effect* e); + EffectUI(Node* e); /** * @brief Attach additional effects to this UI @@ -62,7 +63,7 @@ public: * * The Effect to add to this UI object. */ - void AddAdditionalEffect(Effect* e); + void AddAdditionalEffect(Node* e); /** * @brief Get the primary Effect that this UI object was created for @@ -71,7 +72,7 @@ public: * * The Effect object passed to the constrcutor whe creating this EffectUI. */ - Effect* GetEffect(); + Node* GetEffect(); /** * @brief Get the Y position of a given row @@ -175,12 +176,12 @@ private: /** * @brief Internal reference to the Effect this object was constructed around. */ - Effect* effect_; + Node* effect_; /** * @brief Internal array of additional Effect objects attached to this UI. */ - QVector additional_effects_; + QVector additional_effects_; /** * @brief Layout for UI widgets diff --git a/ui/graphview.cpp b/ui/graphview.cpp index 5885d7f76..637bf3e3e 100644 --- a/ui/graphview.cpp +++ b/ui/graphview.cpp @@ -33,7 +33,7 @@ #include "ui/keyframedrawing.h" #include "undo/undo.h" #include "undo/undostack.h" -#include "effects/effect.h" +#include "nodes/node.h" #include "timeline/clip.h" #include "ui/rectangleselect.h" #include "ui/menu.h" diff --git a/ui/keyframedrawing.cpp b/ui/keyframedrawing.cpp index 895319b7a..ce4a49f24 100644 --- a/ui/keyframedrawing.cpp +++ b/ui/keyframedrawing.cpp @@ -20,7 +20,7 @@ #include "keyframedrawing.h" -#include "effects/effect.h" +#include "nodes/node.h" #include "timeline/clip.h" #define KEYFRAME_POINT_COUNT 4 diff --git a/ui/keyframeview.cpp b/ui/keyframeview.cpp index e1926c394..44c122fc1 100644 --- a/ui/keyframeview.cpp +++ b/ui/keyframeview.cpp @@ -23,7 +23,7 @@ #include #include -#include "effects/effect.h" +#include "nodes/node.h" #include "ui/collapsiblewidget.h" #include "panels/panels.h" #include "timeline/clip.h" @@ -120,7 +120,7 @@ void KeyframeView::paintEvent(QPaintEvent*) { for (int j=0;jGetEffect(); + Node* e = container->GetEffect(); if (container->IsExpanded()) { for (int j=0;jrow_count();j++) { diff --git a/ui/keyframeview.h b/ui/keyframeview.h index 534438f66..918b40ee3 100644 --- a/ui/keyframeview.h +++ b/ui/keyframeview.h @@ -27,7 +27,7 @@ #include "ui/effectui.h" class Clip; -class Effect; +class Node; class EffectRow; class EffectField; class TimelineHeader; diff --git a/ui/nodeui.cpp b/ui/nodeui.cpp index ebc3f10bd..9e29e6db5 100644 --- a/ui/nodeui.cpp +++ b/ui/nodeui.cpp @@ -157,7 +157,7 @@ QVector NodeUI::GetNodeSocketRects() QVector rects; if (proxy_ != nullptr) { - Effect* e = central_widget_->GetEffect(); + Node* e = central_widget_->GetEffect(); for (int i=0;irow_count();i++) { diff --git a/ui/timelinearea.cpp b/ui/timelinearea.cpp index 5fe9d29ff..e0c795ab8 100644 --- a/ui/timelinearea.cpp +++ b/ui/timelinearea.cpp @@ -49,7 +49,7 @@ TimelineArea::TimelineArea(Timeline* timeline, olive::timeline::Alignment alignm connect(view_, SIGNAL(requestScrollChange(int)), scrollbar_, SLOT(setValue(int))); } -void TimelineArea::SetTrackList(Sequence *sequence, Track::Type track_list) +void TimelineArea::SetTrackList(Sequence *sequence, olive::TrackType track_list) { if (track_list_ != nullptr) { disconnect(track_list_, SIGNAL(TrackCountChanged()), this, SLOT(RefreshLabels())); diff --git a/ui/timelinearea.h b/ui/timelinearea.h index 50e499e71..c4c929bf8 100644 --- a/ui/timelinearea.h +++ b/ui/timelinearea.h @@ -14,7 +14,7 @@ class TimelineArea : public QWidget public: TimelineArea(Timeline *timeline, olive::timeline::Alignment alignment = olive::timeline::kAlignmentTop); - void SetTrackList(Sequence* sequence, Track::Type track_list); + void SetTrackList(Sequence* sequence, olive::TrackType track_list); void SetAlignment(olive::timeline::Alignment alignment); TrackList* track_list(); diff --git a/ui/timelineview.cpp b/ui/timelineview.cpp index 91356b676..403410de0 100644 --- a/ui/timelineview.cpp +++ b/ui/timelineview.cpp @@ -56,7 +56,7 @@ #include "ui/focusfilter.h" #include "dialogs/clippropertiesdialog.h" #include "global/debug.h" -#include "effects/effect.h" +#include "nodes/node.h" #include "effects/internal/solideffect.h" #include "timeline/track.h" #include "global/math.h" @@ -143,7 +143,7 @@ void TimelineView::show_context_menu(const QPoint& pos) { bool audio_clips_are_selected = false; for (int i=0;itype() == Track::kTypeVideo) { + if (selected_clips.at(i)->type() == olive::kTypeVideo) { video_clips_are_selected = true; } else { audio_clips_are_selected = true; @@ -611,7 +611,7 @@ void TimelineView::mousePressEvent(QMouseEvent *event) { // if the user is creating an object if (ParentTimeline()->creating) { - Track::Type create_type = Track::kTypeVideo; + olive::TrackType create_type = olive::kTypeVideo; switch (ParentTimeline()->creating_object) { case olive::timeline::ADD_OBJ_TITLE: case olive::timeline::ADD_OBJ_SOLID: @@ -620,7 +620,7 @@ void TimelineView::mousePressEvent(QMouseEvent *event) { case olive::timeline::ADD_OBJ_TONE: case olive::timeline::ADD_OBJ_NOISE: case olive::timeline::ADD_OBJ_AUDIO: - create_type = Track::kTypeAudio; + create_type = olive::kTypeAudio; break; } @@ -1024,24 +1024,24 @@ void TimelineView::mouseReleaseEvent(QMouseEvent *event) { add.append(c); ca->append(new AddClipCommand(add)); - if (c->type() == Track::kTypeVideo && olive::config.add_default_effects_to_clips) { - // default video effects (before custom effects) - c->effects.append(Effect::Create(c.get(), Effect::GetInternalMeta(EFFECT_INTERNAL_TRANSFORM, EFFECT_TYPE_EFFECT))); + if (c->type() == olive::kTypeVideo && olive::config.add_default_effects_to_clips) { + // default video effects (before custom effects) + c->effects.append(olive::node_library[kTransformEffect]->Create(c.get())); } switch (ParentTimeline()->creating_object) { case olive::timeline::ADD_OBJ_TITLE: c->set_name(tr("Title")); - c->effects.append(Effect::Create(c.get(), Effect::GetInternalMeta(EFFECT_INTERNAL_RICHTEXT, EFFECT_TYPE_EFFECT))); + c->effects.append(olive::node_library[kRichTextInput]->Create(c.get())); break; case olive::timeline::ADD_OBJ_SOLID: c->set_name(tr("Solid Color")); - c->effects.append(Effect::Create(c.get(), Effect::GetInternalMeta(EFFECT_INTERNAL_SOLID, EFFECT_TYPE_EFFECT))); + c->effects.append(olive::node_library[kSolidInput]->Create(c.get())); break; case olive::timeline::ADD_OBJ_BARS: { c->set_name(tr("Bars")); - EffectPtr e = Effect::Create(c.get(), Effect::GetInternalMeta(EFFECT_INTERNAL_SOLID, EFFECT_TYPE_EFFECT)); + NodePtr e = olive::node_library[kSolidInput]->Create(c.get()); // Auto-select bars SolidEffect* solid_effect = static_cast(e.get()); @@ -1052,20 +1052,20 @@ void TimelineView::mouseReleaseEvent(QMouseEvent *event) { break; case olive::timeline::ADD_OBJ_TONE: c->set_name(tr("Tone")); - c->effects.append(Effect::Create(c.get(), Effect::GetInternalMeta(EFFECT_INTERNAL_TONE, EFFECT_TYPE_EFFECT))); + c->effects.append(olive::node_library[kToneInput]->Create(c.get())); break; case olive::timeline::ADD_OBJ_NOISE: c->set_name(tr("Noise")); - c->effects.append(Effect::Create(c.get(), Effect::GetInternalMeta(EFFECT_INTERNAL_NOISE, EFFECT_TYPE_EFFECT))); + c->effects.append(olive::node_library[kNoiseInput]->Create(c.get())); break; default: break; } - if (c->type() == Track::kTypeAudio && olive::config.add_default_effects_to_clips) { + if (c->type() == olive::kTypeAudio && olive::config.add_default_effects_to_clips) { // default audio effects (after custom effects) - c->effects.append(Effect::Create(c.get(), Effect::GetInternalMeta(EFFECT_INTERNAL_VOLUME, EFFECT_TYPE_EFFECT))); - c->effects.append(Effect::Create(c.get(), Effect::GetInternalMeta(EFFECT_INTERNAL_PAN, EFFECT_TYPE_EFFECT))); + c->effects.append(olive::node_library[kVolumeEffect]->Create(c.get())); + c->effects.append(olive::node_library[kPanEffect]->Create(c.get())); } push_undo = true; @@ -1432,7 +1432,7 @@ void TimelineView::mouseReleaseEvent(QMouseEvent *event) { ca->append(new AddTransitionCommand(nullptr, transition->secondary_clip, transition, - nullptr, + kInvalidNode, 0)); } else { @@ -1447,7 +1447,7 @@ void TimelineView::mouseReleaseEvent(QMouseEvent *event) { ca->append(new AddTransitionCommand(nullptr, transition->secondary_clip, transition, - nullptr, + kInvalidNode, 0)); } @@ -2821,7 +2821,7 @@ void TimelineView::draw_transition(QPainter& p, Clip* c, const QRect& clip_rect, if (draw_text) { p.setPen(Qt::white); - p.drawText(transition_text_rect, 0, t->meta->name, &transition_text_rect); + p.drawText(transition_text_rect, 0, t->name(), &transition_text_rect); } } p.setPen(Qt::black); @@ -2920,7 +2920,7 @@ void TimelineView::paintEvent(QPaintEvent*) { // draw thumbnail/waveform long media_length = clip->media_length(); - if (clip->type() == Track::kTypeVideo) { + if (clip->type() == olive::kTypeVideo) { // draw thumbnail int thumb_y = p.fontMetrics().height()+olive::timeline::kClipTextPadding+olive::timeline::kClipTextPadding; if (thumb_x < width() && thumb_y < height()) { diff --git a/ui/viewerwidget.cpp b/ui/viewerwidget.cpp index 186fcc02a..5fb7dd057 100644 --- a/ui/viewerwidget.cpp +++ b/ui/viewerwidget.cpp @@ -63,6 +63,7 @@ extern "C" { #include "ui/menu.h" #include "ui/waveform.h" #include "mainwindow.h" +#include "effects/effectgizmo.h" const int kTitleActionSafeVertexSize = 84; diff --git a/ui/viewerwidget.h b/ui/viewerwidget.h index d5cb80bc2..f2d0fc7f5 100644 --- a/ui/viewerwidget.h +++ b/ui/viewerwidget.h @@ -34,7 +34,7 @@ #include "timeline/clip.h" #include "project/footage.h" -#include "effects/effect.h" +#include "nodes/node.h" #include "ui/viewerwindow.h" #include "ui/viewercontainer.h" #include "rendering/renderthread.h" @@ -84,7 +84,7 @@ private: bool dragging; void seek_from_click(int x); QMatrix4x4 get_matrix(); - Effect* gizmos; + Node* gizmos; int drag_start_x; int drag_start_y; int gizmo_x_mvmt; diff --git a/undo/undo.cpp b/undo/undo.cpp index 82738c21e..f9140cc5b 100644 --- a/undo/undo.cpp +++ b/undo/undo.cpp @@ -189,7 +189,7 @@ void SetTimelineInOutCommand::doRedo() { } } -AddEffectCommand::AddEffectCommand(Clip* c, EffectPtr e, const EffectMeta *m, int insert_pos) { +AddEffectCommand::AddEffectCommand(Clip* c, NodePtr e, NodeType m, int insert_pos) { clip = c; ref = e; meta = m; @@ -207,7 +207,7 @@ void AddEffectCommand::doUndo() { void AddEffectCommand::doRedo() { if (ref == nullptr) { - ref = Effect::Create(clip, meta); + ref = olive::node_library[meta]->Create(clip); } if (pos < 0) { clip->effects.append(ref); @@ -219,7 +219,7 @@ void AddEffectCommand::doRedo() { AddTransitionCommand::AddTransitionCommand(Clip* iopen, Clip* iclose, TransitionPtr copy, - const EffectMeta *itransition, + NodeType itransition, int ilength) { open_ = iopen; close_ = iclose; @@ -251,9 +251,10 @@ void AddTransitionCommand::doRedo() { // create new transition object if (new_transition_ref_ == nullptr) { if (transition_to_copy_ == nullptr) { - new_transition_ref_ = Transition::CreateFromMeta(primary, secondary, transition_meta_); + new_transition_ref_ = std::static_pointer_cast(olive::node_library[transition_meta_]->Create(primary)); + new_transition_ref_->secondary_clip = secondary; } else { - new_transition_ref_ = transition_to_copy_->copy(primary, nullptr); + new_transition_ref_ = std::static_pointer_cast(transition_to_copy_->copy(primary)); } } @@ -544,7 +545,7 @@ void ReplaceClipMediaCommand::doRedo() { update_ui(true); } -EffectDeleteCommand::EffectDeleteCommand(Effect *e) : +EffectDeleteCommand::EffectDeleteCommand(Node *e) : effect_(e) {} @@ -1132,7 +1133,7 @@ void UpdateViewer::doRedo() { panel_sequence_viewer->viewer_widget()->frame_update(); } -SetEffectData::SetEffectData(Effect *e, const QByteArray &s) { +SetEffectData::SetEffectData(Node *e, const QByteArray &s) { effect = e; data = s; } diff --git a/undo/undo.h b/undo/undo.h index fd6bd0669..9ce89d493 100644 --- a/undo/undo.h +++ b/undo/undo.h @@ -30,6 +30,7 @@ #include "comboaction.h" +#include "nodes/node.h" #include "timeline/marker.h" #include "timeline/selection.h" #include "effects/keyframe.h" @@ -43,13 +44,12 @@ using SequencePtr = std::shared_ptr; class Media; using MediaPtr = std::shared_ptr; -class Effect; -using EffectPtr = std::shared_ptr; +class Node; +using NodePtr = std::shared_ptr; class Transition; using TransitionPtr = std::shared_ptr; -struct EffectMeta; class EffectRow; class EffectField; @@ -124,27 +124,27 @@ private: class AddEffectCommand : public OliveAction { public: - AddEffectCommand(Clip* c, EffectPtr e, const EffectMeta* m, int insert_pos = -1); + AddEffectCommand(Clip* c, NodePtr e, NodeType m, int insert_pos = -1); virtual void doUndo() override; virtual void doRedo() override; private: Clip* clip; - const EffectMeta* meta; - EffectPtr ref; + NodeType meta; + NodePtr ref; int pos; bool done; }; class AddTransitionCommand : public OliveAction { public: - AddTransitionCommand(Clip* iopen, Clip* iclose, TransitionPtr copy, const EffectMeta* itransition, int ilength); + AddTransitionCommand(Clip* iopen, Clip* iclose, TransitionPtr copy, NodeType itransition, int ilength); virtual void doUndo() override; virtual void doRedo() override; private: Clip* open_; Clip* close_; TransitionPtr transition_to_copy_; - const EffectMeta* transition_meta_; + NodeType transition_meta_; int length_; TransitionPtr old_open_transition_; TransitionPtr old_close_transition_; @@ -273,12 +273,12 @@ private: class EffectDeleteCommand : public OliveAction { public: - EffectDeleteCommand(Effect* e); + EffectDeleteCommand(Node* e); virtual void doUndo() override; virtual void doRedo() override; private: - Effect* effect_; - EffectPtr deleted_obj_; + Node* effect_; + NodePtr deleted_obj_; Clip* parent_clip_; int index_; }; @@ -593,11 +593,11 @@ public: class SetEffectData : public OliveAction { public: - SetEffectData(Effect* e, const QByteArray &s); + SetEffectData(Node* e, const QByteArray &s); virtual void doUndo() override; virtual void doRedo() override; private: - Effect* effect; + Node* effect; QByteArray data; QByteArray old_data; };