From 7f08925385fd963bb3da6ea7f226b026578c3a75 Mon Sep 17 00:00:00 2001 From: itsmattkc Date: Sun, 9 Dec 2018 01:25:22 +1100 Subject: [PATCH 1/5] began work on scrollable headers on viewer panels --- mainwindow.cpp | 14 +++++++++++--- panels/viewer.cpp | 21 ++++++++++++++++++--- panels/viewer.h | 3 +++ panels/viewer.ui | 7 +++++++ ui/timelineheader.cpp | 6 +++++- ui/timelineheader.h | 1 + 6 files changed, 45 insertions(+), 7 deletions(-) diff --git a/mainwindow.cpp b/mainwindow.cpp index b2a3005df..2354caf01 100644 --- a/mainwindow.cpp +++ b/mainwindow.cpp @@ -311,7 +311,11 @@ void MainWindow::on_actionZoom_In_triggered() panel_timeline->set_zoom(true); } else if (panel_effect_controls->keyframe_focus()) { panel_effect_controls->set_zoom(true); - } + } else if (panel_footage_viewer->is_focused()) { + panel_footage_viewer->set_zoom(true); + } else if (panel_sequence_viewer->is_focused()) { + panel_sequence_viewer->set_zoom(true); + } } void MainWindow::on_actionZoom_out_triggered() @@ -320,7 +324,11 @@ void MainWindow::on_actionZoom_out_triggered() panel_timeline->set_zoom(false); } else if (panel_effect_controls->keyframe_focus()) { panel_effect_controls->set_zoom(false); - } + } else if (panel_footage_viewer->is_focused()) { + panel_footage_viewer->set_zoom(false); + } else if (panel_sequence_viewer->is_focused()) { + panel_sequence_viewer->set_zoom(false); + } } void MainWindow::on_actionExport_triggered() @@ -582,7 +590,7 @@ void MainWindow::on_actionEdit_Tool_triggered() void MainWindow::on_actionToggle_Snapping_triggered() { - if (panel_timeline->focused()) panel_timeline->ui->snappingButton->click(); + if (panel_timeline->focused() || panel_effect_controls->keyframe_focus()) panel_timeline->ui->snappingButton->click(); } void MainWindow::on_actionPointer_Tool_triggered() diff --git a/panels/viewer.cpp b/panels/viewer.cpp index 9e2fccde9..5b13fe699 100644 --- a/panels/viewer.cpp +++ b/panels/viewer.cpp @@ -37,7 +37,8 @@ Viewer::Viewer(QWidget *parent) : ui(new Ui::Viewer), created_sequence(false), cue_recording_internal(false), - panel_name("Viewer: ") + panel_name("Viewer: "), + minimum_zoom(1.0) { ui->setupUi(this); ui->headers->viewer = this; @@ -59,6 +60,7 @@ Viewer::Viewer(QWidget *parent) : connect(&playback_updater, SIGNAL(timeout()), this, SLOT(timer_update())); connect(&recording_flasher, SIGNAL(timeout()), this, SLOT(recording_flasher_update())); + connect(ui->horizontalScrollBar, SIGNAL(valueChanged(int)), ui->headers, SLOT(set_scroll(int))); update_playhead_timecode(0); update_end_timecode(); @@ -380,7 +382,12 @@ void Viewer::update_end_timecode() { void Viewer::update_header_zoom() { if (seq != NULL) { long sequenceEndFrame = seq->getEndFrame(); - ui->headers->update_zoom((sequenceEndFrame > 0) ? ((double) ui->headers->width() / (double) sequenceEndFrame) : 1); + if (cached_end_frame != sequenceEndFrame) { + minimum_zoom = (sequenceEndFrame > 0) ? ((double) ui->headers->width() / (double) sequenceEndFrame) : 1; + ui->headers->update_zoom(qMax(ui->headers->get_zoom(), minimum_zoom)); + } else { + ui->headers->update(); + } } } @@ -411,7 +418,15 @@ void Viewer::set_in_point() { } void Viewer::set_out_point() { - ui->headers->set_out_point(seq->playhead); + ui->headers->set_out_point(seq->playhead); +} + +void Viewer::set_zoom(bool in) { + if (in) { + ui->headers->update_zoom(ui->headers->get_zoom()*2); + } else { + ui->headers->update_zoom(qMax(minimum_zoom, ui->headers->get_zoom()*0.5)); + } } void Viewer::set_media(int type, void* media) { diff --git a/panels/viewer.h b/panels/viewer.h index 547efdf7b..a46c24c66 100644 --- a/panels/viewer.h +++ b/panels/viewer.h @@ -36,6 +36,7 @@ public: void clear_inout_point(); void set_in_point(); void set_out_point(); + void set_zoom(bool in); // playback functions void go_to_start(); @@ -86,7 +87,9 @@ private: void set_sequence(bool main, Sequence* s); bool main_sequence; bool created_sequence; + long cached_end_frame; QString panel_name; + double minimum_zoom; bool cue_recording_internal; QTimer recording_flasher; diff --git a/panels/viewer.ui b/panels/viewer.ui index 111812803..648765042 100644 --- a/panels/viewer.ui +++ b/panels/viewer.ui @@ -64,6 +64,13 @@ + + + + Qt::Horizontal + + + diff --git a/ui/timelineheader.cpp b/ui/timelineheader.cpp index 00094fac2..c67c8d39f 100644 --- a/ui/timelineheader.cpp +++ b/ui/timelineheader.cpp @@ -255,7 +255,11 @@ void TimelineHeader::update_parents() { void TimelineHeader::update_zoom(double z) { zoom = z; - update(); + update(); +} + +double TimelineHeader::get_zoom() { + return zoom; } void TimelineHeader::delete_markers() { diff --git a/ui/timelineheader.h b/ui/timelineheader.h index 68cb38573..979b3fd38 100644 --- a/ui/timelineheader.h +++ b/ui/timelineheader.h @@ -20,6 +20,7 @@ public: void show_text(bool enable); void update_zoom(double z); + double get_zoom(); void delete_markers(); public slots: From 5d89afb639b0124cd23dd941f16f8a87376ff1d0 Mon Sep 17 00:00:00 2001 From: itsmattkc Date: Sun, 9 Dec 2018 01:39:36 +1100 Subject: [PATCH 2/5] finished scrollable viewer playheads --- panels/timeline.cpp | 16 +++------------- panels/timeline.h | 3 +-- panels/viewer.cpp | 3 +++ panels/viewer.ui | 9 +++++++++ ui/timelineheader.cpp | 16 +++++++++++++++- ui/timelineheader.h | 5 ++++- 6 files changed, 35 insertions(+), 17 deletions(-) diff --git a/panels/timeline.cpp b/panels/timeline.cpp index e9279206f..7726a08e8 100644 --- a/panels/timeline.cpp +++ b/panels/timeline.cpp @@ -417,16 +417,6 @@ bool Timeline::focused() { return (sequence != NULL && (ui->headers->hasFocus() || ui->video_area->hasFocus() || ui->audio_area->hasFocus())); } -bool Timeline::center_scroll_to_playhead() { - // returns true is the scroll was changed, false if not - int target_scroll = qMin(ui->horizontalScrollBar->maximum(), qMax(0, getScreenPointFromFrame(zoom, sequence->playhead)-(ui->editAreas->width()>>1))); - if (target_scroll == ui->horizontalScrollBar->value()) { - return false; - } - ui->horizontalScrollBar->setValue(target_scroll); - return true; -} - void Timeline::repaint_timeline() { bool draw = true; @@ -442,7 +432,7 @@ void Timeline::repaint_timeline() { draw = false; } } else if (config.autoscroll == AUTOSCROLL_SMOOTH_SCROLL) { - if (center_scroll_to_playhead()) { + if (center_scroll_to_playhead(ui->horizontalScrollBar, zoom, sequence->playhead)) { draw = false; } } @@ -458,7 +448,7 @@ void Timeline::repaint_timeline() { if (sequence != NULL) { long sequenceEndFrame = sequence->getEndFrame(); - ui->horizontalScrollBar->setMaximum(qMax(0, getScreenPointFromFrame(zoom, sequenceEndFrame) - (ui->editAreas->width()/2))); + ui->headers->set_scrollbar_max(ui->horizontalScrollBar, sequenceEndFrame, (ui->editAreas->width()/2)); if (last_frame != sequence->playhead) { ui->audio_monitor->update(); @@ -579,7 +569,7 @@ void Timeline::set_zoom_value(double v) { repaint_timeline(); // TODO find a way to gradually move towards target_scroll instead of just centering it? - center_scroll_to_playhead(); + center_scroll_to_playhead(ui->horizontalScrollBar, zoom, sequence->playhead); } void Timeline::set_zoom(bool in) { diff --git a/panels/timeline.h b/panels/timeline.h index db73a87da..fddd177b4 100644 --- a/panels/timeline.h +++ b/panels/timeline.h @@ -227,8 +227,7 @@ private: void set_zoom_value(double v); QVector tool_buttons; void decheck_tool_buttons(QObject* sender); - void set_tool(int tool); - bool center_scroll_to_playhead(); + void set_tool(int tool); long last_frame; int scroll; diff --git a/panels/viewer.cpp b/panels/viewer.cpp index 5b13fe699..b92d96935 100644 --- a/panels/viewer.cpp +++ b/panels/viewer.cpp @@ -385,6 +385,7 @@ void Viewer::update_header_zoom() { if (cached_end_frame != sequenceEndFrame) { minimum_zoom = (sequenceEndFrame > 0) ? ((double) ui->headers->width() / (double) sequenceEndFrame) : 1; ui->headers->update_zoom(qMax(ui->headers->get_zoom(), minimum_zoom)); + ui->headers->set_scrollbar_max(ui->horizontalScrollBar, sequenceEndFrame, ui->headers->width()); } else { ui->headers->update(); } @@ -427,6 +428,8 @@ void Viewer::set_zoom(bool in) { } else { ui->headers->update_zoom(qMax(minimum_zoom, ui->headers->get_zoom()*0.5)); } + ui->headers->set_scrollbar_max(ui->horizontalScrollBar, seq->getEndFrame(), ui->headers->width()); + center_scroll_to_playhead(ui->horizontalScrollBar, ui->headers->get_zoom(), seq->playhead); } void Viewer::set_media(int type, void* media) { diff --git a/panels/viewer.ui b/panels/viewer.ui index 648765042..0a7613183 100644 --- a/panels/viewer.ui +++ b/panels/viewer.ui @@ -66,6 +66,15 @@ + + 0 + + + 20 + + + 1826 + Qt::Horizontal diff --git a/ui/timelineheader.cpp b/ui/timelineheader.cpp index c67c8d39f..d39976bbd 100644 --- a/ui/timelineheader.cpp +++ b/ui/timelineheader.cpp @@ -10,7 +10,7 @@ #include #include -#include +#include #include #define CLICK_RANGE 5 @@ -19,6 +19,16 @@ #define SUBLINE_MIN_PADDING 50 // TODO play with this #define MARKER_SIZE 4 +bool center_scroll_to_playhead(QScrollBar* bar, double zoom, long playhead) { + // returns true is the scroll was changed, false if not + int target_scroll = qMin(bar->maximum(), qMax(0, getScreenPointFromFrame(zoom, playhead)-(bar->width()>>1))); + if (target_scroll == bar->value()) { + return false; + } + bar->setValue(target_scroll); + return true; +} + TimelineHeader::TimelineHeader(QWidget *parent) : QWidget(parent), snapping(true), @@ -87,6 +97,10 @@ void TimelineHeader::set_out_point(long new_out) { update_parents(); } +void TimelineHeader::set_scrollbar_max(QScrollBar* bar, long sequence_end_frame, int offset) { + bar->setMaximum(qMax(0, getScreenPointFromFrame(zoom, sequence_end_frame) - offset)); +} + void TimelineHeader::show_text(bool enable) { text_enabled = enable; if (enable) { diff --git a/ui/timelineheader.h b/ui/timelineheader.h index 979b3fd38..88adc3151 100644 --- a/ui/timelineheader.h +++ b/ui/timelineheader.h @@ -3,8 +3,10 @@ #include #include -class QScrollArea; class Viewer; +class QScrollBar; + +bool center_scroll_to_playhead(QScrollBar* bar, double zoom, long playhead); class TimelineHeader : public QWidget { @@ -22,6 +24,7 @@ public: void update_zoom(double z); double get_zoom(); void delete_markers(); + void set_scrollbar_max(QScrollBar* bar, long sequence_end_frame, int offset); public slots: void set_scroll(int); From e623b8640e0734c0170cad5611f60308a18fed54 Mon Sep 17 00:00:00 2001 From: itsmattkc Date: Sun, 9 Dec 2018 02:15:53 +1100 Subject: [PATCH 3/5] integrated waveform with scrollable playhead --- panels/viewer.cpp | 8 +++++++- ui/viewercontainer.cpp | 41 ++++++++++++++++++++++++----------------- ui/viewercontainer.h | 3 ++- ui/viewerwidget.cpp | 27 ++++++++++++++++++--------- ui/viewerwidget.h | 3 +++ 5 files changed, 54 insertions(+), 28 deletions(-) diff --git a/panels/viewer.cpp b/panels/viewer.cpp index b92d96935..49b144b42 100644 --- a/panels/viewer.cpp +++ b/panels/viewer.cpp @@ -61,6 +61,7 @@ Viewer::Viewer(QWidget *parent) : connect(&playback_updater, SIGNAL(timeout()), this, SLOT(timer_update())); connect(&recording_flasher, SIGNAL(timeout()), this, SLOT(recording_flasher_update())); connect(ui->horizontalScrollBar, SIGNAL(valueChanged(int)), ui->headers, SLOT(set_scroll(int))); + connect(ui->horizontalScrollBar, SIGNAL(valueChanged(int)), ui->openGLWidget, SLOT(set_waveform_scroll(int))); update_playhead_timecode(0); update_end_timecode(); @@ -386,6 +387,7 @@ void Viewer::update_header_zoom() { minimum_zoom = (sequenceEndFrame > 0) ? ((double) ui->headers->width() / (double) sequenceEndFrame) : 1; ui->headers->update_zoom(qMax(ui->headers->get_zoom(), minimum_zoom)); ui->headers->set_scrollbar_max(ui->horizontalScrollBar, sequenceEndFrame, ui->headers->width()); + ui->openGLWidget->waveform_zoom = ui->headers->get_zoom(); } else { ui->headers->update(); } @@ -401,8 +403,8 @@ void Viewer::update_parents() { } void Viewer::update_viewer() { + update_header_zoom(); viewer_widget->update(); - update_header_zoom(); if (seq != NULL) update_playhead_timecode(seq->playhead); update_end_timecode(); } @@ -428,6 +430,10 @@ void Viewer::set_zoom(bool in) { } else { ui->headers->update_zoom(qMax(minimum_zoom, ui->headers->get_zoom()*0.5)); } + if (ui->openGLWidget->waveform) { + ui->openGLWidget->waveform_zoom = ui->headers->get_zoom(); + ui->openGLWidget->update(); + } ui->headers->set_scrollbar_max(ui->horizontalScrollBar, seq->getEndFrame(), ui->headers->width()); center_scroll_to_playhead(ui->horizontalScrollBar, ui->headers->get_zoom(), seq->playhead); } diff --git a/ui/viewercontainer.cpp b/ui/viewercontainer.cpp index cd3e7cbfd..82b203bba 100644 --- a/ui/viewercontainer.cpp +++ b/ui/viewercontainer.cpp @@ -3,6 +3,8 @@ #include #include +#include "viewerwidget.h" + // enforces aspect ratio ViewerContainer::ViewerContainer(QWidget *parent) : QWidget(parent), @@ -11,26 +13,31 @@ ViewerContainer::ViewerContainer(QWidget *parent) : {} void ViewerContainer::adjust() { - if (child != NULL) { - QSize widget_size = size(); - int widget_x = 0; - int widget_y = 0; - int widget_width = widget_size.width(); - int widget_height = widget_size.height(); - float widget_ar = (float) widget_width /(float) widget_height; + if (child != NULL) { + if (child->waveform) { + child->move(0, 0); + child->resize(size()); + } else { + QSize widget_size = size(); + int widget_x = 0; + int widget_y = 0; + int widget_width = widget_size.width(); + int widget_height = widget_size.height(); + float widget_ar = (float) widget_width /(float) widget_height; - bool widget_is_larger_than_sequence = widget_ar > aspect_ratio; + bool widget_is_larger_than_sequence = widget_ar > aspect_ratio; - if (widget_is_larger_than_sequence) { - widget_width = widget_height * aspect_ratio; - widget_x = (widget_size.width() / 2) - (widget_width / 2); - } else { - widget_height = widget_width / aspect_ratio; - widget_y = (widget_size.height() / 2) - (widget_height / 2); - } + if (widget_is_larger_than_sequence) { + widget_width = widget_height * aspect_ratio; + widget_x = (widget_size.width() / 2) - (widget_width / 2); + } else { + widget_height = widget_width / aspect_ratio; + widget_y = (widget_size.height() / 2) - (widget_height / 2); + } - child->move(widget_x, widget_y); - child->resize(widget_width, widget_height); + child->move(widget_x, widget_y); + child->resize(widget_width, widget_height); + } } } diff --git a/ui/viewercontainer.h b/ui/viewercontainer.h index 2d2bdd0b6..c33a65ac6 100644 --- a/ui/viewercontainer.h +++ b/ui/viewercontainer.h @@ -2,6 +2,7 @@ #define VIEWERCONTAINER_H #include +class ViewerWidget; class ViewerContainer : public QWidget { @@ -9,7 +10,7 @@ class ViewerContainer : public QWidget public: explicit ViewerContainer(QWidget *parent = 0); float aspect_ratio; - QWidget* child; + ViewerWidget* child; void adjust(); protected: diff --git a/ui/viewerwidget.cpp b/ui/viewerwidget.cpp index d0730a725..53c3c47ee 100644 --- a/ui/viewerwidget.cpp +++ b/ui/viewerwidget.cpp @@ -43,7 +43,9 @@ ViewerWidget::ViewerWidget(QWidget *parent) : default_fbo(NULL), waveform(false), dragging(false), - selected_gizmo(NULL) + selected_gizmo(NULL), + waveform_zoom(1.0), + waveform_scroll(0) { setMouseTracking(true); setFocusPolicy(Qt::ClickFocus); @@ -69,6 +71,13 @@ void ViewerWidget::delete_function() { } } +void ViewerWidget::set_waveform_scroll(int s) { + if (waveform) { + waveform_scroll = s; + update(); + } +} + void ViewerWidget::show_context_menu() { QMenu menu(this); @@ -141,7 +150,7 @@ void ViewerWidget::paintEvent(QPaintEvent *e) { } void ViewerWidget::seek_from_click(int x) { - viewer->seek(getFrameFromScreenPoint((double) width() / (double) waveform_clip->timeline_out, x)); + viewer->seek(getFrameFromScreenPoint(waveform_zoom, x+waveform_scroll)); } double get_timecode(Clip* c, long playhead) { @@ -765,23 +774,23 @@ void ViewerWidget::paintGL() { compose_sequence(nests, render_audio); if (waveform) { - double waveform_zoom = (double) waveform_ms->audio_preview.size() / (double) width(); - double timeline_zoom = (double) width() / (double) waveform_clip->timeline_out; - QPainter p(this); if (viewer->seq->using_workarea) { - int in_x = getScreenPointFromFrame(timeline_zoom, viewer->seq->workarea_in); - int out_x = getScreenPointFromFrame(timeline_zoom, viewer->seq->workarea_out); + int in_x = getScreenPointFromFrame(waveform_zoom, viewer->seq->workarea_in) - waveform_scroll; + int out_x = getScreenPointFromFrame(waveform_zoom, viewer->seq->workarea_out) - waveform_scroll; p.fillRect(QRect(in_x, 0, out_x - in_x, height()), QColor(255, 255, 255, 64)); p.setPen(Qt::white); p.drawLine(in_x, 0, in_x, height()); p.drawLine(out_x, 0, out_x, height()); } + QRect wr = rect(); + wr.setX(wr.x() - waveform_scroll); + p.setPen(Qt::green); - draw_waveform(waveform_clip, waveform_ms, waveform_clip->timeline_out, &p, rect(), 0, width(), waveform_zoom); + draw_waveform(waveform_clip, waveform_ms, waveform_clip->timeline_out, &p, wr, waveform_scroll, width()+waveform_scroll, waveform_zoom); p.setPen(Qt::red); - int playhead_x = getScreenPointFromFrame(timeline_zoom, viewer->seq->playhead); + int playhead_x = getScreenPointFromFrame(waveform_zoom, viewer->seq->playhead) - waveform_scroll; p.drawLine(playhead_x, 0, playhead_x, height()); } diff --git a/ui/viewerwidget.h b/ui/viewerwidget.h index 1b7abc7d5..d7b9bb859 100644 --- a/ui/viewerwidget.h +++ b/ui/viewerwidget.h @@ -33,10 +33,13 @@ public: bool waveform; Clip* waveform_clip; MediaStream* waveform_ms; + double waveform_zoom; + int waveform_scroll; bool force_quit; public slots: void delete_function(); + void set_waveform_scroll(int s); protected: void paintEvent(QPaintEvent *e); // void resizeGL(int w, int h); From 25e4bd9d8d3b87eb486e06e6e4af992b142831ca Mon Sep 17 00:00:00 2001 From: itsmattkc Date: Sun, 9 Dec 2018 15:44:17 +1100 Subject: [PATCH 4/5] added routines for alpha channel editing --- olive.pro | 392 +++++++++++++++++++++--------------------- playback/playback.cpp | 29 +++- playback/playback.h | 1 + project/effect.cpp | 25 +-- project/effect.h | 4 +- project/effectgizmo.h | 2 + ui/viewerwidget.cpp | 22 ++- 7 files changed, 263 insertions(+), 212 deletions(-) diff --git a/olive.pro b/olive.pro index 52a855dab..78d642345 100644 --- a/olive.pro +++ b/olive.pro @@ -1,195 +1,197 @@ -#------------------------------------------------- -# -# 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/timecodeeffect.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/timecodeeffect.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 +#------------------------------------------------- +# +# 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/timecodeeffect.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 \ + effects/internal/maskeffect.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/timecodeeffect.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 \ + effects/internal/maskeffect.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/playback/playback.cpp b/playback/playback.cpp index 638a4ec43..c8295e0ba 100644 --- a/playback/playback.cpp +++ b/playback/playback.cpp @@ -111,6 +111,10 @@ void cache_clip(Clip* clip, long playhead, bool reset, bool scrubbing, QVectorget_timeline_in_with_transition()+c->get_clip_in_with_transition())/(double)c->sequence->frame_rate); +} + void get_clip_frame(Clip* c, long playhead) { if (c->finished_opening) { MediaStream* ms = static_cast(c->media)->get_stream_from_file_index(c->track < 0, c->media_stream); @@ -220,8 +224,29 @@ void get_clip_frame(Clip* c, long playhead) { if (target_frame != NULL) { // add gate if this is the same frame - glPixelStorei(GL_UNPACK_ROW_LENGTH, target_frame->linesize[0]/4); - c->texture->setData(0, QOpenGLTexture::RGBA, QOpenGLTexture::UInt8, target_frame->data[0]); + glPixelStorei(GL_UNPACK_ROW_LENGTH, target_frame->linesize[0]/4); + + bool copied = false; + uint8_t* data = target_frame->data[0]; + int frame_size; + + for (int i=0;ieffects.size();i++) { + Effect* e = c->effects.at(i); + if (e->enable_image) { + if (!copied) { + frame_size = target_frame->linesize[0]*target_frame->height; + data = new uint8_t[frame_size]; + memcpy(data, target_frame->data[0], frame_size); + copied = true; + } + e->process_image(get_timecode(c, playhead), data, frame_size); + } + } + + c->texture->setData(0, QOpenGLTexture::RGBA, QOpenGLTexture::UInt8, data); + + if (copied) delete [] data; + glPixelStorei(GL_UNPACK_ROW_LENGTH, 0); } diff --git a/playback/playback.h b/playback/playback.h index af1d742f6..ba7062a2a 100644 --- a/playback/playback.h +++ b/playback/playback.h @@ -20,6 +20,7 @@ void cache_video_worker(Clip* c, long playhead); void handle_media(Sequence* sequence, long playhead, bool multithreaded); void reset_cache(Clip* c, long target_frame); void get_clip_frame(Clip* c, long playhead); +double get_timecode(Clip* c, long playhead); long playhead_to_clip_frame(Clip* c, long playhead); double playhead_to_clip_seconds(Clip* c, long playhead); diff --git a/project/effect.cpp b/project/effect.cpp index 8255631ce..7bee62a95 100644 --- a/project/effect.cpp +++ b/project/effect.cpp @@ -27,6 +27,7 @@ #include "effects/internal/paneffect.h" #include "effects/internal/shakeeffect.h" #include "effects/internal/cornerpineffect.h" +#include "effects/internal/maskeffect.h" #include #include @@ -59,6 +60,7 @@ Effect* create_effect(Clip* c, const EffectMeta* em) { case EFFECT_INTERNAL_TONE: return new ToneEffect(c, em); case EFFECT_INTERNAL_SHAKE: return new ShakeEffect(c, em); case EFFECT_INTERNAL_CORNERPIN: return new CornerPinEffect(c, em); + case EFFECT_INTERNAL_MASK: return new MaskEffect(c, em); } } else { dout << "[ERROR] Invalid effect data"; @@ -107,8 +109,15 @@ void load_internal_effects() { effects.append(em); em.name = "Corner Pin"; - em.category = "Distort"; em.internal = EFFECT_INTERNAL_CORNERPIN; + effects.append(em); + + em.name = "Mask"; + em.internal = EFFECT_INTERNAL_MASK; + effects.append(em); + + em.name = "Shake"; + em.internal = EFFECT_INTERNAL_SHAKE; effects.append(em); em.name = "Text"; @@ -117,20 +126,13 @@ void load_internal_effects() { effects.append(em); em.name = "Timecode"; - em.category = "Render"; em.internal = EFFECT_INTERNAL_TIMECODE; effects.append(em); - em.name = "Solid"; - em.category = "Render"; + em.name = "Solid"; em.internal = EFFECT_INTERNAL_SOLID; effects.append(em); - em.name = "Shake"; - em.category = "Distort"; - em.internal = EFFECT_INTERNAL_SHAKE; - effects.append(em); - // internal transitions em.type = EFFECT_TYPE_TRANSITION; em.category = ""; @@ -230,6 +232,7 @@ Effect::Effect(Clip* c, const EffectMeta *em) : enable_shader(false), enable_coords(false), enable_superimpose(false), + enable_image(false), glslProgram(NULL), texture(NULL), isOpen(false), @@ -767,9 +770,11 @@ void Effect::startEffect() { void Effect::endEffect() { if (bound) glslProgram->release(); - bound = false; + bound = false; } +void Effect::process_image(double, uint8_t *, int) {} + Effect* Effect::copy(Clip* c) { Effect* copy = create_effect(c, meta); copy->set_enabled(is_enabled()); diff --git a/project/effect.h b/project/effect.h index 4f15a4123..08fcc13b4 100644 --- a/project/effect.h +++ b/project/effect.h @@ -62,7 +62,7 @@ extern QMutex effects_loaded; #define EFFECT_INTERNAL_TONE 6 #define EFFECT_INTERNAL_SHAKE 7 #define EFFECT_INTERNAL_TIMECODE 8 - +#define EFFECT_INTERNAL_MASK 9 #define EFFECT_INTERNAL_CORNERPIN 12 @@ -147,12 +147,14 @@ public: bool enable_shader; bool enable_coords; bool enable_superimpose; + bool enable_image; int getIterations(); void setIterations(int i); const char* ffmpeg_filter; + virtual void process_image(double timecode, uint8_t* data, int size); virtual void process_shader(double timecode, GLTextureCoords&); virtual void process_coords(double timecode, GLTextureCoords& coords, int data); virtual GLuint process_superimpose(double timecode); diff --git a/project/effectgizmo.h b/project/effectgizmo.h index befe4bcd3..ec10f4b09 100644 --- a/project/effectgizmo.h +++ b/project/effectgizmo.h @@ -3,8 +3,10 @@ #define GIZMO_TYPE_DOT 0 #define GIZMO_TYPE_POLY 1 +#define GIZMO_TYPE_TARGET 2 #define GIZMO_DOT_SIZE 2.5F +#define GIZMO_TARGET_SIZE 5.0F #include #include diff --git a/ui/viewerwidget.cpp b/ui/viewerwidget.cpp index 53c3c47ee..81e22ae7e 100644 --- a/ui/viewerwidget.cpp +++ b/ui/viewerwidget.cpp @@ -153,15 +153,12 @@ void ViewerWidget::seek_from_click(int x) { viewer->seek(getFrameFromScreenPoint(waveform_zoom, x+waveform_scroll)); } -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) viewer->seq->width / (double) width(); QPoint mouse_pos(qRound(x*multiplier), qRound(y*multiplier)); int dot_size = 2 * qRound(GIZMO_DOT_SIZE * multiplier); + int target_size = 2 * qRound(GIZMO_TARGET_SIZE * multiplier); for (int i=0;igizmo_count();i++) { EffectGizmo* g = gizmos->gizmo(i); @@ -179,6 +176,14 @@ EffectGizmo* ViewerWidget::get_gizmo_from_mouse(int x, int y) { return g; } break; + case GIZMO_TYPE_TARGET: + if (mouse_pos.x() > g->screen_pos[0].x() - target_size + && mouse_pos.y() > g->screen_pos[0].y() - target_size + && mouse_pos.x() < g->screen_pos[0].x() + target_size + && mouse_pos.y() < g->screen_pos[0].y() + target_size) { + return g; + } + break; } } @@ -813,6 +818,7 @@ void ViewerWidget::paintGL() { glGetFloatv(GL_CURRENT_COLOR, color); float dot_size = GIZMO_DOT_SIZE / width() * viewer->seq->width; + float target_size = GIZMO_TARGET_SIZE / width() * viewer->seq->width; glPushMatrix(); glLoadIdentity(); @@ -840,6 +846,14 @@ void ViewerWidget::paintGL() { glVertex3f(g->screen_pos[0].x(), g->screen_pos[0].y(), gizmo_z); glEnd(); break; + case GIZMO_TYPE_DOT: // draw target + glBegin(GL_QUADS); + glVertex3f(g->screen_pos[0].x()-target_size, g->screen_pos[0].y()-target_size, gizmo_z); + glVertex3f(g->screen_pos[0].x()+target_size, g->screen_pos[0].y()-target_size, gizmo_z); + glVertex3f(g->screen_pos[0].x()+target_size, g->screen_pos[0].y()+target_size, gizmo_z); + glVertex3f(g->screen_pos[0].x()-target_size, g->screen_pos[0].y()+target_size, gizmo_z); + glEnd(); + break; } } glPopMatrix(); From 3e57e06542774ed6758e89951d86765f4f55d028 Mon Sep 17 00:00:00 2001 From: itsmattkc Date: Sun, 9 Dec 2018 15:56:47 +1100 Subject: [PATCH 5/5] added gizmo for anchor point --- effects/internal/transformeffect.cpp | 5 +++++ effects/internal/transformeffect.h | 1 + ui/viewerwidget.cpp | 17 +++++++++++++++-- 3 files changed, 21 insertions(+), 2 deletions(-) diff --git a/effects/internal/transformeffect.cpp b/effects/internal/transformeffect.cpp index b83aef23f..5ece40f36 100644 --- a/effects/internal/transformeffect.cpp +++ b/effects/internal/transformeffect.cpp @@ -98,6 +98,11 @@ TransformEffect::TransformEffect(Clip* c, const EffectMeta* em) : Effect(c, em) right_center_gizmo->set_cursor(Qt::SizeHorCursor); right_center_gizmo->x_field = scale_x; + anchor_gizmo = add_gizmo(GIZMO_TYPE_TARGET); + anchor_gizmo->set_cursor(Qt::SizeAllCursor); + anchor_gizmo->x_field = anchor_x_box; + anchor_gizmo->y_field = anchor_y_box; + rotate_gizmo = add_gizmo(GIZMO_TYPE_DOT); rotate_gizmo->color = Qt::green; rotate_gizmo->set_cursor(Qt::SizeAllCursor); diff --git a/effects/internal/transformeffect.h b/effects/internal/transformeffect.h index 7fc635ad2..c198ffb0a 100644 --- a/effects/internal/transformeffect.h +++ b/effects/internal/transformeffect.h @@ -33,6 +33,7 @@ private: EffectGizmo* bottom_right_gizmo; EffectGizmo* left_center_gizmo; EffectGizmo* right_center_gizmo; + EffectGizmo* anchor_gizmo; EffectGizmo* rotate_gizmo; EffectGizmo* rect_gizmo; diff --git a/ui/viewerwidget.cpp b/ui/viewerwidget.cpp index 81e22ae7e..3fcc8dd4d 100644 --- a/ui/viewerwidget.cpp +++ b/ui/viewerwidget.cpp @@ -846,12 +846,25 @@ void ViewerWidget::paintGL() { glVertex3f(g->screen_pos[0].x(), g->screen_pos[0].y(), gizmo_z); glEnd(); break; - case GIZMO_TYPE_DOT: // draw target - glBegin(GL_QUADS); + case GIZMO_TYPE_TARGET: // draw target + glBegin(GL_LINES); glVertex3f(g->screen_pos[0].x()-target_size, g->screen_pos[0].y()-target_size, gizmo_z); glVertex3f(g->screen_pos[0].x()+target_size, g->screen_pos[0].y()-target_size, gizmo_z); + + glVertex3f(g->screen_pos[0].x()+target_size, g->screen_pos[0].y()-target_size, gizmo_z); + glVertex3f(g->screen_pos[0].x()+target_size, g->screen_pos[0].y()+target_size, gizmo_z); + glVertex3f(g->screen_pos[0].x()+target_size, g->screen_pos[0].y()+target_size, gizmo_z); glVertex3f(g->screen_pos[0].x()-target_size, g->screen_pos[0].y()+target_size, gizmo_z); + + glVertex3f(g->screen_pos[0].x()-target_size, g->screen_pos[0].y()+target_size, gizmo_z); + glVertex3f(g->screen_pos[0].x()-target_size, g->screen_pos[0].y()-target_size, gizmo_z); + + glVertex3f(g->screen_pos[0].x()-target_size, g->screen_pos[0].y(), gizmo_z); + glVertex3f(g->screen_pos[0].x()+target_size, g->screen_pos[0].y(), gizmo_z); + + glVertex3f(g->screen_pos[0].x(), g->screen_pos[0].y()-target_size, gizmo_z); + glVertex3f(g->screen_pos[0].x(), g->screen_pos[0].y()+target_size, gizmo_z); glEnd(); break; }