diff --git a/app/panel/curve/curve.cpp b/app/panel/curve/curve.cpp
index 48223f277..165a332c8 100644
--- a/app/panel/curve/curve.cpp
+++ b/app/panel/curve/curve.cpp
@@ -6,6 +6,10 @@ CurvePanel::CurvePanel(QWidget *parent) :
// FIXME: This won't work if there's ever more than one of this panel
setObjectName("CurvePanel");
+ // Create main widget and set it
+ widget_ = new CurveWidget();
+ setWidget(widget_);
+
// Set strings
Retranslate();
}
diff --git a/app/panel/curve/curve.h b/app/panel/curve/curve.h
index d793b610d..ecdee580d 100644
--- a/app/panel/curve/curve.h
+++ b/app/panel/curve/curve.h
@@ -1,6 +1,7 @@
#ifndef CURVEPANEL_H
#define CURVEPANEL_H
+#include "widget/curvewidget/curvewidget.h"
#include "widget/panel/panel.h"
class CurvePanel : public PanelWidget
@@ -14,6 +15,8 @@ protected:
private:
void Retranslate();
+ CurveWidget* widget_;
+
};
#endif // CURVEPANEL_H
diff --git a/app/widget/CMakeLists.txt b/app/widget/CMakeLists.txt
index 1de01521b..4ae18ef53 100644
--- a/app/widget/CMakeLists.txt
+++ b/app/widget/CMakeLists.txt
@@ -17,6 +17,7 @@
add_subdirectory(audiomonitor)
add_subdirectory(clickablelabel)
add_subdirectory(columnedgridlayout)
+add_subdirectory(curvewidget)
add_subdirectory(flowlayout)
add_subdirectory(focusablelineedit)
add_subdirectory(footagecombobox)
diff --git a/app/widget/curveview/curveview.cpp b/app/widget/curveview/curveview.cpp
deleted file mode 100644
index dfa49d5c3..000000000
--- a/app/widget/curveview/curveview.cpp
+++ /dev/null
@@ -1,6 +0,0 @@
-#include "curveview.h"
-
-CurveView::CurveView()
-{
-
-}
diff --git a/app/widget/curveview/curveview.h b/app/widget/curveview/curveview.h
deleted file mode 100644
index 757b240dd..000000000
--- a/app/widget/curveview/curveview.h
+++ /dev/null
@@ -1,11 +0,0 @@
-#ifndef CURVEVIEW_H
-#define CURVEVIEW_H
-
-
-class CurveView
-{
-public:
- CurveView();
-};
-
-#endif // CURVEVIEW_H
diff --git a/app/widget/curvewidget/CMakeLists.txt b/app/widget/curvewidget/CMakeLists.txt
new file mode 100644
index 000000000..69be102f4
--- /dev/null
+++ b/app/widget/curvewidget/CMakeLists.txt
@@ -0,0 +1,24 @@
+# Olive - Non-Linear Video Editor
+# Copyright (C) 2019 Olive Team
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see .
+
+set(OLIVE_SOURCES
+ ${OLIVE_SOURCES}
+ widget/curvewidget/curveview.h
+ widget/curvewidget/curveview.cpp
+ widget/curvewidget/curvewidget.h
+ widget/curvewidget/curvewidget.cpp
+ PARENT_SCOPE
+)
diff --git a/app/widget/curvewidget/curveview.cpp b/app/widget/curvewidget/curveview.cpp
index dfa49d5c3..4f32d18e7 100644
--- a/app/widget/curvewidget/curveview.cpp
+++ b/app/widget/curvewidget/curveview.cpp
@@ -1,6 +1,45 @@
#include "curveview.h"
-CurveView::CurveView()
-{
+#include
+#include "common/qtversionabstraction.h"
+
+CurveView::CurveView(QWidget *parent) :
+ TimelineViewBase(parent)
+{
+ setAlignment(Qt::AlignLeft | Qt::AlignBottom);
+ setDragMode(RubberBandDrag);
+ setViewportUpdateMode(FullViewportUpdate);
+
+ text_padding_ = QFontMetricsWidth(fontMetrics(), QStringLiteral("i"));
+}
+
+void CurveView::drawBackground(QPainter *painter, const QRectF &rect)
+{
+ QVector lines;
+
+ //painter->setPen(palette().window().color());
+
+ int grid_interval = 100;
+
+ int x_start = qCeil(rect.left() / grid_interval) * grid_interval;
+ int y_start = qCeil(rect.top() / grid_interval) * grid_interval;
+
+ QPoint viewport_edges(0, qRound(rect.height()));
+ QPointF scene_edges = mapToScene(viewport_edges);
+ //QRectF scene_edges = mapToScene(viewport()->geometry()).boundingRect();
+
+ // Add vertical lines
+ for (int i=x_start;idrawText(i + text_padding_, qRound(scene_edges.y()) - text_padding_, QString::number(i));
+ lines.append(QLine(i, qRound(rect.top()), i, qRound(rect.bottom())));
+ }
+
+ // Add horizontal lines
+ for (int i=y_start;idrawText(qRound(scene_edges.x()) + text_padding_, i - text_padding_, QString::number(-i));
+ lines.append(QLine(qRound(rect.left()), i, qRound(rect.right()), i));
+ }
+
+ painter->drawLines(lines);
}
diff --git a/app/widget/curvewidget/curveview.h b/app/widget/curvewidget/curveview.h
index 757b240dd..8f8ada0f9 100644
--- a/app/widget/curvewidget/curveview.h
+++ b/app/widget/curvewidget/curveview.h
@@ -1,11 +1,19 @@
#ifndef CURVEVIEW_H
#define CURVEVIEW_H
+#include "widget/timelinewidget/view/timelineviewbase.h"
-class CurveView
+class CurveView : public TimelineViewBase
{
public:
- CurveView();
+ CurveView(QWidget* parent = nullptr);
+
+protected:
+ virtual void drawBackground(QPainter* painter, const QRectF& rect) override;
+
+private:
+ int text_padding_;
+
};
#endif // CURVEVIEW_H
diff --git a/app/widget/curvewidget/curvewidget.cpp b/app/widget/curvewidget/curvewidget.cpp
new file mode 100644
index 000000000..5cdeb1e7f
--- /dev/null
+++ b/app/widget/curvewidget/curvewidget.cpp
@@ -0,0 +1,45 @@
+#include "curvewidget.h"
+
+#include
+#include
+
+#include "widget/nodeparamview/nodeparamviewkeyframecontrol.h"
+
+CurveWidget::CurveWidget(QWidget *parent) :
+ QWidget(parent)
+{
+ QVBoxLayout* layout = new QVBoxLayout(this);
+
+ QHBoxLayout* top_controls = new QHBoxLayout();
+
+ NodeParamViewKeyframeControl* key_controls = new NodeParamViewKeyframeControl(false);
+ key_controls->SetEnableButtonVisible(false);
+ key_controls->SetPreviousButtonEnabled(false);
+ key_controls->SetToggleButtonEnabled(false);
+ key_controls->SetNextButtonEnabled(false);
+ top_controls->addWidget(key_controls);
+
+ top_controls->addStretch();
+
+ linear_button_ = new QPushButton(tr("Linear"));
+ linear_button_->setCheckable(true);
+ linear_button_->setEnabled(false);
+ top_controls->addWidget(linear_button_);
+
+ bezier_button_ = new QPushButton(tr("Bezier"));
+ bezier_button_->setCheckable(true);
+ bezier_button_->setEnabled(false);
+ top_controls->addWidget(bezier_button_);
+
+ hold_button_ = new QPushButton(tr("Hold"));
+ hold_button_->setCheckable(true);
+ hold_button_->setEnabled(false);
+ top_controls->addWidget(hold_button_);
+
+ layout->addLayout(top_controls);
+
+ view_ = new CurveView();
+ layout->addWidget(view_);
+
+ layout->addWidget(new QLabel("Values"));
+}
diff --git a/app/widget/curvewidget/curvewidget.h b/app/widget/curvewidget/curvewidget.h
new file mode 100644
index 000000000..21758e24d
--- /dev/null
+++ b/app/widget/curvewidget/curvewidget.h
@@ -0,0 +1,25 @@
+#ifndef CURVEWIDGET_H
+#define CURVEWIDGET_H
+
+#include
+#include
+
+#include "curveview.h"
+
+class CurveWidget : public QWidget
+{
+public:
+ CurveWidget(QWidget* parent = nullptr);
+
+private:
+ QPushButton* linear_button_;
+
+ QPushButton* bezier_button_;
+
+ QPushButton* hold_button_;
+
+ CurveView* view_;
+
+};
+
+#endif // CURVEWIDGET_H
diff --git a/app/widget/nodeparamview/nodeparamview.cpp b/app/widget/nodeparamview/nodeparamview.cpp
index d027629d1..6e4da7860 100644
--- a/app/widget/nodeparamview/nodeparamview.cpp
+++ b/app/widget/nodeparamview/nodeparamview.cpp
@@ -131,6 +131,8 @@ void NodeParamView::SetNodes(QList nodes)
connect(item, &NodeParamViewItem::RequestSetTime, this, &NodeParamView::ItemRequestedTimeChanged);
items_.append(item);
+
+ QTimer::singleShot(1, item, &NodeParamViewItem::SignalAllKeyframes);
}
if (!nodes_.isEmpty()) {
diff --git a/app/widget/nodeparamview/nodeparamviewitem.cpp b/app/widget/nodeparamview/nodeparamviewitem.cpp
index c3ea054d8..be4556e96 100644
--- a/app/widget/nodeparamview/nodeparamviewitem.cpp
+++ b/app/widget/nodeparamview/nodeparamviewitem.cpp
@@ -88,6 +88,19 @@ void NodeParamViewItem::SetTime(const rational &time)
}
}
+void NodeParamViewItem::SignalAllKeyframes()
+{
+ foreach (NodeParam* param, node_->parameters()) {
+ if (param->type() == NodeParam::kInput) {
+ NodeInput* input = static_cast(param);
+
+ foreach (NodeKeyframePtr key, input->keyframes()) {
+ InputAddedKeyframeInternal(input, key);
+ }
+ }
+ }
+}
+
void NodeParamViewItem::changeEvent(QEvent *e)
{
if (e->type() == QEvent::LanguageChange) {
@@ -146,7 +159,8 @@ void NodeParamViewItem::SetupUI()
// Hacky but effective way to make sure this widget is always as far right as possible
int control_column = 10;
- NodeParamViewKeyframeControl* key_control = new NodeParamViewKeyframeControl(input);
+ NodeParamViewKeyframeControl* key_control = new NodeParamViewKeyframeControl();
+ key_control->SetInput(input);
content_layout_->addWidget(key_control, row_count, control_column);
connect(key_control, &NodeParamViewKeyframeControl::KeyframeEnableChanged, this, &NodeParamViewItem::UserChangedKeyframeEnable);
connect(key_control, &NodeParamViewKeyframeControl::GoToPreviousKey, this, &NodeParamViewItem::GoToPreviousKey);
diff --git a/app/widget/nodeparamview/nodeparamviewitem.h b/app/widget/nodeparamview/nodeparamviewitem.h
index 824ddf011..7528db49e 100644
--- a/app/widget/nodeparamview/nodeparamviewitem.h
+++ b/app/widget/nodeparamview/nodeparamviewitem.h
@@ -47,6 +47,9 @@ public:
void SetTime(const rational& time);
+public slots:
+ void SignalAllKeyframes();
+
signals:
void KeyframeAdded(NodeKeyframePtr key, int y);
diff --git a/app/widget/nodeparamview/nodeparamviewkeyframecontrol.cpp b/app/widget/nodeparamview/nodeparamviewkeyframecontrol.cpp
index 72c28b8e0..66d9e26d4 100644
--- a/app/widget/nodeparamview/nodeparamviewkeyframecontrol.cpp
+++ b/app/widget/nodeparamview/nodeparamviewkeyframecontrol.cpp
@@ -4,16 +4,18 @@
#include "ui/icons/icons.h"
-NodeParamViewKeyframeControl::NodeParamViewKeyframeControl(NodeInput* input, QWidget *parent) :
+NodeParamViewKeyframeControl::NodeParamViewKeyframeControl(bool right_align, QWidget *parent) :
QWidget(parent),
- input_(input)
+ input_(nullptr)
{
QHBoxLayout* layout = new QHBoxLayout(this);
layout->setMargin(0);
layout->setSpacing(0);
- // Automatically right aligns all buttons
- layout->addStretch();
+ if (right_align) {
+ // Automatically right aligns all buttons
+ layout->addStretch();
+ }
prev_key_btn_ = CreateNewToolButton(icon::TriLeft);
prev_key_btn_->setIconSize(prev_key_btn_->iconSize() / 2);
@@ -38,10 +40,6 @@ NodeParamViewKeyframeControl::NodeParamViewKeyframeControl(NodeInput* input, QWi
connect(toggle_key_btn_, &QPushButton::toggled, this, &NodeParamViewKeyframeControl::KeyframeToggled);
connect(enable_key_btn_, &QPushButton::toggled, this, &NodeParamViewKeyframeControl::ShowButtonsFromKeyframeEnable);
connect(enable_key_btn_, &QPushButton::toggled, this, &NodeParamViewKeyframeControl::KeyframeEnableChanged);
- connect(input_, &NodeInput::KeyframeEnableChanged, this, &NodeParamViewKeyframeControl::SetKeyframeEnabled);
-
- // Pick up keyframing value
- ShowButtonsFromKeyframeEnable(input_->is_keyframing());
}
NodeInput *NodeParamViewKeyframeControl::GetConnectedInput() const
@@ -59,6 +57,11 @@ void NodeParamViewKeyframeControl::SetNextButtonEnabled(bool enabled)
next_key_btn_->setEnabled(enabled);
}
+void NodeParamViewKeyframeControl::SetToggleButtonEnabled(bool enable)
+{
+ toggle_key_btn_->setEnabled(enable);
+}
+
void NodeParamViewKeyframeControl::SetToggleButtonChecked(bool checked)
{
// Suppress KeyframeToggled() signal from this object
@@ -69,6 +72,27 @@ void NodeParamViewKeyframeControl::SetToggleButtonChecked(bool checked)
blockSignals(false);
}
+void NodeParamViewKeyframeControl::SetEnableButtonVisible(bool visible)
+{
+ enable_key_btn_->setVisible(visible);
+}
+
+void NodeParamViewKeyframeControl::SetInput(NodeInput *input)
+{
+ if (input_ != nullptr) {
+ disconnect(input_, &NodeInput::KeyframeEnableChanged, this, &NodeParamViewKeyframeControl::SetKeyframeEnabled);
+ }
+
+ input_ = input;
+
+ if (input_ != nullptr) {
+ connect(input_, &NodeInput::KeyframeEnableChanged, this, &NodeParamViewKeyframeControl::SetKeyframeEnabled);
+
+ // Pick up keyframing value
+ ShowButtonsFromKeyframeEnable(input_->is_keyframing());
+ }
+}
+
void NodeParamViewKeyframeControl::SetKeyframeEnabled(bool e)
{
// Suppress KeyframeEnableChanged() signal from this object
diff --git a/app/widget/nodeparamview/nodeparamviewkeyframecontrol.h b/app/widget/nodeparamview/nodeparamviewkeyframecontrol.h
index f3a566940..028925bff 100644
--- a/app/widget/nodeparamview/nodeparamviewkeyframecontrol.h
+++ b/app/widget/nodeparamview/nodeparamviewkeyframecontrol.h
@@ -10,13 +10,17 @@ class NodeParamViewKeyframeControl : public QWidget
{
Q_OBJECT
public:
- NodeParamViewKeyframeControl(NodeInput* input, QWidget* parent = nullptr);
+ NodeParamViewKeyframeControl(bool right_align = true, QWidget* parent = nullptr);
NodeInput* GetConnectedInput() const;
void SetPreviousButtonEnabled(bool enabled);
void SetNextButtonEnabled(bool enabled);
+ void SetToggleButtonEnabled(bool enable);
void SetToggleButtonChecked(bool checked);
+ void SetEnableButtonVisible(bool visible);
+
+ void SetInput(NodeInput* input);
public slots:
void SetKeyframeEnabled(bool e);
diff --git a/app/window/mainwindow/mainwindow.cpp b/app/window/mainwindow/mainwindow.cpp
index 8807dbb73..295c63bb5 100644
--- a/app/window/mainwindow/mainwindow.cpp
+++ b/app/window/mainwindow/mainwindow.cpp
@@ -27,6 +27,7 @@
// Panel objects
#include "panel/panelmanager.h"
#include "panel/audiomonitor/audiomonitor.h"
+#include "panel/curve/curve.h"
#include "panel/node/node.h"
#include "panel/param/param.h"
#include "panel/project/project.h"
@@ -137,6 +138,10 @@ void MainWindow::ProjectOpen(Project* p)
task_man_panel->setFloating(true);
task_man_panel->setVisible(false);
+ CurvePanel* curve_panel = PanelManager::instance()->CreatePanel(this);
+ addDockWidget(Qt::BottomDockWidgetArea, curve_panel);
+ task_man_panel->setFloating(true);
+
connect(node_panel, SIGNAL(SelectionChanged(QList)), param_panel, SLOT(SetNodes(QList)));
}