better ]shared transitions, dock tabs, effects panel name
This commit is contained in:
@@ -49,7 +49,7 @@ CornerPinEffect::CornerPinEffect(Clip *c, const EffectMeta *em) : Effect(c, em)
|
||||
fragPath = "cornerpin.frag";
|
||||
}
|
||||
|
||||
void CornerPinEffect::process_coords(double timecode, GLTextureCoords &coords) {
|
||||
void CornerPinEffect::process_coords(double timecode, GLTextureCoords &coords, int data) {
|
||||
coords.vertexTopLeftX += top_left_x->get_double_value(timecode);
|
||||
coords.vertexTopLeftY += top_left_y->get_double_value(timecode);
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@ class CornerPinEffect : public Effect {
|
||||
Q_OBJECT
|
||||
public:
|
||||
CornerPinEffect(Clip* c, const EffectMeta* em);
|
||||
void process_coords(double timecode, GLTextureCoords& coords);
|
||||
void process_coords(double timecode, GLTextureCoords& coords, int data);
|
||||
void process_shader(double timecode, GLTextureCoords& coords);
|
||||
private:
|
||||
EffectField* top_left_x;
|
||||
|
||||
@@ -6,8 +6,10 @@ CrossDissolveTransition::CrossDissolveTransition(Clip* c, Clip* s, const EffectM
|
||||
enable_coords = true;
|
||||
}
|
||||
|
||||
void CrossDissolveTransition::process_coords(double progress, GLTextureCoords&) {
|
||||
float color[4];
|
||||
glGetFloatv(GL_CURRENT_COLOR, color);
|
||||
glColor4f(1.0, 1.0, 1.0, color[3]*progress);
|
||||
void CrossDissolveTransition::process_coords(double progress, GLTextureCoords&, int data) {
|
||||
if (!(data == TA_CLOSING_TRANSITION && secondary_clip != NULL)) {
|
||||
float color[4];
|
||||
glGetFloatv(GL_CURRENT_COLOR, color);
|
||||
glColor4f(1.0, 1.0, 1.0, color[3]*progress);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
class CrossDissolveTransition : public Transition {
|
||||
public:
|
||||
CrossDissolveTransition(Clip* c, Clip* s, const EffectMeta* em);
|
||||
void process_coords(double timecode, GLTextureCoords &);
|
||||
void process_coords(double timecode, GLTextureCoords &, int data);
|
||||
};
|
||||
|
||||
#endif // CROSSDISSOLVETRANSITION_H
|
||||
|
||||
@@ -21,12 +21,10 @@ void ExponentialFadeTransition::process_audio(double timecode_start, double time
|
||||
break;
|
||||
}*/
|
||||
switch (type) {
|
||||
case TRAN_TYPE_OPEN:
|
||||
case TRAN_TYPE_OPENWLINK:
|
||||
case TA_OPENING_TRANSITION:
|
||||
samp *= qPow(timecode_start + (interval * i), 2);
|
||||
break;
|
||||
case TRAN_TYPE_CLOSE:
|
||||
case TRAN_TYPE_CLOSEWLINK:
|
||||
case TA_CLOSING_TRANSITION:
|
||||
samp *= qPow(1 - (timecode_start + (interval * i)), 2);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -9,12 +9,10 @@ void LinearFadeTransition::process_audio(double timecode_start, double timecode_
|
||||
qint16 samp = (qint16) (((samples[i+1] & 0xFF) << 8) | (samples[i] & 0xFF));
|
||||
|
||||
switch (type) {
|
||||
case TRAN_TYPE_OPEN:
|
||||
case TRAN_TYPE_OPENWLINK:
|
||||
case TA_OPENING_TRANSITION:
|
||||
samp *= timecode_start + (interval * i);
|
||||
break;
|
||||
case TRAN_TYPE_CLOSE:
|
||||
case TRAN_TYPE_CLOSEWLINK:
|
||||
case TA_CLOSING_TRANSITION:
|
||||
samp *= 1 - (timecode_start + (interval * i));
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -11,12 +11,10 @@ void LogarithmicFadeTransition::process_audio(double timecode_start, double time
|
||||
qint16 samp = (qint16) (((samples[i+1] & 0xFF) << 8) | (samples[i] & 0xFF));
|
||||
|
||||
switch (type) {
|
||||
case TRAN_TYPE_OPEN:
|
||||
case TRAN_TYPE_OPENWLINK:
|
||||
case TA_OPENING_TRANSITION:
|
||||
samp *= qSqrt(timecode_start + (interval * i));
|
||||
break;
|
||||
case TRAN_TYPE_CLOSE:
|
||||
case TRAN_TYPE_CLOSEWLINK:
|
||||
case TA_CLOSING_TRANSITION:
|
||||
samp *= qSqrt(1 - (timecode_start + (interval * i)));
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -47,7 +47,7 @@ ShakeEffect::ShakeEffect(Clip *c, const EffectMeta *em) : Effect(c, em) {
|
||||
connect(frequency_val, SIGNAL(changed()), this, SLOT(field_changed()));
|
||||
}
|
||||
|
||||
void ShakeEffect::process_coords(double timecode, GLTextureCoords& coords) {
|
||||
void ShakeEffect::process_coords(double timecode, GLTextureCoords& coords, int data) {
|
||||
int lim = RANDOM_VAL_SIZE/6;
|
||||
|
||||
double multiplier = intensity_val->get_double_value(timecode)/lim;
|
||||
|
||||
@@ -9,7 +9,7 @@ class ShakeEffect : public Effect {
|
||||
Q_OBJECT
|
||||
public:
|
||||
ShakeEffect(Clip* c, const EffectMeta* em);
|
||||
void process_coords(double timecode, GLTextureCoords& coords);
|
||||
void process_coords(double timecode, GLTextureCoords& coords, int data);
|
||||
|
||||
EffectField* intensity_val;
|
||||
EffectField* rotation_val;
|
||||
|
||||
@@ -114,7 +114,7 @@ void TransformEffect::toggle_uniform_scale(bool enabled) {
|
||||
scale_y->set_enabled(!enabled);
|
||||
}
|
||||
|
||||
void TransformEffect::process_coords(double timecode, GLTextureCoords& coords) {
|
||||
void TransformEffect::process_coords(double timecode, GLTextureCoords& coords, int data) {
|
||||
// position
|
||||
glTranslatef(position_x->get_double_value(timecode)-(parent_clip->sequence->width/2), position_y->get_double_value(timecode)-(parent_clip->sequence->height/2), 0);
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@ class TransformEffect : public Effect {
|
||||
public:
|
||||
TransformEffect(Clip* c, const EffectMeta* em);
|
||||
void refresh();
|
||||
void process_coords(double timecode, GLTextureCoords& coords);
|
||||
void process_coords(double timecode, GLTextureCoords& coords, int data);
|
||||
|
||||
EffectField* position_x;
|
||||
EffectField* position_y;
|
||||
|
||||
@@ -119,6 +119,8 @@ MainWindow::MainWindow(QWidget *parent) :
|
||||
// end style
|
||||
ui->setupUi(this);
|
||||
|
||||
setTabPosition(Qt::AllDockWidgetAreas, QTabWidget::North);
|
||||
|
||||
updateTitle("");
|
||||
|
||||
statusBar()->showMessage("Welcome to " + appName);
|
||||
|
||||
@@ -23,7 +23,8 @@ EffectControls::EffectControls(QWidget *parent) :
|
||||
QDockWidget(parent),
|
||||
multiple(false),
|
||||
zoom(1),
|
||||
ui(new Ui::EffectControls)
|
||||
ui(new Ui::EffectControls),
|
||||
panel_name("Effects: ")
|
||||
{
|
||||
ui->setupUi(this);
|
||||
init_effects();
|
||||
@@ -34,7 +35,6 @@ EffectControls::EffectControls(QWidget *parent) :
|
||||
ui->effects_area->parent_widget = ui->scrollArea;
|
||||
ui->effects_area->keyframe_area = ui->keyframeView;
|
||||
ui->effects_area->header = ui->headers;
|
||||
|
||||
ui->keyframeView->header = ui->headers;
|
||||
|
||||
ui->label_2->setVisible(false);
|
||||
@@ -262,6 +262,7 @@ void EffectControls::clear_effects(bool clear_cache) {
|
||||
ui->headers->setVisible(false);
|
||||
ui->keyframeView->setEnabled(false);
|
||||
if (clear_cache) selected_clips.clear();
|
||||
setWindowTitle(panel_name + "(none)");
|
||||
}
|
||||
|
||||
void EffectControls::deselect_all_effects(QWidget* sender) {
|
||||
@@ -298,6 +299,7 @@ void EffectControls::load_effects() {
|
||||
}
|
||||
}
|
||||
if (selected_clips.size() > 0) {
|
||||
setWindowTitle(panel_name + sequence->clips.at(selected_clips.at(0))->name);
|
||||
ui->verticalScrollBar->setMaximum(qMax(0, ui->effects_area->sizeHint().height() - ui->headers->height() + ui->scrollArea->horizontalScrollBar()->height()/* - ui->keyframeView->height() - ui->headers->height()*/));
|
||||
ui->keyframeView->setEnabled(true);
|
||||
ui->headers->setVisible(true);
|
||||
|
||||
+1
-12
@@ -66,18 +66,7 @@ private:
|
||||
|
||||
bool video_menu;
|
||||
bool transition_menu;
|
||||
QString panel_name;
|
||||
};
|
||||
|
||||
/*class EffectAddCommand : public QUndoCommand {
|
||||
public:
|
||||
EffectAddCommand();
|
||||
~EffectAddCommand();
|
||||
void undo();
|
||||
void redo();
|
||||
QVector<Clip*> clips;
|
||||
QVector<Effect*> effects;
|
||||
private:
|
||||
bool done;
|
||||
};*/
|
||||
|
||||
#endif // EFFECTCONTROLS_H
|
||||
|
||||
+3
-7
@@ -1076,8 +1076,7 @@ bool Project::load_worker(QFile& f, QXmlStreamReader& stream, int type) {
|
||||
int effect_id = -1;
|
||||
QString effect_name;
|
||||
bool effect_enabled = true;
|
||||
long effect_pre_length = -1;
|
||||
long effect_post_length = -1;
|
||||
long effect_length = -1;
|
||||
for (int j=0;j<stream.attributes().size();j++) {
|
||||
const QXmlStreamAttribute& attr = stream.attributes().at(j);
|
||||
if (attr.name() == "id") {
|
||||
@@ -1087,9 +1086,7 @@ bool Project::load_worker(QFile& f, QXmlStreamReader& stream, int type) {
|
||||
} else if (attr.name() == "name") {
|
||||
effect_name = attr.value().toString();
|
||||
} else if (attr.name() == "length") {
|
||||
effect_pre_length = attr.value().toLong();
|
||||
} else if (attr.name() == "postlength") { // backwards compatibility
|
||||
effect_post_length = attr.value().toLong();
|
||||
effect_length = attr.value().toLong();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1139,8 +1136,7 @@ bool Project::load_worker(QFile& f, QXmlStreamReader& stream, int type) {
|
||||
|
||||
int transition_index = create_transition(c, NULL, meta);
|
||||
Transition* t = c->sequence->transitions.at(transition_index);
|
||||
if (effect_pre_length > -1) t->length = effect_pre_length;
|
||||
if (effect_post_length > -1) t->length2 = effect_post_length;
|
||||
if (effect_length > -1) t->length = effect_length;
|
||||
t->set_enabled(effect_enabled);
|
||||
t->load(stream);
|
||||
|
||||
|
||||
+2
-3
@@ -18,8 +18,6 @@
|
||||
#define FRAMES_IN_ONE_MINUTE 1798 // 1800 - 2
|
||||
#define FRAMES_IN_TEN_MINUTES 17978 // (FRAMES_IN_ONE_MINUTE * 10) - 2
|
||||
|
||||
QString panel_name = "Viewer: ";
|
||||
|
||||
extern "C" {
|
||||
#include <libavformat/avformat.h>
|
||||
#include <libavcodec/avcodec.h>
|
||||
@@ -38,7 +36,8 @@ Viewer::Viewer(QWidget *parent) :
|
||||
seq(NULL),
|
||||
ui(new Ui::Viewer),
|
||||
created_sequence(false),
|
||||
cue_recording_internal(false)
|
||||
cue_recording_internal(false),
|
||||
panel_name("Viewer: ")
|
||||
{
|
||||
ui->setupUi(this);
|
||||
ui->headers->viewer = this;
|
||||
|
||||
@@ -86,6 +86,7 @@ private:
|
||||
void set_sequence(bool main, Sequence* s);
|
||||
bool main_sequence;
|
||||
bool created_sequence;
|
||||
QString panel_name;
|
||||
|
||||
bool cue_recording_internal;
|
||||
QTimer recording_flasher;
|
||||
|
||||
+20
-19
@@ -40,7 +40,7 @@ double bytes_to_seconds(int nb_bytes, int nb_channels, int sample_rate) {
|
||||
}
|
||||
|
||||
void apply_audio_effects(Clip* c, double timecode_start, AVFrame* frame, int nb_bytes, QVector<Clip*> nests) {
|
||||
// perform all aud io effects
|
||||
// perform all audio effects
|
||||
double timecode_end;
|
||||
timecode_end = timecode_start + bytes_to_seconds(nb_bytes, frame->channels, frame->sample_rate);
|
||||
|
||||
@@ -50,25 +50,26 @@ void apply_audio_effects(Clip* c, double timecode_start, AVFrame* frame, int nb_
|
||||
}
|
||||
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->get_opening_transition()->length) / c->sequence->frame_rate;
|
||||
double transition_start = (c->get_clip_in_with_transition() / c->sequence->frame_rate);
|
||||
double transition_end = (c->get_clip_in_with_transition() + c->get_opening_transition()->get_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->get_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, TA_OPENING_TRANSITION);
|
||||
}
|
||||
}
|
||||
}
|
||||
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) {
|
||||
long length_with_transitions = c->get_timeline_out_with_transition() - c->get_timeline_in_with_transition();
|
||||
double transition_start = (c->get_clip_in_with_transition() + length_with_transitions - c->get_closing_transition()->get_length()) / c->sequence->frame_rate;
|
||||
double transition_end = (c->get_clip_in_with_transition() + length_with_transitions) / 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->get_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, TA_CLOSING_TRANSITION);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -76,33 +77,33 @@ void apply_audio_effects(Clip* c, double timecode_start, AVFrame* frame, int nb_
|
||||
if (!nests.isEmpty()) {
|
||||
Clip* next_nest = nests.last();
|
||||
nests.removeLast();
|
||||
apply_audio_effects(next_nest, timecode_start + (((double)c->timeline_in-c->clip_in)/c->sequence->frame_rate), frame, nb_bytes, nests);
|
||||
apply_audio_effects(next_nest, timecode_start + (((double)c->get_timeline_in_with_transition()-c->get_clip_in_with_transition())/c->sequence->frame_rate), frame, nb_bytes, nests);
|
||||
}
|
||||
}
|
||||
|
||||
#define AUDIO_BUFFER_PADDING 2048
|
||||
|
||||
void cache_audio_worker(Clip* c, bool scrubbing, QVector<Clip*>& nests) {
|
||||
long timeline_in = c->timeline_in;
|
||||
long timeline_out = c->timeline_out;
|
||||
long timeline_in = c->get_timeline_in_with_transition();
|
||||
long timeline_out = c->get_timeline_out_with_transition();
|
||||
long target_frame = c->audio_target_frame;
|
||||
|
||||
long frame_skip = 0;
|
||||
double last_fr = c->sequence->frame_rate;
|
||||
if (!nests.isEmpty()) {
|
||||
for (int i=nests.size()-1;i>=0;i--) {
|
||||
timeline_in = refactor_frame_number(timeline_in, last_fr, nests.at(i)->sequence->frame_rate) + nests.at(i)->timeline_in - nests.at(i)->clip_in;
|
||||
timeline_out = refactor_frame_number(timeline_out, last_fr, nests.at(i)->sequence->frame_rate) + nests.at(i)->timeline_in - nests.at(i)->clip_in;
|
||||
target_frame = refactor_frame_number(target_frame, last_fr, nests.at(i)->sequence->frame_rate) + nests.at(i)->timeline_in - nests.at(i)->clip_in;
|
||||
timeline_in = refactor_frame_number(timeline_in, last_fr, nests.at(i)->sequence->frame_rate) + nests.at(i)->get_timeline_in_with_transition() - nests.at(i)->get_clip_in_with_transition();
|
||||
timeline_out = refactor_frame_number(timeline_out, last_fr, nests.at(i)->sequence->frame_rate) + nests.at(i)->get_timeline_in_with_transition() - nests.at(i)->get_clip_in_with_transition();
|
||||
target_frame = refactor_frame_number(target_frame, last_fr, nests.at(i)->sequence->frame_rate) + nests.at(i)->get_timeline_in_with_transition() - nests.at(i)->get_clip_in_with_transition();
|
||||
|
||||
timeline_out = qMin(timeline_out, nests.at(i)->timeline_out);
|
||||
timeline_out = qMin(timeline_out, nests.at(i)->get_timeline_out_with_transition());
|
||||
|
||||
frame_skip = refactor_frame_number(frame_skip, last_fr, nests.at(i)->sequence->frame_rate);
|
||||
|
||||
long validator = nests.at(i)->timeline_in - timeline_in;
|
||||
long validator = nests.at(i)->get_timeline_in_with_transition() - timeline_in;
|
||||
if (validator > 0) {
|
||||
frame_skip += validator;
|
||||
//timeline_in = nests.at(i)->timeline_in;
|
||||
//timeline_in = nests.at(i)->get_timeline_in_with_transition();
|
||||
}
|
||||
|
||||
last_fr = nests.at(i)->sequence->frame_rate;
|
||||
@@ -120,7 +121,7 @@ void cache_audio_worker(Clip* c, bool scrubbing, QVector<Clip*>& nests) {
|
||||
|
||||
frame = c->queue.at(0);
|
||||
|
||||
// retrieve frame
|
||||
// retrieve frame
|
||||
bool new_frame = false;
|
||||
while ((c->frame_sample_index == -1 || c->frame_sample_index >= nb_bytes) && nb_bytes > 0) {
|
||||
// no more audio left in frame, get a new one
|
||||
@@ -331,7 +332,7 @@ void cache_audio_worker(Clip* c, bool scrubbing, QVector<Clip*>& nests) {
|
||||
// apply any audio effects to the data
|
||||
if (nb_bytes == INT_MAX) nb_bytes = frame->nb_samples * av_get_bytes_per_sample(static_cast<AVSampleFormat>(frame->format)) * frame->channels;
|
||||
if (new_frame) {
|
||||
apply_audio_effects(c, bytes_to_seconds(c->audio_buffer_write, 2, audio_output->format().sampleRate()) + audio_ibuffer_timecode + ((double)c->clip_in/c->sequence->frame_rate) - ((double)timeline_in/last_fr), frame, nb_bytes, nests);
|
||||
apply_audio_effects(c, bytes_to_seconds(c->audio_buffer_write, 2, audio_output->format().sampleRate()) + audio_ibuffer_timecode + ((double)c->get_clip_in_with_transition()/c->sequence->frame_rate) - ((double)timeline_in/last_fr), frame, nb_bytes, nests);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -233,7 +233,7 @@ void get_clip_frame(Clip* c, long playhead) {
|
||||
}
|
||||
|
||||
long playhead_to_clip_frame(Clip* c, long playhead) {
|
||||
return (qMax(0L, playhead - c->timeline_in) + c->clip_in);
|
||||
return (qMax(0L, playhead - c->get_timeline_in_with_transition()) + c->get_clip_in_with_transition());
|
||||
}
|
||||
|
||||
double playhead_to_clip_seconds(Clip* c, long playhead) {
|
||||
@@ -299,9 +299,9 @@ int retrieve_next_frame(Clip* c, AVFrame* f) {
|
||||
|
||||
bool is_clip_active(Clip* c, long playhead) {
|
||||
return c->enabled
|
||||
&& c->timeline_in < playhead + ceil(c->sequence->frame_rate*2)
|
||||
&& c->timeline_out > playhead
|
||||
&& playhead - c->timeline_in + c->clip_in < c->getMaximumLength();
|
||||
&& c->get_timeline_in_with_transition() < playhead + ceil(c->sequence->frame_rate*2)
|
||||
&& c->get_timeline_out_with_transition() > playhead
|
||||
&& playhead - c->get_timeline_in_with_transition() + c->get_clip_in_with_transition() < c->getMaximumLength();
|
||||
}
|
||||
|
||||
void set_sequence(Sequence* s) {
|
||||
|
||||
+10
-2
@@ -123,7 +123,7 @@ void Clip::refresh() {
|
||||
effects.at(i)->refresh();
|
||||
}
|
||||
|
||||
recalculateMaxLength();
|
||||
recalculateMaxLength();
|
||||
}
|
||||
|
||||
void Clip::queue_clear() {
|
||||
@@ -178,6 +178,14 @@ Clip::~Clip() {
|
||||
av_packet_free(&pkt);
|
||||
}
|
||||
|
||||
long Clip::get_clip_in_with_transition() {
|
||||
if (get_opening_transition() != NULL && get_opening_transition()->secondary_clip != NULL) {
|
||||
// we must be the secondary clip, so return (timeline in - length)
|
||||
return clip_in - get_opening_transition()->length;
|
||||
}
|
||||
return clip_in;
|
||||
}
|
||||
|
||||
long Clip::get_timeline_in_with_transition() {
|
||||
if (get_opening_transition() != NULL && get_opening_transition()->secondary_clip != NULL) {
|
||||
// we must be the secondary clip, so return (timeline in - length)
|
||||
@@ -189,7 +197,7 @@ long Clip::get_timeline_in_with_transition() {
|
||||
long Clip::get_timeline_out_with_transition() {
|
||||
if (get_closing_transition() != NULL && get_closing_transition()->secondary_clip != NULL) {
|
||||
// we must be the primary clip, so return (timeline out + length2)
|
||||
return timeline_out + get_closing_transition()->length2;
|
||||
return timeline_out + get_closing_transition()->length;
|
||||
} else {
|
||||
return timeline_out;
|
||||
}
|
||||
|
||||
@@ -37,6 +37,7 @@ struct Clip
|
||||
void reset_audio();
|
||||
void reset();
|
||||
void refresh();
|
||||
long get_clip_in_with_transition();
|
||||
long get_timeline_in_with_transition();
|
||||
long get_timeline_out_with_transition();
|
||||
long getLength();
|
||||
|
||||
+1
-1
@@ -782,7 +782,7 @@ void Effect::process_shader(double timecode, GLTextureCoords&) {
|
||||
}
|
||||
}
|
||||
|
||||
void Effect::process_coords(double, GLTextureCoords&) {}
|
||||
void Effect::process_coords(double, GLTextureCoords&, int data) {}
|
||||
|
||||
GLuint Effect::process_superimpose(double timecode) {
|
||||
bool recreate_texture = false;
|
||||
|
||||
+1
-7
@@ -71,11 +71,6 @@ extern QMutex effects_loaded;
|
||||
#define KEYFRAME_TYPE_SMOOTH 1
|
||||
#define KEYFRAME_TYPE_BEZIER 2
|
||||
|
||||
#define TRAN_TYPE_OPEN 1
|
||||
#define TRAN_TYPE_CLOSE 2
|
||||
#define TRAN_TYPE_OPENWLINK 3
|
||||
#define TRAN_TYPE_CLOSEWLINK 4
|
||||
|
||||
struct GLTextureCoords {
|
||||
int grid_size;
|
||||
|
||||
@@ -111,7 +106,6 @@ public:
|
||||
Clip* parent_clip;
|
||||
const EffectMeta* meta;
|
||||
long length; // used only for transitions
|
||||
long length2; // used only for transitions
|
||||
int id;
|
||||
QString name;
|
||||
CollapsibleWidget* container;
|
||||
@@ -147,7 +141,7 @@ public:
|
||||
const char* ffmpeg_filter;
|
||||
|
||||
virtual void process_shader(double timecode, GLTextureCoords&);
|
||||
virtual void process_coords(double timecode, GLTextureCoords& coords);
|
||||
virtual void process_coords(double timecode, GLTextureCoords& coords, int data);
|
||||
virtual GLuint process_superimpose(double timecode);
|
||||
virtual void process_audio(double timecode_start, double timecode_end, quint8* samples, int nb_bytes, int channel_count);
|
||||
public slots:
|
||||
|
||||
@@ -22,6 +22,13 @@ int Transition::copy(Clip *c, Clip* s) {
|
||||
return copy_index;
|
||||
}
|
||||
|
||||
long Transition::get_length() {
|
||||
if (secondary_clip != NULL) {
|
||||
return length * 2;
|
||||
}
|
||||
return length;
|
||||
}
|
||||
|
||||
Transition* get_transition_from_meta(Clip* c, Clip* s, const EffectMeta* em) {
|
||||
if (!em->filename.isEmpty()) {
|
||||
// load effect from file
|
||||
|
||||
@@ -20,6 +20,7 @@ public:
|
||||
Transition(Clip* c, Clip* s, const EffectMeta* em);
|
||||
int copy(Clip* c, Clip* s);
|
||||
Clip* secondary_clip;
|
||||
long get_length();
|
||||
};
|
||||
|
||||
#endif // TRANSITION_H
|
||||
|
||||
+6
-2
@@ -243,11 +243,15 @@ void AddTransitionCommand::redo() {
|
||||
if (type == TA_OPENING_TRANSITION) {
|
||||
clip->opening_transition = create_transition(clip, secondary, transition);
|
||||
if (secondary != NULL) secondary->closing_transition = clip->opening_transition;
|
||||
if (length > 0) clip->get_opening_transition()->length = length;
|
||||
if (length > 0) {
|
||||
clip->get_opening_transition()->length = length;
|
||||
}
|
||||
} else {
|
||||
clip->closing_transition = create_transition(clip, secondary, transition);
|
||||
if (secondary != NULL) secondary->opening_transition = clip->closing_transition;
|
||||
if (length > 0) clip->get_closing_transition()->length = length;
|
||||
if (length > 0) {
|
||||
clip->get_closing_transition()->length = length;
|
||||
}
|
||||
}
|
||||
mainWindow->setWindowModified(true);
|
||||
}
|
||||
|
||||
+60
-37
@@ -902,6 +902,10 @@ void TimelineWidget::mouseReleaseEvent(QMouseEvent *event) {
|
||||
const Ghost& g = panel_timeline->ghosts.at(i);
|
||||
|
||||
sequence->clips.at(g.clip)->undeletable = true;
|
||||
if (g.transition != NULL) {
|
||||
g.transition->parent_clip->undeletable = true;
|
||||
g.transition->secondary_clip->undeletable = true;
|
||||
}
|
||||
|
||||
Selection s;
|
||||
s.in = g.in;
|
||||
@@ -911,7 +915,12 @@ void TimelineWidget::mouseReleaseEvent(QMouseEvent *event) {
|
||||
}
|
||||
panel_timeline->delete_areas_and_relink(ca, delete_areas);
|
||||
for (int i=0;i<panel_timeline->ghosts.size();i++) {
|
||||
sequence->clips.at(panel_timeline->ghosts[i].clip)->undeletable = false;
|
||||
const Ghost& g = panel_timeline->ghosts.at(i);
|
||||
sequence->clips.at(g.clip)->undeletable = false;
|
||||
if (g.transition != NULL) {
|
||||
g.transition->parent_clip->undeletable = false;
|
||||
g.transition->secondary_clip->undeletable = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
for (int i=0;i<panel_timeline->ghosts.size();i++) {
|
||||
@@ -949,38 +958,41 @@ void TimelineWidget::mouseReleaseEvent(QMouseEvent *event) {
|
||||
} else {
|
||||
bool is_opening_transition = (g.transition == c->get_opening_transition());
|
||||
long new_transition_length = g.out - g.in;
|
||||
if (g.transition->secondary_clip != NULL) new_transition_length >>= 1;
|
||||
ca->append(new ModifyTransitionCommand(c, is_opening_transition ? TA_OPENING_TRANSITION : TA_CLOSING_TRANSITION, new_transition_length));
|
||||
|
||||
long clip_length = c->getLength();
|
||||
if (is_opening_transition) {
|
||||
if (g.in != g.old_in) {
|
||||
// if transition is going to make the clip bigger, make the clip bigger
|
||||
ca->append(new MoveClipAction(c, c->timeline_in + (g.in - g.old_in), c->timeline_out, c->clip_in + (g.clip_in - g.old_clip_in), c->track));
|
||||
clip_length -= (g.in - g.old_in);
|
||||
}
|
||||
if (g.transition->secondary_clip == NULL) {
|
||||
if (is_opening_transition) {
|
||||
if (g.in != g.old_in) {
|
||||
// if transition is going to make the clip bigger, make the clip bigger
|
||||
ca->append(new MoveClipAction(c, c->timeline_in + (g.in - g.old_in), c->timeline_out, c->clip_in + (g.clip_in - g.old_clip_in), c->track));
|
||||
clip_length -= (g.in - g.old_in);
|
||||
}
|
||||
|
||||
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->get_closing_transition()->length) {
|
||||
ca->append(new ModifyTransitionCommand(c, TA_CLOSING_TRANSITION, clip_length - new_transition_length));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (g.out != g.old_out) {
|
||||
// if transition is going to make the clip bigger, make the clip bigger
|
||||
ca->append(new MoveClipAction(c, c->timeline_in, c->timeline_out + (g.out - g.old_out), c->clip_in, c->track));
|
||||
clip_length += (g.out - g.old_out);
|
||||
}
|
||||
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->get_closing_transition()->length) {
|
||||
ca->append(new ModifyTransitionCommand(c, TA_CLOSING_TRANSITION, clip_length - new_transition_length));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (g.out != g.old_out) {
|
||||
// if transition is going to make the clip bigger, make the clip bigger
|
||||
ca->append(new MoveClipAction(c, c->timeline_in, c->timeline_out + (g.out - g.old_out), c->clip_in, c->track));
|
||||
clip_length += (g.out - g.old_out);
|
||||
}
|
||||
|
||||
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->get_opening_transition()->length) {
|
||||
ca->append(new ModifyTransitionCommand(c, TA_OPENING_TRANSITION, clip_length - new_transition_length));
|
||||
}
|
||||
}
|
||||
}
|
||||
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->get_opening_transition()->length) {
|
||||
ca->append(new ModifyTransitionCommand(c, TA_OPENING_TRANSITION, clip_length - new_transition_length));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1015,7 +1027,7 @@ void TimelineWidget::mouseReleaseEvent(QMouseEvent *event) {
|
||||
pre = post;
|
||||
post = temp;
|
||||
}
|
||||
ca->append(new AddTransitionCommand(pre, post, panel_timeline->transition_tool_meta, panel_timeline->transition_tool_type, transition_end - pre->timeline_in));
|
||||
ca->append(new AddTransitionCommand(pre, post, panel_timeline->transition_tool_meta, TA_OPENING_TRANSITION, transition_end - pre->timeline_in));
|
||||
} else {
|
||||
if (transition_start < c->timeline_in || transition_end > c->timeline_out) {
|
||||
// delete shit over there and extend timeline in
|
||||
@@ -1107,13 +1119,13 @@ void TimelineWidget::init_ghosts() {
|
||||
g.out = g.old_out = c->timeline_out;
|
||||
g.ghost_length = g.old_out - g.old_in;
|
||||
} 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->get_opening_transition()->length;
|
||||
g.ghost_length = c->get_opening_transition()->length;
|
||||
g.in = g.old_in = c->get_timeline_in_with_transition();
|
||||
g.ghost_length = c->get_opening_transition()->get_length();
|
||||
g.out = g.old_out = g.in + g.ghost_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->get_closing_transition()->length;
|
||||
g.out = g.old_out = c->get_timeline_out_with_transition();
|
||||
g.ghost_length = c->get_closing_transition()->get_length();
|
||||
g.in = g.old_in = g.out - g.ghost_length;
|
||||
g.clip_in = g.old_clip_in = c->clip_in + c->getLength() - c->get_closing_transition()->length;
|
||||
}
|
||||
|
||||
@@ -1201,7 +1213,7 @@ void TimelineWidget::update_ghosts(const QPoint& mouse_pos, bool lock_frame) {
|
||||
|| (ms != NULL && !ms->infinite_length)) {
|
||||
validator = g.old_clip_in + frame_diff;
|
||||
if (validator < 0) frame_diff -= validator;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// prevent clip length from being less than 1 frame long
|
||||
validator = g.ghost_length + frame_diff;
|
||||
@@ -1215,6 +1227,14 @@ void TimelineWidget::update_ghosts(const QPoint& mouse_pos, bool lock_frame) {
|
||||
}
|
||||
}
|
||||
|
||||
// prevent dual transition from going below 0 on the secondary or media length on the primary
|
||||
if (g.transition != NULL && g.transition->secondary_clip != NULL) {
|
||||
validator = g.transition->secondary_clip->clip_in + frame_diff;
|
||||
if (validator > 0) frame_diff -= validator;
|
||||
|
||||
|
||||
}
|
||||
|
||||
// ripple ops
|
||||
if (panel_timeline->tool == TIMELINE_TOOL_RIPPLE) {
|
||||
for (int j=0;j<post_clips.size();j++) {
|
||||
@@ -1343,7 +1363,10 @@ void TimelineWidget::update_ghosts(const QPoint& mouse_pos, bool lock_frame) {
|
||||
}
|
||||
|
||||
// apply changes
|
||||
if (g.trim_in) {
|
||||
if (g.transition != NULL && g.transition->secondary_clip != NULL) {
|
||||
g.in = g.old_in - ghost_diff;
|
||||
g.out = g.old_out + ghost_diff;
|
||||
} else if (g.trim_in) {
|
||||
g.in = g.old_in + ghost_diff;
|
||||
g.clip_in = g.old_clip_in + ghost_diff;
|
||||
} else {
|
||||
|
||||
+27
-26
@@ -247,10 +247,10 @@ GLuint ViewerWidget::draw_clip(QOpenGLFramebufferObject* fbo, GLuint texture, bo
|
||||
return fbo->texture();
|
||||
}
|
||||
|
||||
void ViewerWidget::process_effect(Clip* c, Effect* e, double timecode, GLTextureCoords& coords, GLuint& composite_texture, bool& fbo_switcher) {
|
||||
void ViewerWidget::process_effect(Clip* c, Effect* e, double timecode, GLTextureCoords& coords, GLuint& composite_texture, bool& fbo_switcher, int data) {
|
||||
if (e->is_enabled()) {
|
||||
if (e->enable_coords) {
|
||||
e->process_coords(timecode, coords);
|
||||
e->process_coords(timecode, coords, data);
|
||||
}
|
||||
if (e->enable_shader || e->enable_superimpose) {
|
||||
e->startEffect();
|
||||
@@ -264,7 +264,7 @@ void ViewerWidget::process_effect(Clip* c, Effect* e, double timecode, GLTexture
|
||||
if (superimpose_texture != 0) composite_texture = draw_clip(c->fbo[!fbo_switcher], superimpose_texture, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int motion_blur_prog = 0;
|
||||
@@ -277,7 +277,7 @@ GLuint ViewerWidget::compose_sequence(QVector<Clip*>& nests, bool render_audio)
|
||||
if (!nests.isEmpty()) {
|
||||
for (int i=0;i<nests.size();i++) {
|
||||
s = static_cast<Sequence*>(nests.at(i)->media);
|
||||
playhead += nests.at(i)->clip_in - nests.at(i)->timeline_in;
|
||||
playhead += nests.at(i)->clip_in - nests.at(i)->get_timeline_in_with_transition();
|
||||
playhead = refactor_frame_number(playhead, nests.at(i)->sequence->frame_rate, s->frame_rate);
|
||||
}
|
||||
|
||||
@@ -353,14 +353,17 @@ GLuint ViewerWidget::compose_sequence(QVector<Clip*>& nests, bool render_audio)
|
||||
int half_width = s->width/2;
|
||||
int half_height = s->height/2;
|
||||
if (rendering || !nests.isEmpty()) half_height = -half_height; // invert vertical
|
||||
glPushMatrix();
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
glColor4f(1.0, 1.0, 1.0, 1.0);
|
||||
glLoadIdentity();
|
||||
glOrtho(-half_width, half_width, half_height, -half_height, -1, 1);
|
||||
|
||||
glPushMatrix();
|
||||
glLoadIdentity();
|
||||
glOrtho(-half_width, half_width, half_height, -half_height, -1, 1);
|
||||
|
||||
for (int i=0;i<current_clips.size();i++) {
|
||||
Clip* c = current_clips.at(i);
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
glColor4f(1.0, 1.0, 1.0, 1.0);
|
||||
|
||||
Clip* c = current_clips.at(i);
|
||||
|
||||
if (c->media_type == MEDIA_TYPE_FOOTAGE && !c->finished_opening) {
|
||||
dout << "[WARNING] Tried to display clip" << i << "but it's closed";
|
||||
texture_failed = true;
|
||||
@@ -389,7 +392,7 @@ GLuint ViewerWidget::compose_sequence(QVector<Clip*>& nests, bool render_audio)
|
||||
if (textureID == 0 && c->media_type != MEDIA_TYPE_SOLID) {
|
||||
dout << "[WARNING] Texture hasn't been created yet";
|
||||
texture_failed = true;
|
||||
} else if (playhead >= c->timeline_in) {
|
||||
} else if (playhead >= c->get_timeline_in_with_transition()) {
|
||||
glPushMatrix();
|
||||
|
||||
// start preparing cache
|
||||
@@ -441,31 +444,29 @@ GLuint ViewerWidget::compose_sequence(QVector<Clip*>& nests, bool render_audio)
|
||||
coords.textureBottomLeftY = coords.textureBottomRightY = coords.textureTopRightX = coords.textureBottomRightX = 1.0;
|
||||
|
||||
if (c->autoscale && (video_width != s->width && video_height != s->height)) {
|
||||
double width_multiplier = (double) s->width / (double) video_width;
|
||||
double height_multiplier = (double) s->height / (double) video_height;
|
||||
double scale_multiplier = qMin(width_multiplier, height_multiplier);
|
||||
float width_multiplier = (float) s->width / (float) video_width;
|
||||
float height_multiplier = (float) s->height / (float) video_height;
|
||||
float scale_multiplier = qMin(width_multiplier, height_multiplier);
|
||||
glScalef(scale_multiplier, scale_multiplier, 1);
|
||||
}
|
||||
|
||||
// EFFECT CODE START
|
||||
double timecode = ((double)(playhead-c->timeline_in+c->clip_in)/(double)c->sequence->frame_rate);
|
||||
double timecode = ((double)(playhead-c->get_timeline_in_with_transition()+c->get_clip_in_with_transition())/(double)c->sequence->frame_rate);
|
||||
for (int j=0;j<c->effects.size();j++) {
|
||||
process_effect(c, c->effects.at(j), timecode, coords, composite_texture, fbo_switcher);
|
||||
process_effect(c, c->effects.at(j), timecode, coords, composite_texture, fbo_switcher, TA_NO_TRANSITION);
|
||||
}
|
||||
|
||||
if (c->get_opening_transition() != NULL) {
|
||||
int transition_progress = playhead - c->timeline_in;
|
||||
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);
|
||||
int transition_progress = playhead - c->get_timeline_in_with_transition();
|
||||
if (transition_progress < c->get_opening_transition()->get_length()) {
|
||||
process_effect(c, c->get_opening_transition(), (double)transition_progress/(double)c->get_opening_transition()->get_length(), coords, composite_texture, fbo_switcher, TA_OPENING_TRANSITION);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
int transition_progress = playhead - (c->get_timeline_out_with_transition() - c->get_closing_transition()->get_length());
|
||||
if (transition_progress >= 0 && transition_progress < c->get_closing_transition()->get_length()) {
|
||||
process_effect(c, c->get_closing_transition(), (double)transition_progress/(double)c->get_closing_transition()->get_length(), coords, composite_texture, fbo_switcher, TA_CLOSING_TRANSITION);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -574,7 +575,7 @@ GLuint ViewerWidget::compose_sequence(QVector<Clip*>& nests, bool render_audio)
|
||||
|
||||
// visually update all the keyframe values
|
||||
if (c->sequence == viewer->seq) { // only if you can currently see them
|
||||
double ts = (playhead - c->timeline_in + c->clip_in)/s->frame_rate;
|
||||
double ts = (playhead - c->get_timeline_in_with_transition() + c->get_clip_in_with_transition())/s->frame_rate;
|
||||
for (int i=0;i<c->effects.size();i++) {
|
||||
Effect* e = c->effects.at(i);
|
||||
for (int j=0;j<e->row_count();j++) {
|
||||
|
||||
+1
-1
@@ -44,7 +44,7 @@ private:
|
||||
void seek_from_click(int x);
|
||||
GLuint compose_sequence(QVector<Clip *> &nests, bool render_audio);
|
||||
GLuint draw_clip(QOpenGLFramebufferObject *clip, GLuint texture, bool clear);
|
||||
void process_effect(Clip* c, Effect* e, double timecode, GLTextureCoords& coords, GLuint& composite_texture, bool& fbo_switcher);
|
||||
void process_effect(Clip* c, Effect* e, double timecode, GLTextureCoords& coords, GLuint& composite_texture, bool& fbo_switcher, int data);
|
||||
private slots:
|
||||
void retry();
|
||||
void deleteFunction();
|
||||
|
||||
Reference in New Issue
Block a user