From 4a7abcdeaab273caeeb1e619373d967d9c404527 Mon Sep 17 00:00:00 2001 From: itsmattkc Date: Fri, 23 Nov 2018 19:49:29 +1100 Subject: [PATCH] better ]shared transitions, dock tabs, effects panel name --- effects/internal/cornerpineffect.cpp | 2 +- effects/internal/cornerpineffect.h | 2 +- effects/internal/crossdissolvetransition.cpp | 10 +- effects/internal/crossdissolvetransition.h | 2 +- .../internal/exponentialfadetransition.cpp | 6 +- effects/internal/linearfadetransition.cpp | 6 +- .../internal/logarithmicfadetransition.cpp | 6 +- effects/internal/shakeeffect.cpp | 2 +- effects/internal/shakeeffect.h | 2 +- effects/internal/transformeffect.cpp | 2 +- effects/internal/transformeffect.h | 2 +- mainwindow.cpp | 2 + panels/effectcontrols.cpp | 6 +- panels/effectcontrols.h | 13 +-- panels/project.cpp | 10 +- panels/viewer.cpp | 5 +- panels/viewer.h | 1 + playback/cacher.cpp | 39 ++++---- playback/playback.cpp | 8 +- project/clip.cpp | 12 ++- project/clip.h | 1 + project/effect.cpp | 2 +- project/effect.h | 8 +- project/transition.cpp | 7 ++ project/transition.h | 1 + project/undo.cpp | 8 +- ui/timelinewidget.cpp | 97 ++++++++++++------- ui/viewerwidget.cpp | 53 +++++----- ui/viewerwidget.h | 2 +- 29 files changed, 171 insertions(+), 146 deletions(-) diff --git a/effects/internal/cornerpineffect.cpp b/effects/internal/cornerpineffect.cpp index a0206946d..8e621f880 100644 --- a/effects/internal/cornerpineffect.cpp +++ b/effects/internal/cornerpineffect.cpp @@ -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); diff --git a/effects/internal/cornerpineffect.h b/effects/internal/cornerpineffect.h index 0c28f8810..164101a58 100644 --- a/effects/internal/cornerpineffect.h +++ b/effects/internal/cornerpineffect.h @@ -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; diff --git a/effects/internal/crossdissolvetransition.cpp b/effects/internal/crossdissolvetransition.cpp index dc89eb2be..802700dda 100644 --- a/effects/internal/crossdissolvetransition.cpp +++ b/effects/internal/crossdissolvetransition.cpp @@ -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); + } } diff --git a/effects/internal/crossdissolvetransition.h b/effects/internal/crossdissolvetransition.h index c90fd8080..61bd483ca 100644 --- a/effects/internal/crossdissolvetransition.h +++ b/effects/internal/crossdissolvetransition.h @@ -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 diff --git a/effects/internal/exponentialfadetransition.cpp b/effects/internal/exponentialfadetransition.cpp index 6182e62c7..7146d6fe4 100644 --- a/effects/internal/exponentialfadetransition.cpp +++ b/effects/internal/exponentialfadetransition.cpp @@ -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; } diff --git a/effects/internal/linearfadetransition.cpp b/effects/internal/linearfadetransition.cpp index 32e18b755..f82821c56 100644 --- a/effects/internal/linearfadetransition.cpp +++ b/effects/internal/linearfadetransition.cpp @@ -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; } diff --git a/effects/internal/logarithmicfadetransition.cpp b/effects/internal/logarithmicfadetransition.cpp index 60509c77c..b4267644b 100644 --- a/effects/internal/logarithmicfadetransition.cpp +++ b/effects/internal/logarithmicfadetransition.cpp @@ -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; } diff --git a/effects/internal/shakeeffect.cpp b/effects/internal/shakeeffect.cpp index 5e453d30e..7568bae6b 100644 --- a/effects/internal/shakeeffect.cpp +++ b/effects/internal/shakeeffect.cpp @@ -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; diff --git a/effects/internal/shakeeffect.h b/effects/internal/shakeeffect.h index 216e2d53b..6df5692a4 100644 --- a/effects/internal/shakeeffect.h +++ b/effects/internal/shakeeffect.h @@ -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; diff --git a/effects/internal/transformeffect.cpp b/effects/internal/transformeffect.cpp index 2bdd5e780..1884d818c 100644 --- a/effects/internal/transformeffect.cpp +++ b/effects/internal/transformeffect.cpp @@ -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); diff --git a/effects/internal/transformeffect.h b/effects/internal/transformeffect.h index 93a67a006..bfeffcbf6 100644 --- a/effects/internal/transformeffect.h +++ b/effects/internal/transformeffect.h @@ -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; diff --git a/mainwindow.cpp b/mainwindow.cpp index aebb9fbad..9359d2efd 100644 --- a/mainwindow.cpp +++ b/mainwindow.cpp @@ -119,6 +119,8 @@ MainWindow::MainWindow(QWidget *parent) : // end style ui->setupUi(this); + setTabPosition(Qt::AllDockWidgetAreas, QTabWidget::North); + updateTitle(""); statusBar()->showMessage("Welcome to " + appName); diff --git a/panels/effectcontrols.cpp b/panels/effectcontrols.cpp index da0368d30..18637db7f 100644 --- a/panels/effectcontrols.cpp +++ b/panels/effectcontrols.cpp @@ -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); diff --git a/panels/effectcontrols.h b/panels/effectcontrols.h index d1eb8bdd3..4e54ff481 100644 --- a/panels/effectcontrols.h +++ b/panels/effectcontrols.h @@ -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 clips; - QVector effects; -private: - bool done; -};*/ - #endif // EFFECTCONTROLS_H diff --git a/panels/project.cpp b/panels/project.cpp index 3ba823e07..1794edcf7 100644 --- a/panels/project.cpp +++ b/panels/project.cpp @@ -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;jsequence->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); diff --git a/panels/viewer.cpp b/panels/viewer.cpp index 4a41d26dc..02fec95ac 100644 --- a/panels/viewer.cpp +++ b/panels/viewer.cpp @@ -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 #include @@ -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; diff --git a/panels/viewer.h b/panels/viewer.h index 61625ed02..d7b5f1d53 100644 --- a/panels/viewer.h +++ b/panels/viewer.h @@ -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; diff --git a/playback/cacher.cpp b/playback/cacher.cpp index ecb9de3cb..08bf224e7 100644 --- a/playback/cacher.cpp +++ b/playback/cacher.cpp @@ -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 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& 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& 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& 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(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; diff --git a/playback/playback.cpp b/playback/playback.cpp index 4a401c02d..abe16436e 100644 --- a/playback/playback.cpp +++ b/playback/playback.cpp @@ -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) { diff --git a/project/clip.cpp b/project/clip.cpp index 60e64ec6b..94eabeacb 100644 --- a/project/clip.cpp +++ b/project/clip.cpp @@ -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; } diff --git a/project/clip.h b/project/clip.h index 6f7fc6fbd..890a7d9df 100644 --- a/project/clip.h +++ b/project/clip.h @@ -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(); diff --git a/project/effect.cpp b/project/effect.cpp index 4826f6df8..5a8de3eb5 100644 --- a/project/effect.cpp +++ b/project/effect.cpp @@ -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; diff --git a/project/effect.h b/project/effect.h index c9e84bf35..d91a1d24e 100644 --- a/project/effect.h +++ b/project/effect.h @@ -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: diff --git a/project/transition.cpp b/project/transition.cpp index 7f67e0587..9792b310a 100644 --- a/project/transition.cpp +++ b/project/transition.cpp @@ -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 diff --git a/project/transition.h b/project/transition.h index 6ca111433..4464632f5 100644 --- a/project/transition.h +++ b/project/transition.h @@ -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 diff --git a/project/undo.cpp b/project/undo.cpp index fcea5fe04..7093aeeb4 100644 --- a/project/undo.cpp +++ b/project/undo.cpp @@ -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); } diff --git a/ui/timelinewidget.cpp b/ui/timelinewidget.cpp index de018a958..1d9ae35d0 100644 --- a/ui/timelinewidget.cpp +++ b/ui/timelinewidget.cpp @@ -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;ighosts.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;ighosts.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;jsecondary_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 { diff --git a/ui/viewerwidget.cpp b/ui/viewerwidget.cpp index 76f1bf13f..6cb3ff263 100644 --- a/ui/viewerwidget.cpp +++ b/ui/viewerwidget.cpp @@ -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& nests, bool render_audio) if (!nests.isEmpty()) { for (int i=0;i(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& 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;imedia_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& 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& 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;jeffects.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& 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;ieffects.size();i++) { Effect* e = c->effects.at(i); for (int j=0;jrow_count();j++) { diff --git a/ui/viewerwidget.h b/ui/viewerwidget.h index f8faa1eac..1f2931484 100644 --- a/ui/viewerwidget.h +++ b/ui/viewerwidget.h @@ -44,7 +44,7 @@ private: void seek_from_click(int x); GLuint compose_sequence(QVector &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();