diff options
author | Knud Dollereder <[email protected]> | 2020-02-21 15:28:31 +0100 |
---|---|---|
committer | Thomas Hartmann <[email protected]> | 2020-03-17 17:19:14 +0000 |
commit | 5b000d17cb2f42891db7bd8c9c857866245eddd3 (patch) | |
tree | 97b2a33c6be95de50028e24e2d2f0e85ac262055 | |
parent | 0f60f120d2e24b9912b43b5ba4859adcd5a1a803 (diff) |
QmlDesigner: Add the ability to modify the animation rangev4.12.0-beta2
Add the ability to modify the animation range from the curve editor
Fix a synchronization issue between timeline and curve editor when
the animation contains pinned curves
Change-Id: I89dda234063259f41d662749d696f5fc8a04f988
Reviewed-by: Thomas Hartmann <[email protected]>
10 files changed, 179 insertions, 34 deletions
diff --git a/src/plugins/qmldesigner/components/curveeditor/curveeditor.cpp b/src/plugins/qmldesigner/components/curveeditor/curveeditor.cpp index c6eb2f6327b..f5b2ffae1b0 100644 --- a/src/plugins/qmldesigner/components/curveeditor/curveeditor.cpp +++ b/src/plugins/qmldesigner/components/curveeditor/curveeditor.cpp @@ -48,15 +48,18 @@ CurveEditor::CurveEditor(CurveEditorModel *model, QWidget *parent) splitter->setStretchFactor(1, 2); auto *box = new QVBoxLayout; - box->addWidget(createToolBar()); + box->addWidget(createToolBar(model)); box->addWidget(splitter); setLayout(box); - connect(m_tree, &TreeView::treeItemLocked, m_view, &GraphicsView::setLocked); - connect(m_tree->selectionModel(), &SelectionModel::curvesSelected, m_view, &GraphicsView::reset); - connect(m_tree, &TreeView::treeItemLocked, model, &CurveEditorModel::curveChanged); connect(m_tree, &TreeView::treeItemPinned, model, &CurveEditorModel::curveChanged); + + connect(m_tree, &TreeView::treeItemLocked, m_view, &GraphicsView::setLocked); + connect(m_tree->selectionModel(), + &SelectionModel::curvesSelected, + m_view, + &GraphicsView::updateSelection); } void CurveEditor::zoomX(double zoom) @@ -74,7 +77,7 @@ void CurveEditor::clearCanvas() m_view->reset({}); } -QToolBar *CurveEditor::createToolBar() +QToolBar *CurveEditor::createToolBar(CurveEditorModel *model) { auto *bar = new QToolBar; bar->setFloatable(false); @@ -111,8 +114,38 @@ QToolBar *CurveEditor::createToolBar() bar->addWidget(valueWidget); auto *durationBox = new QHBoxLayout; - durationBox->addWidget(new QLabel(tr("Duration"))); - durationBox->addWidget(new QSpinBox); + auto *startSpin = new QSpinBox; + auto *endSpin = new QSpinBox; + + startSpin->setRange(std::numeric_limits<int>::lowest(), std::numeric_limits<int>::max()); + startSpin->setValue(model->minimumTime()); + + auto updateStartFrame = [this, model](int frame) { + model->setMinimumTime(frame, false); + m_view->viewport()->update(); + }; + connect(startSpin, QOverload<int>::of(&QSpinBox::valueChanged), updateStartFrame); + + endSpin->setRange(std::numeric_limits<int>::lowest(), std::numeric_limits<int>::max()); + endSpin->setValue(model->maximumTime()); + + auto updateEndFrame = [this, model](int frame) { + model->setMaximumTime(frame, false); + m_view->viewport()->update(); + }; + connect(endSpin, QOverload<int>::of(&QSpinBox::valueChanged), updateEndFrame); + + auto setStartSlot = [startSpin](int frame) { startSpin->setValue(frame); }; + connect(model, &CurveEditorModel::updateStartFrame, setStartSlot); + + auto setEndSlot = [endSpin](int frame) { endSpin->setValue(frame); }; + connect(model, &CurveEditorModel::updateEndFrame, setEndSlot); + + durationBox->addWidget(new QLabel(tr("Start Frame"))); + durationBox->addWidget(startSpin); + durationBox->addWidget(new QLabel(tr("End Frame"))); + durationBox->addWidget(endSpin); + auto *durationWidget = new QWidget; durationWidget->setLayout(durationBox); bar->addWidget(durationWidget); diff --git a/src/plugins/qmldesigner/components/curveeditor/curveeditor.h b/src/plugins/qmldesigner/components/curveeditor/curveeditor.h index c82204d83fa..b6d9cfc0138 100644 --- a/src/plugins/qmldesigner/components/curveeditor/curveeditor.h +++ b/src/plugins/qmldesigner/components/curveeditor/curveeditor.h @@ -48,7 +48,7 @@ public: void clearCanvas(); private: - QToolBar *createToolBar(); + QToolBar *createToolBar(CurveEditorModel *model); TreeView *m_tree; diff --git a/src/plugins/qmldesigner/components/curveeditor/curveeditormodel.cpp b/src/plugins/qmldesigner/components/curveeditor/curveeditormodel.cpp index 1769c1d6dd4..e6f0f3e326a 100644 --- a/src/plugins/qmldesigner/components/curveeditor/curveeditormodel.cpp +++ b/src/plugins/qmldesigner/components/curveeditor/curveeditormodel.cpp @@ -25,13 +25,16 @@ #include "curveeditormodel.h" #include "treeitem.h" + #include "detail/graphicsview.h" #include "detail/selectionmodel.h" namespace DesignTools { -CurveEditorModel::CurveEditorModel(QObject *parent) +CurveEditorModel::CurveEditorModel(double minTime, double maxTime, QObject *parent) : TreeModel(parent) + , m_minTime(minTime) + , m_maxTime(maxTime) {} CurveEditorModel::~CurveEditorModel() {} @@ -42,6 +45,24 @@ void CurveEditorModel::setCurrentFrame(int frame) graphicsView()->setCurrentFrame(frame); } +void CurveEditorModel::setMinimumTime(double time, bool internal) +{ + m_minTime = time; + if (internal) + emit updateStartFrame(m_minTime); + else + emit startFrameChanged(m_minTime); +} + +void CurveEditorModel::setMaximumTime(double time, bool internal) +{ + m_maxTime = time; + if (internal) + emit updateEndFrame(m_maxTime); + else + emit endFrameChanged(m_maxTime); +} + void CurveEditorModel::setCurve(unsigned int id, const AnimationCurve &curve) { if (TreeItem *item = find(id)) { diff --git a/src/plugins/qmldesigner/components/curveeditor/curveeditormodel.h b/src/plugins/qmldesigner/components/curveeditor/curveeditormodel.h index 6e212d4c6af..48d05586a2a 100644 --- a/src/plugins/qmldesigner/components/curveeditor/curveeditormodel.h +++ b/src/plugins/qmldesigner/components/curveeditor/curveeditormodel.h @@ -48,6 +48,14 @@ class CurveEditorModel : public TreeModel signals: void currentFrameChanged(int frame); + void startFrameChanged(int frame); + + void endFrameChanged(int frame); + + void updateStartFrame(int frame); + + void updateEndFrame(int frame); + void curveChanged(PropertyTreeItem *item); public: @@ -58,15 +66,24 @@ public: virtual CurveEditorStyle style() const = 0; public: - CurveEditorModel(QObject *parent = nullptr); + CurveEditorModel(double minTime, double maxTime, QObject *parent = nullptr); ~CurveEditorModel() override; void setCurrentFrame(int frame); + void setMinimumTime(double time, bool internal); + + void setMaximumTime(double time, bool internal); + void setCurve(unsigned int id, const AnimationCurve &curve); void reset(const std::vector<TreeItem *> &items); + +protected: + double m_minTime = 0.; + + double m_maxTime = 0.; }; } // End namespace DesignTools. diff --git a/src/plugins/qmldesigner/components/curveeditor/detail/graphicsview.cpp b/src/plugins/qmldesigner/components/curveeditor/detail/graphicsview.cpp index 51e4b35c88e..b51d916fb03 100644 --- a/src/plugins/qmldesigner/components/curveeditor/detail/graphicsview.cpp +++ b/src/plugins/qmldesigner/components/curveeditor/detail/graphicsview.cpp @@ -231,6 +231,16 @@ void GraphicsView::scrollContent(double x, double y) void GraphicsView::reset(const std::vector<CurveItem *> &items) { + m_scene.clear(); + for (auto *item : items) + m_scene.addCurveItem(item); + + applyZoom(m_zoomX, m_zoomY); + viewport()->update(); +} + +void GraphicsView::updateSelection(const std::vector<CurveItem *> &items) +{ const std::vector<CurveItem *> pinnedItems = m_scene.takePinnedItems(); auto notPinned = [pinnedItems](CurveItem *item) { for (auto *pinned : pinnedItems) { @@ -541,6 +551,38 @@ void GraphicsView::drawExtremaY(QPainter *painter, const QRectF &rect) } #endif +void GraphicsView::drawRangeBar(QPainter *painter, const QRectF &rect) +{ + QFontMetrics fm(painter->font()); + QRectF labelRect = fm.boundingRect(QString("0")); + labelRect.moveCenter(rect.center()); + + qreal bTick = rect.bottom() - 2; + qreal tTick = labelRect.bottom() + 2; + QRectF activeRect = QRectF(QPointF(mapTimeToX(m_model->minimumTime()), tTick), + QPointF(mapTimeToX(m_model->maximumTime()), bTick)); + + QColor color = Qt::white; + color.setAlpha(30); + + painter->fillRect(activeRect, color); + + QColor handleColor(Qt::green); + painter->setBrush(handleColor); + painter->setPen(handleColor); + + const qreal radius = 5.; + QRectF minHandle = rangeMinHandle(rect); + painter->drawRoundedRect(minHandle, radius, radius); + minHandle.setLeft(minHandle.center().x()); + painter->fillRect(minHandle, Qt::green); + + QRectF maxHandle = rangeMaxHandle(rect); + painter->drawRoundedRect(maxHandle, radius, radius); + maxHandle.setRight(maxHandle.center().x()); + painter->fillRect(maxHandle, Qt::green); +} + void GraphicsView::drawTimeScale(QPainter *painter, const QRectF &rect) { painter->save(); @@ -565,6 +607,8 @@ void GraphicsView::drawTimeScale(QPainter *painter, const QRectF &rect) for (double i = minimumTime(); i <= maximumTime(); i += timeIncrement) paintLabeledTick(i); + drawRangeBar(painter, rect); + painter->restore(); } @@ -619,4 +663,28 @@ double GraphicsView::timeLabelInterval(QPainter *painter, double maxTime) return deltaTime; } +QRectF GraphicsView::rangeMinHandle(const QRectF &rect) +{ + QRectF labelRect = fontMetrics().boundingRect(QString("0")); + labelRect.moveCenter(rect.center()); + + qreal top = rect.bottom() - 2; + qreal bottom = labelRect.bottom() + 2; + QSize size(10, top - bottom); + + int leftHandleLeft = mapTimeToX(m_model->minimumTime()) - size.width(); + return QRectF(QPointF(leftHandleLeft, bottom), size); +} + +QRectF GraphicsView::rangeMaxHandle(const QRectF &rect) +{ + QRectF labelRect = fontMetrics().boundingRect(QString("0")); + labelRect.moveCenter(rect.center()); + + qreal bottom = rect.bottom() - 2; + qreal top = labelRect.bottom() + 2; + + return QRectF(QPointF(mapTimeToX(m_model->maximumTime()), bottom), QSize(10, top - bottom)); +} + } // End namespace DesignTools. diff --git a/src/plugins/qmldesigner/components/curveeditor/detail/graphicsview.h b/src/plugins/qmldesigner/components/curveeditor/detail/graphicsview.h index d56dfa7c57b..7308d77608d 100644 --- a/src/plugins/qmldesigner/components/curveeditor/detail/graphicsview.h +++ b/src/plugins/qmldesigner/components/curveeditor/detail/graphicsview.h @@ -108,6 +108,8 @@ public: void reset(const std::vector<CurveItem *> &items); + void updateSelection(const std::vector<CurveItem *> &items); + void setInterpolation(Keyframe::Interpolation interpol); protected: @@ -148,8 +150,14 @@ private: void drawValueScale(QPainter *painter, const QRectF &rect); + void drawRangeBar(QPainter *painter, const QRectF &rect); + double timeLabelInterval(QPainter *painter, double maxTime); + QRectF rangeMinHandle(const QRectF &rect); + + QRectF rangeMaxHandle(const QRectF &rect); + private: double m_zoomX; diff --git a/src/plugins/qmldesigner/components/timelineeditor/animationcurveeditormodel.cpp b/src/plugins/qmldesigner/components/timelineeditor/animationcurveeditormodel.cpp index ce7beba2c91..e09d09532d5 100644 --- a/src/plugins/qmldesigner/components/timelineeditor/animationcurveeditormodel.cpp +++ b/src/plugins/qmldesigner/components/timelineeditor/animationcurveeditormodel.cpp @@ -35,9 +35,7 @@ namespace QmlDesigner { AnimationCurveEditorModel::AnimationCurveEditorModel(double minTime, double maxTime) - : CurveEditorModel() - , m_minTime(minTime) - , m_maxTime(maxTime) + : CurveEditorModel(minTime, maxTime) {} AnimationCurveEditorModel::~AnimationCurveEditorModel() {} @@ -102,16 +100,6 @@ void AnimationCurveEditorModel::setTimeline(const QmlTimeline &timeline) reset(items); } -void AnimationCurveEditorModel::setMinimumTime(double time) -{ - m_minTime = time; -} - -void AnimationCurveEditorModel::setMaximumTime(double time) -{ - m_maxTime = time; -} - DesignTools::ValueType typeFrom(const QmlTimelineKeyframeGroup &group) { if (group.valueType() == TypeName("double") || group.valueType() == TypeName("real") diff --git a/src/plugins/qmldesigner/components/timelineeditor/animationcurveeditormodel.h b/src/plugins/qmldesigner/components/timelineeditor/animationcurveeditormodel.h index fe85929cf1f..4da0be62b0b 100644 --- a/src/plugins/qmldesigner/components/timelineeditor/animationcurveeditormodel.h +++ b/src/plugins/qmldesigner/components/timelineeditor/animationcurveeditormodel.h @@ -49,20 +49,12 @@ public: void setTimeline(const QmlTimeline &timeline); - void setMinimumTime(double time); - - void setMaximumTime(double time); - private: DesignTools::TreeItem *createTopLevelItem(const QmlTimeline &timeline, const ModelNode &node); DesignTools::AnimationCurve createAnimationCurve(const QmlTimelineKeyframeGroup &group); DesignTools::AnimationCurve createDoubleCurve(const QmlTimelineKeyframeGroup &group); - - double m_minTime; - - double m_maxTime; }; } // namespace QmlDesigner diff --git a/src/plugins/qmldesigner/components/timelineeditor/timelinetoolbar.cpp b/src/plugins/qmldesigner/components/timelineeditor/timelinetoolbar.cpp index ea065e49a15..5d693f54225 100644 --- a/src/plugins/qmldesigner/components/timelineeditor/timelinetoolbar.cpp +++ b/src/plugins/qmldesigner/components/timelineeditor/timelinetoolbar.cpp @@ -38,7 +38,6 @@ #include <variantproperty.h> #include <qmlstate.h> #include <qmltimeline.h> -#include <qmltimelinekeyframegroup.h> #include <coreplugin/actionmanager/actionmanager.h> #include <coreplugin/actionmanager/command.h> @@ -112,6 +111,23 @@ TimelineToolBar::TimelineToolBar(QWidget *parent) &AnimationCurveEditorModel::currentFrameChanged, this, &TimelineToolBar::currentFrameChanged); + + auto setStartFrameValue = [this](int val) { + if (m_firstFrame) { + m_firstFrame->setText(QString::number(val, 'f', 0)); + emit startFrameChanged(val); + } + }; + connect(m_curveModel, &AnimationCurveEditorModel::startFrameChanged, setStartFrameValue); + + auto setEndFrameValue = [this](int val) { + if (m_lastFrame) { + m_lastFrame->setText(QString::number(val, 'f', 0)); + emit endFrameChanged(val); + } + }; + connect(m_curveModel, &AnimationCurveEditorModel::endFrameChanged, setEndFrameValue); + connect(m_curveModel, &AnimationCurveEditorModel::curveChanged, this, @@ -181,7 +197,7 @@ void TimelineToolBar::setCurrentTimeline(const QmlTimeline &timeline) void TimelineToolBar::setStartFrame(qreal frame) { - m_curveModel->setMinimumTime(frame); + m_curveModel->setMinimumTime(frame, true); auto text = QString::number(frame, 'f', 0); m_firstFrame->setText(text); @@ -198,7 +214,7 @@ void TimelineToolBar::setCurrentFrame(qreal frame) void TimelineToolBar::setEndFrame(qreal frame) { - m_curveModel->setMaximumTime(frame); + m_curveModel->setMaximumTime(frame, true); auto text = QString::number(frame, 'f', 0); m_lastFrame->setText(text); diff --git a/src/plugins/qmldesigner/components/timelineeditor/timelinewidget.cpp b/src/plugins/qmldesigner/components/timelineeditor/timelinewidget.cpp index e7f12fb5a2a..d80749ad082 100644 --- a/src/plugins/qmldesigner/components/timelineeditor/timelinewidget.cpp +++ b/src/plugins/qmldesigner/components/timelineeditor/timelinewidget.cpp @@ -459,6 +459,8 @@ void TimelineWidget::invalidateTimelineDuration(const QmlTimeline &timeline) if (timelineView() && timelineView()->model()) { QmlTimeline currentTimeline = graphicsScene()->currentTimeline(); if (currentTimeline.isValid() && currentTimeline == timeline) { + m_toolbar->setStartFrame(timeline.startKeyframe()); + m_toolbar->setEndFrame(timeline.endKeyframe()); graphicsScene()->setTimeline(timeline); qreal playHeadFrame = getcurrentFrame(timeline); |