From 1414c6a5bbb3ee6dc0c1dc215c1b2ca4fd7c378f Mon Sep 17 00:00:00 2001 From: itsmattkc Date: Sat, 24 Nov 2018 10:59:00 +1100 Subject: [PATCH 01/31] fixed up validationn issues with transition tool --- playback/playback.cpp | 2 +- project/sequence.cpp | 11 ++++++++--- ui/timelinewidget.cpp | 12 ++++++++++++ 3 files changed, 21 insertions(+), 4 deletions(-) diff --git a/playback/playback.cpp b/playback/playback.cpp index 3c303299d..96501f94c 100644 --- a/playback/playback.cpp +++ b/playback/playback.cpp @@ -194,7 +194,7 @@ void get_clip_frame(Clip* c, long playhead) { #ifdef GCF_DEBUG dout << "GCF ==> RESET" << target_pts << "(" << target_frame->pts << "-" << target_frame->pts+target_frame->pkt_duration << ")"; #endif -// target_frame = NULL; +// target_frame = NULL; reset = true; c->last_invalid_ts = target_pts; } else { diff --git a/project/sequence.cpp b/project/sequence.cpp index be887693d..f454243a7 100644 --- a/project/sequence.cpp +++ b/project/sequence.cpp @@ -57,6 +57,7 @@ long Sequence::getEndFrame() { 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) { + bool del = true; for (int i=0;iopening_transition == transition_index || cc->closing_transition == transition_index)) { // another clip is using this, don't delete just yet - return; + del = false; + break; } } - delete transitions.at(transition_index); - transitions[transition_index] = NULL; + if (del) { + delete transitions.at(transition_index); + transitions[transition_index] = NULL; + } + if (type == TA_OPENING_TRANSITION) { c->opening_transition = -1; } else { diff --git a/ui/timelinewidget.cpp b/ui/timelinewidget.cpp index 3d853e047..e266297f9 100644 --- a/ui/timelinewidget.cpp +++ b/ui/timelinewidget.cpp @@ -1310,6 +1310,13 @@ void TimelineWidget::update_ghosts(const QPoint& mouse_pos, bool lock_frame) { } } } else if (panel_timeline->tool == TIMELINE_TOOL_TRANSITION) { + bool flipped = false; + + if (frame_diff < 0) { + frame_diff = -frame_diff; + flipped = true; + } + Clip* otc = c; // open transition clip Clip* ctc = (panel_timeline->transition_tool_post_clip > -1) ? sequence->clips.at(panel_timeline->transition_tool_post_clip) : NULL; // close transition clip @@ -1327,6 +1334,7 @@ void TimelineWidget::update_ghosts(const QPoint& mouse_pos, bool lock_frame) { } validator = otc->clip_in - frame_diff; + dout << "validator" << validator; if (validator < 0) { // prevent from going below 0 for the media frame_diff += validator; } @@ -1351,6 +1359,10 @@ void TimelineWidget::update_ghosts(const QPoint& mouse_pos, bool lock_frame) { frame_diff -= validator; } } + + if (flipped) { + frame_diff = -frame_diff; + } } } if (temp_frame_diff != frame_diff) panel_timeline->snapped = false; From af266d287100a87d2a68a2a30be963217f30b15e Mon Sep 17 00:00:00 2001 From: itsmattkc Date: Sat, 24 Nov 2018 11:05:49 +1100 Subject: [PATCH 02/31] fixed validators when resizing transitions --- ui/timelinewidget.cpp | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/ui/timelinewidget.cpp b/ui/timelinewidget.cpp index e266297f9..7d64f7986 100644 --- a/ui/timelinewidget.cpp +++ b/ui/timelinewidget.cpp @@ -1229,17 +1229,20 @@ void TimelineWidget::update_ghosts(const QPoint& mouse_pos, bool lock_frame) { // prevent dual transition from going below 0 on the primary or media length on the secondary if (g.transition != NULL && g.transition->secondary_clip != NULL) { if (g.trim_in) { - validator = g.transition->parent_clip->get_clip_in_with_transition() + frame_diff; - if (validator < 0) frame_diff -= validator; + frame_diff = -frame_diff; + } - validator = g.transition->secondary_clip->get_timeline_out_with_transition() - g.transition->secondary_clip->get_timeline_in_with_transition() + g.transition->secondary_clip->get_clip_in_with_transition() - frame_diff - g.transition->secondary_clip->getMaximumLength(); - if (validator > 0) frame_diff += validator; - } else { - validator = g.transition->parent_clip->get_clip_in_with_transition() - frame_diff; - if (validator < 0) frame_diff += validator; + validator = g.transition->parent_clip->get_clip_in_with_transition() - frame_diff; + if (validator < 0) frame_diff += validator; - validator = g.transition->secondary_clip->get_timeline_out_with_transition() - g.transition->secondary_clip->get_timeline_in_with_transition() + g.transition->secondary_clip->get_clip_in_with_transition() + frame_diff - g.transition->secondary_clip->getMaximumLength(); - if (validator > 0) frame_diff -= validator; + validator = g.transition->secondary_clip->get_timeline_out_with_transition() - g.transition->secondary_clip->get_timeline_in_with_transition() + g.transition->secondary_clip->get_clip_in_with_transition() + frame_diff - g.transition->secondary_clip->getMaximumLength(); + if (validator > 0) frame_diff -= validator; + + validator = g.transition->length + frame_diff - 1; + if (validator < 0) frame_diff -= validator; + + if (g.trim_in) { + frame_diff = -frame_diff; } } @@ -1334,7 +1337,6 @@ void TimelineWidget::update_ghosts(const QPoint& mouse_pos, bool lock_frame) { } validator = otc->clip_in - frame_diff; - dout << "validator" << validator; if (validator < 0) { // prevent from going below 0 for the media frame_diff += validator; } From 16ccb4d9c32b061ce7e3fb0ab55a88f64bf1d89e Mon Sep 17 00:00:00 2001 From: itsmattkc Date: Sat, 24 Nov 2018 11:27:17 +1100 Subject: [PATCH 03/31] more validator corrections and deleting shared transitions --- panels/timeline.cpp | 22 ++++++++++++++++------ panels/timeline.h | 1 + ui/timelinewidget.cpp | 32 ++++++++++++++------------------ 3 files changed, 31 insertions(+), 24 deletions(-) diff --git a/panels/timeline.cpp b/panels/timeline.cpp index 06d53deb9..305e289cd 100644 --- a/panels/timeline.cpp +++ b/panels/timeline.cpp @@ -743,6 +743,20 @@ void Timeline::clean_up_selections(QVector& areas) { } } +bool selection_contains_transition(const Selection& s, Clip* c, int type) { + if (type == TA_OPENING_TRANSITION) { + return c->get_opening_transition() != NULL + && s.out == c->timeline_in + c->get_opening_transition()->length + && ((c->get_opening_transition()->secondary_clip == NULL && s.in == c->timeline_in) + || (c->get_opening_transition()->secondary_clip != NULL && s.in == c->timeline_in - c->get_opening_transition()->length)); + } else { + return c->get_closing_transition() != NULL + && s.in == c->timeline_out - c->get_closing_transition()->length + && ((c->get_closing_transition()->secondary_clip == NULL && s.out == c->timeline_out) + || (c->get_closing_transition()->secondary_clip != NULL && s.out == c->timeline_out + c->get_closing_transition()->length)); + } +} + void Timeline::delete_areas_and_relink(ComboAction* ca, QVector& areas) { clean_up_selections(areas); @@ -754,14 +768,10 @@ void Timeline::delete_areas_and_relink(ComboAction* ca, QVector& area for (int j=0;jclips.size();j++) { Clip* c = sequence->clips.at(j); if (c != NULL && c->track == s.track && !c->undeletable) { - if (c->get_opening_transition() != NULL - && s.in == c->timeline_in - && s.out == c->timeline_in + c->get_opening_transition()->length) { + if (selection_contains_transition(s, c, TA_OPENING_TRANSITION)) { // delete opening transition ca->append(new DeleteTransitionCommand(c, TA_OPENING_TRANSITION)); - } else if (c->get_closing_transition() != NULL - && s.out == c->timeline_out - && s.in == c->timeline_out - c->get_closing_transition()->length) { + } else if (selection_contains_transition(s, c, TA_CLOSING_TRANSITION)) { // delete closing transition ca->append(new DeleteTransitionCommand(c, TA_CLOSING_TRANSITION)); } else if (c->timeline_in >= s.in && c->timeline_out <= s.out) { diff --git a/panels/timeline.h b/panels/timeline.h index 779029108..96c2f97be 100644 --- a/panels/timeline.h +++ b/panels/timeline.h @@ -33,6 +33,7 @@ long refactor_frame_number(long framenumber, double source_frame_rate, double ta int getScreenPointFromFrame(double zoom, long frame); long getFrameFromScreenPoint(double zoom, int x); void draw_selection_rectangle(QPainter& painter, const QRect& rect); +bool selection_contains_transition(const Selection& s, Clip* c, int type); struct Ghost { int clip; diff --git a/ui/timelinewidget.cpp b/ui/timelinewidget.cpp index 7d64f7986..ec5693d3a 100644 --- a/ui/timelinewidget.cpp +++ b/ui/timelinewidget.cpp @@ -1315,7 +1315,7 @@ void TimelineWidget::update_ghosts(const QPoint& mouse_pos, bool lock_frame) { } else if (panel_timeline->tool == TIMELINE_TOOL_TRANSITION) { bool flipped = false; - if (frame_diff < 0) { + if (frame_diff < 0 && panel_timeline->transition_tool_post_clip > -1) { frame_diff = -frame_diff; flipped = true; } @@ -1332,17 +1332,19 @@ void TimelineWidget::update_ghosts(const QPoint& mouse_pos, bool lock_frame) { if (otc != NULL) { validator = otc->timeline_in + frame_diff; - if (validator < 0) { // prevent from going below 0 on the timeline - frame_diff -= validator; - } + if (validator < 0) frame_diff -= validator; // prevent from going below 0 on the timeline - validator = otc->clip_in - frame_diff; - if (validator < 0) { // prevent from going below 0 for the media - frame_diff += validator; - } + if (panel_timeline->transition_tool_post_clip > -1) { + validator = otc->clip_in - frame_diff; + if (validator < 0) frame_diff += validator; // prevent from going below 0 for the media - if (validator > otc->getMaximumLength()) { // prevent transition from exceeding media length - frame_diff -= (validator - otc->getMaximumLength()); + validator = otc->clip_in + frame_diff - otc->getMaximumLength(); + dout << validator << otc->getMaximumLength(); + if (validator > 0) frame_diff -= validator; // prevent transition from exceeding media length + } else { + validator = otc->clip_in + frame_diff; + if (validator < 0) frame_diff -= validator; // prevent from going below 0 for the media + if (validator > otc->getMaximumLength()) frame_diff -= (validator - otc->getMaximumLength()); // prevent transition from exceeding media length } } @@ -1604,17 +1606,11 @@ void TimelineWidget::mouseMoveEvent(QMouseEvent *event) { for (int j=0;jselections.size();j++) { const Selection& s = sequence->selections.at(j); if (s.track == c->track) { - if (c->get_opening_transition() != NULL - && s.out == c->timeline_in + c->get_opening_transition()->length - && ((c->get_opening_transition()->secondary_clip == NULL && s.in == c->timeline_in) - || (c->get_opening_transition()->secondary_clip != NULL && s.in == c->timeline_in - c->get_opening_transition()->length))) { + if (selection_contains_transition(s, c, TA_OPENING_TRANSITION)) { g.transition = c->get_opening_transition(); add = true; break; - } else if (c->get_closing_transition() != NULL - && s.in == c->timeline_out - c->get_closing_transition()->length - && ((c->get_closing_transition()->secondary_clip == NULL && s.out == c->timeline_out) - || (c->get_closing_transition()->secondary_clip != NULL && s.out == c->timeline_out + c->get_closing_transition()->length))) { + } else if (selection_contains_transition(s, c, TA_CLOSING_TRANSITION)) { g.transition = c->get_closing_transition(); add = true; break; From c5dca79d1df6625daaef51bc56c8ea77c8cc2f63 Mon Sep 17 00:00:00 2001 From: itsmattkc Date: Sat, 24 Nov 2018 13:20:33 +1100 Subject: [PATCH 04/31] fixed transition copying --- panels/timeline.cpp | 9 +++- playback/playback.cpp | 2 +- project/clip.cpp | 8 +-- project/undo.cpp | 3 ++ ui/timelinewidget.cpp | 119 +++++++++++++++++++++++------------------- 5 files changed, 81 insertions(+), 60 deletions(-) diff --git a/panels/timeline.cpp b/panels/timeline.cpp index 305e289cd..9d041f484 100644 --- a/panels/timeline.cpp +++ b/panels/timeline.cpp @@ -637,6 +637,12 @@ 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->get_opening_transition() != NULL) { + /*if (frame < pre->timeline_in + pre->get_opening_transition()->length && pre->get_opening_transition()->secondary_clip != NULL) { + // separate shared transition + ca->append(new SetPointer((void**) &pre->get_opening_transition()->secondary_clip, NULL)); + pre->get_opening_transition()->secondary_clip->closing_transition = pre->get_opening_transition()->copy(pre->get_opening_transition()->secondary_clip, NULL); + }*/ + if (pre->get_opening_transition()->length > new_clip_length) { ca->append(new ModifyTransitionCommand(pre, TA_OPENING_TRANSITION, new_clip_length)); } @@ -645,8 +651,7 @@ Clip* Timeline::split_clip(ComboAction* ca, int p, long frame, long post_in) { } if (pre->get_closing_transition() != NULL) { ca->append(new DeleteTransitionCommand(pre, TA_CLOSING_TRANSITION)); - - post->get_closing_transition()->length = qMin((long) post->get_closing_transition()->length, post->getLength()); + if (pre->get_closing_transition()->secondary_clip == NULL) post->get_closing_transition()->length = qMin((long) post->get_closing_transition()->length, post->getLength()); } return post; diff --git a/playback/playback.cpp b/playback/playback.cpp index 96501f94c..638a4ec43 100644 --- a/playback/playback.cpp +++ b/playback/playback.cpp @@ -26,7 +26,7 @@ extern "C" { #include #ifdef QT_DEBUG -#define GCF_DEBUG +//#define GCF_DEBUG #endif bool texture_failed = false; diff --git a/project/clip.cpp b/project/clip.cpp index 94eabeacb..1cfcb71c6 100644 --- a/project/clip.cpp +++ b/project/clip.cpp @@ -66,8 +66,8 @@ Clip* Clip::copy(Sequence* s) { } // TODO make a replacemennt for this somehow - //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); + if (get_opening_transition() != NULL && get_opening_transition()->secondary_clip == NULL) copy->opening_transition = get_opening_transition()->copy(copy, NULL); + if (get_closing_transition() != NULL && get_closing_transition()->secondary_clip == NULL) copy->closing_transition = get_closing_transition()->copy(copy, NULL); copy->recalculateMaxLength(); @@ -169,8 +169,8 @@ Clip::~Clip() { } } - //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); + 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;iclips.last(); panel_timeline->deselect_area(c->timeline_in, c->timeline_out, c->track); undone_clips.prepend(c); + if (c->open) close_clip(c); seq->clips.removeLast(); } mainWindow->setWindowModified(old_project_changed); @@ -504,6 +505,8 @@ void AddClipCommand::redo() { for (int j=0;jlinked.size();j++) { copy->linked[j] = original->linked.at(j) + linkOffset; } + if (original->opening_transition > -1) copy->opening_transition = original->get_opening_transition()->copy(copy, NULL); + if (original->closing_transition > -1) copy->closing_transition = original->get_closing_transition()->copy(copy, NULL); seq->clips.append(copy); } } diff --git a/ui/timelinewidget.cpp b/ui/timelinewidget.cpp index ec5693d3a..da72080a6 100644 --- a/ui/timelinewidget.cpp +++ b/ui/timelinewidget.cpp @@ -594,30 +594,28 @@ void TimelineWidget::mousePressEvent(QMouseEvent *event) { panel_timeline->deselect_area(link->timeline_in, link->timeline_out, link->track); } } - } else { - if (panel_timeline->transition_select != TA_NO_TRANSITION) { - panel_timeline->deselect_area(clip->timeline_in, clip->timeline_out, clip->track); + } else if (panel_timeline->tool == TIMELINE_TOOL_POINTER && panel_timeline->transition_select != TA_NO_TRANSITION) { + panel_timeline->deselect_area(clip->timeline_in, clip->timeline_out, clip->track); - for (int i=0;ilinked.size();i++) { - Clip* link = sequence->clips.at(clip->linked.at(i)); - panel_timeline->deselect_area(link->timeline_in, link->timeline_out, link->track); - } + for (int i=0;ilinked.size();i++) { + Clip* link = sequence->clips.at(clip->linked.at(i)); + panel_timeline->deselect_area(link->timeline_in, link->timeline_out, link->track); + } - Selection s; - s.track = clip->track; + Selection s; + s.track = clip->track; - if (panel_timeline->transition_select == TA_OPENING_TRANSITION && clip->get_opening_transition() != NULL) { - s.in = clip->timeline_in; - if (clip->get_opening_transition()->secondary_clip != NULL) s.in -= clip->get_opening_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; - if (clip->get_closing_transition()->secondary_clip != NULL) s.out += clip->get_closing_transition()->length; - } - sequence->selections.append(s); - } - } + if (panel_timeline->transition_select == TA_OPENING_TRANSITION && clip->get_opening_transition() != NULL) { + s.in = clip->timeline_in; + if (clip->get_opening_transition()->secondary_clip != NULL) s.in -= clip->get_opening_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; + if (clip->get_closing_transition()->secondary_clip != NULL) s.out += clip->get_closing_transition()->length; + } + sequence->selections.append(s); + } } else { // if "shift" is not down if (!shift) { @@ -629,15 +627,17 @@ void TimelineWidget::mousePressEvent(QMouseEvent *event) { s.in = clip->timeline_in; s.out = clip->timeline_out; - if (panel_timeline->transition_select == TA_OPENING_TRANSITION) { - s.out = clip->timeline_in + clip->get_opening_transition()->length; - if (clip->get_opening_transition()->secondary_clip != NULL) s.in -= clip->get_opening_transition()->length; - } + if (panel_timeline->tool == TIMELINE_TOOL_POINTER) { + if (panel_timeline->transition_select == TA_OPENING_TRANSITION) { + s.out = clip->timeline_in + clip->get_opening_transition()->length; + if (clip->get_opening_transition()->secondary_clip != NULL) s.in -= clip->get_opening_transition()->length; + } - if (panel_timeline->transition_select == TA_CLOSING_TRANSITION) { - s.in = clip->timeline_out - clip->get_closing_transition()->length; - if (clip->get_closing_transition()->secondary_clip != NULL) s.out += clip->get_closing_transition()->length; - } + if (panel_timeline->transition_select == TA_CLOSING_TRANSITION) { + s.in = clip->timeline_out - clip->get_closing_transition()->length; + if (clip->get_closing_transition()->secondary_clip != NULL) s.out += clip->get_closing_transition()->length; + } + } s.track = clip->track; sequence->selections.append(s); @@ -1001,16 +1001,16 @@ void TimelineWidget::mouseReleaseEvent(QMouseEvent *event) { const Ghost& g = panel_timeline->ghosts.at(0); if (g.in != g.out) { - Clip* c = sequence->clips.at(g.clip); - long transition_start = qMin(g.in, g.out); long transition_end = qMax(g.in, g.out); - make_room_for_transition(ca, c, panel_timeline->transition_tool_type, transition_start, transition_end, true); + Clip* pre = sequence->clips.at(g.clip); + Clip* post = pre; + + make_room_for_transition(ca, pre, panel_timeline->transition_tool_type, transition_start, transition_end, true); if (panel_timeline->transition_tool_post_clip > -1) { - Clip* pre = c; - Clip* post = sequence->clips.at(panel_timeline->transition_tool_post_clip); + post = sequence->clips.at(panel_timeline->transition_tool_post_clip); int opposite_type = (panel_timeline->transition_tool_type == TA_OPENING_TRANSITION) ? TA_CLOSING_TRANSITION : TA_OPENING_TRANSITION; make_room_for_transition( ca, @@ -1020,33 +1020,47 @@ void TimelineWidget::mouseReleaseEvent(QMouseEvent *event) { transition_end, true ); + if (panel_timeline->transition_tool_type == TA_CLOSING_TRANSITION) { // swap Clip* temp = pre; pre = post; post = temp; } - 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 - QVector areas; - Selection s; - if (transition_start < c->timeline_in) { - s.in = transition_start; - s.out = c->timeline_in; - } else if (transition_end > c->timeline_out) { - s.in = c->timeline_out; - s.out = transition_end; - } - s.track = c->track; - areas.append(s); + } - panel_timeline->delete_areas_and_relink(ca, areas); - ca->append(new MoveClipAction(c, qMin(transition_start, c->timeline_in), qMax(transition_end, c->timeline_out), c->clip_in, c->track)); + if (transition_start < post->timeline_in || transition_end > pre->timeline_out) { + // delete shit over there and extend timeline in + QVector areas; + Selection s; + s.track = post->track; + + bool move_post = false; + bool move_pre = false; + + if (transition_start < post->timeline_in) { + s.in = transition_start; + s.out = post->timeline_in; + areas.append(s); + move_post = true; + } + if (transition_end > pre->timeline_out) { + s.in = pre->timeline_out; + s.out = transition_end; + areas.append(s); + move_pre = true; } - ca->append(new AddTransitionCommand(c, NULL, panel_timeline->transition_tool_meta, panel_timeline->transition_tool_type, transition_end - transition_start)); + panel_timeline->delete_areas_and_relink(ca, areas); + + if (move_post) ca->append(new MoveClipAction(post, qMin(transition_start, post->timeline_in), post->timeline_out, post->clip_in - (post->timeline_in - transition_start), post->track)); + if (move_pre) ca->append(new MoveClipAction(pre, pre->timeline_in, qMax(transition_end, pre->timeline_out), pre->clip_in, pre->track)); + } + + if (panel_timeline->transition_tool_post_clip > -1) { + ca->append(new AddTransitionCommand(pre, post, panel_timeline->transition_tool_meta, TA_OPENING_TRANSITION, transition_end - pre->timeline_in)); + } else { + ca->append(new AddTransitionCommand(pre, NULL, panel_timeline->transition_tool_meta, panel_timeline->transition_tool_type, transition_end - transition_start)); } push_undo = true; @@ -1339,7 +1353,6 @@ void TimelineWidget::update_ghosts(const QPoint& mouse_pos, bool lock_frame) { if (validator < 0) frame_diff += validator; // prevent from going below 0 for the media validator = otc->clip_in + frame_diff - otc->getMaximumLength(); - dout << validator << otc->getMaximumLength(); if (validator > 0) frame_diff -= validator; // prevent transition from exceeding media length } else { validator = otc->clip_in + frame_diff; From 00b31d514e922c94d8dfc99aa7b82d3ca7f4e838 Mon Sep 17 00:00:00 2001 From: itsmattkc Date: Sat, 24 Nov 2018 20:12:51 +1100 Subject: [PATCH 05/31] enforced field semantics and completed shared transitions --- dialogs/speeddialog.cpp | 4 +- effects/internal/audionoiseeffect.cpp | 8 +- effects/internal/cornerpineffect.cpp | 26 +- effects/internal/cubetransition.cpp | 6 +- effects/internal/paneffect.cpp | 7 +- effects/internal/shakeeffect.cpp | 9 +- effects/internal/solideffect.cpp | 14 +- effects/internal/texteffect.cpp | 51 ++-- effects/internal/toneeffect.cpp | 12 +- effects/internal/transformeffect.cpp | 32 +-- effects/internal/volumeeffect.cpp | 5 +- io/config.h | 4 +- io/math.cpp | 4 + io/math.h | 1 + olive.pro | 378 +++++++++++++------------- panels/effectcontrols.cpp | 4 +- panels/project.cpp | 272 +++++++++++------- panels/timeline.cpp | 30 +- panels/timeline.h | 1 + project/clip.cpp | 10 +- project/effect.cpp | 17 +- project/effect.h | 25 +- project/effectfield.cpp | 2 +- project/effectfield.h | 2 +- project/effectrow.cpp | 4 +- project/effectrow.h | 2 +- project/transition.cpp | 2 +- project/undo.cpp | 28 +- project/undo.h | 5 +- ui/timelinewidget.cpp | 128 +++++---- ui/viewerwidget.cpp | 73 ++--- 31 files changed, 635 insertions(+), 531 deletions(-) diff --git a/dialogs/speeddialog.cpp b/dialogs/speeddialog.cpp index 8f85f4594..6713bad1b 100644 --- a/dialogs/speeddialog.cpp +++ b/dialogs/speeddialog.cpp @@ -314,7 +314,7 @@ void set_speed(ComboAction* ca, Clip* c, double speed, bool ripple, long& ep, lo } ep = qMin(ep, c->timeline_out); lr = qMax(lr, proposed_out - c->timeline_out); - ca->append(new MoveClipAction(c, c->timeline_in, proposed_out, c->clip_in * multiplier, c->track)); + move_clip(ca, c, c->timeline_in, proposed_out, c->clip_in * multiplier, c->track); c->refactor_frame_rate(ca, multiplier, false); @@ -346,7 +346,7 @@ void SpeedDialog::accept() { if (reverse->checkState() != Qt::PartiallyChecked && c->reverse != reverse->isChecked()) { long new_clip_in = (c->getMaximumLength() - (c->getLength() + c->clip_in)); - ca->append(new MoveClipAction(c, c->timeline_in, c->timeline_out, new_clip_in, c->track)); + move_clip(ca, c, c->timeline_in, c->timeline_out, new_clip_in, c->track); c->clip_in = new_clip_in; ca->append(new SetBool(&c->reverse, reverse->isChecked())); } diff --git a/effects/internal/audionoiseeffect.cpp b/effects/internal/audionoiseeffect.cpp index 5a65763df..c86c5f38d 100644 --- a/effects/internal/audionoiseeffect.cpp +++ b/effects/internal/audionoiseeffect.cpp @@ -4,14 +4,12 @@ #include AudioNoiseEffect::AudioNoiseEffect(Clip* c, const EffectMeta *em) : Effect(c, em) { - amount_val = add_row("Amount:")->add_field(EFFECT_FIELD_DOUBLE); + amount_val = add_row("Amount:")->add_field(EFFECT_FIELD_DOUBLE, "amount"); amount_val->set_double_minimum_value(0); amount_val->set_double_maximum_value(100); - amount_val->set_double_default_value(20); - amount_val->id = "amount"; + amount_val->set_double_default_value(20); - mix_val = add_row("Mix:")->add_field(EFFECT_FIELD_BOOL); - mix_val->id = "mix"; + mix_val = add_row("Mix:")->add_field(EFFECT_FIELD_BOOL, "mix"); mix_val->set_bool_value(true); srand(QDateTime::currentMSecsSinceEpoch()); diff --git a/effects/internal/cornerpineffect.cpp b/effects/internal/cornerpineffect.cpp index 8e621f880..994d5bb6b 100644 --- a/effects/internal/cornerpineffect.cpp +++ b/effects/internal/cornerpineffect.cpp @@ -9,30 +9,22 @@ CornerPinEffect::CornerPinEffect(Clip *c, const EffectMeta *em) : Effect(c, em) enable_shader = true; EffectRow* top_left = add_row("Top Left:"); - top_left_x = top_left->add_field(EFFECT_FIELD_DOUBLE); - top_left_x->id = "topleftx"; - top_left_y = top_left->add_field(EFFECT_FIELD_DOUBLE); - top_left_y->id = "toplefty"; + top_left_x = top_left->add_field(EFFECT_FIELD_DOUBLE, "topleftx"); + top_left_y = top_left->add_field(EFFECT_FIELD_DOUBLE, "toplefty"); EffectRow* top_right = add_row("Top Right:"); - top_right_x = top_right->add_field(EFFECT_FIELD_DOUBLE); - top_right_x->id = "toprightx"; - top_right_y = top_right->add_field(EFFECT_FIELD_DOUBLE); - top_right_y->id = "toprighty"; + top_right_x = top_right->add_field(EFFECT_FIELD_DOUBLE, "toprightx"); + top_right_y = top_right->add_field(EFFECT_FIELD_DOUBLE, "toprighty"); EffectRow* bottom_left = add_row("Bottom Left:"); - bottom_left_x = bottom_left->add_field(EFFECT_FIELD_DOUBLE); - bottom_left_x->id = "bottomleftx"; - bottom_left_y = bottom_left->add_field(EFFECT_FIELD_DOUBLE); - bottom_left_y->id = "bottomlefty"; + bottom_left_x = bottom_left->add_field(EFFECT_FIELD_DOUBLE, "bottomleftx"); + bottom_left_y = bottom_left->add_field(EFFECT_FIELD_DOUBLE, "bottomlefty"); EffectRow* bottom_right = add_row("Bottom Right:"); - bottom_right_x = bottom_right->add_field(EFFECT_FIELD_DOUBLE); - bottom_right_x->id = "bottomrightx"; - bottom_right_y = bottom_right->add_field(EFFECT_FIELD_DOUBLE); - bottom_right_y->id = "bottomrighty"; + bottom_right_x = bottom_right->add_field(EFFECT_FIELD_DOUBLE, "bottomrightx"); + bottom_right_y = bottom_right->add_field(EFFECT_FIELD_DOUBLE, "bottomrighty"); - perspective = add_row("Perspective:")->add_field(EFFECT_FIELD_BOOL); + perspective = add_row("Perspective:")->add_field(EFFECT_FIELD_BOOL, "perspective"); perspective->set_bool_value(true); connect(top_left_x, SIGNAL(changed()), this, SLOT(field_changed())); diff --git a/effects/internal/cubetransition.cpp b/effects/internal/cubetransition.cpp index ae44537dc..e97cf0c66 100644 --- a/effects/internal/cubetransition.cpp +++ b/effects/internal/cubetransition.cpp @@ -6,6 +6,8 @@ CubeTransition::CubeTransition(Clip* c, Clip* s, const EffectMeta* em) : Transit enable_coords = true; } -void CubeTransition::process_coords(double progress, GLTextureCoords&, int data) { - glTranslatef(-progress, 0, -progress); +void CubeTransition::process_coords(double progress, GLTextureCoords& coords, int data) { + + coords.vertexTopLeftZ = 1; + coords.vertexBottomLeftZ = 1; } diff --git a/effects/internal/paneffect.cpp b/effects/internal/paneffect.cpp index 159cc7136..a9fff136a 100644 --- a/effects/internal/paneffect.cpp +++ b/effects/internal/paneffect.cpp @@ -9,11 +9,10 @@ #include "ui/collapsiblewidget.h" PanEffect::PanEffect(Clip* c, const EffectMeta *em) : Effect(c, em) { - EffectRow* pan_row = add_row("Pan:"); - pan_val = pan_row->add_field(EFFECT_FIELD_DOUBLE); + EffectRow* pan_row = add_row("Pan:"); + pan_val = pan_row->add_field(EFFECT_FIELD_DOUBLE, "pan"); pan_val->set_double_minimum_value(-100); - pan_val->set_double_maximum_value(100); - pan_val->id = "pan"; + pan_val->set_double_maximum_value(100); // set defaults pan_val->set_double_default_value(0); diff --git a/effects/internal/shakeeffect.cpp b/effects/internal/shakeeffect.cpp index 7568bae6b..7460658e4 100644 --- a/effects/internal/shakeeffect.cpp +++ b/effects/internal/shakeeffect.cpp @@ -17,18 +17,15 @@ ShakeEffect::ShakeEffect(Clip *c, const EffectMeta *em) : Effect(c, em) { enable_coords = true; EffectRow* intensity_row = add_row("Intensity:"); - intensity_val = intensity_row->add_field(EFFECT_FIELD_DOUBLE); - intensity_val->id = "intensity"; + intensity_val = intensity_row->add_field(EFFECT_FIELD_DOUBLE, "intensity"); intensity_val->set_double_minimum_value(0); EffectRow* rotation_row = add_row("Rotation:"); - rotation_val = rotation_row->add_field(EFFECT_FIELD_DOUBLE); - rotation_val->id = "rotation"; + rotation_val = rotation_row->add_field(EFFECT_FIELD_DOUBLE, "rotation"); rotation_val->set_double_minimum_value(0); EffectRow* frequency_row = add_row("Frequency:"); - frequency_val = frequency_row->add_field(EFFECT_FIELD_DOUBLE); - frequency_val->id = "frequency"; + frequency_val = frequency_row->add_field(EFFECT_FIELD_DOUBLE, "frequency"); frequency_val->set_double_minimum_value(0); // set defaults diff --git a/effects/internal/solideffect.cpp b/effects/internal/solideffect.cpp index 42006253d..413722569 100644 --- a/effects/internal/solideffect.cpp +++ b/effects/internal/solideffect.cpp @@ -21,26 +21,22 @@ SolidEffect::SolidEffect(Clip* c, const EffectMeta* em) : Effect(c, em) { enable_superimpose = true; - solid_type = add_row("Type:")->add_field(EFFECT_FIELD_COMBO); + solid_type = add_row("Type:")->add_field(EFFECT_FIELD_COMBO, "type"); solid_type->add_combo_item("Solid Color", SOLID_TYPE_COLOR); solid_type->add_combo_item("SMPTE Bars", SOLID_TYPE_BARS); solid_type->add_combo_item("Checkerboard", SOLID_TYPE_CHECKERBOARD); - solid_type->id = "type"; - opacity_field = add_row("Opacity:")->add_field(EFFECT_FIELD_DOUBLE); + opacity_field = add_row("Opacity:")->add_field(EFFECT_FIELD_DOUBLE, "opacity"); opacity_field->set_double_minimum_value(0); opacity_field->set_double_maximum_value(100); opacity_field->set_double_default_value(100); - opacity_field->id = "opacity"; - solid_color_field = add_row("Color:")->add_field(EFFECT_FIELD_COLOR); - solid_color_field->set_color_value(Qt::red); - solid_color_field->id = "color"; + solid_color_field = add_row("Color:")->add_field(EFFECT_FIELD_COLOR, "color"); + solid_color_field->set_color_value(Qt::red); - checkerboard_size_field = add_row("Checkerboard Size:")->add_field(EFFECT_FIELD_DOUBLE); + checkerboard_size_field = add_row("Checkerboard Size:")->add_field(EFFECT_FIELD_DOUBLE, "checker_size"); checkerboard_size_field->set_double_minimum_value(1); checkerboard_size_field->set_double_default_value(10); - checkerboard_size_field->id = "checker_size"; connect(solid_type, SIGNAL(changed()), this, SLOT(field_changed())); connect(solid_color_field, SIGNAL(changed()), this, SLOT(field_changed())); diff --git a/effects/internal/texteffect.cpp b/effects/internal/texteffect.cpp index 2ec788964..e34f4c080 100644 --- a/effects/internal/texteffect.cpp +++ b/effects/internal/texteffect.cpp @@ -24,56 +24,41 @@ TextEffect::TextEffect(Clip *c, const EffectMeta* em) : { enable_superimpose = true; - text_val = add_row("Text:")->add_field(EFFECT_FIELD_STRING, 2); - text_val->id = "text"; + text_val = add_row("Text:")->add_field(EFFECT_FIELD_STRING, "text", 2); - set_font_combobox = add_row("Font:")->add_field(EFFECT_FIELD_FONT, 2); - set_font_combobox->id = "font"; + set_font_combobox = add_row("Font:")->add_field(EFFECT_FIELD_FONT, "font", 2); - size_val = add_row("Size:")->add_field(EFFECT_FIELD_DOUBLE, 2); - size_val->set_double_minimum_value(0); - size_val->id = "size"; + size_val = add_row("Size:")->add_field(EFFECT_FIELD_DOUBLE, "size", 2); + size_val->set_double_minimum_value(0); - set_color_button = add_row("Color:")->add_field(EFFECT_FIELD_COLOR, 2); - set_color_button->id = "color"; + set_color_button = add_row("Color:")->add_field(EFFECT_FIELD_COLOR, "color", 2); EffectRow* alignment_row = add_row("Alignment:"); - halign_field = alignment_row->add_field(EFFECT_FIELD_COMBO); + halign_field = alignment_row->add_field(EFFECT_FIELD_COMBO, "halign"); halign_field->add_combo_item("Left", Qt::AlignLeft); halign_field->add_combo_item("Center", Qt::AlignHCenter); halign_field->add_combo_item("Right", Qt::AlignRight); - halign_field->add_combo_item("Justify", Qt::AlignJustify); - halign_field->id = "halign"; + halign_field->add_combo_item("Justify", Qt::AlignJustify); - valign_field = alignment_row->add_field(EFFECT_FIELD_COMBO); + valign_field = alignment_row->add_field(EFFECT_FIELD_COMBO, "valign"); valign_field->add_combo_item("Top", Qt::AlignTop); valign_field->add_combo_item("Center", Qt::AlignVCenter); - valign_field->add_combo_item("Bottom", Qt::AlignBottom); - valign_field->id = "valign"; + valign_field->add_combo_item("Bottom", Qt::AlignBottom); - word_wrap_field = add_row("Word Wrap:")->add_field(EFFECT_FIELD_BOOL, 2); - word_wrap_field->id = "wordwrap"; + word_wrap_field = add_row("Word Wrap:")->add_field(EFFECT_FIELD_BOOL, "wordwrap", 2); - outline_bool = add_row("Outline:")->add_field(EFFECT_FIELD_BOOL, 2); - outline_bool->id = "outline"; - outline_color = add_row("Outline Color:")->add_field(EFFECT_FIELD_COLOR, 2); - outline_color->id = "outlinecolor"; - outline_width = add_row("Outline Width:")->add_field(EFFECT_FIELD_DOUBLE, 2); - outline_width->id = "outlinewidth"; + outline_bool = add_row("Outline:")->add_field(EFFECT_FIELD_BOOL, "outline", 2); + outline_color = add_row("Outline Color:")->add_field(EFFECT_FIELD_COLOR, "outlinecolor", 2); + outline_width = add_row("Outline Width:")->add_field(EFFECT_FIELD_DOUBLE, "outlinewidth", 2); outline_width->set_double_minimum_value(0); - shadow_bool = add_row("Shadow:")->add_field(EFFECT_FIELD_BOOL, 2); - shadow_bool->id = "shadow"; - shadow_color = add_row("Shadow Color:")->add_field(EFFECT_FIELD_COLOR, 2); - shadow_color->id = "shadowcolor"; - shadow_distance = add_row("Shadow Distance:")->add_field(EFFECT_FIELD_DOUBLE, 2); - shadow_distance->id = "shadowdistance"; + shadow_bool = add_row("Shadow:")->add_field(EFFECT_FIELD_BOOL, "shadow", 2); + shadow_color = add_row("Shadow Color:")->add_field(EFFECT_FIELD_COLOR, "shadowcolor", 2); + shadow_distance = add_row("Shadow Distance:")->add_field(EFFECT_FIELD_DOUBLE, "shadowdistance", 2); shadow_distance->set_double_minimum_value(0); - shadow_softness = add_row("Shadow Softness:")->add_field(EFFECT_FIELD_DOUBLE, 2); - shadow_softness->id = "shadowsoftness"; + shadow_softness = add_row("Shadow Softness:")->add_field(EFFECT_FIELD_DOUBLE, "shadowsoftness", 2); shadow_softness->set_double_minimum_value(0); - shadow_opacity = add_row("Shadow Opacity:")->add_field(EFFECT_FIELD_DOUBLE, 2); - shadow_opacity->id = "shadowopacity"; + shadow_opacity = add_row("Shadow Opacity:")->add_field(EFFECT_FIELD_DOUBLE, "shadowopacity", 2); shadow_opacity->set_double_minimum_value(0); shadow_opacity->set_double_maximum_value(100); diff --git a/effects/internal/toneeffect.cpp b/effects/internal/toneeffect.cpp index 66e24ab17..873a70817 100644 --- a/effects/internal/toneeffect.cpp +++ b/effects/internal/toneeffect.cpp @@ -9,24 +9,20 @@ #include "debug.h" ToneEffect::ToneEffect(Clip* c, const EffectMeta *em) : Effect(c, em), sinX(INT_MIN) { - type_val = add_row("Type:")->add_field(EFFECT_FIELD_COMBO); - type_val->id = "type"; + type_val = add_row("Type:")->add_field(EFFECT_FIELD_COMBO, "type"); type_val->add_combo_item("Sine", TONE_TYPE_SINE); - freq_val = add_row("Frequency:")->add_field(EFFECT_FIELD_DOUBLE); - freq_val->id = "frequency"; + freq_val = add_row("Frequency:")->add_field(EFFECT_FIELD_DOUBLE, "frequency"); freq_val->set_double_minimum_value(20); freq_val->set_double_maximum_value(20000); freq_val->set_double_default_value(1000); - amount_val = add_row("Amount:")->add_field(EFFECT_FIELD_DOUBLE); - amount_val->id = "amount"; + amount_val = add_row("Amount:")->add_field(EFFECT_FIELD_DOUBLE, "amount"); amount_val->set_double_minimum_value(0); amount_val->set_double_maximum_value(100); amount_val->set_double_default_value(25); - mix_val = add_row("Mix:")->add_field(EFFECT_FIELD_BOOL); - mix_val->id = "mix"; + mix_val = add_row("Mix:")->add_field(EFFECT_FIELD_BOOL, "mix"); mix_val->set_bool_value(true); connect(freq_val, SIGNAL(changed()), this, SLOT(field_changed())); diff --git a/effects/internal/transformeffect.cpp b/effects/internal/transformeffect.cpp index 1884d818c..894b291e2 100644 --- a/effects/internal/transformeffect.cpp +++ b/effects/internal/transformeffect.cpp @@ -26,44 +26,34 @@ TransformEffect::TransformEffect(Clip* c, const EffectMeta* em) : Effect(c, em) enable_coords = true; EffectRow* position_row = add_row("Position:"); - position_x = position_row->add_field(EFFECT_FIELD_DOUBLE); // position X - position_x->id = "posx"; - position_y = position_row->add_field(EFFECT_FIELD_DOUBLE); // position Y - position_y->id = "posy"; + position_x = position_row->add_field(EFFECT_FIELD_DOUBLE, "posx"); // position X + position_y = position_row->add_field(EFFECT_FIELD_DOUBLE, "posy"); // position Y EffectRow* scale_row = add_row("Scale:"); - scale_x = scale_row->add_field(EFFECT_FIELD_DOUBLE); // scale X (and Y is uniform scale is selected) - scale_x->id = "scalex"; + scale_x = scale_row->add_field(EFFECT_FIELD_DOUBLE, "scalex"); // scale X (and Y is uniform scale is selected) scale_x->set_double_minimum_value(0); scale_x->set_double_maximum_value(3000); - scale_y = scale_row->add_field(EFFECT_FIELD_DOUBLE); // scale Y (disabled if uniform scale is selected) - scale_y->id = "scaley"; + scale_y = scale_row->add_field(EFFECT_FIELD_DOUBLE, "scaley"); // scale Y (disabled if uniform scale is selected) scale_y->set_double_minimum_value(0); scale_y->set_double_maximum_value(3000); EffectRow* uniform_scale_row = add_row("Uniform Scale:"); - uniform_scale_field = uniform_scale_row->add_field(EFFECT_FIELD_BOOL); // uniform scale option - uniform_scale_field->id = "uniformscale"; + uniform_scale_field = uniform_scale_row->add_field(EFFECT_FIELD_BOOL, "uniformscale"); // uniform scale option EffectRow* rotation_row = add_row("Rotation:"); - rotation = rotation_row->add_field(EFFECT_FIELD_DOUBLE); - rotation->id = "rotation"; + rotation = rotation_row->add_field(EFFECT_FIELD_DOUBLE, "rotation"); EffectRow* anchor_point_row = add_row("Anchor Point:"); - anchor_x_box = anchor_point_row->add_field(EFFECT_FIELD_DOUBLE); // anchor point X - anchor_x_box->id = "anchorx"; - anchor_y_box = anchor_point_row->add_field(EFFECT_FIELD_DOUBLE); // anchor point Y - anchor_y_box->id = "anchory"; + anchor_x_box = anchor_point_row->add_field(EFFECT_FIELD_DOUBLE, "anchorx"); // anchor point X + anchor_y_box = anchor_point_row->add_field(EFFECT_FIELD_DOUBLE, "anchory"); // anchor point Y EffectRow* opacity_row = add_row("Opacity:"); - opacity = opacity_row->add_field(EFFECT_FIELD_DOUBLE); // opacity - opacity->id = "opacity"; + opacity = opacity_row->add_field(EFFECT_FIELD_DOUBLE, "opacity"); // opacity opacity->set_double_minimum_value(0); opacity->set_double_maximum_value(100); EffectRow* blend_mode_row = add_row("Blend Mode:"); - blend_mode_box = blend_mode_row->add_field(EFFECT_FIELD_COMBO); // blend mode - blend_mode_box->id = "blendmode"; + blend_mode_box = blend_mode_row->add_field(EFFECT_FIELD_COMBO, "blendmode"); // blend mode blend_mode_box->add_combo_item("Normal", BLEND_MODE_NORMAL); blend_mode_box->add_combo_item("Overlay", BLEND_MODE_OVERLAY); blend_mode_box->add_combo_item("Screen", BLEND_MODE_SCREEN); @@ -131,7 +121,7 @@ void TransformEffect::process_coords(double timecode, GLTextureCoords& coords, i coords.vertexBottomRightY -= anchor_y_offset; // rotation - glRotatef(rotation->get_double_value(timecode), 0, 0, 1); + glRotatef(rotation->get_double_value(timecode), 0, 0, 1); // scale float sx = scale_x->get_double_value(timecode)*0.01; diff --git a/effects/internal/volumeeffect.cpp b/effects/internal/volumeeffect.cpp index 8ea84e473..a876e810d 100644 --- a/effects/internal/volumeeffect.cpp +++ b/effects/internal/volumeeffect.cpp @@ -9,9 +9,8 @@ #include "ui/collapsiblewidget.h" VolumeEffect::VolumeEffect(Clip* c, const EffectMeta *em) : Effect(c, em) { - EffectRow* volume_row = add_row("Volume:"); - volume_val = volume_row->add_field(EFFECT_FIELD_DOUBLE); - volume_val->id = "volume"; + EffectRow* volume_row = add_row("Volume:"); + volume_val = volume_row->add_field(EFFECT_FIELD_DOUBLE, "volume"); volume_val->set_double_minimum_value(0); // set defaults diff --git a/io/config.h b/io/config.h index fe3b68ce6..5259971a5 100644 --- a/io/config.h +++ b/io/config.h @@ -3,8 +3,8 @@ #include -#define SAVE_VERSION 181114 // YYMMDD -#define MIN_SAVE_VERSION 180820 // lowest compatible project version +#define SAVE_VERSION 181124 // YYMMDD +#define MIN_SAVE_VERSION 181114 // lowest compatible project version #define TIMECODE_DROP 0 #define TIMECODE_NONDROP 1 diff --git a/io/math.cpp b/io/math.cpp index 32a12db6e..c26bb5cad 100644 --- a/io/math.cpp +++ b/io/math.cpp @@ -6,6 +6,10 @@ int lerp(int a, int b, double t) { return qRound(((1.0 - t) * a) + (t * b)); } +float float_lerp(float a, float b, float t) { + return ((1.0F - t) * a) + (t * b); +} + double double_lerp(double a, double b, double t) { return ((1.0 - t) * a) + (t * b); } diff --git a/io/math.h b/io/math.h index 68264cff7..927e988ac 100644 --- a/io/math.h +++ b/io/math.h @@ -2,6 +2,7 @@ #define MATH_H int lerp(int a, int b, double t); +float float_lerp(float a, float b, float t); double double_lerp(double a, double b, double t); #endif // MATH_H diff --git a/olive.pro b/olive.pro index 4e45e4ea8..f81d7e964 100644 --- a/olive.pro +++ b/olive.pro @@ -1,189 +1,189 @@ -#------------------------------------------------- -# -# Project created by QtCreator 2018-05-11T10:31:59 -# -#------------------------------------------------- - -QT += core gui multimedia opengl - -greaterThan(QT_MAJOR_VERSION, 4): QT += widgets - -TARGET = Olive -TEMPLATE = app - -# The following define makes your compiler emit warnings if you use -# any feature of Qt which has been marked as deprecated (the exact warnings -# depend on your compiler). Please consult the documentation of the -# deprecated API in order to know how to port your code away from it. -DEFINES += QT_DEPRECATED_WARNINGS - -# You can also make your code fail to compile if you use deprecated APIs. -# In order to do so, uncomment the following line. -# You can also select to disable deprecated APIs only up to a certain version of Qt. -#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0 - - -SOURCES += \ - main.cpp \ - mainwindow.cpp \ - panels/project.cpp \ - panels/effectcontrols.cpp \ - panels/viewer.cpp \ - panels/timeline.cpp \ - ui/sourcetable.cpp \ - dialogs/aboutdialog.cpp \ - ui/timelinewidget.cpp \ - io/media.cpp \ - project/sequence.cpp \ - project/clip.cpp \ - playback/playback.cpp \ - playback/audio.cpp \ - io/config.cpp \ - dialogs/newsequencedialog.cpp \ - ui/viewerwidget.cpp \ - ui/viewercontainer.cpp \ - dialogs/exportdialog.cpp \ - ui/collapsiblewidget.cpp \ - panels/panels.cpp \ - playback/cacher.cpp \ - io/exportthread.cpp \ - ui/timelineheader.cpp \ - io/previewgenerator.cpp \ - ui/labelslider.cpp \ - dialogs/preferencesdialog.cpp \ - ui/audiomonitor.cpp \ - project/undo.cpp \ - ui/scrollarea.cpp \ - ui/comboboxex.cpp \ - ui/colorbutton.cpp \ - dialogs/replaceclipmediadialog.cpp \ - ui/fontcombobox.cpp \ - ui/checkboxex.cpp \ - ui/keyframeview.cpp \ - ui/texteditex.cpp \ - dialogs/demonotice.cpp \ - project/marker.cpp \ - dialogs/speeddialog.cpp \ - dialogs/mediapropertiesdialog.cpp \ - io/crc32.cpp \ - dialogs/loaddialog.cpp \ - debug.cpp \ - io/path.cpp \ - effects/internal/linearfadetransition.cpp \ - effects/internal/transformeffect.cpp \ - effects/internal/solideffect.cpp \ - effects/internal/texteffect.cpp \ - effects/internal/audionoiseeffect.cpp \ - effects/internal/paneffect.cpp \ - effects/internal/toneeffect.cpp \ - effects/internal/volumeeffect.cpp \ - effects/internal/crossdissolvetransition.cpp \ - effects/internal/shakeeffect.cpp \ - effects/internal/exponentialfadetransition.cpp \ - effects/internal/logarithmicfadetransition.cpp \ - effects/internal/cornerpineffect.cpp \ - io/math.cpp \ - io/qpainterwrapper.cpp \ - project/effect.cpp \ - project/transition.cpp \ - project/effectrow.cpp \ - project/effectfield.cpp \ - effects/internal/cubetransition.cpp - -HEADERS += \ - mainwindow.h \ - panels/project.h \ - panels/effectcontrols.h \ - panels/viewer.h \ - panels/timeline.h \ - ui/sourcetable.h \ - dialogs/aboutdialog.h \ - ui/timelinewidget.h \ - io/media.h \ - project/sequence.h \ - project/clip.h \ - playback/playback.h \ - playback/audio.h \ - io/config.h \ - dialogs/newsequencedialog.h \ - ui/viewerwidget.h \ - ui/viewercontainer.h \ - dialogs/exportdialog.h \ - ui/collapsiblewidget.h \ - panels/panels.h \ - playback/cacher.h \ - io/exportthread.h \ - ui/timelinetools.h \ - ui/timelineheader.h \ - io/previewgenerator.h \ - ui/labelslider.h \ - dialogs/preferencesdialog.h \ - ui/audiomonitor.h \ - project/undo.h \ - ui/scrollarea.h \ - ui/comboboxex.h \ - ui/colorbutton.h \ - dialogs/replaceclipmediadialog.h \ - ui/fontcombobox.h \ - ui/checkboxex.h \ - ui/keyframeview.h \ - ui/texteditex.h \ - dialogs/demonotice.h \ - project/marker.h \ - project/selection.h \ - dialogs/speeddialog.h \ - dialogs/mediapropertiesdialog.h \ - io/crc32.h \ - dialogs/loaddialog.h \ - debug.h \ - io/path.h \ - effects/internal/transformeffect.h \ - effects/internal/solideffect.h \ - effects/internal/texteffect.h \ - effects/internal/audionoiseeffect.h \ - effects/internal/paneffect.h \ - effects/internal/toneeffect.h \ - effects/internal/volumeeffect.h \ - effects/internal/shakeeffect.h \ - effects/internal/linearfadetransition.h \ - effects/internal/crossdissolvetransition.h \ - effects/internal/exponentialfadetransition.h \ - effects/internal/logarithmicfadetransition.h \ - effects/internal/cornerpineffect.h \ - io/math.h \ - io/qpainterwrapper.h \ - project/effect.h \ - project/transition.h \ - project/effectrow.h \ - project/effectfield.h \ - effects/internal/cubetransition.h - -FORMS += \ - mainwindow.ui \ - panels/project.ui \ - panels/effectcontrols.ui \ - panels/viewer.ui \ - panels/timeline.ui \ - dialogs/aboutdialog.ui \ - dialogs/newsequencedialog.ui \ - dialogs/exportdialog.ui \ - dialogs/preferencesdialog.ui \ - dialogs/demonotice.ui - -win32 { - RC_FILE = icons/resources.rc - LIBS += -lavutil -lavformat -lavcodec -lavfilter -lswscale -lswresample -lopengl32 -} - -mac { - LIBS += -L/usr/local/lib -lavutil -lavformat -lavcodec -lavfilter -lswscale -lswresample - ICON = icons/olive.icns - INCLUDEPATH = /usr/local/include -} - -linux { - LIBS += -lavutil -lavformat -lavcodec -lavfilter -lswscale -lswresample -} - -RESOURCES += \ - icons/icons.qrc +#------------------------------------------------- +# +# Project created by QtCreator 2018-05-11T10:31:59 +# +#------------------------------------------------- + +QT += core gui multimedia opengl + +greaterThan(QT_MAJOR_VERSION, 4): QT += widgets + +TARGET = Olive +TEMPLATE = app + +# The following define makes your compiler emit warnings if you use +# any feature of Qt which has been marked as deprecated (the exact warnings +# depend on your compiler). Please consult the documentation of the +# deprecated API in order to know how to port your code away from it. +DEFINES += QT_DEPRECATED_WARNINGS + +# You can also make your code fail to compile if you use deprecated APIs. +# In order to do so, uncomment the following line. +# You can also select to disable deprecated APIs only up to a certain version of Qt. +#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0 + + +SOURCES += \ + main.cpp \ + mainwindow.cpp \ + panels/project.cpp \ + panels/effectcontrols.cpp \ + panels/viewer.cpp \ + panels/timeline.cpp \ + ui/sourcetable.cpp \ + dialogs/aboutdialog.cpp \ + ui/timelinewidget.cpp \ + io/media.cpp \ + project/sequence.cpp \ + project/clip.cpp \ + playback/playback.cpp \ + playback/audio.cpp \ + io/config.cpp \ + dialogs/newsequencedialog.cpp \ + ui/viewerwidget.cpp \ + ui/viewercontainer.cpp \ + dialogs/exportdialog.cpp \ + ui/collapsiblewidget.cpp \ + panels/panels.cpp \ + playback/cacher.cpp \ + io/exportthread.cpp \ + ui/timelineheader.cpp \ + io/previewgenerator.cpp \ + ui/labelslider.cpp \ + dialogs/preferencesdialog.cpp \ + ui/audiomonitor.cpp \ + project/undo.cpp \ + ui/scrollarea.cpp \ + ui/comboboxex.cpp \ + ui/colorbutton.cpp \ + dialogs/replaceclipmediadialog.cpp \ + ui/fontcombobox.cpp \ + ui/checkboxex.cpp \ + ui/keyframeview.cpp \ + ui/texteditex.cpp \ + dialogs/demonotice.cpp \ + project/marker.cpp \ + dialogs/speeddialog.cpp \ + dialogs/mediapropertiesdialog.cpp \ + io/crc32.cpp \ + dialogs/loaddialog.cpp \ + debug.cpp \ + io/path.cpp \ + effects/internal/linearfadetransition.cpp \ + effects/internal/transformeffect.cpp \ + effects/internal/solideffect.cpp \ + effects/internal/texteffect.cpp \ + effects/internal/audionoiseeffect.cpp \ + effects/internal/paneffect.cpp \ + effects/internal/toneeffect.cpp \ + effects/internal/volumeeffect.cpp \ + effects/internal/crossdissolvetransition.cpp \ + effects/internal/shakeeffect.cpp \ + effects/internal/exponentialfadetransition.cpp \ + effects/internal/logarithmicfadetransition.cpp \ + effects/internal/cornerpineffect.cpp \ + io/math.cpp \ + io/qpainterwrapper.cpp \ + project/effect.cpp \ + project/transition.cpp \ + project/effectrow.cpp \ + project/effectfield.cpp \ + effects/internal/cubetransition.cpp + +HEADERS += \ + mainwindow.h \ + panels/project.h \ + panels/effectcontrols.h \ + panels/viewer.h \ + panels/timeline.h \ + ui/sourcetable.h \ + dialogs/aboutdialog.h \ + ui/timelinewidget.h \ + io/media.h \ + project/sequence.h \ + project/clip.h \ + playback/playback.h \ + playback/audio.h \ + io/config.h \ + dialogs/newsequencedialog.h \ + ui/viewerwidget.h \ + ui/viewercontainer.h \ + dialogs/exportdialog.h \ + ui/collapsiblewidget.h \ + panels/panels.h \ + playback/cacher.h \ + io/exportthread.h \ + ui/timelinetools.h \ + ui/timelineheader.h \ + io/previewgenerator.h \ + ui/labelslider.h \ + dialogs/preferencesdialog.h \ + ui/audiomonitor.h \ + project/undo.h \ + ui/scrollarea.h \ + ui/comboboxex.h \ + ui/colorbutton.h \ + dialogs/replaceclipmediadialog.h \ + ui/fontcombobox.h \ + ui/checkboxex.h \ + ui/keyframeview.h \ + ui/texteditex.h \ + dialogs/demonotice.h \ + project/marker.h \ + project/selection.h \ + dialogs/speeddialog.h \ + dialogs/mediapropertiesdialog.h \ + io/crc32.h \ + dialogs/loaddialog.h \ + debug.h \ + io/path.h \ + effects/internal/transformeffect.h \ + effects/internal/solideffect.h \ + effects/internal/texteffect.h \ + effects/internal/audionoiseeffect.h \ + effects/internal/paneffect.h \ + effects/internal/toneeffect.h \ + effects/internal/volumeeffect.h \ + effects/internal/shakeeffect.h \ + effects/internal/linearfadetransition.h \ + effects/internal/crossdissolvetransition.h \ + effects/internal/exponentialfadetransition.h \ + effects/internal/logarithmicfadetransition.h \ + effects/internal/cornerpineffect.h \ + io/math.h \ + io/qpainterwrapper.h \ + project/effect.h \ + project/transition.h \ + project/effectrow.h \ + project/effectfield.h \ + effects/internal/cubetransition.h + +FORMS += \ + mainwindow.ui \ + panels/project.ui \ + panels/effectcontrols.ui \ + panels/viewer.ui \ + panels/timeline.ui \ + dialogs/aboutdialog.ui \ + dialogs/newsequencedialog.ui \ + dialogs/exportdialog.ui \ + dialogs/preferencesdialog.ui \ + dialogs/demonotice.ui + +win32 { + RC_FILE = icons/resources.rc + LIBS += -lavutil -lavformat -lavcodec -lavfilter -lswscale -lswresample -lopengl32 +} + +mac { + LIBS += -L/usr/local/lib -lavutil -lavformat -lavcodec -lavfilter -lswscale -lswresample + ICON = icons/olive.icns + INCLUDEPATH = /usr/local/include +} + +linux { + LIBS += -lavutil -lavformat -lavcodec -lavfilter -lswscale -lswresample +} + +RESOURCES += \ + icons/icons.qrc diff --git a/panels/effectcontrols.cpp b/panels/effectcontrols.cpp index 095c25e06..727fa3bf5 100644 --- a/panels/effectcontrols.cpp +++ b/panels/effectcontrols.cpp @@ -68,10 +68,10 @@ void EffectControls::menu_select(QAction* q) { const EffectMeta* meta = reinterpret_cast(q->data().value()); if (transition_menu) { if (c->get_opening_transition() == NULL) { - ca->append(new AddTransitionCommand(c, NULL, meta, TA_OPENING_TRANSITION, 30)); + ca->append(new AddTransitionCommand(c, NULL, NULL, meta, TA_OPENING_TRANSITION, 30)); } if (c->get_closing_transition() == NULL) { - ca->append(new AddTransitionCommand(c, NULL, meta, TA_CLOSING_TRANSITION, 30)); + ca->append(new AddTransitionCommand(c, NULL, NULL, meta, TA_CLOSING_TRANSITION, 30)); } } else { ca->append(new AddEffectCommand(c, meta)); diff --git a/panels/project.cpp b/panels/project.cpp index 1794edcf7..74228c232 100644 --- a/panels/project.cpp +++ b/panels/project.cpp @@ -808,6 +808,102 @@ QTreeWidgetItem* Project::find_loaded_folder_by_id(int id) { return NULL; } +const EffectMeta* get_meta_from_name(const QString& name, int type) { + QVector& effect_list = (type == EFFECT_TYPE_VIDEO) ? video_effects : audio_effects; + for (int j=0;jtrack < 0) ? "Transform" : "Volume"; break; + case 1: effect_name = (c->track < 0) ? "Shake" : "Pan"; break; + case 2: effect_name = (c->track < 0) ? "Text" : "Noise"; break; + case 3: effect_name = (c->track < 0) ? "Solid" : "Tone"; break; + case 4: effect_name = "Invert"; break; + case 5: effect_name = "Chroma Key"; break; + case 6: effect_name = "Gaussian Blur"; break; + case 7: effect_name = "Crop"; break; + case 8: effect_name = "Flip"; break; + case 9: effect_name = "Box Blur"; break; + case 10: effect_name = "Wave"; break; + case 11: effect_name = "Temperature"; break; + } + } + + // wait for effects to be loaded + effects_loaded.lock(); + + const EffectMeta* meta = NULL; + + // find effect with this name + if (!effect_name.isEmpty()) { + meta = get_meta_from_name(effect_name, (c->track < 0) ? EFFECT_TYPE_VIDEO : EFFECT_TYPE_AUDIO); + } + + effects_loaded.unlock(); + + if (meta == NULL) { + dout << "[WARNING] An effect used by this project is missing. It was not loaded."; + } else { + QString tag = stream.name().toString(); + + if (tag == "opening" || tag == "closing") { + // TODO replace NULL/s with something else + + int transition_index = create_transition(c, NULL, 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 = transition_index; + } else { + c->closing_transition = transition_index; + } + } else { + Effect* e = create_effect(c, meta); + e->set_enabled(effect_enabled); + e->load(stream); + + c->effects.append(e); + } + } +} + +struct TransitionData { + int id; + QString name; + long length; + Clip* otc; + Clip* ctc; +}; + bool Project::load_worker(QFile& f, QXmlStreamReader& stream, int type) { f.seek(0); stream.setDevice(stream.device()); @@ -968,6 +1064,8 @@ bool Project::load_worker(QFile& f, QXmlStreamReader& stream, int type) { } } + QVector transition_data; + // load all clips and clip information while (!(stream.name() == child_search && stream.isEndElement()) && !stream.atEnd()) { stream.readNextStartElement(); @@ -982,7 +1080,22 @@ bool Project::load_worker(QFile& f, QXmlStreamReader& stream, int type) { } } s->markers.append(m); - } else if (stream.name() == "clip" && stream.isStartElement()) { + } else if (stream.name() == "transition" && stream.isStartElement()) { + TransitionData td; + td.otc = NULL; + td.ctc = NULL; + for (int j=0;jmaintain_audio_pitch = (attr.value() == "1"); } else if (attr.name() == "reverse") { c->reverse = (attr.value() == "1"); + } else if (attr.name() == "opening") { + c->opening_transition = attr.value().toInt(); + } else if (attr.name() == "closing") { + c->closing_transition = attr.value().toInt(); } else if (attr.name() == "sequence") { c->media_type = MEDIA_TYPE_SEQUENCE; @@ -1072,87 +1189,9 @@ 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; - long effect_length = -1; - for (int j=0;jtrack < 0) ? "Transform" : "Volume"; break; - case 1: effect_name = (c->track < 0) ? "Shake" : "Pan"; break; - case 2: effect_name = (c->track < 0) ? "Text" : "Noise"; break; - case 3: effect_name = (c->track < 0) ? "Solid" : "Tone"; break; - case 4: effect_name = "Invert"; break; - case 5: effect_name = "Chroma Key"; break; - case 6: effect_name = "Gaussian Blur"; break; - case 7: effect_name = "Crop"; break; - case 8: effect_name = "Flip"; break; - case 9: effect_name = "Box Blur"; break; - case 10: effect_name = "Wave"; break; - case 11: effect_name = "Temperature"; break; - } - } - - // wait for effects to be loaded - effects_loaded.lock(); - - const EffectMeta* meta = NULL; - - // find effect with this name - if (!effect_name.isEmpty()) { - QVector& effect_list = (c->track < 0) ? video_effects : audio_effects; - for (int j=0;jsequence->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 = transition_index; - } else { - c->closing_transition = transition_index; - } - } else { - Effect* e = create_effect(c, meta); - e->set_enabled(effect_enabled); - e->load(stream); - - c->effects.append(e); - } - } + } else if (stream.isStartElement() && (stream.name() == "effect" || stream.name() == "opening" || stream.name() == "closing")) { + // "opening" and "closing" are backwards compatibility code + load_effect(stream, c); } } } @@ -1161,8 +1200,8 @@ bool Project::load_worker(QFile& f, QXmlStreamReader& stream, int type) { } } - // correct links and clip IDs - for (int i=0;iclips.size();i++) { + // correct links, clip IDs, transitions + for (int i=0;iclips.size();i++) { // correct links Clip* correct_clip = s->clips.at(i); for (int j=0;jlinked.size();j++) { @@ -1183,6 +1222,44 @@ bool Project::load_worker(QFile& f, QXmlStreamReader& stream, int type) { } } } + + // re-link clips to transitions + if (correct_clip->opening_transition > -1) { + for (int j=0;jopening_transition) { + transition_data[j].otc = correct_clip; + } + } + } + if (correct_clip->closing_transition > -1) { + for (int j=0;jclosing_transition) { + transition_data[j].ctc = correct_clip; + } + } + } + } + + // create transitions + for (int i=0;itrack < 0) ? EFFECT_TYPE_VIDEO : EFFECT_TYPE_AUDIO); + if (meta == NULL) { + dout << "[WARNING] Failed to link transition with name:" << td.name; + if (td.otc != NULL) td.otc->opening_transition = -1; + if (td.ctc != NULL) td.ctc->closing_transition = -1; + } else { + int transition_index = create_transition(primary, secondary, meta); + primary->sequence->transitions.at(transition_index)->length = td.length; + if (td.otc != NULL) td.otc->opening_transition = transition_index; + if (td.ctc != NULL) td.ctc->closing_transition = transition_index; + } } new_sequence(NULL, s, false, parent); @@ -1414,6 +1491,17 @@ void Project::save_folder(QXmlStreamWriter& stream, QTreeWidgetItem* parent, int stream.writeAttribute("workarea", QString::number(s->using_workarea)); stream.writeAttribute("workareaIn", QString::number(s->workarea_in)); stream.writeAttribute("workareaOut", QString::number(s->workarea_out)); + + for (int j=0;jtransitions.size();j++) { + Transition* t = s->transitions.at(j); + if (t != NULL) { + stream.writeStartElement("transition"); + stream.writeAttribute("id", QString::number(j)); + t->save(stream); + stream.writeEndElement(); // transition + } + } + for (int j=0;jclips.size();j++) { Clip* c = s->clips.at(j); if (c != NULL) { @@ -1425,6 +1513,8 @@ void Project::save_folder(QXmlStreamWriter& stream, QTreeWidgetItem* parent, int stream.writeAttribute("in", QString::number(c->timeline_in)); stream.writeAttribute("out", QString::number(c->timeline_out)); stream.writeAttribute("track", QString::number(c->track)); + stream.writeAttribute("opening", QString::number(c->opening_transition)); + stream.writeAttribute("closing", QString::number(c->closing_transition)); stream.writeAttribute("r", QString::number(c->color_r)); stream.writeAttribute("g", QString::number(c->color_g)); @@ -1458,19 +1548,7 @@ void Project::save_folder(QXmlStreamWriter& stream, QTreeWidgetItem* parent, int stream.writeStartElement("effect"); // effect c->effects.at(k)->save(stream); stream.writeEndElement(); // effect - } - - if (c->get_opening_transition() != NULL) { - stream.writeStartElement("opening"); - c->get_opening_transition()->save(stream); - stream.writeEndElement(); // opening - } - - if (c->get_closing_transition() != NULL) { - stream.writeStartElement("closing"); // closing - c->get_closing_transition()->save(stream); - stream.writeEndElement(); // closing - } + } stream.writeEndElement(); // clip } diff --git a/panels/timeline.cpp b/panels/timeline.cpp index 9d041f484..4d9ce5b6e 100644 --- a/panels/timeline.cpp +++ b/panels/timeline.cpp @@ -355,11 +355,11 @@ void Timeline::add_transition() { Clip* c = sequence->clips.at(i); if (c != NULL && is_clip_selected(c, true)) { if (c->get_opening_transition() == NULL) { - ca->append(new AddTransitionCommand(c, NULL, get_internal_meta(TRANSITION_INTERNAL_LINEARFADE), TA_OPENING_TRANSITION, 30)); + ca->append(new AddTransitionCommand(c, NULL, NULL, get_internal_meta(TRANSITION_INTERNAL_LINEARFADE), TA_OPENING_TRANSITION, 30)); adding = true; } if (c->get_closing_transition() == NULL) { - ca->append(new AddTransitionCommand(c, NULL, get_internal_meta(TRANSITION_INTERNAL_LINEARFADE), TA_OPENING_TRANSITION, 30)); + ca->append(new AddTransitionCommand(c, NULL, NULL, get_internal_meta(TRANSITION_INTERNAL_LINEARFADE), TA_OPENING_TRANSITION, 30)); adding = true; } } @@ -634,7 +634,7 @@ Clip* Timeline::split_clip(ComboAction* ca, int p, long frame, long post_in) { post->timeline_in = post_in; post->clip_in = pre->clip_in + (post->timeline_in - pre->timeline_in); - ca->append(new MoveClipAction(pre, pre->timeline_in, frame, pre->clip_in, pre->track)); + move_clip(ca, pre, pre->timeline_in, frame, pre->clip_in, pre->track); if (pre->get_opening_transition() != NULL) { /*if (frame < pre->timeline_in + pre->get_opening_transition()->length && pre->get_opening_transition()->secondary_clip != NULL) { @@ -792,7 +792,7 @@ void Timeline::delete_areas_and_relink(ComboAction* ca, QVector& area post_clips.append(post); } else if (c->timeline_in < s.in && c->timeline_out > s.in) { // only out point is in deletion area - ca->append(new MoveClipAction(c, c->timeline_in, s.in, c->clip_in, c->track)); + move_clip(ca, c, c->timeline_in, s.in, c->clip_in, c->track); if (c->get_closing_transition() != NULL) { if (s.in < c->timeline_out - c->get_closing_transition()->length) { @@ -803,7 +803,7 @@ void Timeline::delete_areas_and_relink(ComboAction* ca, QVector& area } } 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)); + move_clip(ca, c, s.out, c->timeline_out, c->clip_in + (s.out - c->timeline_in), c->track); if (c->get_opening_transition() != NULL) { if (s.out > c->timeline_in + c->get_opening_transition()->length) { @@ -1075,7 +1075,7 @@ bool Timeline::split_selection(ComboAction* ca) { 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)); + move_clip(ca, clip, clip->timeline_in, s.in, clip->clip_in, clip->track); split = true; } else { Clip* post_a = split_clip(ca, j, s.in); @@ -1489,3 +1489,21 @@ void Timeline::transition_menu_select(QAction* a) { tool = TIMELINE_TOOL_TRANSITION; ui->toolTransitionButton->setChecked(true); } + +void move_clip(ComboAction* ca, Clip *c, long iin, long iout, long iclip_in, int itrack, bool verify_transitions) { + ca->append(new MoveClipAction(c, iin, iout, iclip_in, itrack)); + + if (verify_transitions) { + if (c->get_opening_transition() != NULL && c->get_opening_transition()->secondary_clip != NULL && c->get_opening_transition()->secondary_clip->timeline_out != iin) { + // separate transition + ca->append(new SetPointer((void**) &c->get_opening_transition()->secondary_clip, NULL)); + ca->append(new AddTransitionCommand(c->get_opening_transition()->secondary_clip, NULL, c->get_opening_transition(), NULL, TA_CLOSING_TRANSITION, 0)); + } + + if (c->get_closing_transition() != NULL && c->get_closing_transition()->secondary_clip != NULL && c->get_closing_transition()->parent_clip->timeline_in != iout) { + // separate transition + ca->append(new SetPointer((void**) &c->get_closing_transition()->secondary_clip, NULL)); + ca->append(new AddTransitionCommand(c, NULL, c->get_closing_transition(), NULL, TA_CLOSING_TRANSITION, 0)); + } + } +} diff --git a/panels/timeline.h b/panels/timeline.h index 96c2f97be..a218ae2cd 100644 --- a/panels/timeline.h +++ b/panels/timeline.h @@ -34,6 +34,7 @@ int getScreenPointFromFrame(double zoom, long frame); long getFrameFromScreenPoint(double zoom, int x); void draw_selection_rectangle(QPainter& painter, const QRect& rect); bool selection_contains_transition(const Selection& s, Clip* c, int type); +void move_clip(ComboAction *ca, Clip *c, long iin, long iout, long iclip_in, int itrack, bool verify_transitions = true); struct Ghost { int clip; diff --git a/project/clip.cpp b/project/clip.cpp index 1cfcb71c6..d136f666c 100644 --- a/project/clip.cpp +++ b/project/clip.cpp @@ -293,11 +293,11 @@ int Clip::getHeight() { void Clip::refactor_frame_rate(ComboAction* ca, double multiplier, bool change_timeline_points) { if (change_timeline_points) { - ca->append(new MoveClipAction(this, - qRound((double) timeline_in * multiplier), - qRound((double) timeline_out * multiplier), - qRound((double) clip_in * multiplier), - track)); + move_clip(ca, this, + qRound((double) timeline_in * multiplier), + qRound((double) timeline_out * multiplier), + qRound((double) clip_in * multiplier), + track); } for (int i=0;ifilename << "- ID cannot be empty."; } else if (type > -1) { - EffectField* field = row->add_field(type); - field->id = id; + EffectField* field = row->add_field(type, id); connect(field, SIGNAL(changed()), this, SLOT(field_changed())); switch (type) { case EFFECT_FIELD_DOUBLE: diff --git a/project/effect.h b/project/effect.h index d91a1d24e..0caf160ce 100644 --- a/project/effect.h +++ b/project/effect.h @@ -63,7 +63,6 @@ extern QMutex effects_loaded; - #define EFFECT_INTERNAL_CORNERPIN 12 #define EFFECT_INTERNAL_COUNT 13 @@ -76,21 +75,29 @@ struct GLTextureCoords { int vertexTopLeftX; int vertexTopLeftY; + int vertexTopLeftZ; int vertexTopRightX; int vertexTopRightY; + int vertexTopRightZ; int vertexBottomLeftX; int vertexBottomLeftY; + int vertexBottomLeftZ; int vertexBottomRightX; int vertexBottomRightY; + int vertexBottomRightZ; - double textureTopLeftX; - double textureTopLeftY; - double textureTopRightX; - double textureTopRightY; - double textureBottomRightX; - double textureBottomRightY; - double textureBottomLeftX; - double textureBottomLeftY; + float textureTopLeftX; + float textureTopLeftY; + float textureTopLeftQ; + float textureTopRightX; + float textureTopRightY; + float textureTopRightQ; + float textureBottomRightX; + float textureBottomRightY; + float textureBottomRightQ; + float textureBottomLeftX; + float textureBottomLeftY; + float textureBottomLeftQ; }; qint16 mix_audio_sample(qint16 a, qint16 b); diff --git a/project/effectfield.cpp b/project/effectfield.cpp index 51f8331c5..f2893f97f 100644 --- a/project/effectfield.cpp +++ b/project/effectfield.cpp @@ -17,7 +17,7 @@ #include "io/math.h" #include -EffectField::EffectField(EffectRow *parent, int t) : parent_row(parent), type(t) { +EffectField::EffectField(EffectRow *parent, int t, const QString &i) : parent_row(parent), type(t), id(i) { switch (t) { case EFFECT_FIELD_DOUBLE: { diff --git a/project/effectfield.h b/project/effectfield.h index 7c61ee967..c94d6a3fb 100644 --- a/project/effectfield.h +++ b/project/effectfield.h @@ -17,7 +17,7 @@ class EffectRow; class EffectField : public QObject { Q_OBJECT public: - EffectField(EffectRow* parent, int t); + EffectField(EffectRow* parent, int t, const QString& i); EffectRow* parent_row; int type; QString id; diff --git a/project/effectrow.cpp b/project/effectrow.cpp index c4fd58f11..0772162f0 100644 --- a/project/effectrow.cpp +++ b/project/effectrow.cpp @@ -144,8 +144,8 @@ void EffectRow::goto_next_key() { if (key != LONG_MAX) panel_sequence_viewer->seek(key); } -EffectField* EffectRow::add_field(int type, int colspan) { - EffectField* field = new EffectField(this, type); +EffectField* EffectRow::add_field(int type, const QString& id, int colspan) { + EffectField* field = new EffectField(this, type, id); fields.append(field); QWidget* element = field->get_ui_element(); ui->addWidget(element, ui_row, fields.size(), 1, colspan); diff --git a/project/effectrow.h b/project/effectrow.h index f74940326..5a6305a09 100644 --- a/project/effectrow.h +++ b/project/effectrow.h @@ -16,7 +16,7 @@ class EffectRow : public QObject { public: EffectRow(Effect* parent, QGridLayout* uilayout, const QString& n, int row); ~EffectRow(); - EffectField* add_field(int type, int colspan = 1); + EffectField* add_field(int type, const QString &id, int colspan = 1); EffectField* field(int i); int fieldCount(); void set_keyframe_now(bool undoable); diff --git a/project/transition.cpp b/project/transition.cpp index 23d12fa6d..51467c14e 100644 --- a/project/transition.cpp +++ b/project/transition.cpp @@ -14,7 +14,7 @@ #include Transition::Transition(Clip* c, Clip* s, const EffectMeta* em) : Effect(c, em), secondary_clip(s) { - add_row("Length:")->add_field(EFFECT_FIELD_DOUBLE); + //add_row("Length:")->add_field(EFFECT_FIELD_DOUBLE); } int Transition::copy(Clip *c, Clip* s) { diff --git a/project/undo.cpp b/project/undo.cpp index 0b514d4cb..22c1f8a0b 100644 --- a/project/undo.cpp +++ b/project/undo.cpp @@ -224,9 +224,10 @@ void AddEffectCommand::redo() { mainWindow->setWindowModified(true); } -AddTransitionCommand::AddTransitionCommand(Clip* c, Clip *s, const EffectMeta *itransition, int itype, int ilength) : +AddTransitionCommand::AddTransitionCommand(Clip* c, Clip *s, Transition* copy, const EffectMeta *itransition, int itype, int ilength) : clip(c), secondary(s), + transition_to_copy(copy), transition(itransition), type(itype), length(ilength), @@ -236,19 +237,36 @@ AddTransitionCommand::AddTransitionCommand(Clip* c, Clip *s, const EffectMeta *i void AddTransitionCommand::undo() { clip->sequence->hard_delete_transition(clip, type); if (secondary != NULL) secondary->sequence->hard_delete_transition(secondary, (type == TA_OPENING_TRANSITION) ? TA_CLOSING_TRANSITION : TA_OPENING_TRANSITION); + + if (type == TA_OPENING_TRANSITION) { + clip->opening_transition = old_ptransition; + if (secondary != NULL) secondary->closing_transition = old_stransition; + } else { + clip->closing_transition = old_ptransition; + if (secondary != NULL) secondary->opening_transition = old_stransition; + } + mainWindow->setWindowModified(old_project_changed); } 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; + old_ptransition = clip->opening_transition; + clip->opening_transition = (transition_to_copy == NULL) ? create_transition(clip, secondary, transition) : transition_to_copy->copy(clip, NULL); + if (secondary != NULL) { + old_stransition = secondary->closing_transition; + secondary->closing_transition = clip->opening_transition; + } 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; + old_ptransition = clip->closing_transition; + clip->closing_transition = (transition_to_copy == NULL) ? create_transition(clip, secondary, transition) : transition_to_copy->copy(clip, NULL); + if (secondary != NULL) { + old_stransition = secondary->opening_transition; + secondary->opening_transition = clip->closing_transition; + } if (length > 0) { clip->get_closing_transition()->length = length; } diff --git a/project/undo.h b/project/undo.h index bd8d1cf2e..e69c466ab 100644 --- a/project/undo.h +++ b/project/undo.h @@ -101,16 +101,19 @@ private: class AddTransitionCommand : public QUndoCommand { public: - AddTransitionCommand(Clip* c, Clip* s, const EffectMeta* itransition, int itype, int ilength); + AddTransitionCommand(Clip* c, Clip* s, Transition *copy, const EffectMeta* itransition, int itype, int ilength); void undo(); void redo(); private: Clip* clip; Clip* secondary; + Transition* transition_to_copy; const EffectMeta* transition; int type; int length; bool old_project_changed; + int old_ptransition; + int old_stransition; }; class ModifyTransitionCommand : public QUndoCommand { diff --git a/ui/timelinewidget.cpp b/ui/timelinewidget.cpp index da72080a6..0a56b83b4 100644 --- a/ui/timelinewidget.cpp +++ b/ui/timelinewidget.cpp @@ -934,7 +934,7 @@ void TimelineWidget::mouseReleaseEvent(QMouseEvent *event) { // step 3 - move clips Clip* c = sequence->clips.at(g.clip); if (g.transition == NULL) { - ca->append(new MoveClipAction(c, c->timeline_in + (g.in - g.old_in), c->timeline_out + (g.out - g.old_out), c->clip_in + (g.clip_in - g.old_clip_in), c->track + (g.track - g.old_track))); + move_clip(ca, c, c->timeline_in + (g.in - g.old_in), c->timeline_out + (g.out - g.old_out), c->clip_in + (g.clip_in - g.old_clip_in), c->track + (g.track - g.old_track)); // adjust transitions if we need to long new_clip_length = (g.out - g.in); @@ -971,13 +971,13 @@ void TimelineWidget::mouseReleaseEvent(QMouseEvent *event) { if (g.transition->secondary_clip != NULL) { if (g.in != g.old_in && !g.trimming) { long movement = g.in - g.old_in; - ca->append(new MoveClipAction(g.transition->parent_clip, g.transition->parent_clip->timeline_in + movement, g.transition->parent_clip->timeline_out, g.transition->parent_clip->clip_in + movement, g.transition->parent_clip->track)); - ca->append(new MoveClipAction(g.transition->secondary_clip, g.transition->secondary_clip->timeline_in, g.transition->secondary_clip->timeline_out + movement, g.transition->secondary_clip->clip_in, g.transition->secondary_clip->track)); + move_clip(ca, g.transition->parent_clip, g.transition->parent_clip->timeline_in + movement, g.transition->parent_clip->timeline_out, g.transition->parent_clip->clip_in + movement, g.transition->parent_clip->track, false); + move_clip(ca, g.transition->secondary_clip, g.transition->secondary_clip->timeline_in, g.transition->secondary_clip->timeline_out + movement, g.transition->secondary_clip->clip_in, g.transition->secondary_clip->track, false); } } else 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)); + move_clip(ca, 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); } @@ -985,7 +985,7 @@ void TimelineWidget::mouseReleaseEvent(QMouseEvent *event) { } 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)); + move_clip(ca, c, c->timeline_in, c->timeline_out + (g.out - g.old_out), c->clip_in, c->track); clip_length += (g.out - g.old_out); } @@ -1053,14 +1053,14 @@ void TimelineWidget::mouseReleaseEvent(QMouseEvent *event) { panel_timeline->delete_areas_and_relink(ca, areas); - if (move_post) ca->append(new MoveClipAction(post, qMin(transition_start, post->timeline_in), post->timeline_out, post->clip_in - (post->timeline_in - transition_start), post->track)); - if (move_pre) ca->append(new MoveClipAction(pre, pre->timeline_in, qMax(transition_end, pre->timeline_out), pre->clip_in, pre->track)); + if (move_post) move_clip(ca, post, qMin(transition_start, post->timeline_in), post->timeline_out, post->clip_in - (post->timeline_in - transition_start), post->track); + if (move_pre) move_clip(ca, pre, pre->timeline_in, qMax(transition_end, pre->timeline_out), pre->clip_in, pre->track); } if (panel_timeline->transition_tool_post_clip > -1) { - ca->append(new AddTransitionCommand(pre, post, panel_timeline->transition_tool_meta, TA_OPENING_TRANSITION, transition_end - pre->timeline_in)); + ca->append(new AddTransitionCommand(pre, post, NULL, panel_timeline->transition_tool_meta, TA_OPENING_TRANSITION, transition_end - pre->timeline_in)); } else { - ca->append(new AddTransitionCommand(pre, NULL, panel_timeline->transition_tool_meta, panel_timeline->transition_tool_type, transition_end - transition_start)); + ca->append(new AddTransitionCommand(pre, NULL, NULL, panel_timeline->transition_tool_meta, panel_timeline->transition_tool_type, transition_end - transition_start)); } push_undo = true; @@ -1124,9 +1124,14 @@ void TimelineWidget::init_ghosts() { Clip* c = sequence->clips.at(g.clip); g.track = g.old_track = c->track; - g.clip_in = g.old_clip_in = panel_timeline->tool == TIMELINE_TOOL_SLIP ? c->get_clip_in_with_transition() : c->clip_in; + g.clip_in = g.old_clip_in = c->clip_in; - if (g.transition == NULL) { + if (panel_timeline->tool == TIMELINE_TOOL_SLIP) { + g.clip_in = g.old_clip_in = c->get_clip_in_with_transition(); + g.in = g.old_in = c->get_timeline_in_with_transition(); + g.out = g.old_out = c->get_timeline_out_with_transition(); + g.ghost_length = g.old_out - g.old_in; + } else if (g.transition == NULL) { // this ghost is for a clip g.in = g.old_in = c->timeline_in; g.out = g.old_out = c->timeline_out; @@ -1153,6 +1158,42 @@ void TimelineWidget::init_ghosts() { } } +void validate_transitions(Clip* otc, Clip* ctc, long length, long& frame_diff) { + long validator; + if (otc != NULL) { + validator = otc->timeline_in + frame_diff; + if (validator < 0) frame_diff -= validator; // prevent from going below 0 on the timeline + + if (panel_timeline->transition_tool_post_clip > -1) { + validator = otc->clip_in + length - frame_diff; + if (validator < 0) frame_diff += validator; // prevent from going below 0 for the media + + validator = otc->clip_in + length + frame_diff - otc->getMaximumLength(); + if (validator > 0) frame_diff -= validator; // prevent transition from exceeding media length + } else { + validator = otc->clip_in + length + frame_diff; + if (validator < 0) frame_diff -= validator; // prevent from going below 0 for the media + if (validator > otc->getMaximumLength()) frame_diff -= (validator - otc->getMaximumLength()); // prevent transition from exceeding media length + } + } + + if (ctc != NULL) { + // prevent transition from exceeding media length + validator = ctc->clip_in + length + ctc->getLength() + frame_diff; + if (validator > ctc->getMaximumLength()) frame_diff -= (validator - ctc->getMaximumLength()); + + // prevent from going below 0 for the media + if (panel_timeline->transition_tool_post_clip > -1) { + validator = ctc->clip_in + length - ctc->getLength() + frame_diff; + if (validator > 0) frame_diff -= validator; + } + + // prevent from going below 0 on the timeline + validator = ctc->timeline_out + length + frame_diff; + if (validator < 0) frame_diff -= validator; + } +} + void TimelineWidget::update_ghosts(const QPoint& mouse_pos, bool lock_frame) { int mouse_track = getTrackFromScreenPoint(mouse_pos.y()); long frame_diff = (lock_frame) ? 0 : panel_timeline->getTimelineFrameFromScreenPoint(mouse_pos.x()) - panel_timeline->drag_frame_start; @@ -1246,14 +1287,12 @@ void TimelineWidget::update_ghosts(const QPoint& mouse_pos, bool lock_frame) { frame_diff = -frame_diff; } - validator = g.transition->parent_clip->get_clip_in_with_transition() - frame_diff; - if (validator < 0) frame_diff += validator; + // TESTING CODE + Clip* otc = g.transition->parent_clip; + Clip* ctc = g.transition->secondary_clip; - validator = g.transition->secondary_clip->get_timeline_out_with_transition() - g.transition->secondary_clip->get_timeline_in_with_transition() + g.transition->secondary_clip->get_clip_in_with_transition() + frame_diff - g.transition->secondary_clip->getMaximumLength(); - if (validator > 0) frame_diff -= validator; - - validator = g.transition->length + frame_diff - 1; - if (validator < 0) frame_diff -= validator; + validate_transitions(otc, ctc, g.transition->length, frame_diff); + // TESTING CODE END if (g.trim_in) { frame_diff = -frame_diff; @@ -1294,9 +1333,16 @@ void TimelineWidget::update_ghosts(const QPoint& mouse_pos, bool lock_frame) { if (g.transition != NULL) { if (g.transition->secondary_clip != NULL) { // prevent dual transitions from going below 0 on the primary or above media length on the secondary + validator = g.transition->parent_clip->get_clip_in_with_transition() + frame_diff; if (validator < 0) frame_diff -= validator; + validator = g.transition->secondary_clip->get_timeline_out_with_transition() - g.transition->secondary_clip->get_timeline_in_with_transition() - g.transition->get_length() + g.transition->secondary_clip->get_clip_in_with_transition() + frame_diff; + if (validator < 0) frame_diff -= validator; + + validator = g.transition->parent_clip->clip_in + frame_diff - g.transition->parent_clip->getMaximumLength() + g.transition->length; + if (validator > 0) frame_diff -= validator; + validator = g.transition->secondary_clip->get_timeline_out_with_transition() - g.transition->secondary_clip->get_timeline_in_with_transition() + g.transition->secondary_clip->get_clip_in_with_transition() + frame_diff - g.transition->secondary_clip->getMaximumLength(); if (validator > 0) frame_diff -= validator; } else { @@ -1344,38 +1390,7 @@ void TimelineWidget::update_ghosts(const QPoint& mouse_pos, bool lock_frame) { ctc = temp; } - if (otc != NULL) { - validator = otc->timeline_in + frame_diff; - if (validator < 0) frame_diff -= validator; // prevent from going below 0 on the timeline - - if (panel_timeline->transition_tool_post_clip > -1) { - validator = otc->clip_in - frame_diff; - if (validator < 0) frame_diff += validator; // prevent from going below 0 for the media - - validator = otc->clip_in + frame_diff - otc->getMaximumLength(); - if (validator > 0) frame_diff -= validator; // prevent transition from exceeding media length - } else { - validator = otc->clip_in + frame_diff; - if (validator < 0) frame_diff -= validator; // prevent from going below 0 for the media - if (validator > otc->getMaximumLength()) frame_diff -= (validator - otc->getMaximumLength()); // prevent transition from exceeding media length - } - } - - if (ctc != NULL) { - validator = ctc->clip_in + ctc->getLength() + frame_diff; // prevent transition from exceeding media length - if (validator > ctc->getMaximumLength()) { - frame_diff -= (validator - ctc->getMaximumLength()); - } - - if (validator < 0) { // prevent from going below 0 for the media - frame_diff -= validator; - } - - validator = ctc->timeline_out + frame_diff; // prevent from going below 0 on the timeline - if (validator < 0) { - frame_diff -= validator; - } - } + validate_transitions(otc, ctc, 0, frame_diff); if (flipped) { frame_diff = -frame_diff; @@ -1614,7 +1629,7 @@ 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->get_opening_transition() != NULL || c->get_closing_transition() != NULL)) { + if (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;jselections.size();j++) { const Selection& s = sequence->selections.at(j); @@ -2129,6 +2144,8 @@ void draw_transition(QPainter& p, Clip* c, const QRect& clip_rect, QRect& text_r p.fillRect(transition_rect, transition_color); QRect transition_text_rect(transition_rect.x() + CLIP_TEXT_PADDING, transition_rect.y() + CLIP_TEXT_PADDING, transition_rect.width() - CLIP_TEXT_PADDING, transition_rect.height() - CLIP_TEXT_PADDING); if (transition_text_rect.width() > MAX_TEXT_WIDTH) { + bool draw_text = true; + p.setPen(QColor(0, 0, 0, 96)); if (t->secondary_clip == NULL) { if (transition_type == TA_OPENING_TRANSITION) { @@ -2136,18 +2153,21 @@ void draw_transition(QPainter& p, Clip* c, const QRect& clip_rect, QRect& text_r } else { p.drawLine(transition_rect.topLeft(), transition_rect.bottomRight()); } - } else{ + } else { if (transition_type == TA_OPENING_TRANSITION) { p.drawLine(QPoint(transition_rect.left(), transition_rect.center().y()), transition_rect.topRight()); p.drawLine(QPoint(transition_rect.left(), transition_rect.center().y()), transition_rect.bottomRight()); + draw_text = false; } else { p.drawLine(QPoint(transition_rect.right(), transition_rect.center().y()), transition_rect.topLeft()); p.drawLine(QPoint(transition_rect.right(), transition_rect.center().y()), transition_rect.bottomLeft()); } } - p.setPen(Qt::white); - p.drawText(transition_text_rect, 0, t->name, &transition_text_rect); + if (draw_text) { + p.setPen(Qt::white); + p.drawText(transition_text_rect, 0, t->meta->name, &transition_text_rect); + } } p.setPen(Qt::black); p.drawRect(transition_rect); diff --git a/ui/viewerwidget.cpp b/ui/viewerwidget.cpp index f1b1dbbd3..e105c0447 100644 --- a/ui/viewerwidget.cpp +++ b/ui/viewerwidget.cpp @@ -441,9 +441,11 @@ GLuint ViewerWidget::compose_sequence(QVector& nests, bool render_audio) coords.vertexTopLeftX = coords.vertexBottomLeftX = -video_width/2; coords.vertexTopLeftY = coords.vertexTopRightY = -video_height/2; coords.vertexTopRightX = coords.vertexBottomRightX = video_width/2; - coords.vertexBottomLeftY = coords.vertexBottomRightY = video_height/2; - coords.textureTopLeftY = coords.textureTopRightY = coords.textureTopLeftX = coords.textureBottomLeftX = 0; + coords.vertexBottomLeftY = coords.vertexBottomRightY = video_height/2; + coords.vertexBottomLeftZ = coords.vertexBottomRightZ = coords.vertexTopLeftZ = coords.vertexTopRightZ = 1; + coords.textureTopLeftY = coords.textureTopRightY = coords.textureTopLeftX = coords.textureBottomLeftX = 0.0; coords.textureBottomLeftY = coords.textureBottomRightY = coords.textureTopRightX = coords.textureBottomRightX = 1.0; + coords.textureTopLeftQ = coords.textureTopRightQ = coords.textureTopLeftQ = coords.textureBottomLeftQ = 1; if (c->autoscale && (video_width != s->width && video_height != s->height)) { float width_multiplier = (float) s->width / (float) video_width; @@ -496,43 +498,45 @@ GLuint ViewerWidget::compose_sequence(QVector& nests, bool render_audio) glBegin(GL_QUADS); if (coords.grid_size <= 1) { - glTexCoord2f(coords.textureTopLeftX, coords.textureTopLeftY); // top left - glVertex2f(coords.vertexTopLeftX, coords.vertexTopLeftY); // top left - glTexCoord2f(coords.textureTopRightX, coords.textureTopRightY); // top right - glVertex2f(coords.vertexTopRightX, coords.vertexTopRightY); // top right - glTexCoord2f(coords.textureBottomRightX, coords.textureBottomRightY); // bottom right - glVertex2f(coords.vertexBottomRightX, coords.vertexBottomRightY); // bottom right - glTexCoord2f(coords.textureBottomLeftX, coords.textureBottomLeftY); // bottom left - glVertex2f(coords.vertexBottomLeftX, coords.vertexBottomLeftY); // bottom left + float z = 0.5f; + + glTexCoord2f(coords.textureTopLeftX, coords.textureTopLeftY); // top left + glVertex3f(coords.vertexTopLeftX, coords.vertexTopLeftY, z); // top left + glTexCoord2f(coords.textureTopRightX, coords.textureTopRightY); // top right + glVertex3f(coords.vertexTopRightX, coords.vertexTopRightY, z); // top right + glTexCoord2f(coords.textureBottomRightX, coords.textureBottomRightY); // bottom right + glVertex3f(coords.vertexBottomRightX, coords.vertexBottomRightY, z); // bottom right + glTexCoord2f(coords.textureBottomLeftX, coords.textureBottomLeftY); // bottom left + glVertex3f(coords.vertexBottomLeftX, coords.vertexBottomLeftY, z); // bottom left } else { - double rows = coords.grid_size; - double cols = coords.grid_size; + float rows = coords.grid_size; + float cols = coords.grid_size; - for (double i=0;i Date: Sat, 24 Nov 2018 22:51:26 +1100 Subject: [PATCH 06/31] fixed timeline objects retrieving incorrect name --- panels/timeline.cpp | 10 +++++----- project/effect.cpp | 6 +++--- project/effect.h | 2 +- ui/timelinewidget.cpp | 16 ++++++++-------- 4 files changed, 17 insertions(+), 17 deletions(-) diff --git a/panels/timeline.cpp b/panels/timeline.cpp index 4d9ce5b6e..e3d56034b 100644 --- a/panels/timeline.cpp +++ b/panels/timeline.cpp @@ -324,11 +324,11 @@ void Timeline::add_clips_from_ghosts(ComboAction* ca, Sequence* s) { if (c->track < 0) { // add default video effects - c->effects.append(create_effect(c, get_internal_meta(EFFECT_INTERNAL_TRANSFORM))); + c->effects.append(create_effect(c, get_internal_meta(EFFECT_INTERNAL_TRANSFORM, EFFECT_TYPE_EFFECT))); } else { // add default audio effects - c->effects.append(create_effect(c, get_internal_meta(EFFECT_INTERNAL_VOLUME))); - c->effects.append(create_effect(c, get_internal_meta(EFFECT_INTERNAL_PAN))); + c->effects.append(create_effect(c, get_internal_meta(EFFECT_INTERNAL_VOLUME, EFFECT_TYPE_EFFECT))); + c->effects.append(create_effect(c, get_internal_meta(EFFECT_INTERNAL_PAN, EFFECT_TYPE_EFFECT))); } } if (config.enable_seek_to_import) { @@ -355,11 +355,11 @@ void Timeline::add_transition() { Clip* c = sequence->clips.at(i); if (c != NULL && is_clip_selected(c, true)) { if (c->get_opening_transition() == NULL) { - ca->append(new AddTransitionCommand(c, NULL, NULL, get_internal_meta(TRANSITION_INTERNAL_LINEARFADE), TA_OPENING_TRANSITION, 30)); + ca->append(new AddTransitionCommand(c, NULL, NULL, get_internal_meta(TRANSITION_INTERNAL_LINEARFADE, EFFECT_TYPE_TRANSITION), TA_OPENING_TRANSITION, 30)); adding = true; } if (c->get_closing_transition() == NULL) { - ca->append(new AddTransitionCommand(c, NULL, NULL, get_internal_meta(TRANSITION_INTERNAL_LINEARFADE), TA_OPENING_TRANSITION, 30)); + ca->append(new AddTransitionCommand(c, NULL, NULL, get_internal_meta(TRANSITION_INTERNAL_LINEARFADE, EFFECT_TYPE_TRANSITION), TA_OPENING_TRANSITION, 30)); adding = true; } } diff --git a/project/effect.cpp b/project/effect.cpp index c4c67fa9d..f1d1fc30b 100644 --- a/project/effect.cpp +++ b/project/effect.cpp @@ -66,14 +66,14 @@ Effect* create_effect(Clip* c, const EffectMeta* em) { return NULL; } -const EffectMeta* get_internal_meta(int internal_id) { +const EffectMeta* get_internal_meta(int internal_id, int type) { for (int i=0;i audio_effects; double log_volume(double linear); void init_effects(); Effect* create_effect(Clip* c, const EffectMeta *em); -const EffectMeta* get_internal_meta(int internal_id); +const EffectMeta* get_internal_meta(int internal_id, int type); extern QMutex effects_loaded; diff --git a/ui/timelinewidget.cpp b/ui/timelinewidget.cpp index 0a56b83b4..bd990f19b 100644 --- a/ui/timelinewidget.cpp +++ b/ui/timelinewidget.cpp @@ -772,41 +772,41 @@ void TimelineWidget::mouseReleaseEvent(QMouseEvent *event) { if (c->track < 0) { // default video effects (before custom effects) - c->effects.append(create_effect(c, get_internal_meta(EFFECT_INTERNAL_TRANSFORM))); + c->effects.append(create_effect(c, get_internal_meta(EFFECT_INTERNAL_TRANSFORM, EFFECT_TYPE_EFFECT))); c->media_type = MEDIA_TYPE_SOLID; } switch (panel_timeline->creating_object) { case ADD_OBJ_TITLE: c->name = "Title"; - c->effects.append(create_effect(c, get_internal_meta(EFFECT_INTERNAL_TEXT))); + c->effects.append(create_effect(c, get_internal_meta(EFFECT_INTERNAL_TEXT, EFFECT_TYPE_EFFECT))); break; case ADD_OBJ_SOLID: c->name = "Solid Color"; - c->effects.append(create_effect(c, get_internal_meta(EFFECT_INTERNAL_SOLID))); + c->effects.append(create_effect(c, get_internal_meta(EFFECT_INTERNAL_SOLID, EFFECT_TYPE_EFFECT))); break; case ADD_OBJ_BARS: { c->name = "Bars"; - Effect* e = create_effect(c, get_internal_meta(EFFECT_INTERNAL_SOLID)); + Effect* e = create_effect(c, get_internal_meta(EFFECT_INTERNAL_SOLID, EFFECT_TYPE_EFFECT)); e->row(0)->field(0)->set_combo_index(1); c->effects.append(e); } break; case ADD_OBJ_TONE: c->name = "Tone"; - c->effects.append(create_effect(c, get_internal_meta(EFFECT_INTERNAL_TONE))); + c->effects.append(create_effect(c, get_internal_meta(EFFECT_INTERNAL_TONE, EFFECT_TYPE_EFFECT))); break; case ADD_OBJ_NOISE: c->name = "Noise"; - c->effects.append(create_effect(c, get_internal_meta(EFFECT_INTERNAL_NOISE))); + c->effects.append(create_effect(c, get_internal_meta(EFFECT_INTERNAL_NOISE, EFFECT_TYPE_EFFECT))); break; } if (c->track >= 0) { // default audio effects (after custom effects) - c->effects.append(create_effect(c, get_internal_meta(EFFECT_INTERNAL_VOLUME))); - c->effects.append(create_effect(c, get_internal_meta(EFFECT_INTERNAL_PAN))); + c->effects.append(create_effect(c, get_internal_meta(EFFECT_INTERNAL_VOLUME, EFFECT_TYPE_EFFECT))); + c->effects.append(create_effect(c, get_internal_meta(EFFECT_INTERNAL_PAN, EFFECT_TYPE_EFFECT))); c->media_type = MEDIA_TYPE_TONE; } From 234110de09c71af53970e01ba8b21def6abb78fd Mon Sep 17 00:00:00 2001 From: itsmattkc Date: Sat, 24 Nov 2018 23:10:13 +1100 Subject: [PATCH 07/31] added fine control to label slider --- ui/labelslider.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/ui/labelslider.cpp b/ui/labelslider.cpp index 9833f7b33..1e7dad08d 100644 --- a/ui/labelslider.cpp +++ b/ui/labelslider.cpp @@ -119,11 +119,13 @@ void LabelSlider::mousePressEvent(QMouseEvent *ev) { } } -void LabelSlider::mouseMoveEvent(QMouseEvent*) { +void LabelSlider::mouseMoveEvent(QMouseEvent* event) { if (drag_start) { drag_proc = true; - int diff = (cursor().pos().x()-drag_start_x) + (drag_start_y-cursor().pos().y()); - set_value(internal_value + ((display_type == LABELSLIDER_PERCENT) ? (diff*0.01) : diff), true); + double diff = (cursor().pos().x()-drag_start_x) + (drag_start_y-cursor().pos().y()); + if (event->modifiers() & Qt::ControlModifier) diff *= 0.01; + if (display_type == LABELSLIDER_PERCENT) diff *= 0.01; + set_value(internal_value + diff, true); cursor().setPos(drag_start_x, drag_start_y); } } From 66f5b37c3b595696f186850f93a4d696a721cf57 Mon Sep 17 00:00:00 2001 From: itsmattkc Date: Sat, 24 Nov 2018 23:27:59 +1100 Subject: [PATCH 08/31] removed some effects boilerplate code --- effects/internal/audionoiseeffect.cpp | 5 +---- effects/internal/cornerpineffect.cpp | 12 +----------- effects/internal/crossdissolvetransition.cpp | 2 ++ effects/internal/paneffect.cpp | 4 +--- effects/internal/shakeeffect.cpp | 4 ---- effects/internal/solideffect.cpp | 5 ----- effects/internal/texteffect.cpp | 18 +----------------- effects/internal/toneeffect.cpp | 6 +----- effects/internal/transformeffect.cpp | 10 ---------- effects/internal/volumeeffect.cpp | 4 +--- project/effectrow.cpp | 1 + 11 files changed, 9 insertions(+), 62 deletions(-) diff --git a/effects/internal/audionoiseeffect.cpp b/effects/internal/audionoiseeffect.cpp index c86c5f38d..bd0283a5b 100644 --- a/effects/internal/audionoiseeffect.cpp +++ b/effects/internal/audionoiseeffect.cpp @@ -12,10 +12,7 @@ AudioNoiseEffect::AudioNoiseEffect(Clip* c, const EffectMeta *em) : Effect(c, em mix_val = add_row("Mix:")->add_field(EFFECT_FIELD_BOOL, "mix"); mix_val->set_bool_value(true); - srand(QDateTime::currentMSecsSinceEpoch()); - - connect(amount_val, SIGNAL(changed()), this, SLOT(field_changed())); - connect(mix_val, SIGNAL(changed()), this, SLOT(field_changed())); + srand(QDateTime::currentMSecsSinceEpoch()); } void AudioNoiseEffect::process_audio(double timecode_start, double timecode_end, quint8 *samples, int nb_bytes, int) { diff --git a/effects/internal/cornerpineffect.cpp b/effects/internal/cornerpineffect.cpp index 994d5bb6b..1f8650e0e 100644 --- a/effects/internal/cornerpineffect.cpp +++ b/effects/internal/cornerpineffect.cpp @@ -25,17 +25,7 @@ CornerPinEffect::CornerPinEffect(Clip *c, const EffectMeta *em) : Effect(c, em) bottom_right_y = bottom_right->add_field(EFFECT_FIELD_DOUBLE, "bottomrighty"); perspective = add_row("Perspective:")->add_field(EFFECT_FIELD_BOOL, "perspective"); - perspective->set_bool_value(true); - - connect(top_left_x, SIGNAL(changed()), this, SLOT(field_changed())); - connect(top_left_y, SIGNAL(changed()), this, SLOT(field_changed())); - connect(top_right_x, SIGNAL(changed()), this, SLOT(field_changed())); - connect(top_right_y, SIGNAL(changed()), this, SLOT(field_changed())); - connect(bottom_left_x, SIGNAL(changed()), this, SLOT(field_changed())); - connect(bottom_left_y, SIGNAL(changed()), this, SLOT(field_changed())); - connect(bottom_right_x, SIGNAL(changed()), this, SLOT(field_changed())); - connect(bottom_right_y, SIGNAL(changed()), this, SLOT(field_changed())); - connect(perspective, SIGNAL(changed()), this, SLOT(field_changed())); + perspective->set_bool_value(true); vertPath = "cornerpin.vert"; fragPath = "cornerpin.frag"; diff --git a/effects/internal/crossdissolvetransition.cpp b/effects/internal/crossdissolvetransition.cpp index 06183138a..527698fb6 100644 --- a/effects/internal/crossdissolvetransition.cpp +++ b/effects/internal/crossdissolvetransition.cpp @@ -4,6 +4,8 @@ CrossDissolveTransition::CrossDissolveTransition(Clip* c, Clip* s, const EffectMeta* em) : Transition(c, s, em) { enable_coords = true; + + add_row("Smooth")->add_field(EFFECT_FIELD_BOOL, "smooth"); } void CrossDissolveTransition::process_coords(double progress, GLTextureCoords&, int data) { diff --git a/effects/internal/paneffect.cpp b/effects/internal/paneffect.cpp index a9fff136a..0a7b25a58 100644 --- a/effects/internal/paneffect.cpp +++ b/effects/internal/paneffect.cpp @@ -15,9 +15,7 @@ PanEffect::PanEffect(Clip* c, const EffectMeta *em) : Effect(c, em) { pan_val->set_double_maximum_value(100); // set defaults - pan_val->set_double_default_value(0); - - connect(pan_val, SIGNAL(changed()), this, SLOT(field_changed())); + pan_val->set_double_default_value(0); } void PanEffect::process_audio(double timecode_start, double timecode_end, quint8* samples, int nb_bytes, int) { diff --git a/effects/internal/shakeeffect.cpp b/effects/internal/shakeeffect.cpp index 7460658e4..0687a71ad 100644 --- a/effects/internal/shakeeffect.cpp +++ b/effects/internal/shakeeffect.cpp @@ -38,10 +38,6 @@ ShakeEffect::ShakeEffect(Clip *c, const EffectMeta *em) : Effect(c, em) { for (int i=0;iset_double_minimum_value(1); checkerboard_size_field->set_double_default_value(10); - connect(solid_type, SIGNAL(changed()), this, SLOT(field_changed())); - connect(solid_color_field, SIGNAL(changed()), this, SLOT(field_changed())); - connect(opacity_field, SIGNAL(changed()), this, SLOT(field_changed())); - connect(checkerboard_size_field, SIGNAL(changed()), this, SLOT(field_changed())); - // hacky but eh QComboBox* solid_type_combo = static_cast(solid_type->get_ui_element()); connect(solid_type_combo, SIGNAL(currentIndexChanged(int)), this, SLOT(ui_update(int))); diff --git a/effects/internal/texteffect.cpp b/effects/internal/texteffect.cpp index e34f4c080..2fae8d2f0 100644 --- a/effects/internal/texteffect.cpp +++ b/effects/internal/texteffect.cpp @@ -76,23 +76,7 @@ TextEffect::TextEffect(Clip *c, const EffectMeta* em) : outline_width->set_double_default_value(20); outline_enable(false); - shadow_enable(false); - - connect(text_val, SIGNAL(changed()), this, SLOT(field_changed())); - connect(size_val, SIGNAL(changed()), this, SLOT(field_changed())); - connect(set_color_button, SIGNAL(changed()), this, SLOT(field_changed())); - connect(set_font_combobox, SIGNAL(changed()), this, SLOT(field_changed())); - connect(halign_field, SIGNAL(changed()), this, SLOT(field_changed())); - connect(valign_field, SIGNAL(changed()), this, SLOT(field_changed())); - connect(word_wrap_field, SIGNAL(changed()), this, SLOT(field_changed())); - connect(outline_bool, SIGNAL(changed()), this, SLOT(field_changed())); - connect(outline_color, SIGNAL(changed()), this, SLOT(field_changed())); - connect(outline_width, SIGNAL(changed()), this, SLOT(field_changed())); - connect(shadow_bool, SIGNAL(changed()), this, SLOT(field_changed())); - connect(shadow_color, SIGNAL(changed()), this, SLOT(field_changed())); - connect(shadow_distance, SIGNAL(changed()), this, SLOT(field_changed())); - connect(shadow_softness, SIGNAL(changed()), this, SLOT(field_changed())); - connect(shadow_opacity, SIGNAL(changed()), this, SLOT(field_changed())); + shadow_enable(false); connect(shadow_bool, SIGNAL(toggled(bool)), this, SLOT(shadow_enable(bool))); connect(outline_bool, SIGNAL(toggled(bool)), this, SLOT(outline_enable(bool))); diff --git a/effects/internal/toneeffect.cpp b/effects/internal/toneeffect.cpp index 873a70817..bb0fb7ac8 100644 --- a/effects/internal/toneeffect.cpp +++ b/effects/internal/toneeffect.cpp @@ -23,11 +23,7 @@ ToneEffect::ToneEffect(Clip* c, const EffectMeta *em) : Effect(c, em), sinX(INT_ amount_val->set_double_default_value(25); mix_val = add_row("Mix:")->add_field(EFFECT_FIELD_BOOL, "mix"); - mix_val->set_bool_value(true); - - connect(freq_val, SIGNAL(changed()), this, SLOT(field_changed())); - connect(amount_val, SIGNAL(changed()), this, SLOT(field_changed())); - connect(mix_val, SIGNAL(changed()), this, SLOT(field_changed())); + mix_val->set_bool_value(true); } void ToneEffect::process_audio(double timecode_start, double timecode_end, quint8 *samples, int nb_bytes, int) { diff --git a/effects/internal/transformeffect.cpp b/effects/internal/transformeffect.cpp index 894b291e2..52cf6d7eb 100644 --- a/effects/internal/transformeffect.cpp +++ b/effects/internal/transformeffect.cpp @@ -65,16 +65,6 @@ TransformEffect::TransformEffect(Clip* c, const EffectMeta* em) : Effect(c, em) blend_mode_box->set_combo_index(0); refresh(); - connect(position_x, SIGNAL(changed()), this, SLOT(field_changed())); - connect(position_y, SIGNAL(changed()), this, SLOT(field_changed())); - connect(scale_x, SIGNAL(changed()), this, SLOT(field_changed())); - connect(scale_y, SIGNAL(changed()), this, SLOT(field_changed())); - connect(uniform_scale_field, SIGNAL(changed()), this, SLOT(field_changed())); - connect(rotation, SIGNAL(changed()), this, SLOT(field_changed())); - connect(anchor_x_box, SIGNAL(changed()), this, SLOT(field_changed())); - connect(anchor_y_box, SIGNAL(changed()), this, SLOT(field_changed())); - connect(opacity, SIGNAL(changed()), this, SLOT(field_changed())); - connect(blend_mode_box, SIGNAL(changed()), this, SLOT(field_changed())); connect(uniform_scale_field, SIGNAL(toggled(bool)), this, SLOT(toggle_uniform_scale(bool))); } diff --git a/effects/internal/volumeeffect.cpp b/effects/internal/volumeeffect.cpp index a876e810d..6a71d06a7 100644 --- a/effects/internal/volumeeffect.cpp +++ b/effects/internal/volumeeffect.cpp @@ -14,9 +14,7 @@ VolumeEffect::VolumeEffect(Clip* c, const EffectMeta *em) : Effect(c, em) { volume_val->set_double_minimum_value(0); // set defaults - volume_val->set_double_default_value(100); - - connect(volume_val, SIGNAL(changed()), this, SLOT(field_changed())); + volume_val->set_double_default_value(100); } void VolumeEffect::process_audio(double timecode_start, double timecode_end, quint8* samples, int nb_bytes, int) { diff --git a/project/effectrow.cpp b/project/effectrow.cpp index 0772162f0..c3804be1f 100644 --- a/project/effectrow.cpp +++ b/project/effectrow.cpp @@ -149,6 +149,7 @@ EffectField* EffectRow::add_field(int type, const QString& id, int colspan) { fields.append(field); QWidget* element = field->get_ui_element(); ui->addWidget(element, ui_row, fields.size(), 1, colspan); + connect(field, SIGNAL(changed()), parent_effect, SLOT(field_changed())); return field; } From 1113c74c0065731cd082547de1234610318d0f80 Mon Sep 17 00:00:00 2001 From: itsmattkc Date: Sun, 25 Nov 2018 00:10:45 +1100 Subject: [PATCH 09/31] added controls for transitions --- effects/internal/crossdissolvetransition.cpp | 2 +- panels/effectcontrols.cpp | 246 +++++++------------ panels/effectcontrols.h | 6 +- panels/panels.cpp | 48 ++-- project/effect.cpp | 2 +- project/effect.h | 2 +- project/effectrow.cpp | 64 ++--- project/transition.cpp | 2 +- 8 files changed, 163 insertions(+), 209 deletions(-) diff --git a/effects/internal/crossdissolvetransition.cpp b/effects/internal/crossdissolvetransition.cpp index 527698fb6..ef2d684ac 100644 --- a/effects/internal/crossdissolvetransition.cpp +++ b/effects/internal/crossdissolvetransition.cpp @@ -5,7 +5,7 @@ CrossDissolveTransition::CrossDissolveTransition(Clip* c, Clip* s, const EffectMeta* em) : Transition(c, s, em) { enable_coords = true; - add_row("Smooth")->add_field(EFFECT_FIELD_BOOL, "smooth"); +// add_row("Smooth")->add_field(EFFECT_FIELD_BOOL, "smooth"); } void CrossDissolveTransition::process_coords(double progress, GLTextureCoords&, int data) { diff --git a/panels/effectcontrols.cpp b/panels/effectcontrols.cpp index 727fa3bf5..2bb27b32b 100644 --- a/panels/effectcontrols.cpp +++ b/panels/effectcontrols.cpp @@ -24,7 +24,8 @@ EffectControls::EffectControls(QWidget *parent) : multiple(false), zoom(1), ui(new Ui::EffectControls), - panel_name("Effects: ") + panel_name("Effects: "), + mode(TA_NO_TRANSITION) { ui->setupUi(this); @@ -97,151 +98,68 @@ void EffectControls::delete_selected_keyframes() { } void EffectControls::show_effect_menu(bool video, bool transitions) { + video_menu = video; + transition_menu = transitions; + effects_loaded.lock(); - /*video_menu = video; - transition_menu = transitions; - - int lim; - QVector* effect_names; - if (transitions) { - if (video) { - lim = VIDEO_TRANSITION_COUNT; - effect_names = &video_transition_names; - } else { - lim = AUDIO_TRANSITION_COUNT; - effect_names = &audio_transition_names; - } - } else { - if (video) { - lim = VIDEO_EFFECT_COUNT; - effect_names = &video_effect_names; - } else { - lim = AUDIO_EFFECT_COUNT; - effect_names = &audio_effect_names; - } - } - + QVector& effect_list = (video) ? video_effects : audio_effects; QMenu effects_menu(this); + for (int i=0;isetText(effect_names->at(i)); - action->setData(i); + if ((em.type == EFFECT_TYPE_TRANSITION) == transition_menu) { + QAction* action = new QAction(&effects_menu); + action->setText(em.name); + action->setData(reinterpret_cast(&em)); - // sort alphabetically - bool added = false; - for (int j=0;jtext() > effect_names->at(i)) { - effects_menu.insertAction(comp_action, action); - added = true; - break; + QMenu* parent = &effects_menu; + if (!em.category.isEmpty()) { + bool found = false; + for (int j=0;jmenu() != NULL) { + if (action->menu()->title() == em.category) { + parent = action->menu(); + found = true; + break; + } + } + } + if (!found) { + parent = new QMenu(&effects_menu); + parent->setTitle(em.category); + + bool found = false; + for (int i=0;itext() > em.category) { + effects_menu.insertMenu(comp_action, parent); + found = true; + break; + } + } + if (!found) effects_menu.addMenu(parent); + } } + + bool found = false; + for (int i=0;iactions().size();i++) { + QAction* comp_action = parent->actions().at(i); + if (comp_action->text() > action->text()) { + parent->insertAction(comp_action, action); + found = true; + break; + } + } + if (!found) parent->addAction(action); } - if (!added) effects_menu.addAction(action); } + effects_loaded.unlock(); + connect(&effects_menu, SIGNAL(triggered(QAction*)), this, SLOT(menu_select(QAction*))); - - effects_menu.exec(QCursor::pos());*/ - - video_menu = video; - transition_menu = transitions; - - /*if (transition_menu) { - // TODO old effect/transition code grandfathered in, to be updated - - int lim; - QVector* effect_names; - if (video) { - lim = VIDEO_TRANSITION_COUNT; - effect_names = &video_transition_names; - } else { - lim = AUDIO_TRANSITION_COUNT; - effect_names = &audio_transition_names; - } - QMenu effects_menu(this); - for (int i=0;isetText(effect_names->at(i)); - action->setData(i); - - // sort alphabetically - bool added = false; - for (int j=0;jtext() > effect_names->at(i)) { - effects_menu.insertAction(comp_action, action); - added = true; - break; - } - } - if (!added) effects_menu.addAction(action); - } - connect(&effects_menu, SIGNAL(triggered(QAction*)), this, SLOT(menu_select(QAction*))); - effects_menu.exec(QCursor::pos()); - } else {*/ - effects_loaded.lock(); - - QVector& effect_list = (video) ? video_effects : audio_effects; - QMenu effects_menu(this); - for (int i=0;isetText(em.name); - action->setData(reinterpret_cast(&em)); - - QMenu* parent = &effects_menu; - if (!em.category.isEmpty()) { - bool found = false; - for (int j=0;jmenu() != NULL) { - if (action->menu()->title() == em.category) { - parent = action->menu(); - found = true; - break; - } - } - } - if (!found) { - parent = new QMenu(&effects_menu); - parent->setTitle(em.category); - - bool found = false; - for (int i=0;itext() > em.category) { - effects_menu.insertMenu(comp_action, parent); - found = true; - break; - } - } - if (!found) effects_menu.addMenu(parent); - } - } - - bool found = false; - for (int i=0;iactions().size();i++) { - QAction* comp_action = parent->actions().at(i); - if (comp_action->text() > action->text()) { - parent->insertAction(comp_action, action); - found = true; - break; - } - } - if (!found) parent->addAction(action); - } - } - - effects_loaded.unlock(); - - connect(&effects_menu, SIGNAL(triggered(QAction*)), this, SLOT(menu_select(QAction*))); - effects_menu.exec(QCursor::pos()); - //} + effects_menu.exec(QCursor::pos()); } void EffectControls::clear_effects(bool clear_cache) { @@ -277,10 +195,16 @@ void EffectControls::deselect_all_effects(QWidget* sender) { } } +void EffectControls::open_effect(QVBoxLayout* layout, Effect* e) { + CollapsibleWidget* container = e->container; + layout->addWidget(container); + connect(container, SIGNAL(deselect_others(QWidget*)), this, SLOT(deselect_all_effects(QWidget*))); +} + void EffectControls::load_effects() { ui->label_2->setVisible(multiple); - if (!multiple) { + if (!multiple) { // load in new clips for (int i=0;iclips.at(selected_clips.at(i)); @@ -292,12 +216,15 @@ void EffectControls::load_effects() { ui->acontainer->setVisible(true); layout = static_cast(ui->audio_effect_area->layout()); } - for (int j=0;jeffects.size();j++) { - Effect* e = c->effects.at(j); - CollapsibleWidget* container = e->container; - layout->addWidget(container); - connect(container, SIGNAL(deselect_others(QWidget*)), this, SLOT(deselect_all_effects(QWidget*))); - } + if (mode == TA_NO_TRANSITION) { + for (int j=0;jeffects.size();j++) { + open_effect(layout, c->effects.at(j)); + } + } else if (mode == TA_OPENING_TRANSITION && c->get_opening_transition() != NULL) { + open_effect(layout, c->get_opening_transition()); + } else if (mode == TA_CLOSING_TRANSITION && c->get_closing_transition() != NULL) { + open_effect(layout, c->get_closing_transition()); + } } if (selected_clips.size() > 0) { setWindowTitle(panel_name + sequence->clips.at(selected_clips.at(0))->name); @@ -311,22 +238,24 @@ void EffectControls::load_effects() { void EffectControls::delete_effects() { // load in new clips - EffectDeleteCommand* command = new EffectDeleteCommand(); - for (int i=0;iclips.at(selected_clips.at(i)); - for (int j=0;jeffects.size();j++) { - Effect* effect = c->effects.at(j); - if (effect->container->selected) { - command->clips.append(c); - command->fx.append(j); + if (mode == TA_NO_TRANSITION) { + EffectDeleteCommand* command = new EffectDeleteCommand(); + for (int i=0;iclips.at(selected_clips.at(i)); + for (int j=0;jeffects.size();j++) { + Effect* effect = c->effects.at(j); + if (effect->container->selected) { + command->clips.append(c); + command->fx.append(j); + } } } - } - if (command->clips.size() > 0) { - undo_stack.push(command); - panel_sequence_viewer->viewer_widget->update(); - } else { - delete command; + if (command->clips.size() > 0) { + undo_stack.push(command); + panel_sequence_viewer->viewer_widget->update(); + } else { + delete command; + } } } @@ -335,11 +264,12 @@ void EffectControls::reload_clips() { load_effects(); } -void EffectControls::set_clips(QVector& clips) { +void EffectControls::set_clips(QVector& clips, int m) { clear_effects(true); // replace clip vector selected_clips = clips; + mode = m; load_effects(); } diff --git a/panels/effectcontrols.h b/panels/effectcontrols.h index 4e54ff481..d80b10c39 100644 --- a/panels/effectcontrols.h +++ b/panels/effectcontrols.h @@ -10,6 +10,7 @@ class Effect; class TimelineHeader; class QScrollArea; class KeyframeView; +class QVBoxLayout; class EffectsArea : public QWidget { public: @@ -31,7 +32,7 @@ class EffectControls : public QDockWidget public: explicit EffectControls(QWidget *parent = 0); ~EffectControls(); - void set_clips(QVector& clips); + void set_clips(QVector& clips, int mode); void clear_effects(bool clear_cache); void delete_effects(); bool is_focused(); @@ -55,7 +56,6 @@ private slots: void deselect_all_effects(QWidget*); void on_add_video_transition_button_clicked(); - void on_add_audio_transition_button_clicked(); protected: void resizeEvent(QResizeEvent *event); @@ -63,10 +63,12 @@ private: void show_effect_menu(bool video, bool transitions); void load_effects(); void load_keyframes(); + void open_effect(QVBoxLayout* layout, Effect* e); bool video_menu; bool transition_menu; QString panel_name; + int mode; }; #endif // EFFECTCONTROLS_H diff --git a/panels/panels.cpp b/panels/panels.cpp index 07e87f288..8b458fcd1 100644 --- a/panels/panels.cpp +++ b/panels/panels.cpp @@ -5,6 +5,8 @@ #include "viewer.h" #include "project/sequence.h" #include "project/clip.h" +#include "project/transition.h" +#include "debug.h" Project* panel_project = 0; EffectControls* panel_effect_controls = 0; @@ -21,24 +23,42 @@ void update_effect_controls() { int vclip = -1; int aclip = -1; QVector selected_clips; + int mode = TA_NO_TRANSITION; if (sequence != NULL) { for (int i=0;iclips.size();i++) { Clip* clip = sequence->clips.at(i); - if (clip != NULL && panel_timeline->is_clip_selected(clip, true)) { - if (clip->track < 0 && vclip == -1) { - vclip = i; - } else if (clip->track >= 0 && aclip == -1) { - aclip = i; - } else { - vclip = -2; - aclip = -2; - panel_effect_controls->multiple = true; - break; - } + if (clip != NULL) { + for (int j=0;jselections.size();j++) { + const Selection& s = sequence->selections.at(j); + bool add = true; + if (clip->timeline_in >= s.in && clip->timeline_out <= s.out && clip->track == s.track) { + mode = TA_NO_TRANSITION; + } else if (selection_contains_transition(s, clip, TA_OPENING_TRANSITION)) { + mode = TA_OPENING_TRANSITION; + } else if (selection_contains_transition(s, clip, TA_CLOSING_TRANSITION)) { + mode = TA_CLOSING_TRANSITION; + } else { + add = false; + } + + if (add) { + if (clip->track < 0 && vclip == -1) { + vclip = i; + } else if (clip->track >= 0 && aclip == -1) { + aclip = i; + } else { + vclip = -2; + aclip = -2; + panel_effect_controls->multiple = true; + break; + } + } + } } } - // check if aclip is linked to vclip - if (!panel_effect_controls->multiple) { + + if (!panel_effect_controls->multiple) { + // check if aclip is linked to vclip if (vclip >= 0) selected_clips.append(vclip); if (aclip >= 0) selected_clips.append(aclip); if (vclip >= 0 && aclip >= 0) { @@ -58,7 +78,7 @@ void update_effect_controls() { } } } - panel_effect_controls->set_clips(selected_clips); + panel_effect_controls->set_clips(selected_clips, mode); } void update_ui(bool modified) { diff --git a/project/effect.cpp b/project/effect.cpp index f1d1fc30b..d2f6f1885 100644 --- a/project/effect.cpp +++ b/project/effect.cpp @@ -447,7 +447,7 @@ void Effect::copy_field_keyframes(Effect* e) { EffectRow* Effect::add_row(const QString& name) { EffectRow* row = new EffectRow(this, ui_layout, name, rows.size()); - rows.append(row); + rows.append(row); return row; } diff --git a/project/effect.h b/project/effect.h index 9c8eb062b..f24051b7d 100644 --- a/project/effect.h +++ b/project/effect.h @@ -117,7 +117,7 @@ public: QString name; CollapsibleWidget* container; - EffectRow* add_row(const QString &name); + EffectRow* add_row(const QString &name); EffectRow* row(int i); int row_count(); diff --git a/project/effectrow.cpp b/project/effectrow.cpp index c3804be1f..aac97d6b7 100644 --- a/project/effectrow.cpp +++ b/project/effectrow.cpp @@ -25,43 +25,45 @@ EffectRow::EffectRow(Effect *parent, QGridLayout *uilayout, const QString &n, in label = new QLabel(name); ui->addWidget(label, row, 0); - QSize button_size(20, 20); - QSize icon_size(12, 12); + if (parent_effect->meta->type != EFFECT_TYPE_TRANSITION) { + 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(); + 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())); + 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())); + 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())); + 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); + 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); + ui->addLayout(key_controls, row, 6); + } } bool EffectRow::isKeyframing() { diff --git a/project/transition.cpp b/project/transition.cpp index 51467c14e..be8db58ad 100644 --- a/project/transition.cpp +++ b/project/transition.cpp @@ -14,7 +14,7 @@ #include Transition::Transition(Clip* c, Clip* s, const EffectMeta* em) : Effect(c, em), secondary_clip(s) { - //add_row("Length:")->add_field(EFFECT_FIELD_DOUBLE); +// add_row("Length:", false)->add_field(EFFECT_FIELD_DOUBLE, "length"); } int Transition::copy(Clip *c, Clip* s) { From 4dee202494fabe53ca406b76ae5bae1222dd619f Mon Sep 17 00:00:00 2001 From: itsmattkc Date: Sun, 25 Nov 2018 00:36:15 +1100 Subject: [PATCH 10/31] began work on #119 --- effects/internal/transformeffect.cpp | 7 ++++++- effects/internal/transformeffect.h | 1 + panels/effectcontrols.cpp | 1 + panels/project.cpp | 1 - project/effect.cpp | 5 ++++- project/effect.h | 2 ++ ui/viewerwidget.cpp | 14 +++++++++++++- ui/viewerwidget.h | 1 + 8 files changed, 28 insertions(+), 4 deletions(-) diff --git a/effects/internal/transformeffect.cpp b/effects/internal/transformeffect.cpp index 52cf6d7eb..517e21cda 100644 --- a/effects/internal/transformeffect.cpp +++ b/effects/internal/transformeffect.cpp @@ -24,6 +24,7 @@ TransformEffect::TransformEffect(Clip* c, const EffectMeta* em) : Effect(c, em) { enable_coords = true; + enable_gizmos = true; EffectRow* position_row = add_row("Position:"); position_x = position_row->add_field(EFFECT_FIELD_DOUBLE, "posx"); // position X @@ -139,5 +140,9 @@ void TransformEffect::process_coords(double timecode, GLTextureCoords& coords, i // opacity float color[4]; glGetFloatv(GL_CURRENT_COLOR, color); - glColor4f(1.0, 1.0, 1.0, color[3]*(opacity->get_double_value(timecode)*0.01)); + glColor4f(1.0, 1.0, 1.0, color[3]*(opacity->get_double_value(timecode)*0.01)); +} + +void TransformEffect::process_gizmos() { + // TODO put gizmo code here } diff --git a/effects/internal/transformeffect.h b/effects/internal/transformeffect.h index bfeffcbf6..b9e3704ac 100644 --- a/effects/internal/transformeffect.h +++ b/effects/internal/transformeffect.h @@ -9,6 +9,7 @@ public: TransformEffect(Clip* c, const EffectMeta* em); void refresh(); void process_coords(double timecode, GLTextureCoords& coords, int data); + void process_gizmos(); EffectField* position_x; EffectField* position_y; diff --git a/panels/effectcontrols.cpp b/panels/effectcontrols.cpp index 2bb27b32b..b4b0cdeee 100644 --- a/panels/effectcontrols.cpp +++ b/panels/effectcontrols.cpp @@ -193,6 +193,7 @@ void EffectControls::deselect_all_effects(QWidget* sender) { } } } + panel_sequence_viewer->viewer_widget->update(); } void EffectControls::open_effect(QVBoxLayout* layout, Effect* e) { diff --git a/panels/project.cpp b/panels/project.cpp index 74228c232..4cec12011 100644 --- a/panels/project.cpp +++ b/panels/project.cpp @@ -811,7 +811,6 @@ QTreeWidgetItem* Project::find_loaded_folder_by_id(int id) { const EffectMeta* get_meta_from_name(const QString& name, int type) { QVector& effect_list = (type == EFFECT_TYPE_VIDEO) ? video_effects : audio_effects; for (int j=0;j #include @@ -457,7 +458,12 @@ GLuint ViewerWidget::compose_sequence(QVector& nests, bool render_audio) // EFFECT CODE START 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, TA_NO_TRANSITION); + Effect* e = c->effects.at(j); + process_effect(c, e, timecode, coords, composite_texture, fbo_switcher, TA_NO_TRANSITION); + + if (e->enable_gizmos && e->container->selected) { + gizmos = e; + } } if (c->get_opening_transition() != NULL) { @@ -612,6 +618,8 @@ GLuint ViewerWidget::compose_sequence(QVector& nests, bool render_audio) void ViewerWidget::paintGL() { if (viewer->seq != NULL) { + gizmos = NULL; + bool render_audio = (viewer->playing || rendering); bool loop = false; do { @@ -670,6 +678,10 @@ void ViewerWidget::paintGL() { drawTitleSafeArea(); } + if (gizmos != NULL && !rendering) { + gizmos->process_gizmos(); + } + glDisable(GL_BLEND); glDisable(GL_TEXTURE_2D); } while (loop); diff --git a/ui/viewerwidget.h b/ui/viewerwidget.h index 7d15b8cc2..3b3cc709f 100644 --- a/ui/viewerwidget.h +++ b/ui/viewerwidget.h @@ -47,6 +47,7 @@ private: 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, int data); + Effect* gizmos; private slots: void retry(); void show_context_menu(); From 1a8c89371eac26f6f9183e889061679b34c1deb3 Mon Sep 17 00:00:00 2001 From: itsmattkc Date: Sun, 25 Nov 2018 00:39:47 +1100 Subject: [PATCH 11/31] tweaked gizmo behavior --- ui/viewerwidget.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ui/viewerwidget.cpp b/ui/viewerwidget.cpp index 0843e150b..30203983a 100644 --- a/ui/viewerwidget.cpp +++ b/ui/viewerwidget.cpp @@ -139,7 +139,7 @@ void ViewerWidget::mouseMoveEvent(QMouseEvent* event) { if (dragging) { if (waveform) { seek_from_click(event->x()); - } else { + } else if (gizmos == NULL) { QDrag* drag = new QDrag(this); QMimeData* mimeData = new QMimeData; mimeData->setText("h"); // QMimeData will fail without some kind of data @@ -461,7 +461,7 @@ GLuint ViewerWidget::compose_sequence(QVector& nests, bool render_audio) Effect* e = c->effects.at(j); process_effect(c, e, timecode, coords, composite_texture, fbo_switcher, TA_NO_TRANSITION); - if (e->enable_gizmos && e->container->selected) { + if (gizmos == NULL && e->enable_gizmos && (e->container->selected || panel_timeline->is_clip_selected(c, true))) { gizmos = e; } } From 7d11c9fbabd96e39b6485a7e2adaeb35ca3c3338 Mon Sep 17 00:00:00 2001 From: itsmattkc Date: Sun, 25 Nov 2018 01:45:32 +1100 Subject: [PATCH 12/31] rudimentary support for #119 in transform effect --- effects/internal/transformeffect.cpp | 43 ++++++++++++++++++++++++++-- effects/internal/transformeffect.h | 10 ++++++- project/effect.cpp | 5 +++- project/effect.h | 7 ++++- ui/viewerwidget.cpp | 26 +++++++++++------ 5 files changed, 78 insertions(+), 13 deletions(-) diff --git a/effects/internal/transformeffect.cpp b/effects/internal/transformeffect.cpp index 517e21cda..48a4eed65 100644 --- a/effects/internal/transformeffect.cpp +++ b/effects/internal/transformeffect.cpp @@ -7,6 +7,7 @@ #include #include #include +#include #include "ui/collapsiblewidget.h" #include "project/clip.h" @@ -143,6 +144,44 @@ void TransformEffect::process_coords(double timecode, GLTextureCoords& coords, i glColor4f(1.0, 1.0, 1.0, color[3]*(opacity->get_double_value(timecode)*0.01)); } -void TransformEffect::process_gizmos() { - // TODO put gizmo code here +void TransformEffect::gizmo_draw(double timecode, GLTextureCoords& coords) { + // proof of concept drawing pattern + + /*float color[4]; + glGetFloatv(GL_CURRENT_COLOR, color); + + glBegin(GL_TRIANGLES); + glColor4f(1.0, 0.0, 0.0, 0.5); + glVertex3f(coords.vertexTopLeftX, coords.vertexTopLeftY, 1); + glVertex3f(coords.vertexTopRightX, coords.vertexTopRightY, 1); + glVertex3f(coords.vertexBottomLeftX, coords.vertexBottomLeftY, 1); + glColor4f(0.0, 0.0, 1.0, 0.5); + glVertex3f(coords.vertexTopRightX, coords.vertexTopRightY, 1); + glVertex3f(coords.vertexBottomLeftX, coords.vertexBottomLeftY, 1); + glVertex3f(coords.vertexBottomRightX, coords.vertexBottomRightY, 1); + glEnd(); + + glColor4f(color[0], color[1], color[2], color[3]);*/ +} + +void TransformEffect::gizmo_down(QMouseEvent *event, double) { + dragging = true; + drag_start_x = event->pos().x(); + drag_start_y = event->pos().y(); +} + +void TransformEffect::gizmo_move(QMouseEvent *event, double timecode) { + if (dragging) { + position_x->set_double_value(position_x->get_double_value(timecode) + (event->pos().x() - drag_start_x)); + position_y->set_double_value(position_y->get_double_value(timecode) + (event->pos().y() - drag_start_y)); + + drag_start_x = event->pos().x(); + drag_start_y = event->pos().y(); + + field_changed(); + } +} + +void TransformEffect::gizmo_up(QMouseEvent *event, double) { + dragging = false; } diff --git a/effects/internal/transformeffect.h b/effects/internal/transformeffect.h index b9e3704ac..38834c45d 100644 --- a/effects/internal/transformeffect.h +++ b/effects/internal/transformeffect.h @@ -9,7 +9,11 @@ public: TransformEffect(Clip* c, const EffectMeta* em); void refresh(); void process_coords(double timecode, GLTextureCoords& coords, int data); - void process_gizmos(); + + void gizmo_draw(double timecode, GLTextureCoords& coords); + void gizmo_down(QMouseEvent *event, double); + void gizmo_move(QMouseEvent *event, double); + void gizmo_up(QMouseEvent *event, double); EffectField* position_x; EffectField* position_y; @@ -26,6 +30,10 @@ public slots: private: int default_anchor_x; int default_anchor_y; + + bool dragging; + int drag_start_x; + int drag_start_y; }; #endif // TRANSFORMEFFECT_H diff --git a/project/effect.cpp b/project/effect.cpp index 0731d3336..4b0150c83 100644 --- a/project/effect.cpp +++ b/project/effect.cpp @@ -833,7 +833,10 @@ void Effect::process_audio(double, double, quint8*, int, int) { }*/ } -void Effect::process_gizmos() {} +void Effect::gizmo_draw(double, GLTextureCoords &) {} +void Effect::gizmo_down(QMouseEvent *, double) {} +void Effect::gizmo_move(QMouseEvent *, double) {} +void Effect::gizmo_up(QMouseEvent *, double) {} void Effect::redraw(double) { /* diff --git a/project/effect.h b/project/effect.h index 62f8ba53d..ecf2cff05 100644 --- a/project/effect.h +++ b/project/effect.h @@ -15,6 +15,7 @@ class QWidget; class CollapsibleWidget; class QGridLayout; class QPushButton; +class QMouseEvent; struct Clip; class QXmlStreamReader; @@ -152,7 +153,11 @@ public: 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); - virtual void process_gizmos(); + + virtual void gizmo_draw(double timecode, GLTextureCoords& coords); + virtual void gizmo_down(QMouseEvent* event, double); + virtual void gizmo_move(QMouseEvent* event, double); + virtual void gizmo_up(QMouseEvent* event, double); public slots: void field_changed(); private slots: diff --git a/ui/viewerwidget.cpp b/ui/viewerwidget.cpp index 30203983a..8f01b761d 100644 --- a/ui/viewerwidget.cpp +++ b/ui/viewerwidget.cpp @@ -130,9 +130,14 @@ void ViewerWidget::seek_from_click(int x) { viewer->seek(getFrameFromScreenPoint((double) width() / (double) waveform_clip->timeline_out, x)); } +double get_timecode(Clip* c, long playhead) { + return ((double)(playhead-c->get_timeline_in_with_transition()+c->get_clip_in_with_transition())/(double)c->sequence->frame_rate); +} + void ViewerWidget::mousePressEvent(QMouseEvent* event) { if (waveform) seek_from_click(event->x()); dragging = true; + if (gizmos != NULL) gizmos->gizmo_down(event, get_timecode(gizmos->parent_clip, gizmos->parent_clip->sequence->playhead)); } void ViewerWidget::mouseMoveEvent(QMouseEvent* event) { @@ -147,10 +152,12 @@ void ViewerWidget::mouseMoveEvent(QMouseEvent* event) { drag->exec(); } } + if (gizmos != NULL) gizmos->gizmo_move(event, get_timecode(gizmos->parent_clip, gizmos->parent_clip->sequence->playhead)); } -void ViewerWidget::mouseReleaseEvent(QMouseEvent *) { +void ViewerWidget::mouseReleaseEvent(QMouseEvent *event) { dragging = false; + if (gizmos != NULL) gizmos->gizmo_up(event, get_timecode(gizmos->parent_clip, gizmos->parent_clip->sequence->playhead)); } void ViewerWidget::drawTitleSafeArea() { @@ -168,7 +175,7 @@ void ViewerWidget::drawTitleSafeArea() { } glLoadIdentity(); - glOrtho(-halfWidth, halfWidth, halfHeight, -halfHeight, -1, 1); + glOrtho(-halfWidth, halfWidth, halfHeight, -halfHeight, 0, 1); glColor4f(0.66f, 0.66f, 0.66f, 1.0f); glBegin(GL_LINES); @@ -437,6 +444,8 @@ GLuint ViewerWidget::compose_sequence(QVector& nests, bool render_audio) fbo_switcher = !fbo_switcher; + bool draw_gizmos = false; + GLTextureCoords coords; coords.grid_size = 1; coords.vertexTopLeftX = coords.vertexBottomLeftX = -video_width/2; @@ -456,13 +465,14 @@ GLuint ViewerWidget::compose_sequence(QVector& nests, bool render_audio) } // EFFECT CODE START - double timecode = ((double)(playhead-c->get_timeline_in_with_transition()+c->get_clip_in_with_transition())/(double)c->sequence->frame_rate); + double timecode = get_timecode(c, playhead); for (int j=0;jeffects.size();j++) { Effect* e = c->effects.at(j); process_effect(c, e, timecode, coords, composite_texture, fbo_switcher, TA_NO_TRANSITION); - if (gizmos == NULL && e->enable_gizmos && (e->container->selected || panel_timeline->is_clip_selected(c, true))) { + if (!rendering && gizmos == NULL && e->enable_gizmos && (e->container->selected || panel_timeline->is_clip_selected(c, true))) { gizmos = e; + draw_gizmos = true; } } @@ -551,6 +561,10 @@ GLuint ViewerWidget::compose_sequence(QVector& nests, bool render_audio) glBindTexture(GL_TEXTURE_2D, 0); // unbind texture + if (draw_gizmos) { + gizmos->gizmo_draw(timecode, coords); + } + if (!nests.isEmpty()) { nests.last()->fbo[0]->release(); if (default_fbo != NULL) default_fbo->bind(); @@ -678,10 +692,6 @@ void ViewerWidget::paintGL() { drawTitleSafeArea(); } - if (gizmos != NULL && !rendering) { - gizmos->process_gizmos(); - } - glDisable(GL_BLEND); glDisable(GL_TEXTURE_2D); } while (loop); From 313b9d1a1b48e2d8bcd01a90c434718115f401c7 Mon Sep 17 00:00:00 2001 From: itsmattkc Date: Sun, 25 Nov 2018 09:44:16 +1100 Subject: [PATCH 13/31] added length field for transitions --- panels/project.cpp | 4 ++-- panels/timeline.cpp | 24 ++++++++++----------- project/clip.cpp | 6 +++--- project/effect.cpp | 48 +++++++++++++++++++++--------------------- project/effect.h | 3 +-- project/effectrow.cpp | 3 ++- project/effectrow.h | 3 ++- project/transition.cpp | 33 +++++++++++++++++++++++++++-- project/transition.h | 8 +++++++ project/undo.cpp | 10 ++++----- ui/timelinewidget.cpp | 48 +++++++++++++++++++++--------------------- 11 files changed, 114 insertions(+), 76 deletions(-) diff --git a/panels/project.cpp b/panels/project.cpp index 4cec12011..96ad97d39 100644 --- a/panels/project.cpp +++ b/panels/project.cpp @@ -876,7 +876,7 @@ void load_effect(QXmlStreamReader& stream, Clip* c) { int transition_index = create_transition(c, NULL, meta); Transition* t = c->sequence->transitions.at(transition_index); - if (effect_length > -1) t->length = effect_length; + if (effect_length > -1) t->set_length(effect_length); t->set_enabled(effect_enabled); t->load(stream); @@ -1255,7 +1255,7 @@ bool Project::load_worker(QFile& f, QXmlStreamReader& stream, int type) { if (td.ctc != NULL) td.ctc->closing_transition = -1; } else { int transition_index = create_transition(primary, secondary, meta); - primary->sequence->transitions.at(transition_index)->length = td.length; + primary->sequence->transitions.at(transition_index)->set_length(td.length); if (td.otc != NULL) td.otc->opening_transition = transition_index; if (td.ctc != NULL) td.ctc->closing_transition = transition_index; } diff --git a/panels/timeline.cpp b/panels/timeline.cpp index e3d56034b..71ae30183 100644 --- a/panels/timeline.cpp +++ b/panels/timeline.cpp @@ -643,7 +643,7 @@ Clip* Timeline::split_clip(ComboAction* ca, int p, long frame, long post_in) { pre->get_opening_transition()->secondary_clip->closing_transition = pre->get_opening_transition()->copy(pre->get_opening_transition()->secondary_clip, NULL); }*/ - if (pre->get_opening_transition()->length > new_clip_length) { + if (pre->get_opening_transition()->get_true_length() > new_clip_length) { ca->append(new ModifyTransitionCommand(pre, TA_OPENING_TRANSITION, new_clip_length)); } @@ -651,7 +651,7 @@ Clip* Timeline::split_clip(ComboAction* ca, int p, long frame, long post_in) { } if (pre->get_closing_transition() != NULL) { ca->append(new DeleteTransitionCommand(pre, TA_CLOSING_TRANSITION)); - if (pre->get_closing_transition()->secondary_clip == NULL) post->get_closing_transition()->length = qMin((long) post->get_closing_transition()->length, post->getLength()); + if (pre->get_closing_transition()->secondary_clip == NULL) post->get_closing_transition()->set_length(qMin((long) post->get_closing_transition()->get_true_length(), post->getLength())); } return post; @@ -751,14 +751,14 @@ void Timeline::clean_up_selections(QVector& areas) { bool selection_contains_transition(const Selection& s, Clip* c, int type) { if (type == TA_OPENING_TRANSITION) { return c->get_opening_transition() != NULL - && s.out == c->timeline_in + c->get_opening_transition()->length + && s.out == c->timeline_in + c->get_opening_transition()->get_true_length() && ((c->get_opening_transition()->secondary_clip == NULL && s.in == c->timeline_in) - || (c->get_opening_transition()->secondary_clip != NULL && s.in == c->timeline_in - c->get_opening_transition()->length)); + || (c->get_opening_transition()->secondary_clip != NULL && s.in == c->timeline_in - c->get_opening_transition()->get_true_length())); } else { return c->get_closing_transition() != NULL - && s.in == c->timeline_out - c->get_closing_transition()->length + && s.in == c->timeline_out - c->get_closing_transition()->get_true_length() && ((c->get_closing_transition()->secondary_clip == NULL && s.out == c->timeline_out) - || (c->get_closing_transition()->secondary_clip != NULL && s.out == c->timeline_out + c->get_closing_transition()->length)); + || (c->get_closing_transition()->secondary_clip != NULL && s.out == c->timeline_out + c->get_closing_transition()->get_true_length())); } } @@ -795,10 +795,10 @@ void Timeline::delete_areas_and_relink(ComboAction* ca, QVector& area move_clip(ca, c, c->timeline_in, s.in, c->clip_in, c->track); if (c->get_closing_transition() != NULL) { - if (s.in < c->timeline_out - c->get_closing_transition()->length) { + if (s.in < c->timeline_out - c->get_closing_transition()->get_true_length()) { ca->append(new DeleteTransitionCommand(c, TA_CLOSING_TRANSITION)); } else { - ca->append(new ModifyTransitionCommand(c, TA_CLOSING_TRANSITION, c->get_closing_transition()->length - (c->timeline_out - s.in))); + ca->append(new ModifyTransitionCommand(c, TA_CLOSING_TRANSITION, c->get_closing_transition()->get_true_length() - (c->timeline_out - s.in))); } } } else if (c->timeline_in < s.out && c->timeline_out > s.out) { @@ -806,10 +806,10 @@ void Timeline::delete_areas_and_relink(ComboAction* ca, QVector& area move_clip(ca, c, s.out, c->timeline_out, c->clip_in + (s.out - c->timeline_in), c->track); if (c->get_opening_transition() != NULL) { - if (s.out > c->timeline_in + c->get_opening_transition()->length) { + if (s.out > c->timeline_in + c->get_opening_transition()->get_true_length()) { ca->append(new DeleteTransitionCommand(c, TA_OPENING_TRANSITION)); } else { - ca->append(new ModifyTransitionCommand(c, TA_OPENING_TRANSITION, c->get_opening_transition()->length - (s.out - c->timeline_in))); + ca->append(new ModifyTransitionCommand(c, TA_OPENING_TRANSITION, c->get_opening_transition()->get_true_length() - (s.out - c->timeline_in))); } } } @@ -1241,10 +1241,10 @@ bool Timeline::snap_to_timeline(long* l, bool use_playhead, bool use_markers, bo } else if (snap_to_point(c->timeline_out, l)) { return true; } else if (c->get_opening_transition() != NULL - && snap_to_point(c->timeline_in + c->get_opening_transition()->length, l)) { + && snap_to_point(c->timeline_in + c->get_opening_transition()->get_true_length(), l)) { return true; } else if (c->get_closing_transition() != NULL - && snap_to_point(c->timeline_out - c->get_closing_transition()->length, l)) { + && snap_to_point(c->timeline_out - c->get_closing_transition()->get_true_length(), l)) { return true; } } diff --git a/project/clip.cpp b/project/clip.cpp index d136f666c..08bf01299 100644 --- a/project/clip.cpp +++ b/project/clip.cpp @@ -181,7 +181,7 @@ Clip::~Clip() { 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 - get_opening_transition()->get_true_length(); } return clip_in; } @@ -189,7 +189,7 @@ long Clip::get_clip_in_with_transition() { 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) - return timeline_in - get_opening_transition()->length; + return timeline_in - get_opening_transition()->get_true_length(); } return timeline_in; } @@ -197,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()->length; + return timeline_out + get_closing_transition()->get_true_length(); } else { return timeline_out; } diff --git a/project/effect.cpp b/project/effect.cpp index 4b0150c83..bd524fb98 100644 --- a/project/effect.cpp +++ b/project/effect.cpp @@ -220,7 +220,6 @@ void EffectInit::run() { Effect::Effect(Clip* c, const EffectMeta *em) : parent_clip(c), meta(em), - length(30), enable_shader(false), enable_coords(false), enable_superimpose(false), @@ -446,8 +445,8 @@ void Effect::copy_field_keyframes(Effect* e) { } } -EffectRow* Effect::add_row(const QString& name) { - EffectRow* row = new EffectRow(this, ui_layout, name, rows.size()); +EffectRow* Effect::add_row(const QString& name, bool savable) { + EffectRow* row = new EffectRow(this, savable, ui_layout, name, rows.size()); rows.append(row); return row; } @@ -668,31 +667,32 @@ void Effect::load(QXmlStreamReader& stream) { void Effect::save(QXmlStreamWriter& stream) { stream.writeAttribute("name", meta->name); stream.writeAttribute("enabled", QString::number(is_enabled())); - stream.writeAttribute("length", QString::number(length)); for (int i=0;iisKeyframing())); - for (int j=0;jkeyframe_times.size();j++) { - stream.writeStartElement("key"); // key - stream.writeAttribute("frame", QString::number(row->keyframe_times.at(j))); - stream.writeAttribute("type", QString::number(row->keyframe_types.at(j))); - stream.writeEndElement(); // key + if (row->savable) { + stream.writeStartElement("row"); // row + stream.writeStartElement("keyframes"); // keyframes + stream.writeAttribute("enabled", QString::number(row->isKeyframing())); + for (int j=0;jkeyframe_times.size();j++) { + stream.writeStartElement("key"); // key + stream.writeAttribute("frame", QString::number(row->keyframe_times.at(j))); + stream.writeAttribute("type", QString::number(row->keyframe_types.at(j))); + stream.writeEndElement(); // key + } + stream.writeEndElement(); // keyframes + for (int j=0;jfieldCount();j++) { + EffectField* field = row->field(j); + stream.writeStartElement("field"); // field + stream.writeAttribute("id", field->id); + stream.writeAttribute("value", save_data_to_string(field->type, field->get_current_data())); + for (int k=0;kkeyframe_data.size();k++) { + stream.writeTextElement("key", save_data_to_string(field->type, field->keyframe_data.at(k))); + } + stream.writeEndElement(); // field + } + stream.writeEndElement(); // row } - stream.writeEndElement(); // keyframes - for (int j=0;jfieldCount();j++) { - EffectField* field = row->field(j); - stream.writeStartElement("field"); // field - stream.writeAttribute("id", field->id); - stream.writeAttribute("value", save_data_to_string(field->type, field->get_current_data())); - for (int k=0;kkeyframe_data.size();k++) { - stream.writeTextElement("key", save_data_to_string(field->type, field->keyframe_data.at(k))); - } - stream.writeEndElement(); // field - } - stream.writeEndElement(); // row } } diff --git a/project/effect.h b/project/effect.h index ecf2cff05..be7979199 100644 --- a/project/effect.h +++ b/project/effect.h @@ -113,12 +113,11 @@ public: ~Effect(); Clip* parent_clip; const EffectMeta* meta; - long length; // used only for transitions int id; QString name; CollapsibleWidget* container; - EffectRow* add_row(const QString &name); + EffectRow* add_row(const QString &name, bool savable = true); EffectRow* row(int i); int row_count(); diff --git a/project/effectrow.cpp b/project/effectrow.cpp index aac97d6b7..2ce7244c7 100644 --- a/project/effectrow.cpp +++ b/project/effectrow.cpp @@ -14,8 +14,9 @@ #include "effect.h" #include "ui/viewerwidget.h" -EffectRow::EffectRow(Effect *parent, QGridLayout *uilayout, const QString &n, int row) : +EffectRow::EffectRow(Effect *parent, bool save, QGridLayout *uilayout, const QString &n, int row) : parent_effect(parent), + savable(save), keyframing(false), ui(uilayout), name(n), diff --git a/project/effectrow.h b/project/effectrow.h index 5a6305a09..5ae5165e7 100644 --- a/project/effectrow.h +++ b/project/effectrow.h @@ -14,7 +14,7 @@ class QPushButton; class EffectRow : public QObject { Q_OBJECT public: - EffectRow(Effect* parent, QGridLayout* uilayout, const QString& n, int row); + EffectRow(Effect* parent, bool save, QGridLayout* uilayout, const QString& n, int row); ~EffectRow(); EffectField* add_field(int type, const QString &id, int colspan = 1); EffectField* field(int i); @@ -24,6 +24,7 @@ public: void delete_keyframe_at_time(KeyframeDelete* kd, long time); QLabel* label; Effect* parent_effect; + bool savable; bool isKeyframing(); void setKeyframing(bool); diff --git a/project/transition.cpp b/project/transition.cpp index be8db58ad..440ae7729 100644 --- a/project/transition.cpp +++ b/project/transition.cpp @@ -11,10 +11,25 @@ #include "effects/internal/logarithmicfadetransition.h" #include "effects/internal/cubetransition.h" +#include "ui/labelslider.h" + +#include "panels/panels.h" +#include "panels/timeline.h" + #include -Transition::Transition(Clip* c, Clip* s, const EffectMeta* em) : Effect(c, em), secondary_clip(s) { -// add_row("Length:", false)->add_field(EFFECT_FIELD_DOUBLE, "length"); +Transition::Transition(Clip* c, Clip* s, const EffectMeta* em) : + Effect(c, em), secondary_clip(s), + length(30) +{ + length_field = add_row("Length:", false)->add_field(EFFECT_FIELD_DOUBLE, "length"); + connect(length_field, SIGNAL(changed()), this, SLOT(set_length_from_slider())); + length_field->set_double_default_value(30); + length_field->set_double_minimum_value(0); + + LabelSlider* length_ui_ele = static_cast(length_field->ui_element); + length_ui_ele->set_display_type(LABELSLIDER_FRAMENUMBER); + length_ui_ele->set_frame_rate(parent_clip->sequence->frame_rate); } int Transition::copy(Clip *c, Clip* s) { @@ -23,6 +38,15 @@ int Transition::copy(Clip *c, Clip* s) { return copy_index; } +void Transition::set_length(long l) { + length = l; + length_field->set_double_value(l); +} + +long Transition::get_true_length() { + return length; +} + long Transition::get_length() { if (secondary_clip != NULL) { return length * 2; @@ -30,6 +54,11 @@ long Transition::get_length() { return length; } +void Transition::set_length_from_slider() { + set_length(length_field->get_double_value(0)); + update_ui(false); +} + 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 e998fdb61..2f9df63f4 100644 --- a/project/transition.h +++ b/project/transition.h @@ -17,11 +17,19 @@ int create_transition(Clip* c, Clip* s, const EffectMeta* em); class Transition : public Effect { + Q_OBJECT public: Transition(Clip* c, Clip* s, const EffectMeta* em); int copy(Clip* c, Clip* s); Clip* secondary_clip; + void set_length(long l); + long get_true_length(); long get_length(); +private slots: + void set_length_from_slider(); +private: + long length; // used only for transitions + EffectField* length_field; }; #endif // TRANSITION_H diff --git a/project/undo.cpp b/project/undo.cpp index 22c1f8a0b..48dd2989f 100644 --- a/project/undo.cpp +++ b/project/undo.cpp @@ -258,7 +258,7 @@ void AddTransitionCommand::redo() { secondary->closing_transition = clip->opening_transition; } if (length > 0) { - clip->get_opening_transition()->length = length; + clip->get_opening_transition()->set_length(length); } } else { old_ptransition = clip->closing_transition; @@ -268,7 +268,7 @@ void AddTransitionCommand::redo() { secondary->opening_transition = clip->closing_transition; } if (length > 0) { - clip->get_closing_transition()->length = length; + clip->get_closing_transition()->set_length(length); } } mainWindow->setWindowModified(true); @@ -283,14 +283,14 @@ ModifyTransitionCommand::ModifyTransitionCommand(Clip* c, int itype, long ilengt void ModifyTransitionCommand::undo() { Transition* t = (type == TA_OPENING_TRANSITION) ? clip->get_opening_transition() : clip->get_closing_transition(); - t->length = old_length; + t->set_length(old_length); mainWindow->setWindowModified(old_project_changed); } void ModifyTransitionCommand::redo() { Transition* t = (type == TA_OPENING_TRANSITION) ? clip->get_opening_transition() : clip->get_closing_transition(); - old_length = t->length; - t->length = new_length; + old_length = t->get_true_length(); + t->set_length(new_length); mainWindow->setWindowModified(true); } diff --git a/ui/timelinewidget.cpp b/ui/timelinewidget.cpp index bd990f19b..043173b27 100644 --- a/ui/timelinewidget.cpp +++ b/ui/timelinewidget.cpp @@ -607,12 +607,12 @@ void TimelineWidget::mousePressEvent(QMouseEvent *event) { if (panel_timeline->transition_select == TA_OPENING_TRANSITION && clip->get_opening_transition() != NULL) { s.in = clip->timeline_in; - if (clip->get_opening_transition()->secondary_clip != NULL) s.in -= clip->get_opening_transition()->length; - s.out = clip->timeline_in + clip->get_opening_transition()->length; + if (clip->get_opening_transition()->secondary_clip != NULL) s.in -= clip->get_opening_transition()->get_true_length(); + s.out = clip->timeline_in + clip->get_opening_transition()->get_true_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.in = clip->timeline_out - clip->get_closing_transition()->get_true_length(); s.out = clip->timeline_out; - if (clip->get_closing_transition()->secondary_clip != NULL) s.out += clip->get_closing_transition()->length; + if (clip->get_closing_transition()->secondary_clip != NULL) s.out += clip->get_closing_transition()->get_true_length(); } sequence->selections.append(s); } @@ -629,13 +629,13 @@ void TimelineWidget::mousePressEvent(QMouseEvent *event) { if (panel_timeline->tool == TIMELINE_TOOL_POINTER) { if (panel_timeline->transition_select == TA_OPENING_TRANSITION) { - s.out = clip->timeline_in + clip->get_opening_transition()->length; - if (clip->get_opening_transition()->secondary_clip != NULL) s.in -= clip->get_opening_transition()->length; + s.out = clip->timeline_in + clip->get_opening_transition()->get_true_length(); + if (clip->get_opening_transition()->secondary_clip != NULL) s.in -= clip->get_opening_transition()->get_true_length(); } if (panel_timeline->transition_select == TA_CLOSING_TRANSITION) { - s.in = clip->timeline_out - clip->get_closing_transition()->length; - if (clip->get_closing_transition()->secondary_clip != NULL) s.out += clip->get_closing_transition()->length; + s.in = clip->timeline_out - clip->get_closing_transition()->get_true_length(); + if (clip->get_closing_transition()->secondary_clip != NULL) s.out += clip->get_closing_transition()->get_true_length(); } } @@ -707,7 +707,7 @@ void make_room_for_transition(ComboAction* ca, Clip* c, int type, long transitio 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->get_closing_transition()->length) { + } else if (transition_end > c->timeline_out - c->get_closing_transition()->get_true_length()) { ca->append(new ModifyTransitionCommand(c, TA_CLOSING_TRANSITION, c->timeline_out - transition_end)); } } @@ -718,7 +718,7 @@ void make_room_for_transition(ComboAction* ca, Clip* c, int type, long transitio 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->get_opening_transition()->length) { + } else if (transition_start < c->timeline_in + c->get_opening_transition()->get_true_length()) { ca->append(new ModifyTransitionCommand(c, TA_OPENING_TRANSITION, transition_start - c->timeline_in)); } } @@ -941,22 +941,22 @@ void TimelineWidget::mouseReleaseEvent(QMouseEvent *event) { if (c->get_opening_transition() != NULL) { long max_open_length = new_clip_length; if (c->get_closing_transition() != NULL && !panel_timeline->trim_in_point) { - max_open_length -= c->get_closing_transition()->length; + max_open_length -= c->get_closing_transition()->get_true_length(); } if (max_open_length <= 0) { ca->append(new DeleteTransitionCommand(c, TA_OPENING_TRANSITION)); - } else if (c->get_opening_transition()->length > max_open_length) { + } else if (c->get_opening_transition()->get_true_length() > max_open_length) { ca->append(new ModifyTransitionCommand(c, TA_OPENING_TRANSITION, max_open_length)); } } if (c->get_closing_transition() != NULL) { long max_open_length = new_clip_length; if (c->get_opening_transition() != NULL && panel_timeline->trim_in_point) { - max_open_length -= c->get_opening_transition()->length; + max_open_length -= c->get_opening_transition()->get_true_length(); } if (max_open_length <= 0) { ca->append(new DeleteTransitionCommand(c, TA_CLOSING_TRANSITION)); - } else if (c->get_closing_transition()->length > max_open_length) { + } else if (c->get_closing_transition()->get_true_length() > max_open_length) { ca->append(new ModifyTransitionCommand(c, TA_CLOSING_TRANSITION, max_open_length)); } } @@ -1144,7 +1144,7 @@ void TimelineWidget::init_ghosts() { 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; + g.clip_in = g.old_clip_in = c->clip_in + c->getLength() - c->get_closing_transition()->get_true_length(); } // used for trim ops @@ -1291,7 +1291,7 @@ void TimelineWidget::update_ghosts(const QPoint& mouse_pos, bool lock_frame) { Clip* otc = g.transition->parent_clip; Clip* ctc = g.transition->secondary_clip; - validate_transitions(otc, ctc, g.transition->length, frame_diff); + validate_transitions(otc, ctc, g.transition->get_true_length(), frame_diff); // TESTING CODE END if (g.trim_in) { @@ -1340,7 +1340,7 @@ void TimelineWidget::update_ghosts(const QPoint& mouse_pos, bool lock_frame) { validator = g.transition->secondary_clip->get_timeline_out_with_transition() - g.transition->secondary_clip->get_timeline_in_with_transition() - g.transition->get_length() + g.transition->secondary_clip->get_clip_in_with_transition() + frame_diff; if (validator < 0) frame_diff -= validator; - validator = g.transition->parent_clip->clip_in + frame_diff - g.transition->parent_clip->getMaximumLength() + g.transition->length; + validator = g.transition->parent_clip->clip_in + frame_diff - g.transition->parent_clip->getMaximumLength() + g.transition->get_true_length(); if (validator > 0) frame_diff -= validator; validator = g.transition->secondary_clip->get_timeline_out_with_transition() - g.transition->secondary_clip->get_timeline_in_with_transition() + g.transition->secondary_clip->get_clip_in_with_transition() + frame_diff - g.transition->secondary_clip->getMaximumLength(); @@ -1935,9 +1935,9 @@ void TimelineWidget::mouseMoveEvent(QMouseEvent *event) { tooltip_timer.start(); tooltip_clip = i; - if (c->get_opening_transition() != NULL && panel_timeline->cursor_frame <= c->timeline_in + c->get_opening_transition()->length) { + if (c->get_opening_transition() != NULL && panel_timeline->cursor_frame <= c->timeline_in + c->get_opening_transition()->get_true_length()) { panel_timeline->transition_select = TA_OPENING_TRANSITION; - } else if (c->get_closing_transition() != NULL && panel_timeline->cursor_frame >= c->timeline_out - c->get_closing_transition()->length) { + } else if (c->get_closing_transition() != NULL && panel_timeline->cursor_frame >= c->timeline_out - c->get_closing_transition()->get_true_length()) { panel_timeline->transition_select = TA_CLOSING_TRANSITION; } } @@ -1961,7 +1961,7 @@ void TimelineWidget::mouseMoveEvent(QMouseEvent *event) { } if (panel_timeline->tool == TIMELINE_TOOL_POINTER) { if (c->get_opening_transition() != NULL) { - long transition_point = c->timeline_in + c->get_opening_transition()->length; + long transition_point = c->timeline_in + c->get_opening_transition()->get_true_length(); if (transition_point > mouse_frame_lower && transition_point < mouse_frame_upper) { int nc = qAbs(transition_point - 1 - panel_timeline->cursor_frame); @@ -1975,7 +1975,7 @@ void TimelineWidget::mouseMoveEvent(QMouseEvent *event) { } } if (c->get_closing_transition() != NULL) { - long transition_point = c->timeline_out - c->get_closing_transition()->length; + long transition_point = c->timeline_out - c->get_closing_transition()->get_true_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) { @@ -2129,7 +2129,7 @@ void draw_transition(QPainter& p, Clip* c, const QRect& clip_rect, QRect& text_r Transition* t = (transition_type == TA_OPENING_TRANSITION) ? c->get_opening_transition() : c->get_closing_transition(); if (t != NULL) { QColor transition_color(255, 0, 0, 16); - int transition_width = getScreenPointFromFrame(panel_timeline->zoom, t->length); + int transition_width = getScreenPointFromFrame(panel_timeline->zoom, t->get_true_length()); int transition_height = clip_rect.height(); int tr_y = clip_rect.y(); int tr_x = 0; @@ -2274,12 +2274,12 @@ void TimelineWidget::paintEvent(QPaintEvent*) { if (thumb_x < width() && thumb_y < height()) { int space_for_thumb = clip_rect.width()-1; if (clip->get_opening_transition() != NULL) { - int ot_width = getScreenPointFromFrame(panel_timeline->zoom, clip->get_opening_transition()->length); + int ot_width = getScreenPointFromFrame(panel_timeline->zoom, clip->get_opening_transition()->get_true_length()); thumb_x += ot_width; space_for_thumb -= ot_width; } if (clip->get_closing_transition() != NULL) { - space_for_thumb -= getScreenPointFromFrame(panel_timeline->zoom, clip->get_closing_transition()->length); + space_for_thumb -= getScreenPointFromFrame(panel_timeline->zoom, clip->get_closing_transition()->get_true_length()); } int thumb_height = clip_rect.height()-thumb_y; int thumb_width = (thumb_height*((double)ms->video_preview.width()/(double)ms->video_preview.height())); From 3a4b9c75311432b49cb9549b50eab55448715d9f Mon Sep 17 00:00:00 2001 From: itsmattkc Date: Sun, 25 Nov 2018 18:20:28 +1100 Subject: [PATCH 14/31] added millisecond view mode --- io/config.h | 1 + mainwindow.cpp | 6 ++++++ mainwindow.h | 2 ++ mainwindow.ui | 11 ++++++++++- panels/viewer.cpp | 37 +++++++++++++++++++++++++++++-------- project/effectrow.cpp | 6 ++++-- 6 files changed, 52 insertions(+), 11 deletions(-) diff --git a/io/config.h b/io/config.h index 5259971a5..ea0745650 100644 --- a/io/config.h +++ b/io/config.h @@ -9,6 +9,7 @@ #define TIMECODE_DROP 0 #define TIMECODE_NONDROP 1 #define TIMECODE_FRAMES 2 +#define TIMECODE_MILLISECONDS 3 #define RECORD_MODE_MONO 1 #define RECORD_MODE_STEREO 2 diff --git a/mainwindow.cpp b/mainwindow.cpp index cb8c525e9..612c4996c 100644 --- a/mainwindow.cpp +++ b/mainwindow.cpp @@ -646,6 +646,7 @@ void MainWindow::viewMenu_About_To_Be_Shown() { ui->actionFrames->setChecked(config.timecode_view == TIMECODE_FRAMES); ui->actionDrop_Frame->setChecked(config.timecode_view == TIMECODE_DROP); ui->actionNon_Drop_Frame->setChecked(config.timecode_view == TIMECODE_NONDROP); + ui->actionMilliseconds->setChecked(config.timecode_view == TIMECODE_MILLISECONDS); ui->actionOff->setChecked(!config.show_title_safe_area); ui->actionDefault->setChecked(config.show_title_safe_area && !config.use_custom_title_safe_ratio); @@ -1012,3 +1013,8 @@ void MainWindow::on_actionPage_Autoscroll_triggered() { void MainWindow::on_actionSmooth_Auto_scroll_triggered() { config.autoscroll = AUTOSCROLL_SMOOTH_SCROLL; } + +void MainWindow::on_actionMilliseconds_triggered() { + config.timecode_view = TIMECODE_MILLISECONDS; + update_ui(false); +} diff --git a/mainwindow.h b/mainwindow.h index d4f4052c1..6d9cec2c4 100644 --- a/mainwindow.h +++ b/mainwindow.h @@ -211,6 +211,8 @@ private slots: void on_actionSmooth_Auto_scroll_triggered(); + void on_actionMilliseconds_triggered(); + private: Ui::MainWindow *ui; void setup_layout(bool reset); diff --git a/mainwindow.ui b/mainwindow.ui index 66260f4ce..b444a2a49 100644 --- a/mainwindow.ui +++ b/mainwindow.ui @@ -33,7 +33,7 @@ 0 0 653 - 19 + 25 @@ -144,6 +144,7 @@ + @@ -916,6 +917,14 @@ Smooth Auto-scroll + + + true + + + Milliseconds + + diff --git a/panels/viewer.cpp b/panels/viewer.cpp index 02fec95ac..d6d14380d 100644 --- a/panels/viewer.cpp +++ b/panels/viewer.cpp @@ -108,19 +108,37 @@ void Viewer::assert_audio_device() { long timecode_to_frame(const QString& s, int view, double frame_rate) { QList list = s.split(QRegExp("[:;]")); - if (view == TIMECODE_FRAMES || list.size() == 1) { + if (view == TIMECODE_FRAMES || (list.size() == 1 && view != TIMECODE_MILLISECONDS)) { return s.toLong(); } int frRound = qRound(frame_rate); - int hours = ((list.size() > 0) ? list.at(0).toInt() : 0) * frRound * 3600; - int minutes = ((list.size() > 1) ? list.at(1).toInt() : 0) * frRound * 60; - int seconds = ((list.size() > 2) ? list.at(2).toInt() : 0) * frRound; - int frames = (list.size() > 3) ? list.at(3).toInt() : 0; + int hours, minutes, seconds, frames; + + if (view == TIMECODE_MILLISECONDS) { + long milliseconds = s.toLong(); + + hours = milliseconds/3600000; + milliseconds -= (hours*3600000); + minutes = milliseconds/60000; + milliseconds -= (minutes*60000); + seconds = milliseconds/1000; + milliseconds -= (seconds*1000); + frames = qRound64((milliseconds*0.001)*frame_rate); + + seconds = qRound64(seconds * frame_rate); + minutes = qRound64(minutes * frame_rate * 60); + hours = qRound64(hours * frame_rate * 3600); + } else { + hours = ((list.size() > 0) ? list.at(0).toInt() : 0) * frRound * 3600; + minutes = ((list.size() > 1) ? list.at(1).toInt() : 0) * frRound * 60; + seconds = ((list.size() > 2) ? list.at(2).toInt() : 0) * frRound; + frames = (list.size() > 3) ? list.at(3).toInt() : 0; + } int f = (frames + seconds + minutes + hours); - if (view == TIMECODE_DROP && frame_rate_is_droppable(frame_rate)) { + if ((view == TIMECODE_DROP || view == TIMECODE_MILLISECONDS) && frame_rate_is_droppable(frame_rate)) { // return drop int d; int m; @@ -155,7 +173,7 @@ QString frame_to_timecode(long f, int view, double frame_rate) { int frames = 0; QString token = ":"; - if (view == TIMECODE_DROP && frame_rate_is_droppable(frame_rate)) { + if ((view == TIMECODE_DROP || view == TIMECODE_MILLISECONDS) && frame_rate_is_droppable(frame_rate)) { //CONVERT A FRAME NUMBER TO DROP FRAME TIMECODE //Code by David Heidelberger, adapted from Andrew Duncan, further adapted for Olive by Olive Team //Given an int called framenumber and a double called framerate @@ -165,7 +183,7 @@ QString frame_to_timecode(long f, int view, double frame_rate) { int m; int dropFrames = round(frame_rate * .066666); //Number of frames to drop on the minute marks is the nearest integer to 6% of the framerate - int framesPerHour = round(frame_rate*60*60); //Number of frames in an hour + int framesPerHour = round(frame_rate*60*60); //Number of frqRound64ames in an hour int framesPer24Hours = framesPerHour*24; //Number of frames in a day - timecode rolls over after 24 hours int framesPer10Minutes = round(frame_rate * 60 * 10); //Number of frames per ten minutes int framesPerMinute = (round(frame_rate)*60)- dropFrames; //Number of frames per minute is the round of the framerate * 60 minus the number of dropped frames @@ -199,6 +217,9 @@ QString frame_to_timecode(long f, int view, double frame_rate) { secs = f/int_fps % 60; frames = f%int_fps; } + if (view == TIMECODE_MILLISECONDS) { + return QString::number((hours*3600000)+(mins*60000)+(secs*1000)+qCeil(frames*1000/frame_rate)); + } return QString(QString::number(hours).rightJustified(2, '0') + ":" + QString::number(mins).rightJustified(2, '0') + ":" + QString::number(secs).rightJustified(2, '0') + diff --git a/project/effectrow.cpp b/project/effectrow.cpp index 2ce7244c7..fba1cfbe8 100644 --- a/project/effectrow.cpp +++ b/project/effectrow.cpp @@ -72,8 +72,10 @@ bool EffectRow::isKeyframing() { } void EffectRow::setKeyframing(bool b) { - keyframing = b; - keyframe_enable->setChecked(b); + if (parent_effect->meta->type != EFFECT_TYPE_TRANSITION) { + keyframing = b; + keyframe_enable->setChecked(b); + } } void EffectRow::set_keyframe_enabled(bool enabled) { From 82bcb5d25fe8f5eb996d7b4f06387c544674f262 Mon Sep 17 00:00:00 2001 From: itsmattkc Date: Tue, 27 Nov 2018 11:22:43 +1100 Subject: [PATCH 15/31] fixed critical bug that corrupts transitions --- effects/internal/transformeffect.cpp | 67 +++++++++++--------------- effects/internal/transformeffect.h | 41 ++++++++-------- olive.pro | 6 ++- panels/project.cpp | 1 + project/effect.cpp | 44 +++++++++++++++-- project/effect.h | 17 ++++--- project/effectgizmo.cpp | 35 ++++++++++++++ project/effectgizmo.h | 30 ++++++++++++ ui/viewerwidget.cpp | 71 +++++++++++++++++++++++----- ui/viewerwidget.h | 6 ++- 10 files changed, 233 insertions(+), 85 deletions(-) create mode 100644 project/effectgizmo.cpp create mode 100644 project/effectgizmo.h diff --git a/effects/internal/transformeffect.cpp b/effects/internal/transformeffect.cpp index 48a4eed65..73d4353fd 100644 --- a/effects/internal/transformeffect.cpp +++ b/effects/internal/transformeffect.cpp @@ -1,4 +1,4 @@ -#include "transformeffect.h" +#include "transformeffect.h" #include #include @@ -13,19 +13,23 @@ #include "project/clip.h" #include "project/sequence.h" #include "io/media.h" +#include "io/math.h" #include "ui/labelslider.h" #include "ui/comboboxex.h" #include "panels/project.h" #include "debug.h" +#include "panels/panels.h" +#include "panels/viewer.h" +#include "ui/viewerwidget.h" + #define BLEND_MODE_NORMAL 0 #define BLEND_MODE_SCREEN 1 #define BLEND_MODE_MULTIPLY 2 #define BLEND_MODE_OVERLAY 3 TransformEffect::TransformEffect(Clip* c, const EffectMeta* em) : Effect(c, em) { - enable_coords = true; - enable_gizmos = true; + enable_coords = true; EffectRow* position_row = add_row("Position:"); position_x = position_row->add_field(EFFECT_FIELD_DOUBLE, "posx"); // position X @@ -61,6 +65,15 @@ TransformEffect::TransformEffect(Clip* c, const EffectMeta* em) : Effect(c, em) blend_mode_box->add_combo_item("Screen", BLEND_MODE_SCREEN); blend_mode_box->add_combo_item("Multiply", BLEND_MODE_MULTIPLY); + top_left_gizmo = add_gizmo(GIZMO_TYPE_DOT); + top_center_gizmo = add_gizmo(GIZMO_TYPE_DOT); + top_right_gizmo = add_gizmo(GIZMO_TYPE_DOT); + bottom_left_gizmo = add_gizmo(GIZMO_TYPE_DOT); + bottom_center_gizmo = add_gizmo(GIZMO_TYPE_DOT); + bottom_right_gizmo = add_gizmo(GIZMO_TYPE_DOT); + left_center_gizmo = add_gizmo(GIZMO_TYPE_DOT); + right_center_gizmo = add_gizmo(GIZMO_TYPE_DOT); + // set defaults scale_y->set_enabled(false); uniform_scale_field->set_bool_value(true); @@ -145,43 +158,17 @@ void TransformEffect::process_coords(double timecode, GLTextureCoords& coords, i } void TransformEffect::gizmo_draw(double timecode, GLTextureCoords& coords) { - // proof of concept drawing pattern - - /*float color[4]; - glGetFloatv(GL_CURRENT_COLOR, color); - - glBegin(GL_TRIANGLES); - glColor4f(1.0, 0.0, 0.0, 0.5); - glVertex3f(coords.vertexTopLeftX, coords.vertexTopLeftY, 1); - glVertex3f(coords.vertexTopRightX, coords.vertexTopRightY, 1); - glVertex3f(coords.vertexBottomLeftX, coords.vertexBottomLeftY, 1); - glColor4f(0.0, 0.0, 1.0, 0.5); - glVertex3f(coords.vertexTopRightX, coords.vertexTopRightY, 1); - glVertex3f(coords.vertexBottomLeftX, coords.vertexBottomLeftY, 1); - glVertex3f(coords.vertexBottomRightX, coords.vertexBottomRightY, 1); - glEnd(); - - glColor4f(color[0], color[1], color[2], color[3]);*/ + top_left_gizmo->set_pos(coords.vertexTopLeftX, coords.vertexTopLeftY); + top_center_gizmo->set_pos(lerp(coords.vertexTopLeftX, coords.vertexTopRightX, 0.5), lerp(coords.vertexTopLeftY, coords.vertexTopRightY, 0.5)); + top_right_gizmo->set_pos(coords.vertexTopRightX, coords.vertexTopRightY); + right_center_gizmo->set_pos(lerp(coords.vertexTopRightX, coords.vertexBottomRightX, 0.5), lerp(coords.vertexTopRightY, coords.vertexBottomRightY, 0.5)); + bottom_right_gizmo->set_pos(coords.vertexBottomRightX, coords.vertexBottomRightY); + bottom_center_gizmo->set_pos(lerp(coords.vertexBottomRightX, coords.vertexBottomLeftX, 0.5), lerp(coords.vertexBottomRightY, coords.vertexBottomLeftY, 0.5)); + bottom_left_gizmo->set_pos(coords.vertexBottomLeftX, coords.vertexBottomLeftY); + left_center_gizmo->set_pos(lerp(coords.vertexBottomLeftX, coords.vertexTopLeftX, 0.5), lerp(coords.vertexBottomLeftY, coords.vertexTopLeftY, 0.5)); } -void TransformEffect::gizmo_down(QMouseEvent *event, double) { - dragging = true; - drag_start_x = event->pos().x(); - drag_start_y = event->pos().y(); -} - -void TransformEffect::gizmo_move(QMouseEvent *event, double timecode) { - if (dragging) { - position_x->set_double_value(position_x->get_double_value(timecode) + (event->pos().x() - drag_start_x)); - position_y->set_double_value(position_y->get_double_value(timecode) + (event->pos().y() - drag_start_y)); - - drag_start_x = event->pos().x(); - drag_start_y = event->pos().y(); - - field_changed(); - } -} - -void TransformEffect::gizmo_up(QMouseEvent *event, double) { - dragging = false; +void TransformEffect::gizmo_move(EffectGizmo* sender, int x_movement, int y_movement, double timecode) { + position_x->set_double_value(position_x->get_double_value(timecode) + x_movement); + position_y->set_double_value(position_y->get_double_value(timecode) + y_movement); } diff --git a/effects/internal/transformeffect.h b/effects/internal/transformeffect.h index 38834c45d..c2f936544 100644 --- a/effects/internal/transformeffect.h +++ b/effects/internal/transformeffect.h @@ -11,29 +11,32 @@ public: void process_coords(double timecode, GLTextureCoords& coords, int data); void gizmo_draw(double timecode, GLTextureCoords& coords); - void gizmo_down(QMouseEvent *event, double); - void gizmo_move(QMouseEvent *event, double); - void gizmo_up(QMouseEvent *event, double); - - EffectField* position_x; - EffectField* position_y; - EffectField* scale_x; - EffectField* scale_y; - EffectField* uniform_scale_field; - EffectField* rotation; - EffectField* anchor_x_box; - EffectField* anchor_y_box; - EffectField* opacity; - EffectField* blend_mode_box; + void gizmo_move(EffectGizmo* sender, int x_movement, int y_movement, double timecode); public slots: void toggle_uniform_scale(bool enabled); private: - int default_anchor_x; - int default_anchor_y; + EffectField* position_x; + EffectField* position_y; + EffectField* scale_x; + EffectField* scale_y; + EffectField* uniform_scale_field; + EffectField* rotation; + EffectField* anchor_x_box; + EffectField* anchor_y_box; + EffectField* opacity; + EffectField* blend_mode_box; - bool dragging; - int drag_start_x; - int drag_start_y; + EffectGizmo* top_left_gizmo; + EffectGizmo* top_center_gizmo; + EffectGizmo* top_right_gizmo; + EffectGizmo* bottom_left_gizmo; + EffectGizmo* bottom_center_gizmo; + EffectGizmo* bottom_right_gizmo; + EffectGizmo* left_center_gizmo; + EffectGizmo* right_center_gizmo; + + int default_anchor_x; + int default_anchor_y; }; #endif // TRANSFORMEFFECT_H diff --git a/olive.pro b/olive.pro index f81d7e964..368d37887 100644 --- a/olive.pro +++ b/olive.pro @@ -88,7 +88,8 @@ SOURCES += \ project/transition.cpp \ project/effectrow.cpp \ project/effectfield.cpp \ - effects/internal/cubetransition.cpp + effects/internal/cubetransition.cpp \ + project/effectgizmo.cpp HEADERS += \ mainwindow.h \ @@ -156,7 +157,8 @@ HEADERS += \ project/transition.h \ project/effectrow.h \ project/effectfield.h \ - effects/internal/cubetransition.h + effects/internal/cubetransition.h \ + project/effectgizmo.h FORMS += \ mainwindow.ui \ diff --git a/panels/project.cpp b/panels/project.cpp index 96ad97d39..3db428698 100644 --- a/panels/project.cpp +++ b/panels/project.cpp @@ -1496,6 +1496,7 @@ void Project::save_folder(QXmlStreamWriter& stream, QTreeWidgetItem* parent, int if (t != NULL) { stream.writeStartElement("transition"); stream.writeAttribute("id", QString::number(j)); + stream.writeAttribute("length", QString::number(t->get_true_length())); t->save(stream); stream.writeEndElement(); // transition } diff --git a/project/effect.cpp b/project/effect.cpp index bd524fb98..228c45bee 100644 --- a/project/effect.cpp +++ b/project/effect.cpp @@ -223,7 +223,6 @@ Effect::Effect(Clip* c, const EffectMeta *em) : enable_shader(false), enable_coords(false), enable_superimpose(false), - enable_gizmos(false), glslProgram(NULL), texture(NULL), isOpen(false), @@ -456,7 +455,21 @@ EffectRow* Effect::row(int i) { } int Effect::row_count() { - return rows.size(); + return rows.size(); +} + +EffectGizmo *Effect::add_gizmo(int type) { + EffectGizmo* gizmo = new EffectGizmo(type); + gizmos.append(gizmo); + return gizmo; +} + +EffectGizmo *Effect::gizmo(int i) { + return gizmos.at(i); +} + +int Effect::gizmo_count(){ + return gizmos.size(); } void Effect::refresh() {} @@ -834,9 +847,30 @@ void Effect::process_audio(double, double, quint8*, int, int) { } void Effect::gizmo_draw(double, GLTextureCoords &) {} -void Effect::gizmo_down(QMouseEvent *, double) {} -void Effect::gizmo_move(QMouseEvent *, double) {} -void Effect::gizmo_up(QMouseEvent *, double) {} +void Effect::gizmo_move(EffectGizmo* , int , int , double ) {} + +void Effect::gizmo_world_to_screen() { + GLfloat view_val[16]; + GLfloat projection_val[16]; + glGetFloatv(GL_MODELVIEW_MATRIX, view_val); + glGetFloatv(GL_PROJECTION_MATRIX, projection_val); + + QMatrix4x4 view_matrix(view_val[0], view_val[4], view_val[8], view_val[12], view_val[1], view_val[5], view_val[9], view_val[13], view_val[2], view_val[6], view_val[10], view_val[14], view_val[3], view_val[7], view_val[11], view_val[15]); + QMatrix4x4 projection_matrix(projection_val[0], projection_val[4], projection_val[8], projection_val[12], projection_val[1], projection_val[5], projection_val[9], projection_val[13], projection_val[2], projection_val[6], projection_val[10], projection_val[14], projection_val[3], projection_val[7], projection_val[11], projection_val[15]); + + for (int i=0;iget_x(), g->get_y(), 0, 1.0); + QVector4D screen_pos = world_pos * (view_matrix * projection_matrix); + + g->set_screen_pos(screen_pos.x(), screen_pos.y()); + } +} + +bool Effect::are_gizmos_enabled() { + return (gizmos.size() > 0); +} void Effect::redraw(double) { /* diff --git a/project/effect.h b/project/effect.h index be7979199..928da37c3 100644 --- a/project/effect.h +++ b/project/effect.h @@ -1,4 +1,4 @@ -#ifndef EFFECT_H +#ifndef EFFECT_H #define EFFECT_H #include @@ -105,6 +105,7 @@ qint16 mix_audio_sample(qint16 a, qint16 b); #include "effectfield.h" #include "effectrow.h" +#include "effectgizmo.h" class Effect : public QObject { Q_OBJECT @@ -121,6 +122,10 @@ public: EffectRow* row(int i); int row_count(); + EffectGizmo* add_gizmo(int type); + EffectGizmo* gizmo(int i); + int gizmo_count(); + bool is_enabled(); void set_enabled(bool b); @@ -140,8 +145,7 @@ public: bool enable_shader; bool enable_coords; - bool enable_superimpose; - bool enable_gizmos; + bool enable_superimpose; int getIterations(); void setIterations(int i); @@ -154,9 +158,9 @@ public: virtual void process_audio(double timecode_start, double timecode_end, quint8* samples, int nb_bytes, int channel_count); virtual void gizmo_draw(double timecode, GLTextureCoords& coords); - virtual void gizmo_down(QMouseEvent* event, double); - virtual void gizmo_move(QMouseEvent* event, double); - virtual void gizmo_up(QMouseEvent* event, double); + virtual void gizmo_move(EffectGizmo* sender, int x_movement, int y_movement, double timecode); + void gizmo_world_to_screen(); + bool are_gizmos_enabled(); public slots: void field_changed(); private slots: @@ -179,6 +183,7 @@ private: bool isOpen; QVector rows; + QVector gizmos; QGridLayout* ui_layout; QWidget* ui; bool bound; diff --git a/project/effectgizmo.cpp b/project/effectgizmo.cpp new file mode 100644 index 000000000..a6a747863 --- /dev/null +++ b/project/effectgizmo.cpp @@ -0,0 +1,35 @@ +#include "effectgizmo.h" + +EffectGizmo::EffectGizmo(int type) : + type(type) +{} + +void EffectGizmo::set_pos(int ix, int iy) { + x = ix; + y = iy; +} + +int EffectGizmo::get_x() { + return x; +} + +int EffectGizmo::get_y() { + return y; +} + +int EffectGizmo::get_type() { + return type; +} + +void EffectGizmo::set_screen_pos(int isx, int isy) { + sx = isx; + sy = isy; +} + +int EffectGizmo::get_screen_x() { + return sx; +} + +int EffectGizmo::get_screen_y() { + return sy; +} diff --git a/project/effectgizmo.h b/project/effectgizmo.h new file mode 100644 index 000000000..6a9588d95 --- /dev/null +++ b/project/effectgizmo.h @@ -0,0 +1,30 @@ +#ifndef EFFECTGIZMO_H +#define EFFECTGIZMO_H + +#define GIZMO_TYPE_DOT 0 +#define GIZMO_TYPE_QUAD 1 + +#include + +class EffectGizmo +{ +public: + EffectGizmo(int type); + + void set_pos(int ix, int iy); + int get_x(); + int get_y(); + int get_type(); + + void set_screen_pos(int isx, int isy); + int get_screen_x(); + int get_screen_y(); +private: + int type; + int x; + int y; + int sx; + int sy; +}; + +#endif // EFFECTGIZMO_H diff --git a/ui/viewerwidget.cpp b/ui/viewerwidget.cpp index 8f01b761d..e1470406e 100644 --- a/ui/viewerwidget.cpp +++ b/ui/viewerwidget.cpp @@ -135,9 +135,23 @@ double get_timecode(Clip* c, long playhead) { } void ViewerWidget::mousePressEvent(QMouseEvent* event) { - if (waveform) seek_from_click(event->x()); - dragging = true; - if (gizmos != NULL) gizmos->gizmo_down(event, get_timecode(gizmos->parent_clip, gizmos->parent_clip->sequence->playhead)); + if (waveform) { + seek_from_click(event->x()); + } else { + drag_start_x = event->pos().x(); + drag_start_y = event->pos().y(); + + if (gizmos != NULL) { + int clicked = -1; + for (int i=0;igizmo_count();i++) { + EffectGizmo* g = gizmos->gizmo(i); + + dout << "gizmo" << i << "screen pos was" << g->get_screen_x() << g->get_screen_y() << "compared to" << g->get_x() << g->get_y(); + } + dout << "clicked on" << clicked; + } + } + dragging = true; } void ViewerWidget::mouseMoveEvent(QMouseEvent* event) { @@ -150,14 +164,24 @@ void ViewerWidget::mouseMoveEvent(QMouseEvent* event) { mimeData->setText("h"); // QMimeData will fail without some kind of data drag->setMimeData(mimeData); drag->exec(); - } + } else { + double multiplier = (double) viewer->seq->width / (double) width(); + + int x_movement = (event->pos().x() - drag_start_x)*multiplier; + int y_movement = (event->pos().y() - drag_start_y)*multiplier; + +// gizmos->gizmo_move(g, x_movement, y_movement, get_timecode(gizmos->parent_clip, gizmos->parent_clip->sequence->playhead)); + + drag_start_x = event->pos().x(); + drag_start_y = event->pos().y(); + + gizmos->field_changed(); + } } - if (gizmos != NULL) gizmos->gizmo_move(event, get_timecode(gizmos->parent_clip, gizmos->parent_clip->sequence->playhead)); } void ViewerWidget::mouseReleaseEvent(QMouseEvent *event) { - dragging = false; - if (gizmos != NULL) gizmos->gizmo_up(event, get_timecode(gizmos->parent_clip, gizmos->parent_clip->sequence->playhead)); + dragging = false; } void ViewerWidget::drawTitleSafeArea() { @@ -470,7 +494,7 @@ GLuint ViewerWidget::compose_sequence(QVector& nests, bool render_audio) Effect* e = c->effects.at(j); process_effect(c, e, timecode, coords, composite_texture, fbo_switcher, TA_NO_TRANSITION); - if (!rendering && gizmos == NULL && e->enable_gizmos && (e->container->selected || panel_timeline->is_clip_selected(c, true))) { + if (!rendering && gizmos == NULL && e->are_gizmos_enabled() && (e->container->selected || panel_timeline->is_clip_selected(c, true))) { gizmos = e; draw_gizmos = true; } @@ -528,9 +552,9 @@ GLuint ViewerWidget::compose_sequence(QVector& nests, bool render_audio) float rows = coords.grid_size; float cols = coords.grid_size; - for (float i=0;i& nests, bool render_audio) glBindTexture(GL_TEXTURE_2D, 0); // unbind texture if (draw_gizmos) { - gizmos->gizmo_draw(timecode, coords); + float color[4]; + glGetFloatv(GL_CURRENT_COLOR, color); + + float multiplier = (float) width() / (float) viewer->seq->width; + float dot_size = 20 * multiplier; + + gizmos->gizmo_draw(timecode, coords); // set correct gizmo coords + gizmos->gizmo_world_to_screen(); + for (int j=0;jgizmo_count();j++) { + EffectGizmo* g = gizmos->gizmo(j); + switch (g->get_type()) { + case GIZMO_TYPE_DOT: // draw dot + glBegin(GL_QUADS); + glColor4f(1.0, 1.0, 1.0, 1.0); + glVertex2f(g->get_x()-dot_size, g->get_y()-dot_size); + glVertex2f(g->get_x()+dot_size, g->get_y()-dot_size); + glVertex2f(g->get_x()+dot_size, g->get_y()+dot_size); + glVertex2f(g->get_x()-dot_size, g->get_y()+dot_size); + glEnd(); + break; + } + } + + glColor4f(color[0], color[1], color[2], color[3]); } if (!nests.isEmpty()) { diff --git a/ui/viewerwidget.h b/ui/viewerwidget.h index 3b3cc709f..0be77f172 100644 --- a/ui/viewerwidget.h +++ b/ui/viewerwidget.h @@ -1,4 +1,4 @@ -#ifndef VIEWERWIDGET_H +#ifndef VIEWERWIDGET_H #define VIEWERWIDGET_H #include @@ -14,6 +14,7 @@ struct Clip; struct MediaStream; class QOpenGLFramebufferObject; class Effect; +class EffectGizmo; struct GLTextureCoords; class ViewerWidget : public QOpenGLWidget @@ -48,6 +49,9 @@ private: 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, int data); Effect* gizmos; + int drag_start_x; + int drag_start_y; + EffectGizmo* selected_gizmo; private slots: void retry(); void show_context_menu(); From f28427302ebc1e244509d8661dcb2a9185be38e9 Mon Sep 17 00:00:00 2001 From: itsmattkc Date: Tue, 27 Nov 2018 12:46:17 +1100 Subject: [PATCH 16/31] dot gizmos implemented --- effects/internal/cornerpineffect.cpp | 30 +++++++++- effects/internal/cornerpineffect.h | 7 +++ effects/internal/transformeffect.cpp | 46 ++++++++++++++- project/effect.cpp | 9 ++- project/effectgizmo.cpp | 11 +++- project/effectgizmo.h | 7 +++ ui/viewerwidget.cpp | 87 +++++++++++++++++++--------- ui/viewerwidget.h | 1 + 8 files changed, 165 insertions(+), 33 deletions(-) diff --git a/effects/internal/cornerpineffect.cpp b/effects/internal/cornerpineffect.cpp index 1f8650e0e..d2ff57ba9 100644 --- a/effects/internal/cornerpineffect.cpp +++ b/effects/internal/cornerpineffect.cpp @@ -27,6 +27,11 @@ CornerPinEffect::CornerPinEffect(Clip *c, const EffectMeta *em) : Effect(c, em) perspective = add_row("Perspective:")->add_field(EFFECT_FIELD_BOOL, "perspective"); perspective->set_bool_value(true); + top_left_gizmo = add_gizmo(GIZMO_TYPE_DOT); + top_right_gizmo = add_gizmo(GIZMO_TYPE_DOT); + bottom_left_gizmo = add_gizmo(GIZMO_TYPE_DOT); + bottom_right_gizmo = add_gizmo(GIZMO_TYPE_DOT); + vertPath = "cornerpin.vert"; fragPath = "cornerpin.frag"; } @@ -50,5 +55,28 @@ void CornerPinEffect::process_shader(double timecode, GLTextureCoords &coords) { glslProgram->setUniformValue("p1", (GLfloat) coords.vertexBottomRightX, (GLfloat) coords.vertexBottomRightY); glslProgram->setUniformValue("p2", (GLfloat) coords.vertexTopLeftX, (GLfloat) coords.vertexTopLeftY); glslProgram->setUniformValue("p3", (GLfloat) coords.vertexTopRightX, (GLfloat) coords.vertexTopRightY); - glslProgram->setUniformValue("perspective", perspective->get_bool_value(timecode)); + glslProgram->setUniformValue("perspective", perspective->get_bool_value(timecode)); +} + +void CornerPinEffect::gizmo_draw(double timecode, GLTextureCoords &coords) { + top_left_gizmo->set_pos(coords.vertexTopLeftX, coords.vertexTopLeftY); + top_right_gizmo->set_pos(coords.vertexTopRightX, coords.vertexTopRightY); + bottom_right_gizmo->set_pos(coords.vertexBottomRightX, coords.vertexBottomRightY); + bottom_left_gizmo->set_pos(coords.vertexBottomLeftX, coords.vertexBottomLeftY); +} + +void CornerPinEffect::gizmo_move(EffectGizmo *sender, int x_movement, int y_movement, double timecode) { + if (sender == bottom_right_gizmo) { + bottom_right_x->set_double_value(bottom_right_x->get_double_value(timecode) + x_movement); + bottom_right_y->set_double_value(bottom_right_y->get_double_value(timecode) + y_movement); + } else if (sender == top_left_gizmo) { + top_left_x->set_double_value(top_left_x->get_double_value(timecode) + x_movement); + top_left_y->set_double_value(top_left_y->get_double_value(timecode) + y_movement); + } else if (sender == bottom_left_gizmo) { + bottom_left_x->set_double_value(bottom_left_x->get_double_value(timecode) + x_movement); + bottom_left_y->set_double_value(bottom_left_y->get_double_value(timecode) + y_movement); + } else if (sender == top_right_gizmo) { + top_right_x->set_double_value(top_right_x->get_double_value(timecode) + x_movement); + top_right_y->set_double_value(top_right_y->get_double_value(timecode) + y_movement); + } } diff --git a/effects/internal/cornerpineffect.h b/effects/internal/cornerpineffect.h index 164101a58..b0d615142 100644 --- a/effects/internal/cornerpineffect.h +++ b/effects/internal/cornerpineffect.h @@ -9,6 +9,8 @@ public: CornerPinEffect(Clip* c, const EffectMeta* em); void process_coords(double timecode, GLTextureCoords& coords, int data); void process_shader(double timecode, GLTextureCoords& coords); + void gizmo_draw(double timecode, GLTextureCoords& coords); + void gizmo_move(EffectGizmo* sender, int x_movement, int y_movement, double timecode); private: EffectField* top_left_x; EffectField* top_left_y; @@ -19,6 +21,11 @@ private: EffectField* bottom_right_x; EffectField* bottom_right_y; EffectField* perspective; + + EffectGizmo* top_left_gizmo; + EffectGizmo* top_right_gizmo; + EffectGizmo* bottom_left_gizmo; + EffectGizmo* bottom_right_gizmo; }; #endif // CORNERPINEFFECT_H diff --git a/effects/internal/transformeffect.cpp b/effects/internal/transformeffect.cpp index 73d4353fd..bc793d8f0 100644 --- a/effects/internal/transformeffect.cpp +++ b/effects/internal/transformeffect.cpp @@ -74,6 +74,15 @@ TransformEffect::TransformEffect(Clip* c, const EffectMeta* em) : Effect(c, em) left_center_gizmo = add_gizmo(GIZMO_TYPE_DOT); right_center_gizmo = add_gizmo(GIZMO_TYPE_DOT); + top_left_gizmo->set_cursor(Qt::SizeFDiagCursor); + top_center_gizmo->set_cursor(Qt::SizeVerCursor); + top_right_gizmo->set_cursor(Qt::SizeBDiagCursor); + bottom_left_gizmo->set_cursor(Qt::SizeBDiagCursor); + bottom_center_gizmo->set_cursor(Qt::SizeVerCursor); + bottom_right_gizmo->set_cursor(Qt::SizeFDiagCursor); + left_center_gizmo->set_cursor(Qt::SizeHorCursor); + right_center_gizmo->set_cursor(Qt::SizeHorCursor); + // set defaults scale_y->set_enabled(false); uniform_scale_field->set_bool_value(true); @@ -169,6 +178,39 @@ void TransformEffect::gizmo_draw(double timecode, GLTextureCoords& coords) { } void TransformEffect::gizmo_move(EffectGizmo* sender, int x_movement, int y_movement, double timecode) { - position_x->set_double_value(position_x->get_double_value(timecode) + x_movement); - position_y->set_double_value(position_y->get_double_value(timecode) + y_movement); + double x_percent = ((double) x_movement / parent_clip->sequence->width)*200; + double y_percent = ((double) y_movement / parent_clip->sequence->height)*200; + + if (sender == bottom_right_gizmo) { + scale_x->set_double_value(scale_x->get_double_value(timecode) + x_percent); + if (!uniform_scale_field->get_bool_value(timecode)) scale_y->set_double_value(scale_y->get_double_value(timecode) + y_percent); + } else if (sender == top_left_gizmo) { + scale_x->set_double_value(scale_x->get_double_value(timecode) - x_percent); + if (!uniform_scale_field->get_bool_value(timecode)) scale_y->set_double_value(scale_y->get_double_value(timecode) - y_percent); + } else if (sender == bottom_left_gizmo) { + scale_x->set_double_value(scale_x->get_double_value(timecode) - x_percent); + if (!uniform_scale_field->get_bool_value(timecode)) scale_y->set_double_value(scale_y->get_double_value(timecode) + y_percent); + } else if (sender == top_right_gizmo) { + scale_x->set_double_value(scale_x->get_double_value(timecode) + x_percent); + if (!uniform_scale_field->get_bool_value(timecode)) scale_y->set_double_value(scale_y->get_double_value(timecode) - y_percent); + } else if (sender == left_center_gizmo) { + scale_x->set_double_value(scale_x->get_double_value(timecode) - x_percent); + } else if (sender == right_center_gizmo) { + scale_x->set_double_value(scale_x->get_double_value(timecode) + x_percent); + } else if (sender == top_center_gizmo) { + if (uniform_scale_field->get_bool_value(timecode)) { + scale_x->set_double_value(scale_x->get_double_value(timecode) - y_percent); + } else { + scale_y->set_double_value(scale_y->get_double_value(timecode) - y_percent); + } + } else if (sender == bottom_center_gizmo) { + if (uniform_scale_field->get_bool_value(timecode)) { + scale_x->set_double_value(scale_x->get_double_value(timecode) + y_percent); + } else { + scale_y->set_double_value(scale_y->get_double_value(timecode) + y_percent); + } + } else { + position_x->set_double_value(position_x->get_double_value(timecode) + x_movement); + position_y->set_double_value(position_y->get_double_value(timecode) + y_movement); + } } diff --git a/project/effect.cpp b/project/effect.cpp index 228c45bee..8bf538fca 100644 --- a/project/effect.cpp +++ b/project/effect.cpp @@ -855,8 +855,8 @@ void Effect::gizmo_world_to_screen() { glGetFloatv(GL_MODELVIEW_MATRIX, view_val); glGetFloatv(GL_PROJECTION_MATRIX, projection_val); - QMatrix4x4 view_matrix(view_val[0], view_val[4], view_val[8], view_val[12], view_val[1], view_val[5], view_val[9], view_val[13], view_val[2], view_val[6], view_val[10], view_val[14], view_val[3], view_val[7], view_val[11], view_val[15]); - QMatrix4x4 projection_matrix(projection_val[0], projection_val[4], projection_val[8], projection_val[12], projection_val[1], projection_val[5], projection_val[9], projection_val[13], projection_val[2], projection_val[6], projection_val[10], projection_val[14], projection_val[3], projection_val[7], projection_val[11], projection_val[15]); + QMatrix4x4 view_matrix(view_val); + QMatrix4x4 projection_matrix(projection_val); for (int i=0;iget_x(), g->get_y(), 0, 1.0); QVector4D screen_pos = world_pos * (view_matrix * projection_matrix); - g->set_screen_pos(screen_pos.x(), screen_pos.y()); + int adjusted_sx = qRound(((screen_pos.x()*0.5)+0.5)*parent_clip->sequence->width); + int adjusted_sy = qRound((1.0-((screen_pos.y()*0.5)+0.5))*parent_clip->sequence->height); + + g->set_screen_pos(adjusted_sx, adjusted_sy); } } diff --git a/project/effectgizmo.cpp b/project/effectgizmo.cpp index a6a747863..8cb3c7437 100644 --- a/project/effectgizmo.cpp +++ b/project/effectgizmo.cpp @@ -1,7 +1,8 @@ #include "effectgizmo.h" EffectGizmo::EffectGizmo(int type) : - type(type) + type(type), + cursor(-1) {} void EffectGizmo::set_pos(int ix, int iy) { @@ -33,3 +34,11 @@ int EffectGizmo::get_screen_x() { int EffectGizmo::get_screen_y() { return sy; } + +int EffectGizmo::get_cursor() { + return cursor; +} + +void EffectGizmo::set_cursor(int c) { + cursor = c; +} diff --git a/project/effectgizmo.h b/project/effectgizmo.h index 6a9588d95..6473af0f7 100644 --- a/project/effectgizmo.h +++ b/project/effectgizmo.h @@ -4,7 +4,10 @@ #define GIZMO_TYPE_DOT 0 #define GIZMO_TYPE_QUAD 1 +#define GIZMO_DOT_SIZE 2.5F + #include +#include class EffectGizmo { @@ -19,12 +22,16 @@ public: void set_screen_pos(int isx, int isy); int get_screen_x(); int get_screen_y(); + + int get_cursor(); + void set_cursor(int c); private: int type; int x; int y; int sx; int sy; + int cursor; }; #endif // EFFECTGIZMO_H diff --git a/ui/viewerwidget.cpp b/ui/viewerwidget.cpp index e1470406e..ab6f50930 100644 --- a/ui/viewerwidget.cpp +++ b/ui/viewerwidget.cpp @@ -39,8 +39,10 @@ ViewerWidget::ViewerWidget(QWidget *parent) : QOpenGLWidget(parent), default_fbo(NULL), waveform(false), - dragging(false) + dragging(false), + selected_gizmo(NULL) { + setMouseTracking(true); setFocusPolicy(Qt::ClickFocus); QSurfaceFormat format; @@ -134,6 +136,25 @@ double get_timecode(Clip* c, long playhead) { return ((double)(playhead-c->get_timeline_in_with_transition()+c->get_clip_in_with_transition())/(double)c->sequence->frame_rate); } +EffectGizmo* ViewerWidget::get_gizmo_from_mouse(int x, int y) { + if (gizmos != NULL) { + double multiplier = (double) width() / (double) viewer->seq->width; + int dot_size = qRound(GIZMO_DOT_SIZE / width() * viewer->seq->width); + for (int i=0;igizmo_count();i++) { + EffectGizmo* g = gizmos->gizmo(i); + + if (x > g->get_screen_x()*multiplier - dot_size + && y > g->get_screen_y()*multiplier - dot_size + && x < g->get_screen_x()*multiplier + dot_size + && y < g->get_screen_y()*multiplier + dot_size) { + return g; + break; + } + } + } + return NULL; +} + void ViewerWidget::mousePressEvent(QMouseEvent* event) { if (waveform) { seek_from_click(event->x()); @@ -141,15 +162,7 @@ void ViewerWidget::mousePressEvent(QMouseEvent* event) { drag_start_x = event->pos().x(); drag_start_y = event->pos().y(); - if (gizmos != NULL) { - int clicked = -1; - for (int i=0;igizmo_count();i++) { - EffectGizmo* g = gizmos->gizmo(i); - - dout << "gizmo" << i << "screen pos was" << g->get_screen_x() << g->get_screen_y() << "compared to" << g->get_x() << g->get_y(); - } - dout << "clicked on" << clicked; - } + selected_gizmo = get_gizmo_from_mouse(event->pos().x(), event->pos().y()); } dragging = true; } @@ -164,20 +177,28 @@ void ViewerWidget::mouseMoveEvent(QMouseEvent* event) { mimeData->setText("h"); // QMimeData will fail without some kind of data drag->setMimeData(mimeData); drag->exec(); - } else { + } else if (selected_gizmo != NULL) { double multiplier = (double) viewer->seq->width / (double) width(); int x_movement = (event->pos().x() - drag_start_x)*multiplier; int y_movement = (event->pos().y() - drag_start_y)*multiplier; -// gizmos->gizmo_move(g, x_movement, y_movement, get_timecode(gizmos->parent_clip, gizmos->parent_clip->sequence->playhead)); + gizmos->gizmo_move(selected_gizmo, x_movement, y_movement, get_timecode(gizmos->parent_clip, gizmos->parent_clip->sequence->playhead)); drag_start_x = event->pos().x(); drag_start_y = event->pos().y(); gizmos->field_changed(); } - } + } else { + unsetCursor(); + EffectGizmo* g = get_gizmo_from_mouse(event->pos().x(), event->pos().y()); + if (g != NULL) { + if (g->get_cursor() > -1) { + setCursor(static_cast(g->get_cursor())); + } + } + } } void ViewerWidget::mouseReleaseEvent(QMouseEvent *event) { @@ -466,9 +487,7 @@ GLuint ViewerWidget::compose_sequence(QVector& nests, bool render_audio) composite_texture = draw_clip(c->fbo[fbo_switcher], textureID, true); } - fbo_switcher = !fbo_switcher; - - bool draw_gizmos = false; + fbo_switcher = !fbo_switcher; GLTextureCoords coords; coords.grid_size = 1; @@ -490,16 +509,28 @@ GLuint ViewerWidget::compose_sequence(QVector& nests, bool render_audio) // EFFECT CODE START double timecode = get_timecode(c, playhead); + + Effect* first_gizmo_effect = NULL; + Effect* selected_effect = NULL; + for (int j=0;jeffects.size();j++) { Effect* e = c->effects.at(j); process_effect(c, e, timecode, coords, composite_texture, fbo_switcher, TA_NO_TRANSITION); - if (!rendering && gizmos == NULL && e->are_gizmos_enabled() && (e->container->selected || panel_timeline->is_clip_selected(c, true))) { - gizmos = e; - draw_gizmos = true; + if (e->are_gizmos_enabled()) { + if (first_gizmo_effect == NULL) first_gizmo_effect = e; + if (e->container->selected) selected_effect = e; } } + if (!rendering) { + if (selected_effect != NULL) { + gizmos = selected_effect; + } else if (panel_timeline->is_clip_selected(c, true)) { + gizmos = first_gizmo_effect; + } + } + if (c->get_opening_transition() != NULL) { int transition_progress = playhead - c->get_timeline_in_with_transition(); if (transition_progress < c->get_opening_transition()->get_length()) { @@ -585,29 +616,33 @@ GLuint ViewerWidget::compose_sequence(QVector& nests, bool render_audio) glBindTexture(GL_TEXTURE_2D, 0); // unbind texture - if (draw_gizmos) { + if (gizmos != NULL) { float color[4]; glGetFloatv(GL_CURRENT_COLOR, color); - float multiplier = (float) width() / (float) viewer->seq->width; - float dot_size = 20 * multiplier; + float dot_size = GIZMO_DOT_SIZE / width() * viewer->seq->width; gizmos->gizmo_draw(timecode, coords); // set correct gizmo coords gizmos->gizmo_world_to_screen(); + + glPushMatrix(); + glLoadIdentity(); + glOrtho(0, viewer->seq->width, viewer->seq->height, 0, -1, 1); for (int j=0;jgizmo_count();j++) { EffectGizmo* g = gizmos->gizmo(j); switch (g->get_type()) { case GIZMO_TYPE_DOT: // draw dot glBegin(GL_QUADS); glColor4f(1.0, 1.0, 1.0, 1.0); - glVertex2f(g->get_x()-dot_size, g->get_y()-dot_size); - glVertex2f(g->get_x()+dot_size, g->get_y()-dot_size); - glVertex2f(g->get_x()+dot_size, g->get_y()+dot_size); - glVertex2f(g->get_x()-dot_size, g->get_y()+dot_size); + glVertex2f(g->get_screen_x()-dot_size, g->get_screen_y()-dot_size); + glVertex2f(g->get_screen_x()+dot_size, g->get_screen_y()-dot_size); + glVertex2f(g->get_screen_x()+dot_size, g->get_screen_y()+dot_size); + glVertex2f(g->get_screen_x()-dot_size, g->get_screen_y()+dot_size); glEnd(); break; } } + glPopMatrix(); glColor4f(color[0], color[1], color[2], color[3]); } diff --git a/ui/viewerwidget.h b/ui/viewerwidget.h index 0be77f172..ab909e842 100644 --- a/ui/viewerwidget.h +++ b/ui/viewerwidget.h @@ -52,6 +52,7 @@ private: int drag_start_x; int drag_start_y; EffectGizmo* selected_gizmo; + EffectGizmo* get_gizmo_from_mouse(int x, int y); private slots: void retry(); void show_context_menu(); From 3069fb6f7c88c3acb9b3cc836af17829e617d3c1 Mon Sep 17 00:00:00 2001 From: itsmattkc Date: Wed, 28 Nov 2018 13:53:31 +1100 Subject: [PATCH 17/31] gizmos fairly complete --- effects/internal/cornerpineffect.cpp | 8 ++--- effects/internal/transformeffect.cpp | 32 +++++++++++++------ effects/internal/transformeffect.h | 2 ++ project/effect.cpp | 11 ++++--- project/effectgizmo.cpp | 30 +++++------------- project/effectgizmo.h | 21 ++++++------- ui/viewerwidget.cpp | 47 ++++++++++++++++++++-------- 7 files changed, 85 insertions(+), 66 deletions(-) diff --git a/effects/internal/cornerpineffect.cpp b/effects/internal/cornerpineffect.cpp index d2ff57ba9..0b696718f 100644 --- a/effects/internal/cornerpineffect.cpp +++ b/effects/internal/cornerpineffect.cpp @@ -59,10 +59,10 @@ void CornerPinEffect::process_shader(double timecode, GLTextureCoords &coords) { } void CornerPinEffect::gizmo_draw(double timecode, GLTextureCoords &coords) { - top_left_gizmo->set_pos(coords.vertexTopLeftX, coords.vertexTopLeftY); - top_right_gizmo->set_pos(coords.vertexTopRightX, coords.vertexTopRightY); - bottom_right_gizmo->set_pos(coords.vertexBottomRightX, coords.vertexBottomRightY); - bottom_left_gizmo->set_pos(coords.vertexBottomLeftX, coords.vertexBottomLeftY); + top_left_gizmo->world_pos[0] = QPoint(coords.vertexTopLeftX, coords.vertexTopLeftY); + top_right_gizmo->world_pos[0] = QPoint(coords.vertexTopRightX, coords.vertexTopRightY); + bottom_right_gizmo->world_pos[0] = QPoint(coords.vertexBottomRightX, coords.vertexBottomRightY); + bottom_left_gizmo->world_pos[0] = QPoint(coords.vertexBottomLeftX, coords.vertexBottomLeftY); } void CornerPinEffect::gizmo_move(EffectGizmo *sender, int x_movement, int y_movement, double timecode) { diff --git a/effects/internal/transformeffect.cpp b/effects/internal/transformeffect.cpp index bc793d8f0..cfa7260ef 100644 --- a/effects/internal/transformeffect.cpp +++ b/effects/internal/transformeffect.cpp @@ -72,7 +72,9 @@ TransformEffect::TransformEffect(Clip* c, const EffectMeta* em) : Effect(c, em) bottom_center_gizmo = add_gizmo(GIZMO_TYPE_DOT); bottom_right_gizmo = add_gizmo(GIZMO_TYPE_DOT); left_center_gizmo = add_gizmo(GIZMO_TYPE_DOT); - right_center_gizmo = add_gizmo(GIZMO_TYPE_DOT); + right_center_gizmo = add_gizmo(GIZMO_TYPE_DOT); + rotate_gizmo = add_gizmo(GIZMO_TYPE_DOT); + rect_gizmo = add_gizmo(GIZMO_TYPE_POLY); top_left_gizmo->set_cursor(Qt::SizeFDiagCursor); top_center_gizmo->set_cursor(Qt::SizeVerCursor); @@ -82,6 +84,8 @@ TransformEffect::TransformEffect(Clip* c, const EffectMeta* em) : Effect(c, em) bottom_right_gizmo->set_cursor(Qt::SizeFDiagCursor); left_center_gizmo->set_cursor(Qt::SizeHorCursor); right_center_gizmo->set_cursor(Qt::SizeHorCursor); + rotate_gizmo->color = Qt::green; + rotate_gizmo->set_cursor(Qt::SizeAllCursor); // set defaults scale_y->set_enabled(false); @@ -167,14 +171,21 @@ void TransformEffect::process_coords(double timecode, GLTextureCoords& coords, i } void TransformEffect::gizmo_draw(double timecode, GLTextureCoords& coords) { - top_left_gizmo->set_pos(coords.vertexTopLeftX, coords.vertexTopLeftY); - top_center_gizmo->set_pos(lerp(coords.vertexTopLeftX, coords.vertexTopRightX, 0.5), lerp(coords.vertexTopLeftY, coords.vertexTopRightY, 0.5)); - top_right_gizmo->set_pos(coords.vertexTopRightX, coords.vertexTopRightY); - right_center_gizmo->set_pos(lerp(coords.vertexTopRightX, coords.vertexBottomRightX, 0.5), lerp(coords.vertexTopRightY, coords.vertexBottomRightY, 0.5)); - bottom_right_gizmo->set_pos(coords.vertexBottomRightX, coords.vertexBottomRightY); - bottom_center_gizmo->set_pos(lerp(coords.vertexBottomRightX, coords.vertexBottomLeftX, 0.5), lerp(coords.vertexBottomRightY, coords.vertexBottomLeftY, 0.5)); - bottom_left_gizmo->set_pos(coords.vertexBottomLeftX, coords.vertexBottomLeftY); - left_center_gizmo->set_pos(lerp(coords.vertexBottomLeftX, coords.vertexTopLeftX, 0.5), lerp(coords.vertexBottomLeftY, coords.vertexTopLeftY, 0.5)); + top_left_gizmo->world_pos[0] = QPoint(coords.vertexTopLeftX, coords.vertexTopLeftY); + top_center_gizmo->world_pos[0] = QPoint(lerp(coords.vertexTopLeftX, coords.vertexTopRightX, 0.5), lerp(coords.vertexTopLeftY, coords.vertexTopRightY, 0.5)); + top_right_gizmo->world_pos[0] = QPoint(coords.vertexTopRightX, coords.vertexTopRightY); + right_center_gizmo->world_pos[0] = QPoint(lerp(coords.vertexTopRightX, coords.vertexBottomRightX, 0.5), lerp(coords.vertexTopRightY, coords.vertexBottomRightY, 0.5)); + bottom_right_gizmo->world_pos[0] = QPoint(coords.vertexBottomRightX, coords.vertexBottomRightY); + bottom_center_gizmo->world_pos[0] = QPoint(lerp(coords.vertexBottomRightX, coords.vertexBottomLeftX, 0.5), lerp(coords.vertexBottomRightY, coords.vertexBottomLeftY, 0.5)); + bottom_left_gizmo->world_pos[0] = QPoint(coords.vertexBottomLeftX, coords.vertexBottomLeftY); + left_center_gizmo->world_pos[0] = QPoint(lerp(coords.vertexBottomLeftX, coords.vertexTopLeftX, 0.5), lerp(coords.vertexBottomLeftY, coords.vertexTopLeftY, 0.5)); + + rotate_gizmo->world_pos[0] = QPoint(lerp(top_center_gizmo->world_pos[0].x(), bottom_center_gizmo->world_pos[0].x(), -0.1), lerp(top_center_gizmo->world_pos[0].y(), bottom_center_gizmo->world_pos[0].y(), -0.1)); + + rect_gizmo->world_pos[0] = QPoint(coords.vertexTopLeftX, coords.vertexTopLeftY); + rect_gizmo->world_pos[1] = QPoint(coords.vertexTopRightX, coords.vertexTopRightY); + rect_gizmo->world_pos[2] = QPoint(coords.vertexBottomRightX, coords.vertexBottomRightY); + rect_gizmo->world_pos[3] = QPoint(coords.vertexBottomLeftX, coords.vertexBottomLeftY); } void TransformEffect::gizmo_move(EffectGizmo* sender, int x_movement, int y_movement, double timecode) { @@ -209,6 +220,9 @@ void TransformEffect::gizmo_move(EffectGizmo* sender, int x_movement, int y_move } else { scale_y->set_double_value(scale_y->get_double_value(timecode) + y_percent); } + } else if (sender == rotate_gizmo) { + // TODO make this perfectly circular + rotation->set_double_value(rotation->get_double_value(timecode) + x_percent); } else { position_x->set_double_value(position_x->get_double_value(timecode) + x_movement); position_y->set_double_value(position_y->get_double_value(timecode) + y_movement); diff --git a/effects/internal/transformeffect.h b/effects/internal/transformeffect.h index c2f936544..41bb45dd3 100644 --- a/effects/internal/transformeffect.h +++ b/effects/internal/transformeffect.h @@ -34,6 +34,8 @@ private: EffectGizmo* bottom_right_gizmo; EffectGizmo* left_center_gizmo; EffectGizmo* right_center_gizmo; + EffectGizmo* rotate_gizmo; + EffectGizmo* rect_gizmo; int default_anchor_x; int default_anchor_y; diff --git a/project/effect.cpp b/project/effect.cpp index 8bf538fca..3be8ec413 100644 --- a/project/effect.cpp +++ b/project/effect.cpp @@ -861,13 +861,14 @@ void Effect::gizmo_world_to_screen() { for (int i=0;iget_x(), g->get_y(), 0, 1.0); - QVector4D screen_pos = world_pos * (view_matrix * projection_matrix); + for (int j=0;jget_point_count();j++) { + QVector4D screen_pos = QVector4D(g->world_pos[j].x(), g->world_pos[j].y(), 0, 1.0) * (view_matrix * projection_matrix); - int adjusted_sx = qRound(((screen_pos.x()*0.5)+0.5)*parent_clip->sequence->width); - int adjusted_sy = qRound((1.0-((screen_pos.y()*0.5)+0.5))*parent_clip->sequence->height); + int adjusted_sx1 = qRound(((screen_pos.x()*0.5f)+0.5f)*parent_clip->sequence->width); + int adjusted_sy1 = qRound((1.0f-((screen_pos.y()*0.5f)+0.5f))*parent_clip->sequence->height); - g->set_screen_pos(adjusted_sx, adjusted_sy); + g->screen_pos[j] = QPoint(adjusted_sx1, adjusted_sy1); + } } } diff --git a/project/effectgizmo.cpp b/project/effectgizmo.cpp index 8cb3c7437..301bb555a 100644 --- a/project/effectgizmo.cpp +++ b/project/effectgizmo.cpp @@ -3,38 +3,22 @@ EffectGizmo::EffectGizmo(int type) : type(type), cursor(-1) -{} +{ + int point_count = (type == GIZMO_TYPE_POLY) ? 4 : 1; + world_pos.resize(point_count); + screen_pos.resize(point_count); -void EffectGizmo::set_pos(int ix, int iy) { - x = ix; - y = iy; + color = Qt::white; } -int EffectGizmo::get_x() { - return x; -} - -int EffectGizmo::get_y() { - return y; +int EffectGizmo::get_point_count() { + return world_pos.size(); } int EffectGizmo::get_type() { return type; } -void EffectGizmo::set_screen_pos(int isx, int isy) { - sx = isx; - sy = isy; -} - -int EffectGizmo::get_screen_x() { - return sx; -} - -int EffectGizmo::get_screen_y() { - return sy; -} - int EffectGizmo::get_cursor() { return cursor; } diff --git a/project/effectgizmo.h b/project/effectgizmo.h index 6473af0f7..fc7eb05f3 100644 --- a/project/effectgizmo.h +++ b/project/effectgizmo.h @@ -2,35 +2,32 @@ #define EFFECTGIZMO_H #define GIZMO_TYPE_DOT 0 -#define GIZMO_TYPE_QUAD 1 +#define GIZMO_TYPE_POLY 1 #define GIZMO_DOT_SIZE 2.5F #include #include +#include +#include +#include class EffectGizmo { public: EffectGizmo(int type); - void set_pos(int ix, int iy); - int get_x(); - int get_y(); - int get_type(); + QVector world_pos; + QVector screen_pos; + QColor color; + int get_point_count(); - void set_screen_pos(int isx, int isy); - int get_screen_x(); - int get_screen_y(); + int get_type(); int get_cursor(); void set_cursor(int c); private: int type; - int x; - int y; - int sx; - int sy; int cursor; }; diff --git a/ui/viewerwidget.cpp b/ui/viewerwidget.cpp index ab6f50930..e32ebcef8 100644 --- a/ui/viewerwidget.cpp +++ b/ui/viewerwidget.cpp @@ -30,6 +30,7 @@ #include #include #include +#include extern "C" { #include @@ -137,19 +138,29 @@ double get_timecode(Clip* c, long playhead) { } EffectGizmo* ViewerWidget::get_gizmo_from_mouse(int x, int y) { - if (gizmos != NULL) { - double multiplier = (double) width() / (double) viewer->seq->width; - int dot_size = qRound(GIZMO_DOT_SIZE / width() * viewer->seq->width); + if (gizmos != NULL) { + double multiplier = (double) viewer->seq->width / (double) width(); + QPoint mouse_pos(qRound(x*multiplier), qRound(y*multiplier)); + int dot_size = 2 * qRound(GIZMO_DOT_SIZE * multiplier); for (int i=0;igizmo_count();i++) { EffectGizmo* g = gizmos->gizmo(i); - if (x > g->get_screen_x()*multiplier - dot_size - && y > g->get_screen_y()*multiplier - dot_size - && x < g->get_screen_x()*multiplier + dot_size - && y < g->get_screen_y()*multiplier + dot_size) { - return g; + switch (g->get_type()) { + case GIZMO_TYPE_DOT: + if (mouse_pos.x() > g->screen_pos[0].x() - dot_size + && mouse_pos.y() > g->screen_pos[0].y() - dot_size + && mouse_pos.x() < g->screen_pos[0].x() + dot_size + && mouse_pos.y() < g->screen_pos[0].y() + dot_size) { + return g; + } + break; + case GIZMO_TYPE_POLY: + if (QPolygon(g->screen_pos).containsPoint(mouse_pos, Qt::OddEvenFill)) { + return g; + } break; } + } } return NULL; @@ -630,14 +641,24 @@ GLuint ViewerWidget::compose_sequence(QVector& nests, bool render_audio) glOrtho(0, viewer->seq->width, viewer->seq->height, 0, -1, 1); for (int j=0;jgizmo_count();j++) { EffectGizmo* g = gizmos->gizmo(j); + glColor4f(g->color.redF(), g->color.greenF(), g->color.blueF(), 1.0); switch (g->get_type()) { case GIZMO_TYPE_DOT: // draw dot glBegin(GL_QUADS); - glColor4f(1.0, 1.0, 1.0, 1.0); - glVertex2f(g->get_screen_x()-dot_size, g->get_screen_y()-dot_size); - glVertex2f(g->get_screen_x()+dot_size, g->get_screen_y()-dot_size); - glVertex2f(g->get_screen_x()+dot_size, g->get_screen_y()+dot_size); - glVertex2f(g->get_screen_x()-dot_size, g->get_screen_y()+dot_size); + glVertex2f(g->screen_pos[0].x()-dot_size, g->screen_pos[0].y()-dot_size); + glVertex2f(g->screen_pos[0].x()+dot_size, g->screen_pos[0].y()-dot_size); + glVertex2f(g->screen_pos[0].x()+dot_size, g->screen_pos[0].y()+dot_size); + glVertex2f(g->screen_pos[0].x()-dot_size, g->screen_pos[0].y()+dot_size); + glEnd(); + break; + case GIZMO_TYPE_POLY: // draw lines + glBegin(GL_LINES); + for (int k=1;kget_point_count();k++) { + glVertex2f(g->screen_pos[k-1].x(), g->screen_pos[k-1].y()); + glVertex2f(g->screen_pos[k].x(), g->screen_pos[k].y()); + } + glVertex2f(g->screen_pos[g->get_point_count()-1].x(), g->screen_pos[g->get_point_count()-1].y()); + glVertex2f(g->screen_pos[0].x(), g->screen_pos[0].y()); glEnd(); break; } From 431525703d1023ce1efc1723102a0bf023a76313 Mon Sep 17 00:00:00 2001 From: itsmattkc Date: Thu, 29 Nov 2018 12:07:28 +1100 Subject: [PATCH 18/31] returned to QImage because QPixmaps seemed to cause crashes --- io/media.h | 2 +- io/previewgenerator.cpp | 7 +++---- ui/timelinewidget.cpp | 2 +- 3 files changed, 5 insertions(+), 6 deletions(-) diff --git a/io/media.h b/io/media.h index 32db5f11f..c746bc217 100644 --- a/io/media.h +++ b/io/media.h @@ -37,7 +37,7 @@ struct MediaStream { // preview thumbnail/waveform bool preview_done; - QPixmap video_preview; + QImage video_preview; QVector audio_preview; }; diff --git a/io/previewgenerator.cpp b/io/previewgenerator.cpp index 39deb2d08..c0838ac10 100644 --- a/io/previewgenerator.cpp +++ b/io/previewgenerator.cpp @@ -124,10 +124,9 @@ bool PreviewGenerator::retrieve_preview(const QString& hash) { MediaStream* ms = media->video_tracks.at(i); QString thumb_path = get_thumbnail_path(hash, ms); QFile f(thumb_path); - if (f.exists()) { + if (f.exists() && ms->video_preview.load(thumb_path)) { //dout << "loaded thumb" << ms->file_index << "from" << thumb_path; - ms->video_preview.load(thumb_path); - ms->preview_done = true; + ms->preview_done = true; } else { found = false; break; @@ -270,7 +269,7 @@ void PreviewGenerator::generate_waveform() { linesize[0] = dstW*3; sws_scale(sws_ctx, temp_frame->data, temp_frame->linesize, 0, temp_frame->height, &data, linesize); - s->video_preview.convertFromImage(QImage(data, dstW, dstH, linesize[0], QImage::Format_RGB888)); + s->video_preview = QImage(data, dstW, dstH, linesize[0], QImage::Format_RGB888); // is video interlaced? s->video_auto_interlacing = (temp_frame->interlaced_frame) ? ((temp_frame->top_field_first) ? VIDEO_TOP_FIELD_FIRST : VIDEO_BOTTOM_FIELD_FIRST) : VIDEO_PROGRESSIVE; diff --git a/ui/timelinewidget.cpp b/ui/timelinewidget.cpp index 043173b27..86a202991 100644 --- a/ui/timelinewidget.cpp +++ b/ui/timelinewidget.cpp @@ -2288,7 +2288,7 @@ void TimelineWidget::paintEvent(QPaintEvent*) { && thumb_y + thumb_height >= 0 && space_for_thumb > MAX_TEXT_WIDTH) { int thumb_clip_width = qMin(thumb_width, space_for_thumb); - p.drawPixmap(QRect(thumb_x, clip_rect.y()+thumb_y, thumb_clip_width, thumb_height), ms->video_preview, QRect(0, 0, thumb_clip_width*((double)ms->video_preview.width()/(double)thumb_width), ms->video_preview.height())); + p.drawImage(QRect(thumb_x, clip_rect.y()+thumb_y, thumb_clip_width, thumb_height), ms->video_preview, QRect(0, 0, thumb_clip_width*((double)ms->video_preview.width()/(double)thumb_width), ms->video_preview.height())); } } } else if (clip_rect.height() > TRACK_MIN_HEIGHT) { From fc65b3c83173511e92239227c2d44e0d03d9ab6e Mon Sep 17 00:00:00 2001 From: itsmattkc Date: Thu, 29 Nov 2018 12:44:50 +1100 Subject: [PATCH 19/31] fixed issue zooming into timeline while playing --- panels/timeline.cpp | 12 +++++++++--- panels/timeline.h | 1 + 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/panels/timeline.cpp b/panels/timeline.cpp index 71ae30183..e269dd095 100644 --- a/panels/timeline.cpp +++ b/panels/timeline.cpp @@ -45,6 +45,7 @@ Timeline::Timeline(QWidget *parent) : cursor_frame(0), cursor_track(0), zoom(1.0), + zoom_just_changed(false), showing_all(false), snapping(true), snapped(false), @@ -430,7 +431,8 @@ void Timeline::repaint_timeline() { if (sequence != NULL && !ui->horizontalScrollBar->isSliderDown() - && panel_sequence_viewer->playing) { + && panel_sequence_viewer->playing + && !zoom_just_changed) { // auto scroll if (config.autoscroll == AUTOSCROLL_PAGE_SCROLL) { int playhead_x = panel_timeline->getTimelineScreenPointFromFrame(sequence->playhead); @@ -445,6 +447,8 @@ void Timeline::repaint_timeline() { } } + zoom_just_changed = false; + if (draw) { ui->headers->update(); ui->video_area->update(); @@ -568,8 +572,10 @@ void Timeline::delete_selection(QVector& selections, bool ripple_dele void Timeline::set_zoom_value(double v) { zoom = v; - ui->headers->update_zoom(zoom); - repaint_timeline(); + zoom_just_changed = true; + ui->headers->update_zoom(zoom); + + repaint_timeline(); // TODO find a way to gradually move towards target_scroll instead of just centering it? center_scroll_to_playhead(); diff --git a/panels/timeline.h b/panels/timeline.h index a218ae2cd..eb14d5631 100644 --- a/panels/timeline.h +++ b/panels/timeline.h @@ -120,6 +120,7 @@ public: long cursor_frame; int cursor_track; double zoom; + bool zoom_just_changed; long drag_frame_start; int drag_track_start; void update_effect_controls(); From fb1851884dc35d4cc19d4b876ee608e621ddcb3a Mon Sep 17 00:00:00 2001 From: itsmattkc Date: Thu, 29 Nov 2018 14:08:44 +1100 Subject: [PATCH 20/31] fixed copying clips between sequences with different frame rates --- io/clipboard.cpp | 4 ++++ io/clipboard.h | 12 ++++++++++++ olive.pro | 6 ++++-- panels/project.cpp | 21 ++++++++++++--------- panels/timeline.cpp | 36 ++++++++++++++++++++++++------------ panels/timeline.h | 3 --- project/clip.h | 1 + project/undo.cpp | 7 ++++--- 8 files changed, 61 insertions(+), 29 deletions(-) create mode 100644 io/clipboard.cpp create mode 100644 io/clipboard.h diff --git a/io/clipboard.cpp b/io/clipboard.cpp new file mode 100644 index 000000000..c674841a2 --- /dev/null +++ b/io/clipboard.cpp @@ -0,0 +1,4 @@ +#include "clipboard.h" + +int clipboard_type = CLIPBOARD_TYPE_CLIP; +QVector clipboard; diff --git a/io/clipboard.h b/io/clipboard.h new file mode 100644 index 000000000..e96344a62 --- /dev/null +++ b/io/clipboard.h @@ -0,0 +1,12 @@ +#ifndef CLIPBOARD_H +#define CLIPBOARD_H + +#include + +#define CLIPBOARD_TYPE_CLIP 0 +#define CLIPBOARD_TYPE_EFFECT 1 + +extern int clipboard_type; +extern QVector clipboard; + +#endif // CLIPBOARD_H diff --git a/olive.pro b/olive.pro index 368d37887..547c460f2 100644 --- a/olive.pro +++ b/olive.pro @@ -89,7 +89,8 @@ SOURCES += \ project/effectrow.cpp \ project/effectfield.cpp \ effects/internal/cubetransition.cpp \ - project/effectgizmo.cpp + project/effectgizmo.cpp \ + io/clipboard.cpp HEADERS += \ mainwindow.h \ @@ -158,7 +159,8 @@ HEADERS += \ project/effectrow.h \ project/effectfield.h \ effects/internal/cubetransition.h \ - project/effectgizmo.h + project/effectgizmo.h \ + io/clipboard.h FORMS += \ mainwindow.ui \ diff --git a/panels/project.cpp b/panels/project.cpp index 3db428698..593d52a4b 100644 --- a/panels/project.cpp +++ b/panels/project.cpp @@ -21,6 +21,7 @@ #include "dialogs/newsequencedialog.h" #include "dialogs/mediapropertiesdialog.h" #include "dialogs/loaddialog.h" +#include "io/clipboard.h" #include "debug.h" #include @@ -317,15 +318,17 @@ void Project::get_all_media_from_table(QList items, QListclip_clipboard.size();i++) { - Clip* c = panel_timeline->clip_clipboard.at(i); - if (c->media == m) { - ca->append(new RemoveClipsFromClipboard(i-delete_count)); - delete_count++; - } - } - return (delete_count > 0); + int delete_count = 0; + if (clipboard_type == CLIPBOARD_TYPE_CLIP) { + for (int i=0;i(clipboard.at(i)); + if (c->media == m) { + ca->append(new RemoveClipsFromClipboard(i-delete_count)); + delete_count++; + } + } + } + return (delete_count > 0); } void Project::delete_selected_media() { diff --git a/panels/timeline.cpp b/panels/timeline.cpp index e269dd095..6459bcb40 100644 --- a/panels/timeline.cpp +++ b/panels/timeline.cpp @@ -18,6 +18,7 @@ #include "project/effect.h" #include "project/transition.h" #include "io/media.h" +#include "io/clipboard.h" #include "debug.h" #include @@ -838,13 +839,17 @@ void Timeline::copy(bool del) { for (int j=0;jselections.size();j++) { const Selection& s = sequence->selections.at(j); if (s.track == c->track && !((c->timeline_in <= s.in && c->timeline_out <= s.in) || (c->timeline_in >= s.out && c->timeline_out >= s.out))) { + clipboard_type = CLIPBOARD_TYPE_CLIP; + if (!cleared) { - clip_clipboard.clear(); + clipboard.clear(); cleared = true; } Clip* copied_clip = c->copy(NULL); + copied_clip->cached_fr = sequence->frame_rate; + // copy linked IDs (we correct these later in paste()) copied_clip->linked = c->linked; @@ -866,16 +871,16 @@ void Timeline::copy(bool del) { copied_clip->load_id = i; - clip_clipboard.append(copied_clip); + clipboard.append(copied_clip); } } } } - for (int i=0;itimeline_in -= min_in; - clip_clipboard[i]->timeline_out -= min_in; + static_cast(clipboard.at(i))->timeline_in -= min_in; + static_cast(clipboard.at(i))->timeline_out -= min_in; } if (del && copied) { @@ -899,7 +904,7 @@ void Timeline::relink_clips_using_ids(QVector& old_clips, QVector& n } void Timeline::paste(bool insert) { - if (clip_clipboard.size() > 0) { + if (clipboard_type == CLIPBOARD_TYPE_CLIP && clipboard.size() > 0) { ComboAction* ca = new ComboAction(); // create copies and delete areas that we'll be pasting to @@ -907,11 +912,17 @@ void Timeline::paste(bool insert) { QVector pasted_clips; long paste_start = LONG_MAX; long paste_end = LONG_MIN; - for (int i=0;i(clipboard.at(i)); // create copy of clip and offset by playhead Clip* cc = c->copy(sequence); + + // convert frame rates + cc->timeline_in = refactor_frame_number(cc->timeline_in, c->cached_fr, sequence->frame_rate); + cc->timeline_out = refactor_frame_number(cc->timeline_out, c->cached_fr, sequence->frame_rate); + cc->clip_in = refactor_frame_number(cc->clip_in, c->cached_fr, sequence->frame_rate); + cc->timeline_in += sequence->playhead; cc->timeline_out += sequence->playhead; cc->track = c->track; @@ -938,13 +949,14 @@ void Timeline::paste(bool insert) { } // correct linked clips - for (int i=0;i(clipboard.at(i)); for (int j=0;jlinked.size();j++) { - for (int k=0;kload_id == oc->linked.at(j)) { + for (int k=0;k(clipboard.at(k)); + if (comp->load_id == oc->linked.at(j)) { pasted_clips.at(i)->linked.append(k); } } diff --git a/panels/timeline.h b/panels/timeline.h index eb14d5631..db73a87da 100644 --- a/panels/timeline.h +++ b/panels/timeline.h @@ -185,9 +185,6 @@ public: const EffectMeta* transition_tool_meta; int transition_tool_side; - // clipboard - QVector clip_clipboard; - Ui::Timeline *ui; public slots: void repaint_timeline(); diff --git a/project/clip.h b/project/clip.h index 1c96e217d..ea0fc6e85 100644 --- a/project/clip.h +++ b/project/clip.h @@ -67,6 +67,7 @@ struct Clip int media_type; int media_stream; double speed; + double cached_fr; bool reverse; bool maintain_audio_pitch; bool autoscale; diff --git a/project/undo.cpp b/project/undo.cpp index 48dd2989f..71b474b7f 100644 --- a/project/undo.cpp +++ b/project/undo.cpp @@ -21,6 +21,7 @@ #include "ui/viewerwidget.h" #include "project/marker.h" #include "mainwindow.h" +#include "io/clipboard.h" #include "debug.h" QUndoStack undo_stack; @@ -1254,13 +1255,13 @@ RemoveClipsFromClipboard::~RemoveClipsFromClipboard() { } void RemoveClipsFromClipboard::undo() { - panel_timeline->clip_clipboard.insert(pos, clip); + clipboard.insert(pos, clip); done = false; } void RemoveClipsFromClipboard::redo() { - clip = panel_timeline->clip_clipboard.at(pos); - panel_timeline->clip_clipboard.removeAt(pos); + clip = static_cast(clipboard.at(pos)); + clipboard.removeAt(pos); done = true; } From 6526ece3b0d75fef13abe2ff50c2c555be81721b Mon Sep 17 00:00:00 2001 From: itsmattkc Date: Thu, 29 Nov 2018 17:32:22 +1100 Subject: [PATCH 21/31] implemented effect copying/pasting --- effects/internal/transformeffect.cpp | 2 +- io/clipboard.cpp | 13 +++ io/clipboard.h | 1 + mainwindow.cpp | 22 +++-- panels/effectcontrols.cpp | 79 +++++++++++----- panels/effectcontrols.h | 7 +- panels/project.cpp | 7 +- panels/timeline.cpp | 132 +++++++++++++++------------ project/effect.cpp | 50 +++++----- project/effect.h | 4 +- 10 files changed, 193 insertions(+), 124 deletions(-) diff --git a/effects/internal/transformeffect.cpp b/effects/internal/transformeffect.cpp index cfa7260ef..41e249a5e 100644 --- a/effects/internal/transformeffect.cpp +++ b/effects/internal/transformeffect.cpp @@ -97,7 +97,7 @@ TransformEffect::TransformEffect(Clip* c, const EffectMeta* em) : Effect(c, em) } void TransformEffect::refresh() { - if (parent_clip->sequence != NULL) { + if (parent_clip != NULL && parent_clip->sequence != NULL) { double default_pos_x = parent_clip->sequence->width/2; double default_pos_y = parent_clip->sequence->height/2; diff --git a/io/clipboard.cpp b/io/clipboard.cpp index c674841a2..bca0912df 100644 --- a/io/clipboard.cpp +++ b/io/clipboard.cpp @@ -1,4 +1,17 @@ #include "clipboard.h" +#include "project/clip.h" + int clipboard_type = CLIPBOARD_TYPE_CLIP; QVector clipboard; + +void clear_clipboard() { + for (int i=0;i(clipboard.at(i)); + } else if (clipboard_type == CLIPBOARD_TYPE_EFFECT) { + delete static_cast(clipboard.at(i)); + } + } + clipboard.clear(); +} diff --git a/io/clipboard.h b/io/clipboard.h index e96344a62..d76b7fa59 100644 --- a/io/clipboard.h +++ b/io/clipboard.h @@ -8,5 +8,6 @@ extern int clipboard_type; extern QVector clipboard; +void clear_clipboard(); #endif // CLIPBOARD_H diff --git a/mainwindow.cpp b/mainwindow.cpp index 612c4996c..c04e467be 100644 --- a/mainwindow.cpp +++ b/mainwindow.cpp @@ -385,19 +385,27 @@ void MainWindow::openSpeedDialog() { } void MainWindow::cut() { - if (panel_timeline->focused() && sequence != NULL) { - panel_timeline->copy(true); - } + if (sequence != NULL) { + if (panel_timeline->focused()) { + panel_timeline->copy(true); + } else if (panel_effect_controls->is_focused()) { + panel_effect_controls->copy(true); + } + } } void MainWindow::copy() { - if (panel_timeline->focused() && sequence != NULL) { - panel_timeline->copy(false); - } + if (sequence != NULL) { + if (panel_timeline->focused()) { + panel_timeline->copy(false); + } else if (panel_effect_controls->is_focused()) { + panel_effect_controls->copy(false); + } + } } void MainWindow::paste() { - if (panel_timeline->focused() && sequence != NULL) { + if ((panel_timeline->focused() || panel_effect_controls->is_focused()) && sequence != NULL) { panel_timeline->paste(false); } } diff --git a/panels/effectcontrols.cpp b/panels/effectcontrols.cpp index b4b0cdeee..18e0baffc 100644 --- a/panels/effectcontrols.cpp +++ b/panels/effectcontrols.cpp @@ -17,6 +17,7 @@ #include "panels/timeline.h" #include "panels/viewer.h" #include "ui/viewerwidget.h" +#include "io/clipboard.h" #include "debug.h" EffectControls::EffectControls(QWidget *parent) : @@ -65,9 +66,9 @@ void EffectControls::menu_select(QAction* q) { ComboAction* ca = new ComboAction(); for (int i=0;iclips.at(selected_clips.at(i)); - if ((c->track < 0) == video_menu) { + if ((c->track < 0) == (effect_menu_subtype == EFFECT_TYPE_VIDEO)) { const EffectMeta* meta = reinterpret_cast(q->data().value()); - if (transition_menu) { + if (effect_menu_type == EFFECT_TYPE_TRANSITION) { if (c->get_opening_transition() == NULL) { ca->append(new AddTransitionCommand(c, NULL, NULL, meta, TA_OPENING_TRANSITION, 30)); } @@ -80,7 +81,7 @@ void EffectControls::menu_select(QAction* q) { } } undo_stack.push(ca); - if (transition_menu) { + if (effect_menu_type == EFFECT_TYPE_TRANSITION) { update_ui(true); } else { reload_clips(); @@ -94,21 +95,57 @@ void EffectControls::update_keyframes() { } void EffectControls::delete_selected_keyframes() { - ui->keyframeView->delete_selected_keyframes(); + ui->keyframeView->delete_selected_keyframes(); } -void EffectControls::show_effect_menu(bool video, bool transitions) { - video_menu = video; - transition_menu = transitions; +void EffectControls::copy(bool del) { + if (mode == TA_NO_TRANSITION) { + bool cleared = false; + + ComboAction* ca = new ComboAction(); + EffectDeleteCommand* del_com = (del) ? new EffectDeleteCommand() : NULL; + for (int i=0;iclips.at(selected_clips.at(i)); + for (int j=0;jeffects.size();j++) { + Effect* effect = c->effects.at(j); + if (effect->container->selected) { + if (!cleared) { + clipboard_type = CLIPBOARD_TYPE_EFFECT; + clear_clipboard(); + cleared = true; + } + + clipboard.append(effect->copy(NULL)); + + if (del_com != NULL) { + del_com->clips.append(c); + del_com->fx.append(j); + } + } + } + } + if (del_com != NULL) { + if (del_com->clips.size() > 0) { + ca->append(del_com); + } else { + delete del_com; + } + } + undo_stack.push(ca); + } +} + +void EffectControls::show_effect_menu(int type, int subtype) { + effect_menu_type = type; + effect_menu_subtype = subtype; effects_loaded.lock(); - QVector& effect_list = (video) ? video_effects : audio_effects; QMenu effects_menu(this); - for (int i=0;isetText(em.name); action->setData(reinterpret_cast(&em)); @@ -275,24 +312,20 @@ void EffectControls::set_clips(QVector& clips, int m) { load_effects(); } -void EffectControls::on_add_video_effect_button_clicked() -{ - show_effect_menu(true, false); +void EffectControls::on_add_video_effect_button_clicked() { + show_effect_menu(EFFECT_TYPE_EFFECT, EFFECT_TYPE_VIDEO); } -void EffectControls::on_add_audio_effect_button_clicked() -{ - show_effect_menu(false, false); +void EffectControls::on_add_audio_effect_button_clicked() { + show_effect_menu(EFFECT_TYPE_EFFECT, EFFECT_TYPE_AUDIO); } -void EffectControls::on_add_video_transition_button_clicked() -{ - show_effect_menu(true, true); +void EffectControls::on_add_video_transition_button_clicked() { + show_effect_menu(EFFECT_TYPE_TRANSITION, EFFECT_TYPE_VIDEO); } -void EffectControls::on_add_audio_transition_button_clicked() -{ - show_effect_menu(false, true); +void EffectControls::on_add_audio_transition_button_clicked() { + show_effect_menu(EFFECT_TYPE_TRANSITION, EFFECT_TYPE_AUDIO); } void EffectControls::resizeEvent(QResizeEvent*) { diff --git a/panels/effectcontrols.h b/panels/effectcontrols.h index d80b10c39..6e2bdb807 100644 --- a/panels/effectcontrols.h +++ b/panels/effectcontrols.h @@ -40,6 +40,7 @@ public: void set_zoom(bool in); bool keyframe_focus(); void delete_selected_keyframes(); + void copy(bool del); bool multiple; QVector selected_clips; @@ -60,13 +61,13 @@ private slots: protected: void resizeEvent(QResizeEvent *event); private: - void show_effect_menu(bool video, bool transitions); + void show_effect_menu(int type, int subtype); void load_effects(); void load_keyframes(); void open_effect(QVBoxLayout* layout, Effect* e); - bool video_menu; - bool transition_menu; + int effect_menu_type; + int effect_menu_subtype; QString panel_name; int mode; }; diff --git a/panels/project.cpp b/panels/project.cpp index 593d52a4b..5b5eb05e0 100644 --- a/panels/project.cpp +++ b/panels/project.cpp @@ -812,10 +812,9 @@ QTreeWidgetItem* Project::find_loaded_folder_by_id(int id) { } const EffectMeta* get_meta_from_name(const QString& name, int type) { - QVector& effect_list = (type == EFFECT_TYPE_VIDEO) ? video_effects : audio_effects; - for (int j=0;jselections.size();j++) { const Selection& s = sequence->selections.at(j); if (s.track == c->track && !((c->timeline_in <= s.in && c->timeline_out <= s.in) || (c->timeline_in >= s.out && c->timeline_out >= s.out))) { - clipboard_type = CLIPBOARD_TYPE_CLIP; - if (!cleared) { - clipboard.clear(); + clear_clipboard(); cleared = true; + clipboard_type = CLIPBOARD_TYPE_CLIP; } Clip* copied_clip = c->copy(NULL); @@ -904,73 +903,88 @@ void Timeline::relink_clips_using_ids(QVector& old_clips, QVector& n } void Timeline::paste(bool insert) { - if (clipboard_type == CLIPBOARD_TYPE_CLIP && clipboard.size() > 0) { - ComboAction* ca = new ComboAction(); + if (clipboard.size() > 0) { + if (clipboard_type == CLIPBOARD_TYPE_CLIP) { + ComboAction* ca = new ComboAction(); - // create copies and delete areas that we'll be pasting to - QVector delete_areas; - QVector pasted_clips; - long paste_start = LONG_MAX; - long paste_end = LONG_MIN; - for (int i=0;i(clipboard.at(i)); + // create copies and delete areas that we'll be pasting to + QVector delete_areas; + QVector pasted_clips; + long paste_start = LONG_MAX; + long paste_end = LONG_MIN; + for (int i=0;i(clipboard.at(i)); - // create copy of clip and offset by playhead - Clip* cc = c->copy(sequence); + // create copy of clip and offset by playhead + Clip* cc = c->copy(sequence); - // convert frame rates - cc->timeline_in = refactor_frame_number(cc->timeline_in, c->cached_fr, sequence->frame_rate); - cc->timeline_out = refactor_frame_number(cc->timeline_out, c->cached_fr, sequence->frame_rate); - cc->clip_in = refactor_frame_number(cc->clip_in, c->cached_fr, sequence->frame_rate); + // convert frame rates + cc->timeline_in = refactor_frame_number(cc->timeline_in, c->cached_fr, sequence->frame_rate); + cc->timeline_out = refactor_frame_number(cc->timeline_out, c->cached_fr, sequence->frame_rate); + cc->clip_in = refactor_frame_number(cc->clip_in, c->cached_fr, sequence->frame_rate); - cc->timeline_in += sequence->playhead; - cc->timeline_out += sequence->playhead; - cc->track = c->track; + cc->timeline_in += sequence->playhead; + cc->timeline_out += sequence->playhead; + cc->track = c->track; - paste_start = qMin(paste_start, cc->timeline_in); - paste_end = qMax(paste_end, cc->timeline_out); + paste_start = qMin(paste_start, cc->timeline_in); + paste_end = qMax(paste_end, cc->timeline_out); - pasted_clips.append(cc); + pasted_clips.append(cc); - if (!insert) { - Selection s; - s.in = cc->timeline_in; - s.out = cc->timeline_out; - s.track = c->track; - delete_areas.append(s); + if (!insert) { + Selection s; + s.in = cc->timeline_in; + s.out = cc->timeline_out; + s.track = c->track; + delete_areas.append(s); + } + } + if (insert) { + split_cache.clear(); + split_all_clips_at_point(ca, sequence->playhead); + ca->append(new RippleCommand(sequence, paste_start, paste_end - paste_start)); + } else { + delete_areas_and_relink(ca, delete_areas); } - } - if (insert) { - split_cache.clear(); - split_all_clips_at_point(ca, sequence->playhead); - ca->append(new RippleCommand(sequence, paste_start, paste_end - paste_start)); - } else { - delete_areas_and_relink(ca, delete_areas); - } - // correct linked clips - for (int i=0;i(clipboard.at(i)); + // correct linked clips + for (int i=0;i(clipboard.at(i)); - for (int j=0;jlinked.size();j++) { - for (int k=0;k(clipboard.at(k)); - if (comp->load_id == oc->linked.at(j)) { - pasted_clips.at(i)->linked.append(k); + for (int j=0;jlinked.size();j++) { + for (int k=0;k(clipboard.at(k)); + if (comp->load_id == oc->linked.at(j)) { + pasted_clips.at(i)->linked.append(k); + } } } } - } - ca->append(new AddClipCommand(sequence, pasted_clips)); + ca->append(new AddClipCommand(sequence, pasted_clips)); - undo_stack.push(ca); + undo_stack.push(ca); - update_ui(true); + update_ui(true); - if (config.paste_seeks) { - panel_sequence_viewer->seek(paste_end); + if (config.paste_seeks) { + panel_sequence_viewer->seek(paste_end); + } + } else if (clipboard_type == CLIPBOARD_TYPE_EFFECT) { + for (int i=0;iclips.size();i++) { + Clip* c = sequence->clips.at(i); + if (c != NULL && is_clip_selected(c, true)) { + for (int j=0;j(clipboard.at(j)); + if ((c->track < 0) == (e->meta->subtype == EFFECT_TYPE_VIDEO)) { + c->effects.append(e->copy(c)); + } + } + } + } + update_ui(true); } } } @@ -1466,9 +1480,9 @@ void Timeline::on_toolTransitionButton_clicked() { QMenu transition_menu(this); - for (int i=0;isetObjectName("v"); a->setData(reinterpret_cast(&em)); @@ -1477,9 +1491,9 @@ void Timeline::on_toolTransitionButton_clicked() { transition_menu.addSeparator(); - for (int i=0;isetObjectName("a"); a->setData(reinterpret_cast(&em)); diff --git a/project/effect.cpp b/project/effect.cpp index 3be8ec413..011d7dfc2 100644 --- a/project/effect.cpp +++ b/project/effect.cpp @@ -38,8 +38,7 @@ #include #include -QVector video_effects; -QVector audio_effects; +QVector effects; QMutex effects_loaded; Effect* create_effect(Clip* c, const EffectMeta* em) { @@ -67,16 +66,11 @@ Effect* create_effect(Clip* c, const EffectMeta* em) { } const EffectMeta* get_internal_meta(int internal_id, int type) { - for (int i=0;i video_effects; -extern QVector audio_effects; +extern QVector effects; double log_volume(double linear); void init_effects(); From 34260674b39cb0ec490a1b05066dc3fab55941fb Mon Sep 17 00:00:00 2001 From: itsmattkc Date: Thu, 29 Nov 2018 22:17:59 +1100 Subject: [PATCH 22/31] fixed labelsliders entering val on cancel --- ui/labelslider.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/ui/labelslider.cpp b/ui/labelslider.cpp index 1e7dad08d..9636554de 100644 --- a/ui/labelslider.cpp +++ b/ui/labelslider.cpp @@ -148,8 +148,10 @@ void LabelSlider::mouseReleaseEvent(QMouseEvent*) { QLineEdit::Normal, valueToString(internal_value) ); + if (s.isEmpty()) return; d = timecode_to_frame(s, config.timecode_view, frame_rate); // string to frame number } else { + bool ok; d = QInputDialog::getDouble( this, "Set Value", @@ -157,9 +159,11 @@ void LabelSlider::mouseReleaseEvent(QMouseEvent*) { (display_type == LABELSLIDER_PERCENT) ? internal_value * 100 : internal_value, (min_enabled) ? min_value : INT_MIN, (max_enabled) ? max_value : INT_MAX, - decimal_places + decimal_places, + &ok ); - if (display_type == LABELSLIDER_PERCENT) d *= 0.01; + if (!ok) return; + if (display_type == LABELSLIDER_PERCENT) d *= 0.01; } if (d != internal_value) { previous_value = internal_value; From bb9861da25dcce2e29003315b1623ae98bfa6fbd Mon Sep 17 00:00:00 2001 From: itsmattkc Date: Thu, 29 Nov 2018 23:13:32 +1100 Subject: [PATCH 23/31] fixed bug where superimpose effect alpha affected whole clip alpha --- effects/internal/transformeffect.cpp | 2 +- ui/timelinewidget.cpp | 2 +- ui/viewerwidget.cpp | 18 +++++++++++------- 3 files changed, 13 insertions(+), 9 deletions(-) diff --git a/effects/internal/transformeffect.cpp b/effects/internal/transformeffect.cpp index 41e249a5e..ec12941e4 100644 --- a/effects/internal/transformeffect.cpp +++ b/effects/internal/transformeffect.cpp @@ -28,7 +28,7 @@ #define BLEND_MODE_MULTIPLY 2 #define BLEND_MODE_OVERLAY 3 -TransformEffect::TransformEffect(Clip* c, const EffectMeta* em) : Effect(c, em) { +TransformEffect::TransformEffect(Clip* c, const EffectMeta* em) : Effect(c, em) { enable_coords = true; EffectRow* position_row = add_row("Position:"); diff --git a/ui/timelinewidget.cpp b/ui/timelinewidget.cpp index 86a202991..50e9a0cd0 100644 --- a/ui/timelinewidget.cpp +++ b/ui/timelinewidget.cpp @@ -1504,7 +1504,7 @@ void TimelineWidget::update_ghosts(const QPoint& mouse_pos, bool lock_frame) { if (panel_timeline->importing) { QToolTip::showText(mapToGlobal(mouse_pos), frame_to_timecode(earliest_in_point, config.timecode_view, sequence->frame_rate)); - } else { + } else { QString tip = ((frame_diff < 0) ? "-" : "+") + frame_to_timecode(qAbs(frame_diff), config.timecode_view, sequence->frame_rate); if (panel_timeline->trim_target > -1) { // find which clip is being moved diff --git a/ui/viewerwidget.cpp b/ui/viewerwidget.cpp index e32ebcef8..aaec6385e 100644 --- a/ui/viewerwidget.cpp +++ b/ui/viewerwidget.cpp @@ -285,16 +285,16 @@ void ViewerWidget::drawTitleSafeArea() { } GLuint ViewerWidget::draw_clip(QOpenGLFramebufferObject* fbo, GLuint texture, bool clear) { - glPushMatrix(); - glLoadIdentity(); - glOrtho(0, 1, 0, 1, -1, 1); + glPushMatrix(); + glLoadIdentity(); + glOrtho(0, 1, 0, 1, -1, 1); - fbo->bind(); + fbo->bind(); if (clear) glClear(GL_COLOR_BUFFER_BIT); - glBindTexture(GL_TEXTURE_2D, texture); - glBegin(GL_QUADS); + glBindTexture(GL_TEXTURE_2D, texture); + glBegin(GL_QUADS); glTexCoord2f(0, 0); // top left glVertex2f(0, 0); // top left glTexCoord2f(1, 0); // top right @@ -327,7 +327,11 @@ void ViewerWidget::process_effect(Clip* c, Effect* e, double timecode, GLTexture } if (e->enable_superimpose) { GLuint superimpose_texture = e->process_superimpose(timecode); - if (superimpose_texture != 0) composite_texture = draw_clip(c->fbo[!fbo_switcher], superimpose_texture, false); + if (superimpose_texture != 0) { + glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA); + composite_texture = draw_clip(c->fbo[!fbo_switcher], superimpose_texture, false); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + } } } } From 9d4339512e05e7548d6878c98e1b0abbee3fec91 Mon Sep 17 00:00:00 2001 From: itsmattkc Date: Fri, 30 Nov 2018 00:14:36 +1100 Subject: [PATCH 24/31] fixed issue dragging media from viewer widget --- src.pro | 1 + ui/viewerwidget.cpp | 7 +++++-- 2 files changed, 6 insertions(+), 2 deletions(-) create mode 120000 src.pro diff --git a/src.pro b/src.pro new file mode 120000 index 000000000..eb1b3bf56 --- /dev/null +++ b/src.pro @@ -0,0 +1 @@ +olive.pro \ No newline at end of file diff --git a/ui/viewerwidget.cpp b/ui/viewerwidget.cpp index aaec6385e..254ba1cc2 100644 --- a/ui/viewerwidget.cpp +++ b/ui/viewerwidget.cpp @@ -36,6 +36,8 @@ extern "C" { #include } +#define GL_DEFAULT_BLEND glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + ViewerWidget::ViewerWidget(QWidget *parent) : QOpenGLWidget(parent), default_fbo(NULL), @@ -188,6 +190,7 @@ void ViewerWidget::mouseMoveEvent(QMouseEvent* event) { mimeData->setText("h"); // QMimeData will fail without some kind of data drag->setMimeData(mimeData); drag->exec(); + dragging = false; } else if (selected_gizmo != NULL) { double multiplier = (double) viewer->seq->width / (double) width(); @@ -330,7 +333,7 @@ void ViewerWidget::process_effect(Clip* c, Effect* e, double timecode, GLTexture if (superimpose_texture != 0) { glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA); composite_texture = draw_clip(c->fbo[!fbo_switcher], superimpose_texture, false); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + GL_DEFAULT_BLEND } } } @@ -429,7 +432,7 @@ GLuint ViewerWidget::compose_sequence(QVector& nests, bool render_audio) glOrtho(-half_width, half_width, half_height, -half_height, -1, 1); for (int i=0;i Date: Fri, 30 Nov 2018 09:52:29 +1100 Subject: [PATCH 25/31] fixed gizmos underneath other videos --- src.pro | 194 +++++++++++++++++++++++++++++++++++++++++++- ui/viewerwidget.cpp | 85 ++++++++++--------- ui/viewerwidget.h | 1 + 3 files changed, 241 insertions(+), 39 deletions(-) mode change 120000 => 100644 src.pro diff --git a/src.pro b/src.pro deleted file mode 120000 index eb1b3bf56..000000000 --- a/src.pro +++ /dev/null @@ -1 +0,0 @@ -olive.pro \ No newline at end of file diff --git a/src.pro b/src.pro new file mode 100644 index 000000000..547c460f2 --- /dev/null +++ b/src.pro @@ -0,0 +1,193 @@ +#------------------------------------------------- +# +# Project created by QtCreator 2018-05-11T10:31:59 +# +#------------------------------------------------- + +QT += core gui multimedia opengl + +greaterThan(QT_MAJOR_VERSION, 4): QT += widgets + +TARGET = Olive +TEMPLATE = app + +# The following define makes your compiler emit warnings if you use +# any feature of Qt which has been marked as deprecated (the exact warnings +# depend on your compiler). Please consult the documentation of the +# deprecated API in order to know how to port your code away from it. +DEFINES += QT_DEPRECATED_WARNINGS + +# You can also make your code fail to compile if you use deprecated APIs. +# In order to do so, uncomment the following line. +# You can also select to disable deprecated APIs only up to a certain version of Qt. +#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0 + + +SOURCES += \ + main.cpp \ + mainwindow.cpp \ + panels/project.cpp \ + panels/effectcontrols.cpp \ + panels/viewer.cpp \ + panels/timeline.cpp \ + ui/sourcetable.cpp \ + dialogs/aboutdialog.cpp \ + ui/timelinewidget.cpp \ + io/media.cpp \ + project/sequence.cpp \ + project/clip.cpp \ + playback/playback.cpp \ + playback/audio.cpp \ + io/config.cpp \ + dialogs/newsequencedialog.cpp \ + ui/viewerwidget.cpp \ + ui/viewercontainer.cpp \ + dialogs/exportdialog.cpp \ + ui/collapsiblewidget.cpp \ + panels/panels.cpp \ + playback/cacher.cpp \ + io/exportthread.cpp \ + ui/timelineheader.cpp \ + io/previewgenerator.cpp \ + ui/labelslider.cpp \ + dialogs/preferencesdialog.cpp \ + ui/audiomonitor.cpp \ + project/undo.cpp \ + ui/scrollarea.cpp \ + ui/comboboxex.cpp \ + ui/colorbutton.cpp \ + dialogs/replaceclipmediadialog.cpp \ + ui/fontcombobox.cpp \ + ui/checkboxex.cpp \ + ui/keyframeview.cpp \ + ui/texteditex.cpp \ + dialogs/demonotice.cpp \ + project/marker.cpp \ + dialogs/speeddialog.cpp \ + dialogs/mediapropertiesdialog.cpp \ + io/crc32.cpp \ + dialogs/loaddialog.cpp \ + debug.cpp \ + io/path.cpp \ + effects/internal/linearfadetransition.cpp \ + effects/internal/transformeffect.cpp \ + effects/internal/solideffect.cpp \ + effects/internal/texteffect.cpp \ + effects/internal/audionoiseeffect.cpp \ + effects/internal/paneffect.cpp \ + effects/internal/toneeffect.cpp \ + effects/internal/volumeeffect.cpp \ + effects/internal/crossdissolvetransition.cpp \ + effects/internal/shakeeffect.cpp \ + effects/internal/exponentialfadetransition.cpp \ + effects/internal/logarithmicfadetransition.cpp \ + effects/internal/cornerpineffect.cpp \ + io/math.cpp \ + io/qpainterwrapper.cpp \ + project/effect.cpp \ + project/transition.cpp \ + project/effectrow.cpp \ + project/effectfield.cpp \ + effects/internal/cubetransition.cpp \ + project/effectgizmo.cpp \ + io/clipboard.cpp + +HEADERS += \ + mainwindow.h \ + panels/project.h \ + panels/effectcontrols.h \ + panels/viewer.h \ + panels/timeline.h \ + ui/sourcetable.h \ + dialogs/aboutdialog.h \ + ui/timelinewidget.h \ + io/media.h \ + project/sequence.h \ + project/clip.h \ + playback/playback.h \ + playback/audio.h \ + io/config.h \ + dialogs/newsequencedialog.h \ + ui/viewerwidget.h \ + ui/viewercontainer.h \ + dialogs/exportdialog.h \ + ui/collapsiblewidget.h \ + panels/panels.h \ + playback/cacher.h \ + io/exportthread.h \ + ui/timelinetools.h \ + ui/timelineheader.h \ + io/previewgenerator.h \ + ui/labelslider.h \ + dialogs/preferencesdialog.h \ + ui/audiomonitor.h \ + project/undo.h \ + ui/scrollarea.h \ + ui/comboboxex.h \ + ui/colorbutton.h \ + dialogs/replaceclipmediadialog.h \ + ui/fontcombobox.h \ + ui/checkboxex.h \ + ui/keyframeview.h \ + ui/texteditex.h \ + dialogs/demonotice.h \ + project/marker.h \ + project/selection.h \ + dialogs/speeddialog.h \ + dialogs/mediapropertiesdialog.h \ + io/crc32.h \ + dialogs/loaddialog.h \ + debug.h \ + io/path.h \ + effects/internal/transformeffect.h \ + effects/internal/solideffect.h \ + effects/internal/texteffect.h \ + effects/internal/audionoiseeffect.h \ + effects/internal/paneffect.h \ + effects/internal/toneeffect.h \ + effects/internal/volumeeffect.h \ + effects/internal/shakeeffect.h \ + effects/internal/linearfadetransition.h \ + effects/internal/crossdissolvetransition.h \ + effects/internal/exponentialfadetransition.h \ + effects/internal/logarithmicfadetransition.h \ + effects/internal/cornerpineffect.h \ + io/math.h \ + io/qpainterwrapper.h \ + project/effect.h \ + project/transition.h \ + project/effectrow.h \ + project/effectfield.h \ + effects/internal/cubetransition.h \ + project/effectgizmo.h \ + io/clipboard.h + +FORMS += \ + mainwindow.ui \ + panels/project.ui \ + panels/effectcontrols.ui \ + panels/viewer.ui \ + panels/timeline.ui \ + dialogs/aboutdialog.ui \ + dialogs/newsequencedialog.ui \ + dialogs/exportdialog.ui \ + dialogs/preferencesdialog.ui \ + dialogs/demonotice.ui + +win32 { + RC_FILE = icons/resources.rc + LIBS += -lavutil -lavformat -lavcodec -lavfilter -lswscale -lswresample -lopengl32 +} + +mac { + LIBS += -L/usr/local/lib -lavutil -lavformat -lavcodec -lavfilter -lswscale -lswresample + ICON = icons/olive.icns + INCLUDEPATH = /usr/local/include +} + +linux { + LIBS += -lavutil -lavformat -lavcodec -lavfilter -lswscale -lswresample +} + +RESOURCES += \ + icons/icons.qrc diff --git a/ui/viewerwidget.cpp b/ui/viewerwidget.cpp index 254ba1cc2..bb58ffd69 100644 --- a/ui/viewerwidget.cpp +++ b/ui/viewerwidget.cpp @@ -429,7 +429,7 @@ GLuint ViewerWidget::compose_sequence(QVector& nests, bool render_audio) glPushMatrix(); glLoadIdentity(); - glOrtho(-half_width, half_width, half_height, -half_height, -1, 1); + glOrtho(-half_width, half_width, half_height, -half_height, -1, 10); for (int i=0;i& nests, bool render_audio) glBegin(GL_QUADS); if (coords.grid_size <= 1) { - float z = 0.5f; + float z = 0.0f; glTexCoord2f(coords.textureTopLeftX, coords.textureTopLeftY); // top left glVertex3f(coords.vertexTopLeftX, coords.vertexTopLeftY, z); // top left @@ -634,45 +634,11 @@ GLuint ViewerWidget::compose_sequence(QVector& nests, bool render_audio) glBindTexture(GL_TEXTURE_2D, 0); // unbind texture - if (gizmos != NULL) { - float color[4]; - glGetFloatv(GL_CURRENT_COLOR, color); - - float dot_size = GIZMO_DOT_SIZE / width() * viewer->seq->width; - + if (gizmos != NULL && !drawn_gizmos) { gizmos->gizmo_draw(timecode, coords); // set correct gizmo coords gizmos->gizmo_world_to_screen(); - glPushMatrix(); - glLoadIdentity(); - glOrtho(0, viewer->seq->width, viewer->seq->height, 0, -1, 1); - for (int j=0;jgizmo_count();j++) { - EffectGizmo* g = gizmos->gizmo(j); - glColor4f(g->color.redF(), g->color.greenF(), g->color.blueF(), 1.0); - switch (g->get_type()) { - case GIZMO_TYPE_DOT: // draw dot - glBegin(GL_QUADS); - glVertex2f(g->screen_pos[0].x()-dot_size, g->screen_pos[0].y()-dot_size); - glVertex2f(g->screen_pos[0].x()+dot_size, g->screen_pos[0].y()-dot_size); - glVertex2f(g->screen_pos[0].x()+dot_size, g->screen_pos[0].y()+dot_size); - glVertex2f(g->screen_pos[0].x()-dot_size, g->screen_pos[0].y()+dot_size); - glEnd(); - break; - case GIZMO_TYPE_POLY: // draw lines - glBegin(GL_LINES); - for (int k=1;kget_point_count();k++) { - glVertex2f(g->screen_pos[k-1].x(), g->screen_pos[k-1].y()); - glVertex2f(g->screen_pos[k].x(), g->screen_pos[k].y()); - } - glVertex2f(g->screen_pos[g->get_point_count()-1].x(), g->screen_pos[g->get_point_count()-1].y()); - glVertex2f(g->screen_pos[0].x(), g->screen_pos[0].y()); - glEnd(); - break; - } - } - glPopMatrix(); - - glColor4f(color[0], color[1], color[2], color[3]); + drawn_gizmos = true; } if (!nests.isEmpty()) { @@ -741,6 +707,7 @@ GLuint ViewerWidget::compose_sequence(QVector& nests, bool render_audio) } void ViewerWidget::paintGL() { + drawn_gizmos = false; if (viewer->seq != NULL) { gizmos = NULL; @@ -802,6 +769,48 @@ void ViewerWidget::paintGL() { drawTitleSafeArea(); } + if (gizmos != NULL && drawn_gizmos) { + float color[4]; + glGetFloatv(GL_CURRENT_COLOR, color); + + float dot_size = GIZMO_DOT_SIZE / width() * viewer->seq->width; + + glPushMatrix(); + glLoadIdentity(); + glOrtho(0, viewer->seq->width, viewer->seq->height, 0, -1, 10); + float gizmo_z = 0.0f; + for (int j=0;jgizmo_count();j++) { + EffectGizmo* g = gizmos->gizmo(j); + glColor4f(g->color.redF(), g->color.greenF(), g->color.blueF(), 1.0); + switch (g->get_type()) { + case GIZMO_TYPE_DOT: // draw dot + glBegin(GL_QUADS); + glVertex3f(g->screen_pos[0].x()-dot_size, g->screen_pos[0].y()-dot_size, gizmo_z); + glVertex3f(g->screen_pos[0].x()+dot_size, g->screen_pos[0].y()-dot_size, gizmo_z); + glVertex3f(g->screen_pos[0].x()+dot_size, g->screen_pos[0].y()+dot_size, gizmo_z); + glVertex3f(g->screen_pos[0].x()-dot_size, g->screen_pos[0].y()+dot_size, gizmo_z); + glEnd(); + break; + case GIZMO_TYPE_POLY: // draw lines + glBegin(GL_LINES); + for (int k=1;kget_point_count();k++) { + glVertex3f(g->screen_pos[k-1].x(), g->screen_pos[k-1].y(), gizmo_z); + glVertex3f(g->screen_pos[k].x(), g->screen_pos[k].y(), gizmo_z); + } + glVertex3f(g->screen_pos[g->get_point_count()-1].x(), g->screen_pos[g->get_point_count()-1].y(), gizmo_z); + glVertex3f(g->screen_pos[0].x(), g->screen_pos[0].y(), gizmo_z); + glEnd(); + break; + } + } + glPopMatrix(); + + glColor4f(color[0], color[1], color[2], color[3]); + + drawn_gizmos = true; + } + + glDisable(GL_DEPTH); glDisable(GL_BLEND); glDisable(GL_TEXTURE_2D); } while (loop); diff --git a/ui/viewerwidget.h b/ui/viewerwidget.h index ab909e842..69e34b71a 100644 --- a/ui/viewerwidget.h +++ b/ui/viewerwidget.h @@ -53,6 +53,7 @@ private: int drag_start_y; EffectGizmo* selected_gizmo; EffectGizmo* get_gizmo_from_mouse(int x, int y); + bool drawn_gizmos; private slots: void retry(); void show_context_menu(); From f6406cab9caad650340b779023b4970851308b74 Mon Sep 17 00:00:00 2001 From: itsmattkc Date: Fri, 30 Nov 2018 10:24:27 +1100 Subject: [PATCH 26/31] implemented gizmo undoing --- project/undo.cpp | 24 ++++++++++++++++++++++++ project/undo.h | 16 ++++++++++++++++ ui/viewerwidget.cpp | 16 ++++++++++++++++ ui/viewerwidget.h | 2 ++ 4 files changed, 58 insertions(+) diff --git a/project/undo.cpp b/project/undo.cpp index 71b474b7f..f5529fc69 100644 --- a/project/undo.cpp +++ b/project/undo.cpp @@ -1299,3 +1299,27 @@ void SetPointer::redo() { *p = new_data; mainWindow->setWindowModified(true); } + +MoveGizmo::MoveGizmo(Effect *e, EffectGizmo *g, int x_movement, int y_movement, double tc) : + effect(e), + gizmo(g), + x(x_movement), + y(y_movement), + timecode(tc), + done(true), + old_changed(mainWindow->isWindowModified()) +{} + +void MoveGizmo::undo() { + effect->gizmo_move(gizmo, -x, -y, timecode); + mainWindow->setWindowModified(old_changed); + done = false; +} + +void MoveGizmo::redo() { + if (!done) { + effect->gizmo_move(gizmo, x, y, timecode); + mainWindow->setWindowModified(true); + done = true; + } +} diff --git a/project/undo.h b/project/undo.h index e69c466ab..22261866c 100644 --- a/project/undo.h +++ b/project/undo.h @@ -9,6 +9,7 @@ class SourceTable; class EffectRow; class EffectField; class Transition; +class EffectGizmo; struct Clip; struct Sequence; struct Media; @@ -597,4 +598,19 @@ private: void* old_data; }; +class MoveGizmo : public QUndoCommand { +public: + MoveGizmo(Effect* e, EffectGizmo* g, int x_movement, int y_movement, double tc); + void undo(); + void redo(); +private: + Effect* effect; + EffectGizmo* gizmo; + int x; + int y; + double timecode; + bool done; + bool old_changed; +}; + #endif // UNDO_H diff --git a/ui/viewerwidget.cpp b/ui/viewerwidget.cpp index bb58ffd69..eb9152270 100644 --- a/ui/viewerwidget.cpp +++ b/ui/viewerwidget.cpp @@ -17,6 +17,7 @@ #include "debug.h" #include "io/math.h" #include "ui/collapsiblewidget.h" +#include "project/undo.h" #include #include @@ -175,6 +176,9 @@ void ViewerWidget::mousePressEvent(QMouseEvent* event) { drag_start_x = event->pos().x(); drag_start_y = event->pos().y(); + gizmo_x_mvmt = 0; + gizmo_y_mvmt = 0; + selected_gizmo = get_gizmo_from_mouse(event->pos().x(), event->pos().y()); } dragging = true; @@ -199,6 +203,9 @@ void ViewerWidget::mouseMoveEvent(QMouseEvent* event) { gizmos->gizmo_move(selected_gizmo, x_movement, y_movement, get_timecode(gizmos->parent_clip, gizmos->parent_clip->sequence->playhead)); + gizmo_x_mvmt += x_movement; + gizmo_y_mvmt += y_movement; + drag_start_x = event->pos().x(); drag_start_y = event->pos().y(); @@ -216,6 +223,15 @@ void ViewerWidget::mouseMoveEvent(QMouseEvent* event) { } void ViewerWidget::mouseReleaseEvent(QMouseEvent *event) { + if (selected_gizmo != NULL) { + undo_stack.push(new MoveGizmo( + gizmos, + selected_gizmo, + gizmo_x_mvmt, + gizmo_y_mvmt, + get_timecode(gizmos->parent_clip, gizmos->parent_clip->sequence->playhead) + )); + } dragging = false; } diff --git a/ui/viewerwidget.h b/ui/viewerwidget.h index 69e34b71a..38837cbaf 100644 --- a/ui/viewerwidget.h +++ b/ui/viewerwidget.h @@ -51,6 +51,8 @@ private: Effect* gizmos; int drag_start_x; int drag_start_y; + int gizmo_x_mvmt; + int gizmo_y_mvmt; EffectGizmo* selected_gizmo; EffectGizmo* get_gizmo_from_mouse(int x, int y); bool drawn_gizmos; From 1d4600439f63ab81e13934dfb75996bcf4778083 Mon Sep 17 00:00:00 2001 From: itsmattkc Date: Fri, 30 Nov 2018 18:04:24 +1100 Subject: [PATCH 27/31] reduced effects control updates --- panels/panels.cpp | 1 + ui/timelinewidget.cpp | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/panels/panels.cpp b/panels/panels.cpp index 8b458fcd1..b7c221faf 100644 --- a/panels/panels.cpp +++ b/panels/panels.cpp @@ -84,6 +84,7 @@ void update_effect_controls() { void update_ui(bool modified) { if (modified) { // panel_sequence_viewer->reset_all_audio(); + dout << "h"; update_effect_controls(); } panel_effect_controls->update_keyframes(); diff --git a/ui/timelinewidget.cpp b/ui/timelinewidget.cpp index 50e9a0cd0..61c178781 100644 --- a/ui/timelinewidget.cpp +++ b/ui/timelinewidget.cpp @@ -1807,7 +1807,7 @@ void TimelineWidget::mouseMoveEvent(QMouseEvent *event) { panel_timeline->moving_proc = true; } - update_ui(true); + update_ui(false); } else if (panel_timeline->splitting) { int track_start = qMin(panel_timeline->cursor_track, panel_timeline->drag_track_start); int track_end = qMax(panel_timeline->cursor_track, panel_timeline->drag_track_start); @@ -1831,7 +1831,7 @@ void TimelineWidget::mouseMoveEvent(QMouseEvent *event) { } } } - update_ui(true); + update_ui(false); } else if (panel_timeline->rect_select_init) { if (panel_timeline->rect_select_proc) { panel_timeline->rect_select_w = event->pos().x() - panel_timeline->rect_select_x; From e86931d79ab434b5fd3d76e21b824bbe98a29552 Mon Sep 17 00:00:00 2001 From: itsmattkc Date: Fri, 30 Nov 2018 18:17:55 +1100 Subject: [PATCH 28/31] removed stray print line --- panels/panels.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/panels/panels.cpp b/panels/panels.cpp index b7c221faf..8b458fcd1 100644 --- a/panels/panels.cpp +++ b/panels/panels.cpp @@ -84,7 +84,6 @@ void update_effect_controls() { void update_ui(bool modified) { if (modified) { // panel_sequence_viewer->reset_all_audio(); - dout << "h"; update_effect_controls(); } panel_effect_controls->update_keyframes(); From 4fae026abb708117a6b03a5a7765c0447a242484 Mon Sep 17 00:00:00 2001 From: itsmattkc Date: Fri, 30 Nov 2018 19:22:15 +1100 Subject: [PATCH 29/31] further optimized effects controls --- panels/panels.cpp | 25 ++++++++++++++++++++----- 1 file changed, 20 insertions(+), 5 deletions(-) diff --git a/panels/panels.cpp b/panels/panels.cpp index 8b458fcd1..e2ed4599b 100644 --- a/panels/panels.cpp +++ b/panels/panels.cpp @@ -19,7 +19,7 @@ void update_effect_controls() { // find out how many clips are selected // limits to one video clip and one audio clip and only if they're linked // one of these days it might be nice to have multiple clips in the effects panel - panel_effect_controls->multiple = false; + bool multiple = false; int vclip = -1; int aclip = -1; QVector selected_clips; @@ -49,7 +49,8 @@ void update_effect_controls() { } else { vclip = -2; aclip = -2; - panel_effect_controls->multiple = true; + multiple = true; + multiple = true; break; } } @@ -57,7 +58,7 @@ void update_effect_controls() { } } - if (!panel_effect_controls->multiple) { + if (!multiple) { // check if aclip is linked to vclip if (vclip >= 0) selected_clips.append(vclip); if (aclip >= 0) selected_clips.append(aclip); @@ -73,12 +74,26 @@ void update_effect_controls() { if (!found) { // only display multiple clips if they're linked selected_clips.clear(); - panel_effect_controls->multiple = true; + multiple = true; } } } } - panel_effect_controls->set_clips(selected_clips, mode); + + bool same = (selected_clips.size() == panel_effect_controls->selected_clips.size()); + if (same) { + for (int i=0;iselected_clips.at(i)) { + same = false; + break; + } + } + } + + if (panel_effect_controls->multiple != multiple || !same) { + panel_effect_controls->multiple = multiple; + panel_effect_controls->set_clips(selected_clips, mode); + } } void update_ui(bool modified) { From 326403c126d3222ba1ad875be61e875a04c5d11d Mon Sep 17 00:00:00 2001 From: itsmattkc Date: Sat, 1 Dec 2018 10:55:25 +1100 Subject: [PATCH 30/31] switch the glBlendFuncSeparate --- panels/project.cpp | 30 ++++++++++++++++-------------- ui/viewerwidget.cpp | 9 +++++---- ui/viewerwidget.h | 3 ++- 3 files changed, 23 insertions(+), 19 deletions(-) diff --git a/panels/project.cpp b/panels/project.cpp index 5b5eb05e0..cb95e69a1 100644 --- a/panels/project.cpp +++ b/panels/project.cpp @@ -1246,20 +1246,22 @@ bool Project::load_worker(QFile& f, QXmlStreamReader& stream, int type) { const TransitionData& td = transition_data.at(i); Clip* primary = td.otc; Clip* secondary = td.ctc; - if (primary == NULL) { - primary = secondary; - secondary = NULL; - } - const EffectMeta* meta = get_meta_from_name(td.name, (primary->track < 0) ? EFFECT_TYPE_VIDEO : EFFECT_TYPE_AUDIO); - if (meta == NULL) { - dout << "[WARNING] Failed to link transition with name:" << td.name; - if (td.otc != NULL) td.otc->opening_transition = -1; - if (td.ctc != NULL) td.ctc->closing_transition = -1; - } else { - int transition_index = create_transition(primary, secondary, meta); - primary->sequence->transitions.at(transition_index)->set_length(td.length); - if (td.otc != NULL) td.otc->opening_transition = transition_index; - if (td.ctc != NULL) td.ctc->closing_transition = transition_index; + if (primary != NULL || secondary != NULL) { + if (primary == NULL) { + primary = secondary; + secondary = NULL; + } + const EffectMeta* meta = get_meta_from_name(td.name, (primary->track < 0) ? EFFECT_TYPE_VIDEO : EFFECT_TYPE_AUDIO); + if (meta == NULL) { + dout << "[WARNING] Failed to link transition with name:" << td.name; + if (td.otc != NULL) td.otc->opening_transition = -1; + if (td.ctc != NULL) td.ctc->closing_transition = -1; + } else { + int transition_index = create_transition(primary, secondary, meta); + primary->sequence->transitions.at(transition_index)->set_length(td.length); + if (td.otc != NULL) td.otc->opening_transition = transition_index; + if (td.ctc != NULL) td.ctc->closing_transition = transition_index; + } } } diff --git a/ui/viewerwidget.cpp b/ui/viewerwidget.cpp index eb9152270..7329f2e9a 100644 --- a/ui/viewerwidget.cpp +++ b/ui/viewerwidget.cpp @@ -24,7 +24,6 @@ #include #include #include -#include #include #include #include @@ -37,7 +36,7 @@ extern "C" { #include } -#define GL_DEFAULT_BLEND glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); +#define GL_DEFAULT_BLEND glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_SRC_ALPHA, GL_ONE); ViewerWidget::ViewerWidget(QWidget *parent) : QOpenGLWidget(parent), @@ -116,6 +115,8 @@ void ViewerWidget::retry() { } void ViewerWidget::initializeGL() { + initializeOpenGLFunctions(); + connect(context(), SIGNAL(aboutToBeDestroyed()), this, SLOT(delete_function()), Qt::DirectConnection); retry_timer.start(); @@ -347,9 +348,7 @@ void ViewerWidget::process_effect(Clip* c, Effect* e, double timecode, GLTexture if (e->enable_superimpose) { GLuint superimpose_texture = e->process_superimpose(timecode); if (superimpose_texture != 0) { - glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA); composite_texture = draw_clip(c->fbo[!fbo_switcher], superimpose_texture, false); - GL_DEFAULT_BLEND } } } @@ -523,6 +522,7 @@ GLuint ViewerWidget::compose_sequence(QVector& nests, bool render_audio) fbo_switcher = !fbo_switcher; + // set up default coords GLTextureCoords coords; coords.grid_size = 1; coords.vertexTopLeftX = coords.vertexBottomLeftX = -video_width/2; @@ -534,6 +534,7 @@ GLuint ViewerWidget::compose_sequence(QVector& nests, bool render_audio) coords.textureBottomLeftY = coords.textureBottomRightY = coords.textureTopRightX = coords.textureBottomRightX = 1.0; coords.textureTopLeftQ = coords.textureTopRightQ = coords.textureTopLeftQ = coords.textureBottomLeftQ = 1; + // set up autoscale if (c->autoscale && (video_width != s->width && video_height != s->height)) { float width_multiplier = (float) s->width / (float) video_width; float height_multiplier = (float) s->height / (float) video_height; diff --git a/ui/viewerwidget.h b/ui/viewerwidget.h index 38837cbaf..a6f9e3632 100644 --- a/ui/viewerwidget.h +++ b/ui/viewerwidget.h @@ -8,6 +8,7 @@ #include #include #include +#include class Viewer; struct Clip; @@ -17,7 +18,7 @@ class Effect; class EffectGizmo; struct GLTextureCoords; -class ViewerWidget : public QOpenGLWidget +class ViewerWidget : public QOpenGLWidget, QOpenGLFunctions { Q_OBJECT public: From 0188920556a5d32e19e93d1fcc038a591d7eb73c Mon Sep 17 00:00:00 2001 From: itsmattkc Date: Sat, 1 Dec 2018 11:56:30 +1100 Subject: [PATCH 31/31] fixed alpha blending in some situations --- effects/internal/solideffect.cpp | 2 +- ui/viewerwidget.cpp | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/effects/internal/solideffect.cpp b/effects/internal/solideffect.cpp index ecf998ca9..0f888da61 100644 --- a/effects/internal/solideffect.cpp +++ b/effects/internal/solideffect.cpp @@ -50,7 +50,7 @@ SolidEffect::SolidEffect(Clip* c, const EffectMeta* em) : Effect(c, em) { void SolidEffect::redraw(double timecode) { int w = img.width(); int h = img.height(); - int alpha = (opacity_field->get_double_value(timecode)*2.55); + int alpha = qRound(opacity_field->get_double_value(timecode)*2.55); switch (solid_type->get_combo_data(timecode).toInt()) { case SOLID_TYPE_COLOR: { diff --git a/ui/viewerwidget.cpp b/ui/viewerwidget.cpp index 7329f2e9a..c01912839 100644 --- a/ui/viewerwidget.cpp +++ b/ui/viewerwidget.cpp @@ -36,7 +36,7 @@ extern "C" { #include } -#define GL_DEFAULT_BLEND glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_SRC_ALPHA, GL_ONE); +#define GL_DEFAULT_BLEND glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE); ViewerWidget::ViewerWidget(QWidget *parent) : QOpenGLWidget(parent), @@ -312,6 +312,7 @@ GLuint ViewerWidget::draw_clip(QOpenGLFramebufferObject* fbo, GLuint texture, bo fbo->bind(); if (clear) glClear(GL_COLOR_BUFFER_BIT); + GL_DEFAULT_BLEND glBindTexture(GL_TEXTURE_2D, texture); glBegin(GL_QUADS);