From d64e872b61cfeb0f7bc36e21b2b98e5ff10f580a Mon Sep 17 00:00:00 2001 From: Knud Dollereder Date: Mon, 25 Feb 2019 12:37:44 +0100 Subject: Introduce TreeView Provide example of intended usage. Move code, not intended for the client into subfolder detail. Add resources. (currently only temporary icons) Add evaluator functions to the AnimationCurve class. Change-Id: I9a8787af219d648d40181adc7433708030294628 Reviewed-by: Miikka Heikkinen --- examples/curveeditorapp/curveeditorapp.pro | 5 +- examples/curveeditorapp/examplecurvemodel.cpp | 94 +++--- examples/curveeditorapp/examplecurvemodel.h | 12 +- examples/curveeditorapp/mainwindow.cpp | 7 +- resources/curveeditor.qrc | 14 + resources/instance.png | Bin 0 -> 1182 bytes resources/locked.png | Bin 0 -> 1049 bytes resources/material.png | Bin 0 -> 1404 bytes resources/pinned.png | Bin 0 -> 916 bytes resources/unlocked.png | Bin 0 -> 1049 bytes resources/unpinned.png | Bin 0 -> 916 bytes src/curveeditor/animationcurve.cpp | 175 +++++++----- src/curveeditor/animationcurve.h | 64 ++--- src/curveeditor/colorcontrol.cpp | 101 ------- src/curveeditor/colorcontrol.h | 63 ---- src/curveeditor/curveeditor.cpp | 25 +- src/curveeditor/curveeditor.h | 13 +- src/curveeditor/curveeditor.pri | 47 +-- src/curveeditor/curveeditormodel.cpp | 106 +++++++ src/curveeditor/curveeditormodel.h | 59 +++- src/curveeditor/curveeditorstyle.h | 22 ++ src/curveeditor/curveeditorstyledialog.cpp | 244 ---------------- src/curveeditor/curveeditorstyledialog.h | 117 -------- src/curveeditor/curveeditorview.cpp | 313 -------------------- src/curveeditor/curveeditorview.h | 101 ------- src/curveeditor/curveitem.cpp | 141 --------- src/curveeditor/curveitem.h | 75 ----- src/curveeditor/detail/colorcontrol.cpp | 101 +++++++ src/curveeditor/detail/colorcontrol.h | 63 ++++ src/curveeditor/detail/curveeditorstyledialog.cpp | 245 ++++++++++++++++ src/curveeditor/detail/curveeditorstyledialog.h | 117 ++++++++ src/curveeditor/detail/curveitem.cpp | 216 ++++++++++++++ src/curveeditor/detail/curveitem.h | 97 +++++++ src/curveeditor/detail/curvesegment.cpp | 280 ++++++++++++++++++ src/curveeditor/detail/curvesegment.h | 63 ++++ src/curveeditor/detail/graphicsscene.cpp | 141 +++++++++ src/curveeditor/detail/graphicsscene.h | 72 +++++ src/curveeditor/detail/graphicsview.cpp | 332 ++++++++++++++++++++++ src/curveeditor/detail/graphicsview.h | 104 +++++++ src/curveeditor/detail/handleitem.cpp | 132 +++++++++ src/curveeditor/detail/handleitem.h | 60 ++++ src/curveeditor/detail/keyframeitem.cpp | 181 ++++++++++++ src/curveeditor/detail/keyframeitem.h | 85 ++++++ src/curveeditor/detail/treeitem.cpp | 188 ++++++++++++ src/curveeditor/detail/treeitem.h | 102 +++++++ src/curveeditor/detail/treeitemdelegate.cpp | 146 ++++++++++ src/curveeditor/detail/treeitemdelegate.h | 63 ++++ src/curveeditor/detail/treemodel.cpp | 142 +++++++++ src/curveeditor/detail/treemodel.h | 68 +++++ src/curveeditor/detail/treeview.cpp | 127 +++++++++ src/curveeditor/detail/treeview.h | 61 ++++ src/curveeditor/detail/utils.cpp | 107 +++++++ src/curveeditor/detail/utils.h | 52 ++++ src/curveeditor/handleitem.cpp | 134 --------- src/curveeditor/handleitem.h | 60 ---- src/curveeditor/keyframe.cpp | 88 ++++++ src/curveeditor/keyframe.h | 65 +++++ src/curveeditor/keyframeitem.cpp | 181 ------------ src/curveeditor/keyframeitem.h | 85 ------ src/curveeditor/utils.cpp | 78 ----- src/curveeditor/utils.h | 48 ---- 61 files changed, 3941 insertions(+), 1941 deletions(-) create mode 100644 resources/curveeditor.qrc create mode 100644 resources/instance.png create mode 100644 resources/locked.png create mode 100644 resources/material.png create mode 100644 resources/pinned.png create mode 100644 resources/unlocked.png create mode 100644 resources/unpinned.png delete mode 100644 src/curveeditor/colorcontrol.cpp delete mode 100644 src/curveeditor/colorcontrol.h create mode 100644 src/curveeditor/curveeditormodel.cpp delete mode 100644 src/curveeditor/curveeditorstyledialog.cpp delete mode 100644 src/curveeditor/curveeditorstyledialog.h delete mode 100644 src/curveeditor/curveeditorview.cpp delete mode 100644 src/curveeditor/curveeditorview.h delete mode 100644 src/curveeditor/curveitem.cpp delete mode 100644 src/curveeditor/curveitem.h create mode 100644 src/curveeditor/detail/colorcontrol.cpp create mode 100644 src/curveeditor/detail/colorcontrol.h create mode 100644 src/curveeditor/detail/curveeditorstyledialog.cpp create mode 100644 src/curveeditor/detail/curveeditorstyledialog.h create mode 100644 src/curveeditor/detail/curveitem.cpp create mode 100644 src/curveeditor/detail/curveitem.h create mode 100644 src/curveeditor/detail/curvesegment.cpp create mode 100644 src/curveeditor/detail/curvesegment.h create mode 100644 src/curveeditor/detail/graphicsscene.cpp create mode 100644 src/curveeditor/detail/graphicsscene.h create mode 100644 src/curveeditor/detail/graphicsview.cpp create mode 100644 src/curveeditor/detail/graphicsview.h create mode 100644 src/curveeditor/detail/handleitem.cpp create mode 100644 src/curveeditor/detail/handleitem.h create mode 100644 src/curveeditor/detail/keyframeitem.cpp create mode 100644 src/curveeditor/detail/keyframeitem.h create mode 100644 src/curveeditor/detail/treeitem.cpp create mode 100644 src/curveeditor/detail/treeitem.h create mode 100644 src/curveeditor/detail/treeitemdelegate.cpp create mode 100644 src/curveeditor/detail/treeitemdelegate.h create mode 100644 src/curveeditor/detail/treemodel.cpp create mode 100644 src/curveeditor/detail/treemodel.h create mode 100644 src/curveeditor/detail/treeview.cpp create mode 100644 src/curveeditor/detail/treeview.h create mode 100644 src/curveeditor/detail/utils.cpp create mode 100644 src/curveeditor/detail/utils.h delete mode 100644 src/curveeditor/handleitem.cpp delete mode 100644 src/curveeditor/handleitem.h create mode 100644 src/curveeditor/keyframe.cpp create mode 100644 src/curveeditor/keyframe.h delete mode 100644 src/curveeditor/keyframeitem.cpp delete mode 100644 src/curveeditor/keyframeitem.h delete mode 100644 src/curveeditor/utils.cpp delete mode 100644 src/curveeditor/utils.h diff --git a/examples/curveeditorapp/curveeditorapp.pro b/examples/curveeditorapp/curveeditorapp.pro index 2602ffd..3f44741 100644 --- a/examples/curveeditorapp/curveeditorapp.pro +++ b/examples/curveeditorapp/curveeditorapp.pro @@ -10,11 +10,14 @@ DEFINES += QT_DEPRECATED_WARNINGS INCLUDEPATH += . +RESOURCES = $$PWD/../../resources/curveeditor.qrc + include($$PWD/../../sharedcomponents.pri) # Input HEADERS += \ - mainwindow.h + mainwindow.h \ + examplecurvemodel.h SOURCES += \ main.cpp \ diff --git a/examples/curveeditorapp/examplecurvemodel.cpp b/examples/curveeditorapp/examplecurvemodel.cpp index a20740b..751ae1c 100644 --- a/examples/curveeditorapp/examplecurvemodel.cpp +++ b/examples/curveeditorapp/examplecurvemodel.cpp @@ -24,9 +24,18 @@ ****************************************************************************/ #include "examplecurvemodel.h" #include "animationcurve.h" +#include "curveeditorstyle.h" + +#include namespace DesignTools { +ExampleCurveModel::ExampleCurveModel() + : CurveEditorModel() +{ + connect(this, &CurveEditorModel::curveChanged, this, &ExampleCurveModel::curveChangeEmitted); +} + double ExampleCurveModel::minimumTime() const { return 0.0; @@ -37,64 +46,75 @@ double ExampleCurveModel::maximumTime() const return 500.0; } -double ExampleCurveModel::minimumValue() const -{ - return -1.0; -} - -double ExampleCurveModel::maximumValue() const -{ - return 1.0; -} - -AnimationCurve ExampleCurveModel::curve(int i) const -{ - if (i == 0) { - return AnimationCurve({ - Keyframe(QPointF(0.0, -1.0), QPointF(), QPointF(100.0, -1.0)), - Keyframe(QPointF(250.0, 0.0), QPointF(150.0, 0.0), QPointF(350.0, 0.0)), - Keyframe(QPointF(500.0, 1.0), QPointF(400.0, 1.0), QPointF()), - }); - } else { - return AnimationCurve({ - Keyframe(QPointF(0.0, -1.0), QPointF(), QPointF(1.0, -1.0)), - Keyframe(QPointF(5.0, 0.0), QPointF(4.0, 0.0), QPointF(6.0, 0.0)), - Keyframe(QPointF(200.0, 1.0), QPointF(199.0, 1.0), QPointF()), - }); - } -} - CurveEditorStyle ExampleCurveModel::style() const { // Pseudo auto generated. See: CurveEditorStyleDialog CurveEditorStyle out; - out.backgroundBrush = QBrush(QColor(5, 0, 100)); + out.backgroundBrush = QBrush(QColor(55, 55, 55)); out.backgroundAlternateBrush = QBrush(QColor(0, 0, 50)); - out.fontColor = QColor(200, 200, 200); - out.gridColor = QColor(128, 128, 128); + out.fontColor = QColor(255, 255, 255); + out.gridColor = QColor(114, 116, 118); out.canvasMargin = 5; out.zoomInWidth = 99; out.zoomInHeight = 99; out.timeAxisHeight = 40; out.timeOffsetLeft = 10; out.timeOffsetRight = 10; - out.rangeBarColor = QColor(50, 50, 255); + out.rangeBarColor = QColor(46, 47, 48); out.rangeBarCapsColor = QColor(50, 50, 255); out.valueAxisWidth = 60; out.valueOffsetTop = 10; out.valueOffsetBottom = 10; - out.playheadColor = QColor(200, 200, 0); + out.playheadColor = QColor(255, 255, 0); out.handleStyle.size = 12; out.handleStyle.lineWidth = 1; - out.handleStyle.color = QColor(200, 0, 0); - out.handleStyle.selectionColor = QColor(200, 200, 200); + out.handleStyle.color = QColor(255, 255, 255); + out.handleStyle.selectionColor = QColor(255, 255, 255); out.keyframeStyle.size = 13; - out.keyframeStyle.color = QColor(240, 255, 0); - out.keyframeStyle.selectionColor = QColor(200, 200, 200); + out.keyframeStyle.color = QColor(172, 210, 255); + out.keyframeStyle.selectionColor = QColor(255, 255, 255); out.curveStyle.width = 1; out.curveStyle.color = QColor(0, 200, 0); - out.curveStyle.selectionColor = QColor(200, 200, 200); + out.curveStyle.selectionColor = QColor(255, 255, 255); return out; } +void ExampleCurveModel::createItems() +{ + AnimationCurve curve1({ + Keyframe(QPointF(0.0, -1.0), QPointF(), QPointF(100.0, -1.0)), + Keyframe(QPointF(150.0, 0.7), QPointF(50.0, 0.7), QPointF(250.0, 0.7)), + Keyframe(QPointF(500.0, 1.0), QPointF(400.0, 1.0), QPointF())}); + + AnimationCurve curve2({ + Keyframe(QPointF(0.0, -1.0), QPointF(), QPointF(100.0, -1.0)), + Keyframe(QPointF(200.0, 0.4), QPointF(100.0, 0.4), QPointF(300.0, 0.4)), + Keyframe(QPointF(500.0, 1.0), QPointF(400.0, 1.0), QPointF())}); + + AnimationCurve curve3({ + Keyframe(QPointF(0.0, -1.0), QPointF(), QPointF(100.0, -1.0)), + Keyframe(QPointF(250.0, 0.0), QPointF(150.0, 0.0), QPointF(350.0, 0.0)), + Keyframe(QPointF(500.0, 1.0), QPointF(400.0, 1.0), QPointF())}); + + AnimationCurve curve4({ + Keyframe(QPointF(0.0, -1.0), QPointF(), QPointF(100.0, -1.0)), + Keyframe(QPointF(300.0, -0.4), QPointF(200.0, -0.4), QPointF(400.0, -0.4)), + Keyframe(QPointF(500.0, 1.0), QPointF(400.0, 1.0), QPointF())}); + + auto *instance = new NodeTreeItem("Instance", QIcon(":/ICON_INSTANCE")); + instance->addChild(new PropertyTreeItem("Position X", curve1)); + instance->addChild(new PropertyTreeItem("Position Y", curve2)); + + auto *material = new NodeTreeItem("Material", QIcon(":/ICON_MATERIAL")); + material->addChild(new PropertyTreeItem("Opacity", curve3)); + material->addChild(new PropertyTreeItem("Color R", curve4)); + + reset({instance, material}); +} + +void ExampleCurveModel::curveChangeEmitted(PropertyTreeItem *item) +{ + qDebug() << "The Curve with the id " << item->id() << " has changed"; +} + } // End namespace DesignTools. diff --git a/examples/curveeditorapp/examplecurvemodel.h b/examples/curveeditorapp/examplecurvemodel.h index 7f0433e..815af5e 100644 --- a/examples/curveeditorapp/examplecurvemodel.h +++ b/examples/curveeditorapp/examplecurvemodel.h @@ -31,18 +31,20 @@ namespace DesignTools { class ExampleCurveModel : public CurveEditorModel { + Q_OBJECT + public: + ExampleCurveModel(); + double minimumTime() const override; double maximumTime() const override; - double minimumValue() const override; - - double maximumValue() const override; + CurveEditorStyle style() const override; - AnimationCurve curve(int i) const override; + void createItems(); - CurveEditorStyle style() const override; + void curveChangeEmitted(PropertyTreeItem *item); }; } // End namespace DesignTools. diff --git a/examples/curveeditorapp/mainwindow.cpp b/examples/curveeditorapp/mainwindow.cpp index 7138b4e..6fbcd67 100644 --- a/examples/curveeditorapp/mainwindow.cpp +++ b/examples/curveeditorapp/mainwindow.cpp @@ -24,7 +24,6 @@ ****************************************************************************/ #include "mainwindow.h" #include "curveeditor.h" -#include "curveeditorview.h" #include "examplecurvemodel.h" #include @@ -58,8 +57,8 @@ MainWindow::MainWindow() auto *model = new ExampleCurveModel; auto *editor = new CurveEditor(model); - auto zoomX = [editor](int val) { editor->view()->zoomX(static_cast(val) / 1000.); }; - auto zoomY = [editor](int val) { editor->view()->zoomY(static_cast(val) / 1000.); }; + auto zoomX = [editor](int val) { editor->zoomX(static_cast(val) / 1000.); }; + auto zoomY = [editor](int val) { editor->zoomY(static_cast(val) / 1000.); }; auto *box = new QVBoxLayout; box->addWidget(editor); @@ -71,6 +70,8 @@ MainWindow::MainWindow() setCentralWidget(centralWidget); resize(QSize(1070, 739)); + + model->createItems(); } } // End namespace DesignTools. diff --git a/resources/curveeditor.qrc b/resources/curveeditor.qrc new file mode 100644 index 0000000..9dfc5d7 --- /dev/null +++ b/resources/curveeditor.qrc @@ -0,0 +1,14 @@ + + + + material.png + instance.png + + locked.png + unlocked.png + + pinned.png + unpinned.png + + + diff --git a/resources/instance.png b/resources/instance.png new file mode 100644 index 0000000..4f3d80a Binary files /dev/null and b/resources/instance.png differ diff --git a/resources/locked.png b/resources/locked.png new file mode 100644 index 0000000..1e8d129 Binary files /dev/null and b/resources/locked.png differ diff --git a/resources/material.png b/resources/material.png new file mode 100644 index 0000000..22524e8 Binary files /dev/null and b/resources/material.png differ diff --git a/resources/pinned.png b/resources/pinned.png new file mode 100644 index 0000000..8f70e76 Binary files /dev/null and b/resources/pinned.png differ diff --git a/resources/unlocked.png b/resources/unlocked.png new file mode 100644 index 0000000..1e8d129 Binary files /dev/null and b/resources/unlocked.png differ diff --git a/resources/unpinned.png b/resources/unpinned.png new file mode 100644 index 0000000..8f70e76 Binary files /dev/null and b/resources/unpinned.png differ diff --git a/src/curveeditor/animationcurve.cpp b/src/curveeditor/animationcurve.cpp index 4818a81..acb64ce 100644 --- a/src/curveeditor/animationcurve.cpp +++ b/src/curveeditor/animationcurve.cpp @@ -24,120 +24,155 @@ ****************************************************************************/ #include "animationcurve.h" +#include "detail/curvesegment.h" -#include -#include +#include namespace DesignTools { -Keyframe::Keyframe() - : m_position() - , m_leftHandle() - , m_rightHandle() +AnimationCurve::AnimationCurve() + : m_frames() {} -Keyframe::Keyframe(const QPointF &position) - : m_position(position) - , m_leftHandle() - , m_rightHandle() -{} +AnimationCurve::AnimationCurve(const std::vector &frames) + : m_frames(frames) + , m_minY(std::numeric_limits::max()) + , m_maxY(std::numeric_limits::lowest()) +{ + if (m_frames.size() >= 2) { + for (auto e : extrema()) { -Keyframe::Keyframe(const QPointF &position, const QPointF &leftHandle, const QPointF &rightHandle) - : m_position(position) - , m_leftHandle(leftHandle) - , m_rightHandle(rightHandle) -{} + if (m_minY > e.y()) + m_minY = e.y(); -bool Keyframe::hasLeftHandle() const -{ - return !m_leftHandle.isNull(); + if (m_maxY < e.y()) + m_maxY = e.y(); + } + } } -bool Keyframe::hasRightHandle() const +bool AnimationCurve::isValid() const { - return !m_rightHandle.isNull(); + return !m_frames.empty(); } -QPointF Keyframe::position() const +double AnimationCurve::minimumTime() const { - return m_position; + if (!m_frames.empty()) + return m_frames.front().position().x(); + + return std::numeric_limits::max(); } -QPointF Keyframe::leftHandle() const +double AnimationCurve::maximumTime() const { - return m_leftHandle; + if (!m_frames.empty()) + return m_frames.back().position().x(); + + return std::numeric_limits::lowest(); } -QPointF Keyframe::rightHandle() const +double AnimationCurve::minimumValue() const { - return m_rightHandle; + return m_minY; } -void Keyframe::setPosition(const QPointF &pos) +double AnimationCurve::maximumValue() const { - m_position = pos; + return m_maxY; } -void Keyframe::setLeftHandle(const QPointF &pos) +std::vector AnimationCurve::keyframes() const { - m_leftHandle = pos; + return m_frames; } -void Keyframe::setRightHandle(const QPointF &pos) +std::vector AnimationCurve::extrema() const { - m_rightHandle = pos; -} + std::vector out; + CurveSegment segment; + segment.setLeft(m_frames.at(0)); -CurveSegment::CurveSegment() - : m_left() - , m_right() -{} + for (size_t i = 1; i < m_frames.size(); ++i) { -CurveSegment::CurveSegment(const Keyframe &left, const Keyframe &right) - : m_left(left) - , m_right(right) -{} + segment.setRight(m_frames[i]); + + const auto es = segment.extrema(); + out.insert(std::end(out), std::begin(es), std::end(es)); + + segment.setLeft(m_frames[i]); + } + + return out; +} -QPointF CurveSegment::evaluate(double t) const +std::vector AnimationCurve::yForX(double x) const { - assert(t >= 0. && t <= 1.); + if (m_frames.front().position().x() > x) + return std::vector(); + + CurveSegment segment; + for (auto &frame : m_frames) { + if (frame.position().x() > x) { + segment.setRight(frame); + return segment.yForX(x); + } + segment.setLeft(frame); + } + return std::vector(); +} - const double it = 1.0 - t; +std::vector AnimationCurve::xForY(double y, uint segment) const +{ + if (m_frames.size() > segment + 1) { + CurveSegment seg(m_frames[segment], m_frames[segment + 1]); + return seg.xForY(y); + } + return std::vector(); +} - auto binomialPolynomial = [t, it](double p0, double p1, double p2, double p3) { - return p0 * std::pow(it, 3.0) + p1 * 3.0 * std::pow(it, 2.0) * t - + p2 * 3.0 * it * std::pow(t, 2.0) + p3 * std::pow(t, 3.0); - }; +bool AnimationCurve::intersects(const QPointF &coord, double radius) +{ + if (m_frames.size() < 2) + return false; - const double x = binomialPolynomial( - m_left.position().x(), m_left.rightHandle().x(), - m_right.leftHandle().x(), m_right.position().x()); + std::vector influencer; - const double y = binomialPolynomial( - m_left.position().y(), m_left.rightHandle().y(), - m_right.leftHandle().y(), m_right.position().y()); + CurveSegment current; + current.setLeft(m_frames.at(0)); - return QPointF(x, y); -} + for (size_t i = 1; i < m_frames.size(); ++i) { + Keyframe &frame = m_frames.at(i); + current.setRight(frame); -AnimationCurve::AnimationCurve() - : m_frames() -{} + if (current.containsX(coord.x() - radius) || + current.containsX(coord.x()) || + current.containsX(coord.x() + radius)) { + influencer.push_back(current); + } -AnimationCurve::AnimationCurve(const std::vector &frames) - : m_frames(frames) -{} + if (frame.position().x() > coord.x() + radius) + break; -bool AnimationCurve::isValid() const -{ - return !m_frames.empty(); -} + current.setLeft(frame); + } -std::vector AnimationCurve::keyframes() const -{ - return m_frames; + for (auto &segment : influencer) { + for (auto &y : segment.yForX(coord.x())) { + QLineF line(coord.x(), y, coord.x(), coord.y()); + if (line.length() < radius) + return true; + } + + for (auto &x : segment.xForY(coord.y())) { + QLineF line(x, coord.y(), coord.x(), coord.y()); + if (line.length() < radius) + return true; + } + } + return false; } } // End namespace DesignTools. diff --git a/src/curveeditor/animationcurve.h b/src/curveeditor/animationcurve.h index 7b42e07..0533e47 100644 --- a/src/curveeditor/animationcurve.h +++ b/src/curveeditor/animationcurve.h @@ -25,75 +25,45 @@ #pragma once -#include +#include "keyframe.h" #include namespace DesignTools { -class Keyframe +class AnimationCurve { public: - Keyframe(); - - Keyframe(const QPointF &position); - - Keyframe(const QPointF &position, const QPointF &leftHandle, const QPointF &rightHandle); - - bool hasLeftHandle() const; - - bool hasRightHandle() const; - - QPointF position() const; - - QPointF leftHandle() const; + AnimationCurve(); - QPointF rightHandle() const; + AnimationCurve(const std::vector &frames); - void setPosition(const QPointF &pos); + bool isValid() const; - void setLeftHandle(const QPointF &pos); + double minimumTime() const; - void setRightHandle(const QPointF &pos); + double maximumTime() const; -private: - QPointF m_position = QPointF(); + double minimumValue() const; - QPointF m_leftHandle = QPointF(); + double maximumValue() const; - QPointF m_rightHandle = QPointF(); -}; + std::vector keyframes() const; + std::vector extrema() const; -class CurveSegment -{ -public: - CurveSegment(); + std::vector yForX(double x) const; - CurveSegment(const Keyframe &first, const Keyframe &last); + std::vector xForY(double y, uint segment) const; - QPointF evaluate(double t) const; + bool intersects(const QPointF &coord, double radius); private: - Keyframe m_left; - - Keyframe m_right; -}; - - -class AnimationCurve -{ -public: - AnimationCurve(); - - AnimationCurve(const std::vector &frames); + std::vector m_frames; - bool isValid() const; + double m_minY; - std::vector keyframes() const; - -private: - std::vector m_frames; + double m_maxY; }; } // End namespace DesignTools. diff --git a/src/curveeditor/colorcontrol.cpp b/src/curveeditor/colorcontrol.cpp deleted file mode 100644 index a833a4c..0000000 --- a/src/curveeditor/colorcontrol.cpp +++ /dev/null @@ -1,101 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2019 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the Qt Design Tooling -** -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -****************************************************************************/ -#include "colorcontrol.h" - -#include -#include -#include -#include -#include - -namespace DesignTools { - -ColorControl::ColorControl() - : QWidget(nullptr) - , m_color(Qt::black) -{ - setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed); - setFixedHeight(20); -} - -ColorControl::ColorControl(const QColor &color, QWidget *parent) - : QWidget(parent) - , m_color(color) -{ - setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed); - setFixedHeight(20); -} - -ColorControl::~ColorControl() = default; - -QColor ColorControl::value() const -{ - return m_color; -} - -void ColorControl::setValue(const QColor &val) -{ - m_color = val; -} - -bool ColorControl::event(QEvent *event) -{ - if (event->type() == QEvent::ToolTip) { - if (auto helpEvent = static_cast(event)) { - QToolTip::showText(helpEvent->globalPos(), m_color.name()); - return true; - } - } - return QWidget::event(event); -} - -void ColorControl::paintEvent(QPaintEvent *event) -{ - QPainter painter(this); - painter.fillRect(event->rect(), m_color); -} - -void ColorControl::mouseReleaseEvent(QMouseEvent *event) -{ - QColor color = QColorDialog::getColor(m_color, this); - - event->accept(); - - if (color != m_color) { - m_color = color; - update(); - emit valueChanged(); - } -} - -void ColorControl::mousePressEvent(QMouseEvent *event) -{ - // Required if embedded in a QGraphicsProxywidget - // in order to call mouseRelease properly. - QWidget::mousePressEvent(event); - event->accept(); -} - -} // End namespace DesignTools. diff --git a/src/curveeditor/colorcontrol.h b/src/curveeditor/colorcontrol.h deleted file mode 100644 index 54dfe19..0000000 --- a/src/curveeditor/colorcontrol.h +++ /dev/null @@ -1,63 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2019 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the Qt Design Tooling -** -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -****************************************************************************/ - -#pragma once - -#include - -namespace DesignTools { - -class ColorControl : public QWidget -{ - Q_OBJECT - -public: - ColorControl(); - - ColorControl(const QColor &color, QWidget *parent = nullptr); - - ~ColorControl() override; - - QColor value() const; - - void setValue(const QColor &val); - -protected: - bool event(QEvent *event) override; - - void paintEvent(QPaintEvent *event) override; - - void mouseReleaseEvent(QMouseEvent *event) override; - - void mousePressEvent(QMouseEvent *event) override; - -signals: - void valueChanged(); - -private: - QColor m_color; -}; - -} // End namespace DesignTools. diff --git a/src/curveeditor/curveeditor.cpp b/src/curveeditor/curveeditor.cpp index b72f905..8501041 100644 --- a/src/curveeditor/curveeditor.cpp +++ b/src/curveeditor/curveeditor.cpp @@ -22,36 +22,43 @@ ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ****************************************************************************/ + #include "curveeditor.h" #include "curveeditormodel.h" -#include "curveeditorview.h" +#include "detail/curveitem.h" +#include "detail/graphicsview.h" +#include "detail/treeview.h" #include #include -#include namespace DesignTools { CurveEditor::CurveEditor(CurveEditorModel *model, QWidget *parent) : QWidget(parent) - , m_tree(new QTreeView) - , m_view(new CurveEditorView(model)) + , m_tree(new TreeView(model, this)) + , m_view(new GraphicsView(model)) { - m_tree->setFixedWidth(100); - QSplitter *splitter = new QSplitter; splitter->addWidget(m_tree); splitter->addWidget(m_view); - splitter->setSizes({5, 80}); + splitter->setStretchFactor(1, 2); QHBoxLayout *box = new QHBoxLayout; box->addWidget(splitter); setLayout(box); + + connect(m_tree, &TreeView::curvesSelected, m_view, &GraphicsView::reset); +} + +void CurveEditor::zoomX(double zoom) +{ + m_view->zoomX(zoom); } -CurveEditorView *CurveEditor::view() const +void CurveEditor::zoomY(double zoom) { - return m_view; + m_view->zoomY(zoom); } } // End namespace DesignTools. diff --git a/src/curveeditor/curveeditor.h b/src/curveeditor/curveeditor.h index f5e1af8..a2c5873 100644 --- a/src/curveeditor/curveeditor.h +++ b/src/curveeditor/curveeditor.h @@ -27,12 +27,11 @@ #include -class QTreeView; - namespace DesignTools { class CurveEditorModel; -class CurveEditorView; +class GraphicsView; +class TreeView; class CurveEditor : public QWidget { @@ -41,12 +40,14 @@ class CurveEditor : public QWidget public: CurveEditor(CurveEditorModel *model, QWidget *parent = nullptr); - CurveEditorView *view() const; + void zoomX(double zoom); + + void zoomY(double zoom); private: - QTreeView *m_tree; + TreeView *m_tree; - CurveEditorView *m_view; + GraphicsView *m_view; }; } // End namespace DesignTools. diff --git a/src/curveeditor/curveeditor.pri b/src/curveeditor/curveeditor.pri index 861abd8..6b325e3 100644 --- a/src/curveeditor/curveeditor.pri +++ b/src/curveeditor/curveeditor.pri @@ -1,23 +1,38 @@ INCLUDEPATH += $$PWD -### include required files -HEADERS += \ +HEADERS += \ $$PWD/animationcurve.h \ $$PWD/curveeditor.h \ - $$PWD/curveeditorstyledialog.h \ - $$PWD/curveeditorview.h \ - $$PWD/curveitem.h \ - $$PWD/colorcontrol.h \ - $$PWD/handleitem.h \ - $$PWD/keyframeitem.h + $$PWD/curveeditormodel.h \ + $$PWD/keyframe.h \ + $$PWD/detail/colorcontrol.h \ + $$PWD/detail/curveeditorstyledialog.h \ + $$PWD/detail/curveitem.h \ + $$PWD/detail/curvesegment.h \ + $$PWD/detail/graphicsscene.h \ + $$PWD/detail/graphicsview.h \ + $$PWD/detail/handleitem.h \ + $$PWD/detail/keyframeitem.h \ + $$PWD/detail/treeitem.h \ + $$PWD/detail/treeitemdelegate.h \ + $$PWD/detail/treemodel.h \ + $$PWD/detail/treeview.h -SOURCES += \ +SOURCES += \ $$PWD/animationcurve.cpp \ $$PWD/curveeditor.cpp \ - $$PWD/curveeditorstyledialog.cpp \ - $$PWD/curveeditorview.cpp \ - $$PWD/curveitem.cpp \ - $$PWD/colorcontrol.cpp \ - $$PWD/handleitem.cpp \ - $$PWD/keyframeitem.cpp \ - $$PWD/utils.cpp + $$PWD/curveeditormodel.cpp \ + $$PWD/keyframe.cpp \ + $$PWD/detail/colorcontrol.cpp \ + $$PWD/detail/curveeditorstyledialog.cpp \ + $$PWD/detail/curveitem.cpp \ + $$PWD/detail/curvesegment.cpp \ + $$PWD/detail/graphicsscene.cpp \ + $$PWD/detail/graphicsview.cpp \ + $$PWD/detail/handleitem.cpp \ + $$PWD/detail/keyframeitem.cpp \ + $$PWD/detail/treeitem.cpp \ + $$PWD/detail/treeitemdelegate.cpp \ + $$PWD/detail/treemodel.cpp \ + $$PWD/detail/treeview.cpp \ + $$PWD/detail/utils.cpp diff --git a/src/curveeditor/curveeditormodel.cpp b/src/curveeditor/curveeditormodel.cpp new file mode 100644 index 0000000..31d4d6b --- /dev/null +++ b/src/curveeditor/curveeditormodel.cpp @@ -0,0 +1,106 @@ +/**************************************************************************** +** +** Copyright (C) 2019 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt Design Tooling +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ + +#include "curveeditormodel.h" + +namespace DesignTools { + +CurveEditorModel::CurveEditorModel(QObject *parent) + : TreeModel(parent) +{} + +CurveEditorModel::~CurveEditorModel() {} + +void CurveEditorModel::setCurrentTime(uint frame) +{ + Q_UNUSED(frame); + printf("CurveEditorModel::setCurrentTime unimplememted!\n"); +} + +void CurveEditorModel::setCurve(unsigned int id, const AnimationCurve &curve) +{ + if (TreeItem *item = find(id)) { + if (PropertyTreeItem *propertyItem = item->asPropertyItem()) { + propertyItem->setCurve(curve); + emit curveChanged(propertyItem); + } + } +} + +void CurveEditorModel::reset(const std::vector &items) +{ + beginResetModel(); + + initialize(); + + unsigned int counter = 0; + for (auto *item : items) { + item->setId(++counter); + root()->addChild(item); + } + + endResetModel(); +} + + +NodeTreeItem::NodeTreeItem(const QString &name, const QIcon &icon) + : TreeItem(name) + , m_icon(icon) +{ + Q_UNUSED(icon); +} + +NodeTreeItem *NodeTreeItem::asNodeItem() +{ + return this; +} + +QIcon NodeTreeItem::icon() const +{ + return m_icon; +} + + +PropertyTreeItem::PropertyTreeItem(const QString &name, const AnimationCurve &curve) + : TreeItem(name) + , m_curve(curve) +{} + +PropertyTreeItem *PropertyTreeItem::asPropertyItem() +{ + return this; +} + +AnimationCurve PropertyTreeItem::curve() const +{ + return m_curve; +} + +void PropertyTreeItem::setCurve(const AnimationCurve &curve) +{ + m_curve = curve; +} + +} // End namespace DesignTools. diff --git a/src/curveeditor/curveeditormodel.h b/src/curveeditor/curveeditormodel.h index 351aa73..5c0bb4e 100644 --- a/src/curveeditor/curveeditormodel.h +++ b/src/curveeditor/curveeditormodel.h @@ -25,7 +25,10 @@ #pragma once -#include "curveeditorstyle.h" +#include "detail/treeitem.h" +#include "detail/treemodel.h" + +#include #include @@ -33,22 +36,66 @@ class QPointF; namespace DesignTools { +struct CurveEditorStyle; + class AnimationCurve; -class CurveEditorModel +class CurveEditorModel : public TreeModel { + Q_OBJECT + +signals: + void curveChanged(PropertyTreeItem *item); + public: virtual double minimumTime() const = 0; virtual double maximumTime() const = 0; - virtual double minimumValue() const = 0; + virtual CurveEditorStyle style() const = 0; + +public: + CurveEditorModel(QObject *parent = nullptr); + + ~CurveEditorModel() override; + + void setCurrentTime(uint frame); + + void setCurve(unsigned int id, const AnimationCurve &curve); + + void reset(const std::vector &items); +}; + + +class NodeTreeItem : public TreeItem +{ +public: + NodeTreeItem(const QString &name, const QIcon &icon); + + NodeTreeItem *asNodeItem() override; + + QIcon icon() const override; + +private: + QIcon m_icon; +}; + + +class PropertyTreeItem : public TreeItem +{ +public: + PropertyTreeItem(const QString &name, const AnimationCurve &curve); + + PropertyTreeItem *asPropertyItem() override; + + AnimationCurve curve() const; - virtual double maximumValue() const = 0; + void setCurve(const AnimationCurve &curve); - virtual AnimationCurve curve(int i) const = 0; +private: + using TreeItem::addChild; - virtual CurveEditorStyle style() const { return CurveEditorStyle(); } + AnimationCurve m_curve; }; } // End namespace DesignTools. diff --git a/src/curveeditor/curveeditorstyle.h b/src/curveeditor/curveeditorstyle.h index 23fdaf8..f60948a 100644 --- a/src/curveeditor/curveeditorstyle.h +++ b/src/curveeditor/curveeditorstyle.h @@ -25,12 +25,23 @@ #pragma once +#include #include #include #include +#include namespace DesignTools { +struct TreeItemStyleOption +{ + double margins; + QIcon pinnedIcon = QIcon(":/ICON_PINNED"); + QIcon unpinnedIcon = QIcon(":/ICON_UNPINNED"); + QIcon lockedIcon = QIcon(":/ICON_LOCKED"); + QIcon unlockedIcon = QIcon(":/ICON_UNLOCKED"); +}; + struct HandleItemStyleOption { double size = 10.0; @@ -92,6 +103,17 @@ struct CurveEditorStyle KeyframeItemStyleOption keyframeStyle; CurveItemStyleOption curveStyle; + + TreeItemStyleOption treeItemStyle; }; +inline QPixmap pixmapFromIcon(const QIcon &icon, const QSize &size, const QColor &color) +{ + QPixmap pixmap = icon.pixmap(size); + QPixmap mask(pixmap.size()); + mask.fill(color); + mask.setMask(pixmap.createMaskFromColor(Qt::transparent)); + return mask; +} + } // End namespace DesignTools. diff --git a/src/curveeditor/curveeditorstyledialog.cpp b/src/curveeditor/curveeditorstyledialog.cpp deleted file mode 100644 index 2629f24..0000000 --- a/src/curveeditor/curveeditorstyledialog.cpp +++ /dev/null @@ -1,244 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2019 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the Qt Design Tooling -** -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -****************************************************************************/ -#include "curveeditorstyledialog.h" -#include "colorcontrol.h" -#include "curveeditorstyle.h" - -#include -#include -#include -#include -#include -#include - -namespace DesignTools { - -QHBoxLayout *createRow(const QString &title, QWidget *widget) -{ - auto *label = new QLabel(title); - label->setFixedWidth(200); - label->setAlignment(Qt::AlignRight); - - auto *box = new QHBoxLayout; - box->addWidget(label); - box->addWidget(widget); - return box; -} - -CurveEditorStyleDialog::CurveEditorStyleDialog(CurveEditorStyle &style, QWidget *parent) - : QDialog(parent) - , m_printButton(new QPushButton("Print")) - , m_background(new ColorControl(style.backgroundBrush.color())) - , m_backgroundAlternate(new ColorControl(style.backgroundAlternateBrush.color())) - , m_fontColor(new ColorControl(style.fontColor)) - , m_gridColor(new ColorControl(style.gridColor)) - , m_canvasMargin(new QDoubleSpinBox()) - , m_zoomInWidth(new QSpinBox()) - , m_zoomInHeight(new QSpinBox()) - , m_timeAxisHeight(new QDoubleSpinBox()) - , m_timeOffsetLeft(new QDoubleSpinBox()) - , m_timeOffsetRight(new QDoubleSpinBox()) - , m_rangeBarColor(new ColorControl(style.rangeBarCapsColor)) - , m_rangeBarCapsColor(new ColorControl(style.rangeBarCapsColor)) - , m_valueAxisWidth(new QDoubleSpinBox()) - , m_valueOffsetTop(new QDoubleSpinBox()) - , m_valueOffsetBottom(new QDoubleSpinBox()) - , m_playhead(new ColorControl(style.playheadColor)) - , m_handleSize(new QDoubleSpinBox()) - , m_handleLineWidth(new QDoubleSpinBox()) - , m_handleColor(new ColorControl(style.handleStyle.color)) - , m_handleSelectionColor(new ColorControl(style.handleStyle.selectionColor)) - , m_keyframeSize(new QDoubleSpinBox()) - , m_keyframeColor(new ColorControl(style.keyframeStyle.color)) - , m_keyframeSelectionColor(new ColorControl(style.keyframeStyle.selectionColor)) - , m_curveWidth(new QDoubleSpinBox()) - , m_curveColor(new ColorControl(style.curveStyle.color)) - , m_curveSelectionColor(new ColorControl(style.curveStyle.selectionColor)) -{ - m_canvasMargin->setValue(style.canvasMargin); - m_zoomInWidth->setValue(style.zoomInWidth); - m_zoomInHeight->setValue(style.zoomInHeight); - m_timeAxisHeight->setValue(style.timeAxisHeight); - m_timeOffsetLeft->setValue(style.timeOffsetLeft); - m_timeOffsetRight->setValue(style.timeOffsetRight); - m_valueAxisWidth->setValue(style.valueAxisWidth); - m_valueOffsetTop->setValue(style.valueOffsetTop); - m_valueOffsetBottom->setValue(style.valueOffsetBottom); - m_handleSize->setValue(style.handleStyle.size); - m_handleLineWidth->setValue(style.handleStyle.lineWidth); - m_keyframeSize->setValue(style.keyframeStyle.size); - m_curveWidth->setValue(style.curveStyle.width); - - connect(m_printButton, &QPushButton::released, this, &CurveEditorStyleDialog::printStyle); - - auto intChanged = [this](int) { emitStyleChanged(); }; - auto doubleChanged = [this](double) { emitStyleChanged(); }; - auto colorChanged = [this]() { emitStyleChanged(); }; - - auto intSignal = static_cast(&QSpinBox::valueChanged); - auto doubleSignal = static_cast(&QDoubleSpinBox::valueChanged); - - connect(m_background, &ColorControl::valueChanged, colorChanged); - connect(m_backgroundAlternate, &ColorControl::valueChanged, colorChanged); - connect(m_fontColor, &ColorControl::valueChanged, colorChanged); - connect(m_gridColor, &ColorControl::valueChanged, colorChanged); - connect(m_canvasMargin, doubleSignal, doubleChanged); - connect(m_zoomInWidth, intSignal, intChanged); - connect(m_zoomInHeight, intSignal, intChanged); - connect(m_timeAxisHeight, doubleSignal, doubleChanged); - connect(m_timeOffsetLeft, doubleSignal, doubleChanged); - connect(m_timeOffsetRight, doubleSignal, doubleChanged); - connect(m_rangeBarColor, &ColorControl::valueChanged, colorChanged); - connect(m_rangeBarCapsColor, &ColorControl::valueChanged, colorChanged); - connect(m_valueAxisWidth, doubleSignal, doubleChanged); - connect(m_valueOffsetTop, doubleSignal, doubleChanged); - connect(m_valueOffsetBottom, doubleSignal, doubleChanged); - connect(m_playhead, &ColorControl::valueChanged, colorChanged); - connect(m_handleSize, doubleSignal, doubleChanged); - connect(m_handleLineWidth, doubleSignal, doubleChanged); - connect(m_handleColor, &ColorControl::valueChanged, colorChanged); - connect(m_handleSelectionColor, &ColorControl::valueChanged, colorChanged); - connect(m_keyframeSize, doubleSignal, doubleChanged); - connect(m_keyframeColor, &ColorControl::valueChanged, colorChanged); - connect(m_keyframeSelectionColor, &ColorControl::valueChanged, colorChanged); - connect(m_curveWidth, doubleSignal, doubleChanged); - connect(m_curveColor, &ColorControl::valueChanged, colorChanged); - connect(m_curveSelectionColor, &ColorControl::valueChanged, colorChanged); - - auto *box = new QVBoxLayout; - box->addLayout(createRow("Background Color", m_background)); - box->addLayout(createRow("Alternate Background Color", m_backgroundAlternate)); - box->addLayout(createRow("Font Color", m_fontColor)); - box->addLayout(createRow("Grid Color", m_gridColor)); - box->addLayout(createRow("Canvas Margin", m_canvasMargin)); - box->addLayout(createRow("Zoom In Width", m_zoomInWidth)); - box->addLayout(createRow("Zoom In Height", m_zoomInHeight)); - box->addLayout(createRow("Time Axis Height", m_timeAxisHeight)); - box->addLayout(createRow("Time Axis Left Offset", m_timeOffsetLeft)); - box->addLayout(createRow("Time Axis Right Offset", m_timeOffsetRight)); - box->addLayout(createRow("Range Bar Color", m_rangeBarColor)); - box->addLayout(createRow("Range Bar Caps Color", m_rangeBarCapsColor)); - box->addLayout(createRow("Value Axis Width", m_valueAxisWidth)); - box->addLayout(createRow("Value Axis Top Offset", m_valueOffsetTop)); - box->addLayout(createRow("Value Axis Bottom Offset", m_valueOffsetBottom)); - box->addLayout(createRow("Playhead Color", m_playhead)); - box->addLayout(createRow("Handle Size", m_handleSize)); - box->addLayout(createRow("Handle Line Width", m_handleLineWidth)); - box->addLayout(createRow("Handle Color", m_handleColor)); - box->addLayout(createRow("Handle Selection Color", m_handleSelectionColor)); - box->addLayout(createRow("Keyframe Size", m_keyframeSize)); - box->addLayout(createRow("Keyframe Color", m_keyframeColor)); - box->addLayout(createRow("Keyframe Selection Color", m_keyframeSelectionColor)); - box->addLayout(createRow("Curve Width", m_curveWidth)); - box->addLayout(createRow("Curve Color", m_curveColor)); - box->addLayout(createRow("Curve Selection Color", m_curveSelectionColor)); - - box->addWidget(m_printButton); - setLayout(box); -} - -CurveEditorStyle CurveEditorStyleDialog::style() const -{ - CurveEditorStyle style; - style.backgroundBrush = QBrush(m_background->value()); - style.backgroundAlternateBrush = QBrush(m_backgroundAlternate->value()); - style.fontColor = m_fontColor->value(); - style.gridColor = m_gridColor->value(); - style.canvasMargin = m_canvasMargin->value(); - style.zoomInWidth = m_zoomInWidth->value(); - style.zoomInHeight = m_zoomInHeight->value(); - style.timeAxisHeight = m_timeAxisHeight->value(); - style.timeOffsetLeft = m_timeOffsetLeft->value(); - style.timeOffsetRight = m_timeOffsetRight->value(); - style.rangeBarColor = m_rangeBarColor->value(); - style.rangeBarCapsColor = m_rangeBarCapsColor->value(); - style.valueAxisWidth = m_valueAxisWidth->value(); - style.valueOffsetTop = m_valueOffsetTop->value(); - style.valueOffsetBottom = m_valueOffsetBottom->value(); - style.playheadColor = m_playhead->value(); - style.handleStyle.size = m_handleSize->value(); - style.handleStyle.lineWidth = m_handleLineWidth->value(); - style.handleStyle.color = m_handleColor->value(); - style.handleStyle.selectionColor = m_handleSelectionColor->value(); - style.keyframeStyle.size = m_keyframeSize->value(); - style.keyframeStyle.color = m_keyframeColor->value(); - style.keyframeStyle.selectionColor = m_keyframeSelectionColor->value(); - style.curveStyle.width = m_curveWidth->value(); - style.curveStyle.color = m_curveColor->value(); - style.curveStyle.selectionColor = m_curveSelectionColor->value(); - return style; -} - -void CurveEditorStyleDialog::emitStyleChanged() -{ - emit styleChanged(style()); -} - -void CurveEditorStyleDialog::printStyle() -{ - auto toString = [](const QColor &color) { - QString tmp = QString("QColor(%1, %2, %3)").arg(color.red()).arg(color.green()).arg(color.blue()); - return qPrintable(tmp); - }; - - CurveEditorStyle s = style(); - qDebug() << ""; - qDebug().nospace() << "CurveEditorStyle out;"; - qDebug().nospace() << "out.backgroundBrush = QBrush(" << toString(s.backgroundBrush.color()) - << ");"; - qDebug().nospace() << "out.backgroundAlternateBrush = QBrush(" - << toString(s.backgroundAlternateBrush.color()) << ");"; - qDebug().nospace() << "out.fontColor = " << toString(s.fontColor) << ";"; - qDebug().nospace() << "out.gridColor = " << toString(s.gridColor) << ";"; - qDebug().nospace() << "out.canvasMargin = " << s.canvasMargin << ";"; - qDebug().nospace() << "out.zoomInWidth = " << s.zoomInWidth << ";"; - qDebug().nospace() << "out.zoomInHeight = " << s.zoomInHeight << ";"; - qDebug().nospace() << "out.timeAxisHeight = " << s.timeAxisHeight << ";"; - qDebug().nospace() << "out.timeOffsetLeft = " << s.timeOffsetLeft << ";"; - qDebug().nospace() << "out.timeOffsetRight = " << s.timeOffsetRight << ";"; - qDebug().nospace() << "out.rangeBarColor = " << toString(s.rangeBarColor) << ";"; - qDebug().nospace() << "out.rangeBarCapsColor = " << toString(s.rangeBarCapsColor) << ";"; - qDebug().nospace() << "out.valueAxisWidth = " << s.valueAxisWidth << ";"; - qDebug().nospace() << "out.valueOffsetTop = " << s.valueOffsetTop << ";"; - qDebug().nospace() << "out.valueOffsetBottom = " << s.valueOffsetBottom << ";"; - qDebug().nospace() << "out.playheadColor = " << toString(s.playheadColor) << ";"; - qDebug().nospace() << "out.handleStyle.size = " << s.handleStyle.size << ";"; - qDebug().nospace() << "out.handleStyle.lineWidth = " << s.handleStyle.lineWidth << ";"; - qDebug().nospace() << "out.handleStyle.color = " << toString(s.handleStyle.color) << ";"; - qDebug().nospace() << "out.handleStyle.selectionColor = " - << toString(s.handleStyle.selectionColor) << ";"; - qDebug().nospace() << "out.keyframeStyle.size = " << s.keyframeStyle.size << ";"; - qDebug().nospace() << "out.keyframeStyle.color = " << toString(s.keyframeStyle.color) << ";"; - qDebug().nospace() << "out.keyframeStyle.selectionColor = " - << toString(s.keyframeStyle.selectionColor) << ";"; - qDebug().nospace() << "out.curveStyle.width = " << s.curveStyle.width << ";"; - qDebug().nospace() << "out.curveStyle.color = " << toString(s.curveStyle.color) << ";"; - qDebug().nospace() << "out.curveStyle.selectionColor = " - << toString(s.curveStyle.selectionColor) << ";"; - qDebug().nospace() << "return out;"; - qDebug() << ""; -} - -} // End namespace DesignTools. diff --git a/src/curveeditor/curveeditorstyledialog.h b/src/curveeditor/curveeditorstyledialog.h deleted file mode 100644 index 645f545..0000000 --- a/src/curveeditor/curveeditorstyledialog.h +++ /dev/null @@ -1,117 +0,0 @@ - -/**************************************************************************** -** -** Copyright (C) 2019 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the Qt Design Tooling -** -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -****************************************************************************/ - -#pragma once - -#include - -class QPushButton; -class QSpinBox; -class QDoubleSpinBox; - -namespace DesignTools { - -class ColorControl; - -struct CurveEditorStyle; - -class CurveEditorStyleDialog : public QDialog -{ - Q_OBJECT - -signals: - void styleChanged(const CurveEditorStyle &style); - -public: - CurveEditorStyleDialog(CurveEditorStyle &style, QWidget *parent = nullptr); - - CurveEditorStyle style() const; - -private: - void emitStyleChanged(); - - void printStyle(); - -private: - QPushButton *m_printButton; - - ColorControl *m_background; - - ColorControl *m_backgroundAlternate; - - ColorControl *m_fontColor; - - ColorControl *m_gridColor; - - QDoubleSpinBox *m_canvasMargin; - - QSpinBox *m_zoomInWidth; - - QSpinBox *m_zoomInHeight; - - QDoubleSpinBox *m_timeAxisHeight; - - QDoubleSpinBox *m_timeOffsetLeft; - - QDoubleSpinBox *m_timeOffsetRight; - - ColorControl *m_rangeBarColor; - - ColorControl *m_rangeBarCapsColor; - - QDoubleSpinBox *m_valueAxisWidth; - - QDoubleSpinBox *m_valueOffsetTop; - - QDoubleSpinBox *m_valueOffsetBottom; - - ColorControl *m_playhead; - - // HandleItem - QDoubleSpinBox *m_handleSize; - - QDoubleSpinBox *m_handleLineWidth; - - ColorControl *m_handleColor; - - ColorControl *m_handleSelectionColor; - - // KeyframeItem - QDoubleSpinBox *m_keyframeSize; - - ColorControl *m_keyframeColor; - - ColorControl *m_keyframeSelectionColor; - - // CurveItem - QDoubleSpinBox *m_curveWidth; - - ColorControl *m_curveColor; - - ColorControl *m_curveSelectionColor; -}; - -} // End namespace DesignTools. diff --git a/src/curveeditor/curveeditorview.cpp b/src/curveeditor/curveeditorview.cpp deleted file mode 100644 index 0a54c82..0000000 --- a/src/curveeditor/curveeditorview.cpp +++ /dev/null @@ -1,313 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2019 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the Qt Design Tooling -** -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -****************************************************************************/ -#include "curveeditorview.h" -#include "curveeditormodel.h" -#include "curveitem.h" -#include "utils.h" - -#include -#include -#include - -#include - -namespace DesignTools { - -CurveEditorView::CurveEditorView(CurveEditorModel *model, QWidget *parent) - : QGraphicsView(parent) - , m_scene() - , m_style(model->style()) - , m_model(model) - , m_dialog(m_style, this) - , m_zoomX(0.0) - , m_zoomY(0.0) -{ - setScene(&m_scene); - setAlignment(Qt::AlignLeft | Qt::AlignVCenter); - setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOn); - setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOn); - setViewportUpdateMode(QGraphicsView::FullViewportUpdate); - - connect(&m_dialog, &CurveEditorStyleDialog::styleChanged, this, &CurveEditorView::setStyle); - - m_scene.addItem(new CurveItem(model->curve(0))); - - applyZoom(m_zoomX, m_zoomY); - update(); -} - -void CurveEditorView::setStyle(const CurveEditorStyle &style) -{ - m_style = style; - - const auto itemList = items(); - for (auto *item : itemList) { - if (auto *curveItem = qgraphicsitem_cast(item)) - curveItem->setStyle(style); - } - - updateSceneRect(); - applyZoom(m_zoomX, m_zoomY); - viewport()->update(); -} - -void CurveEditorView::zoomX(double zoom) -{ - applyZoom(zoom, m_zoomY); - update(); -} - -void CurveEditorView::zoomY(double zoom) -{ - applyZoom(m_zoomX, zoom); - update(); -} - -void CurveEditorView::resizeEvent(QResizeEvent *event) -{ - updateSceneRect(); - applyZoom(m_zoomX, m_zoomY); - QGraphicsView::resizeEvent(event); -} - -void CurveEditorView::contextMenuEvent(QContextMenuEvent *event) -{ - Q_UNUSED(event); - - auto openStyleEditor = [this]() { m_dialog.show(); }; - - QMenu menu; - QAction *openEditorAction = menu.addAction(tr("Open Style Editor")); - connect(openEditorAction, &QAction::triggered, openStyleEditor); - - menu.exec(event->globalPos()); -} - -void CurveEditorView::drawForeground(QPainter *painter, const QRectF &rect) -{ - auto gap = QRectF(rect.topLeft(), QSizeF(m_style.valueAxisWidth, m_style.timeAxisHeight)); - - auto abscissa = QRectF(gap.topRight(), rect.topRight() + QPointF(0.0, gap.height())); - drawTimeScale(painter, abscissa); - - auto ordinate = QRectF(gap.bottomLeft(), rect.bottomLeft() + QPointF(gap.width(), 0.0)); - drawValueScale(painter, ordinate); - - painter->fillRect(gap, m_style.backgroundAlternateBrush); -} - -void CurveEditorView::drawBackground(QPainter *painter, const QRectF &rect) -{ - painter->fillRect(rect, m_style.backgroundBrush); - painter->fillRect(scene()->sceneRect(), m_style.backgroundAlternateBrush); - - drawGrid(painter, rect); - drawExtremaX(painter, rect); - drawExtremaY(painter, rect); -} - -int CurveEditorView::mapTimeToX(double time) -{ - return std::round(time * scaleX(m_transform)); -} - -int CurveEditorView::mapValueToY(double y) -{ - return std::round(y * scaleY(m_transform)); -} - -double CurveEditorView::mapXtoTime(int x) -{ - return static_cast(x) / scaleX(m_transform); -} - -double CurveEditorView::mapYtoValue(int y) -{ - return static_cast(y) / scaleY(m_transform); -} - -void CurveEditorView::applyZoom(double x, double y) -{ - m_zoomX = x; - m_zoomY = y; - - double canvasWidth = rect().width() - m_style.valueAxisWidth - 2 * m_style.canvasMargin - rect().width() / 20.0; - double xZoomedOut = canvasWidth / (m_model->maximumTime() - m_model->minimumTime()); - double xZoomedIn = m_style.zoomInWidth; - double scaleX = lerp(clamp(m_zoomX, 0.0, 1.0), xZoomedOut, xZoomedIn); - - double canvasHeight = rect().height() - m_style.timeAxisHeight - 2 * m_style.canvasMargin - rect().height() / 10; - double yZoomedOut = canvasHeight / (m_model->maximumValue() - m_model->minimumValue()); - double yZoomedIn = m_style.zoomInHeight; - double scaleY = lerp(clamp(m_zoomY, 0.0, 1.0), -yZoomedOut, -yZoomedIn); - - m_transform = QTransform::fromScale(scaleX, scaleY); - - QRectF sceneBounds; - for (auto *item : items()) - if (auto *curveItem = qgraphicsitem_cast(item)) - sceneBounds = sceneBounds.united(curveItem->setComponentTransform(m_transform)); - - updateSceneRect(sceneBounds); -} - -void CurveEditorView::updateSceneRect(const QRectF &rect) -{ - if (rect.isValid()) - scene()->setSceneRect(rect); - - QRectF sr = scene()->sceneRect().adjusted( - -m_style.valueAxisWidth - m_style.canvasMargin, - -m_style.timeAxisHeight - m_style.canvasMargin, - m_style.canvasMargin, - m_style.canvasMargin); - - setSceneRect(sr); -} - -void CurveEditorView::drawGrid(QPainter *painter, const QRectF &rect) -{ - painter->save(); - painter->setPen(m_style.gridColor); - - QRectF gridRect = rect.adjusted( - m_style.valueAxisWidth + m_style.canvasMargin, - m_style.timeAxisHeight + m_style.canvasMargin, - -m_style.canvasMargin, - -m_style.canvasMargin); - - auto drawVerticalLine = [painter, gridRect](double position) { - painter->drawLine(position, gridRect.top(), position, gridRect.bottom()); - }; - - double timeIncrement = timeLabelInterval(painter, m_model->maximumTime()); - for (double i = m_model->minimumTime(); i <= m_model->maximumTime(); i += timeIncrement) - drawVerticalLine(mapTimeToX(i)); - - painter->restore(); -} - -void CurveEditorView::drawExtremaX(QPainter *painter, const QRectF &rect) -{ - auto drawVerticalLine = [rect, painter](double position) { - painter->drawLine(position, rect.top(), position, rect.bottom()); - }; - - painter->save(); - painter->setPen(Qt::red); - drawVerticalLine(mapTimeToX(m_model->minimumTime())); - drawVerticalLine(mapTimeToX(m_model->maximumTime())); - painter->restore(); -} - -void CurveEditorView::drawExtremaY(QPainter *painter, const QRectF &rect) -{ - auto drawHorizontalLine = [rect, painter](double position) { - painter->drawLine(rect.left(), position, rect.right(), position); - }; - - painter->save(); - painter->setPen(Qt::blue); - drawHorizontalLine(mapValueToY(m_model->minimumValue())); - drawHorizontalLine(mapValueToY(m_model->maximumValue())); - - drawHorizontalLine(mapValueToY(0.0)); - - painter->restore(); -} - -void CurveEditorView::drawTimeScale(QPainter *painter, const QRectF &rect) -{ - painter->save(); - painter->setPen(m_style.fontColor); - painter->fillRect(rect, m_style.backgroundAlternateBrush); - - QFontMetrics fm(painter->font()); - - auto paintLabeledTick = [this, painter, rect, fm](double time) { - QString timeText = QString("%1").arg(time); - - int position = mapTimeToX(time); - - QRect textRect = fm.boundingRect(timeText); - textRect.moveCenter(QPoint(position, rect.center().y())); - painter->drawText(textRect, Qt::AlignCenter, timeText); - painter->drawLine(position, rect.bottom() - 2, position, textRect.bottom() + 2); - }; - - double timeIncrement = timeLabelInterval(painter, m_model->maximumTime()); - for (double i = m_model->minimumTime(); i <= m_model->maximumTime(); i += timeIncrement) - paintLabeledTick(i); - - painter->restore(); -} - -void CurveEditorView::drawValueScale(QPainter *painter, const QRectF &rect) -{ - painter->save(); - painter->setPen(m_style.fontColor); - painter->fillRect(rect, m_style.backgroundAlternateBrush); - - QFontMetrics fm(painter->font()); - auto paintLabeledTick = [this, painter, rect, fm](double value) { - QString valueText = QString("%1").arg(value); - - int position = mapValueToY(value); - - QRect textRect = fm.boundingRect(valueText); - textRect.moveCenter(QPoint(rect.center().x(), position)); - painter->drawText(textRect, Qt::AlignCenter, valueText); - }; - - paintLabeledTick(m_model->minimumValue()); - paintLabeledTick(m_model->maximumValue()); - painter->restore(); -} - -double CurveEditorView::timeLabelInterval(QPainter *painter, double maxTime) -{ - QFontMetrics fm(painter->font()); - int minTextSpacing = fm.width(QString("X%1X").arg(maxTime)); - - int deltaTime = 1; - int nextFactor = 5; - - double tickDistance = mapTimeToX(deltaTime); - while (true) { - if (tickDistance > minTextSpacing) - break; - - deltaTime *= nextFactor; - tickDistance = mapTimeToX(deltaTime); - - if (nextFactor == 5) - nextFactor = 2; - else - nextFactor = 5; - } - return deltaTime; -} - -} // End namespace DesignTools. diff --git a/src/curveeditor/curveeditorview.h b/src/curveeditor/curveeditorview.h deleted file mode 100644 index fe35933..0000000 --- a/src/curveeditor/curveeditorview.h +++ /dev/null @@ -1,101 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2019 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the Qt Design Tooling -** -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -****************************************************************************/ - -#pragma once - -#include "curveeditorstyle.h" -#include "curveeditorstyledialog.h" - -#include -#include - -namespace DesignTools { - -class CurveEditorModel; - -class CurveEditorView : public QGraphicsView -{ - Q_OBJECT - -public: - CurveEditorView(CurveEditorModel *model, QWidget *parent = nullptr); - - void setStyle(const CurveEditorStyle &style); - - void zoomX(double zoom); - - void zoomY(double zoom); - -protected: - void resizeEvent(QResizeEvent *event) override; - - void contextMenuEvent(QContextMenuEvent *event) override; - - void drawForeground(QPainter *painter, const QRectF &rect) override; - - void drawBackground(QPainter *painter, const QRectF &rect) override; - -private: - int mapTimeToX(double time); - - int mapValueToY(double value); - - double mapXtoTime(int x); - - double mapYtoValue(int y); - - void applyZoom(double x, double y); - - void updateSceneRect(const QRectF &rect = QRectF()); - - void drawGrid(QPainter *painter, const QRectF &rect); - - void drawExtremaX(QPainter *painter, const QRectF &rect); - - void drawExtremaY(QPainter *painter, const QRectF &rect); - - void drawTimeScale(QPainter *painter, const QRectF &rect); - - void drawValueScale(QPainter *painter, const QRectF &rect); - - double timeLabelInterval(QPainter *painter, double maxTime); - -private: - QGraphicsScene m_scene; - - CurveEditorStyle m_style; - - CurveEditorModel *m_model; - - CurveEditorStyleDialog m_dialog; - - double m_zoomX; - - double m_zoomY; - - QTransform m_transform; -}; - -} // End namespace DesignTools. diff --git a/src/curveeditor/curveitem.cpp b/src/curveeditor/curveitem.cpp deleted file mode 100644 index 128b60e..0000000 --- a/src/curveeditor/curveitem.cpp +++ /dev/null @@ -1,141 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2019 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the Qt Design Tooling -** -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -****************************************************************************/ -#include "curveitem.h" -#include "keyframeitem.h" -#include "utils.h" - -#include -#include - -namespace DesignTools { - -CurveItem::CurveItem(QGraphicsItem *parent) - : QGraphicsObject(parent) - , m_transform() - , m_keyframes() -{} - -CurveItem::CurveItem(const AnimationCurve &curve, QGraphicsItem *parent) - : QGraphicsObject(parent) - , m_transform() - , m_keyframes() -{ - auto emitCurveChanged = [this]() { - update(); - emit curveChanged(this->curve()); - }; - - for (auto frame : curve.keyframes()) { - auto *item = new KeyframeItem(frame, this); - connect(item, &KeyframeItem::keyframeChanged, emitCurveChanged); - m_keyframes.push_back(item); - } -} - -CurveItem::~CurveItem() {} - -int CurveItem::type() const -{ - return Type; -} - -QRectF CurveItem::boundingRect() const -{ - QRectF bounds; - - auto bbox = [&bounds](const Keyframe &frame) { - grow(bounds, frame.position()); - grow(bounds, frame.leftHandle()); - grow(bounds, frame.rightHandle()); - }; - - for (auto *item : m_keyframes) - bbox(item->keyframe()); - - return m_transform.mapRect(bounds); -} - -void CurveItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *, QWidget *) -{ - if (m_keyframes.size() > 1) { - painter->save(); - - QPen pen = painter->pen(); - pen.setWidthF(m_style.width); - pen.setColor(isSelected() ? m_style.selectionColor : m_style.color); - painter->setPen(pen); - - Keyframe previous = m_keyframes.front()->keyframe(); - Keyframe current; - for (size_t i = 1; i < m_keyframes.size(); ++i) { - current = m_keyframes[i]->keyframe(); - - QPainterPath path(m_transform.map(previous.position())); - - if (previous.rightHandle().isNull() || current.leftHandle().isNull()) - path.lineTo(m_transform.map(current.position())); - else - path.cubicTo( - m_transform.map(previous.rightHandle()), - m_transform.map(current.leftHandle()), - m_transform.map(current.position())); - - painter->drawPath(path); - - previous = current; - } - - painter->restore(); - } -} - -AnimationCurve CurveItem::curve() const -{ - std::vector out; - for (auto item : m_keyframes) { - out.push_back(item->keyframe()); - } - return out; -} - -QRectF CurveItem::setComponentTransform(const QTransform &transform) -{ - prepareGeometryChange(); - m_transform = transform; - for (auto frame : m_keyframes) - frame->setComponentTransform(transform); - - return boundingRect(); -} - -void CurveItem::setStyle(const CurveEditorStyle &style) -{ - m_style = style.curveStyle; - - for (auto *frame : m_keyframes) - frame->setStyle(style); -} - -} // End namespace DesignTools. diff --git a/src/curveeditor/curveitem.h b/src/curveeditor/curveitem.h deleted file mode 100644 index bae12e8..0000000 --- a/src/curveeditor/curveitem.h +++ /dev/null @@ -1,75 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2019 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the Qt Design Tooling -** -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -****************************************************************************/ - -#pragma once - -#include "animationcurve.h" -#include "curveeditorstyle.h" - -#include - -namespace DesignTools { - -class KeyframeItem; - -class CurveItem : public QGraphicsObject -{ - Q_OBJECT - -signals: - void curveChanged(const AnimationCurve &curve); - -public: - CurveItem(QGraphicsItem *parent = nullptr); - - CurveItem(const AnimationCurve &curve, QGraphicsItem *parent = nullptr); - - ~CurveItem() override; - - enum { Type = UserType + 1 }; - - int type() const override; - - QRectF boundingRect() const override; - - void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = nullptr) override; - - AnimationCurve curve() const; - - QRectF setComponentTransform(const QTransform &transform); - - void setStyle(const CurveEditorStyle &style); - -private: - QTransform m_transform; - - CurveItemStyleOption m_style; - - AnimationCurve m_curve; - - std::vector m_keyframes; -}; - -} // End namespace DesignTools. diff --git a/src/curveeditor/detail/colorcontrol.cpp b/src/curveeditor/detail/colorcontrol.cpp new file mode 100644 index 0000000..a833a4c --- /dev/null +++ b/src/curveeditor/detail/colorcontrol.cpp @@ -0,0 +1,101 @@ +/**************************************************************************** +** +** Copyright (C) 2019 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt Design Tooling +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ +#include "colorcontrol.h" + +#include +#include +#include +#include +#include + +namespace DesignTools { + +ColorControl::ColorControl() + : QWidget(nullptr) + , m_color(Qt::black) +{ + setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed); + setFixedHeight(20); +} + +ColorControl::ColorControl(const QColor &color, QWidget *parent) + : QWidget(parent) + , m_color(color) +{ + setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed); + setFixedHeight(20); +} + +ColorControl::~ColorControl() = default; + +QColor ColorControl::value() const +{ + return m_color; +} + +void ColorControl::setValue(const QColor &val) +{ + m_color = val; +} + +bool ColorControl::event(QEvent *event) +{ + if (event->type() == QEvent::ToolTip) { + if (auto helpEvent = static_cast(event)) { + QToolTip::showText(helpEvent->globalPos(), m_color.name()); + return true; + } + } + return QWidget::event(event); +} + +void ColorControl::paintEvent(QPaintEvent *event) +{ + QPainter painter(this); + painter.fillRect(event->rect(), m_color); +} + +void ColorControl::mouseReleaseEvent(QMouseEvent *event) +{ + QColor color = QColorDialog::getColor(m_color, this); + + event->accept(); + + if (color != m_color) { + m_color = color; + update(); + emit valueChanged(); + } +} + +void ColorControl::mousePressEvent(QMouseEvent *event) +{ + // Required if embedded in a QGraphicsProxywidget + // in order to call mouseRelease properly. + QWidget::mousePressEvent(event); + event->accept(); +} + +} // End namespace DesignTools. diff --git a/src/curveeditor/detail/colorcontrol.h b/src/curveeditor/detail/colorcontrol.h new file mode 100644 index 0000000..54dfe19 --- /dev/null +++ b/src/curveeditor/detail/colorcontrol.h @@ -0,0 +1,63 @@ +/**************************************************************************** +** +** Copyright (C) 2019 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt Design Tooling +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ + +#pragma once + +#include + +namespace DesignTools { + +class ColorControl : public QWidget +{ + Q_OBJECT + +public: + ColorControl(); + + ColorControl(const QColor &color, QWidget *parent = nullptr); + + ~ColorControl() override; + + QColor value() const; + + void setValue(const QColor &val); + +protected: + bool event(QEvent *event) override; + + void paintEvent(QPaintEvent *event) override; + + void mouseReleaseEvent(QMouseEvent *event) override; + + void mousePressEvent(QMouseEvent *event) override; + +signals: + void valueChanged(); + +private: + QColor m_color; +}; + +} // End namespace DesignTools. diff --git a/src/curveeditor/detail/curveeditorstyledialog.cpp b/src/curveeditor/detail/curveeditorstyledialog.cpp new file mode 100644 index 0000000..fc34737 --- /dev/null +++ b/src/curveeditor/detail/curveeditorstyledialog.cpp @@ -0,0 +1,245 @@ +/**************************************************************************** +** +** Copyright (C) 2019 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt Design Tooling +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ +#include "curveeditorstyledialog.h" +#include "colorcontrol.h" +#include "curveeditorstyle.h" + +#include +#include +#include +#include +#include +#include + +namespace DesignTools { + +QHBoxLayout *createRow(const QString &title, QWidget *widget) +{ + auto *label = new QLabel(title); + label->setFixedWidth(200); + label->setAlignment(Qt::AlignRight); + + auto *box = new QHBoxLayout; + box->addWidget(label); + box->addWidget(widget); + return box; +} + +CurveEditorStyleDialog::CurveEditorStyleDialog(CurveEditorStyle &style, QWidget *parent) + : QDialog(parent) + , m_printButton(new QPushButton("Print")) + , m_background(new ColorControl(style.backgroundBrush.color())) + , m_backgroundAlternate(new ColorControl(style.backgroundAlternateBrush.color())) + , m_fontColor(new ColorControl(style.fontColor)) + , m_gridColor(new ColorControl(style.gridColor)) + , m_canvasMargin(new QDoubleSpinBox()) + , m_zoomInWidth(new QSpinBox()) + , m_zoomInHeight(new QSpinBox()) + , m_timeAxisHeight(new QDoubleSpinBox()) + , m_timeOffsetLeft(new QDoubleSpinBox()) + , m_timeOffsetRight(new QDoubleSpinBox()) + , m_rangeBarColor(new ColorControl(style.rangeBarCapsColor)) + , m_rangeBarCapsColor(new ColorControl(style.rangeBarCapsColor)) + , m_valueAxisWidth(new QDoubleSpinBox()) + , m_valueOffsetTop(new QDoubleSpinBox()) + , m_valueOffsetBottom(new QDoubleSpinBox()) + , m_playhead(new ColorControl(style.playheadColor)) + , m_handleSize(new QDoubleSpinBox()) + , m_handleLineWidth(new QDoubleSpinBox()) + , m_handleColor(new ColorControl(style.handleStyle.color)) + , m_handleSelectionColor(new ColorControl(style.handleStyle.selectionColor)) + , m_keyframeSize(new QDoubleSpinBox()) + , m_keyframeColor(new ColorControl(style.keyframeStyle.color)) + , m_keyframeSelectionColor(new ColorControl(style.keyframeStyle.selectionColor)) + , m_curveWidth(new QDoubleSpinBox()) + , m_curveColor(new ColorControl(style.curveStyle.color)) + , m_curveSelectionColor(new ColorControl(style.curveStyle.selectionColor)) +{ + m_canvasMargin->setValue(style.canvasMargin); + m_zoomInWidth->setValue(style.zoomInWidth); + m_zoomInHeight->setValue(style.zoomInHeight); + m_timeAxisHeight->setValue(style.timeAxisHeight); + m_timeOffsetLeft->setValue(style.timeOffsetLeft); + m_timeOffsetRight->setValue(style.timeOffsetRight); + m_valueAxisWidth->setValue(style.valueAxisWidth); + m_valueOffsetTop->setValue(style.valueOffsetTop); + m_valueOffsetBottom->setValue(style.valueOffsetBottom); + m_handleSize->setValue(style.handleStyle.size); + m_handleLineWidth->setValue(style.handleStyle.lineWidth); + m_keyframeSize->setValue(style.keyframeStyle.size); + m_curveWidth->setValue(style.curveStyle.width); + + connect(m_printButton, &QPushButton::released, this, &CurveEditorStyleDialog::printStyle); + + auto intChanged = [this](int) { emitStyleChanged(); }; + auto doubleChanged = [this](double) { emitStyleChanged(); }; + auto colorChanged = [this]() { emitStyleChanged(); }; + + auto intSignal = static_cast(&QSpinBox::valueChanged); + auto doubleSignal = static_cast(&QDoubleSpinBox::valueChanged); + + connect(m_background, &ColorControl::valueChanged, colorChanged); + connect(m_backgroundAlternate, &ColorControl::valueChanged, colorChanged); + connect(m_fontColor, &ColorControl::valueChanged, colorChanged); + connect(m_gridColor, &ColorControl::valueChanged, colorChanged); + connect(m_canvasMargin, doubleSignal, doubleChanged); + connect(m_zoomInWidth, intSignal, intChanged); + connect(m_zoomInHeight, intSignal, intChanged); + connect(m_timeAxisHeight, doubleSignal, doubleChanged); + connect(m_timeOffsetLeft, doubleSignal, doubleChanged); + connect(m_timeOffsetRight, doubleSignal, doubleChanged); + connect(m_rangeBarColor, &ColorControl::valueChanged, colorChanged); + connect(m_rangeBarCapsColor, &ColorControl::valueChanged, colorChanged); + connect(m_valueAxisWidth, doubleSignal, doubleChanged); + connect(m_valueOffsetTop, doubleSignal, doubleChanged); + connect(m_valueOffsetBottom, doubleSignal, doubleChanged); + connect(m_playhead, &ColorControl::valueChanged, colorChanged); + connect(m_handleSize, doubleSignal, doubleChanged); + connect(m_handleLineWidth, doubleSignal, doubleChanged); + connect(m_handleColor, &ColorControl::valueChanged, colorChanged); + connect(m_handleSelectionColor, &ColorControl::valueChanged, colorChanged); + connect(m_keyframeSize, doubleSignal, doubleChanged); + connect(m_keyframeColor, &ColorControl::valueChanged, colorChanged); + connect(m_keyframeSelectionColor, &ColorControl::valueChanged, colorChanged); + connect(m_curveWidth, doubleSignal, doubleChanged); + connect(m_curveColor, &ColorControl::valueChanged, colorChanged); + connect(m_curveSelectionColor, &ColorControl::valueChanged, colorChanged); + + auto *box = new QVBoxLayout; + box->addLayout(createRow("Background Color", m_background)); + box->addLayout(createRow("Alternate Background Color", m_backgroundAlternate)); + box->addLayout(createRow("Font Color", m_fontColor)); + box->addLayout(createRow("Grid Color", m_gridColor)); + box->addLayout(createRow("Canvas Margin", m_canvasMargin)); + box->addLayout(createRow("Zoom In Width", m_zoomInWidth)); + box->addLayout(createRow("Zoom In Height", m_zoomInHeight)); + box->addLayout(createRow("Time Axis Height", m_timeAxisHeight)); + box->addLayout(createRow("Time Axis Left Offset", m_timeOffsetLeft)); + box->addLayout(createRow("Time Axis Right Offset", m_timeOffsetRight)); + box->addLayout(createRow("Range Bar Color", m_rangeBarColor)); + box->addLayout(createRow("Range Bar Caps Color", m_rangeBarCapsColor)); + box->addLayout(createRow("Value Axis Width", m_valueAxisWidth)); + box->addLayout(createRow("Value Axis Top Offset", m_valueOffsetTop)); + box->addLayout(createRow("Value Axis Bottom Offset", m_valueOffsetBottom)); + box->addLayout(createRow("Playhead Color", m_playhead)); + box->addLayout(createRow("Handle Size", m_handleSize)); + box->addLayout(createRow("Handle Line Width", m_handleLineWidth)); + box->addLayout(createRow("Handle Color", m_handleColor)); + box->addLayout(createRow("Handle Selection Color", m_handleSelectionColor)); + box->addLayout(createRow("Keyframe Size", m_keyframeSize)); + box->addLayout(createRow("Keyframe Color", m_keyframeColor)); + box->addLayout(createRow("Keyframe Selection Color", m_keyframeSelectionColor)); + box->addLayout(createRow("Curve Width", m_curveWidth)); + box->addLayout(createRow("Curve Color", m_curveColor)); + box->addLayout(createRow("Curve Selection Color", m_curveSelectionColor)); + + box->addWidget(m_printButton); + setLayout(box); +} + +CurveEditorStyle CurveEditorStyleDialog::style() const +{ + CurveEditorStyle style; + style.backgroundBrush = QBrush(m_background->value()); + style.backgroundAlternateBrush = QBrush(m_backgroundAlternate->value()); + style.fontColor = m_fontColor->value(); + style.gridColor = m_gridColor->value(); + style.canvasMargin = m_canvasMargin->value(); + style.zoomInWidth = m_zoomInWidth->value(); + style.zoomInHeight = m_zoomInHeight->value(); + style.timeAxisHeight = m_timeAxisHeight->value(); + style.timeOffsetLeft = m_timeOffsetLeft->value(); + style.timeOffsetRight = m_timeOffsetRight->value(); + style.rangeBarColor = m_rangeBarColor->value(); + style.rangeBarCapsColor = m_rangeBarCapsColor->value(); + style.valueAxisWidth = m_valueAxisWidth->value(); + style.valueOffsetTop = m_valueOffsetTop->value(); + style.valueOffsetBottom = m_valueOffsetBottom->value(); + style.playheadColor = m_playhead->value(); + style.handleStyle.size = m_handleSize->value(); + style.handleStyle.lineWidth = m_handleLineWidth->value(); + style.handleStyle.color = m_handleColor->value(); + style.handleStyle.selectionColor = m_handleSelectionColor->value(); + style.keyframeStyle.size = m_keyframeSize->value(); + style.keyframeStyle.color = m_keyframeColor->value(); + style.keyframeStyle.selectionColor = m_keyframeSelectionColor->value(); + style.curveStyle.width = m_curveWidth->value(); + style.curveStyle.color = m_curveColor->value(); + style.curveStyle.selectionColor = m_curveSelectionColor->value(); + return style; +} + +void CurveEditorStyleDialog::emitStyleChanged() +{ + emit styleChanged(style()); +} + +void CurveEditorStyleDialog::printStyle() +{ + auto toString = [](const QColor &color) { + QString tmp + = QString("QColor(%1, %2, %3)").arg(color.red()).arg(color.green()).arg(color.blue()); + return qPrintable(tmp); + }; + + CurveEditorStyle s = style(); + qDebug() << ""; + qDebug().nospace() << "CurveEditorStyle out;"; + qDebug().nospace() << "out.backgroundBrush = QBrush(" << toString(s.backgroundBrush.color()) + << ");"; + qDebug().nospace() << "out.backgroundAlternateBrush = QBrush(" + << toString(s.backgroundAlternateBrush.color()) << ");"; + qDebug().nospace() << "out.fontColor = " << toString(s.fontColor) << ";"; + qDebug().nospace() << "out.gridColor = " << toString(s.gridColor) << ";"; + qDebug().nospace() << "out.canvasMargin = " << s.canvasMargin << ";"; + qDebug().nospace() << "out.zoomInWidth = " << s.zoomInWidth << ";"; + qDebug().nospace() << "out.zoomInHeight = " << s.zoomInHeight << ";"; + qDebug().nospace() << "out.timeAxisHeight = " << s.timeAxisHeight << ";"; + qDebug().nospace() << "out.timeOffsetLeft = " << s.timeOffsetLeft << ";"; + qDebug().nospace() << "out.timeOffsetRight = " << s.timeOffsetRight << ";"; + qDebug().nospace() << "out.rangeBarColor = " << toString(s.rangeBarColor) << ";"; + qDebug().nospace() << "out.rangeBarCapsColor = " << toString(s.rangeBarCapsColor) << ";"; + qDebug().nospace() << "out.valueAxisWidth = " << s.valueAxisWidth << ";"; + qDebug().nospace() << "out.valueOffsetTop = " << s.valueOffsetTop << ";"; + qDebug().nospace() << "out.valueOffsetBottom = " << s.valueOffsetBottom << ";"; + qDebug().nospace() << "out.playheadColor = " << toString(s.playheadColor) << ";"; + qDebug().nospace() << "out.handleStyle.size = " << s.handleStyle.size << ";"; + qDebug().nospace() << "out.handleStyle.lineWidth = " << s.handleStyle.lineWidth << ";"; + qDebug().nospace() << "out.handleStyle.color = " << toString(s.handleStyle.color) << ";"; + qDebug().nospace() << "out.handleStyle.selectionColor = " + << toString(s.handleStyle.selectionColor) << ";"; + qDebug().nospace() << "out.keyframeStyle.size = " << s.keyframeStyle.size << ";"; + qDebug().nospace() << "out.keyframeStyle.color = " << toString(s.keyframeStyle.color) << ";"; + qDebug().nospace() << "out.keyframeStyle.selectionColor = " + << toString(s.keyframeStyle.selectionColor) << ";"; + qDebug().nospace() << "out.curveStyle.width = " << s.curveStyle.width << ";"; + qDebug().nospace() << "out.curveStyle.color = " << toString(s.curveStyle.color) << ";"; + qDebug().nospace() << "out.curveStyle.selectionColor = " + << toString(s.curveStyle.selectionColor) << ";"; + qDebug().nospace() << "return out;"; + qDebug() << ""; +} + +} // End namespace DesignTools. diff --git a/src/curveeditor/detail/curveeditorstyledialog.h b/src/curveeditor/detail/curveeditorstyledialog.h new file mode 100644 index 0000000..645f545 --- /dev/null +++ b/src/curveeditor/detail/curveeditorstyledialog.h @@ -0,0 +1,117 @@ + +/**************************************************************************** +** +** Copyright (C) 2019 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt Design Tooling +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ + +#pragma once + +#include + +class QPushButton; +class QSpinBox; +class QDoubleSpinBox; + +namespace DesignTools { + +class ColorControl; + +struct CurveEditorStyle; + +class CurveEditorStyleDialog : public QDialog +{ + Q_OBJECT + +signals: + void styleChanged(const CurveEditorStyle &style); + +public: + CurveEditorStyleDialog(CurveEditorStyle &style, QWidget *parent = nullptr); + + CurveEditorStyle style() const; + +private: + void emitStyleChanged(); + + void printStyle(); + +private: + QPushButton *m_printButton; + + ColorControl *m_background; + + ColorControl *m_backgroundAlternate; + + ColorControl *m_fontColor; + + ColorControl *m_gridColor; + + QDoubleSpinBox *m_canvasMargin; + + QSpinBox *m_zoomInWidth; + + QSpinBox *m_zoomInHeight; + + QDoubleSpinBox *m_timeAxisHeight; + + QDoubleSpinBox *m_timeOffsetLeft; + + QDoubleSpinBox *m_timeOffsetRight; + + ColorControl *m_rangeBarColor; + + ColorControl *m_rangeBarCapsColor; + + QDoubleSpinBox *m_valueAxisWidth; + + QDoubleSpinBox *m_valueOffsetTop; + + QDoubleSpinBox *m_valueOffsetBottom; + + ColorControl *m_playhead; + + // HandleItem + QDoubleSpinBox *m_handleSize; + + QDoubleSpinBox *m_handleLineWidth; + + ColorControl *m_handleColor; + + ColorControl *m_handleSelectionColor; + + // KeyframeItem + QDoubleSpinBox *m_keyframeSize; + + ColorControl *m_keyframeColor; + + ColorControl *m_keyframeSelectionColor; + + // CurveItem + QDoubleSpinBox *m_curveWidth; + + ColorControl *m_curveColor; + + ColorControl *m_curveSelectionColor; +}; + +} // End namespace DesignTools. diff --git a/src/curveeditor/detail/curveitem.cpp b/src/curveeditor/detail/curveitem.cpp new file mode 100644 index 0000000..2d8e462 --- /dev/null +++ b/src/curveeditor/detail/curveitem.cpp @@ -0,0 +1,216 @@ +/**************************************************************************** +** +** Copyright (C) 2019 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt Design Tooling +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ +#include "curveitem.h" +#include "animationcurve.h" +#include "keyframeitem.h" +#include "utils.h" + +#include +#include + +namespace DesignTools { + +CurveItem::CurveItem(QGraphicsItem *parent) + : QGraphicsObject(parent) + , m_id(0) + , m_style() + , m_transform() + , m_keyframes() + , m_selected(false) + , m_preselected(false) + , m_itemDirty(true) + , m_pathDirty(true) +{} + +CurveItem::CurveItem(unsigned int id, const AnimationCurve &curve, QGraphicsItem *parent) + : QGraphicsObject(parent) + , m_id(id) + , m_style() + , m_transform() + , m_keyframes() + , m_selected(false) + , m_preselected(false) + , m_itemDirty(true) + , m_pathDirty(true) +{ + setAcceptHoverEvents(true); + + auto emitCurveChanged = [this]() { + m_itemDirty = true; + m_pathDirty = true; + update(); + }; + + for (auto frame : curve.keyframes()) { + auto *item = new KeyframeItem(frame, this); + connect(item, &KeyframeItem::keyframeChanged, emitCurveChanged); + m_keyframes.push_back(item); + } +} + +CurveItem::~CurveItem() {} + +int CurveItem::type() const +{ + return Type; +} + +QRectF CurveItem::boundingRect() const +{ + auto bbox = [](QRectF &bounds, const Keyframe &frame) { + grow(bounds, frame.position()); + grow(bounds, frame.leftHandle()); + grow(bounds, frame.rightHandle()); + }; + + QRectF bounds; + for (auto *item : m_keyframes) + bbox(bounds, item->keyframe()); + + return m_transform.mapRect(bounds); +} + +bool CurveItem::contains(const QPointF &point) const +{ + bool valid = false; + QPointF transformed(m_transform.inverted(&valid).map(point)); + + double width = abs(20.0 / scaleY(m_transform)); + + if (valid) + return curve().intersects(transformed, width); + + return false; +} + +void CurveItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *, QWidget *) +{ + if (m_keyframes.size() > 1) { + QPen pen = painter->pen(); + pen.setWidthF(m_style.width); + pen.setColor(m_selected ? m_style.selectionColor : (m_preselected ? Qt::red : m_style.color)); + + painter->save(); + painter->setPen(pen); + painter->drawPath(path()); + + // Tmp. Remove later. + painter->setPen(Qt::red); + for (auto p : curve().extrema()) + painter->drawEllipse(m_transform.map(p), 6., 6.); + + painter->restore(); + } +} + +bool CurveItem::isDirty() const +{ + return m_itemDirty; +} + +unsigned int CurveItem::id() const +{ + return m_id; +} + +AnimationCurve CurveItem::curve() const +{ + std::vector out; + out.reserve(m_keyframes.size()); + for (auto item : m_keyframes) + out.push_back(item->keyframe()); + + return out; +} + +void CurveItem::setDirty(bool dirty) +{ + m_itemDirty = dirty; +} + +QRectF CurveItem::setComponentTransform(const QTransform &transform) +{ + m_pathDirty = true; + + prepareGeometryChange(); + m_transform = transform; + for (auto frame : m_keyframes) + frame->setComponentTransform(transform); + + return boundingRect(); +} + +void CurveItem::setStyle(const CurveEditorStyle &style) +{ + m_style = style.curveStyle; + + for (auto *frame : m_keyframes) + frame->setStyle(style); +} + +QPainterPath CurveItem::path() const +{ + if (m_pathDirty) { + Keyframe previous = m_keyframes.front()->keyframe(); + Keyframe current; + + m_path = QPainterPath(m_transform.map(previous.position())); + for (size_t i = 1; i < m_keyframes.size(); ++i) { + current = m_keyframes[i]->keyframe(); + + if (previous.rightHandle().isNull() || current.leftHandle().isNull()) { + m_path.lineTo(m_transform.map(current.position())); + } else { + m_path.cubicTo( + m_transform.map(previous.rightHandle()), + m_transform.map(current.leftHandle()), + m_transform.map(current.position())); + } + + previous = current; + } + m_pathDirty = false; + } + + return m_path; +} + +void CurveItem::setSelected(bool select) +{ + if (select != m_selected) { + m_selected = select; + update(); + } +} + +void CurveItem::setPreSelected(bool preSelect) +{ + if (preSelect != m_preselected) { + m_preselected = preSelect; + update(); + } +} + +} // End namespace DesignTools. diff --git a/src/curveeditor/detail/curveitem.h b/src/curveeditor/detail/curveitem.h new file mode 100644 index 0000000..cf9b29f --- /dev/null +++ b/src/curveeditor/detail/curveitem.h @@ -0,0 +1,97 @@ +/**************************************************************************** +** +** Copyright (C) 2019 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt Design Tooling +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ + +#pragma once + +#include "curveeditorstyle.h" + +#include + +namespace DesignTools { + +class AnimationCurve; +class KeyframeItem; + +class CurveItem : public QGraphicsObject +{ + Q_OBJECT + +public: + CurveItem(QGraphicsItem *parent = nullptr); + + CurveItem(unsigned int id, const AnimationCurve &curve, QGraphicsItem *parent = nullptr); + + ~CurveItem() override; + + enum { Type = UserType + 1 }; + + int type() const override; + + QRectF boundingRect() const override; + + bool contains(const QPointF &point) const override; + + void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = nullptr) override; + + bool isDirty() const; + + unsigned int id() const; + + AnimationCurve curve() const; + + void setDirty(bool dirty); + + QRectF setComponentTransform(const QTransform &transform); + + void setStyle(const CurveEditorStyle &style); + + void setSelected(bool select); + + void setPreSelected(bool preSelect); + +private: + QPainterPath path() const; + +private: + unsigned int m_id; + + CurveItemStyleOption m_style; + + QTransform m_transform; + + std::vector m_keyframes; + + bool m_selected; + + bool m_preselected; + + bool m_itemDirty; + + mutable bool m_pathDirty; + + mutable QPainterPath m_path; +}; + +} // End namespace DesignTools. diff --git a/src/curveeditor/detail/curvesegment.cpp b/src/curveeditor/detail/curvesegment.cpp new file mode 100644 index 0000000..1bd0ad9 --- /dev/null +++ b/src/curveeditor/detail/curvesegment.cpp @@ -0,0 +1,280 @@ +/**************************************************************************** +** +** Copyright (C) 2019 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt Design Tooling +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ + +#include "curvesegment.h" + +#include + +#include + +namespace DesignTools { + +class CubicPolynomial +{ +public: + CubicPolynomial(double p0, double p1, double p2, double p3); + + double evaluate(double x) const; + + std::vector extrema() const; + + std::vector roots() const; + +private: + double m_a; + double m_b; + double m_c; + double m_d; +}; + +CubicPolynomial::CubicPolynomial(double p0, double p1, double p2, double p3) + : m_a(p3 - 3.0 * p2 + 3.0 * p1 - p0) + , m_b(3.0 * p2 - 6.0 * p1 + 3.0 * p0) + , m_c(3.0 * p1 - 3.0 * p0) + , m_d(p0) +{} + +std::vector CubicPolynomial::extrema() const +{ + std::vector out; + + auto addValidValue = [&out](double value) { + if (!(std::isnan(value) || std::isinf(value))) + out.push_back(value); + }; + + // Find the roots of the first derivative of y. + auto pd2 = (2.0 * m_b) / (3.0 * m_a) / 2.0; + auto q = m_c / (3.0 * m_a); + + auto radi = std::pow(pd2, 2.0) - q; + + auto x1 = -pd2 + std::sqrt(radi); + auto x2 = -pd2 - std::sqrt(radi); + + addValidValue(x1); + addValidValue(x2); + + return out; +} + +std::vector CubicPolynomial::roots() const +{ + std::vector out; + + auto addValidValue = [&out](double value) { + if (!(std::isnan(value) || std::isinf(value))) + out.push_back(value); + }; + + if (m_a == 0.0) { + // Linear + if (m_b == 0.0) { + if (m_c != 0.0) + out.push_back(-m_d / m_c); + // Quadratic + } else { + const double p = m_c / m_b / 2.0; + const double q = m_d / m_b; + addValidValue(-p + std::sqrt(std::pow(p, 2.0) - q)); + addValidValue(-p - std::sqrt(std::pow(p, 2.0) - q)); + } + // Cubic + } else { + const double p = 3.0 * m_a * m_c - std::pow(m_b, 2.0); + const double q = 2.0 * std::pow(m_b, 3.0) - 9.0 * m_a * m_b * m_c + + 27.0 * std::pow(m_a, 2.0) * m_d; + + auto disc = std::pow(q, 2.0) + 4.0 * std::pow(p, 3.0); + + auto toX = [&](double y) { return (y - m_b) / (3.0 * m_a); }; + + // One real solution. + if (disc >= 0) { + auto u = (1.0 / 2.0) + * std::cbrt(-4.0 * q + + 4.0 * std::sqrt(std::pow(q, 2.0) + 4.0 * std::pow(p, 3.0))); + auto v = (1.0 / 2.0) + * std::cbrt(-4.0 * q + - 4.0 * std::sqrt(std::pow(q, 2.0) + 4.0 * std::pow(p, 3.0))); + + addValidValue(toX(u + v)); + // Three real solutions. + } else { + auto phi = acos(-q / (2 * std::sqrt(-std::pow(p, 3.0)))); + auto y1 = std::sqrt(-p) * 2.0 * cos(phi / 3.0); + auto y2 = std::sqrt(-p) * 2.0 * cos((phi / 3.0) + (2.0 * M_PI / 3.0)); + auto y3 = std::sqrt(-p) * 2.0 * cos((phi / 3.0) + (4.0 * M_PI / 3.0)); + + addValidValue(toX(y1)); + addValidValue(toX(y2)); + addValidValue(toX(y3)); + } + } + return out; +} + +CurveSegment::CurveSegment() + : m_left() + , m_right() +{} + +CurveSegment::CurveSegment(const Keyframe &left, const Keyframe &right) + : m_left(left) + , m_right(right) +{} + +bool CurveSegment::containsX(double x) const +{ + return m_left.position().x() <= x && m_right.position().x() >= x; +} + +double evaluateForT(double t, double p0, double p1, double p2, double p3) +{ + assert(t >= 0. && t <= 1.); + + const double it = 1.0 - t; + + return p0 * std::pow(it, 3.0) + p1 * 3.0 * std::pow(it, 2.0) * t + + p2 * 3.0 * it * std::pow(t, 2.0) + p3 * std::pow(t, 3.0); +} + +QPointF CurveSegment::evaluate(double t) const +{ + const double x = evaluateForT( + t, + m_left.position().x(), + m_left.rightHandle().x(), + m_right.leftHandle().x(), + m_right.position().x()); + + const double y = evaluateForT( + t, + m_left.position().y(), + m_left.rightHandle().y(), + m_right.leftHandle().y(), + m_right.position().y()); + + return QPointF(x, y); +} + +std::vector CurveSegment::extrema() const +{ + std::vector out; + + auto polynomial = CubicPolynomial( + m_left.position().y(), + m_left.rightHandle().y(), + m_right.leftHandle().y(), + m_right.position().y()); + + for (double t : polynomial.extrema()) { + if (t < 0.0 || t > 1.0) + continue; + + const double x = evaluateForT( + t, + m_left.position().x(), + m_left.rightHandle().x(), + m_right.leftHandle().x(), + m_right.position().x()); + + const double y = evaluateForT( + t, + m_left.position().y(), + m_left.rightHandle().y(), + m_right.leftHandle().y(), + m_right.position().y()); + + out.push_back(QPointF(x, y)); + } + return out; +} + +std::vector CurveSegment::yForX(double x) const +{ + std::vector out; + + auto polynomial = CubicPolynomial( + m_left.position().x() - x, + m_left.rightHandle().x() - x, + m_right.leftHandle().x() - x, + m_right.position().x() - x); + + for (double t : polynomial.roots()) { + if (t < 0.0 || t > 1.0) + continue; + + const double y = evaluateForT( + t, + m_left.position().y(), + m_left.rightHandle().y(), + m_right.leftHandle().y(), + m_right.position().y()); + + out.push_back(y); + } + + return out; +} + +std::vector CurveSegment::xForY(double y) const +{ + std::vector out; + + auto polynomial = CubicPolynomial( + m_left.position().y() - y, + m_left.rightHandle().y() - y, + m_right.leftHandle().y() - y, + m_right.position().y() - y); + + for (double t : polynomial.roots()) { + if (t < 0.0 || t > 1.0) + continue; + + const double x = evaluateForT( + t, + m_left.position().x(), + m_left.rightHandle().x(), + m_right.leftHandle().x(), + m_right.position().x()); + + out.push_back(x); + } + + return out; +} + +void CurveSegment::setLeft(const Keyframe &frame) +{ + m_left = frame; +} + +void CurveSegment::setRight(const Keyframe &frame) +{ + m_right = frame; +} + +} // End namespace DesignTools. diff --git a/src/curveeditor/detail/curvesegment.h b/src/curveeditor/detail/curvesegment.h new file mode 100644 index 0000000..ce2d700 --- /dev/null +++ b/src/curveeditor/detail/curvesegment.h @@ -0,0 +1,63 @@ +/**************************************************************************** +** +** Copyright (C) 2019 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt Design Tooling +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ + +#pragma once + +#include "keyframe.h" + +#include + +class QPointF; + +namespace DesignTools { + +class CurveSegment +{ +public: + CurveSegment(); + + CurveSegment(const Keyframe &first, const Keyframe &last); + + bool containsX(double x) const; + + QPointF evaluate(double t) const; + + std::vector extrema() const; + + std::vector yForX(double x) const; + + std::vector xForY(double y) const; + + void setLeft(const Keyframe &frame); + + void setRight(const Keyframe &frame); + +private: + Keyframe m_left; + + Keyframe m_right; +}; + +} // End namespace DesignTools. diff --git a/src/curveeditor/detail/graphicsscene.cpp b/src/curveeditor/detail/graphicsscene.cpp new file mode 100644 index 0000000..ddafaf4 --- /dev/null +++ b/src/curveeditor/detail/graphicsscene.cpp @@ -0,0 +1,141 @@ +/**************************************************************************** +** +** Copyright (C) 2019 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt Design Tooling +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ + +#include "graphicsscene.h" +#include "animationcurve.h" +#include "curveitem.h" + +#include + +namespace DesignTools { + +GraphicsScene::GraphicsScene(QObject *parent) + : QGraphicsScene(parent) + , m_dirty(true) + , m_limits() +{} + +double GraphicsScene::minimumTime() const +{ + return limits().left(); +} + +double GraphicsScene::maximumTime() const +{ + return limits().right(); +} + +double GraphicsScene::minimumValue() const +{ + return limits().bottom(); +} + +double GraphicsScene::maximumValue() const +{ + return limits().top(); +} + +void GraphicsScene::addCurveItem(CurveItem *item) +{ + m_dirty = true; + addItem(item); +} + +void GraphicsScene::mouseMoveEvent(QGraphicsSceneMouseEvent *mouseEvent) +{ + QGraphicsScene::mouseMoveEvent(mouseEvent); + + if (!mouseEvent->isAccepted()) { + const auto itemList = items(); + for (auto *item : itemList) { + if (auto *curveItem = qgraphicsitem_cast(item)) { + curveItem->setPreSelected(curveItem->contains(mouseEvent->scenePos())); + } + } + } +} + +void GraphicsScene::mouseReleaseEvent(QGraphicsSceneMouseEvent *mouseEvent) +{ + QGraphicsScene::mouseReleaseEvent(mouseEvent); + + clearSelection(); + + const auto itemList = items(); + for (auto *item : itemList) { + if (auto *curveItem = qgraphicsitem_cast(item)) { + if (curveItem->contains(mouseEvent->scenePos())) + curveItem->setSelected(true); + + if (curveItem->isDirty()) { + m_dirty = true; + emit curveChanged(curveItem->id(), curveItem->curve()); + curveItem->setDirty(false); + } + } + } +} + +QRectF GraphicsScene::limits() const +{ + if (m_dirty) { + QPointF min(std::numeric_limits::max(), std::numeric_limits::max()); + QPointF max(std::numeric_limits::lowest(), std::numeric_limits::lowest()); + + const auto itemList = items(); + for (auto *item : itemList) { + if (auto *curveItem = qgraphicsitem_cast(item)) { + auto curve = curveItem->curve(); + if (min.x() > curve.minimumTime()) + min.rx() = curve.minimumTime(); + + if (min.y() > curve.minimumValue()) + min.ry() = curve.minimumValue(); + + if (max.x() < curve.maximumTime()) + max.rx() = curve.maximumTime(); + + if (max.y() < curve.maximumValue()) + max.ry() = curve.maximumValue(); + } + } + + m_limits = QRectF(QPointF(min.x(), max.y()), QPointF(max.x(), min.y())); + m_dirty = false; + } + return m_limits; +} + +void GraphicsScene::clearSelection() +{ + const auto itemList = items(); + for (auto *item : itemList) { + if (auto *curveItem = qgraphicsitem_cast(item)) { + curveItem->setSelected(false); + } + } +} + +} // End namespace DesignTools. diff --git a/src/curveeditor/detail/graphicsscene.h b/src/curveeditor/detail/graphicsscene.h new file mode 100644 index 0000000..7f80436 --- /dev/null +++ b/src/curveeditor/detail/graphicsscene.h @@ -0,0 +1,72 @@ +/**************************************************************************** +** +** Copyright (C) 2019 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt Design Tooling +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ + +#pragma once + +#include + +namespace DesignTools { + +class AnimationCurve; +class CurveItem; + +class GraphicsScene : public QGraphicsScene +{ + Q_OBJECT + +signals: + void curveChanged(unsigned int id, const AnimationCurve &curve); + +public: + GraphicsScene(QObject *parent = nullptr); + + double minimumTime() const; + + double maximumTime() const; + + double minimumValue() const; + + double maximumValue() const; + + void addCurveItem(CurveItem *item); + +protected: + void mouseMoveEvent(QGraphicsSceneMouseEvent *mouseEvent) override; + + void mouseReleaseEvent(QGraphicsSceneMouseEvent *mouseEvent) override; + +private: + using QGraphicsScene::addItem; + + QRectF limits() const; + + void clearSelection(); + + mutable bool m_dirty; + + mutable QRectF m_limits; +}; + +} // End namespace DesignTools. diff --git a/src/curveeditor/detail/graphicsview.cpp b/src/curveeditor/detail/graphicsview.cpp new file mode 100644 index 0000000..e6dfb11 --- /dev/null +++ b/src/curveeditor/detail/graphicsview.cpp @@ -0,0 +1,332 @@ +/**************************************************************************** +** +** Copyright (C) 2019 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt Design Tooling +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ +#include "graphicsview.h" +#include "curveeditormodel.h" +#include "curveitem.h" +#include "utils.h" + +#include +#include +#include + +#include + +namespace DesignTools { + +GraphicsView::GraphicsView(CurveEditorModel *model, QWidget *parent) + : QGraphicsView(parent) + , m_scene() + , m_style(model->style()) + , m_model(model) + , m_dialog(m_style, this) + , m_zoomX(0.0) + , m_zoomY(0.0) +{ + setScene(&m_scene); + setAlignment(Qt::AlignLeft | Qt::AlignVCenter); + setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOn); + setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOn); + setViewportUpdateMode(QGraphicsView::FullViewportUpdate); + + connect(&m_dialog, &CurveEditorStyleDialog::styleChanged, this, &GraphicsView::setStyle); + + auto itemSlot = [this](unsigned int id, const AnimationCurve &curve) { + applyZoom(m_zoomX, m_zoomY); + m_model->setCurve(id, curve); + }; + + connect(&m_scene, &GraphicsScene::curveChanged, itemSlot); + + applyZoom(m_zoomX, m_zoomY); + update(); +} + +void GraphicsView::setStyle(const CurveEditorStyle &style) +{ + m_style = style; + + const auto itemList = items(); + for (auto *item : itemList) { + if (auto *curveItem = qgraphicsitem_cast(item)) + curveItem->setStyle(style); + } + + applyZoom(m_zoomX, m_zoomY); + viewport()->update(); +} + +void GraphicsView::zoomX(double zoom) +{ + applyZoom(zoom, m_zoomY); + viewport()->update(); +} + +void GraphicsView::zoomY(double zoom) +{ + applyZoom(m_zoomX, zoom); + viewport()->update(); +} + +void GraphicsView::reset(const std::vector &items) +{ + m_scene.clear(); + for (auto *item : items) { + m_scene.addCurveItem(item); + } + + applyZoom(m_zoomX, m_zoomY); + viewport()->update(); +} + +void GraphicsView::resizeEvent(QResizeEvent *event) +{ + applyZoom(m_zoomX, m_zoomY); + QGraphicsView::resizeEvent(event); +} + +void GraphicsView::contextMenuEvent(QContextMenuEvent *event) +{ + Q_UNUSED(event); + + auto openStyleEditor = [this]() { m_dialog.show(); }; + + QMenu menu; + QAction *openEditorAction = menu.addAction(tr("Open Style Editor")); + connect(openEditorAction, &QAction::triggered, openStyleEditor); + + menu.exec(event->globalPos()); +} + +void GraphicsView::drawForeground(QPainter *painter, const QRectF &rect) +{ + auto gap = QRectF(rect.topLeft(), QSizeF(m_style.valueAxisWidth, m_style.timeAxisHeight)); + + auto abscissa = QRectF(gap.topRight(), rect.topRight() + QPointF(0.0, gap.height())); + if (abscissa.isValid()) + drawTimeScale(painter, abscissa); + + auto ordinate = QRectF(gap.bottomLeft(), rect.bottomLeft() + QPointF(gap.width(), 0.0)); + if (ordinate.isValid()) + drawValueScale(painter, ordinate); + + painter->fillRect(gap, m_style.backgroundAlternateBrush); +} + +void GraphicsView::drawBackground(QPainter *painter, const QRectF &rect) +{ + painter->fillRect(rect, m_style.backgroundBrush); + painter->fillRect(scene()->sceneRect(), m_style.backgroundAlternateBrush); + + drawGrid(painter, rect); + drawExtremaX(painter, rect); + drawExtremaY(painter, rect); +} + +int GraphicsView::mapTimeToX(double time) +{ + return std::round(time * scaleX(m_transform)); +} + +int GraphicsView::mapValueToY(double y) +{ + return std::round(y * scaleY(m_transform)); +} + +double GraphicsView::mapXtoTime(int x) +{ + return static_cast(x) / scaleX(m_transform); +} + +double GraphicsView::mapYtoValue(int y) +{ + return static_cast(y) / scaleY(m_transform); +} + +void GraphicsView::applyZoom(double x, double y) +{ + m_zoomX = x; + m_zoomY = y; + + double canvasWidth = rect().width() - m_style.valueAxisWidth - 2 * m_style.canvasMargin - rect().width() / 20.0; + double xZoomedOut = canvasWidth / (m_model->maximumTime() - m_model->minimumTime()); + double xZoomedIn = m_style.zoomInWidth; + double scaleX = lerp(clamp(m_zoomX, 0.0, 1.0), xZoomedOut, xZoomedIn); + + double canvasHeight = rect().height() - m_style.timeAxisHeight - 2 * m_style.canvasMargin - rect().height() / 10; + double yZoomedOut = canvasHeight / (m_scene.maximumValue() - m_scene.minimumValue()); + double yZoomedIn = m_style.zoomInHeight; + double scaleY = lerp(clamp(m_zoomY, 0.0, 1.0), -yZoomedOut, -yZoomedIn); + + m_transform = QTransform::fromScale(scaleX, scaleY); + + QRectF sceneBounds; + for (auto *item : items()) + if (auto *curveItem = qgraphicsitem_cast(item)) + sceneBounds = sceneBounds.united(curveItem->setComponentTransform(m_transform)); + + updateSceneRect(sceneBounds); +} + +void GraphicsView::updateSceneRect(const QRectF &rect) +{ + if (rect.isValid()) + scene()->setSceneRect(rect); + + QRectF sr = scene()->sceneRect().adjusted( + -m_style.valueAxisWidth - m_style.canvasMargin, + -m_style.timeAxisHeight - m_style.canvasMargin, + m_style.canvasMargin, + m_style.canvasMargin); + + setSceneRect(sr); +} + +void GraphicsView::drawGrid(QPainter *painter, const QRectF &rect) +{ + QRectF gridRect = rect.adjusted( + m_style.valueAxisWidth + m_style.canvasMargin, + m_style.timeAxisHeight + m_style.canvasMargin, + -m_style.canvasMargin, + -m_style.canvasMargin); + + if (!gridRect.isValid()) + return; + + auto drawVerticalLine = [painter, gridRect](double position) { + painter->drawLine(position, gridRect.top(), position, gridRect.bottom()); + }; + + painter->save(); + painter->setPen(m_style.gridColor); + + double timeIncrement = timeLabelInterval(painter, m_model->maximumTime()); + for (double i = m_model->minimumTime(); i <= m_model->maximumTime(); i += timeIncrement) + drawVerticalLine(mapTimeToX(i)); + + painter->restore(); +} + +void GraphicsView::drawExtremaX(QPainter *painter, const QRectF &rect) +{ + auto drawVerticalLine = [rect, painter](double position) { + painter->drawLine(position, rect.top(), position, rect.bottom()); + }; + + painter->save(); + painter->setPen(Qt::red); + drawVerticalLine(mapTimeToX(m_model->minimumTime())); + drawVerticalLine(mapTimeToX(m_model->maximumTime())); + painter->restore(); +} + +void GraphicsView::drawExtremaY(QPainter *painter, const QRectF &rect) +{ + auto drawHorizontalLine = [rect, painter](double position) { + painter->drawLine(rect.left(), position, rect.right(), position); + }; + + painter->save(); + painter->setPen(Qt::blue); + drawHorizontalLine(mapValueToY(m_scene.minimumValue())); + drawHorizontalLine(mapValueToY(m_scene.maximumValue())); + + drawHorizontalLine(mapValueToY(0.0)); + + painter->restore(); +} + +void GraphicsView::drawTimeScale(QPainter *painter, const QRectF &rect) +{ + painter->save(); + painter->setPen(m_style.fontColor); + painter->fillRect(rect, m_style.backgroundAlternateBrush); + + QFontMetrics fm(painter->font()); + + auto paintLabeledTick = [this, painter, rect, fm](double time) { + QString timeText = QString("%1").arg(time); + + int position = mapTimeToX(time); + + QRect textRect = fm.boundingRect(timeText); + textRect.moveCenter(QPoint(position, rect.center().y())); + painter->drawText(textRect, Qt::AlignCenter, timeText); + painter->drawLine(position, rect.bottom() - 2, position, textRect.bottom() + 2); + }; + + double timeIncrement = timeLabelInterval(painter, m_model->maximumTime()); + for (double i = m_model->minimumTime(); i <= m_model->maximumTime(); i += timeIncrement) + paintLabeledTick(i); + + painter->restore(); +} + +void GraphicsView::drawValueScale(QPainter *painter, const QRectF &rect) +{ + painter->save(); + painter->setPen(m_style.fontColor); + painter->fillRect(rect, m_style.backgroundAlternateBrush); + + QFontMetrics fm(painter->font()); + auto paintLabeledTick = [this, painter, rect, fm](double value) { + QString valueText = QString("%1").arg(value); + + int position = mapValueToY(value); + + QRect textRect = fm.boundingRect(valueText); + textRect.moveCenter(QPoint(rect.center().x(), position)); + painter->drawText(textRect, Qt::AlignCenter, valueText); + }; + + paintLabeledTick(m_scene.minimumValue()); + paintLabeledTick(m_scene.maximumValue()); + painter->restore(); +} + +double GraphicsView::timeLabelInterval(QPainter *painter, double maxTime) +{ + QFontMetrics fm(painter->font()); + int minTextSpacing = fm.width(QString("X%1X").arg(maxTime)); + + int deltaTime = 1; + int nextFactor = 5; + + double tickDistance = mapTimeToX(deltaTime); + while (true) { + if (tickDistance > minTextSpacing) + break; + + deltaTime *= nextFactor; + tickDistance = mapTimeToX(deltaTime); + + if (nextFactor == 5) + nextFactor = 2; + else + nextFactor = 5; + } + return deltaTime; +} + +} // End namespace DesignTools. diff --git a/src/curveeditor/detail/graphicsview.h b/src/curveeditor/detail/graphicsview.h new file mode 100644 index 0000000..db9933e --- /dev/null +++ b/src/curveeditor/detail/graphicsview.h @@ -0,0 +1,104 @@ +/**************************************************************************** +** +** Copyright (C) 2019 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt Design Tooling +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ + +#pragma once + +#include "curveeditorstyle.h" +#include "curveeditorstyledialog.h" +#include "graphicsscene.h" + +#include + +namespace DesignTools { + +class CurveItem; +class CurveEditorModel; + +class GraphicsView : public QGraphicsView +{ + Q_OBJECT + +public: + GraphicsView(CurveEditorModel *model, QWidget *parent = nullptr); + + void setStyle(const CurveEditorStyle &style); + + void zoomX(double zoom); + + void zoomY(double zoom); + + void reset(const std::vector &items); + +protected: + void resizeEvent(QResizeEvent *event) override; + + void contextMenuEvent(QContextMenuEvent *event) override; + + void drawForeground(QPainter *painter, const QRectF &rect) override; + + void drawBackground(QPainter *painter, const QRectF &rect) override; + +private: + int mapTimeToX(double time); + + int mapValueToY(double value); + + double mapXtoTime(int x); + + double mapYtoValue(int y); + + void applyZoom(double x, double y); + + void updateSceneRect(const QRectF &rect = QRectF()); + + void drawGrid(QPainter *painter, const QRectF &rect); + + void drawExtremaX(QPainter *painter, const QRectF &rect); + + void drawExtremaY(QPainter *painter, const QRectF &rect); + + void drawTimeScale(QPainter *painter, const QRectF &rect); + + void drawValueScale(QPainter *painter, const QRectF &rect); + + double timeLabelInterval(QPainter *painter, double maxTime); + +private: + GraphicsScene m_scene; + + CurveEditorStyle m_style; + + CurveEditorModel *m_model; + + CurveEditorStyleDialog m_dialog; + + double m_zoomX; + + double m_zoomY; + + QTransform m_transform; +}; + +} // End namespace DesignTools. diff --git a/src/curveeditor/detail/handleitem.cpp b/src/curveeditor/detail/handleitem.cpp new file mode 100644 index 0000000..d9abc77 --- /dev/null +++ b/src/curveeditor/detail/handleitem.cpp @@ -0,0 +1,132 @@ +/**************************************************************************** +** +** Copyright (C) 2019 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt Design Tooling +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ + +#include "handleitem.h" +#include "utils.h" + +#include +#include +#include + +namespace DesignTools { + +struct HandleGeometry +{ + HandleGeometry(const QPointF &pos, const HandleItemStyleOption &style) + { + QPointF topLeft(-style.size / 2.0, -style.size / 2.0); + + handle = QRectF(topLeft, -topLeft); + toKeyframe = QLineF(QPointF(0.0, 0.0), -pos); + angle = -toKeyframe.angle() + 45.0; + } + + QRectF handle; + + QLineF toKeyframe; + + double angle; +}; + +HandleItem::HandleItem(QGraphicsItem *parent) + : QGraphicsObject(parent) + , m_style() +{ + setFlag(QGraphicsItem::ItemIsMovable, true); + setFlag(QGraphicsItem::ItemIgnoresTransformations, true); + setFlag(QGraphicsItem::ItemStacksBehindParent, true); +} + +HandleItem::~HandleItem() {} + +int HandleItem::type() const +{ + return Type; +} + +QRectF HandleItem::boundingRect() const +{ + HandleGeometry geom(pos(), m_style); + + QTransform transform; + transform.rotate(geom.angle); + + QRectF bounds = bbox(geom.handle, transform); + grow(bounds, -pos()); + return bounds; +} + +void HandleItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) +{ + Q_UNUSED(option); + Q_UNUSED(widget); + + QColor handleColor(isSelected() ? m_style.selectionColor : m_style.color); + + HandleGeometry geom(pos(), m_style); + + QPen pen = painter->pen(); + pen.setWidthF(m_style.lineWidth); + pen.setColor(handleColor); + + painter->save(); + painter->setPen(pen); + + painter->drawLine(geom.toKeyframe); + painter->rotate(geom.angle); + painter->fillRect(geom.handle, handleColor); + + painter->restore(); +} + +void HandleItem::setStyle(const CurveEditorStyle &style) +{ + m_style = style.handleStyle; +} + +bool HandleItem::sceneEvent(QEvent *event) +{ + auto intersectsHandle = [this, event]() { + HandleGeometry geom(pos(), m_style); + + QTransform transform; + transform.rotate(geom.angle); + + auto *mousePressEvent = static_cast(event); + return bbox(geom.handle, transform).contains(mousePressEvent->pos()); + }; + + switch (event->type()) { + case QEvent::GraphicsSceneMousePress: + if (!intersectsHandle()) + event->ignore(); + return true; + + default: + return QGraphicsObject::sceneEvent(event); + } +} + +} // End namespace DesignTools. diff --git a/src/curveeditor/detail/handleitem.h b/src/curveeditor/detail/handleitem.h new file mode 100644 index 0000000..8e2ffd7 --- /dev/null +++ b/src/curveeditor/detail/handleitem.h @@ -0,0 +1,60 @@ +/**************************************************************************** +** +** Copyright (C) 2019 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt Design Tooling +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ + +#pragma once + +#include "curveeditorstyle.h" + +#include + +namespace DesignTools { + +class HandleItem : public QGraphicsObject +{ + Q_OBJECT + +public: + HandleItem(QGraphicsItem *parent); + + ~HandleItem() override; + + enum { Type = UserType + 3 }; + + int type() const override; + + QRectF boundingRect() const override; + + void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = nullptr) override; + + void setStyle(const CurveEditorStyle &style); + +protected: + bool sceneEvent(QEvent *event) override; + +private: + HandleItemStyleOption m_style; +}; + +} // End namespace DesignTools. diff --git a/src/curveeditor/detail/keyframeitem.cpp b/src/curveeditor/detail/keyframeitem.cpp new file mode 100644 index 0000000..867585c --- /dev/null +++ b/src/curveeditor/detail/keyframeitem.cpp @@ -0,0 +1,181 @@ +/**************************************************************************** +** +** Copyright (C) 2019 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt Design Tooling +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ + +#include "keyframeitem.h" +#include "handleitem.h" + +#include + +#include + +namespace DesignTools { + +KeyframeItem::KeyframeItem(QGraphicsItem *parent) + : QGraphicsObject(parent) + , m_frame() +{} + +KeyframeItem::KeyframeItem(const Keyframe &keyframe, QGraphicsItem *parent) + : QGraphicsObject(parent) + , m_transform() + , m_frame(keyframe) + , m_left(keyframe.hasLeftHandle() ? new HandleItem(this) : nullptr) + , m_right(keyframe.hasRightHandle() ? new HandleItem(this) : nullptr) +{ + setFlag(QGraphicsItem::ItemIsMovable, true); + setFlag(QGraphicsItem::ItemIgnoresTransformations, true); + setFlag(QGraphicsItem::ItemSendsGeometryChanges, true); + + connect(this, &QGraphicsObject::xChanged, this, &KeyframeItem::updatePosition); + connect(this, &QGraphicsObject::yChanged, this, &KeyframeItem::updatePosition); + + if (m_left) { + m_left->setPos(m_frame.leftHandle() - m_frame.position()); + auto updateLeftHandle = [this]() { updateHandle(m_left); }; + connect(m_left, &QGraphicsObject::xChanged, updateLeftHandle); + connect(m_left, &QGraphicsObject::yChanged, updateLeftHandle); + } + + if (m_right) { + m_right->setPos(m_frame.rightHandle() - m_frame.position()); + auto updateRightHandle = [this]() { updateHandle(m_right); }; + connect(m_right, &QGraphicsObject::xChanged, updateRightHandle); + connect(m_right, &QGraphicsObject::yChanged, updateRightHandle); + } + + setPos(m_frame.position()); +} + +int KeyframeItem::type() const +{ + return Type; +} + +QRectF KeyframeItem::boundingRect() const +{ + QPointF topLeft(-m_style.size / 2.0, -m_style.size / 2.0); + return QRectF(topLeft, -topLeft); +} + +void KeyframeItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) +{ + Q_UNUSED(option); + Q_UNUSED(widget); + + QPen pen = painter->pen(); + pen.setColor(Qt::black); + + painter->save(); + painter->setPen(pen); + painter->setBrush(isSelected() ? m_style.selectionColor : m_style.color); + painter->drawEllipse(boundingRect()); + + painter->restore(); +} + +KeyframeItem::~KeyframeItem() {} + +Keyframe KeyframeItem::keyframe() const +{ + return m_frame; +} + +void KeyframeItem::setComponentTransform(const QTransform &transform) +{ + m_transform = transform; + + if (m_left) + m_left->setPos(m_transform.map(m_frame.leftHandle() - m_frame.position())); + + if (m_right) + m_right->setPos(m_transform.map(m_frame.rightHandle() - m_frame.position())); + + setPos(m_transform.map(m_frame.position())); +} + +void KeyframeItem::setStyle(const CurveEditorStyle &style) +{ + m_style = style.keyframeStyle; + + if (m_left) + m_left->setStyle(style); + + if (m_right) + m_right->setStyle(style); +} + +void KeyframeItem::updatePosition() +{ + bool ok = false; + QPointF position = m_transform.inverted(&ok).map(pos()); + + if (!ok) + return; + + m_frame.setPosition(position); + + if (m_left) + updateHandle(m_left, false); + + if (m_right) + updateHandle(m_right, false); + + emit keyframeChanged(); +} + +void KeyframeItem::updateHandle(HandleItem *handle, bool emitChanged) +{ + bool ok = false; + + QPointF handlePosition = m_transform.inverted(&ok).map(handle->pos()); + + if (!ok) + return; + + if (handle == m_left) + m_frame.setLeftHandle(m_frame.position() + handlePosition); + else + m_frame.setRightHandle(m_frame.position() + handlePosition); + + if (emitChanged) + emit keyframeChanged(); +} + +QVariant KeyframeItem::itemChange(QGraphicsItem::GraphicsItemChange change, const QVariant &value) +{ + if (change == ItemPositionChange) { + // Snap to keyframe. + bool ok; + QPointF position = m_transform.inverted(&ok).map(value.toPointF()); + if (ok) { + position.setX(std::round(position.x())); + return QVariant(m_transform.map(position)); + } + } + + return QGraphicsItem::itemChange(change, value); +} + +} // End namespace DesignTools. diff --git a/src/curveeditor/detail/keyframeitem.h b/src/curveeditor/detail/keyframeitem.h new file mode 100644 index 0000000..88eb366 --- /dev/null +++ b/src/curveeditor/detail/keyframeitem.h @@ -0,0 +1,85 @@ +/**************************************************************************** +** +** Copyright (C) 2019 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt Design Tooling +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ + +#pragma once + +#include "curveeditorstyle.h" +#include "keyframe.h" + +#include + +namespace DesignTools { + +class HandleItem; + +class KeyframeItem : public QGraphicsObject +{ + Q_OBJECT + +signals: + void keyframeChanged(); + +public: + KeyframeItem(QGraphicsItem *parent = nullptr); + + KeyframeItem(const Keyframe &keyframe, QGraphicsItem *parent = nullptr); + + ~KeyframeItem() override; + + enum { Type = UserType + 2 }; + + int type() const override; + + QRectF boundingRect() const override; + + void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = nullptr) override; + + Keyframe keyframe() const; + + void setComponentTransform(const QTransform &transform); + + void setStyle(const CurveEditorStyle &style); + +protected: + QVariant itemChange(QGraphicsItem::GraphicsItemChange change, const QVariant &value) override; + +private: + void updatePosition(); + + void updateHandle(HandleItem *handle, bool emit = true); + +private: + QTransform m_transform; + + KeyframeItemStyleOption m_style; + + Keyframe m_frame; + + HandleItem *m_left; + + HandleItem *m_right; +}; + +} // End namespace DesignTools. diff --git a/src/curveeditor/detail/treeitem.cpp b/src/curveeditor/detail/treeitem.cpp new file mode 100644 index 0000000..c8f5360 --- /dev/null +++ b/src/curveeditor/detail/treeitem.cpp @@ -0,0 +1,188 @@ +/**************************************************************************** +** +** Copyright (C) 2019 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt Design Tooling +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ + +#include "treeitem.h" + +#include +#include + +namespace DesignTools { + +TreeItem::TreeItem(const QString &name) + : m_name(name) + , m_id(0) + , m_locked(false) + , m_pinned(false) + , m_parent(nullptr) + , m_children() +{} + +TreeItem::~TreeItem() +{ + m_parent = nullptr; + + qDeleteAll(m_children); +} + +QIcon TreeItem::icon() const +{ + return QIcon(); +} + +NodeTreeItem *TreeItem::asNodeItem() +{ + return nullptr; +} + +PropertyTreeItem *TreeItem::asPropertyItem() +{ + return nullptr; +} + +unsigned int TreeItem::id() const +{ + return m_id; +} + +bool TreeItem::locked() const +{ + return m_locked; +} + +bool TreeItem::pinned() const +{ + return m_pinned; +} + +int TreeItem::row() const +{ + if (m_parent) { + for (size_t i = 0; i < m_parent->m_children.size(); ++i) { + if (m_parent->m_children[i] == this) + return i; + } + } + + return 0; +} + +int TreeItem::column() const +{ + return 0; +} + +int TreeItem::rowCount() const +{ + return m_children.size(); +} + +int TreeItem::columnCount() const +{ + return 3; +} + +TreeItem *TreeItem::parent() const +{ + return m_parent; +} + +TreeItem *TreeItem::child(int row) const +{ + if (row < 0 || row >= static_cast(m_children.size())) + return nullptr; + + return m_children.at(row); +} + +TreeItem *TreeItem::find(unsigned int id) const +{ + for (auto *child : m_children) { + if (child->id() == id) + return child; + + if (auto *childsChild = child->find(id)) + return childsChild; + } + + return nullptr; +} + +QVariant TreeItem::data(int column) const +{ + switch (column) { + case 0: + return QVariant(m_name); + case 1: + return QVariant(m_locked); + case 2: + return QVariant(m_pinned); + case 3: + return QVariant(m_id); + default: + return QVariant(); + } +} + +QVariant TreeItem::headerData(int column) const +{ + switch (column) { + case 0: + return QString("Name"); + case 1: + return QString("L"); + case 2: + return QString("P"); + case 3: + return QString("Id"); + default: + return QVariant(); + } +} + +void TreeItem::setId(unsigned int &id) +{ + m_id = id; + + for (auto *child : m_children) + child->setId(++id); +} + +void TreeItem::addChild(TreeItem *child) +{ + child->m_parent = this; + m_children.push_back(child); +} + +void TreeItem::setLocked(bool locked) +{ + m_locked = locked; +} + +void TreeItem::setPinned(bool pinned) +{ + m_pinned = pinned; +} + +} // End namespace DesignTools. diff --git a/src/curveeditor/detail/treeitem.h b/src/curveeditor/detail/treeitem.h new file mode 100644 index 0000000..15a1014 --- /dev/null +++ b/src/curveeditor/detail/treeitem.h @@ -0,0 +1,102 @@ + +/**************************************************************************** +** +** Copyright (C) 2019 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt Design Tooling +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ + +#pragma once + +#include "animationcurve.h" + +#include + +#include + +class QIcon; +class QVariant; + +namespace DesignTools { + +class NodeTreeItem; +class PropertyTreeItem; + +class TreeItem +{ +public: + TreeItem(const QString &name); + + virtual ~TreeItem(); + + virtual QIcon icon() const; + + virtual NodeTreeItem *asNodeItem(); + + virtual PropertyTreeItem *asPropertyItem(); + + unsigned int id() const; + + bool locked() const; + + bool pinned() const; + + int row() const; + + int column() const; + + int rowCount() const; + + int columnCount() const; + + TreeItem *parent() const; + + TreeItem *child(int row) const; + + TreeItem *find(unsigned int row) const; + + QVariant data(int column) const; + + QVariant headerData(int column) const; + + void setId(unsigned int &id); + + void addChild(TreeItem *child); + + void setLocked(bool locked); + + void setPinned(bool pinned); + +protected: + QString m_name; + + unsigned int m_id; + + bool m_locked; + + bool m_pinned; + + TreeItem *m_parent; + + std::vector m_children; +}; + +} // End namespace DesignTools. diff --git a/src/curveeditor/detail/treeitemdelegate.cpp b/src/curveeditor/detail/treeitemdelegate.cpp new file mode 100644 index 0000000..21633dd --- /dev/null +++ b/src/curveeditor/detail/treeitemdelegate.cpp @@ -0,0 +1,146 @@ +/**************************************************************************** +** +** Copyright (C) 2019 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt Design Tooling +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ +#include "treeitemdelegate.h" +#include "treeitem.h" + +#include +#include +#include + +namespace DesignTools { + +TreeItemDelegate::TreeItemDelegate(const CurveEditorStyle &style, QObject *parent) + : QStyledItemDelegate(parent) + , m_style(style) +{} + +QSize TreeItemDelegate::sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const +{ + return QStyledItemDelegate::sizeHint(option, index); +} + +void TreeItemDelegate::paint(QPainter *painter, + const QStyleOptionViewItem &option, + const QModelIndex &index) const +{ + if (index.column() == 1 || index.column() == 2) { + + int height = option.rect.size().height(); + QRect iconRect(QPoint(0, 0), QSize(height, height)); + iconRect.moveCenter(option.rect.center()); + + auto *treeItem = static_cast(index.internalPointer()); + if (option.state & QStyle::State_MouseOver && iconRect.contains(m_mousePos)) { + + painter->fillRect(option.rect, option.backgroundBrush); + + if (index.column() == 1) { + + if (treeItem->locked()) { + + QPixmap pixmap = pixmapFromIcon( + m_style.treeItemStyle.unlockedIcon, + iconRect.size(), + m_style.fontColor); + + painter->drawPixmap(iconRect, pixmap); + + } else { + + QPixmap pixmap = pixmapFromIcon( + m_style.treeItemStyle.lockedIcon, + iconRect.size(), + m_style.fontColor); + + painter->drawPixmap(iconRect, pixmap); + } + + } else if (index.column() == 2) { + + if (treeItem->pinned()) { + + QPixmap pixmap = pixmapFromIcon( + m_style.treeItemStyle.unpinnedIcon, + iconRect.size(), + m_style.fontColor); + + painter->drawPixmap(iconRect, pixmap); + + } else { + + QPixmap pixmap = pixmapFromIcon( + m_style.treeItemStyle.pinnedIcon, + iconRect.size(), + m_style.fontColor); + + painter->drawPixmap(iconRect, pixmap); + + } + } + + } else { + + if (treeItem->locked() && index.column() == 1) { + + QPixmap pixmap = pixmapFromIcon( + m_style.treeItemStyle.lockedIcon, + iconRect.size(), + m_style.fontColor); + + painter->drawPixmap(iconRect, pixmap); + + } else if (treeItem->pinned() && index.column() == 2) { + + QPixmap pixmap = pixmapFromIcon( + m_style.treeItemStyle.pinnedIcon, + iconRect.size(), + m_style.fontColor); + + painter->drawPixmap(iconRect, pixmap); + + } + } + } else { + QStyledItemDelegate::paint(painter, option, index); + } +} + +void TreeItemDelegate::setStyle(const CurveEditorStyle &style) +{ + m_style = style; +} + +bool TreeItemDelegate::editorEvent(QEvent *event, + QAbstractItemModel *model, + const QStyleOptionViewItem &option, + const QModelIndex &index) +{ + if (event->type() == QEvent::MouseMove) + m_mousePos = static_cast(event)->pos(); + + return QStyledItemDelegate::editorEvent(event, model, option, index); +} + +} // End namespace DesignTools. diff --git a/src/curveeditor/detail/treeitemdelegate.h b/src/curveeditor/detail/treeitemdelegate.h new file mode 100644 index 0000000..6479f48 --- /dev/null +++ b/src/curveeditor/detail/treeitemdelegate.h @@ -0,0 +1,63 @@ +/**************************************************************************** +** +** Copyright (C) 2019 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt Design Tooling +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ + +#pragma once + +#include "curveeditorstyle.h" + +#include + +namespace DesignTools { + +class TreeItemDelegate : public QStyledItemDelegate +{ + Q_OBJECT + +public: + TreeItemDelegate(const CurveEditorStyle &style, QObject *parent = nullptr); + + QSize sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const override; + + void paint( + QPainter *painter, + const QStyleOptionViewItem &option, + const QModelIndex &index) const override; + + void setStyle(const CurveEditorStyle &style); + +protected: + bool editorEvent( + QEvent *event, + QAbstractItemModel *model, + const QStyleOptionViewItem &option, + const QModelIndex &index) override; + +private: + CurveEditorStyle m_style; + + QPoint m_mousePos; +}; + +} // End namespace DesignTools. diff --git a/src/curveeditor/detail/treemodel.cpp b/src/curveeditor/detail/treemodel.cpp new file mode 100644 index 0000000..1fc3fad --- /dev/null +++ b/src/curveeditor/detail/treemodel.cpp @@ -0,0 +1,142 @@ +/**************************************************************************** +** +** Copyright (C) 2019 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt Design Tooling +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ + +#include "treemodel.h" +#include "treeitem.h" + +#include + +namespace DesignTools { + +TreeModel::TreeModel(QObject *parent) + : QAbstractItemModel(parent) + , m_root(new TreeItem("Root")) +{} + +TreeModel::~TreeModel() +{ + if (m_root) { + delete m_root; + m_root = nullptr; + } +} + +QVariant TreeModel::data(const QModelIndex &index, int role) const +{ + if (!index.isValid()) + return QVariant(); + + TreeItem *item = static_cast(index.internalPointer()); + + if (role == Qt::DecorationRole && index.column() == 0) + return item->icon(); + + if (role != Qt::DisplayRole) + return QVariant(); + + return item->data(index.column()); +} + +QVariant TreeModel::headerData(int section, Qt::Orientation orientation, int role) const +{ + if (role != Qt::DisplayRole) + return QVariant(); + + if (orientation == Qt::Horizontal) + return m_root->headerData(section); + + return QVariant(); +} + +QModelIndex TreeModel::index(int row, int column, const QModelIndex &parent) const +{ + if (!hasIndex(row, column, parent)) + return QModelIndex(); + + TreeItem *parentItem = m_root; + + if (parent.isValid()) + parentItem = static_cast(parent.internalPointer()); + + if (TreeItem *childItem = parentItem->child(row)) + return createIndex(row, column, childItem); + + return QModelIndex(); +} + +QModelIndex TreeModel::parent(const QModelIndex &index) const +{ + if (!index.isValid()) + return QModelIndex(); + + TreeItem *childItem = static_cast(index.internalPointer()); + + if (TreeItem *parentItem = childItem->parent()) { + if (parentItem == m_root) + return QModelIndex(); + + return createIndex(parentItem->row(), 0, parentItem); + } + return QModelIndex(); +} + +int TreeModel::rowCount(const QModelIndex &parent) const +{ + if (parent.column() > 0) + return 0; + + TreeItem *parentItem = m_root; + + if (parent.isValid()) + parentItem = static_cast(parent.internalPointer()); + + return parentItem->rowCount(); +} + +int TreeModel::columnCount(const QModelIndex &parent) const +{ + Q_UNUSED(parent); + return m_root->columnCount(); +} + +void TreeModel::initialize() +{ + if (m_root) + delete m_root; + + m_root = new TreeItem("Root"); +} + +TreeItem *TreeModel::root() +{ + return m_root; +} + +TreeItem *TreeModel::find(unsigned int id) +{ + return m_root->find(id); +} + +} // End namespace DesignTools. diff --git a/src/curveeditor/detail/treemodel.h b/src/curveeditor/detail/treemodel.h new file mode 100644 index 0000000..13d2518 --- /dev/null +++ b/src/curveeditor/detail/treemodel.h @@ -0,0 +1,68 @@ +/**************************************************************************** +** +** Copyright (C) 2019 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt Design Tooling +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ + +#pragma once + +#include + +#include + +namespace DesignTools { + +class TreeItem; + +class TreeModel : public QAbstractItemModel +{ + Q_OBJECT + +public: + TreeModel(QObject *parent = nullptr); + + ~TreeModel() override; + + QVariant data(const QModelIndex &index, int role) const override; + + QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override; + + QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const override; + + QModelIndex parent(const QModelIndex &index) const override; + + int rowCount(const QModelIndex &parent = QModelIndex()) const override; + + int columnCount(const QModelIndex &parent = QModelIndex()) const override; + +protected: + void initialize(); + + TreeItem *root(); + + TreeItem *find(unsigned int id); + +private: + TreeItem *m_root; +}; + +} // End namespace DesignTools. diff --git a/src/curveeditor/detail/treeview.cpp b/src/curveeditor/detail/treeview.cpp new file mode 100644 index 0000000..3b9a4ef --- /dev/null +++ b/src/curveeditor/detail/treeview.cpp @@ -0,0 +1,127 @@ +/**************************************************************************** +** +** Copyright (C) 2019 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt Design Tooling +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ +#include "treeview.h" +#include "curveeditormodel.h" +#include "curveitem.h" +#include "treeitem.h" +#include "treeitemdelegate.h" + +#include +#include + +namespace DesignTools { + +TreeView::TreeView(CurveEditorModel *model, QWidget *parent) + : QTreeView(parent) +{ + setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding); + setUniformRowHeights(true); + setRootIsDecorated(false); + setMouseTracking(true); + setHeaderHidden(true); + + model->setParent(this); + setModel(model); + + auto expandItems = [this]() { expandAll(); }; + connect(model, &QAbstractItemModel::modelReset, expandItems); + + auto *delegate = new TreeItemDelegate(model->style(), this); + setItemDelegate(delegate); + + setSelectionBehavior(QAbstractItemView::SelectRows); + setSelectionMode(QAbstractItemView::ExtendedSelection); + + connect(selectionModel(), &QItemSelectionModel::selectionChanged, this, &TreeView::changeSelection); + setStyle(model->style()); + + header()->setSectionResizeMode(0, QHeaderView::Stretch); + header()->setSectionResizeMode(1, QHeaderView::Fixed); + header()->setSectionResizeMode(2, QHeaderView::Fixed); + + header()->setStretchLastSection(false); + header()->resizeSection(1, 20); + header()->resizeSection(2, 20); +} + +void TreeView::setStyle(const CurveEditorStyle &style) +{ + QPalette pal = palette(); + pal.setBrush(QPalette::Base, style.backgroundBrush); + pal.setBrush(QPalette::Button, style.backgroundAlternateBrush); + pal.setBrush(QPalette::Text, style.fontColor); + + // Tmp to see what happens on windows/macOS. + pal.setBrush(backgroundRole(), Qt::white); + pal.setBrush(foregroundRole(), Qt::white); + + setPalette(pal); + + if (auto *delegate = qobject_cast(itemDelegate())) + delegate->setStyle(style); +} + +void TreeView::changeCurve(unsigned int id, const AnimationCurve &curve) +{ + if (auto *curveModel = qobject_cast(model())) + curveModel->setCurve(id, curve); +} + +void TreeView::changeSelection(const QItemSelection &selected, const QItemSelection &deselected) +{ + Q_UNUSED(selected); + Q_UNUSED(deselected); + + std::vector curves; + for (auto index : selectedIndexes()) { + if (index.isValid() && index.column() == 0) { + auto *treeItem = static_cast(index.internalPointer()); + if (auto *propertyItem = treeItem->asPropertyItem()) + curves.push_back(new CurveItem(treeItem->id(), propertyItem->curve())); + } + } + + emit curvesSelected(curves); +} + +QSize TreeView::sizeHint() const +{ + return QSize(170, 300); +} + +void TreeView::mousePressEvent(QMouseEvent *event) +{ + QModelIndex index = indexAt(event->pos()); + if (index.isValid()) { + auto *treeItem = static_cast(index.internalPointer()); + if (index.column() == 1) + treeItem->setLocked(!treeItem->locked()); + else if (index.column() == 2) + treeItem->setPinned(!treeItem->pinned()); + } + QTreeView::mousePressEvent(event); +} + +} // End namespace DesignTools. diff --git a/src/curveeditor/detail/treeview.h b/src/curveeditor/detail/treeview.h new file mode 100644 index 0000000..9d3af64 --- /dev/null +++ b/src/curveeditor/detail/treeview.h @@ -0,0 +1,61 @@ +/**************************************************************************** +** +** Copyright (C) 2019 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt Design Tooling +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ + +#pragma once + +#include + +namespace DesignTools { + +class AnimationCurve; +class CurveEditorModel; +class CurveItem; + +struct CurveEditorStyle; + +class TreeView : public QTreeView +{ + Q_OBJECT + +signals: + void curvesSelected(const std::vector &curves); + +public: + TreeView(CurveEditorModel *model, QWidget *parent = nullptr); + + void changeCurve(unsigned int id, const AnimationCurve &curve); + + void setStyle(const CurveEditorStyle &style); + +protected: + QSize sizeHint() const override; + + void mousePressEvent(QMouseEvent *event) override; + +private: + void changeSelection(const QItemSelection &selected, const QItemSelection &deselected); +}; + +} // End namespace DesignTools. diff --git a/src/curveeditor/detail/utils.cpp b/src/curveeditor/detail/utils.cpp new file mode 100644 index 0000000..4933bcb --- /dev/null +++ b/src/curveeditor/detail/utils.cpp @@ -0,0 +1,107 @@ + +/**************************************************************************** +** +** Copyright (C) 2019 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt Design Tooling +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ + +#include +#include +#include +#include + +namespace DesignTools { + +double clamp(double val, double lo, double hi) +{ + return val < lo ? lo : (val > hi ? hi : val); +} + +double lerp(double blend, double a, double b) +{ + return (1.0 - blend) * a + blend * b; +} + +double scaleX(const QTransform &transform) +{ + return transform.m11(); +} + +double scaleY(const QTransform &transform) +{ + return transform.m22(); +} + +void grow(QRectF &rect, const QPointF &point) +{ + if (rect.left() > point.x()) + rect.setLeft(point.x()); + + if (rect.right() < point.x()) + rect.setRight(point.x()); + + if (rect.top() > point.y()) + rect.setTop(point.y()); + + if (rect.bottom() < point.y()) + rect.setBottom(point.y()); +} + +QRectF bbox(const QRectF &rect, const QTransform &transform) +{ + QRectF out = rect; + grow(out, transform.map(rect.topLeft())); + grow(out, transform.map(rect.topRight())); + grow(out, transform.map(rect.bottomLeft())); + grow(out, transform.map(rect.bottomRight())); + return out; +} + +QPalette singleColorPalette(const QColor &color) +{ + QPalette palette; + palette.setColor(QPalette::Window, color); + palette.setColor(QPalette::Background, color); + palette.setColor(QPalette::WindowText, color); + palette.setColor(QPalette::Foreground, color); + palette.setColor(QPalette::Base, color); + palette.setColor(QPalette::AlternateBase, color); + palette.setColor(QPalette::ToolTipBase, color); + palette.setColor(QPalette::ToolTipText, color); + palette.setColor(QPalette::Text, color); + + palette.setColor(QPalette::Button, color); + palette.setColor(QPalette::ButtonText, color); + palette.setColor(QPalette::BrightText, color); + palette.setColor(QPalette::Light, color); + palette.setColor(QPalette::Midlight, color); + palette.setColor(QPalette::Dark, color); + palette.setColor(QPalette::Mid, color); + palette.setColor(QPalette::Shadow, color); + palette.setColor(QPalette::Highlight, color); + palette.setColor(QPalette::HighlightedText, color); + palette.setColor(QPalette::Link, color); + palette.setColor(QPalette::LinkVisited, color); + return palette; +} + +} // End namespace DesignTools. diff --git a/src/curveeditor/detail/utils.h b/src/curveeditor/detail/utils.h new file mode 100644 index 0000000..450c805 --- /dev/null +++ b/src/curveeditor/detail/utils.h @@ -0,0 +1,52 @@ +/**************************************************************************** +** +** Copyright (C) 2019 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt Design Tooling +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ + +#pragma once + +class QColor; +class QPalette; +class QPointF; +class QRectF; +class QTransform; + +namespace DesignTools { + +class Keyframe; + +double clamp(double val, double lo, double hi); + +double lerp(double blend, double a, double b); + +double scaleX(const QTransform &transform); + +double scaleY(const QTransform &transform); + +void grow(QRectF &rect, const QPointF &point); + +QRectF bbox(const QRectF &rect, const QTransform &transform); + +QPalette singleColorPalette(const QColor &color); + +} // End namespace DesignTools. diff --git a/src/curveeditor/handleitem.cpp b/src/curveeditor/handleitem.cpp deleted file mode 100644 index 4653af6..0000000 --- a/src/curveeditor/handleitem.cpp +++ /dev/null @@ -1,134 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2019 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the Qt Design Tooling -** -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -****************************************************************************/ - -#include "handleitem.h" -#include "utils.h" - -#include -#include -#include - -namespace DesignTools { - -struct HandleGeometry -{ - HandleGeometry(const QPointF &pos, const HandleItemStyleOption &style) - { - QPointF topLeft(-style.size / 2.0, -style.size / 2.0); - - handle = QRectF(topLeft, -topLeft); - toKeyframe = QLineF(QPointF(0.0, 0.0), -pos); - angle = -toKeyframe.angle() + 45.0; - } - - QRectF handle; - - QLineF toKeyframe; - - double angle; -}; - -HandleItem::HandleItem(QGraphicsItem *parent) - : QGraphicsObject(parent) - , m_style() -{ - setFlag(QGraphicsItem::ItemIsMovable, true); - setFlag(QGraphicsItem::ItemIgnoresTransformations, true); - setFlag(QGraphicsItem::ItemStacksBehindParent, true); -} - -HandleItem::~HandleItem() -{ } - -int HandleItem::type() const -{ - return Type; -} - -QRectF HandleItem::boundingRect() const -{ - HandleGeometry geom(pos(), m_style); - - QTransform transform; - transform.rotate(geom.angle); - - QRectF bounds = bbox(geom.handle, transform); - grow(bounds, -pos()); - return bounds; -} - -void HandleItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) -{ - Q_UNUSED(option); - Q_UNUSED(widget); - - QColor handleColor(isSelected() ? m_style.selectionColor : m_style.color); - - HandleGeometry geom(pos(), m_style); - - QPen pen = painter->pen(); - pen.setWidthF(m_style.lineWidth); - pen.setColor(handleColor); - - painter->save(); - painter->setPen(pen); - - painter->drawLine(geom.toKeyframe); - painter->rotate(geom.angle); - painter->fillRect(geom.handle, handleColor); - - painter->restore(); -} - -void HandleItem::setStyle(const CurveEditorStyle &style) -{ - m_style = style.handleStyle; -} - -bool HandleItem::sceneEvent(QEvent *event) -{ - auto intersectsHandle = [this, event]() { - HandleGeometry geom(pos(), m_style); - - QTransform transform; - transform.rotate(geom.angle); - - auto *mousePressEvent = static_cast(event); - return bbox(geom.handle, transform).contains(mousePressEvent->pos()); - }; - - switch (event->type()) { - - case QEvent::GraphicsSceneMousePress: - if (!intersectsHandle()) - event->ignore(); - return true; - - default: - return QGraphicsObject::sceneEvent(event); - } -} - -} // End namespace DesignTools. diff --git a/src/curveeditor/handleitem.h b/src/curveeditor/handleitem.h deleted file mode 100644 index 8e2ffd7..0000000 --- a/src/curveeditor/handleitem.h +++ /dev/null @@ -1,60 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2019 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the Qt Design Tooling -** -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -****************************************************************************/ - -#pragma once - -#include "curveeditorstyle.h" - -#include - -namespace DesignTools { - -class HandleItem : public QGraphicsObject -{ - Q_OBJECT - -public: - HandleItem(QGraphicsItem *parent); - - ~HandleItem() override; - - enum { Type = UserType + 3 }; - - int type() const override; - - QRectF boundingRect() const override; - - void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = nullptr) override; - - void setStyle(const CurveEditorStyle &style); - -protected: - bool sceneEvent(QEvent *event) override; - -private: - HandleItemStyleOption m_style; -}; - -} // End namespace DesignTools. diff --git a/src/curveeditor/keyframe.cpp b/src/curveeditor/keyframe.cpp new file mode 100644 index 0000000..8ff577c --- /dev/null +++ b/src/curveeditor/keyframe.cpp @@ -0,0 +1,88 @@ +/**************************************************************************** +** +** Copyright (C) 2019 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt Design Tooling +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ + +#include "keyframe.h" + +namespace DesignTools { + +Keyframe::Keyframe() + : m_position() + , m_leftHandle() + , m_rightHandle() +{} + +Keyframe::Keyframe(const QPointF &position) + : m_position(position) + , m_leftHandle() + , m_rightHandle() +{} + +Keyframe::Keyframe(const QPointF &position, const QPointF &leftHandle, const QPointF &rightHandle) + : m_position(position) + , m_leftHandle(leftHandle) + , m_rightHandle(rightHandle) +{} + +bool Keyframe::hasLeftHandle() const +{ + return !m_leftHandle.isNull(); +} + +bool Keyframe::hasRightHandle() const +{ + return !m_rightHandle.isNull(); +} + +QPointF Keyframe::position() const +{ + return m_position; +} + +QPointF Keyframe::leftHandle() const +{ + return m_leftHandle; +} + +QPointF Keyframe::rightHandle() const +{ + return m_rightHandle; +} + +void Keyframe::setPosition(const QPointF &pos) +{ + m_position = pos; +} + +void Keyframe::setLeftHandle(const QPointF &pos) +{ + m_leftHandle = pos; +} + +void Keyframe::setRightHandle(const QPointF &pos) +{ + m_rightHandle = pos; +} + +} // End namespace DesignTools. diff --git a/src/curveeditor/keyframe.h b/src/curveeditor/keyframe.h new file mode 100644 index 0000000..5e60425 --- /dev/null +++ b/src/curveeditor/keyframe.h @@ -0,0 +1,65 @@ +/**************************************************************************** +** +** Copyright (C) 2019 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt Design Tooling +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ + +#pragma once + +#include + +namespace DesignTools { + +class Keyframe +{ +public: + Keyframe(); + + Keyframe(const QPointF &position); + + Keyframe(const QPointF &position, const QPointF &leftHandle, const QPointF &rightHandle); + + bool hasLeftHandle() const; + + bool hasRightHandle() const; + + QPointF position() const; + + QPointF leftHandle() const; + + QPointF rightHandle() const; + + void setPosition(const QPointF &pos); + + void setLeftHandle(const QPointF &pos); + + void setRightHandle(const QPointF &pos); + +private: + QPointF m_position; + + QPointF m_leftHandle; + + QPointF m_rightHandle; +}; + +} // End namespace DesignTools. diff --git a/src/curveeditor/keyframeitem.cpp b/src/curveeditor/keyframeitem.cpp deleted file mode 100644 index 867585c..0000000 --- a/src/curveeditor/keyframeitem.cpp +++ /dev/null @@ -1,181 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2019 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the Qt Design Tooling -** -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -****************************************************************************/ - -#include "keyframeitem.h" -#include "handleitem.h" - -#include - -#include - -namespace DesignTools { - -KeyframeItem::KeyframeItem(QGraphicsItem *parent) - : QGraphicsObject(parent) - , m_frame() -{} - -KeyframeItem::KeyframeItem(const Keyframe &keyframe, QGraphicsItem *parent) - : QGraphicsObject(parent) - , m_transform() - , m_frame(keyframe) - , m_left(keyframe.hasLeftHandle() ? new HandleItem(this) : nullptr) - , m_right(keyframe.hasRightHandle() ? new HandleItem(this) : nullptr) -{ - setFlag(QGraphicsItem::ItemIsMovable, true); - setFlag(QGraphicsItem::ItemIgnoresTransformations, true); - setFlag(QGraphicsItem::ItemSendsGeometryChanges, true); - - connect(this, &QGraphicsObject::xChanged, this, &KeyframeItem::updatePosition); - connect(this, &QGraphicsObject::yChanged, this, &KeyframeItem::updatePosition); - - if (m_left) { - m_left->setPos(m_frame.leftHandle() - m_frame.position()); - auto updateLeftHandle = [this]() { updateHandle(m_left); }; - connect(m_left, &QGraphicsObject::xChanged, updateLeftHandle); - connect(m_left, &QGraphicsObject::yChanged, updateLeftHandle); - } - - if (m_right) { - m_right->setPos(m_frame.rightHandle() - m_frame.position()); - auto updateRightHandle = [this]() { updateHandle(m_right); }; - connect(m_right, &QGraphicsObject::xChanged, updateRightHandle); - connect(m_right, &QGraphicsObject::yChanged, updateRightHandle); - } - - setPos(m_frame.position()); -} - -int KeyframeItem::type() const -{ - return Type; -} - -QRectF KeyframeItem::boundingRect() const -{ - QPointF topLeft(-m_style.size / 2.0, -m_style.size / 2.0); - return QRectF(topLeft, -topLeft); -} - -void KeyframeItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) -{ - Q_UNUSED(option); - Q_UNUSED(widget); - - QPen pen = painter->pen(); - pen.setColor(Qt::black); - - painter->save(); - painter->setPen(pen); - painter->setBrush(isSelected() ? m_style.selectionColor : m_style.color); - painter->drawEllipse(boundingRect()); - - painter->restore(); -} - -KeyframeItem::~KeyframeItem() {} - -Keyframe KeyframeItem::keyframe() const -{ - return m_frame; -} - -void KeyframeItem::setComponentTransform(const QTransform &transform) -{ - m_transform = transform; - - if (m_left) - m_left->setPos(m_transform.map(m_frame.leftHandle() - m_frame.position())); - - if (m_right) - m_right->setPos(m_transform.map(m_frame.rightHandle() - m_frame.position())); - - setPos(m_transform.map(m_frame.position())); -} - -void KeyframeItem::setStyle(const CurveEditorStyle &style) -{ - m_style = style.keyframeStyle; - - if (m_left) - m_left->setStyle(style); - - if (m_right) - m_right->setStyle(style); -} - -void KeyframeItem::updatePosition() -{ - bool ok = false; - QPointF position = m_transform.inverted(&ok).map(pos()); - - if (!ok) - return; - - m_frame.setPosition(position); - - if (m_left) - updateHandle(m_left, false); - - if (m_right) - updateHandle(m_right, false); - - emit keyframeChanged(); -} - -void KeyframeItem::updateHandle(HandleItem *handle, bool emitChanged) -{ - bool ok = false; - - QPointF handlePosition = m_transform.inverted(&ok).map(handle->pos()); - - if (!ok) - return; - - if (handle == m_left) - m_frame.setLeftHandle(m_frame.position() + handlePosition); - else - m_frame.setRightHandle(m_frame.position() + handlePosition); - - if (emitChanged) - emit keyframeChanged(); -} - -QVariant KeyframeItem::itemChange(QGraphicsItem::GraphicsItemChange change, const QVariant &value) -{ - if (change == ItemPositionChange) { - // Snap to keyframe. - bool ok; - QPointF position = m_transform.inverted(&ok).map(value.toPointF()); - if (ok) { - position.setX(std::round(position.x())); - return QVariant(m_transform.map(position)); - } - } - - return QGraphicsItem::itemChange(change, value); -} - -} // End namespace DesignTools. diff --git a/src/curveeditor/keyframeitem.h b/src/curveeditor/keyframeitem.h deleted file mode 100644 index 39221d2..0000000 --- a/src/curveeditor/keyframeitem.h +++ /dev/null @@ -1,85 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2019 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the Qt Design Tooling -** -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -****************************************************************************/ - -#pragma once - -#include "animationcurve.h" -#include "curveeditorstyle.h" - -#include - -namespace DesignTools { - -class HandleItem; - -class KeyframeItem : public QGraphicsObject -{ - Q_OBJECT - -signals: - void keyframeChanged(); - -public: - KeyframeItem(QGraphicsItem *parent = nullptr); - - KeyframeItem(const Keyframe &keyframe, QGraphicsItem *parent = nullptr); - - ~KeyframeItem() override; - - enum { Type = UserType + 2 }; - - int type() const override; - - QRectF boundingRect() const override; - - void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = nullptr) override; - - Keyframe keyframe() const; - - void setComponentTransform(const QTransform &transform); - - void setStyle(const CurveEditorStyle &style); - -protected: - QVariant itemChange(QGraphicsItem::GraphicsItemChange change, const QVariant &value) override; - -private: - void updatePosition(); - - void updateHandle(HandleItem *handle, bool emit = true); - -private: - QTransform m_transform; - - KeyframeItemStyleOption m_style; - - Keyframe m_frame; - - HandleItem *m_left; - - HandleItem *m_right; -}; - -} // End namespace DesignTools. diff --git a/src/curveeditor/utils.cpp b/src/curveeditor/utils.cpp deleted file mode 100644 index da74946..0000000 --- a/src/curveeditor/utils.cpp +++ /dev/null @@ -1,78 +0,0 @@ - -/**************************************************************************** -** -** Copyright (C) 2019 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the Qt Design Tooling -** -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -****************************************************************************/ - -#include -#include -#include - -namespace DesignTools { - -double clamp(double val, double lo, double hi) -{ - return val < lo ? lo : (val > hi ? hi : val); -} - -double lerp(double blend, double a, double b) -{ - return (1.0 - blend) * a + blend * b; -} - -double scaleX(const QTransform &transform) -{ - return transform.m11(); -} - -double scaleY(const QTransform &transform) -{ - return transform.m22(); -} - -void grow(QRectF &rect, const QPointF &point) -{ - if (rect.left() > point.x()) - rect.setLeft(point.x()); - - if (rect.right() < point.x()) - rect.setRight(point.x()); - - if (rect.top() > point.y()) - rect.setTop(point.y()); - - if (rect.bottom() < point.y()) - rect.setBottom(point.y()); -} - -QRectF bbox(const QRectF &rect, const QTransform &transform) -{ - QRectF out = rect; - grow(out, transform.map(rect.topLeft())); - grow(out, transform.map(rect.topRight())); - grow(out, transform.map(rect.bottomLeft())); - grow(out, transform.map(rect.bottomRight())); - return out; -} - -} // End namespace DesignTools. diff --git a/src/curveeditor/utils.h b/src/curveeditor/utils.h deleted file mode 100644 index c8a44fb..0000000 --- a/src/curveeditor/utils.h +++ /dev/null @@ -1,48 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2019 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the Qt Design Tooling -** -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -****************************************************************************/ - -#pragma once - -class QPointF; -class QRectF; -class QTransform; - -namespace DesignTools { - -class Keyframe; - -double clamp(double val, double lo, double hi); - -double lerp(double blend, double a, double b); - -double scaleX(const QTransform &transform); - -double scaleY(const QTransform &transform); - -void grow(QRectF &rect, const QPointF &point); - -QRectF bbox(const QRectF &rect, const QTransform &transform); - -} // End namespace DesignTools. -- cgit v1.2.3