added more functionality to transition tool
This commit is contained in:
+51
-11
@@ -29,6 +29,10 @@
|
||||
#include "effects/internal/volumeeffect.h"
|
||||
#include "effects/internal/paneffect.h"
|
||||
#include "effects/internal/shakeeffect.h"
|
||||
#include "effects/internal/crossdissolvetransition.h"
|
||||
#include "effects/internal/linearfadetransition.h"
|
||||
#include "effects/internal/exponentialfadetransition.h"
|
||||
#include "effects/internal/logarithmicfadetransition.h"
|
||||
|
||||
#include <QCheckBox>
|
||||
#include <QGridLayout>
|
||||
@@ -52,14 +56,18 @@ Effect* create_effect(Clip* c, const EffectMeta* em) {
|
||||
} else if (em->internal >= 0 && em->internal < EFFECT_INTERNAL_COUNT) {
|
||||
// must be an internal effect
|
||||
switch (em->internal) {
|
||||
case EFFECT_INTERNAL_TRANSFORM: return new TransformEffect(c, em); break;
|
||||
case EFFECT_INTERNAL_TEXT: return new TextEffect(c, em); break;
|
||||
case EFFECT_INTERNAL_SOLID: return new SolidEffect(c, em); break;
|
||||
case EFFECT_INTERNAL_NOISE: return new AudioNoiseEffect(c, em); break;
|
||||
case EFFECT_INTERNAL_VOLUME: return new VolumeEffect(c, em); break;
|
||||
case EFFECT_INTERNAL_PAN: return new PanEffect(c, em); break;
|
||||
case EFFECT_INTERNAL_TONE: return new ToneEffect(c, em); break;
|
||||
case EFFECT_INTERNAL_SHAKE: return new ShakeEffect(c, em); break;
|
||||
case EFFECT_INTERNAL_TRANSFORM: return new TransformEffect(c, em);
|
||||
case EFFECT_INTERNAL_TEXT: return new TextEffect(c, em);
|
||||
case EFFECT_INTERNAL_SOLID: return new SolidEffect(c, em);
|
||||
case EFFECT_INTERNAL_NOISE: return new AudioNoiseEffect(c, em);
|
||||
case EFFECT_INTERNAL_VOLUME: return new VolumeEffect(c, em);
|
||||
case EFFECT_INTERNAL_PAN: return new PanEffect(c, em);
|
||||
case EFFECT_INTERNAL_TONE: return new ToneEffect(c, em);
|
||||
case EFFECT_INTERNAL_SHAKE: return new ShakeEffect(c, em);
|
||||
case EFFECT_INTERNAL_CROSSDISSOLVE: return new CrossDissolveTransition(c, em);
|
||||
case EFFECT_INTERNAL_LINEARFADE: return new LinearFadeTransition(c, em);
|
||||
case EFFECT_INTERNAL_EXPONENTIALFADE: return new ExponentialFadeTransition(c, em);
|
||||
case EFFECT_INTERNAL_LOGARITHMICFADE: return new LogarithmicFadeTransition(c, em);
|
||||
}
|
||||
} else {
|
||||
dout << "[ERROR] Invalid effect data";
|
||||
@@ -85,6 +93,9 @@ const EffectMeta* get_internal_meta(int internal_id) {
|
||||
void load_internal_effects() {
|
||||
EffectMeta em;
|
||||
|
||||
// internal effects
|
||||
em.type = EFFECT_TYPE_EFFECT;
|
||||
|
||||
em.name = "Volume";
|
||||
em.internal = EFFECT_INTERNAL_VOLUME;
|
||||
audio_effects.append(em);
|
||||
@@ -120,6 +131,27 @@ void load_internal_effects() {
|
||||
em.category = "Distort";
|
||||
em.internal = EFFECT_INTERNAL_SHAKE;
|
||||
video_effects.append(em);
|
||||
|
||||
|
||||
// internal transitions
|
||||
em.type = EFFECT_TYPE_TRANSITION;
|
||||
em.category = "";
|
||||
|
||||
em.name = "Cross Dissolve";
|
||||
em.internal = EFFECT_INTERNAL_CROSSDISSOLVE;
|
||||
video_effects.append(em);
|
||||
|
||||
em.name = "Linear Fade";
|
||||
em.internal = EFFECT_INTERNAL_LINEARFADE;
|
||||
audio_effects.append(em);
|
||||
|
||||
em.name = "Exponential Fade";
|
||||
em.internal = EFFECT_INTERNAL_EXPONENTIALFADE;
|
||||
audio_effects.append(em);
|
||||
|
||||
em.name = "Logarithmic Fade";
|
||||
em.internal = EFFECT_INTERNAL_LOGARITHMICFADE;
|
||||
audio_effects.append(em);
|
||||
}
|
||||
|
||||
void load_shader_effects() {
|
||||
@@ -203,7 +235,9 @@ Effect::Effect(Clip* c, const EffectMeta *em) :
|
||||
isOpen(false),
|
||||
glslProgram(NULL),
|
||||
texture(NULL),
|
||||
bound(false)
|
||||
bound(false),
|
||||
tlink(NULL),
|
||||
length(30)
|
||||
{
|
||||
// set up base UI
|
||||
container = new CollapsibleWidget();
|
||||
@@ -536,7 +570,9 @@ QString save_data_to_string(int type, const QVariant& data) {
|
||||
void Effect::load(QXmlStreamReader& stream) {
|
||||
int row_count = 0;
|
||||
|
||||
while (!stream.atEnd() && !(stream.name() == "effect" && stream.isEndElement())) {
|
||||
QString tag = stream.name().toString();
|
||||
|
||||
while (!stream.atEnd() && !(stream.name() == tag && stream.isEndElement())) {
|
||||
stream.readNext();
|
||||
if (stream.name() == "row" && stream.isStartElement()) {
|
||||
if (row_count < rows.size()) {
|
||||
@@ -552,7 +588,6 @@ void Effect::load(QXmlStreamReader& stream) {
|
||||
const QXmlStreamAttribute& attr = stream.attributes().at(k);
|
||||
if (attr.name() == "enabled") {
|
||||
row->setKeyframing(attr.value() == "1");
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (row->isKeyframing()) {
|
||||
@@ -638,6 +673,10 @@ void Effect::load(QXmlStreamReader& stream) {
|
||||
}
|
||||
|
||||
void Effect::save(QXmlStreamWriter& stream) {
|
||||
stream.writeAttribute("name", meta->name);
|
||||
stream.writeAttribute("enabled", QString::number(is_enabled()));
|
||||
stream.writeAttribute("length", QString::number(length));
|
||||
|
||||
for (int i=0;i<rows.size();i++) {
|
||||
EffectRow* row = rows.at(i);
|
||||
stream.writeStartElement("row"); // row
|
||||
@@ -716,6 +755,7 @@ void Effect::endEffect() {
|
||||
Effect* Effect::copy(Clip* c) {
|
||||
Effect* copy = create_effect(c, meta);
|
||||
copy->set_enabled(is_enabled());
|
||||
copy->length = length;
|
||||
copy_field_keyframes(copy);
|
||||
return copy;
|
||||
}
|
||||
|
||||
+17
-2
@@ -29,6 +29,7 @@ struct EffectMeta {
|
||||
QString category;
|
||||
QString filename;
|
||||
int internal;
|
||||
int type;
|
||||
};
|
||||
|
||||
extern QVector<EffectMeta> video_effects;
|
||||
@@ -44,6 +45,8 @@ extern QMutex effects_loaded;
|
||||
#define EFFECT_TYPE_INVALID 0
|
||||
#define EFFECT_TYPE_VIDEO 1
|
||||
#define EFFECT_TYPE_AUDIO 2
|
||||
#define EFFECT_TYPE_EFFECT 3
|
||||
#define EFFECT_TYPE_TRANSITION 4
|
||||
|
||||
#define EFFECT_FIELD_DOUBLE 0
|
||||
#define EFFECT_FIELD_COLOR 1
|
||||
@@ -64,7 +67,16 @@ extern QMutex effects_loaded;
|
||||
#define EFFECT_INTERNAL_PAN 5
|
||||
#define EFFECT_INTERNAL_TONE 6
|
||||
#define EFFECT_INTERNAL_SHAKE 7
|
||||
#define EFFECT_INTERNAL_COUNT 8
|
||||
#define EFFECT_INTERNAL_CROSSDISSOLVE 8
|
||||
#define EFFECT_INTERNAL_LINEARFADE 9
|
||||
#define EFFECT_INTERNAL_EXPONENTIALFADE 10
|
||||
#define EFFECT_INTERNAL_LOGARITHMICFADE 11
|
||||
#define EFFECT_INTERNAL_COUNT 12
|
||||
|
||||
#define TRAN_TYPE_OPEN 1
|
||||
#define TRAN_TYPE_CLOSE 2
|
||||
#define TRAN_TYPE_OPENWLINK 3
|
||||
#define TRAN_TYPE_CLOSEWLINK 4
|
||||
|
||||
struct GLTextureCoords {
|
||||
int vertexTopLeftX;
|
||||
@@ -193,6 +205,9 @@ public:
|
||||
QString name;
|
||||
CollapsibleWidget* container;
|
||||
|
||||
long length; // only used for transitions
|
||||
Effect* tlink;
|
||||
|
||||
EffectRow* add_row(const QString &name);
|
||||
EffectRow* row(int i);
|
||||
int row_count();
|
||||
@@ -205,7 +220,7 @@ public:
|
||||
Effect* copy(Clip* c);
|
||||
void copy_field_keyframes(Effect *e);
|
||||
|
||||
void load(QXmlStreamReader& stream);
|
||||
void load(QXmlStreamReader& stream);
|
||||
void save(QXmlStreamWriter& stream);
|
||||
|
||||
// glsl handling
|
||||
|
||||
@@ -1,19 +1,13 @@
|
||||
#include "../transition.h"
|
||||
#include "crossdissolvetransition.h"
|
||||
|
||||
#include <QOpenGLFunctions>
|
||||
|
||||
// TODO port to GLSL?
|
||||
CrossDissolveTransition::CrossDissolveTransition(Clip* c, const EffectMeta* em) : Effect(c, em) {
|
||||
enable_coords = true;
|
||||
}
|
||||
|
||||
CrossDissolveTransition::CrossDissolveTransition() : Transition(VIDEO_DISSOLVE_TRANSITION) {}
|
||||
|
||||
void CrossDissolveTransition::process_transition(double progress) {
|
||||
void CrossDissolveTransition::process_coords(double progress, GLTextureCoords&) {
|
||||
float color[4];
|
||||
glGetFloatv(GL_CURRENT_COLOR, color);
|
||||
glColor4f(1.0, 1.0, 1.0, color[3]*progress);
|
||||
}
|
||||
|
||||
Transition* CrossDissolveTransition::copy() {
|
||||
Transition* t = new CrossDissolveTransition();
|
||||
t->length = length;
|
||||
return t;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
#ifndef CROSSDISSOLVETRANSITION_H
|
||||
#define CROSSDISSOLVETRANSITION_H
|
||||
|
||||
#include "../effect.h"
|
||||
|
||||
class CrossDissolveTransition : public Effect {
|
||||
public:
|
||||
CrossDissolveTransition(Clip* c, const EffectMeta* em);
|
||||
void process_coords(double timecode, GLTextureCoords &);
|
||||
};
|
||||
|
||||
#endif // CROSSDISSOLVETRANSITION_H
|
||||
@@ -0,0 +1,37 @@
|
||||
#include "exponentialfadetransition.h"
|
||||
|
||||
#include <QtMath>
|
||||
|
||||
ExponentialFadeTransition::ExponentialFadeTransition(Clip* c, const EffectMeta* em) : Effect(c, em) {}
|
||||
|
||||
void ExponentialFadeTransition::process_audio(double timecode_start, double timecode_end, quint8* samples, int nb_bytes, int type) {
|
||||
double interval = (timecode_end-timecode_start)/nb_bytes;
|
||||
|
||||
for (int i=0;i<nb_bytes;i+=2) {
|
||||
qint16 samp = (qint16) (((samples[i+1] & 0xFF) << 8) | (samples[i] & 0xFF));
|
||||
|
||||
/*switch (type) {
|
||||
case TRAN_TYPE_OPEN:
|
||||
case TRAN_TYPE_OPENWLINK:
|
||||
samp *= qSqrt(timecode_start + (interval * i));
|
||||
break;
|
||||
case TRAN_TYPE_CLOSE:
|
||||
case TRAN_TYPE_CLOSEWLINK:
|
||||
samp *= qSqrt(1 - (timecode_start + (interval * i)));
|
||||
break;
|
||||
}*/
|
||||
switch (type) {
|
||||
case TRAN_TYPE_OPEN:
|
||||
case TRAN_TYPE_OPENWLINK:
|
||||
samp *= qPow(timecode_start + (interval * i), 2);
|
||||
break;
|
||||
case TRAN_TYPE_CLOSE:
|
||||
case TRAN_TYPE_CLOSEWLINK:
|
||||
samp *= qPow(1 - (timecode_start + (interval * i)), 2);
|
||||
break;
|
||||
}
|
||||
|
||||
samples[i+1] = (quint8) (samp >> 8);
|
||||
samples[i] = (quint8) samp;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
#ifndef EXPONENTIALFADETRANSITION_H
|
||||
#define EXPONENTIALFADETRANSITION_H
|
||||
|
||||
#include "../effect.h"
|
||||
|
||||
class ExponentialFadeTransition : public Effect {
|
||||
public:
|
||||
ExponentialFadeTransition(Clip* c, const EffectMeta* em);
|
||||
void process_audio(double timecode_start, double timecode_end, quint8* samples, int nb_bytes, int channel_count);
|
||||
};
|
||||
|
||||
#endif // LINEARFADETRANSITION_H
|
||||
@@ -1,26 +1,25 @@
|
||||
#include "../transition.h"
|
||||
#include "linearfadetransition.h"
|
||||
|
||||
LinearFadeTransition::LinearFadeTransition() : Transition(AUDIO_LINEAR_FADE_TRANSITION) {}
|
||||
LinearFadeTransition::LinearFadeTransition(Clip* c, const EffectMeta* em) : Effect(c, em) {}
|
||||
|
||||
void LinearFadeTransition::process_audio(double range_start, double range_end, quint8* samples, int nb_samples, bool reverse) {
|
||||
double interval = (range_end - range_start) / nb_samples;
|
||||
void LinearFadeTransition::process_audio(double timecode_start, double timecode_end, quint8* samples, int nb_bytes, int type) {
|
||||
double interval = (timecode_end-timecode_start)/nb_bytes;
|
||||
|
||||
for (int i=0;i<nb_samples;i+=2) {
|
||||
for (int i=0;i<nb_bytes;i+=2) {
|
||||
qint16 samp = (qint16) (((samples[i+1] & 0xFF) << 8) | (samples[i] & 0xFF));
|
||||
|
||||
if (reverse) {
|
||||
samp *= 1 - (range_start + (interval * i));
|
||||
} else {
|
||||
samp *= range_start + (interval * i);
|
||||
switch (type) {
|
||||
case TRAN_TYPE_OPEN:
|
||||
case TRAN_TYPE_OPENWLINK:
|
||||
samp *= timecode_start + (interval * i);
|
||||
break;
|
||||
case TRAN_TYPE_CLOSE:
|
||||
case TRAN_TYPE_CLOSEWLINK:
|
||||
samp *= 1 - (timecode_start + (interval * i));
|
||||
break;
|
||||
}
|
||||
|
||||
samples[i+1] = (quint8) (samp >> 8);
|
||||
samples[i] = (quint8) samp;
|
||||
}
|
||||
}
|
||||
|
||||
Transition* LinearFadeTransition::copy() {
|
||||
Transition* t = new LinearFadeTransition();
|
||||
t->length = length;
|
||||
return t;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
#ifndef LINEARFADETRANSITION_H
|
||||
#define LINEARFADETRANSITION_H
|
||||
|
||||
#include "../effect.h"
|
||||
|
||||
class LinearFadeTransition : public Effect {
|
||||
public:
|
||||
LinearFadeTransition(Clip* c, const EffectMeta* em);
|
||||
void process_audio(double timecode_start, double timecode_end, quint8* samples, int nb_bytes, int channel_count);
|
||||
};
|
||||
|
||||
#endif // LINEARFADETRANSITION_H
|
||||
@@ -0,0 +1,27 @@
|
||||
#include "logarithmicfadetransition.h"
|
||||
|
||||
#include <QtMath>
|
||||
|
||||
LogarithmicFadeTransition::LogarithmicFadeTransition(Clip* c, const EffectMeta* em) : Effect(c, em) {}
|
||||
|
||||
void LogarithmicFadeTransition::process_audio(double timecode_start, double timecode_end, quint8* samples, int nb_bytes, int type) {
|
||||
double interval = (timecode_end-timecode_start)/nb_bytes;
|
||||
|
||||
for (int i=0;i<nb_bytes;i+=2) {
|
||||
qint16 samp = (qint16) (((samples[i+1] & 0xFF) << 8) | (samples[i] & 0xFF));
|
||||
|
||||
switch (type) {
|
||||
case TRAN_TYPE_OPEN:
|
||||
case TRAN_TYPE_OPENWLINK:
|
||||
samp *= qSqrt(timecode_start + (interval * i));
|
||||
break;
|
||||
case TRAN_TYPE_CLOSE:
|
||||
case TRAN_TYPE_CLOSEWLINK:
|
||||
samp *= qSqrt(1 - (timecode_start + (interval * i)));
|
||||
break;
|
||||
}
|
||||
|
||||
samples[i+1] = (quint8) (samp >> 8);
|
||||
samples[i] = (quint8) samp;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
#ifndef LOGARITHMICFADETRANSITION_H
|
||||
#define LOGARITHMICFADETRANSITION_H
|
||||
|
||||
#include "../effect.h"
|
||||
|
||||
class LogarithmicFadeTransition : public Effect {
|
||||
public:
|
||||
LogarithmicFadeTransition(Clip* c, const EffectMeta* em);
|
||||
void process_audio(double timecode_start, double timecode_end, quint8* samples, int nb_bytes, int channel_count);
|
||||
};
|
||||
|
||||
#endif // LOGARITHMICFADETRANSITION_H
|
||||
@@ -1,42 +0,0 @@
|
||||
#include "transition.h"
|
||||
|
||||
#include "project/clip.h"
|
||||
#include "io/config.h"
|
||||
#include "debug.h"
|
||||
|
||||
QVector<QString> video_transition_names;
|
||||
QVector<QString> audio_transition_names;
|
||||
|
||||
void init_transitions() {
|
||||
video_transition_names.resize(VIDEO_TRANSITION_COUNT);
|
||||
audio_transition_names.resize(AUDIO_TRANSITION_COUNT);
|
||||
|
||||
video_transition_names[VIDEO_DISSOLVE_TRANSITION] = "Cross Dissolve";
|
||||
|
||||
audio_transition_names[AUDIO_LINEAR_FADE_TRANSITION] = "Linear Fade";
|
||||
}
|
||||
|
||||
Transition::Transition(int i) : id(i), name(video_transition_names[i]), length(config.default_transition_length), link(NULL) {}
|
||||
|
||||
Transition::~Transition() {}
|
||||
|
||||
Transition* Transition::copy() {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void Transition::process_transition(double) {}
|
||||
void Transition::process_audio(double, double, quint8*, int, bool) {}
|
||||
|
||||
Transition* create_transition(int transition_id, Clip* c) {
|
||||
if (c->track < 0) {
|
||||
switch (transition_id) {
|
||||
case VIDEO_DISSOLVE_TRANSITION: return new CrossDissolveTransition();
|
||||
}
|
||||
} else {
|
||||
switch (transition_id) {
|
||||
case AUDIO_LINEAR_FADE_TRANSITION: return new LinearFadeTransition();
|
||||
}
|
||||
}
|
||||
dout << "[ERROR] Invalid transition ID";
|
||||
return NULL;
|
||||
}
|
||||
@@ -1,53 +0,0 @@
|
||||
#ifndef TRANSITION_H
|
||||
#define TRANSITION_H
|
||||
|
||||
#include <QString>
|
||||
|
||||
struct Clip;
|
||||
|
||||
enum VideoTransitions {
|
||||
VIDEO_DISSOLVE_TRANSITION,
|
||||
VIDEO_TRANSITION_COUNT
|
||||
};
|
||||
|
||||
enum AudioTransitions {
|
||||
AUDIO_LINEAR_FADE_TRANSITION,
|
||||
AUDIO_TRANSITION_COUNT
|
||||
};
|
||||
|
||||
class Transition
|
||||
{
|
||||
public:
|
||||
Transition(int);
|
||||
~Transition();
|
||||
int id;
|
||||
QString name;
|
||||
int length;
|
||||
Transition* link;
|
||||
virtual void process_transition(double);
|
||||
virtual void process_audio(double, double, quint8*, int, bool);
|
||||
virtual Transition* copy();
|
||||
};
|
||||
|
||||
void init_transitions();
|
||||
Transition* create_transition(int transition_id, Clip* c);
|
||||
extern QVector<QString> video_transition_names;
|
||||
extern QVector<QString> audio_transition_names;
|
||||
|
||||
// Video Transitions
|
||||
class CrossDissolveTransition : public Transition {
|
||||
public:
|
||||
CrossDissolveTransition();
|
||||
void process_transition(double);
|
||||
Transition* copy();
|
||||
};
|
||||
|
||||
// Audio Transitions
|
||||
class LinearFadeTransition : public Transition {
|
||||
public:
|
||||
LinearFadeTransition();
|
||||
void process_audio(double, double, quint8*, int, bool);
|
||||
Transition* copy();
|
||||
};
|
||||
|
||||
#endif // TRANSITION_H
|
||||
@@ -51,7 +51,6 @@ SOURCES += \
|
||||
io/previewgenerator.cpp \
|
||||
ui/labelslider.cpp \
|
||||
dialogs/preferencesdialog.cpp \
|
||||
effects/transition.cpp \
|
||||
ui/audiomonitor.cpp \
|
||||
project/undo.cpp \
|
||||
ui/scrollarea.cpp \
|
||||
@@ -81,7 +80,9 @@ SOURCES += \
|
||||
effects/internal/toneeffect.cpp \
|
||||
effects/internal/volumeeffect.cpp \
|
||||
effects/internal/crossdissolvetransition.cpp \
|
||||
effects/internal/shakeeffect.cpp
|
||||
effects/internal/shakeeffect.cpp \
|
||||
effects/internal/exponentialfadetransition.cpp \
|
||||
effects/internal/logarithmicfadetransition.cpp
|
||||
|
||||
HEADERS += \
|
||||
mainwindow.h \
|
||||
@@ -111,7 +112,6 @@ HEADERS += \
|
||||
io/previewgenerator.h \
|
||||
ui/labelslider.h \
|
||||
dialogs/preferencesdialog.h \
|
||||
effects/transition.h \
|
||||
ui/audiomonitor.h \
|
||||
project/undo.h \
|
||||
ui/scrollarea.h \
|
||||
@@ -141,7 +141,11 @@ HEADERS += \
|
||||
effects/internal/paneffect.h \
|
||||
effects/internal/toneeffect.h \
|
||||
effects/internal/volumeeffect.h \
|
||||
effects/internal/shakeeffect.h
|
||||
effects/internal/shakeeffect.h \
|
||||
effects/internal/linearfadetransition.h \
|
||||
effects/internal/crossdissolvetransition.h \
|
||||
effects/internal/exponentialfadetransition.h \
|
||||
effects/internal/logarithmicfadetransition.h
|
||||
|
||||
FORMS += \
|
||||
mainwindow.ui \
|
||||
|
||||
+47
-45
@@ -8,7 +8,6 @@
|
||||
|
||||
#include "panels/panels.h"
|
||||
#include "effects/effect.h"
|
||||
#include "effects/transition.h"
|
||||
#include "project/clip.h"
|
||||
#include "effects/effect.h"
|
||||
#include "ui/collapsiblewidget.h"
|
||||
@@ -27,8 +26,7 @@ EffectControls::EffectControls(QWidget *parent) :
|
||||
ui(new Ui::EffectControls)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
init_effects();
|
||||
init_transitions();
|
||||
init_effects();
|
||||
clear_effects(false);
|
||||
ui->headers->viewer = panel_sequence_viewer;
|
||||
ui->headers->snapping = false;
|
||||
@@ -66,15 +64,16 @@ void EffectControls::menu_select(QAction* q) {
|
||||
for (int i=0;i<selected_clips.size();i++) {
|
||||
Clip* c = sequence->clips.at(selected_clips.at(i));
|
||||
if ((c->track < 0) == video_menu) {
|
||||
const EffectMeta* meta = reinterpret_cast<const EffectMeta*>(q->data().value<quintptr>());
|
||||
if (transition_menu) {
|
||||
if (c->opening_transition == NULL) {
|
||||
ca->append(new AddTransitionCommand(c, q->data().toInt(), TA_OPENING_TRANSITION));
|
||||
ca->append(new AddTransitionCommand(c, meta, TA_OPENING_TRANSITION, 30));
|
||||
}
|
||||
if (c->closing_transition == NULL) {
|
||||
ca->append(new AddTransitionCommand(c, q->data().toInt(), TA_CLOSING_TRANSITION));
|
||||
ca->append(new AddTransitionCommand(c, meta, TA_CLOSING_TRANSITION, 30));
|
||||
}
|
||||
} else {
|
||||
ca->append(new AddEffectCommand(c, reinterpret_cast<EffectMeta*>(q->data().value<quintptr>())));
|
||||
ca->append(new AddEffectCommand(c, meta));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -149,7 +148,7 @@ void EffectControls::show_effect_menu(bool video, bool transitions) {
|
||||
video_menu = video;
|
||||
transition_menu = transitions;
|
||||
|
||||
if (transition_menu) {
|
||||
/*if (transition_menu) {
|
||||
// TODO old effect/transition code grandfathered in, to be updated
|
||||
|
||||
int lim;
|
||||
@@ -181,64 +180,67 @@ void EffectControls::show_effect_menu(bool video, bool transitions) {
|
||||
}
|
||||
connect(&effects_menu, SIGNAL(triggered(QAction*)), this, SLOT(menu_select(QAction*)));
|
||||
effects_menu.exec(QCursor::pos());
|
||||
} else {
|
||||
} else {*/
|
||||
effects_loaded.lock();
|
||||
|
||||
QVector<EffectMeta>& effect_list = (video) ? video_effects : audio_effects;
|
||||
QMenu effects_menu(this);
|
||||
for (int i=0;i<effect_list.size();i++) {
|
||||
const EffectMeta& em = effect_list.at(i);
|
||||
QAction* action = new QAction(&effects_menu);
|
||||
action->setText(em.name);
|
||||
action->setData(reinterpret_cast<quintptr>(&em));
|
||||
|
||||
QMenu* parent = &effects_menu;
|
||||
if (!em.category.isEmpty()) {
|
||||
bool found = false;
|
||||
for (int j=0;j<effects_menu.actions().size();j++) {
|
||||
QAction* action = effects_menu.actions().at(j);
|
||||
if (action->menu() != NULL) {
|
||||
if (action->menu()->title() == em.category) {
|
||||
parent = action->menu();
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!found) {
|
||||
parent = new QMenu(&effects_menu);
|
||||
parent->setTitle(em.category);
|
||||
if (em.type == EFFECT_TYPE_TRANSITION == transition_menu) {
|
||||
QAction* action = new QAction(&effects_menu);
|
||||
action->setText(em.name);
|
||||
action->setData(reinterpret_cast<quintptr>(&em));
|
||||
|
||||
QMenu* parent = &effects_menu;
|
||||
if (!em.category.isEmpty()) {
|
||||
bool found = false;
|
||||
for (int i=0;i<effects_menu.actions().size();i++) {
|
||||
QAction* comp_action = effects_menu.actions().at(i);
|
||||
if (comp_action->text() > em.category) {
|
||||
effects_menu.insertMenu(comp_action, parent);
|
||||
found = true;
|
||||
break;
|
||||
for (int j=0;j<effects_menu.actions().size();j++) {
|
||||
QAction* action = effects_menu.actions().at(j);
|
||||
if (action->menu() != NULL) {
|
||||
if (action->menu()->title() == em.category) {
|
||||
parent = action->menu();
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!found) effects_menu.addMenu(parent);
|
||||
}
|
||||
}
|
||||
if (!found) {
|
||||
parent = new QMenu(&effects_menu);
|
||||
parent->setTitle(em.category);
|
||||
|
||||
bool found = false;
|
||||
for (int i=0;i<parent->actions().size();i++) {
|
||||
QAction* comp_action = parent->actions().at(i);
|
||||
if (comp_action->text() > action->text()) {
|
||||
parent->insertAction(comp_action, action);
|
||||
found = true;
|
||||
break;
|
||||
bool found = false;
|
||||
for (int i=0;i<effects_menu.actions().size();i++) {
|
||||
QAction* comp_action = effects_menu.actions().at(i);
|
||||
if (comp_action->text() > em.category) {
|
||||
effects_menu.insertMenu(comp_action, parent);
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!found) effects_menu.addMenu(parent);
|
||||
}
|
||||
}
|
||||
|
||||
bool found = false;
|
||||
for (int i=0;i<parent->actions().size();i++) {
|
||||
QAction* comp_action = parent->actions().at(i);
|
||||
if (comp_action->text() > action->text()) {
|
||||
parent->insertAction(comp_action, action);
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!found) parent->addAction(action);
|
||||
}
|
||||
if (!found) parent->addAction(action);
|
||||
}
|
||||
|
||||
effects_loaded.unlock();
|
||||
|
||||
connect(&effects_menu, SIGNAL(triggered(QAction*)), this, SLOT(menu_select(QAction*)));
|
||||
effects_menu.exec(QCursor::pos());
|
||||
}
|
||||
//}
|
||||
}
|
||||
|
||||
void EffectControls::clear_effects(bool clear_cache) {
|
||||
|
||||
+84
-75
@@ -10,7 +10,6 @@
|
||||
#include "panels/timeline.h"
|
||||
#include "project/sequence.h"
|
||||
#include "effects/effect.h"
|
||||
#include "effects/transition.h"
|
||||
#include "io/previewgenerator.h"
|
||||
#include "project/undo.h"
|
||||
#include "mainwindow.h"
|
||||
@@ -360,7 +359,6 @@ void Project::delete_selected_media() {
|
||||
}
|
||||
|
||||
for (int i=0;i<items.size();i++) {
|
||||
|
||||
ca->append(new DeleteMediaCommand(items.at(i)));
|
||||
|
||||
if (get_type_from_tree(items.at(i)) == MEDIA_TYPE_SEQUENCE) {
|
||||
@@ -982,70 +980,78 @@ bool Project::load_worker(QFile& f, QXmlStreamReader& stream, int type) {
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (stream.name() == "effects") {
|
||||
while (!(stream.name() == "effects" && stream.isEndElement()) && !stream.atEnd()) {
|
||||
stream.readNext();
|
||||
if (stream.name() == "effect" && stream.isStartElement()) {
|
||||
int effect_id = -1;
|
||||
QString effect_name;
|
||||
bool effect_enabled = true;
|
||||
for (int j=0;j<stream.attributes().size();j++) {
|
||||
const QXmlStreamAttribute& attr = stream.attributes().at(j);
|
||||
if (attr.name() == "id") {
|
||||
effect_id = attr.value().toInt();
|
||||
} else if (attr.name() == "enabled") {
|
||||
effect_enabled = (attr.value() == "1");
|
||||
} else if (attr.name() == "name") {
|
||||
effect_name = attr.value().toString();
|
||||
}
|
||||
}
|
||||
} else if (stream.isStartElement() && (stream.name() == "effect" || stream.name() == "opening" || stream.name() == "closing")) {
|
||||
int effect_id = -1;
|
||||
QString effect_name;
|
||||
bool effect_enabled = true;
|
||||
int effect_length = -1;
|
||||
for (int j=0;j<stream.attributes().size();j++) {
|
||||
const QXmlStreamAttribute& attr = stream.attributes().at(j);
|
||||
if (attr.name() == "id") {
|
||||
effect_id = attr.value().toInt();
|
||||
} else if (attr.name() == "enabled") {
|
||||
effect_enabled = (attr.value() == "1");
|
||||
} else if (attr.name() == "name") {
|
||||
effect_name = attr.value().toString();
|
||||
} else if (attr.name() == "length") {
|
||||
effect_length = attr.value().toInt();
|
||||
}
|
||||
}
|
||||
|
||||
// backwards compatibility with 180820
|
||||
if (effect_id != -1) {
|
||||
switch (effect_id) {
|
||||
case 0: effect_name = (c->track < 0) ? "Transform" : "Volume"; break;
|
||||
case 1: effect_name = (c->track < 0) ? "Shake" : "Pan"; break;
|
||||
case 2: effect_name = (c->track < 0) ? "Text" : "Noise"; break;
|
||||
case 3: effect_name = (c->track < 0) ? "Solid" : "Tone"; break;
|
||||
case 4: effect_name = "Invert"; break;
|
||||
case 5: effect_name = "Chroma Key"; break;
|
||||
case 6: effect_name = "Gaussian Blur"; break;
|
||||
case 7: effect_name = "Crop"; break;
|
||||
case 8: effect_name = "Flip"; break;
|
||||
case 9: effect_name = "Box Blur"; break;
|
||||
case 10: effect_name = "Wave"; break;
|
||||
case 11: effect_name = "Temperature"; break;
|
||||
}
|
||||
// backwards compatibility with 180820
|
||||
if (stream.name() == "effect" && effect_id != -1) {
|
||||
switch (effect_id) {
|
||||
case 0: effect_name = (c->track < 0) ? "Transform" : "Volume"; break;
|
||||
case 1: effect_name = (c->track < 0) ? "Shake" : "Pan"; break;
|
||||
case 2: effect_name = (c->track < 0) ? "Text" : "Noise"; break;
|
||||
case 3: effect_name = (c->track < 0) ? "Solid" : "Tone"; break;
|
||||
case 4: effect_name = "Invert"; break;
|
||||
case 5: effect_name = "Chroma Key"; break;
|
||||
case 6: effect_name = "Gaussian Blur"; break;
|
||||
case 7: effect_name = "Crop"; break;
|
||||
case 8: effect_name = "Flip"; break;
|
||||
case 9: effect_name = "Box Blur"; break;
|
||||
case 10: effect_name = "Wave"; break;
|
||||
case 11: effect_name = "Temperature"; break;
|
||||
}
|
||||
}
|
||||
|
||||
// wait for effects to be loaded
|
||||
effects_loaded.lock();
|
||||
|
||||
const EffectMeta* meta = NULL;
|
||||
|
||||
// find effect with this name
|
||||
if (!effect_name.isEmpty()) {
|
||||
QVector<EffectMeta>& effect_list = (c->track < 0) ? video_effects : audio_effects;
|
||||
for (int j=0;j<effect_list.size();j++) {
|
||||
if (effect_list.at(j).name == effect_name) {
|
||||
meta = &effect_list.at(j);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// wait for effects to be loaded
|
||||
effects_loaded.lock();
|
||||
effects_loaded.unlock();
|
||||
|
||||
const EffectMeta* meta = NULL;
|
||||
if (meta == NULL) {
|
||||
dout << "[WARNING] An effect used by this project is missing. It was not loaded.";
|
||||
} else {
|
||||
QString tag = stream.name().toString();
|
||||
|
||||
// find effect with this name
|
||||
if (!effect_name.isEmpty()) {
|
||||
QVector<EffectMeta>& effect_list = (c->track < 0) ? video_effects : audio_effects;
|
||||
for (int j=0;j<effect_list.size();j++) {
|
||||
if (effect_list.at(j).name == effect_name) {
|
||||
meta = &effect_list.at(j);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
Effect* e = create_effect(c, meta);
|
||||
if (effect_length > -1) e->length = effect_length;
|
||||
e->set_enabled(effect_enabled);
|
||||
e->load(stream);
|
||||
|
||||
if (meta == NULL) {
|
||||
dout << "[WARNING] An effect used by this project is missing. It was not loaded.";
|
||||
} else {
|
||||
Effect* e = create_effect(c, meta);
|
||||
e->set_enabled(effect_enabled);
|
||||
e->load(stream);
|
||||
c->effects.append(e);
|
||||
}
|
||||
|
||||
effects_loaded.unlock();
|
||||
}
|
||||
}
|
||||
if (tag == "opening") {
|
||||
c->opening_transition = e;
|
||||
} else if (tag == "closing") {
|
||||
c->closing_transition = e;
|
||||
} else {
|
||||
c->effects.append(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1290,12 +1296,7 @@ void Project::save_folder(QXmlStreamWriter& stream, QTreeWidgetItem* parent, int
|
||||
stream.writeAttribute("in", QString::number(c->timeline_in));
|
||||
stream.writeAttribute("out", QString::number(c->timeline_out));
|
||||
stream.writeAttribute("track", QString::number(c->track));
|
||||
if (c->opening_transition != NULL) {
|
||||
stream.writeAttribute("opening", QString::number(c->opening_transition->id));
|
||||
}
|
||||
if (c->closing_transition != NULL) {
|
||||
stream.writeAttribute("closing", QString::number(c->closing_transition->id));
|
||||
}
|
||||
|
||||
stream.writeAttribute("r", QString::number(c->color_r));
|
||||
stream.writeAttribute("g", QString::number(c->color_g));
|
||||
stream.writeAttribute("b", QString::number(c->color_b));
|
||||
@@ -1324,16 +1325,24 @@ void Project::save_folder(QXmlStreamWriter& stream, QTreeWidgetItem* parent, int
|
||||
}
|
||||
stream.writeEndElement(); // linked
|
||||
|
||||
stream.writeStartElement("effects"); // effects
|
||||
for (int k=0;k<c->effects.size();k++) {
|
||||
stream.writeStartElement("effect"); // effect
|
||||
Effect* e = c->effects.at(k);
|
||||
stream.writeAttribute("name", e->meta->name);
|
||||
stream.writeAttribute("enabled", QString::number(e->is_enabled()));
|
||||
e->save(stream);
|
||||
stream.writeEndElement(); // effect
|
||||
}
|
||||
stream.writeEndElement(); // effects
|
||||
stream.writeStartElement("effect"); // effect
|
||||
c->effects.at(k)->save(stream);
|
||||
stream.writeEndElement(); // effect
|
||||
}
|
||||
|
||||
if (c->opening_transition != NULL) {
|
||||
stream.writeStartElement("opening");
|
||||
c->opening_transition->save(stream);
|
||||
stream.writeEndElement(); // opening
|
||||
}
|
||||
|
||||
if (c->closing_transition != NULL) {
|
||||
stream.writeStartElement("closing"); // closing
|
||||
c->closing_transition->save(stream);
|
||||
stream.writeEndElement(); // closing
|
||||
}
|
||||
|
||||
stream.writeEndElement(); // clip
|
||||
}
|
||||
}
|
||||
|
||||
+42
-5
@@ -12,10 +12,11 @@
|
||||
#include "panels/viewer.h"
|
||||
#include "playback/cacher.h"
|
||||
#include "playback/playback.h"
|
||||
#include "effects/transition.h"
|
||||
#include "ui_viewer.h"
|
||||
#include "project/undo.h"
|
||||
#include "io/config.h"
|
||||
#include "effects/effect.h"
|
||||
#include "debug.h"
|
||||
|
||||
#include <QTime>
|
||||
#include <QScrollBar>
|
||||
@@ -159,11 +160,11 @@ void Timeline::add_transition() {
|
||||
Clip* c = sequence->clips.at(i);
|
||||
if (c != NULL && is_clip_selected(c, true)) {
|
||||
if (c->opening_transition == NULL) {
|
||||
ca->append(new AddTransitionCommand(c, 0, TA_OPENING_TRANSITION));
|
||||
ca->append(new AddTransitionCommand(c, get_internal_meta(EFFECT_INTERNAL_LINEARFADE), TA_OPENING_TRANSITION, 30));
|
||||
adding = true;
|
||||
}
|
||||
if (c->closing_transition == NULL) {
|
||||
ca->append(new AddTransitionCommand(c, 0, TA_OPENING_TRANSITION));
|
||||
ca->append(new AddTransitionCommand(c, get_internal_meta(EFFECT_INTERNAL_LINEARFADE), TA_OPENING_TRANSITION, 30));
|
||||
adding = true;
|
||||
}
|
||||
}
|
||||
@@ -1192,8 +1193,44 @@ void Timeline::on_recordButton_clicked() {
|
||||
}
|
||||
|
||||
void Timeline::on_toolTransitionButton_clicked() {
|
||||
decheck_tool_buttons(sender());
|
||||
creating = false;
|
||||
|
||||
QMenu transition_menu(this);
|
||||
|
||||
for (int i=0;i<video_effects.size();i++) {
|
||||
const EffectMeta& em = video_effects.at(i);
|
||||
if (em.type == EFFECT_TYPE_TRANSITION) {
|
||||
QAction* a = transition_menu.addAction(em.name);
|
||||
a->setObjectName("v");
|
||||
a->setData(reinterpret_cast<quintptr>(&em));
|
||||
}
|
||||
}
|
||||
|
||||
transition_menu.addSeparator();
|
||||
|
||||
for (int i=0;i<audio_effects.size();i++) {
|
||||
const EffectMeta& em = audio_effects.at(i);
|
||||
if (em.type == EFFECT_TYPE_TRANSITION) {
|
||||
QAction* a = transition_menu.addAction(em.name);
|
||||
a->setObjectName("a");
|
||||
a->setData(reinterpret_cast<quintptr>(&em));
|
||||
}
|
||||
}
|
||||
|
||||
connect(&transition_menu, SIGNAL(triggered(QAction*)), this, SLOT(transition_menu_select(QAction*)));
|
||||
transition_menu.exec(QCursor::pos());
|
||||
}
|
||||
|
||||
void Timeline::transition_menu_select(QAction* a) {
|
||||
transition_tool_meta = reinterpret_cast<const EffectMeta*>(a->data().value<quintptr>());
|
||||
|
||||
if (a->objectName() == "v") {
|
||||
transition_tool_side = -1;
|
||||
} else {
|
||||
transition_tool_side = 1;
|
||||
}
|
||||
|
||||
decheck_tool_buttons(sender());
|
||||
ui->timeline_area->setCursor(Qt::CrossCursor);
|
||||
tool = TIMELINE_TOOL_TRANSITION;
|
||||
creating = false;
|
||||
}
|
||||
|
||||
+7
-2
@@ -21,7 +21,8 @@ class QPushButton;
|
||||
class SourceTable;
|
||||
class ViewerWidget;
|
||||
class ComboAction;
|
||||
class Transition;
|
||||
class Effect;
|
||||
struct EffectMeta;
|
||||
struct Sequence;
|
||||
struct Clip;
|
||||
struct Media;
|
||||
@@ -57,7 +58,7 @@ struct Ghost {
|
||||
bool trimming;
|
||||
|
||||
// transition trimming
|
||||
Transition* transition;
|
||||
Effect* transition;
|
||||
};
|
||||
|
||||
namespace Ui {
|
||||
@@ -169,6 +170,8 @@ public:
|
||||
bool transition_tool_proc;
|
||||
int transition_tool_clip;
|
||||
int transition_tool_type;
|
||||
const EffectMeta* transition_tool_meta;
|
||||
int transition_tool_side;
|
||||
|
||||
// clipboard
|
||||
QVector<Clip*> clip_clipboard;
|
||||
@@ -209,6 +212,8 @@ private slots:
|
||||
|
||||
void on_toolTransitionButton_clicked();
|
||||
|
||||
void transition_menu_select(QAction*);
|
||||
|
||||
private:
|
||||
QVector<QPushButton*> tool_buttons;
|
||||
void decheck_tool_buttons(QObject* sender);
|
||||
|
||||
+4
-6
@@ -8,7 +8,6 @@
|
||||
#include "effects/effect.h"
|
||||
#include "panels/timeline.h"
|
||||
#include "panels/project.h"
|
||||
#include "effects/transition.h"
|
||||
#include "debug.h"
|
||||
|
||||
extern "C" {
|
||||
@@ -47,24 +46,24 @@ void apply_audio_effects(Clip* c, double timecode_start, AVFrame* frame, int nb_
|
||||
if (c->opening_transition != NULL) {
|
||||
if (c->media_type == MEDIA_TYPE_FOOTAGE) {
|
||||
double transition_start = (c->clip_in / c->sequence->frame_rate);
|
||||
double transition_end = transition_start + (c->opening_transition->length / c->sequence->frame_rate);
|
||||
double transition_end = ((c->clip_in + c->opening_transition->length) / c->sequence->frame_rate);
|
||||
if (timecode_end < transition_end) {
|
||||
double adjustment = transition_end - transition_start;
|
||||
double adjusted_range_start = (timecode_start - transition_start) / adjustment;
|
||||
double adjusted_range_end = (timecode_end - transition_start) / adjustment;
|
||||
c->opening_transition->process_audio(adjusted_range_start, adjusted_range_end, frame->data[0], nb_bytes, false);
|
||||
c->opening_transition->process_audio(adjusted_range_start, adjusted_range_end, frame->data[0], nb_bytes, TRAN_TYPE_OPEN);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (c->closing_transition != NULL) {
|
||||
if (c->media_type == MEDIA_TYPE_FOOTAGE) {
|
||||
double transition_start = (c->clip_in + c->getLength() - c->closing_transition->length) / c->sequence->frame_rate;
|
||||
double transition_end = (c->clip_in + c->getLength()) / c->sequence->frame_rate;
|
||||
double transition_start = transition_end - (c->closing_transition->length / c->sequence->frame_rate);
|
||||
if (timecode_start > transition_start) {
|
||||
double adjustment = transition_end - transition_start;
|
||||
double adjusted_range_start = (timecode_start - transition_start) / adjustment;
|
||||
double adjusted_range_end = (timecode_end - transition_start) / adjustment;
|
||||
c->closing_transition->process_audio(adjusted_range_start, adjusted_range_end, frame->data[0], nb_bytes, true);
|
||||
c->closing_transition->process_audio(adjusted_range_start, adjusted_range_end, frame->data[0], nb_bytes, TRAN_TYPE_CLOSE);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -485,7 +484,6 @@ void cache_video_worker(Clip* c, long playhead) {
|
||||
}
|
||||
|
||||
void reset_cache(Clip* c, long target_frame) {
|
||||
dout << "reset called";
|
||||
// if we seek to a whole other place in the timeline, we'll need to reset the cache with new values
|
||||
switch (c->media_type) {
|
||||
case MEDIA_TYPE_FOOTAGE:
|
||||
|
||||
+6
-7
@@ -1,7 +1,6 @@
|
||||
#include "clip.h"
|
||||
|
||||
#include "effects/effect.h"
|
||||
#include "effects/transition.h"
|
||||
#include "io/media.h"
|
||||
#include "io/config.h"
|
||||
#include "playback/playback.h"
|
||||
@@ -65,8 +64,8 @@ Clip* Clip::copy(Sequence* s) {
|
||||
copy->effects.append(effects.at(i)->copy(copy));
|
||||
}
|
||||
|
||||
if (opening_transition != NULL) copy->opening_transition = opening_transition->copy();
|
||||
if (closing_transition != NULL) copy->closing_transition = closing_transition->copy();
|
||||
if (opening_transition != NULL) copy->opening_transition = opening_transition->copy(copy);
|
||||
if (closing_transition != NULL) copy->closing_transition = closing_transition->copy(copy);
|
||||
|
||||
copy->recalculateMaxLength();
|
||||
|
||||
@@ -164,16 +163,16 @@ Clip::~Clip() {
|
||||
}
|
||||
|
||||
long Clip::get_timeline_in_with_transition() {
|
||||
if (opening_transition != NULL && opening_transition->link != NULL) {
|
||||
return timeline_in - opening_transition->link->length;
|
||||
if (opening_transition != NULL && opening_transition->tlink != NULL) {
|
||||
return timeline_in - opening_transition->tlink->length;
|
||||
} else {
|
||||
return timeline_in;
|
||||
}
|
||||
}
|
||||
|
||||
long Clip::get_timeline_out_with_transition() {
|
||||
if (closing_transition != NULL && closing_transition->link != NULL) {
|
||||
return timeline_out + closing_transition->link->length;
|
||||
if (closing_transition != NULL && closing_transition->tlink != NULL) {
|
||||
return timeline_out + closing_transition->tlink->length;
|
||||
} else {
|
||||
return timeline_out;
|
||||
}
|
||||
|
||||
+2
-3
@@ -10,7 +10,6 @@
|
||||
|
||||
class Cacher;
|
||||
class Effect;
|
||||
class Transition;
|
||||
class QOpenGLFramebufferObject;
|
||||
class ComboAction;
|
||||
struct Sequence;
|
||||
@@ -73,8 +72,8 @@ struct Clip
|
||||
// other variables (should be deep copied/duplicated in copy())
|
||||
QList<Effect*> effects;
|
||||
QVector<int> linked;
|
||||
Transition* opening_transition;
|
||||
Transition* closing_transition;
|
||||
Effect* opening_transition;
|
||||
Effect* closing_transition;
|
||||
|
||||
// media handling
|
||||
AVFormatContext* formatCtx;
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
#include "sequence.h"
|
||||
|
||||
#include "project/clip.h"
|
||||
#include "effects/transition.h"
|
||||
|
||||
Sequence::Sequence() :
|
||||
playhead(0),
|
||||
|
||||
+4
-5
@@ -16,7 +16,6 @@
|
||||
#include "effects/effect.h"
|
||||
#include "io/media.h"
|
||||
#include "playback/cacher.h"
|
||||
#include "effects/transition.h"
|
||||
#include "ui/labelslider.h"
|
||||
#include "ui/viewerwidget.h"
|
||||
#include "project/marker.h"
|
||||
@@ -194,7 +193,7 @@ void SetTimelineInOutCommand::redo() {
|
||||
mainWindow->setWindowModified(true);
|
||||
}
|
||||
|
||||
AddEffectCommand::AddEffectCommand(Clip* c, EffectMeta *e) :
|
||||
AddEffectCommand::AddEffectCommand(Clip* c, const EffectMeta *e) :
|
||||
clip(c),
|
||||
meta(e),
|
||||
ref(NULL),
|
||||
@@ -221,7 +220,7 @@ void AddEffectCommand::redo() {
|
||||
mainWindow->setWindowModified(true);
|
||||
}
|
||||
|
||||
AddTransitionCommand::AddTransitionCommand(Clip* c, int itransition, int itype, int ilength) :
|
||||
AddTransitionCommand::AddTransitionCommand(Clip* c, const EffectMeta *itransition, int itype, int ilength) :
|
||||
clip(c),
|
||||
transition(itransition),
|
||||
type(itype),
|
||||
@@ -242,10 +241,10 @@ void AddTransitionCommand::undo() {
|
||||
|
||||
void AddTransitionCommand::redo() {
|
||||
if (type == TA_OPENING_TRANSITION) {
|
||||
clip->opening_transition = create_transition(transition, clip);
|
||||
clip->opening_transition = create_effect(clip, transition);
|
||||
if (length > 0) clip->opening_transition->length = length;
|
||||
} else {
|
||||
clip->closing_transition = create_transition(transition, clip);
|
||||
clip->closing_transition = create_effect(clip, transition);
|
||||
if (length > 0) clip->closing_transition->length = length;
|
||||
}
|
||||
mainWindow->setWindowModified(true);
|
||||
|
||||
+5
-5
@@ -91,13 +91,13 @@ private:
|
||||
|
||||
class AddEffectCommand : public QUndoCommand {
|
||||
public:
|
||||
AddEffectCommand(Clip* c, EffectMeta* e);
|
||||
AddEffectCommand(Clip* c, const EffectMeta* e);
|
||||
~AddEffectCommand();
|
||||
void undo();
|
||||
void redo();
|
||||
private:
|
||||
Clip* clip;
|
||||
EffectMeta* meta;
|
||||
const EffectMeta* meta;
|
||||
Effect* ref;
|
||||
bool done;
|
||||
bool old_project_changed;
|
||||
@@ -105,12 +105,12 @@ private:
|
||||
|
||||
class AddTransitionCommand : public QUndoCommand {
|
||||
public:
|
||||
AddTransitionCommand(Clip* c, int itransition, int itype, int ilength = 0);
|
||||
AddTransitionCommand(Clip* c, const EffectMeta* itransition, int itype, int ilength);
|
||||
void undo();
|
||||
void redo();
|
||||
private:
|
||||
Clip* clip;
|
||||
int transition;
|
||||
const EffectMeta* transition;
|
||||
int type;
|
||||
int length;
|
||||
bool old_project_changed;
|
||||
@@ -138,7 +138,7 @@ public:
|
||||
private:
|
||||
Clip* clip;
|
||||
int type;
|
||||
Transition* transition;
|
||||
Effect* transition;
|
||||
bool old_project_changed;
|
||||
};
|
||||
|
||||
|
||||
+18
-12
@@ -18,7 +18,6 @@
|
||||
#include "debug.h"
|
||||
|
||||
#include "effects/effect.h"
|
||||
#include "effects/transition.h"
|
||||
|
||||
#include "effects/internal/solideffect.h"
|
||||
#include "effects/internal/texteffect.h"
|
||||
@@ -1206,9 +1205,9 @@ void TimelineWidget::mouseReleaseEvent(QMouseEvent *event) {
|
||||
|
||||
panel_timeline->delete_areas_and_relink(ca, areas);
|
||||
ca->append(new MoveClipAction(c, qMin(transition_start, c->timeline_in), qMax(transition_end, c->timeline_out), c->clip_in, c->track));
|
||||
}
|
||||
}
|
||||
|
||||
ca->append(new AddTransitionCommand(c, 0, panel_timeline->transition_tool_type, transition_end - transition_start));
|
||||
ca->append(new AddTransitionCommand(c, panel_timeline->transition_tool_meta, panel_timeline->transition_tool_type, transition_end - transition_start));
|
||||
|
||||
push_undo = true;
|
||||
}
|
||||
@@ -2100,15 +2099,22 @@ void TimelineWidget::mouseMoveEvent(QMouseEvent *event) {
|
||||
panel_timeline->transition_tool_proc = true;
|
||||
}
|
||||
} else {
|
||||
panel_timeline->transition_tool_clip = getClipIndexFromCoords(panel_timeline->cursor_frame, panel_timeline->cursor_track);
|
||||
int mouse_clip = getClipIndexFromCoords(panel_timeline->cursor_frame, panel_timeline->cursor_track);
|
||||
if (mouse_clip > -1) {
|
||||
Clip* c = sequence->clips.at(mouse_clip);
|
||||
if (same_sign(c->track, panel_timeline->transition_tool_side)) {
|
||||
panel_timeline->transition_tool_clip = mouse_clip;
|
||||
long halfway = c->timeline_in + (c->getLength()/2);
|
||||
if (panel_timeline->cursor_frame > halfway) {
|
||||
panel_timeline->transition_tool_type = TA_CLOSING_TRANSITION;
|
||||
} else {
|
||||
panel_timeline->transition_tool_type = TA_OPENING_TRANSITION;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (panel_timeline->transition_tool_clip > -1) {
|
||||
Clip* c = sequence->clips.at(panel_timeline->transition_tool_clip);
|
||||
long halfway = c->timeline_in + (c->getLength()/2);
|
||||
if (panel_timeline->cursor_frame > halfway) {
|
||||
panel_timeline->transition_tool_type = TA_CLOSING_TRANSITION;
|
||||
} else {
|
||||
panel_timeline->transition_tool_type = TA_OPENING_TRANSITION;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2323,7 +2329,7 @@ void TimelineWidget::paintEvent(QPaintEvent*) {
|
||||
|
||||
// draw clip transitions
|
||||
for (int i=0;i<2;i++) {
|
||||
Transition* t = (i == 0) ? clip->opening_transition : clip->closing_transition;
|
||||
Effect* t = (i == 0) ? clip->opening_transition : clip->closing_transition;
|
||||
if (t != NULL) {
|
||||
int transition_width = getScreenPointFromFrame(panel_timeline->zoom, t->length);
|
||||
int transition_height = clip_rect.height();
|
||||
|
||||
+1
-4
@@ -76,10 +76,7 @@ private:
|
||||
|
||||
int scroll;
|
||||
|
||||
SetSelectionsCommand* selection_command;
|
||||
|
||||
/*QVector<QTreeWidgetItem*> file_import_items;
|
||||
QVector<Media*> file_import_media;*/
|
||||
SetSelectionsCommand* selection_command;
|
||||
signals:
|
||||
|
||||
public slots:
|
||||
|
||||
+26
-22
@@ -6,7 +6,6 @@
|
||||
#include "panels/project.h"
|
||||
#include "project/sequence.h"
|
||||
#include "effects/effect.h"
|
||||
#include "effects/transition.h"
|
||||
#include "playback/playback.h"
|
||||
#include "playback/audio.h"
|
||||
#include "io/media.h"
|
||||
@@ -198,6 +197,26 @@ GLuint ViewerWidget::draw_clip(QOpenGLFramebufferObject* fbo, GLuint texture) {
|
||||
return fbo->texture();
|
||||
}
|
||||
|
||||
void ViewerWidget::process_effect(Clip* c, Effect* e, double timecode, GLTextureCoords& coords, GLuint& composite_texture, bool& fbo_switcher) {
|
||||
if (e->is_enabled()) {
|
||||
if (e->enable_coords) {
|
||||
e->process_coords(timecode, coords);
|
||||
}
|
||||
if (e->enable_shader || e->enable_superimpose) {
|
||||
e->startEffect();
|
||||
if (e->enable_shader) {
|
||||
e->process_shader(timecode);
|
||||
}
|
||||
composite_texture = draw_clip(c->fbo[fbo_switcher], composite_texture);
|
||||
if (e->enable_superimpose) {
|
||||
GLuint superimpose_texture = e->process_superimpose(timecode);
|
||||
if (superimpose_texture != 0) draw_clip(c->fbo[fbo_switcher], superimpose_texture);
|
||||
}
|
||||
fbo_switcher = !fbo_switcher;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
GLuint ViewerWidget::compose_sequence(Clip* nest, bool render_audio) {
|
||||
Sequence* s = viewer->seq;
|
||||
long playhead = s->playhead;
|
||||
@@ -359,39 +378,24 @@ GLuint ViewerWidget::compose_sequence(Clip* nest, bool render_audio) {
|
||||
}
|
||||
|
||||
// EFFECT CODE START
|
||||
double timecode = ((double)(playhead-c->timeline_in+c->clip_in)/(double)c->sequence->frame_rate);
|
||||
for (int j=0;j<c->effects.size();j++) {
|
||||
Effect* e = c->effects.at(j);
|
||||
if (e->is_enabled()) {
|
||||
double timecode = ((double)(playhead-c->timeline_in+c->clip_in)/(double)c->sequence->frame_rate);
|
||||
if (e->enable_coords) {
|
||||
e->process_coords(timecode, coords);
|
||||
}
|
||||
if (e->enable_shader || e->enable_superimpose) {
|
||||
e->startEffect();
|
||||
if (e->enable_shader) {
|
||||
e->process_shader(timecode);
|
||||
}
|
||||
composite_texture = draw_clip(c->fbo[fbo_switcher], composite_texture);
|
||||
if (e->enable_superimpose) {
|
||||
GLuint superimpose_texture = e->process_superimpose(timecode);
|
||||
if (superimpose_texture != 0) draw_clip(c->fbo[fbo_switcher], superimpose_texture);
|
||||
}
|
||||
fbo_switcher = !fbo_switcher;
|
||||
}
|
||||
}
|
||||
process_effect(c, c->effects.at(j), timecode, coords, composite_texture, fbo_switcher);
|
||||
}
|
||||
|
||||
if (c->opening_transition != NULL) {
|
||||
int transition_progress = playhead - c->timeline_in;
|
||||
if (transition_progress < c->opening_transition->length) {
|
||||
c->opening_transition->process_transition((double)transition_progress/(double)c->opening_transition->length);
|
||||
process_effect(c, c->opening_transition, (double)transition_progress/(double)c->opening_transition->length, coords, composite_texture, fbo_switcher);
|
||||
//c->opening_transition->process_transition((double)transition_progress/(double)c->opening_transition->length);
|
||||
}
|
||||
}
|
||||
|
||||
if (c->closing_transition != NULL) {
|
||||
int transition_progress = c->closing_transition->length - (playhead - c->timeline_in - c->getLength() + c->closing_transition->length);
|
||||
if (transition_progress < c->closing_transition->length) {
|
||||
c->closing_transition->process_transition((double)transition_progress/(double)c->closing_transition->length);
|
||||
process_effect(c, c->closing_transition, (double)transition_progress/(double)c->closing_transition->length, coords, composite_texture, fbo_switcher);
|
||||
//c->closing_transition->process_transition((double)transition_progress/(double)c->closing_transition->length);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -13,6 +13,8 @@ class Viewer;
|
||||
struct Clip;
|
||||
struct MediaStream;
|
||||
class QOpenGLFramebufferObject;
|
||||
class Effect;
|
||||
struct GLTextureCoords;
|
||||
|
||||
class ViewerWidget : public QOpenGLWidget
|
||||
{
|
||||
@@ -42,6 +44,7 @@ private:
|
||||
void seek_from_click(int x);
|
||||
GLuint compose_sequence(Clip *nest, bool render_audio);
|
||||
GLuint draw_clip(QOpenGLFramebufferObject *clip, GLuint texture);
|
||||
void process_effect(Clip* c, Effect* e, double timecode, GLTextureCoords& coords, GLuint& composite_texture, bool& fbo_switcher);
|
||||
private slots:
|
||||
void retry();
|
||||
void deleteFunction();
|
||||
|
||||
Reference in New Issue
Block a user