From 1ee9451343313e38b199b2a21d14df8815f9e706 Mon Sep 17 00:00:00 2001 From: itsmattkc Date: Thu, 27 Dec 2018 10:29:02 +1100 Subject: [PATCH] implemented hold keyframe and began new panel --- mainwindow.cpp | 21 +++++---------------- olive.pro | 8 ++++++-- panels/grapheditor.cpp | 31 +++++++++++++++++++++++++++++++ panels/grapheditor.h | 16 ++++++++++++++++ panels/panels.cpp | 35 ++++++++++++++++++++++++++++++----- panels/panels.h | 6 ++++++ project/effect.h | 4 ++-- project/effectfield.cpp | 13 +++++++++---- ui/graphview.cpp | 13 +++++++++++++ ui/graphview.h | 13 +++++++++++++ ui/keyframeview.cpp | 31 ++++++++++++++++++++++--------- 11 files changed, 153 insertions(+), 38 deletions(-) create mode 100644 panels/grapheditor.cpp create mode 100644 panels/grapheditor.h create mode 100644 ui/graphview.cpp create mode 100644 ui/graphview.h diff --git a/mainwindow.cpp b/mainwindow.cpp index 738e7c9b6..8cd2f0972 100644 --- a/mainwindow.cpp +++ b/mainwindow.cpp @@ -18,6 +18,7 @@ #include "panels/effectcontrols.h" #include "panels/viewer.h" #include "panels/timeline.h" +#include "panels/grapheditor.h" #include "dialogs/aboutdialog.h" #include "dialogs/newsequencedialog.h" @@ -57,6 +58,7 @@ void MainWindow::setup_layout(bool reset) { panel_footage_viewer->show(); panel_sequence_viewer->show(); panel_timeline->show(); + panel_graph_editor->hide(); bool load_default = true; @@ -77,6 +79,7 @@ void MainWindow::setup_layout(bool reset) { panel_footage_viewer->raise(); addDockWidget(Qt::TopDockWidgetArea, panel_sequence_viewer); addDockWidget(Qt::BottomDockWidgetArea, panel_timeline); + panel_graph_editor->setFloating(true); // workaround for strange Qt dock bug (see https://bugreports.qt.io/browse/QTBUG-65592) #if QT_VERSION >= QT_VERSION_CHECK(5, 6, 0) @@ -194,12 +197,7 @@ MainWindow::MainWindow(QWidget *parent) : } } - // TODO maybe replace these with non-pointers later on? - panel_sequence_viewer = new Viewer(this); - panel_footage_viewer = new Viewer(this); - panel_project = new Project(this); - panel_effect_controls = new EffectControls(this); - panel_timeline = new Timeline(this); + alloc_panels(this); if (!data_dir.isEmpty()) { // detect auto-recovery file @@ -259,16 +257,7 @@ MainWindow::~MainWindow() { delete ui; - delete panel_sequence_viewer; - panel_sequence_viewer = NULL; - delete panel_footage_viewer; - panel_footage_viewer = NULL; - delete panel_project; - panel_project = NULL; - delete panel_effect_controls; - panel_effect_controls = NULL; - delete panel_timeline; - panel_timeline = NULL; + free_panels(); close_debug(); } diff --git a/olive.pro b/olive.pro index 650aedb28..eab6b3b19 100644 --- a/olive.pro +++ b/olive.pro @@ -105,7 +105,9 @@ SOURCES += \ ui/resizablescrollbar.cpp \ ui/sourceiconview.cpp \ project/sourcescommon.cpp \ - ui/keyframenavigator.cpp + ui/keyframenavigator.cpp \ + panels/grapheditor.cpp \ + ui/graphview.cpp HEADERS += \ mainwindow.h \ @@ -185,7 +187,9 @@ HEADERS += \ ui/resizablescrollbar.h \ ui/sourceiconview.h \ project/sourcescommon.h \ - ui/keyframenavigator.h + ui/keyframenavigator.h \ + panels/grapheditor.h \ + ui/graphview.h FORMS += \ mainwindow.ui \ diff --git a/panels/grapheditor.cpp b/panels/grapheditor.cpp new file mode 100644 index 000000000..ef2f1fdd2 --- /dev/null +++ b/panels/grapheditor.cpp @@ -0,0 +1,31 @@ +#include "grapheditor.h" + +#include +#include +#include + +#include "ui/graphview.h" + +GraphEditor::GraphEditor(QWidget* parent) : QDockWidget(parent) { + setWindowTitle("Graph Editor"); + + QWidget* central_widget = new QWidget(); + setWidget(central_widget); + + QVBoxLayout* layout = new QVBoxLayout(); + central_widget->setLayout(layout); + + QHBoxLayout* tools = new QHBoxLayout(); + tools->addWidget(new QPushButton("HECK!")); + layout->addLayout(tools); + + view = new GraphView(); + layout->addWidget(view); + + QHBoxLayout* values = new QHBoxLayout(); + values->addStretch(); + values->addWidget(new QLabel("1920.0")); + values->addWidget(new QLabel("1080.0")); + values->addStretch(); + layout->addLayout(values); +} diff --git a/panels/grapheditor.h b/panels/grapheditor.h new file mode 100644 index 000000000..5e4a919cf --- /dev/null +++ b/panels/grapheditor.h @@ -0,0 +1,16 @@ +#ifndef GRAPHEDITOR_H +#define GRAPHEDITOR_H + +#include + +class GraphView; + +class GraphEditor : public QDockWidget { + Q_OBJECT +public: + GraphEditor(QWidget* parent = 0); +private: + GraphView* view; +}; + +#endif // GRAPHEDITOR_H diff --git a/panels/panels.cpp b/panels/panels.cpp index dd8206ccc..fcc9e0008 100644 --- a/panels/panels.cpp +++ b/panels/panels.cpp @@ -8,6 +8,7 @@ #include "project/clip.h" #include "project/transition.h" #include "io/config.h" +#include "grapheditor.h" #include "debug.h" Project* panel_project = 0; @@ -15,6 +16,7 @@ EffectControls* panel_effect_controls = 0; Viewer* panel_sequence_viewer = 0; Viewer* panel_footage_viewer = 0; Timeline* panel_timeline = 0; +GraphEditor* panel_graph_editor = 0; void update_effect_controls() { // SEND CLIPS TO EFFECT CONTROLS @@ -110,15 +112,15 @@ void update_ui(bool modified) { QDockWidget *get_focused_panel() { QDockWidget* w = NULL; if (config.hover_focus) { - if (panel_project->rect().contains(panel_project->mapFromGlobal(QCursor::pos()))) { + if (panel_project->underMouse()) { w = panel_project; - } else if (panel_effect_controls->rect().contains(panel_effect_controls->mapFromGlobal(QCursor::pos()))) { + } else if (panel_effect_controls->underMouse()) { w = panel_effect_controls; - } else if (panel_sequence_viewer->rect().contains(panel_sequence_viewer->mapFromGlobal(QCursor::pos()))) { + } else if (panel_sequence_viewer->underMouse()) { w = panel_sequence_viewer; - } else if (panel_footage_viewer->rect().contains(panel_footage_viewer->mapFromGlobal(QCursor::pos()))) { + } else if (panel_footage_viewer->underMouse()) { w = panel_footage_viewer; - } else if (panel_timeline->rect().contains(panel_timeline->mapFromGlobal(QCursor::pos()))) { + } else if (panel_timeline->underMouse()) { w = panel_timeline; } } @@ -137,3 +139,26 @@ QDockWidget *get_focused_panel() { } return w; } + +void alloc_panels(QWidget* parent) { + // TODO maybe replace these with non-pointers later on? + panel_sequence_viewer = new Viewer(parent); + panel_footage_viewer = new Viewer(parent); + panel_project = new Project(parent); + panel_effect_controls = new EffectControls(parent); + panel_timeline = new Timeline(parent); + panel_graph_editor = new GraphEditor(parent); +} + +void free_panels() { + delete panel_sequence_viewer; + panel_sequence_viewer = NULL; + delete panel_footage_viewer; + panel_footage_viewer = NULL; + delete panel_project; + panel_project = NULL; + delete panel_effect_controls; + panel_effect_controls = NULL; + delete panel_timeline; + panel_timeline = NULL; +} diff --git a/panels/panels.h b/panels/panels.h index 042a652d8..691736b82 100644 --- a/panels/panels.h +++ b/panels/panels.h @@ -5,6 +5,9 @@ class Project; class EffectControls; class Viewer; class Timeline; +class GraphEditor; + +class QWidget; class QDockWidget; extern Project* panel_project; @@ -12,8 +15,11 @@ extern EffectControls* panel_effect_controls; extern Viewer* panel_sequence_viewer; extern Viewer* panel_footage_viewer; extern Timeline* panel_timeline; +extern GraphEditor* panel_graph_editor; void update_ui(bool modified); QDockWidget* get_focused_panel(); +void alloc_panels(QWidget *parent); +void free_panels(); #endif // PANELS_H diff --git a/project/effect.h b/project/effect.h index 08fcc13b4..572baf7a9 100644 --- a/project/effect.h +++ b/project/effect.h @@ -69,8 +69,8 @@ extern QMutex effects_loaded; #define EFFECT_INTERNAL_COUNT 13 #define KEYFRAME_TYPE_LINEAR 0 -#define KEYFRAME_TYPE_SMOOTH 1 -#define KEYFRAME_TYPE_BEZIER 2 +#define KEYFRAME_TYPE_BEZIER 1 +#define KEYFRAME_TYPE_HOLD 2 struct GLTextureCoords { int grid_size; diff --git a/project/effectfield.cpp b/project/effectfield.cpp index d2166a835..2caaf2991 100644 --- a/project/effectfield.cpp +++ b/project/effectfield.cpp @@ -140,7 +140,12 @@ void EffectField::get_keyframe_data(double timecode, int &before, int &after, do before = before_keyframe_index; after = after_keyframe_index; - progress = (timecode-frameToTimecode(before_keyframe_time))/(frameToTimecode(after_keyframe_time)-frameToTimecode(before_keyframe_time)); + if (parent_row->keyframe_types.at(before) == KEYFRAME_TYPE_HOLD) { + progress = 0; + } else { + // TODO replace with bezier function + progress = (timecode-frameToTimecode(before_keyframe_time))/(frameToTimecode(after_keyframe_time)-frameToTimecode(before_keyframe_time)); + } } else if (before_keyframe_index > -1) { before = before_keyframe_index; after = before_keyframe_index; @@ -161,13 +166,13 @@ QVariant EffectField::validate_keyframe_data(double timecode, bool async) { double progress; get_keyframe_data(timecode, before_keyframe, after_keyframe, progress); - int kf_type = (progress < 0.5) ? parent_row->keyframe_types.at(before_keyframe) : parent_row->keyframe_types.at(after_keyframe); - if (kf_type == KEYFRAME_TYPE_SMOOTH) { + /*int kf_type = (progress < 0.5) ? parent_row->keyframe_types.at(before_keyframe) : parent_row->keyframe_types.at(after_keyframe); + if (kf_type == KEYFRAME_TYPE_BEZIER) { double x = (8.0 * progress) - 4.0; progress = 1.0 / (1.0 + qPow(M_E, -x)); progress *= 1.0373; progress -= 0.01865; - } + }*/ const QVariant& before_data = keyframe_data.at(before_keyframe); switch (type) { diff --git a/ui/graphview.cpp b/ui/graphview.cpp new file mode 100644 index 000000000..405663889 --- /dev/null +++ b/ui/graphview.cpp @@ -0,0 +1,13 @@ +#include "graphview.h" + +#include + +GraphView::GraphView(QWidget* parent) {} + +void GraphView::paintEvent(QPaintEvent *event) { + QPainter p(this); + + p.setPen(Qt::white); + + p.drawRect(rect()); +} diff --git a/ui/graphview.h b/ui/graphview.h new file mode 100644 index 000000000..b28d80bf9 --- /dev/null +++ b/ui/graphview.h @@ -0,0 +1,13 @@ +#ifndef GRAPHVIEW_H +#define GRAPHVIEW_H + +#include + +class GraphView : public QWidget { +public: + GraphView(QWidget* parent = 0); + + void paintEvent(QPaintEvent *event); +}; + +#endif // GRAPHVIEW_H diff --git a/ui/keyframeview.cpp b/ui/keyframeview.cpp index c46dcb0c2..431d9ab03 100644 --- a/ui/keyframeview.cpp +++ b/ui/keyframeview.cpp @@ -11,6 +11,7 @@ #include "panels/viewer.h" #include "ui/viewerwidget.h" #include "project/sequence.h" +#include "panels/grapheditor.h" #include "ui_effectcontrols.h" #include @@ -47,24 +48,33 @@ KeyframeView::KeyframeView(QWidget *parent) : void KeyframeView::show_context_menu(const QPoint& pos) { if (selected_rows.size() > 0) { QMenu menu(this); + QAction* linear = menu.addAction("Linear"); linear->setData(KEYFRAME_TYPE_LINEAR); QAction* smooth = menu.addAction("Smooth"); - smooth->setData(KEYFRAME_TYPE_SMOOTH); - /*QAction* bezier = menu.addAction("Bezier"); - bezier->setData(KEYFRAME_TYPE_BEZIER);*/ + smooth->setData(KEYFRAME_TYPE_BEZIER); + QAction* hold = menu.addAction("Hold"); + hold->setData(KEYFRAME_TYPE_HOLD); + menu.addSeparator(); + menu.addAction("Graph Editor"); + connect(&menu, SIGNAL(triggered(QAction*)), this, SLOT(menu_set_key_type(QAction*))); menu.exec(mapToGlobal(pos)); } } void KeyframeView::menu_set_key_type(QAction* a) { - ComboAction* ca = new ComboAction(); - for (int i=0;iappend(new SetInt(&selected_rows.at(i)->keyframe_types[selected_keyframes.at(i)], a->data().toInt())); + if (a->data().isNull()) { + // load graph editor + panel_graph_editor->show(); + } else { + ComboAction* ca = new ComboAction(); + for (int i=0;iappend(new SetInt(&selected_rows.at(i)->keyframe_types[selected_keyframes.at(i)], a->data().toInt())); + } + undo_stack.push(ca); + update(); } - undo_stack.push(ca); - update(); } void KeyframeView::paintEvent(QPaintEvent*) { @@ -184,9 +194,12 @@ void KeyframeView::draw_keyframe(QPainter &p, int type, int x, int y, bool darke p.drawPolygon(points, KEYFRAME_POINT_COUNT); } break; - case KEYFRAME_TYPE_SMOOTH: + case KEYFRAME_TYPE_BEZIER: p.drawEllipse(QPoint(x, y), KEYFRAME_SIZE, KEYFRAME_SIZE); break; + case KEYFRAME_TYPE_HOLD: + p.drawRect(QRect(x - KEYFRAME_SIZE, y - KEYFRAME_SIZE, KEYFRAME_SIZE*2, KEYFRAME_SIZE*2)); + break; } }