transition code rewrite for #110
This commit is contained in:
@@ -5,6 +5,7 @@
|
||||
#include "panels/project.h"
|
||||
#include "project/sequence.h"
|
||||
#include "project/undo.h"
|
||||
#include "project/clip.h"
|
||||
#include "panels/timeline.h"
|
||||
#include "playback/playback.h"
|
||||
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
#include "panels/timeline.h"
|
||||
#include "panels/project.h"
|
||||
#include "project/sequence.h"
|
||||
#include "project/clip.h"
|
||||
#include "playback/playback.h"
|
||||
#include "playback/cacher.h"
|
||||
#include "io/media.h"
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
#include <QOpenGLFunctions>
|
||||
|
||||
CrossDissolveTransition::CrossDissolveTransition(Clip* c, const EffectMeta* em) : Effect(c, em) {
|
||||
CrossDissolveTransition::CrossDissolveTransition(Clip* c, const EffectMeta* em) : Transition(c, em) {
|
||||
enable_coords = true;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
#ifndef CROSSDISSOLVETRANSITION_H
|
||||
#define CROSSDISSOLVETRANSITION_H
|
||||
|
||||
#include "project/effect.h"
|
||||
#include "project/transition.h"
|
||||
|
||||
class CrossDissolveTransition : public Effect {
|
||||
class CrossDissolveTransition : public Transition {
|
||||
public:
|
||||
CrossDissolveTransition(Clip* c, const EffectMeta* em);
|
||||
void process_coords(double timecode, GLTextureCoords &);
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
#include <QtMath>
|
||||
|
||||
ExponentialFadeTransition::ExponentialFadeTransition(Clip* c, const EffectMeta* em) : Effect(c, em) {}
|
||||
ExponentialFadeTransition::ExponentialFadeTransition(Clip* c, const EffectMeta* em) : Transition(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;
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
#ifndef EXPONENTIALFADETRANSITION_H
|
||||
#define EXPONENTIALFADETRANSITION_H
|
||||
|
||||
#include "project/effect.h"
|
||||
#include "project/transition.h"
|
||||
|
||||
class ExponentialFadeTransition : public Effect {
|
||||
class ExponentialFadeTransition : public Transition {
|
||||
public:
|
||||
ExponentialFadeTransition(Clip* c, const EffectMeta* em);
|
||||
void process_audio(double timecode_start, double timecode_end, quint8* samples, int nb_bytes, int channel_count);
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#include "linearfadetransition.h"
|
||||
|
||||
LinearFadeTransition::LinearFadeTransition(Clip* c, const EffectMeta* em) : Effect(c, em) {}
|
||||
LinearFadeTransition::LinearFadeTransition(Clip* c, const EffectMeta* em) : Transition(c, em) {}
|
||||
|
||||
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;
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
#ifndef LINEARFADETRANSITION_H
|
||||
#define LINEARFADETRANSITION_H
|
||||
|
||||
#include "project/effect.h"
|
||||
#include "project/transition.h"
|
||||
|
||||
class LinearFadeTransition : public Effect {
|
||||
class LinearFadeTransition : public Transition {
|
||||
public:
|
||||
LinearFadeTransition(Clip* c, const EffectMeta* em);
|
||||
void process_audio(double timecode_start, double timecode_end, quint8* samples, int nb_bytes, int channel_count);
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
#include <QtMath>
|
||||
|
||||
LogarithmicFadeTransition::LogarithmicFadeTransition(Clip* c, const EffectMeta* em) : Effect(c, em) {}
|
||||
LogarithmicFadeTransition::LogarithmicFadeTransition(Clip* c, const EffectMeta* em) : Transition(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;
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
#ifndef LOGARITHMICFADETRANSITION_H
|
||||
#define LOGARITHMICFADETRANSITION_H
|
||||
|
||||
#include "project/effect.h"
|
||||
#include "project/transition.h"
|
||||
|
||||
class LogarithmicFadeTransition : public Effect {
|
||||
class LogarithmicFadeTransition : public Transition {
|
||||
public:
|
||||
LogarithmicFadeTransition(Clip* c, const EffectMeta* em);
|
||||
void process_audio(double timecode_start, double timecode_end, quint8* samples, int nb_bytes, int channel_count);
|
||||
|
||||
+2
-2
@@ -6,6 +6,8 @@
|
||||
#include "io/media.h"
|
||||
|
||||
#include "project/sequence.h"
|
||||
#include "project/clip.h"
|
||||
#include "project/undo.h"
|
||||
|
||||
#include "ui/sourcetable.h"
|
||||
#include "ui/viewerwidget.h"
|
||||
@@ -16,8 +18,6 @@
|
||||
#include "panels/viewer.h"
|
||||
#include "panels/timeline.h"
|
||||
|
||||
#include "project/undo.h"
|
||||
|
||||
#include "dialogs/aboutdialog.h"
|
||||
#include "dialogs/newsequencedialog.h"
|
||||
#include "dialogs/exportdialog.h"
|
||||
|
||||
@@ -84,7 +84,10 @@ SOURCES += \
|
||||
effects/internal/cornerpineffect.cpp \
|
||||
io/math.cpp \
|
||||
io/qpainterwrapper.cpp \
|
||||
project/effect.cpp
|
||||
project/effect.cpp \
|
||||
project/transition.cpp \
|
||||
project/effectrow.cpp \
|
||||
project/effectfield.cpp
|
||||
|
||||
HEADERS += \
|
||||
mainwindow.h \
|
||||
@@ -148,7 +151,10 @@ HEADERS += \
|
||||
effects/internal/cornerpineffect.h \
|
||||
io/math.h \
|
||||
io/qpainterwrapper.h \
|
||||
project/effect.h
|
||||
project/effect.h \
|
||||
project/transition.h \
|
||||
project/effectrow.h \
|
||||
project/effectfield.h
|
||||
|
||||
FORMS += \
|
||||
mainwindow.ui \
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
#include "panels/panels.h"
|
||||
#include "project/effect.h"
|
||||
#include "project/clip.h"
|
||||
#include "project/transition.h"
|
||||
#include "ui/collapsiblewidget.h"
|
||||
#include "project/sequence.h"
|
||||
#include "project/undo.h"
|
||||
@@ -65,10 +66,10 @@ void EffectControls::menu_select(QAction* q) {
|
||||
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) {
|
||||
if (c->get_opening_transition() == NULL) {
|
||||
ca->append(new AddTransitionCommand(c, meta, TA_OPENING_TRANSITION, 30));
|
||||
}
|
||||
if (c->closing_transition == NULL) {
|
||||
if (c->get_closing_transition() == NULL) {
|
||||
ca->append(new AddTransitionCommand(c, meta, TA_CLOSING_TRANSITION, 30));
|
||||
}
|
||||
} else {
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
#include "effectcontrols.h"
|
||||
#include "viewer.h"
|
||||
#include "project/sequence.h"
|
||||
#include "project/clip.h"
|
||||
|
||||
Project* panel_project = 0;
|
||||
EffectControls* panel_effect_controls = 0;
|
||||
|
||||
+28
-18
@@ -7,8 +7,10 @@
|
||||
#include "panels/viewer.h"
|
||||
#include "playback/playback.h"
|
||||
#include "project/effect.h"
|
||||
#include "project/transition.h"
|
||||
#include "panels/timeline.h"
|
||||
#include "project/sequence.h"
|
||||
#include "project/clip.h"
|
||||
#include "io/previewgenerator.h"
|
||||
#include "project/undo.h"
|
||||
#include "mainwindow.h"
|
||||
@@ -1073,8 +1075,8 @@ bool Project::load_worker(QFile& f, QXmlStreamReader& stream, int type) {
|
||||
} 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;
|
||||
bool effect_enabled = true;
|
||||
long effect_length = -1;
|
||||
for (int j=0;j<stream.attributes().size();j++) {
|
||||
const QXmlStreamAttribute& attr = stream.attributes().at(j);
|
||||
if (attr.name() == "id") {
|
||||
@@ -1083,9 +1085,9 @@ bool Project::load_worker(QFile& f, QXmlStreamReader& stream, int type) {
|
||||
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();
|
||||
}
|
||||
} else if (attr.name() == "length") {
|
||||
effect_length = attr.value().toLong();
|
||||
}
|
||||
}
|
||||
|
||||
// backwards compatibility with 180820
|
||||
@@ -1127,18 +1129,26 @@ bool Project::load_worker(QFile& f, QXmlStreamReader& stream, int type) {
|
||||
if (meta == NULL) {
|
||||
dout << "[WARNING] An effect used by this project is missing. It was not loaded.";
|
||||
} else {
|
||||
QString tag = stream.name().toString();
|
||||
QString tag = stream.name().toString();
|
||||
|
||||
Effect* e = create_effect(c, meta);
|
||||
if (effect_length > -1) e->length = effect_length;
|
||||
e->set_enabled(effect_enabled);
|
||||
e->load(stream);
|
||||
if (tag == "opening" || tag == "closing") {
|
||||
int transition_index = create_transition(c, meta);
|
||||
Transition* t = c->sequence->transitions.at(transition_index);
|
||||
if (effect_length > -1) t->length = effect_length;
|
||||
t->set_enabled(effect_enabled);
|
||||
t->load(stream);
|
||||
|
||||
if (tag == "opening") {
|
||||
c->opening_transition = e;
|
||||
} else if (tag == "closing") {
|
||||
c->closing_transition = e;
|
||||
if (tag == "opening") {
|
||||
c->opening_transition = transition_index;
|
||||
} else {
|
||||
c->closing_transition = transition_index;
|
||||
}
|
||||
} else {
|
||||
Effect* e = create_effect(c, meta);
|
||||
if (effect_length > -1) e->length = effect_length;
|
||||
e->set_enabled(effect_enabled);
|
||||
e->load(stream);
|
||||
|
||||
c->effects.append(e);
|
||||
}
|
||||
}
|
||||
@@ -1449,15 +1459,15 @@ void Project::save_folder(QXmlStreamWriter& stream, QTreeWidgetItem* parent, int
|
||||
stream.writeEndElement(); // effect
|
||||
}
|
||||
|
||||
if (c->opening_transition != NULL) {
|
||||
if (c->get_opening_transition() != NULL) {
|
||||
stream.writeStartElement("opening");
|
||||
c->opening_transition->save(stream);
|
||||
c->get_opening_transition()->save(stream);
|
||||
stream.writeEndElement(); // opening
|
||||
}
|
||||
|
||||
if (c->closing_transition != NULL) {
|
||||
if (c->get_closing_transition() != NULL) {
|
||||
stream.writeStartElement("closing"); // closing
|
||||
c->closing_transition->save(stream);
|
||||
c->get_closing_transition()->save(stream);
|
||||
stream.writeEndElement(); // closing
|
||||
}
|
||||
|
||||
|
||||
+31
-29
@@ -16,6 +16,7 @@
|
||||
#include "project/undo.h"
|
||||
#include "io/config.h"
|
||||
#include "project/effect.h"
|
||||
#include "project/transition.h"
|
||||
#include "io/media.h"
|
||||
#include "debug.h"
|
||||
|
||||
@@ -353,12 +354,12 @@ void Timeline::add_transition() {
|
||||
for (int i=0;i<sequence->clips.size();i++) {
|
||||
Clip* c = sequence->clips.at(i);
|
||||
if (c != NULL && is_clip_selected(c, true)) {
|
||||
if (c->opening_transition == NULL) {
|
||||
ca->append(new AddTransitionCommand(c, get_internal_meta(EFFECT_INTERNAL_LINEARFADE), TA_OPENING_TRANSITION, 30));
|
||||
if (c->get_opening_transition() == NULL) {
|
||||
ca->append(new AddTransitionCommand(c, get_internal_meta(TRANSITION_INTERNAL_LINEARFADE), TA_OPENING_TRANSITION, 30));
|
||||
adding = true;
|
||||
}
|
||||
if (c->closing_transition == NULL) {
|
||||
ca->append(new AddTransitionCommand(c, get_internal_meta(EFFECT_INTERNAL_LINEARFADE), TA_OPENING_TRANSITION, 30));
|
||||
if (c->get_closing_transition() == NULL) {
|
||||
ca->append(new AddTransitionCommand(c, get_internal_meta(TRANSITION_INTERNAL_LINEARFADE), TA_OPENING_TRANSITION, 30));
|
||||
adding = true;
|
||||
}
|
||||
}
|
||||
@@ -605,18 +606,17 @@ Clip* Timeline::split_clip(ComboAction* ca, int p, long frame, long post_in) {
|
||||
|
||||
ca->append(new MoveClipAction(pre, pre->timeline_in, frame, pre->clip_in, pre->track));
|
||||
|
||||
if (pre->opening_transition != NULL) {
|
||||
if (pre->opening_transition->length > new_clip_length) {
|
||||
if (pre->get_opening_transition() != NULL) {
|
||||
if (pre->get_opening_transition()->length > new_clip_length) {
|
||||
ca->append(new ModifyTransitionCommand(pre, TA_OPENING_TRANSITION, new_clip_length));
|
||||
}
|
||||
|
||||
delete post->opening_transition;
|
||||
post->opening_transition = NULL;
|
||||
post->sequence->hard_delete_transition(post, TA_OPENING_TRANSITION);
|
||||
}
|
||||
if (pre->closing_transition != NULL) {
|
||||
if (pre->get_closing_transition() != NULL) {
|
||||
ca->append(new DeleteTransitionCommand(pre, TA_CLOSING_TRANSITION));
|
||||
|
||||
post->closing_transition->length = qMin((long) post->closing_transition->length, post->getLength());
|
||||
post->get_closing_transition()->length = qMin((long) post->get_closing_transition()->length, post->getLength());
|
||||
}
|
||||
|
||||
return post;
|
||||
@@ -724,10 +724,14 @@ void Timeline::delete_areas_and_relink(ComboAction* ca, QVector<Selection>& area
|
||||
for (int j=0;j<sequence->clips.size();j++) {
|
||||
Clip* c = sequence->clips.at(j);
|
||||
if (c != NULL && c->track == s.track && !c->undeletable) {
|
||||
if (c->opening_transition != NULL && s.in == c->timeline_in && s.out == c->timeline_in + c->opening_transition->length) {
|
||||
if (c->get_opening_transition() != NULL
|
||||
&& s.in == c->timeline_in
|
||||
&& s.out == c->timeline_in + c->get_opening_transition()->length) {
|
||||
// delete opening transition
|
||||
ca->append(new DeleteTransitionCommand(c, TA_OPENING_TRANSITION));
|
||||
} else if (c->closing_transition != NULL && s.out == c->timeline_out && s.in == c->timeline_out - c->closing_transition->length) {
|
||||
} else if (c->get_closing_transition() != NULL
|
||||
&& s.out == c->timeline_out
|
||||
&& s.in == c->timeline_out - c->get_closing_transition()->length) {
|
||||
// delete closing transition
|
||||
ca->append(new DeleteTransitionCommand(c, TA_CLOSING_TRANSITION));
|
||||
} else if (c->timeline_in >= s.in && c->timeline_out <= s.out) {
|
||||
@@ -745,22 +749,22 @@ void Timeline::delete_areas_and_relink(ComboAction* ca, QVector<Selection>& area
|
||||
// only out point is in deletion area
|
||||
ca->append(new MoveClipAction(c, c->timeline_in, s.in, c->clip_in, c->track));
|
||||
|
||||
if (c->closing_transition != NULL) {
|
||||
if (s.in < c->timeline_out - c->closing_transition->length) {
|
||||
if (c->get_closing_transition() != NULL) {
|
||||
if (s.in < c->timeline_out - c->get_closing_transition()->length) {
|
||||
ca->append(new DeleteTransitionCommand(c, TA_CLOSING_TRANSITION));
|
||||
} else {
|
||||
ca->append(new ModifyTransitionCommand(c, TA_CLOSING_TRANSITION, c->closing_transition->length - (c->timeline_out - s.in)));
|
||||
ca->append(new ModifyTransitionCommand(c, TA_CLOSING_TRANSITION, c->get_closing_transition()->length - (c->timeline_out - s.in)));
|
||||
}
|
||||
}
|
||||
} else if (c->timeline_in < s.out && c->timeline_out > s.out) {
|
||||
// only in point is in deletion area
|
||||
ca->append(new MoveClipAction(c, s.out, c->timeline_out, c->clip_in + (s.out - c->timeline_in), c->track));
|
||||
|
||||
if (c->opening_transition != NULL) {
|
||||
if (s.out > c->timeline_in + c->opening_transition->length) {
|
||||
if (c->get_opening_transition() != NULL) {
|
||||
if (s.out > c->timeline_in + c->get_opening_transition()->length) {
|
||||
ca->append(new DeleteTransitionCommand(c, TA_OPENING_TRANSITION));
|
||||
} else {
|
||||
ca->append(new ModifyTransitionCommand(c, TA_OPENING_TRANSITION, c->opening_transition->length - (s.out - c->timeline_in)));
|
||||
ca->append(new ModifyTransitionCommand(c, TA_OPENING_TRANSITION, c->get_opening_transition()->length - (s.out - c->timeline_in)));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1015,19 +1019,15 @@ bool Timeline::split_selection(ComboAction* ca) {
|
||||
split_B->timeline_in = s.out;
|
||||
secondary_post_splits.append(split_B);
|
||||
|
||||
if (clip->opening_transition != NULL) {
|
||||
delete split_B->opening_transition;
|
||||
split_B->opening_transition = NULL;
|
||||
|
||||
delete split_A->opening_transition;
|
||||
split_A->opening_transition = NULL;
|
||||
if (clip->get_opening_transition() != NULL) {
|
||||
split_B->sequence->hard_delete_transition(split_B, TA_OPENING_TRANSITION);
|
||||
split_A->sequence->hard_delete_transition(split_A, TA_OPENING_TRANSITION);
|
||||
}
|
||||
|
||||
if (clip->closing_transition != NULL) {
|
||||
if (clip->get_closing_transition() != NULL) {
|
||||
ca->append(new DeleteTransitionCommand(clip, TA_CLOSING_TRANSITION));
|
||||
|
||||
delete split_A->closing_transition;
|
||||
split_A->closing_transition = NULL;
|
||||
split_A->sequence->hard_delete_transition(split_A, TA_CLOSING_TRANSITION);
|
||||
}
|
||||
|
||||
ca->append(new MoveClipAction(clip, clip->timeline_in, s.in, clip->clip_in, clip->track));
|
||||
@@ -1195,9 +1195,11 @@ bool Timeline::snap_to_timeline(long* l, bool use_playhead, bool use_markers, bo
|
||||
return true;
|
||||
} else if (snap_to_point(c->timeline_out, l)) {
|
||||
return true;
|
||||
} else if (c->opening_transition != NULL && snap_to_point(c->timeline_in + c->opening_transition->length, l)) {
|
||||
} else if (c->get_opening_transition() != NULL
|
||||
&& snap_to_point(c->timeline_in + c->get_opening_transition()->length, l)) {
|
||||
return true;
|
||||
} else if (c->closing_transition != NULL && snap_to_point(c->timeline_out - c->closing_transition->length, l)) {
|
||||
} else if (c->get_closing_transition() != NULL
|
||||
&& snap_to_point(c->timeline_out - c->get_closing_transition()->length, l)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
+2
-1
@@ -22,6 +22,7 @@ class SourceTable;
|
||||
class ViewerWidget;
|
||||
class ComboAction;
|
||||
class Effect;
|
||||
class Transition;
|
||||
struct EffectMeta;
|
||||
struct Sequence;
|
||||
struct Clip;
|
||||
@@ -57,7 +58,7 @@ struct Ghost {
|
||||
bool trimming;
|
||||
|
||||
// transition trimming
|
||||
Effect* transition;
|
||||
Transition* transition;
|
||||
};
|
||||
|
||||
namespace Ui {
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
#include "timeline.h"
|
||||
#include "panels/project.h"
|
||||
#include "project/sequence.h"
|
||||
#include "project/clip.h"
|
||||
#include "panels/panels.h"
|
||||
#include "io/config.h"
|
||||
#include "io/media.h"
|
||||
|
||||
+9
-8
@@ -2,6 +2,7 @@
|
||||
|
||||
#include "project/clip.h"
|
||||
#include "project/sequence.h"
|
||||
#include "project/transition.h"
|
||||
#include "io/media.h"
|
||||
#include "playback/audio.h"
|
||||
#include "playback/playback.h"
|
||||
@@ -47,27 +48,27 @@ void apply_audio_effects(Clip* c, double timecode_start, AVFrame* frame, int nb_
|
||||
Effect* e = c->effects.at(j);
|
||||
if (e->is_enabled()) e->process_audio(timecode_start, timecode_end, frame->data[0], nb_bytes, 2);
|
||||
}
|
||||
if (c->opening_transition != NULL) {
|
||||
if (c->media_type == MEDIA_TYPE_FOOTAGE) {
|
||||
if (c->get_opening_transition() != NULL) {
|
||||
if (c->media_type == MEDIA_TYPE_FOOTAGE) {
|
||||
double transition_start = (c->clip_in / c->sequence->frame_rate);
|
||||
double transition_end = ((c->clip_in + c->opening_transition->length) / c->sequence->frame_rate);
|
||||
double transition_end = (c->clip_in + c->get_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, TRAN_TYPE_OPEN);
|
||||
c->get_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;
|
||||
if (c->get_closing_transition() != NULL) {
|
||||
if (c->media_type == MEDIA_TYPE_FOOTAGE) {
|
||||
double transition_start = (c->clip_in + c->getLength() - c->get_closing_transition()->length) / c->sequence->frame_rate;
|
||||
double transition_end = (c->clip_in + c->getLength()) / 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, TRAN_TYPE_CLOSE);
|
||||
c->get_closing_transition()->process_audio(adjusted_range_start, adjusted_range_end, frame->data[0], nb_bytes, TRAN_TYPE_CLOSE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+29
-12
@@ -1,6 +1,7 @@
|
||||
#include "clip.h"
|
||||
|
||||
#include "project/effect.h"
|
||||
#include "project/transition.h"
|
||||
#include "io/media.h"
|
||||
#include "io/config.h"
|
||||
#include "playback/playback.h"
|
||||
@@ -26,8 +27,8 @@ Clip::Clip(Sequence* s) :
|
||||
reverse(false),
|
||||
maintain_audio_pitch(false),
|
||||
autoscale(config.autoscale_by_default),
|
||||
opening_transition(NULL),
|
||||
closing_transition(NULL),
|
||||
opening_transition(-1),
|
||||
closing_transition(-1),
|
||||
undeletable(false),
|
||||
replaced(false),
|
||||
ignore_reverse(false),
|
||||
@@ -64,8 +65,8 @@ Clip* Clip::copy(Sequence* s) {
|
||||
copy->effects.append(effects.at(i)->copy(copy));
|
||||
}
|
||||
|
||||
if (opening_transition != NULL) copy->opening_transition = opening_transition->copy(copy);
|
||||
if (closing_transition != NULL) copy->closing_transition = closing_transition->copy(copy);
|
||||
if (opening_transition != -1) copy->opening_transition = this->sequence->transitions.at(opening_transition)->copy(copy);
|
||||
if (closing_transition != -1) copy->closing_transition = this->sequence->transitions.at(closing_transition)->copy(copy);
|
||||
|
||||
copy->recalculateMaxLength();
|
||||
|
||||
@@ -140,7 +141,21 @@ void Clip::queue_remove_earliest() {
|
||||
}
|
||||
}
|
||||
av_frame_free(&queue[earliest_frame]);
|
||||
queue.removeAt(earliest_frame);
|
||||
queue.removeAt(earliest_frame);
|
||||
}
|
||||
|
||||
Transition* Clip::get_opening_transition() {
|
||||
if (opening_transition > -1) {
|
||||
return this->sequence->transitions.at(opening_transition);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Transition* Clip::get_closing_transition() {
|
||||
if (closing_transition > -1) {
|
||||
return this->sequence->transitions.at(closing_transition);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Clip::~Clip() {
|
||||
@@ -153,8 +168,8 @@ Clip::~Clip() {
|
||||
}
|
||||
}
|
||||
|
||||
if (opening_transition != NULL) delete opening_transition;
|
||||
if (closing_transition != NULL) delete closing_transition;
|
||||
//if (opening_transition != -1) this->sequence->hard_delete_transition(this, TA_OPENING_TRANSITION);
|
||||
//if (closing_transition != -1) this->sequence->hard_delete_transition(this, TA_CLOSING_TRANSITION);
|
||||
|
||||
for (int i=0;i<effects.size();i++) {
|
||||
delete effects.at(i);
|
||||
@@ -163,19 +178,21 @@ Clip::~Clip() {
|
||||
}
|
||||
|
||||
long Clip::get_timeline_in_with_transition() {
|
||||
if (opening_transition != NULL && opening_transition->tlink != NULL) {
|
||||
return timeline_in - opening_transition->tlink->length;
|
||||
/*if (opening_transition != NULL && opening_transition->tlink != NULL) {
|
||||
return timeline_in - this->sequence->transitions(opening_transition)->tlink->length;
|
||||
} else {
|
||||
return timeline_in;
|
||||
}
|
||||
}*/
|
||||
return 0;
|
||||
}
|
||||
|
||||
long Clip::get_timeline_out_with_transition() {
|
||||
if (closing_transition != NULL && closing_transition->tlink != NULL) {
|
||||
/*if (closing_transition != NULL && closing_transition->tlink != NULL) {
|
||||
return timeline_out + closing_transition->tlink->length;
|
||||
} else {
|
||||
return timeline_out;
|
||||
}
|
||||
}*/
|
||||
return 0;
|
||||
}
|
||||
|
||||
// timeline functions
|
||||
|
||||
+5
-2
@@ -10,6 +10,7 @@
|
||||
|
||||
class Cacher;
|
||||
class Effect;
|
||||
class Transition;
|
||||
class QOpenGLFramebufferObject;
|
||||
class ComboAction;
|
||||
struct Sequence;
|
||||
@@ -72,8 +73,10 @@ struct Clip
|
||||
// other variables (should be deep copied/duplicated in copy())
|
||||
QList<Effect*> effects;
|
||||
QVector<int> linked;
|
||||
Effect* opening_transition;
|
||||
Effect* closing_transition;
|
||||
int opening_transition;
|
||||
Transition* get_opening_transition();
|
||||
int closing_transition;
|
||||
Transition* get_closing_transition();
|
||||
|
||||
// media handling
|
||||
AVFormatContext* formatCtx;
|
||||
|
||||
+10
-556
@@ -7,19 +7,15 @@
|
||||
#include "panels/project.h"
|
||||
#include "project/undo.h"
|
||||
#include "project/sequence.h"
|
||||
#include "ui/labelslider.h"
|
||||
#include "ui/colorbutton.h"
|
||||
#include "ui/comboboxex.h"
|
||||
#include "ui/fontcombobox.h"
|
||||
#include "ui/checkboxex.h"
|
||||
#include "ui/texteditex.h"
|
||||
#include "project/clip.h"
|
||||
#include "panels/timeline.h"
|
||||
#include "panels/effectcontrols.h"
|
||||
#include "ui/checkboxex.h"
|
||||
#include "debug.h"
|
||||
#include "io/path.h"
|
||||
#include "mainwindow.h"
|
||||
#include "io/math.h"
|
||||
#include "transition.h"
|
||||
|
||||
#include "effects/internal/transformeffect.h"
|
||||
#include "effects/internal/texteffect.h"
|
||||
@@ -29,10 +25,6 @@
|
||||
#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 "effects/internal/cornerpineffect.h"
|
||||
|
||||
#include <QCheckBox>
|
||||
@@ -64,11 +56,7 @@ Effect* create_effect(Clip* c, const EffectMeta* 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);
|
||||
case EFFECT_INTERNAL_SHAKE: return new ShakeEffect(c, em);
|
||||
case EFFECT_INTERNAL_CORNERPIN: return new CornerPinEffect(c, em);
|
||||
}
|
||||
} else {
|
||||
@@ -144,19 +132,19 @@ void load_internal_effects() {
|
||||
em.category = "";
|
||||
|
||||
em.name = "Cross Dissolve";
|
||||
em.internal = EFFECT_INTERNAL_CROSSDISSOLVE;
|
||||
em.internal = TRANSITION_INTERNAL_CROSSDISSOLVE;
|
||||
video_effects.append(em);
|
||||
|
||||
em.name = "Linear Fade";
|
||||
em.internal = EFFECT_INTERNAL_LINEARFADE;
|
||||
em.internal = TRANSITION_INTERNAL_LINEARFADE;
|
||||
audio_effects.append(em);
|
||||
|
||||
em.name = "Exponential Fade";
|
||||
em.internal = EFFECT_INTERNAL_EXPONENTIALFADE;
|
||||
em.internal = TRANSITION_INTERNAL_EXPONENTIALFADE;
|
||||
audio_effects.append(em);
|
||||
|
||||
em.name = "Logarithmic Fade";
|
||||
em.internal = EFFECT_INTERNAL_LOGARITHMICFADE;
|
||||
em.internal = TRANSITION_INTERNAL_LOGARITHMICFADE;
|
||||
audio_effects.append(em);
|
||||
}
|
||||
|
||||
@@ -233,7 +221,6 @@ Effect::Effect(Clip* c, const EffectMeta *em) :
|
||||
parent_clip(c),
|
||||
meta(em),
|
||||
length(30),
|
||||
tlink(NULL),
|
||||
enable_shader(false),
|
||||
enable_coords(false),
|
||||
enable_superimpose(false),
|
||||
@@ -257,10 +244,6 @@ Effect::Effect(Clip* c, const EffectMeta *em) :
|
||||
// set up UI from effect file
|
||||
container->setText(em->name);
|
||||
|
||||
if (em->type == EFFECT_TYPE_TRANSITION) {
|
||||
add_row("Length:")->add_field(EFFECT_FIELD_DOUBLE);
|
||||
}
|
||||
|
||||
if (!em->filename.isEmpty()) {
|
||||
QFile effect_file(get_effects_dir() + "/" + em->filename);
|
||||
if (effect_file.open(QFile::ReadOnly)) {
|
||||
@@ -682,8 +665,8 @@ 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));
|
||||
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);
|
||||
@@ -762,8 +745,7 @@ void Effect::endEffect() {
|
||||
|
||||
Effect* Effect::copy(Clip* c) {
|
||||
Effect* copy = create_effect(c, meta);
|
||||
copy->set_enabled(is_enabled());
|
||||
copy->length = length;
|
||||
copy->set_enabled(is_enabled());
|
||||
copy_field_keyframes(copy);
|
||||
return copy;
|
||||
}
|
||||
@@ -929,534 +911,6 @@ void Effect::delete_texture() {
|
||||
}
|
||||
}
|
||||
|
||||
/* Effect Row Definitions */
|
||||
|
||||
EffectRow::EffectRow(Effect *parent, QGridLayout *uilayout, const QString &n, int row) :
|
||||
parent_effect(parent),
|
||||
keyframing(false),
|
||||
ui(uilayout),
|
||||
name(n),
|
||||
ui_row(row),
|
||||
just_made_unsafe_keyframe(false)
|
||||
{
|
||||
label = new QLabel(name);
|
||||
ui->addWidget(label, row, 0);
|
||||
|
||||
QSize button_size(20, 20);
|
||||
QSize icon_size(12, 12);
|
||||
|
||||
QHBoxLayout* key_controls = new QHBoxLayout();
|
||||
key_controls->setSpacing(0);
|
||||
key_controls->setMargin(0);
|
||||
key_controls->addStretch();
|
||||
|
||||
left_key_nav = new QPushButton("<");
|
||||
left_key_nav->setVisible(false);
|
||||
left_key_nav->setMaximumSize(button_size);
|
||||
key_controls->addWidget(left_key_nav);
|
||||
connect(left_key_nav, SIGNAL(clicked(bool)), this, SLOT(goto_previous_key()));
|
||||
|
||||
key_addremove = new QPushButton(".");
|
||||
key_addremove->setVisible(false);
|
||||
key_addremove->setMaximumSize(button_size);
|
||||
key_controls->addWidget(key_addremove);
|
||||
connect(key_addremove, SIGNAL(clicked(bool)), this, SLOT(toggle_key()));
|
||||
|
||||
right_key_nav = new QPushButton(">");
|
||||
right_key_nav->setVisible(false);
|
||||
right_key_nav->setMaximumSize(button_size);
|
||||
key_controls->addWidget(right_key_nav);
|
||||
connect(right_key_nav, SIGNAL(clicked(bool)), this, SLOT(goto_next_key()));
|
||||
|
||||
keyframe_enable = new QPushButton(QIcon(":/icons/clock.png"), "");
|
||||
keyframe_enable->setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Fixed);
|
||||
keyframe_enable->setMaximumSize(button_size);
|
||||
keyframe_enable->setIconSize(icon_size);
|
||||
keyframe_enable->setCheckable(true);
|
||||
keyframe_enable->setToolTip("Enable Keyframes");
|
||||
connect(keyframe_enable, SIGNAL(clicked(bool)), this, SLOT(set_keyframe_enabled(bool)));
|
||||
connect(keyframe_enable, SIGNAL(toggled(bool)), this, SLOT(keyframe_ui_enabled(bool)));
|
||||
key_controls->addWidget(keyframe_enable);
|
||||
|
||||
ui->addLayout(key_controls, row, 6);
|
||||
}
|
||||
|
||||
bool EffectRow::isKeyframing() {
|
||||
return keyframing;
|
||||
}
|
||||
|
||||
void EffectRow::setKeyframing(bool b) {
|
||||
keyframing = b;
|
||||
keyframe_enable->setChecked(b);
|
||||
}
|
||||
|
||||
void EffectRow::set_keyframe_enabled(bool enabled) {
|
||||
if (enabled) {
|
||||
set_keyframe_now(true);
|
||||
} else {
|
||||
if (QMessageBox::question(panel_effect_controls, "Disable Keyframes", "Disabling keyframes will delete all current keyframes. Are you sure you want to do this?", QMessageBox::Yes, QMessageBox::No) == QMessageBox::Yes) {
|
||||
// clear
|
||||
KeyframeDelete* kd = new KeyframeDelete();
|
||||
for (int i=keyframe_times.size()-1;i>=0;i--) {
|
||||
delete_keyframe(kd, i);
|
||||
}
|
||||
kd->disable_keyframes_on_row = this;
|
||||
undo_stack.push(kd);
|
||||
panel_effect_controls->update_keyframes();
|
||||
} else {
|
||||
setKeyframing(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void EffectRow::keyframe_ui_enabled(bool enabled) {
|
||||
left_key_nav->setVisible(enabled);
|
||||
key_addremove->setVisible(enabled);
|
||||
right_key_nav->setVisible(enabled);
|
||||
}
|
||||
|
||||
void EffectRow::goto_previous_key() {
|
||||
long key = LONG_MIN;
|
||||
Clip* c = parent_effect->parent_clip;
|
||||
for (int i=0;i<keyframe_times.size();i++) {
|
||||
long comp = keyframe_times.at(i) - c->clip_in + c->timeline_in;
|
||||
if (comp < sequence->playhead) {
|
||||
key = qMax(comp, key);
|
||||
}
|
||||
}
|
||||
if (key != LONG_MIN) panel_sequence_viewer->seek(key);
|
||||
}
|
||||
|
||||
void EffectRow::toggle_key() {
|
||||
int index = -1;
|
||||
Clip* c = parent_effect->parent_clip;
|
||||
for (int i=0;i<keyframe_times.size();i++) {
|
||||
long comp = c->timeline_in - c->clip_in + keyframe_times.at(i);
|
||||
if (comp == sequence->playhead) {
|
||||
index = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (index < 0) {
|
||||
// keyframe doesn't exist, set one
|
||||
set_keyframe_now(true);
|
||||
} else {
|
||||
KeyframeDelete* kd = new KeyframeDelete();
|
||||
delete_keyframe(kd, index);
|
||||
undo_stack.push(kd);
|
||||
panel_effect_controls->update_keyframes();
|
||||
panel_sequence_viewer->viewer_widget->update();
|
||||
}
|
||||
}
|
||||
|
||||
void EffectRow::goto_next_key() {
|
||||
long key = LONG_MAX;
|
||||
Clip* c = parent_effect->parent_clip;
|
||||
for (int i=0;i<keyframe_times.size();i++) {
|
||||
long comp = c->timeline_in - c->clip_in + keyframe_times.at(i);
|
||||
if (comp > sequence->playhead) {
|
||||
key = qMin(comp, key);
|
||||
}
|
||||
}
|
||||
if (key != LONG_MAX) panel_sequence_viewer->seek(key);
|
||||
}
|
||||
|
||||
EffectField* EffectRow::add_field(int type, int colspan) {
|
||||
EffectField* field = new EffectField(this, type);
|
||||
fields.append(field);
|
||||
QWidget* element = field->get_ui_element();
|
||||
ui->addWidget(element, ui_row, fields.size(), 1, colspan);
|
||||
return field;
|
||||
}
|
||||
|
||||
EffectRow::~EffectRow() {
|
||||
for (int i=0;i<fields.size();i++) {
|
||||
delete fields.at(i);
|
||||
}
|
||||
}
|
||||
|
||||
void EffectRow::set_keyframe_now(bool undoable) {
|
||||
int index = -1;
|
||||
long time = sequence->playhead-parent_effect->parent_clip->timeline_in+parent_effect->parent_clip->clip_in;
|
||||
for (int i=0;i<keyframe_times.size();i++) {
|
||||
if (keyframe_times.at(i) == time) {
|
||||
index = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
KeyframeSet* ks = new KeyframeSet(this, index, time, just_made_unsafe_keyframe);
|
||||
|
||||
if (undoable) {
|
||||
just_made_unsafe_keyframe = false;
|
||||
undo_stack.push(ks);
|
||||
} else {
|
||||
if (index == -1) just_made_unsafe_keyframe = true;
|
||||
ks->redo();
|
||||
delete ks;
|
||||
}
|
||||
|
||||
panel_effect_controls->update_keyframes();
|
||||
}
|
||||
|
||||
void EffectRow::delete_keyframe_at_time(KeyframeDelete* kd, long time) {
|
||||
for (int i=0;i<keyframe_times.size();i++) {
|
||||
if (keyframe_times.at(i) == time) {
|
||||
delete_keyframe(kd, i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void EffectRow::delete_keyframe(KeyframeDelete* kd, int index) {
|
||||
kd->rows.append(this);
|
||||
kd->keyframes.append(index);
|
||||
}
|
||||
|
||||
EffectField* EffectRow::field(int i) {
|
||||
return fields.at(i);
|
||||
}
|
||||
|
||||
int EffectRow::fieldCount() {
|
||||
return fields.size();
|
||||
}
|
||||
|
||||
/* Effect Field Definitions */
|
||||
|
||||
EffectField::EffectField(EffectRow *parent, int t) : parent_row(parent), type(t) {
|
||||
switch (t) {
|
||||
case EFFECT_FIELD_DOUBLE:
|
||||
{
|
||||
LabelSlider* ls = new LabelSlider();
|
||||
ui_element = ls;
|
||||
connect(ls, SIGNAL(valueChanged()), this, SLOT(uiElementChange()));
|
||||
}
|
||||
break;
|
||||
case EFFECT_FIELD_COLOR:
|
||||
{
|
||||
ColorButton* cb = new ColorButton();
|
||||
ui_element = cb;
|
||||
connect(cb, SIGNAL(color_changed()), this, SLOT(uiElementChange()));
|
||||
}
|
||||
break;
|
||||
case EFFECT_FIELD_STRING:
|
||||
{
|
||||
TextEditEx* edit = new TextEditEx();
|
||||
edit->setUndoRedoEnabled(true);
|
||||
ui_element = edit;
|
||||
connect(edit, SIGNAL(textChanged()), this, SLOT(uiElementChange()));
|
||||
}
|
||||
break;
|
||||
case EFFECT_FIELD_BOOL:
|
||||
{
|
||||
CheckboxEx* cb = new CheckboxEx();
|
||||
ui_element = cb;
|
||||
connect(cb, SIGNAL(clicked(bool)), this, SLOT(uiElementChange()));
|
||||
connect(cb, SIGNAL(toggled(bool)), this, SIGNAL(toggled(bool)));
|
||||
}
|
||||
break;
|
||||
case EFFECT_FIELD_COMBO:
|
||||
{
|
||||
ComboBoxEx* cb = new ComboBoxEx();
|
||||
ui_element = cb;
|
||||
connect(cb, SIGNAL(activated(int)), this, SLOT(uiElementChange()));
|
||||
}
|
||||
break;
|
||||
case EFFECT_FIELD_FONT:
|
||||
{
|
||||
FontCombobox* fcb = new FontCombobox();
|
||||
ui_element = fcb;
|
||||
connect(fcb, SIGNAL(activated(int)), this, SLOT(uiElementChange()));
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
QVariant EffectField::get_previous_data() {
|
||||
switch (type) {
|
||||
case EFFECT_FIELD_DOUBLE: return static_cast<LabelSlider*>(ui_element)->getPreviousValue(); break;
|
||||
case EFFECT_FIELD_COLOR: return static_cast<ColorButton*>(ui_element)->getPreviousValue(); break;
|
||||
case EFFECT_FIELD_STRING: return static_cast<TextEditEx*>(ui_element)->getPreviousValue(); break;
|
||||
case EFFECT_FIELD_BOOL: return !static_cast<QCheckBox*>(ui_element)->isChecked(); break;
|
||||
case EFFECT_FIELD_COMBO: return static_cast<ComboBoxEx*>(ui_element)->getPreviousIndex(); break;
|
||||
case EFFECT_FIELD_FONT: return static_cast<FontCombobox*>(ui_element)->getPreviousValue(); break;
|
||||
}
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
QVariant EffectField::get_current_data() {
|
||||
switch (type) {
|
||||
case EFFECT_FIELD_DOUBLE: return static_cast<LabelSlider*>(ui_element)->value(); break;
|
||||
case EFFECT_FIELD_COLOR: return static_cast<ColorButton*>(ui_element)->get_color(); break;
|
||||
case EFFECT_FIELD_STRING: return static_cast<TextEditEx*>(ui_element)->getPlainTextEx(); break;
|
||||
case EFFECT_FIELD_BOOL: return static_cast<QCheckBox*>(ui_element)->isChecked(); break;
|
||||
case EFFECT_FIELD_COMBO: return static_cast<ComboBoxEx*>(ui_element)->currentIndex(); break;
|
||||
case EFFECT_FIELD_FONT: return static_cast<FontCombobox*>(ui_element)->currentText(); break;
|
||||
}
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
double EffectField::frameToTimecode(long frame) {
|
||||
return ((double) frame / parent_row->parent_effect->parent_clip->sequence->frame_rate);
|
||||
}
|
||||
|
||||
long EffectField::timecodeToFrame(double timecode) {
|
||||
return qRound(timecode * parent_row->parent_effect->parent_clip->sequence->frame_rate);
|
||||
}
|
||||
|
||||
void EffectField::set_current_data(const QVariant& data) {
|
||||
switch (type) {
|
||||
case EFFECT_FIELD_DOUBLE: return static_cast<LabelSlider*>(ui_element)->set_value(data.toDouble(), false); break;
|
||||
case EFFECT_FIELD_COLOR: return static_cast<ColorButton*>(ui_element)->set_color(data.value<QColor>()); break;
|
||||
case EFFECT_FIELD_STRING: return static_cast<TextEditEx*>(ui_element)->setPlainTextEx(data.toString()); break;
|
||||
case EFFECT_FIELD_BOOL: return static_cast<QCheckBox*>(ui_element)->setChecked(data.toBool()); break;
|
||||
case EFFECT_FIELD_COMBO: return static_cast<ComboBoxEx*>(ui_element)->setCurrentIndexEx(data.toInt()); break;
|
||||
case EFFECT_FIELD_FONT: return static_cast<FontCombobox*>(ui_element)->setCurrentTextEx(data.toString()); break;
|
||||
}
|
||||
}
|
||||
|
||||
void EffectField::get_keyframe_data(double timecode, int &before, int &after, double &progress) {
|
||||
int before_keyframe_index = -1;
|
||||
int after_keyframe_index = -1;
|
||||
long before_keyframe_time = LONG_MIN;
|
||||
long after_keyframe_time = LONG_MAX;
|
||||
long frame = timecodeToFrame(timecode);
|
||||
|
||||
for (int i=0;i<parent_row->keyframe_times.size();i++) {
|
||||
long eval_keyframe_time = parent_row->keyframe_times.at(i);
|
||||
if (eval_keyframe_time == frame) {
|
||||
before = i;
|
||||
after = i;
|
||||
return;
|
||||
} else if (eval_keyframe_time < frame && eval_keyframe_time > before_keyframe_time) {
|
||||
before_keyframe_index = i;
|
||||
before_keyframe_time = eval_keyframe_time;
|
||||
} else if (eval_keyframe_time > frame && eval_keyframe_time < after_keyframe_time) {
|
||||
after_keyframe_index = i;
|
||||
after_keyframe_time = eval_keyframe_time;
|
||||
}
|
||||
}
|
||||
|
||||
if ((type == EFFECT_FIELD_DOUBLE || type == EFFECT_FIELD_COLOR) && (before_keyframe_index > -1 && after_keyframe_index > -1)) {
|
||||
// interpolate
|
||||
before = before_keyframe_index;
|
||||
after = after_keyframe_index;
|
||||
|
||||
progress = (timecode-frameToTimecode(before_keyframe_time))/(frameToTimecode(after_keyframe_time)-frameToTimecode(before_keyframe_time));
|
||||
|
||||
// TODO routines for bezier - currently this is purely linear
|
||||
} else if (before_keyframe_index > -1) {
|
||||
before = before_keyframe_index;
|
||||
after = before_keyframe_index;
|
||||
} else {
|
||||
before = after_keyframe_index;
|
||||
after = after_keyframe_index;
|
||||
}
|
||||
}
|
||||
|
||||
bool EffectField::hasKeyframes() {
|
||||
return (parent_row->isKeyframing() && keyframe_data.size() > 0);
|
||||
}
|
||||
|
||||
QVariant EffectField::validate_keyframe_data(double timecode, bool async) {
|
||||
if (hasKeyframes()) {
|
||||
int before_keyframe;
|
||||
int after_keyframe;
|
||||
double progress;
|
||||
get_keyframe_data(timecode, before_keyframe, after_keyframe, progress);
|
||||
|
||||
int kf_type = (progress < 0.5) ? parent_row->keyframe_types.at(before_keyframe) : parent_row->keyframe_types.at(after_keyframe);
|
||||
if (kf_type == KEYFRAME_TYPE_SMOOTH) {
|
||||
double b = 4;
|
||||
double c = 1.313;
|
||||
double x = (b * progress) - (b*0.5);
|
||||
progress = (c*(qPow(M_E, x)/(qPow(M_E, x) + 1)))-((c-1)*0.5);
|
||||
}
|
||||
|
||||
const QVariant& before_data = keyframe_data.at(before_keyframe);
|
||||
switch (type) {
|
||||
case EFFECT_FIELD_DOUBLE:
|
||||
{
|
||||
double value;
|
||||
if (before_keyframe == after_keyframe) {
|
||||
value = keyframe_data.at(before_keyframe).toDouble();
|
||||
} else {
|
||||
double before_dbl = keyframe_data.at(before_keyframe).toDouble();
|
||||
double after_dbl = keyframe_data.at(after_keyframe).toDouble();
|
||||
value = double_lerp(before_dbl, after_dbl, progress);
|
||||
}
|
||||
if (async) {
|
||||
return value;
|
||||
}
|
||||
static_cast<LabelSlider*>(ui_element)->set_value(value, false);
|
||||
}
|
||||
break;
|
||||
case EFFECT_FIELD_COLOR:
|
||||
{
|
||||
QColor value;
|
||||
if (before_keyframe == after_keyframe) {
|
||||
value = keyframe_data.at(before_keyframe).value<QColor>();
|
||||
} else {
|
||||
QColor before_data = keyframe_data.at(before_keyframe).value<QColor>();
|
||||
QColor after_data = keyframe_data.at(after_keyframe).value<QColor>();
|
||||
value = QColor(lerp(before_data.red(), after_data.red(), progress), lerp(before_data.green(), after_data.green(), progress), lerp(before_data.blue(), after_data.blue(), progress));
|
||||
}
|
||||
if (async) {
|
||||
return value;
|
||||
}
|
||||
static_cast<ColorButton*>(ui_element)->set_color(value);
|
||||
}
|
||||
break;
|
||||
case EFFECT_FIELD_STRING:
|
||||
if (async) {
|
||||
return before_data;
|
||||
}
|
||||
static_cast<TextEditEx*>(ui_element)->setPlainTextEx(before_data.toString());
|
||||
break;
|
||||
case EFFECT_FIELD_BOOL:
|
||||
if (async) {
|
||||
return before_data;
|
||||
}
|
||||
static_cast<QCheckBox*>(ui_element)->setChecked(before_data.toBool());
|
||||
break;
|
||||
case EFFECT_FIELD_COMBO:
|
||||
if (async) {
|
||||
return before_data;
|
||||
}
|
||||
static_cast<ComboBoxEx*>(ui_element)->setCurrentIndexEx(before_data.toInt());
|
||||
break;
|
||||
case EFFECT_FIELD_FONT:
|
||||
if (async) {
|
||||
return before_data;
|
||||
}
|
||||
static_cast<FontCombobox*>(ui_element)->setCurrentTextEx(before_data.toString());
|
||||
break;
|
||||
}
|
||||
}
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
void EffectField::uiElementChange() {
|
||||
bool enableKeyframes = !(type == EFFECT_FIELD_DOUBLE && static_cast<LabelSlider*>(ui_element)->is_dragging());
|
||||
if (parent_row->isKeyframing()) {
|
||||
parent_row->set_keyframe_now(enableKeyframes);
|
||||
} else if (enableKeyframes) {
|
||||
// set undo
|
||||
undo_stack.push(new EffectFieldUndo(this));
|
||||
}
|
||||
emit changed();
|
||||
}
|
||||
|
||||
QWidget* EffectField::get_ui_element() {
|
||||
return ui_element;
|
||||
}
|
||||
|
||||
void EffectField::set_enabled(bool e) {
|
||||
ui_element->setEnabled(e);
|
||||
}
|
||||
|
||||
double EffectField::get_double_value(double timecode, bool async) {
|
||||
if (async && hasKeyframes()) {
|
||||
return validate_keyframe_data(timecode, true).toDouble();
|
||||
}
|
||||
validate_keyframe_data(timecode);
|
||||
return static_cast<LabelSlider*>(ui_element)->value();
|
||||
}
|
||||
|
||||
void EffectField::set_double_value(double v) {
|
||||
static_cast<LabelSlider*>(ui_element)->set_value(v, false);
|
||||
}
|
||||
|
||||
void EffectField::set_double_default_value(double v) {
|
||||
static_cast<LabelSlider*>(ui_element)->set_default_value(v);
|
||||
}
|
||||
|
||||
void EffectField::set_double_minimum_value(double v) {
|
||||
static_cast<LabelSlider*>(ui_element)->set_minimum_value(v);
|
||||
}
|
||||
|
||||
void EffectField::set_double_maximum_value(double v) {
|
||||
static_cast<LabelSlider*>(ui_element)->set_maximum_value(v);
|
||||
}
|
||||
|
||||
void EffectField::add_combo_item(const QString& name, const QVariant& data) {
|
||||
static_cast<ComboBoxEx*>(ui_element)->addItem(name, data);
|
||||
}
|
||||
|
||||
int EffectField::get_combo_index(double timecode, bool async) {
|
||||
if (async && hasKeyframes()) {
|
||||
return validate_keyframe_data(timecode, true).toInt();
|
||||
}
|
||||
validate_keyframe_data(timecode);
|
||||
return static_cast<ComboBoxEx*>(ui_element)->currentIndex();
|
||||
}
|
||||
|
||||
const QVariant EffectField::get_combo_data(double timecode) {
|
||||
validate_keyframe_data(timecode);
|
||||
return static_cast<ComboBoxEx*>(ui_element)->currentData();
|
||||
}
|
||||
|
||||
const QString EffectField::get_combo_string(double timecode) {
|
||||
validate_keyframe_data(timecode);
|
||||
return static_cast<ComboBoxEx*>(ui_element)->currentText();
|
||||
}
|
||||
|
||||
void EffectField::set_combo_index(int index) {
|
||||
static_cast<ComboBoxEx*>(ui_element)->setCurrentIndexEx(index);
|
||||
}
|
||||
|
||||
void EffectField::set_combo_string(const QString& s) {
|
||||
static_cast<ComboBoxEx*>(ui_element)->setCurrentTextEx(s);
|
||||
}
|
||||
|
||||
bool EffectField::get_bool_value(double timecode, bool async) {
|
||||
if (async && hasKeyframes()) {
|
||||
return validate_keyframe_data(timecode, true).toBool();
|
||||
}
|
||||
validate_keyframe_data(timecode);
|
||||
return static_cast<QCheckBox*>(ui_element)->isChecked();
|
||||
}
|
||||
|
||||
void EffectField::set_bool_value(bool b) {
|
||||
return static_cast<QCheckBox*>(ui_element)->setChecked(b);
|
||||
}
|
||||
|
||||
const QString EffectField::get_string_value(double timecode, bool async) {
|
||||
if (async && hasKeyframes()) {
|
||||
return validate_keyframe_data(timecode, true).toString();
|
||||
}
|
||||
validate_keyframe_data(timecode);
|
||||
return static_cast<TextEditEx*>(ui_element)->getPlainTextEx();
|
||||
}
|
||||
|
||||
void EffectField::set_string_value(const QString& s) {
|
||||
static_cast<TextEditEx*>(ui_element)->setPlainTextEx(s);
|
||||
}
|
||||
|
||||
const QString EffectField::get_font_name(double timecode, bool async) {
|
||||
if (async && hasKeyframes()) {
|
||||
return validate_keyframe_data(timecode, true).toString();
|
||||
}
|
||||
validate_keyframe_data(timecode);
|
||||
return static_cast<FontCombobox*>(ui_element)->currentText();
|
||||
}
|
||||
|
||||
void EffectField::set_font_name(const QString& s) {
|
||||
static_cast<FontCombobox*>(ui_element)->setCurrentText(s);
|
||||
}
|
||||
|
||||
QColor EffectField::get_color_value(double timecode, bool async) {
|
||||
if (async && hasKeyframes()) {
|
||||
return validate_keyframe_data(timecode, true).value<QColor>();
|
||||
}
|
||||
validate_keyframe_data(timecode);
|
||||
return static_cast<ColorButton*>(ui_element)->get_color();
|
||||
}
|
||||
|
||||
void EffectField::set_color_value(QColor color) {
|
||||
static_cast<ColorButton*>(ui_element)->set_color(color);
|
||||
}
|
||||
|
||||
qint16 mix_audio_sample(qint16 a, qint16 b) {
|
||||
qint32 mixed_sample = static_cast<qint32>(a) + static_cast<qint32>(b);
|
||||
mixed_sample = qMax(qMin(mixed_sample, static_cast<qint32>(INT16_MAX)), static_cast<qint32>(INT16_MIN));
|
||||
|
||||
+7
-107
@@ -48,13 +48,6 @@ extern QMutex effects_loaded;
|
||||
#define EFFECT_TYPE_EFFECT 3
|
||||
#define EFFECT_TYPE_TRANSITION 4
|
||||
|
||||
#define EFFECT_FIELD_DOUBLE 0
|
||||
#define EFFECT_FIELD_COLOR 1
|
||||
#define EFFECT_FIELD_STRING 2
|
||||
#define EFFECT_FIELD_BOOL 3
|
||||
#define EFFECT_FIELD_COMBO 4
|
||||
#define EFFECT_FIELD_FONT 5
|
||||
|
||||
#define EFFECT_KEYFRAME_LINEAR 0
|
||||
#define EFFECT_KEYFRAME_HOLD 1
|
||||
#define EFFECT_KEYFRAME_BEZIER 2
|
||||
@@ -67,10 +60,10 @@ extern QMutex effects_loaded;
|
||||
#define EFFECT_INTERNAL_PAN 5
|
||||
#define EFFECT_INTERNAL_TONE 6
|
||||
#define EFFECT_INTERNAL_SHAKE 7
|
||||
#define EFFECT_INTERNAL_CROSSDISSOLVE 8
|
||||
#define EFFECT_INTERNAL_LINEARFADE 9
|
||||
#define EFFECT_INTERNAL_EXPONENTIALFADE 10
|
||||
#define EFFECT_INTERNAL_LOGARITHMICFADE 11
|
||||
|
||||
|
||||
|
||||
|
||||
#define EFFECT_INTERNAL_CORNERPIN 12
|
||||
#define EFFECT_INTERNAL_COUNT 13
|
||||
|
||||
@@ -107,99 +100,8 @@ struct GLTextureCoords {
|
||||
|
||||
qint16 mix_audio_sample(qint16 a, qint16 b);
|
||||
|
||||
class EffectField : public QObject {
|
||||
Q_OBJECT
|
||||
public:
|
||||
EffectField(EffectRow* parent, int t);
|
||||
EffectRow* parent_row;
|
||||
int type;
|
||||
QString id;
|
||||
|
||||
QVariant get_previous_data();
|
||||
QVariant get_current_data();
|
||||
double frameToTimecode(long frame);
|
||||
long timecodeToFrame(double timecode);
|
||||
void set_current_data(const QVariant&);
|
||||
void get_keyframe_data(double timecode, int& before, int& after, double& d);
|
||||
QVariant validate_keyframe_data(double timecode, bool async = false);
|
||||
|
||||
double get_double_value(double timecode, bool async = false);
|
||||
void set_double_value(double v);
|
||||
void set_double_default_value(double v);
|
||||
void set_double_minimum_value(double v);
|
||||
void set_double_maximum_value(double v);
|
||||
|
||||
const QString get_string_value(double timecode, bool async = false);
|
||||
void set_string_value(const QString &s);
|
||||
|
||||
void add_combo_item(const QString& name, const QVariant &data);
|
||||
int get_combo_index(double timecode, bool async = false);
|
||||
const QVariant get_combo_data(double timecode);
|
||||
const QString get_combo_string(double timecode);
|
||||
void set_combo_index(int index);
|
||||
void set_combo_string(const QString& s);
|
||||
|
||||
bool get_bool_value(double timecode, bool async = false);
|
||||
void set_bool_value(bool b);
|
||||
|
||||
const QString get_font_name(double timecode, bool async = false);
|
||||
void set_font_name(const QString& s);
|
||||
|
||||
QColor get_color_value(double timecode, bool async = false);
|
||||
void set_color_value(QColor color);
|
||||
|
||||
QWidget* get_ui_element();
|
||||
void set_enabled(bool e);
|
||||
QVector<QVariant> keyframe_data;
|
||||
QWidget* ui_element;
|
||||
private:
|
||||
bool hasKeyframes();
|
||||
private slots:
|
||||
void uiElementChange();
|
||||
signals:
|
||||
void changed();
|
||||
void toggled(bool);
|
||||
};
|
||||
|
||||
class EffectRow : public QObject {
|
||||
Q_OBJECT
|
||||
public:
|
||||
EffectRow(Effect* parent, QGridLayout* uilayout, const QString& n, int row);
|
||||
~EffectRow();
|
||||
EffectField* add_field(int type, int colspan = 1);
|
||||
EffectField* field(int i);
|
||||
int fieldCount();
|
||||
void set_keyframe_now(bool undoable);
|
||||
void delete_keyframe(KeyframeDelete *kd, int index);
|
||||
void delete_keyframe_at_time(KeyframeDelete* kd, long time);
|
||||
QLabel* label;
|
||||
Effect* parent_effect;
|
||||
|
||||
bool isKeyframing();
|
||||
void setKeyframing(bool);
|
||||
|
||||
QVector<long> keyframe_times;
|
||||
QVector<int> keyframe_types;
|
||||
private slots:
|
||||
void set_keyframe_enabled(bool);
|
||||
void keyframe_ui_enabled(bool);
|
||||
void goto_previous_key();
|
||||
void toggle_key();
|
||||
void goto_next_key();
|
||||
private:
|
||||
bool keyframing;
|
||||
QGridLayout* ui;
|
||||
QString name;
|
||||
int ui_row;
|
||||
QVector<EffectField*> fields;
|
||||
|
||||
QPushButton* keyframe_enable;
|
||||
QPushButton* left_key_nav;
|
||||
QPushButton* key_addremove;
|
||||
QPushButton* right_key_nav;
|
||||
|
||||
bool just_made_unsafe_keyframe;
|
||||
};
|
||||
#include "effectfield.h"
|
||||
#include "effectrow.h"
|
||||
|
||||
class Effect : public QObject {
|
||||
Q_OBJECT
|
||||
@@ -208,13 +110,11 @@ public:
|
||||
~Effect();
|
||||
Clip* parent_clip;
|
||||
const EffectMeta* meta;
|
||||
long length; // used only for transitions
|
||||
int id;
|
||||
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();
|
||||
|
||||
@@ -0,0 +1,352 @@
|
||||
#include "effectfield.h"
|
||||
|
||||
#include "ui/labelslider.h"
|
||||
#include "ui/colorbutton.h"
|
||||
#include "ui/texteditex.h"
|
||||
#include "ui/checkboxex.h"
|
||||
#include "ui/comboboxex.h"
|
||||
#include "ui/fontcombobox.h"
|
||||
|
||||
#include "effectrow.h"
|
||||
#include "effect.h"
|
||||
|
||||
#include "project/undo.h"
|
||||
#include "project/clip.h"
|
||||
#include "project/sequence.h"
|
||||
|
||||
#include "io/math.h"
|
||||
#include <QtMath>
|
||||
|
||||
EffectField::EffectField(EffectRow *parent, int t) : parent_row(parent), type(t) {
|
||||
switch (t) {
|
||||
case EFFECT_FIELD_DOUBLE:
|
||||
{
|
||||
LabelSlider* ls = new LabelSlider();
|
||||
ui_element = ls;
|
||||
connect(ls, SIGNAL(valueChanged()), this, SLOT(uiElementChange()));
|
||||
}
|
||||
break;
|
||||
case EFFECT_FIELD_COLOR:
|
||||
{
|
||||
ColorButton* cb = new ColorButton();
|
||||
ui_element = cb;
|
||||
connect(cb, SIGNAL(color_changed()), this, SLOT(uiElementChange()));
|
||||
}
|
||||
break;
|
||||
case EFFECT_FIELD_STRING:
|
||||
{
|
||||
TextEditEx* edit = new TextEditEx();
|
||||
edit->setUndoRedoEnabled(true);
|
||||
ui_element = edit;
|
||||
connect(edit, SIGNAL(textChanged()), this, SLOT(uiElementChange()));
|
||||
}
|
||||
break;
|
||||
case EFFECT_FIELD_BOOL:
|
||||
{
|
||||
CheckboxEx* cb = new CheckboxEx();
|
||||
ui_element = cb;
|
||||
connect(cb, SIGNAL(clicked(bool)), this, SLOT(uiElementChange()));
|
||||
connect(cb, SIGNAL(toggled(bool)), this, SIGNAL(toggled(bool)));
|
||||
}
|
||||
break;
|
||||
case EFFECT_FIELD_COMBO:
|
||||
{
|
||||
ComboBoxEx* cb = new ComboBoxEx();
|
||||
ui_element = cb;
|
||||
connect(cb, SIGNAL(activated(int)), this, SLOT(uiElementChange()));
|
||||
}
|
||||
break;
|
||||
case EFFECT_FIELD_FONT:
|
||||
{
|
||||
FontCombobox* fcb = new FontCombobox();
|
||||
ui_element = fcb;
|
||||
connect(fcb, SIGNAL(activated(int)), this, SLOT(uiElementChange()));
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
QVariant EffectField::get_previous_data() {
|
||||
switch (type) {
|
||||
case EFFECT_FIELD_DOUBLE: return static_cast<LabelSlider*>(ui_element)->getPreviousValue(); break;
|
||||
case EFFECT_FIELD_COLOR: return static_cast<ColorButton*>(ui_element)->getPreviousValue(); break;
|
||||
case EFFECT_FIELD_STRING: return static_cast<TextEditEx*>(ui_element)->getPreviousValue(); break;
|
||||
case EFFECT_FIELD_BOOL: return !static_cast<QCheckBox*>(ui_element)->isChecked(); break;
|
||||
case EFFECT_FIELD_COMBO: return static_cast<ComboBoxEx*>(ui_element)->getPreviousIndex(); break;
|
||||
case EFFECT_FIELD_FONT: return static_cast<FontCombobox*>(ui_element)->getPreviousValue(); break;
|
||||
}
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
QVariant EffectField::get_current_data() {
|
||||
switch (type) {
|
||||
case EFFECT_FIELD_DOUBLE: return static_cast<LabelSlider*>(ui_element)->value(); break;
|
||||
case EFFECT_FIELD_COLOR: return static_cast<ColorButton*>(ui_element)->get_color(); break;
|
||||
case EFFECT_FIELD_STRING: return static_cast<TextEditEx*>(ui_element)->getPlainTextEx(); break;
|
||||
case EFFECT_FIELD_BOOL: return static_cast<QCheckBox*>(ui_element)->isChecked(); break;
|
||||
case EFFECT_FIELD_COMBO: return static_cast<ComboBoxEx*>(ui_element)->currentIndex(); break;
|
||||
case EFFECT_FIELD_FONT: return static_cast<FontCombobox*>(ui_element)->currentText(); break;
|
||||
}
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
double EffectField::frameToTimecode(long frame) {
|
||||
return ((double) frame / parent_row->parent_effect->parent_clip->sequence->frame_rate);
|
||||
}
|
||||
|
||||
long EffectField::timecodeToFrame(double timecode) {
|
||||
return qRound(timecode * parent_row->parent_effect->parent_clip->sequence->frame_rate);
|
||||
}
|
||||
|
||||
void EffectField::set_current_data(const QVariant& data) {
|
||||
switch (type) {
|
||||
case EFFECT_FIELD_DOUBLE: return static_cast<LabelSlider*>(ui_element)->set_value(data.toDouble(), false); break;
|
||||
case EFFECT_FIELD_COLOR: return static_cast<ColorButton*>(ui_element)->set_color(data.value<QColor>()); break;
|
||||
case EFFECT_FIELD_STRING: return static_cast<TextEditEx*>(ui_element)->setPlainTextEx(data.toString()); break;
|
||||
case EFFECT_FIELD_BOOL: return static_cast<QCheckBox*>(ui_element)->setChecked(data.toBool()); break;
|
||||
case EFFECT_FIELD_COMBO: return static_cast<ComboBoxEx*>(ui_element)->setCurrentIndexEx(data.toInt()); break;
|
||||
case EFFECT_FIELD_FONT: return static_cast<FontCombobox*>(ui_element)->setCurrentTextEx(data.toString()); break;
|
||||
}
|
||||
}
|
||||
|
||||
void EffectField::get_keyframe_data(double timecode, int &before, int &after, double &progress) {
|
||||
int before_keyframe_index = -1;
|
||||
int after_keyframe_index = -1;
|
||||
long before_keyframe_time = LONG_MIN;
|
||||
long after_keyframe_time = LONG_MAX;
|
||||
long frame = timecodeToFrame(timecode);
|
||||
|
||||
for (int i=0;i<parent_row->keyframe_times.size();i++) {
|
||||
long eval_keyframe_time = parent_row->keyframe_times.at(i);
|
||||
if (eval_keyframe_time == frame) {
|
||||
before = i;
|
||||
after = i;
|
||||
return;
|
||||
} else if (eval_keyframe_time < frame && eval_keyframe_time > before_keyframe_time) {
|
||||
before_keyframe_index = i;
|
||||
before_keyframe_time = eval_keyframe_time;
|
||||
} else if (eval_keyframe_time > frame && eval_keyframe_time < after_keyframe_time) {
|
||||
after_keyframe_index = i;
|
||||
after_keyframe_time = eval_keyframe_time;
|
||||
}
|
||||
}
|
||||
|
||||
if ((type == EFFECT_FIELD_DOUBLE || type == EFFECT_FIELD_COLOR) && (before_keyframe_index > -1 && after_keyframe_index > -1)) {
|
||||
// interpolate
|
||||
before = before_keyframe_index;
|
||||
after = after_keyframe_index;
|
||||
|
||||
progress = (timecode-frameToTimecode(before_keyframe_time))/(frameToTimecode(after_keyframe_time)-frameToTimecode(before_keyframe_time));
|
||||
|
||||
// TODO routines for bezier - currently this is purely linear
|
||||
} else if (before_keyframe_index > -1) {
|
||||
before = before_keyframe_index;
|
||||
after = before_keyframe_index;
|
||||
} else {
|
||||
before = after_keyframe_index;
|
||||
after = after_keyframe_index;
|
||||
}
|
||||
}
|
||||
|
||||
bool EffectField::hasKeyframes() {
|
||||
return (parent_row->isKeyframing() && keyframe_data.size() > 0);
|
||||
}
|
||||
|
||||
QVariant EffectField::validate_keyframe_data(double timecode, bool async) {
|
||||
if (hasKeyframes()) {
|
||||
int before_keyframe;
|
||||
int after_keyframe;
|
||||
double progress;
|
||||
get_keyframe_data(timecode, before_keyframe, after_keyframe, progress);
|
||||
|
||||
int kf_type = (progress < 0.5) ? parent_row->keyframe_types.at(before_keyframe) : parent_row->keyframe_types.at(after_keyframe);
|
||||
if (kf_type == KEYFRAME_TYPE_SMOOTH) {
|
||||
double b = 4;
|
||||
double c = 1.313;
|
||||
double x = (b * progress) - (b*0.5);
|
||||
progress = (c*(qPow(M_E, x)/(qPow(M_E, x) + 1)))-((c-1)*0.5);
|
||||
}
|
||||
|
||||
const QVariant& before_data = keyframe_data.at(before_keyframe);
|
||||
switch (type) {
|
||||
case EFFECT_FIELD_DOUBLE:
|
||||
{
|
||||
double value;
|
||||
if (before_keyframe == after_keyframe) {
|
||||
value = keyframe_data.at(before_keyframe).toDouble();
|
||||
} else {
|
||||
double before_dbl = keyframe_data.at(before_keyframe).toDouble();
|
||||
double after_dbl = keyframe_data.at(after_keyframe).toDouble();
|
||||
value = double_lerp(before_dbl, after_dbl, progress);
|
||||
}
|
||||
if (async) {
|
||||
return value;
|
||||
}
|
||||
static_cast<LabelSlider*>(ui_element)->set_value(value, false);
|
||||
}
|
||||
break;
|
||||
case EFFECT_FIELD_COLOR:
|
||||
{
|
||||
QColor value;
|
||||
if (before_keyframe == after_keyframe) {
|
||||
value = keyframe_data.at(before_keyframe).value<QColor>();
|
||||
} else {
|
||||
QColor before_data = keyframe_data.at(before_keyframe).value<QColor>();
|
||||
QColor after_data = keyframe_data.at(after_keyframe).value<QColor>();
|
||||
value = QColor(lerp(before_data.red(), after_data.red(), progress), lerp(before_data.green(), after_data.green(), progress), lerp(before_data.blue(), after_data.blue(), progress));
|
||||
}
|
||||
if (async) {
|
||||
return value;
|
||||
}
|
||||
static_cast<ColorButton*>(ui_element)->set_color(value);
|
||||
}
|
||||
break;
|
||||
case EFFECT_FIELD_STRING:
|
||||
if (async) {
|
||||
return before_data;
|
||||
}
|
||||
static_cast<TextEditEx*>(ui_element)->setPlainTextEx(before_data.toString());
|
||||
break;
|
||||
case EFFECT_FIELD_BOOL:
|
||||
if (async) {
|
||||
return before_data;
|
||||
}
|
||||
static_cast<QCheckBox*>(ui_element)->setChecked(before_data.toBool());
|
||||
break;
|
||||
case EFFECT_FIELD_COMBO:
|
||||
if (async) {
|
||||
return before_data;
|
||||
}
|
||||
static_cast<ComboBoxEx*>(ui_element)->setCurrentIndexEx(before_data.toInt());
|
||||
break;
|
||||
case EFFECT_FIELD_FONT:
|
||||
if (async) {
|
||||
return before_data;
|
||||
}
|
||||
static_cast<FontCombobox*>(ui_element)->setCurrentTextEx(before_data.toString());
|
||||
break;
|
||||
}
|
||||
}
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
void EffectField::uiElementChange() {
|
||||
bool enableKeyframes = !(type == EFFECT_FIELD_DOUBLE && static_cast<LabelSlider*>(ui_element)->is_dragging());
|
||||
if (parent_row->isKeyframing()) {
|
||||
parent_row->set_keyframe_now(enableKeyframes);
|
||||
} else if (enableKeyframes) {
|
||||
// set undo
|
||||
undo_stack.push(new EffectFieldUndo(this));
|
||||
}
|
||||
emit changed();
|
||||
}
|
||||
|
||||
QWidget* EffectField::get_ui_element() {
|
||||
return ui_element;
|
||||
}
|
||||
|
||||
void EffectField::set_enabled(bool e) {
|
||||
ui_element->setEnabled(e);
|
||||
}
|
||||
|
||||
double EffectField::get_double_value(double timecode, bool async) {
|
||||
if (async && hasKeyframes()) {
|
||||
return validate_keyframe_data(timecode, true).toDouble();
|
||||
}
|
||||
validate_keyframe_data(timecode);
|
||||
return static_cast<LabelSlider*>(ui_element)->value();
|
||||
}
|
||||
|
||||
void EffectField::set_double_value(double v) {
|
||||
static_cast<LabelSlider*>(ui_element)->set_value(v, false);
|
||||
}
|
||||
|
||||
void EffectField::set_double_default_value(double v) {
|
||||
static_cast<LabelSlider*>(ui_element)->set_default_value(v);
|
||||
}
|
||||
|
||||
void EffectField::set_double_minimum_value(double v) {
|
||||
static_cast<LabelSlider*>(ui_element)->set_minimum_value(v);
|
||||
}
|
||||
|
||||
void EffectField::set_double_maximum_value(double v) {
|
||||
static_cast<LabelSlider*>(ui_element)->set_maximum_value(v);
|
||||
}
|
||||
|
||||
void EffectField::add_combo_item(const QString& name, const QVariant& data) {
|
||||
static_cast<ComboBoxEx*>(ui_element)->addItem(name, data);
|
||||
}
|
||||
|
||||
int EffectField::get_combo_index(double timecode, bool async) {
|
||||
if (async && hasKeyframes()) {
|
||||
return validate_keyframe_data(timecode, true).toInt();
|
||||
}
|
||||
validate_keyframe_data(timecode);
|
||||
return static_cast<ComboBoxEx*>(ui_element)->currentIndex();
|
||||
}
|
||||
|
||||
const QVariant EffectField::get_combo_data(double timecode) {
|
||||
validate_keyframe_data(timecode);
|
||||
return static_cast<ComboBoxEx*>(ui_element)->currentData();
|
||||
}
|
||||
|
||||
const QString EffectField::get_combo_string(double timecode) {
|
||||
validate_keyframe_data(timecode);
|
||||
return static_cast<ComboBoxEx*>(ui_element)->currentText();
|
||||
}
|
||||
|
||||
void EffectField::set_combo_index(int index) {
|
||||
static_cast<ComboBoxEx*>(ui_element)->setCurrentIndexEx(index);
|
||||
}
|
||||
|
||||
void EffectField::set_combo_string(const QString& s) {
|
||||
static_cast<ComboBoxEx*>(ui_element)->setCurrentTextEx(s);
|
||||
}
|
||||
|
||||
bool EffectField::get_bool_value(double timecode, bool async) {
|
||||
if (async && hasKeyframes()) {
|
||||
return validate_keyframe_data(timecode, true).toBool();
|
||||
}
|
||||
validate_keyframe_data(timecode);
|
||||
return static_cast<QCheckBox*>(ui_element)->isChecked();
|
||||
}
|
||||
|
||||
void EffectField::set_bool_value(bool b) {
|
||||
return static_cast<QCheckBox*>(ui_element)->setChecked(b);
|
||||
}
|
||||
|
||||
const QString EffectField::get_string_value(double timecode, bool async) {
|
||||
if (async && hasKeyframes()) {
|
||||
return validate_keyframe_data(timecode, true).toString();
|
||||
}
|
||||
validate_keyframe_data(timecode);
|
||||
return static_cast<TextEditEx*>(ui_element)->getPlainTextEx();
|
||||
}
|
||||
|
||||
void EffectField::set_string_value(const QString& s) {
|
||||
static_cast<TextEditEx*>(ui_element)->setPlainTextEx(s);
|
||||
}
|
||||
|
||||
const QString EffectField::get_font_name(double timecode, bool async) {
|
||||
if (async && hasKeyframes()) {
|
||||
return validate_keyframe_data(timecode, true).toString();
|
||||
}
|
||||
validate_keyframe_data(timecode);
|
||||
return static_cast<FontCombobox*>(ui_element)->currentText();
|
||||
}
|
||||
|
||||
void EffectField::set_font_name(const QString& s) {
|
||||
static_cast<FontCombobox*>(ui_element)->setCurrentText(s);
|
||||
}
|
||||
|
||||
QColor EffectField::get_color_value(double timecode, bool async) {
|
||||
if (async && hasKeyframes()) {
|
||||
return validate_keyframe_data(timecode, true).value<QColor>();
|
||||
}
|
||||
validate_keyframe_data(timecode);
|
||||
return static_cast<ColorButton*>(ui_element)->get_color();
|
||||
}
|
||||
|
||||
void EffectField::set_color_value(QColor color) {
|
||||
static_cast<ColorButton*>(ui_element)->set_color(color);
|
||||
}
|
||||
@@ -0,0 +1,71 @@
|
||||
#ifndef EFFECTFIELD_H
|
||||
#define EFFECTFIELD_H
|
||||
|
||||
#define EFFECT_FIELD_DOUBLE 0
|
||||
#define EFFECT_FIELD_COLOR 1
|
||||
#define EFFECT_FIELD_STRING 2
|
||||
#define EFFECT_FIELD_BOOL 3
|
||||
#define EFFECT_FIELD_COMBO 4
|
||||
#define EFFECT_FIELD_FONT 5
|
||||
|
||||
#include <QObject>
|
||||
#include <QVariant>
|
||||
#include <QVector>
|
||||
|
||||
class EffectRow;
|
||||
|
||||
class EffectField : public QObject {
|
||||
Q_OBJECT
|
||||
public:
|
||||
EffectField(EffectRow* parent, int t);
|
||||
EffectRow* parent_row;
|
||||
int type;
|
||||
QString id;
|
||||
|
||||
QVariant get_previous_data();
|
||||
QVariant get_current_data();
|
||||
double frameToTimecode(long frame);
|
||||
long timecodeToFrame(double timecode);
|
||||
void set_current_data(const QVariant&);
|
||||
void get_keyframe_data(double timecode, int& before, int& after, double& d);
|
||||
QVariant validate_keyframe_data(double timecode, bool async = false);
|
||||
|
||||
double get_double_value(double timecode, bool async = false);
|
||||
void set_double_value(double v);
|
||||
void set_double_default_value(double v);
|
||||
void set_double_minimum_value(double v);
|
||||
void set_double_maximum_value(double v);
|
||||
|
||||
const QString get_string_value(double timecode, bool async = false);
|
||||
void set_string_value(const QString &s);
|
||||
|
||||
void add_combo_item(const QString& name, const QVariant &data);
|
||||
int get_combo_index(double timecode, bool async = false);
|
||||
const QVariant get_combo_data(double timecode);
|
||||
const QString get_combo_string(double timecode);
|
||||
void set_combo_index(int index);
|
||||
void set_combo_string(const QString& s);
|
||||
|
||||
bool get_bool_value(double timecode, bool async = false);
|
||||
void set_bool_value(bool b);
|
||||
|
||||
const QString get_font_name(double timecode, bool async = false);
|
||||
void set_font_name(const QString& s);
|
||||
|
||||
QColor get_color_value(double timecode, bool async = false);
|
||||
void set_color_value(QColor color);
|
||||
|
||||
QWidget* get_ui_element();
|
||||
void set_enabled(bool e);
|
||||
QVector<QVariant> keyframe_data;
|
||||
QWidget* ui_element;
|
||||
private:
|
||||
bool hasKeyframes();
|
||||
private slots:
|
||||
void uiElementChange();
|
||||
signals:
|
||||
void changed();
|
||||
void toggled(bool);
|
||||
};
|
||||
|
||||
#endif // EFFECTFIELD_H
|
||||
@@ -0,0 +1,205 @@
|
||||
#include "effectrow.h"
|
||||
|
||||
#include <QLabel>
|
||||
#include <QHBoxLayout>
|
||||
#include <QPushButton>
|
||||
#include <QMessageBox>
|
||||
|
||||
#include "project/undo.h"
|
||||
#include "project/clip.h"
|
||||
#include "project/sequence.h"
|
||||
#include "panels/panels.h"
|
||||
#include "panels/effectcontrols.h"
|
||||
#include "panels/viewer.h"
|
||||
#include "effect.h"
|
||||
#include "ui/viewerwidget.h"
|
||||
|
||||
EffectRow::EffectRow(Effect *parent, QGridLayout *uilayout, const QString &n, int row) :
|
||||
parent_effect(parent),
|
||||
keyframing(false),
|
||||
ui(uilayout),
|
||||
name(n),
|
||||
ui_row(row),
|
||||
just_made_unsafe_keyframe(false)
|
||||
{
|
||||
label = new QLabel(name);
|
||||
ui->addWidget(label, row, 0);
|
||||
|
||||
QSize button_size(20, 20);
|
||||
QSize icon_size(12, 12);
|
||||
|
||||
QHBoxLayout* key_controls = new QHBoxLayout();
|
||||
key_controls->setSpacing(0);
|
||||
key_controls->setMargin(0);
|
||||
key_controls->addStretch();
|
||||
|
||||
left_key_nav = new QPushButton("<");
|
||||
left_key_nav->setVisible(false);
|
||||
left_key_nav->setMaximumSize(button_size);
|
||||
key_controls->addWidget(left_key_nav);
|
||||
connect(left_key_nav, SIGNAL(clicked(bool)), this, SLOT(goto_previous_key()));
|
||||
|
||||
key_addremove = new QPushButton(".");
|
||||
key_addremove->setVisible(false);
|
||||
key_addremove->setMaximumSize(button_size);
|
||||
key_controls->addWidget(key_addremove);
|
||||
connect(key_addremove, SIGNAL(clicked(bool)), this, SLOT(toggle_key()));
|
||||
|
||||
right_key_nav = new QPushButton(">");
|
||||
right_key_nav->setVisible(false);
|
||||
right_key_nav->setMaximumSize(button_size);
|
||||
key_controls->addWidget(right_key_nav);
|
||||
connect(right_key_nav, SIGNAL(clicked(bool)), this, SLOT(goto_next_key()));
|
||||
|
||||
keyframe_enable = new QPushButton(QIcon(":/icons/clock.png"), "");
|
||||
keyframe_enable->setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Fixed);
|
||||
keyframe_enable->setMaximumSize(button_size);
|
||||
keyframe_enable->setIconSize(icon_size);
|
||||
keyframe_enable->setCheckable(true);
|
||||
keyframe_enable->setToolTip("Enable Keyframes");
|
||||
connect(keyframe_enable, SIGNAL(clicked(bool)), this, SLOT(set_keyframe_enabled(bool)));
|
||||
connect(keyframe_enable, SIGNAL(toggled(bool)), this, SLOT(keyframe_ui_enabled(bool)));
|
||||
key_controls->addWidget(keyframe_enable);
|
||||
|
||||
ui->addLayout(key_controls, row, 6);
|
||||
}
|
||||
|
||||
bool EffectRow::isKeyframing() {
|
||||
return keyframing;
|
||||
}
|
||||
|
||||
void EffectRow::setKeyframing(bool b) {
|
||||
keyframing = b;
|
||||
keyframe_enable->setChecked(b);
|
||||
}
|
||||
|
||||
void EffectRow::set_keyframe_enabled(bool enabled) {
|
||||
if (enabled) {
|
||||
set_keyframe_now(true);
|
||||
} else {
|
||||
if (QMessageBox::question(panel_effect_controls, "Disable Keyframes", "Disabling keyframes will delete all current keyframes. Are you sure you want to do this?", QMessageBox::Yes, QMessageBox::No) == QMessageBox::Yes) {
|
||||
// clear
|
||||
KeyframeDelete* kd = new KeyframeDelete();
|
||||
for (int i=keyframe_times.size()-1;i>=0;i--) {
|
||||
delete_keyframe(kd, i);
|
||||
}
|
||||
kd->disable_keyframes_on_row = this;
|
||||
undo_stack.push(kd);
|
||||
panel_effect_controls->update_keyframes();
|
||||
} else {
|
||||
setKeyframing(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void EffectRow::keyframe_ui_enabled(bool enabled) {
|
||||
left_key_nav->setVisible(enabled);
|
||||
key_addremove->setVisible(enabled);
|
||||
right_key_nav->setVisible(enabled);
|
||||
}
|
||||
|
||||
void EffectRow::goto_previous_key() {
|
||||
long key = LONG_MIN;
|
||||
Clip* c = parent_effect->parent_clip;
|
||||
for (int i=0;i<keyframe_times.size();i++) {
|
||||
long comp = keyframe_times.at(i) - c->clip_in + c->timeline_in;
|
||||
if (comp < sequence->playhead) {
|
||||
key = qMax(comp, key);
|
||||
}
|
||||
}
|
||||
if (key != LONG_MIN) panel_sequence_viewer->seek(key);
|
||||
}
|
||||
|
||||
void EffectRow::toggle_key() {
|
||||
int index = -1;
|
||||
Clip* c = parent_effect->parent_clip;
|
||||
for (int i=0;i<keyframe_times.size();i++) {
|
||||
long comp = c->timeline_in - c->clip_in + keyframe_times.at(i);
|
||||
if (comp == sequence->playhead) {
|
||||
index = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (index < 0) {
|
||||
// keyframe doesn't exist, set one
|
||||
set_keyframe_now(true);
|
||||
} else {
|
||||
KeyframeDelete* kd = new KeyframeDelete();
|
||||
delete_keyframe(kd, index);
|
||||
undo_stack.push(kd);
|
||||
panel_effect_controls->update_keyframes();
|
||||
panel_sequence_viewer->viewer_widget->update();
|
||||
}
|
||||
}
|
||||
|
||||
void EffectRow::goto_next_key() {
|
||||
long key = LONG_MAX;
|
||||
Clip* c = parent_effect->parent_clip;
|
||||
for (int i=0;i<keyframe_times.size();i++) {
|
||||
long comp = c->timeline_in - c->clip_in + keyframe_times.at(i);
|
||||
if (comp > sequence->playhead) {
|
||||
key = qMin(comp, key);
|
||||
}
|
||||
}
|
||||
if (key != LONG_MAX) panel_sequence_viewer->seek(key);
|
||||
}
|
||||
|
||||
EffectField* EffectRow::add_field(int type, int colspan) {
|
||||
EffectField* field = new EffectField(this, type);
|
||||
fields.append(field);
|
||||
QWidget* element = field->get_ui_element();
|
||||
ui->addWidget(element, ui_row, fields.size(), 1, colspan);
|
||||
return field;
|
||||
}
|
||||
|
||||
EffectRow::~EffectRow() {
|
||||
for (int i=0;i<fields.size();i++) {
|
||||
delete fields.at(i);
|
||||
}
|
||||
}
|
||||
|
||||
void EffectRow::set_keyframe_now(bool undoable) {
|
||||
int index = -1;
|
||||
long time = sequence->playhead-parent_effect->parent_clip->timeline_in+parent_effect->parent_clip->clip_in;
|
||||
for (int i=0;i<keyframe_times.size();i++) {
|
||||
if (keyframe_times.at(i) == time) {
|
||||
index = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
KeyframeSet* ks = new KeyframeSet(this, index, time, just_made_unsafe_keyframe);
|
||||
|
||||
if (undoable) {
|
||||
just_made_unsafe_keyframe = false;
|
||||
undo_stack.push(ks);
|
||||
} else {
|
||||
if (index == -1) just_made_unsafe_keyframe = true;
|
||||
ks->redo();
|
||||
delete ks;
|
||||
}
|
||||
|
||||
panel_effect_controls->update_keyframes();
|
||||
}
|
||||
|
||||
void EffectRow::delete_keyframe_at_time(KeyframeDelete* kd, long time) {
|
||||
for (int i=0;i<keyframe_times.size();i++) {
|
||||
if (keyframe_times.at(i) == time) {
|
||||
delete_keyframe(kd, i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void EffectRow::delete_keyframe(KeyframeDelete* kd, int index) {
|
||||
kd->rows.append(this);
|
||||
kd->keyframes.append(index);
|
||||
}
|
||||
|
||||
EffectField* EffectRow::field(int i) {
|
||||
return fields.at(i);
|
||||
}
|
||||
|
||||
int EffectRow::fieldCount() {
|
||||
return fields.size();
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
#ifndef EFFECTROW_H
|
||||
#define EFFECTROW_H
|
||||
|
||||
#include <QObject>
|
||||
#include <QVector>
|
||||
|
||||
class Effect;
|
||||
class QGridLayout;
|
||||
class EffectField;
|
||||
class QLabel;
|
||||
class KeyframeDelete;
|
||||
class QPushButton;
|
||||
|
||||
class EffectRow : public QObject {
|
||||
Q_OBJECT
|
||||
public:
|
||||
EffectRow(Effect* parent, QGridLayout* uilayout, const QString& n, int row);
|
||||
~EffectRow();
|
||||
EffectField* add_field(int type, int colspan = 1);
|
||||
EffectField* field(int i);
|
||||
int fieldCount();
|
||||
void set_keyframe_now(bool undoable);
|
||||
void delete_keyframe(KeyframeDelete *kd, int index);
|
||||
void delete_keyframe_at_time(KeyframeDelete* kd, long time);
|
||||
QLabel* label;
|
||||
Effect* parent_effect;
|
||||
|
||||
bool isKeyframing();
|
||||
void setKeyframing(bool);
|
||||
|
||||
QVector<long> keyframe_times;
|
||||
QVector<int> keyframe_types;
|
||||
private slots:
|
||||
void set_keyframe_enabled(bool);
|
||||
void keyframe_ui_enabled(bool);
|
||||
void goto_previous_key();
|
||||
void toggle_key();
|
||||
void goto_next_key();
|
||||
private:
|
||||
bool keyframing;
|
||||
QGridLayout* ui;
|
||||
QString name;
|
||||
int ui_row;
|
||||
QVector<EffectField*> fields;
|
||||
|
||||
QPushButton* keyframe_enable;
|
||||
QPushButton* left_key_nav;
|
||||
QPushButton* key_addremove;
|
||||
QPushButton* right_key_nav;
|
||||
|
||||
bool just_made_unsafe_keyframe;
|
||||
};
|
||||
|
||||
#endif // EFFECTROW_H
|
||||
+28
-1
@@ -1,6 +1,9 @@
|
||||
#include "sequence.h"
|
||||
|
||||
#include "project/clip.h"
|
||||
#include "clip.h"
|
||||
#include "transition.h"
|
||||
|
||||
#include "debug.h"
|
||||
|
||||
Sequence::Sequence() :
|
||||
playhead(0),
|
||||
@@ -51,6 +54,30 @@ long Sequence::getEndFrame() {
|
||||
return end;
|
||||
}
|
||||
|
||||
void Sequence::hard_delete_transition(Clip *c, int type) {
|
||||
int transition_index = (type == TA_OPENING_TRANSITION) ? c->opening_transition : c->closing_transition;
|
||||
if (transition_index > -1) {
|
||||
for (int i=0;i<clips.size();i++) {
|
||||
Clip* cc = clips.at(i);
|
||||
if (cc != NULL
|
||||
&& c != cc
|
||||
&& (cc->opening_transition == transition_index
|
||||
|| cc->closing_transition == transition_index)) {
|
||||
// another clip is using this, don't delete just yet
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
delete transitions.at(transition_index);
|
||||
transitions[transition_index] = NULL;
|
||||
if (type == TA_OPENING_TRANSITION) {
|
||||
c->opening_transition = -1;
|
||||
} else {
|
||||
c->closing_transition = -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Sequence::getTrackLimits(int* video_tracks, int* audio_tracks) {
|
||||
int vt = 0;
|
||||
int at = 0;
|
||||
|
||||
+5
-1
@@ -3,10 +3,12 @@
|
||||
|
||||
#include <QVector>
|
||||
|
||||
#include "project/clip.h"
|
||||
#include "project/marker.h"
|
||||
#include "project/selection.h"
|
||||
|
||||
struct Clip;
|
||||
class Transition;
|
||||
|
||||
struct Sequence {
|
||||
Sequence();
|
||||
~Sequence();
|
||||
@@ -14,6 +16,7 @@ struct Sequence {
|
||||
QString name;
|
||||
void getTrackLimits(int* video_tracks, int* audio_tracks);
|
||||
long getEndFrame();
|
||||
void hard_delete_transition(Clip *c, int type);
|
||||
int width;
|
||||
int height;
|
||||
double frame_rate;
|
||||
@@ -33,6 +36,7 @@ struct Sequence {
|
||||
|
||||
QVector<Marker> markers;
|
||||
QVector<Clip*> clips;
|
||||
QVector<Transition*> transitions;
|
||||
};
|
||||
|
||||
// static variable for the currently active sequence
|
||||
|
||||
@@ -0,0 +1,51 @@
|
||||
#include "transition.h"
|
||||
|
||||
#include "mainwindow.h"
|
||||
#include "clip.h"
|
||||
#include "sequence.h"
|
||||
#include "debug.h"
|
||||
|
||||
#include "effects/internal/crossdissolvetransition.h"
|
||||
#include "effects/internal/linearfadetransition.h"
|
||||
#include "effects/internal/exponentialfadetransition.h"
|
||||
#include "effects/internal/logarithmicfadetransition.h"
|
||||
|
||||
#include <QMessageBox>
|
||||
|
||||
Transition::Transition(Clip* c, const EffectMeta* em) : Effect(c, em) {
|
||||
add_row("Length:")->add_field(EFFECT_FIELD_DOUBLE);
|
||||
}
|
||||
|
||||
int Transition::copy(Clip *c) {
|
||||
int copy_index = create_transition(c, meta);
|
||||
c->sequence->transitions.at(copy_index)->length = length;
|
||||
return copy_index;
|
||||
}
|
||||
|
||||
Transition* get_transition_from_meta(Clip* c, const EffectMeta* em) {
|
||||
if (!em->filename.isEmpty()) {
|
||||
// load effect from file
|
||||
return new Transition(c, em);
|
||||
} else if (em->internal >= 0 && em->internal < TRANSITION_INTERNAL_COUNT) {
|
||||
// must be an internal effect
|
||||
switch (em->internal) {
|
||||
case TRANSITION_INTERNAL_CROSSDISSOLVE: return new CrossDissolveTransition(c, em);
|
||||
case TRANSITION_INTERNAL_LINEARFADE: return new LinearFadeTransition(c, em);
|
||||
case TRANSITION_INTERNAL_EXPONENTIALFADE: return new ExponentialFadeTransition(c, em);
|
||||
case TRANSITION_INTERNAL_LOGARITHMICFADE: return new LogarithmicFadeTransition(c, em);
|
||||
}
|
||||
} else {
|
||||
dout << "[ERROR] Invalid transition data";
|
||||
QMessageBox::critical(mainWindow, "Invalid transition", "No candidate for transition '" + em->name + "'. This transition may be corrupt. Try reinstalling it or Olive.");
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int create_transition(Clip* c, const EffectMeta* em) {
|
||||
Transition* t = get_transition_from_meta(c, em);
|
||||
if (t != NULL) {
|
||||
c->sequence->transitions.append(t);
|
||||
return c->sequence->transitions.size() - 1;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
#ifndef TRANSITION_H
|
||||
#define TRANSITION_H
|
||||
|
||||
#include "effect.h"
|
||||
|
||||
#define TA_NO_TRANSITION 0
|
||||
#define TA_OPENING_TRANSITION 1
|
||||
#define TA_CLOSING_TRANSITION 2
|
||||
|
||||
#define TRANSITION_INTERNAL_CROSSDISSOLVE 0
|
||||
#define TRANSITION_INTERNAL_LINEARFADE 1
|
||||
#define TRANSITION_INTERNAL_EXPONENTIALFADE 2
|
||||
#define TRANSITION_INTERNAL_LOGARITHMICFADE 3
|
||||
#define TRANSITION_INTERNAL_COUNT 4
|
||||
|
||||
int create_transition(Clip* c, const EffectMeta* em);
|
||||
|
||||
class Transition : public Effect {
|
||||
public:
|
||||
Transition(Clip* c, const EffectMeta* em);
|
||||
int copy(Clip* c);
|
||||
};
|
||||
|
||||
#endif // TRANSITION_H
|
||||
+17
-561
@@ -14,6 +14,7 @@
|
||||
#include "playback/playback.h"
|
||||
#include "ui/sourcetable.h"
|
||||
#include "project/effect.h"
|
||||
#include "project/transition.h"
|
||||
#include "io/media.h"
|
||||
#include "playback/cacher.h"
|
||||
#include "ui/labelslider.h"
|
||||
@@ -232,23 +233,17 @@ AddTransitionCommand::AddTransitionCommand(Clip* c, const EffectMeta *itransitio
|
||||
{}
|
||||
|
||||
void AddTransitionCommand::undo() {
|
||||
if (type == TA_OPENING_TRANSITION) {
|
||||
delete clip->opening_transition;
|
||||
clip->opening_transition = NULL;
|
||||
} else {
|
||||
delete clip->closing_transition;
|
||||
clip->closing_transition = NULL;
|
||||
}
|
||||
clip->sequence->hard_delete_transition(clip, type);
|
||||
mainWindow->setWindowModified(old_project_changed);
|
||||
}
|
||||
|
||||
void AddTransitionCommand::redo() {
|
||||
if (type == TA_OPENING_TRANSITION) {
|
||||
clip->opening_transition = create_effect(clip, transition);
|
||||
if (length > 0) clip->opening_transition->length = length;
|
||||
clip->opening_transition = create_transition(clip, transition);
|
||||
if (length > 0) clip->get_opening_transition()->length = length;
|
||||
} else {
|
||||
clip->closing_transition = create_effect(clip, transition);
|
||||
if (length > 0) clip->closing_transition->length = length;
|
||||
clip->closing_transition = create_transition(clip, transition);
|
||||
if (length > 0) clip->get_closing_transition()->length = length;
|
||||
}
|
||||
mainWindow->setWindowModified(true);
|
||||
}
|
||||
@@ -261,22 +256,15 @@ ModifyTransitionCommand::ModifyTransitionCommand(Clip* c, int itype, long ilengt
|
||||
{}
|
||||
|
||||
void ModifyTransitionCommand::undo() {
|
||||
if (type == TA_OPENING_TRANSITION) {
|
||||
clip->opening_transition->length = old_length;
|
||||
} else {
|
||||
clip->closing_transition->length = old_length;
|
||||
}
|
||||
Transition* t = (type == TA_OPENING_TRANSITION) ? clip->get_opening_transition() : clip->get_closing_transition();
|
||||
t->length = old_length;
|
||||
mainWindow->setWindowModified(old_project_changed);
|
||||
}
|
||||
|
||||
void ModifyTransitionCommand::redo() {
|
||||
if (type == TA_OPENING_TRANSITION) {
|
||||
old_length = clip->opening_transition->length;
|
||||
clip->opening_transition->length = new_length;
|
||||
} else {
|
||||
old_length = clip->closing_transition->length;
|
||||
clip->closing_transition->length = new_length;
|
||||
}
|
||||
Transition* t = (type == TA_OPENING_TRANSITION) ? clip->get_opening_transition() : clip->get_closing_transition();
|
||||
old_length = t->length;
|
||||
t->length = new_length;
|
||||
mainWindow->setWindowModified(true);
|
||||
}
|
||||
|
||||
@@ -293,22 +281,19 @@ DeleteTransitionCommand::~DeleteTransitionCommand() {
|
||||
|
||||
void DeleteTransitionCommand::undo() {
|
||||
if (type == TA_OPENING_TRANSITION) {
|
||||
clip->opening_transition = transition;
|
||||
clip->opening_transition = old_index;
|
||||
} else {
|
||||
clip->closing_transition = transition;
|
||||
clip->closing_transition = old_index;
|
||||
}
|
||||
clip->sequence->transitions[old_index] = transition;
|
||||
transition = NULL;
|
||||
mainWindow->setWindowModified(old_project_changed);
|
||||
}
|
||||
|
||||
void DeleteTransitionCommand::redo() {
|
||||
if (type == TA_OPENING_TRANSITION) {
|
||||
transition = clip->opening_transition;
|
||||
clip->opening_transition = NULL;
|
||||
} else {
|
||||
transition = clip->closing_transition;
|
||||
clip->closing_transition = NULL;
|
||||
}
|
||||
old_index = (type == TA_OPENING_TRANSITION) ? clip->opening_transition : clip->closing_transition;
|
||||
transition = clip->sequence->transitions.at(old_index);
|
||||
clip->sequence->transitions[old_index] = NULL;
|
||||
mainWindow->setWindowModified(true);
|
||||
}
|
||||
|
||||
@@ -517,535 +502,6 @@ void AddClipCommand::redo() {
|
||||
mainWindow->setWindowModified(true);
|
||||
}
|
||||
|
||||
/*
|
||||
#define TA_ADD_EFFECT 9
|
||||
#define TA_ADD_TRANSITION 10
|
||||
#define TA_MODIFY_TRANSITION 11
|
||||
#define TA_DELETE_TRANSITION 12
|
||||
|
||||
TimelineAction::TimelineAction() :
|
||||
done(false),
|
||||
change_seq(false),
|
||||
ripple_enabled(false),
|
||||
change_in_out(false),
|
||||
old_project_changed(mainWindow->isWindowModified())
|
||||
{}
|
||||
|
||||
TimelineAction::~TimelineAction() {
|
||||
for (int i=0;i<clips_to_add.size();i++) {
|
||||
delete clips_to_add.at(i);
|
||||
}
|
||||
if (done) {
|
||||
for (int i=0;i<deleted_clips.size();i++) {
|
||||
delete deleted_clips.at(i);
|
||||
}
|
||||
for (int i=0;i<deleted_media.size();i++) {
|
||||
panel_project->delete_media(deleted_media.at(i));
|
||||
delete deleted_media.at(i);
|
||||
}
|
||||
} else {
|
||||
for (int i=0;i<new_sequence_items.size();i++) {
|
||||
delete get_sequence_from_tree(new_sequence_items.at(i));
|
||||
delete new_sequence_items.at(i);
|
||||
}
|
||||
for (int i=0;i<media_to_add.size();i++) {
|
||||
panel_project->delete_media(media_to_add.at(i));
|
||||
delete media_to_add.at(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void TimelineAction::offset_links(QVector<Clip*>& clips, int offset) {
|
||||
for (int i=0;i<clips.size();i++) {
|
||||
Clip* c = clips.at(i);
|
||||
for (int j=0;j<c->linked.size();j++) {
|
||||
c->linked[j] += offset;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void TimelineAction::change_sequence(Sequence* s) {
|
||||
new_seq = s;
|
||||
change_seq = true;
|
||||
}
|
||||
|
||||
void TimelineAction::new_sequence(QTreeWidgetItem *s, QTreeWidgetItem* parent) {
|
||||
new_sequence_items.append(s);
|
||||
new_sequence_parents.append(parent);
|
||||
}
|
||||
|
||||
void TimelineAction::add_clips(Sequence* s, QVector<Clip*>& add) {
|
||||
offset_links(add, clips_to_add.size());
|
||||
clips_to_add.append(add);
|
||||
for (int i=0;i<clips_to_add.size();i++) {
|
||||
sequence_to_add_clips_to.append(s);
|
||||
}
|
||||
}
|
||||
|
||||
void TimelineAction::new_action(Sequence* s, int action, int clip, int transition_type, long old_val, long new_val) {
|
||||
sequences.append(s);
|
||||
actions.append(action);
|
||||
clips.append(clip);
|
||||
transition_types.append(transition_type);
|
||||
old_values.append(old_val);
|
||||
new_values.append(new_val);
|
||||
}
|
||||
|
||||
void TimelineAction::set_timeline_in(Sequence* s, int clip, long value) {
|
||||
new_action(s, TA_IN, clip, TA_NO_TRANSITION, s->get_clip(clip)->timeline_in, value);
|
||||
}
|
||||
|
||||
void TimelineAction::set_timeline_out(Sequence* s, int clip, long value) {
|
||||
new_action(s, TA_OUT, clip, TA_NO_TRANSITION, s->get_clip(clip)->timeline_out, value);
|
||||
}
|
||||
|
||||
void TimelineAction::set_clip_in(Sequence* s, int clip, long value) {
|
||||
new_action(s, TA_CLIP_IN, clip, TA_NO_TRANSITION, s->get_clip(clip)->clip_in, value);
|
||||
}
|
||||
|
||||
void TimelineAction::set_track(Sequence* s, int clip, int value) {
|
||||
new_action(s, TA_TRACK, clip, TA_NO_TRANSITION, s->get_clip(clip)->track, value);
|
||||
}
|
||||
|
||||
void TimelineAction::increase_timeline_in(Sequence* s, int clip, long value) {
|
||||
new_action(s, TA_ADD_IN, clip, TA_NO_TRANSITION, 0, value);
|
||||
}
|
||||
|
||||
void TimelineAction::increase_timeline_out(Sequence* s, int clip, long value) {
|
||||
new_action(s, TA_ADD_OUT, clip, TA_NO_TRANSITION, 0, value);
|
||||
}
|
||||
|
||||
void TimelineAction::increase_clip_in(Sequence* s, int clip, long value) {
|
||||
new_action(s, TA_ADD_CLIP_IN, clip, TA_NO_TRANSITION, 0, value);
|
||||
}
|
||||
|
||||
void TimelineAction::increase_track(Sequence* s, int clip, int value) {
|
||||
new_action(s, TA_ADD_TRACK, clip, TA_NO_TRANSITION, 0, value);
|
||||
}
|
||||
|
||||
void TimelineAction::delete_clip(Sequence* s, int clip) {
|
||||
new_action(s, TA_DELETE, clip, TA_NO_TRANSITION, 0, 0);
|
||||
}
|
||||
|
||||
void TimelineAction::add_media(QTreeWidgetItem* item, QTreeWidgetItem *parent) {
|
||||
media_to_add.append(item);
|
||||
media_to_add_parents.append(parent);
|
||||
}
|
||||
|
||||
void TimelineAction::delete_media(QTreeWidgetItem* item) {
|
||||
deleted_media.append(item);
|
||||
}
|
||||
|
||||
void TimelineAction::ripple(Sequence* s, long point, long length) {
|
||||
QVector<int> i;
|
||||
ripple(s, point, length, i);
|
||||
}
|
||||
|
||||
void TimelineAction::add_effect(Sequence* s, int clip, int effect) {
|
||||
new_action(s, TA_ADD_EFFECT, clip, TA_NO_TRANSITION, 0, effect);
|
||||
}
|
||||
|
||||
void TimelineAction::add_transition(Sequence* s, int clip, int transition, int type) {
|
||||
new_action(s, TA_ADD_TRANSITION, clip, type, 0, transition);
|
||||
}
|
||||
|
||||
void TimelineAction::modify_transition(Sequence* s, int clip, int type, long length) {
|
||||
new_action(s, TA_MODIFY_TRANSITION, clip, type, 0, length);
|
||||
}
|
||||
|
||||
void TimelineAction::delete_transition(Sequence* s, int clip, int type) {
|
||||
new_action(s, TA_DELETE_TRANSITION, clip, type, 0, 0);
|
||||
}
|
||||
|
||||
void TimelineAction::set_in_out(Sequence* s, bool enabled, long in, long out) {
|
||||
change_in_out = true;
|
||||
change_in_out_sequence = s;
|
||||
|
||||
old_in_out_enabled = s->using_workarea;
|
||||
old_sequence_in = s->workarea_in;
|
||||
old_sequence_out = s->workarea_out;
|
||||
|
||||
new_in_out_enabled = enabled;
|
||||
new_sequence_in = in;
|
||||
new_sequence_out = out;
|
||||
|
||||
}
|
||||
|
||||
void TimelineAction::ripple(Sequence* s, long point, long length, QVector<int>& ignore) {
|
||||
ripple_enabled = true;
|
||||
ripple_point = point;
|
||||
ripple_length = length;
|
||||
ripple_sequence = s;
|
||||
ripple_ignores = ignore;
|
||||
}
|
||||
|
||||
void TimelineAction::undo() {
|
||||
// re-add deleted media
|
||||
for (int i=0;i<deleted_media.size();i++) {
|
||||
QTreeWidgetItem* item = deleted_media.at(i);
|
||||
QTreeWidgetItem* parent = deleted_media_parents.at(i);
|
||||
if (parent == NULL) {
|
||||
panel_project->source_table->addTopLevelItem(item);
|
||||
} else {
|
||||
parent->addChild(item);
|
||||
}
|
||||
}
|
||||
|
||||
// de-ripple clips
|
||||
if (ripple_enabled) {
|
||||
for (int i=0;i<rippled_clips.size();i++) {
|
||||
Clip* c = ripple_sequence->get_clip(rippled_clips.at(i));
|
||||
c->timeline_in -= ripple_length;
|
||||
c->timeline_out -= ripple_length;
|
||||
}
|
||||
}
|
||||
|
||||
for (int i=actions.size()-1;i>=0;i--) {
|
||||
switch (actions.at(i)) {
|
||||
case TA_IN:
|
||||
sequences.at(i)->get_clip(clips.at(i))->timeline_in = old_values.at(i);
|
||||
break;
|
||||
case TA_OUT:
|
||||
sequences.at(i)->get_clip(clips.at(i))->timeline_out = old_values.at(i);
|
||||
break;
|
||||
case TA_CLIP_IN:
|
||||
sequences.at(i)->get_clip(clips.at(i))->clip_in = old_values.at(i);
|
||||
break;
|
||||
case TA_TRACK:
|
||||
sequences.at(i)->get_clip(clips.at(i))->track = old_values.at(i);
|
||||
break;
|
||||
case TA_DELETE:
|
||||
sequences.at(i)->replace_clip(clips.at(i), deleted_clips.at(new_values.at(i)));
|
||||
break;
|
||||
case TA_ADD_IN:
|
||||
sequences.at(i)->get_clip(clips.at(i))->timeline_in -= new_values.at(i);
|
||||
break;
|
||||
case TA_ADD_OUT:
|
||||
sequences.at(i)->get_clip(clips.at(i))->timeline_out -= new_values.at(i);
|
||||
break;
|
||||
case TA_ADD_CLIP_IN:
|
||||
sequences.at(i)->get_clip(clips.at(i))->clip_in -= new_values.at(i);
|
||||
break;
|
||||
case TA_ADD_TRACK:
|
||||
sequences.at(i)->get_clip(clips.at(i))->track -= new_values.at(i);
|
||||
break;
|
||||
case TA_ADD_EFFECT:
|
||||
{
|
||||
Clip* c = sequences.at(i)->get_clip(clips.at(i));
|
||||
Effect* effect = c->effects.at(old_values.at(i));
|
||||
c->effects.removeAt(old_values.at(i));
|
||||
delete effect;
|
||||
}
|
||||
break;
|
||||
case TA_ADD_TRANSITION:
|
||||
{
|
||||
Clip* c = sequences.at(i)->get_clip(clips.at(i));
|
||||
if (transition_types.at(i) == TA_OPENING_TRANSITION) {
|
||||
delete c->opening_transition;
|
||||
c->opening_transition = NULL;
|
||||
} else {
|
||||
delete c->closing_transition;
|
||||
c->closing_transition = NULL;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case TA_MODIFY_TRANSITION:
|
||||
{
|
||||
Clip* c = sequences.at(i)->get_clip(clips.at(i));
|
||||
if (transition_types.at(i) == TA_OPENING_TRANSITION) {
|
||||
c->opening_transition->length = old_values.at(i);
|
||||
} else {
|
||||
c->closing_transition->length = old_values.at(i);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case TA_DELETE_TRANSITION:
|
||||
{
|
||||
Clip* c = sequences.at(i)->get_clip(clips.at(i));
|
||||
if (transition_types.at(i) == TA_OPENING_TRANSITION) {
|
||||
c->opening_transition = create_transition(new_values.at(i), c);
|
||||
c->opening_transition->length = old_values.at(i);
|
||||
} else {
|
||||
c->closing_transition = create_transition(new_values.at(i), c);
|
||||
c->closing_transition->length = old_values.at(i);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// remove added sequences
|
||||
for (int i=0;i<new_sequence_items.size();i++) {
|
||||
if (new_sequence_parents.at(i) == NULL) {
|
||||
panel_project->source_table->takeTopLevelItem(panel_project->source_table->indexOfTopLevelItem(new_sequence_items.at(i)));
|
||||
} else {
|
||||
new_sequence_parents.at(i)->removeChild(new_sequence_items.at(i));
|
||||
}
|
||||
}
|
||||
|
||||
// restore link references to deleted clips
|
||||
for (int i=0;i<removed_link_to.size();i++) {
|
||||
removed_link_from_sequence.at(i)->get_clip(removed_link_from.at(i))->linked.append(removed_link_to.at(i));
|
||||
}
|
||||
|
||||
// delete added clips
|
||||
int delete_count = 0;
|
||||
for (int i=0;i<clips_to_add.size();i++) {
|
||||
sequence_to_add_clips_to.at(i)->destroy_clip(added_indexes.at(i)-delete_count, true);
|
||||
delete_count++;
|
||||
}
|
||||
|
||||
// remove any added media
|
||||
for (int i=0;i<media_to_add.size();i++) {
|
||||
if (media_to_add_parents.at(i) == NULL) {
|
||||
panel_project->source_table->takeTopLevelItem(panel_project->source_table->indexOfTopLevelItem(media_to_add.at(i)));
|
||||
} else {
|
||||
media_to_add_parents.at(i)->removeChild(media_to_add.at(i));
|
||||
}
|
||||
}
|
||||
|
||||
// un-change workarea
|
||||
if (change_in_out) {
|
||||
change_in_out_sequence->using_workarea = old_in_out_enabled;
|
||||
change_in_out_sequence->workarea_in = old_sequence_in;
|
||||
change_in_out_sequence->workarea_out = old_sequence_out;
|
||||
}
|
||||
|
||||
// un-change current active sequence
|
||||
if (change_seq) {
|
||||
set_sequence(old_seq);
|
||||
}
|
||||
|
||||
mainWindow->setWindowModified(old_project_changed);
|
||||
|
||||
done = false;
|
||||
}
|
||||
|
||||
void TimelineAction::redo() {
|
||||
removed_link_from.clear();
|
||||
removed_link_to.clear();
|
||||
deleted_clips.clear();
|
||||
deleted_clips_indices.clear();
|
||||
deleted_clip_sequences.clear();
|
||||
added_indexes.clear();
|
||||
deleted_media_parents.clear();
|
||||
removed_link_from_sequence.clear();
|
||||
rippled_clips.clear();
|
||||
|
||||
for (int i=0;i<new_sequence_items.size();i++) {
|
||||
if (new_sequence_parents.at(i) == NULL) {
|
||||
panel_project->source_table->addTopLevelItem(new_sequence_items.at(i));
|
||||
} else {
|
||||
new_sequence_parents.at(i)->addChild(new_sequence_items.at(i));
|
||||
}
|
||||
}
|
||||
|
||||
// add any new clips
|
||||
if (clips_to_add.size() > 0) {
|
||||
QVector<Clip*> copies;
|
||||
for (int i=0;i<clips_to_add.size();i++) {
|
||||
Clip* original = clips_to_add.at(i);
|
||||
Clip* copy = original->copy(sequence_to_add_clips_to.at(i));
|
||||
copy->linked.resize(original->linked.size());
|
||||
for (int j=0;j<original->linked.size();j++) {
|
||||
copy->linked[j] = original->linked.at(j) + sequence_to_add_clips_to.at(i)->clip_count();
|
||||
}
|
||||
copies.append(copy);
|
||||
}
|
||||
for (int i=0;i<clips_to_add.size();i++) {
|
||||
added_indexes.append(sequence_to_add_clips_to.at(i)->add_clip(copies.at(i)));
|
||||
}
|
||||
}
|
||||
|
||||
for (int i=0;i<actions.size();i++) {
|
||||
switch (actions.at(i)) {
|
||||
case TA_IN:
|
||||
{
|
||||
sequences.at(i)->get_clip(clips.at(i))->timeline_in = new_values.at(i);
|
||||
}
|
||||
break;
|
||||
case TA_OUT:
|
||||
{
|
||||
sequences.at(i)->get_clip(clips.at(i))->timeline_out = new_values.at(i);
|
||||
}
|
||||
break;
|
||||
case TA_CLIP_IN:
|
||||
{
|
||||
sequences.at(i)->get_clip(clips.at(i))->clip_in = new_values.at(i);
|
||||
}
|
||||
break;
|
||||
case TA_TRACK:
|
||||
{
|
||||
sequences.at(i)->get_clip(clips.at(i))->track = new_values.at(i);
|
||||
}
|
||||
break;
|
||||
case TA_DELETE:
|
||||
{
|
||||
new_values[i] = deleted_clips.size();
|
||||
deleted_clips.append(sequences.at(i)->get_clip(clips.at(i)));
|
||||
deleted_clips_indices.append(clips.at(i));
|
||||
deleted_clip_sequences.append(sequences.at(i));
|
||||
sequences.at(i)->replace_clip(clips.at(i), NULL);
|
||||
}
|
||||
break;
|
||||
case TA_ADD_IN:
|
||||
{
|
||||
sequences.at(i)->get_clip(clips.at(i))->timeline_in += new_values.at(i);
|
||||
}
|
||||
break;
|
||||
case TA_ADD_OUT:
|
||||
{
|
||||
sequences.at(i)->get_clip(clips.at(i))->timeline_out += new_values.at(i);
|
||||
}
|
||||
break;
|
||||
case TA_ADD_CLIP_IN:
|
||||
{
|
||||
sequences.at(i)->get_clip(clips.at(i))->clip_in += new_values.at(i);
|
||||
}
|
||||
break;
|
||||
case TA_ADD_TRACK:
|
||||
{
|
||||
sequences.at(i)->get_clip(clips.at(i))->track += new_values.at(i);
|
||||
}
|
||||
break;
|
||||
case TA_ADD_EFFECT:
|
||||
{
|
||||
Clip* c = sequences.at(i)->get_clip(clips.at(i));
|
||||
old_values[i] = c->effects.size();
|
||||
Effect* e = create_effect(new_values.at(i), c);
|
||||
c->effects.append(e);
|
||||
}
|
||||
break;
|
||||
case TA_ADD_TRANSITION:
|
||||
{
|
||||
Clip* c = sequences.at(i)->get_clip(clips.at(i));
|
||||
if (transition_types.at(i) == TA_OPENING_TRANSITION) {
|
||||
c->opening_transition = create_transition(new_values.at(i), c);
|
||||
} else {
|
||||
c->closing_transition = create_transition(new_values.at(i), c);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case TA_MODIFY_TRANSITION:
|
||||
{
|
||||
Clip* c = sequences.at(i)->get_clip(clips.at(i));
|
||||
if (transition_types.at(i) == TA_OPENING_TRANSITION) {
|
||||
old_values[i] = c->opening_transition->length;
|
||||
c->opening_transition->length = new_values.at(i);
|
||||
} else {
|
||||
old_values[i] = c->closing_transition->length;
|
||||
c->closing_transition->length = new_values.at(i);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case TA_DELETE_TRANSITION:
|
||||
{
|
||||
Clip* c = sequences.at(i)->get_clip(clips.at(i));
|
||||
if (transition_types.at(i) == TA_OPENING_TRANSITION) {
|
||||
new_values[i] = c->opening_transition->id;
|
||||
old_values[i] = c->opening_transition->length;
|
||||
delete c->opening_transition;
|
||||
c->opening_transition = NULL;
|
||||
} else {
|
||||
new_values[i] = c->closing_transition->id;
|
||||
old_values[i] = c->closing_transition->length;
|
||||
delete c->closing_transition;
|
||||
c->closing_transition = NULL;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// remove any potential link references from deleted clips
|
||||
for (int i=0;i<deleted_clips_indices.size();i++) {
|
||||
Sequence* s = deleted_clip_sequences.at(i);
|
||||
for (int j=0;j<s->clip_count();j++) {
|
||||
Clip* c = s->get_clip(j);
|
||||
if (c != NULL) {
|
||||
for (int k=0;k<c->linked.size();k++) {
|
||||
if (c->linked.at(k) == deleted_clips_indices.at(i)) {
|
||||
removed_link_from_sequence.append(s);
|
||||
removed_link_from.append(j);
|
||||
removed_link_to.append(deleted_clips_indices.at(i));
|
||||
c->linked.removeAt(k);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ripple clips - moves all clips after a certain ripple_point by ripple_length
|
||||
if (ripple_enabled) {
|
||||
for (int j=0;j<ripple_sequence->clip_count();j++) {
|
||||
bool found = false;
|
||||
for (int i=0;i<ripple_ignores.size();i++) {
|
||||
if (ripple_ignores.at(i) == j) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!found) {
|
||||
Clip* c = ripple_sequence->get_clip(j);
|
||||
if (c != NULL && c->timeline_in >= ripple_point) {
|
||||
c->timeline_in += ripple_length;
|
||||
c->timeline_out += ripple_length;
|
||||
rippled_clips.append(j);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// delete media
|
||||
for (int i=0;i<deleted_media.size();i++) {
|
||||
QTreeWidgetItem* item = deleted_media.at(i);
|
||||
deleted_media_parents.append(item->parent());
|
||||
|
||||
// if we're deleting the open sequence, close it
|
||||
if (get_type_from_tree(item) == MEDIA_TYPE_SEQUENCE &&
|
||||
get_sequence_from_tree(item) == sequence &&
|
||||
!change_seq) {
|
||||
old_seq = sequence;
|
||||
new_seq = NULL;
|
||||
change_seq = true;
|
||||
}
|
||||
|
||||
if (item->parent() == NULL) {
|
||||
panel_project->source_table->takeTopLevelItem(panel_project->source_table->indexOfTopLevelItem(item));
|
||||
} else {
|
||||
item->parent()->removeChild(item);
|
||||
}
|
||||
}
|
||||
|
||||
// add any new media
|
||||
for (int i=0;i<media_to_add.size();i++) {
|
||||
if (media_to_add_parents.at(i) == NULL) {
|
||||
panel_project->source_table->addTopLevelItem(media_to_add.at(i));
|
||||
} else {
|
||||
media_to_add_parents.at(i)->addChild(media_to_add.at(i));
|
||||
}
|
||||
}
|
||||
|
||||
// change sequence workarea
|
||||
if (change_in_out) {
|
||||
change_in_out_sequence->using_workarea = new_in_out_enabled;
|
||||
change_in_out_sequence->workarea_in = new_sequence_in;
|
||||
change_in_out_sequence->workarea_out = new_sequence_out;
|
||||
}
|
||||
|
||||
// change current sequence
|
||||
if (change_seq) {
|
||||
old_seq = sequence;
|
||||
set_sequence(new_seq);
|
||||
}
|
||||
|
||||
mainWindow->setWindowModified(true);
|
||||
|
||||
done = true;
|
||||
}*/
|
||||
|
||||
LinkCommand::LinkCommand() : link(true), old_project_changed(mainWindow->isWindowModified()) {}
|
||||
|
||||
void LinkCommand::undo() {
|
||||
|
||||
+3
-6
@@ -22,10 +22,6 @@ struct EffectMeta;
|
||||
#include <QVector>
|
||||
#include <QVariant>
|
||||
|
||||
#define TA_NO_TRANSITION 0
|
||||
#define TA_OPENING_TRANSITION 1
|
||||
#define TA_CLOSING_TRANSITION 2
|
||||
|
||||
extern QUndoStack undo_stack;
|
||||
|
||||
class ComboAction : public QUndoCommand {
|
||||
@@ -105,7 +101,7 @@ private:
|
||||
|
||||
class AddTransitionCommand : public QUndoCommand {
|
||||
public:
|
||||
AddTransitionCommand(Clip* c, const EffectMeta* itransition, int itype, int ilength);
|
||||
AddTransitionCommand(Clip* c, const EffectMeta* itransition, int itype, int ilength);
|
||||
void undo();
|
||||
void redo();
|
||||
private:
|
||||
@@ -138,7 +134,8 @@ public:
|
||||
private:
|
||||
Clip* clip;
|
||||
int type;
|
||||
Effect* transition;
|
||||
Transition* transition;
|
||||
int old_index;
|
||||
bool old_project_changed;
|
||||
};
|
||||
|
||||
|
||||
+52
-51
@@ -4,6 +4,7 @@
|
||||
#include "panels/panels.h"
|
||||
#include "io/config.h"
|
||||
#include "project/sequence.h"
|
||||
#include "project/transition.h"
|
||||
#include "project/clip.h"
|
||||
#include "panels/project.h"
|
||||
#include "panels/timeline.h"
|
||||
@@ -604,11 +605,11 @@ void TimelineWidget::mousePressEvent(QMouseEvent *event) {
|
||||
|
||||
Selection s;
|
||||
s.track = clip->track;
|
||||
if (panel_timeline->transition_select == TA_OPENING_TRANSITION && clip->opening_transition != NULL) {
|
||||
if (panel_timeline->transition_select == TA_OPENING_TRANSITION && clip->get_opening_transition() != NULL) {
|
||||
s.in = clip->timeline_in;
|
||||
s.out = clip->timeline_in + clip->opening_transition->length;
|
||||
} else if (panel_timeline->transition_select == TA_CLOSING_TRANSITION && clip->closing_transition != NULL) {
|
||||
s.in = clip->timeline_out - clip->closing_transition->length;
|
||||
s.out = clip->timeline_in + clip->get_opening_transition()->length;
|
||||
} else if (panel_timeline->transition_select == TA_CLOSING_TRANSITION && clip->get_closing_transition() != NULL) {
|
||||
s.in = clip->timeline_out - clip->get_closing_transition()->length;
|
||||
s.out = clip->timeline_out;
|
||||
}
|
||||
sequence->selections.append(s);
|
||||
@@ -626,11 +627,11 @@ void TimelineWidget::mousePressEvent(QMouseEvent *event) {
|
||||
s.out = clip->timeline_out;
|
||||
|
||||
if (panel_timeline->transition_select == TA_OPENING_TRANSITION) {
|
||||
s.out = clip->timeline_in + clip->opening_transition->length;
|
||||
s.out = clip->timeline_in + clip->get_opening_transition()->length;
|
||||
}
|
||||
|
||||
if (panel_timeline->transition_select == TA_CLOSING_TRANSITION) {
|
||||
s.in = clip->timeline_out - clip->closing_transition->length;
|
||||
s.in = clip->timeline_out - clip->get_closing_transition()->length;
|
||||
}
|
||||
|
||||
s.track = clip->track;
|
||||
@@ -695,24 +696,24 @@ void TimelineWidget::mousePressEvent(QMouseEvent *event) {
|
||||
void make_room_for_transition(ComboAction* ca, Clip* c, int type, long transition_start, long transition_end) {
|
||||
// make room for transition
|
||||
if (type == TA_OPENING_TRANSITION) {
|
||||
if (c->opening_transition != NULL) {
|
||||
if (c->get_opening_transition() != NULL) {
|
||||
ca->append(new DeleteTransitionCommand(c, TA_OPENING_TRANSITION));
|
||||
}
|
||||
if (c->closing_transition != NULL) {
|
||||
if (c->get_closing_transition() != NULL) {
|
||||
if (transition_end >= c->timeline_out) {
|
||||
ca->append(new DeleteTransitionCommand(c, TA_CLOSING_TRANSITION));
|
||||
} else if (transition_end > c->timeline_out - c->closing_transition->length) {
|
||||
} else if (transition_end > c->timeline_out - c->get_closing_transition()->length) {
|
||||
ca->append(new ModifyTransitionCommand(c, TA_CLOSING_TRANSITION, c->timeline_out - transition_end));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (c->closing_transition != NULL) {
|
||||
if (c->get_closing_transition() != NULL) {
|
||||
ca->append(new DeleteTransitionCommand(c, TA_CLOSING_TRANSITION));
|
||||
}
|
||||
if (c->opening_transition != NULL) {
|
||||
if (c->get_opening_transition() != NULL) {
|
||||
if (transition_start <= c->timeline_in) {
|
||||
ca->append(new DeleteTransitionCommand(c, TA_OPENING_TRANSITION));
|
||||
} else if (transition_start < c->timeline_in + c->opening_transition->length) {
|
||||
} else if (transition_start < c->timeline_in + c->get_opening_transition()->length) {
|
||||
ca->append(new ModifyTransitionCommand(c, TA_OPENING_TRANSITION, transition_start - c->timeline_in));
|
||||
}
|
||||
}
|
||||
@@ -923,30 +924,30 @@ void TimelineWidget::mouseReleaseEvent(QMouseEvent *event) {
|
||||
|
||||
// adjust transitions if we need to
|
||||
long new_clip_length = (g.out - g.in);
|
||||
if (c->opening_transition != NULL) {
|
||||
if (c->get_opening_transition() != NULL) {
|
||||
long max_open_length = new_clip_length;
|
||||
if (c->closing_transition != NULL && !panel_timeline->trim_in_point) {
|
||||
max_open_length -= c->closing_transition->length;
|
||||
if (c->get_closing_transition() != NULL && !panel_timeline->trim_in_point) {
|
||||
max_open_length -= c->get_closing_transition()->length;
|
||||
}
|
||||
if (max_open_length <= 0) {
|
||||
ca->append(new DeleteTransitionCommand(c, TA_OPENING_TRANSITION));
|
||||
} else if (c->opening_transition->length > max_open_length) {
|
||||
} else if (c->get_opening_transition()->length > max_open_length) {
|
||||
ca->append(new ModifyTransitionCommand(c, TA_OPENING_TRANSITION, max_open_length));
|
||||
}
|
||||
}
|
||||
if (c->closing_transition != NULL) {
|
||||
if (c->get_closing_transition() != NULL) {
|
||||
long max_open_length = new_clip_length;
|
||||
if (c->opening_transition != NULL && panel_timeline->trim_in_point) {
|
||||
max_open_length -= c->opening_transition->length;
|
||||
if (c->get_opening_transition() != NULL && panel_timeline->trim_in_point) {
|
||||
max_open_length -= c->get_opening_transition()->length;
|
||||
}
|
||||
if (max_open_length <= 0) {
|
||||
ca->append(new DeleteTransitionCommand(c, TA_CLOSING_TRANSITION));
|
||||
} else if (c->closing_transition->length > max_open_length) {
|
||||
} else if (c->get_closing_transition()->length > max_open_length) {
|
||||
ca->append(new ModifyTransitionCommand(c, TA_CLOSING_TRANSITION, max_open_length));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
bool is_opening_transition = (g.transition == c->opening_transition);
|
||||
bool is_opening_transition = (g.transition == c->get_opening_transition());
|
||||
long new_transition_length = g.out - g.in;
|
||||
ca->append(new ModifyTransitionCommand(c, is_opening_transition ? TA_OPENING_TRANSITION : TA_CLOSING_TRANSITION, new_transition_length));
|
||||
|
||||
@@ -958,10 +959,10 @@ void TimelineWidget::mouseReleaseEvent(QMouseEvent *event) {
|
||||
clip_length -= (g.in - g.old_in);
|
||||
}
|
||||
|
||||
if (c->closing_transition != NULL) {
|
||||
if (c->get_closing_transition() != NULL) {
|
||||
if (new_transition_length == clip_length) {
|
||||
ca->append(new DeleteTransitionCommand(c, TA_CLOSING_TRANSITION));
|
||||
} else if (new_transition_length > clip_length - c->closing_transition->length) {
|
||||
} else if (new_transition_length > clip_length - c->get_closing_transition()->length) {
|
||||
ca->append(new ModifyTransitionCommand(c, TA_CLOSING_TRANSITION, clip_length - new_transition_length));
|
||||
}
|
||||
}
|
||||
@@ -972,10 +973,10 @@ void TimelineWidget::mouseReleaseEvent(QMouseEvent *event) {
|
||||
clip_length += (g.out - g.old_out);
|
||||
}
|
||||
|
||||
if (c->opening_transition != NULL) {
|
||||
if (c->get_opening_transition() != NULL) {
|
||||
if (new_transition_length == clip_length) {
|
||||
ca->append(new DeleteTransitionCommand(c, TA_OPENING_TRANSITION));
|
||||
} else if (new_transition_length > clip_length - c->opening_transition->length) {
|
||||
} else if (new_transition_length > clip_length - c->get_opening_transition()->length) {
|
||||
ca->append(new ModifyTransitionCommand(c, TA_OPENING_TRANSITION, clip_length - new_transition_length));
|
||||
}
|
||||
}
|
||||
@@ -1106,15 +1107,15 @@ void TimelineWidget::init_ghosts() {
|
||||
g.in = g.old_in = c->timeline_in;
|
||||
g.out = g.old_out = c->timeline_out;
|
||||
g.ghost_length = g.old_out - g.old_in;
|
||||
} else if (g.transition == c->opening_transition) {
|
||||
} else if (g.transition == c->get_opening_transition()) {
|
||||
g.in = g.old_in = c->timeline_in;
|
||||
g.out = g.old_out = c->timeline_in + c->opening_transition->length;
|
||||
g.ghost_length = c->opening_transition->length;
|
||||
} else if (g.transition == c->closing_transition) {
|
||||
g.in = g.old_in = c->timeline_out - c->closing_transition->length;
|
||||
g.out = g.old_out = c->timeline_in + c->get_opening_transition()->length;
|
||||
g.ghost_length = c->get_opening_transition()->length;
|
||||
} else if (g.transition == c->get_closing_transition()) {
|
||||
g.in = g.old_in = c->timeline_out - c->get_closing_transition()->length;
|
||||
g.out = g.old_out = c->timeline_out;
|
||||
g.ghost_length = c->closing_transition->length;
|
||||
g.clip_in = g.old_clip_in = c->clip_in + c->getLength() - c->closing_transition->length;
|
||||
g.ghost_length = c->get_closing_transition()->length;
|
||||
g.clip_in = g.old_clip_in = c->clip_in + c->getLength() - c->get_closing_transition()->length;
|
||||
}
|
||||
|
||||
// used for trim ops
|
||||
@@ -1354,7 +1355,7 @@ void TimelineWidget::update_ghosts(const QPoint& mouse_pos, bool lock_frame) {
|
||||
g.in = g.old_in + frame_diff;
|
||||
g.out = g.old_out + frame_diff;
|
||||
|
||||
if (g.transition != NULL && g.transition == sequence->clips.at(g.clip)->opening_transition) {
|
||||
if (g.transition != NULL && g.transition == sequence->clips.at(g.clip)->get_opening_transition()) {
|
||||
g.clip_in = g.old_clip_in + frame_diff;
|
||||
}
|
||||
|
||||
@@ -1544,21 +1545,21 @@ void TimelineWidget::mouseMoveEvent(QMouseEvent *event) {
|
||||
bool add = panel_timeline->is_clip_selected(c, true);
|
||||
|
||||
// if a whole clip is not selected, maybe just a transition is
|
||||
if (!add && panel_timeline->tool == TIMELINE_TOOL_POINTER && (c->opening_transition != NULL || c->closing_transition != NULL)) {
|
||||
if (!add && panel_timeline->tool == TIMELINE_TOOL_POINTER && (c->get_opening_transition() != NULL || c->get_closing_transition() != NULL)) {
|
||||
// check if any selections contain the whole clip or transition
|
||||
for (int j=0;j<sequence->selections.size();j++) {
|
||||
const Selection& s = sequence->selections.at(j);
|
||||
if (s.track == c->track) {
|
||||
if (c->opening_transition != NULL
|
||||
if (c->get_opening_transition() != NULL
|
||||
&& s.in == c->timeline_in
|
||||
&& s.out == c->timeline_in + c->opening_transition->length) {
|
||||
g.transition = c->opening_transition;
|
||||
&& s.out == c->timeline_in + c->get_opening_transition()->length) {
|
||||
g.transition = c->get_opening_transition();
|
||||
add = true;
|
||||
break;
|
||||
} else if (c->closing_transition != NULL
|
||||
&& s.in == c->timeline_out - c->closing_transition->length
|
||||
} else if (c->get_closing_transition() != NULL
|
||||
&& s.in == c->timeline_out - c->get_closing_transition()->length
|
||||
&& s.out == c->timeline_out) {
|
||||
g.transition = c->closing_transition;
|
||||
g.transition = c->get_closing_transition();
|
||||
add = true;
|
||||
break;
|
||||
}
|
||||
@@ -1844,9 +1845,9 @@ void TimelineWidget::mouseMoveEvent(QMouseEvent *event) {
|
||||
tooltip_timer.start();
|
||||
tooltip_clip = i;
|
||||
|
||||
if (c->opening_transition != NULL && panel_timeline->cursor_frame <= c->timeline_in + c->opening_transition->length) {
|
||||
if (c->get_opening_transition() != NULL && panel_timeline->cursor_frame <= c->timeline_in + c->get_opening_transition()->length) {
|
||||
panel_timeline->transition_select = TA_OPENING_TRANSITION;
|
||||
} else if (c->closing_transition != NULL && panel_timeline->cursor_frame >= c->timeline_out - c->closing_transition->length) {
|
||||
} else if (c->get_closing_transition() != NULL && panel_timeline->cursor_frame >= c->timeline_out - c->get_closing_transition()->length) {
|
||||
panel_timeline->transition_select = TA_CLOSING_TRANSITION;
|
||||
}
|
||||
}
|
||||
@@ -1869,8 +1870,8 @@ void TimelineWidget::mouseMoveEvent(QMouseEvent *event) {
|
||||
}
|
||||
}
|
||||
if (panel_timeline->tool == TIMELINE_TOOL_POINTER) {
|
||||
if (c->opening_transition != NULL) {
|
||||
long transition_point = c->timeline_in + c->opening_transition->length;
|
||||
if (c->get_opening_transition() != NULL) {
|
||||
long transition_point = c->timeline_in + c->get_opening_transition()->length;
|
||||
|
||||
if (transition_point > mouse_frame_lower && transition_point < mouse_frame_upper) {
|
||||
int nc = qAbs(transition_point - 1 - panel_timeline->cursor_frame);
|
||||
@@ -1883,8 +1884,8 @@ void TimelineWidget::mouseMoveEvent(QMouseEvent *event) {
|
||||
}
|
||||
}
|
||||
}
|
||||
if (c->closing_transition != NULL) {
|
||||
long transition_point = c->timeline_out - c->closing_transition->length;
|
||||
if (c->get_closing_transition() != NULL) {
|
||||
long transition_point = c->timeline_out - c->get_closing_transition()->length;
|
||||
if (transition_point > mouse_frame_lower && transition_point < mouse_frame_upper) {
|
||||
int nc = qAbs(transition_point + 1 - panel_timeline->cursor_frame);
|
||||
if (nc < closeness) {
|
||||
@@ -2133,13 +2134,13 @@ void TimelineWidget::paintEvent(QPaintEvent*) {
|
||||
int thumb_y = p.fontMetrics().height()+CLIP_TEXT_PADDING+CLIP_TEXT_PADDING;
|
||||
if (thumb_x < width() && thumb_y < height()) {
|
||||
int space_for_thumb = clip_rect.width()-1;
|
||||
if (clip->opening_transition != NULL) {
|
||||
int ot_width = getScreenPointFromFrame(panel_timeline->zoom, clip->opening_transition->length);
|
||||
if (clip->get_opening_transition() != NULL) {
|
||||
int ot_width = getScreenPointFromFrame(panel_timeline->zoom, clip->get_opening_transition()->length);
|
||||
thumb_x += ot_width;
|
||||
space_for_thumb -= ot_width;
|
||||
}
|
||||
if (clip->closing_transition != NULL) {
|
||||
space_for_thumb -= getScreenPointFromFrame(panel_timeline->zoom, clip->closing_transition->length);
|
||||
if (clip->get_closing_transition() != NULL) {
|
||||
space_for_thumb -= getScreenPointFromFrame(panel_timeline->zoom, clip->get_closing_transition()->length);
|
||||
}
|
||||
int thumb_height = clip_rect.height()-thumb_y;
|
||||
int thumb_width = (thumb_height*((double)ms->video_preview.width()/(double)ms->video_preview.height()));
|
||||
@@ -2203,7 +2204,7 @@ void TimelineWidget::paintEvent(QPaintEvent*) {
|
||||
|
||||
// draw clip transitions
|
||||
for (int i=0;i<2;i++) {
|
||||
Effect* t = (i == 0) ? clip->opening_transition : clip->closing_transition;
|
||||
Transition* t = (i == 0) ? clip->get_opening_transition() : clip->get_closing_transition();
|
||||
if (t != NULL) {
|
||||
int transition_width = getScreenPointFromFrame(panel_timeline->zoom, t->length);
|
||||
int transition_height = clip_rect.height();
|
||||
|
||||
+9
-7
@@ -5,7 +5,9 @@
|
||||
#include "panels/timeline.h"
|
||||
#include "panels/project.h"
|
||||
#include "project/sequence.h"
|
||||
#include "project/clip.h"
|
||||
#include "project/effect.h"
|
||||
#include "project/transition.h"
|
||||
#include "playback/playback.h"
|
||||
#include "playback/audio.h"
|
||||
#include "io/media.h"
|
||||
@@ -451,18 +453,18 @@ GLuint ViewerWidget::compose_sequence(QVector<Clip*>& nests, bool render_audio)
|
||||
process_effect(c, c->effects.at(j), timecode, coords, composite_texture, fbo_switcher);
|
||||
}
|
||||
|
||||
if (c->opening_transition != NULL) {
|
||||
if (c->get_opening_transition() != NULL) {
|
||||
int transition_progress = playhead - c->timeline_in;
|
||||
if (transition_progress < c->opening_transition->length) {
|
||||
process_effect(c, c->opening_transition, (double)transition_progress/(double)c->opening_transition->length, coords, composite_texture, fbo_switcher);
|
||||
if (transition_progress < c->get_opening_transition()->length) {
|
||||
process_effect(c, c->get_opening_transition(), (double)transition_progress/(double)c->get_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) {
|
||||
process_effect(c, c->closing_transition, (double)transition_progress/(double)c->closing_transition->length, coords, composite_texture, fbo_switcher);
|
||||
if (c->get_closing_transition() != NULL) {
|
||||
int transition_progress = c->get_closing_transition()->length - (playhead - c->timeline_in - c->getLength() + c->get_closing_transition()->length);
|
||||
if (transition_progress < c->get_closing_transition()->length) {
|
||||
process_effect(c, c->get_closing_transition(), (double)transition_progress/(double)c->get_closing_transition()->length, coords, composite_texture, fbo_switcher);
|
||||
//c->closing_transition->process_transition((double)transition_progress/(double)c->closing_transition->length);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user