forked from qt-creator/qt-creator
Convert the CurveEditorDialog to a view-plugin
Continuously send frame-changed signals when dragging the playhead Fix timescale painting Paint playhead behind the valuescale Task-number: QDS-2551 Change-Id: Ia8d3952b4401500a4c6d31ff9f5742ff44b2c092 Reviewed-by: Thomas Hartmann <thomas.hartmann@qt.io>
This commit is contained in:
@@ -649,8 +649,6 @@ extend_qtc_plugin(QmlDesigner
|
|||||||
extend_qtc_plugin(QmlDesigner
|
extend_qtc_plugin(QmlDesigner
|
||||||
SOURCES_PREFIX components/timelineeditor
|
SOURCES_PREFIX components/timelineeditor
|
||||||
SOURCES
|
SOURCES
|
||||||
animationcurvedialog.cpp animationcurvedialog.h
|
|
||||||
animationcurveeditormodel.cpp animationcurveeditormodel.h
|
|
||||||
canvas.cpp canvas.h
|
canvas.cpp canvas.h
|
||||||
canvasstyledialog.cpp canvasstyledialog.h
|
canvasstyledialog.cpp canvasstyledialog.h
|
||||||
easingcurve.cpp easingcurve.h
|
easingcurve.cpp easingcurve.h
|
||||||
@@ -707,6 +705,7 @@ extend_qtc_plugin(QmlDesigner
|
|||||||
SOURCES_PREFIX components/curveeditor
|
SOURCES_PREFIX components/curveeditor
|
||||||
SOURCES
|
SOURCES
|
||||||
curveeditor.qrc
|
curveeditor.qrc
|
||||||
|
curveeditorview.cpp curveeditorview.h
|
||||||
animationcurve.cpp animationcurve.h
|
animationcurve.cpp animationcurve.h
|
||||||
curveeditor.cpp curveeditor.h
|
curveeditor.cpp curveeditor.h
|
||||||
curveeditormodel.cpp curveeditormodel.h
|
curveeditormodel.cpp curveeditormodel.h
|
||||||
|
|||||||
@@ -62,6 +62,11 @@ CurveEditor::CurveEditor(CurveEditorModel *model, QWidget *parent)
|
|||||||
&GraphicsView::updateSelection);
|
&GraphicsView::updateSelection);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool CurveEditor::dragging() const
|
||||||
|
{
|
||||||
|
return m_view->dragging();
|
||||||
|
}
|
||||||
|
|
||||||
void CurveEditor::zoomX(double zoom)
|
void CurveEditor::zoomX(double zoom)
|
||||||
{
|
{
|
||||||
m_view->setZoomX(zoom);
|
m_view->setZoomX(zoom);
|
||||||
@@ -82,18 +87,21 @@ QToolBar *CurveEditor::createToolBar(CurveEditorModel *model)
|
|||||||
auto *bar = new QToolBar;
|
auto *bar = new QToolBar;
|
||||||
bar->setFloatable(false);
|
bar->setFloatable(false);
|
||||||
|
|
||||||
QAction *tangentLinearAction = bar->addAction(QIcon(":/curveeditor/images/tangetToolsLinearIcon.png"), "Linear");
|
QAction *tangentLinearAction = bar->addAction(
|
||||||
QAction *tangentStepAction = bar->addAction(QIcon(":/curveeditor/images/tangetToolsStepIcon.png"), "Step");
|
QIcon(":/curveeditor/images/tangetToolsLinearIcon.png"), "Linear");
|
||||||
QAction *tangentSplineAction = bar->addAction(QIcon(":/curveeditor/images/tangetToolsSplineIcon.png"), "Spline");
|
QAction *tangentStepAction = bar->addAction(QIcon(
|
||||||
QAction *tangentDefaultAction = bar->addAction("Set Default");
|
":/curveeditor/images/tangetToolsStepIcon.png"),
|
||||||
QAction *tangentUnifyAction = bar->addAction("Unify");
|
"Step");
|
||||||
|
QAction *tangentSplineAction = bar->addAction(
|
||||||
|
QIcon(":/curveeditor/images/tangetToolsSplineIcon.png"), "Spline");
|
||||||
|
|
||||||
|
QAction *tangentDefaultAction = bar->addAction(tr("Set Default"));
|
||||||
|
QAction *tangentUnifyAction = bar->addAction(tr("Unify"));
|
||||||
|
|
||||||
auto setLinearInterpolation = [this]() {
|
auto setLinearInterpolation = [this]() {
|
||||||
m_view->setInterpolation(Keyframe::Interpolation::Linear);
|
m_view->setInterpolation(Keyframe::Interpolation::Linear);
|
||||||
};
|
};
|
||||||
auto setStepInterpolation = [this]() {
|
auto setStepInterpolation = [this]() { m_view->setInterpolation(Keyframe::Interpolation::Step); };
|
||||||
m_view->setInterpolation(Keyframe::Interpolation::Step);
|
|
||||||
};
|
|
||||||
auto setSplineInterpolation = [this]() {
|
auto setSplineInterpolation = [this]() {
|
||||||
m_view->setInterpolation(Keyframe::Interpolation::Bezier);
|
m_view->setInterpolation(Keyframe::Interpolation::Bezier);
|
||||||
};
|
};
|
||||||
@@ -118,7 +126,7 @@ QToolBar *CurveEditor::createToolBar(CurveEditorModel *model)
|
|||||||
startSpin->setValue(model->minimumTime());
|
startSpin->setValue(model->minimumTime());
|
||||||
|
|
||||||
auto updateStartFrame = [this, model](int frame) {
|
auto updateStartFrame = [this, model](int frame) {
|
||||||
model->setMinimumTime(frame, false);
|
model->setMinimumTime(frame);
|
||||||
m_view->viewport()->update();
|
m_view->viewport()->update();
|
||||||
};
|
};
|
||||||
connect(startSpin, QOverload<int>::of(&QSpinBox::valueChanged), updateStartFrame);
|
connect(startSpin, QOverload<int>::of(&QSpinBox::valueChanged), updateStartFrame);
|
||||||
@@ -127,16 +135,16 @@ QToolBar *CurveEditor::createToolBar(CurveEditorModel *model)
|
|||||||
endSpin->setValue(model->maximumTime());
|
endSpin->setValue(model->maximumTime());
|
||||||
|
|
||||||
auto updateEndFrame = [this, model](int frame) {
|
auto updateEndFrame = [this, model](int frame) {
|
||||||
model->setMaximumTime(frame, false);
|
model->setMaximumTime(frame);
|
||||||
m_view->viewport()->update();
|
m_view->viewport()->update();
|
||||||
};
|
};
|
||||||
connect(endSpin, QOverload<int>::of(&QSpinBox::valueChanged), updateEndFrame);
|
connect(endSpin, QOverload<int>::of(&QSpinBox::valueChanged), updateEndFrame);
|
||||||
|
|
||||||
auto setStartSlot = [startSpin](int frame) { startSpin->setValue(frame); };
|
auto setStartSlot = [startSpin](int frame) { startSpin->setValue(frame); };
|
||||||
connect(model, &CurveEditorModel::updateStartFrame, setStartSlot);
|
connect(model, &CurveEditorModel::commitStartFrame, setStartSlot);
|
||||||
|
|
||||||
auto setEndSlot = [endSpin](int frame) { endSpin->setValue(frame); };
|
auto setEndSlot = [endSpin](int frame) { endSpin->setValue(frame); };
|
||||||
connect(model, &CurveEditorModel::updateEndFrame, setEndSlot);
|
connect(model, &CurveEditorModel::commitEndFrame, setEndSlot);
|
||||||
|
|
||||||
durationBox->addWidget(new QLabel(tr("Start Frame")));
|
durationBox->addWidget(new QLabel(tr("Start Frame")));
|
||||||
durationBox->addWidget(startSpin);
|
durationBox->addWidget(startSpin);
|
||||||
@@ -152,10 +160,14 @@ QToolBar *CurveEditor::createToolBar(CurveEditorModel *model)
|
|||||||
cfspin->setMaximum(std::numeric_limits<int>::max());
|
cfspin->setMaximum(std::numeric_limits<int>::max());
|
||||||
|
|
||||||
auto intSignal = static_cast<void (QSpinBox::*)(int)>(&QSpinBox::valueChanged);
|
auto intSignal = static_cast<void (QSpinBox::*)(int)>(&QSpinBox::valueChanged);
|
||||||
connect(cfspin, intSignal, [this](int val) { m_view->setCurrentFrame(val, false); });
|
connect(cfspin, intSignal, [this, model](int val) { model->commitCurrentFrame(val); });
|
||||||
connect(m_view, &GraphicsView::notifyFrameChanged, [cfspin](int val) {
|
connect(m_view, &GraphicsView::currentFrameChanged, [cfspin](int val, bool notify) {
|
||||||
QSignalBlocker blocker(cfspin);
|
if (notify) {
|
||||||
cfspin->setValue(val);
|
cfspin->setValue(val);
|
||||||
|
} else {
|
||||||
|
const QSignalBlocker blocker(cfspin);
|
||||||
|
cfspin->setValue(val);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
auto *positionBox = new QHBoxLayout;
|
auto *positionBox = new QHBoxLayout;
|
||||||
|
|||||||
@@ -41,6 +41,8 @@ class CurveEditor : public QWidget
|
|||||||
public:
|
public:
|
||||||
CurveEditor(CurveEditorModel *model, QWidget *parent = nullptr);
|
CurveEditor(CurveEditorModel *model, QWidget *parent = nullptr);
|
||||||
|
|
||||||
|
bool dragging() const;
|
||||||
|
|
||||||
void zoomX(double zoom);
|
void zoomX(double zoom);
|
||||||
|
|
||||||
void zoomY(double zoom);
|
void zoomY(double zoom);
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ HEADERS += \
|
|||||||
$$PWD/animationcurve.h \
|
$$PWD/animationcurve.h \
|
||||||
$$PWD/curveeditor.h \
|
$$PWD/curveeditor.h \
|
||||||
$$PWD/curveeditormodel.h \
|
$$PWD/curveeditormodel.h \
|
||||||
|
$$PWD/curveeditorview.h \
|
||||||
$$PWD/curvesegment.h \
|
$$PWD/curvesegment.h \
|
||||||
$$PWD/detail/colorcontrol.h \
|
$$PWD/detail/colorcontrol.h \
|
||||||
$$PWD/detail/curveeditorstyledialog.h \
|
$$PWD/detail/curveeditorstyledialog.h \
|
||||||
@@ -28,6 +29,7 @@ SOURCES += \
|
|||||||
$$PWD/curvesegment.cpp \
|
$$PWD/curvesegment.cpp \
|
||||||
$$PWD/curveeditor.cpp \
|
$$PWD/curveeditor.cpp \
|
||||||
$$PWD/curveeditormodel.cpp \
|
$$PWD/curveeditormodel.cpp \
|
||||||
|
$$PWD/curveeditorview.cpp \
|
||||||
$$PWD/detail/colorcontrol.cpp \
|
$$PWD/detail/colorcontrol.cpp \
|
||||||
$$PWD/detail/curveeditorstyledialog.cpp \
|
$$PWD/detail/curveeditorstyledialog.cpp \
|
||||||
$$PWD/detail/curveitem.cpp \
|
$$PWD/detail/curveitem.cpp \
|
||||||
|
|||||||
@@ -24,11 +24,19 @@
|
|||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
#include "curveeditormodel.h"
|
#include "curveeditormodel.h"
|
||||||
|
#include "curveeditorstyle.h"
|
||||||
#include "treeitem.h"
|
#include "treeitem.h"
|
||||||
|
|
||||||
#include "detail/graphicsview.h"
|
#include "detail/graphicsview.h"
|
||||||
#include "detail/selectionmodel.h"
|
#include "detail/selectionmodel.h"
|
||||||
|
|
||||||
|
#include "easingcurve.h"
|
||||||
|
#include "qmltimeline.h"
|
||||||
|
|
||||||
|
#include <bindingproperty.h>
|
||||||
|
#include <theme.h>
|
||||||
|
#include <variantproperty.h>
|
||||||
|
|
||||||
namespace DesignTools {
|
namespace DesignTools {
|
||||||
|
|
||||||
CurveEditorModel::CurveEditorModel(double minTime, double maxTime, QObject *parent)
|
CurveEditorModel::CurveEditorModel(double minTime, double maxTime, QObject *parent)
|
||||||
@@ -39,28 +47,82 @@ CurveEditorModel::CurveEditorModel(double minTime, double maxTime, QObject *pare
|
|||||||
|
|
||||||
CurveEditorModel::~CurveEditorModel() {}
|
CurveEditorModel::~CurveEditorModel() {}
|
||||||
|
|
||||||
|
double CurveEditorModel::minimumTime() const
|
||||||
|
{
|
||||||
|
return m_minTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
double CurveEditorModel::maximumTime() const
|
||||||
|
{
|
||||||
|
return m_maxTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
DesignTools::CurveEditorStyle CurveEditorModel::style() const
|
||||||
|
{
|
||||||
|
// Pseudo auto generated. See: CurveEditorStyleDialog
|
||||||
|
DesignTools::CurveEditorStyle out;
|
||||||
|
out.backgroundBrush = QBrush(QColor(21, 21, 21));
|
||||||
|
out.backgroundAlternateBrush = QBrush(QColor(32, 32, 32));
|
||||||
|
out.fontColor = QColor(255, 255, 255);
|
||||||
|
out.gridColor = QColor(114, 116, 118);
|
||||||
|
out.canvasMargin = 15;
|
||||||
|
out.zoomInWidth = 99;
|
||||||
|
out.zoomInHeight = 99;
|
||||||
|
out.timeAxisHeight = 60;
|
||||||
|
out.timeOffsetLeft = 10;
|
||||||
|
out.timeOffsetRight = 10;
|
||||||
|
out.rangeBarColor = QmlDesigner::Theme::instance()->qmlDesignerBackgroundColorDarkAlternate();
|
||||||
|
out.rangeBarCapsColor = QmlDesigner::Theme::getColor(
|
||||||
|
QmlDesigner::Theme::QmlDesigner_HighlightColor);
|
||||||
|
out.valueAxisWidth = 60;
|
||||||
|
out.valueOffsetTop = 10;
|
||||||
|
out.valueOffsetBottom = 10;
|
||||||
|
out.handleStyle.size = 10;
|
||||||
|
out.handleStyle.lineWidth = 1;
|
||||||
|
out.handleStyle.color = QColor(255, 255, 255);
|
||||||
|
out.handleStyle.selectionColor = QColor(255, 255, 255);
|
||||||
|
out.keyframeStyle.size = 14;
|
||||||
|
out.keyframeStyle.color = QColor(172, 210, 255);
|
||||||
|
out.keyframeStyle.selectionColor = QColor(255, 255, 255);
|
||||||
|
out.curveStyle.width = 2;
|
||||||
|
out.curveStyle.color = QColor(0, 200, 0);
|
||||||
|
out.curveStyle.selectionColor = QColor(255, 255, 255);
|
||||||
|
out.treeItemStyle.margins = 0;
|
||||||
|
out.playhead.width = 20;
|
||||||
|
out.playhead.radius = 4;
|
||||||
|
out.playhead.color = QColor(200, 200, 0);
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CurveEditorModel::setTimeline(const QmlDesigner::QmlTimeline &timeline)
|
||||||
|
{
|
||||||
|
m_minTime = timeline.startKeyframe();
|
||||||
|
m_maxTime = timeline.endKeyframe();
|
||||||
|
std::vector<DesignTools::TreeItem *> items;
|
||||||
|
for (auto &&target : timeline.allTargets()) {
|
||||||
|
if (DesignTools::TreeItem *item = createTopLevelItem(timeline, target))
|
||||||
|
items.push_back(item);
|
||||||
|
}
|
||||||
|
|
||||||
|
reset(items);
|
||||||
|
}
|
||||||
|
|
||||||
void CurveEditorModel::setCurrentFrame(int frame)
|
void CurveEditorModel::setCurrentFrame(int frame)
|
||||||
{
|
{
|
||||||
if (graphicsView())
|
if (graphicsView())
|
||||||
graphicsView()->setCurrentFrame(frame);
|
graphicsView()->setCurrentFrame(frame, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CurveEditorModel::setMinimumTime(double time, bool internal)
|
void CurveEditorModel::setMinimumTime(double time)
|
||||||
{
|
{
|
||||||
m_minTime = time;
|
m_minTime = time;
|
||||||
if (internal)
|
emit commitStartFrame(static_cast<int>(m_minTime));
|
||||||
emit updateStartFrame(m_minTime);
|
|
||||||
else
|
|
||||||
emit startFrameChanged(m_minTime);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void CurveEditorModel::setMaximumTime(double time, bool internal)
|
void CurveEditorModel::setMaximumTime(double time)
|
||||||
{
|
{
|
||||||
m_maxTime = time;
|
m_maxTime = time;
|
||||||
if (internal)
|
emit commitEndFrame(static_cast<int>(m_maxTime));
|
||||||
emit updateEndFrame(m_maxTime);
|
|
||||||
else
|
|
||||||
emit endFrameChanged(m_maxTime);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void CurveEditorModel::setCurve(unsigned int id, const AnimationCurve &curve)
|
void CurveEditorModel::setCurve(unsigned int id, const AnimationCurve &curve)
|
||||||
@@ -114,4 +176,152 @@ void CurveEditorModel::reset(const std::vector<TreeItem *> &items)
|
|||||||
sm->selectPaths(sel);
|
sm->selectPaths(sel);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DesignTools::ValueType typeFrom(const QmlDesigner::QmlTimelineKeyframeGroup &group)
|
||||||
|
{
|
||||||
|
if (group.valueType() == QmlDesigner::TypeName("double")
|
||||||
|
|| group.valueType() == QmlDesigner::TypeName("real")
|
||||||
|
|| group.valueType() == QmlDesigner::TypeName("float"))
|
||||||
|
return DesignTools::ValueType::Double;
|
||||||
|
|
||||||
|
if (group.valueType() == QmlDesigner::TypeName("boolean")
|
||||||
|
|| group.valueType() == QmlDesigner::TypeName("bool"))
|
||||||
|
return DesignTools::ValueType::Bool;
|
||||||
|
|
||||||
|
if (group.valueType() == QmlDesigner::TypeName("integer")
|
||||||
|
|| group.valueType() == QmlDesigner::TypeName("int"))
|
||||||
|
return DesignTools::ValueType::Integer;
|
||||||
|
|
||||||
|
// Ignoring: QColor / HAlignment / VAlignment
|
||||||
|
return DesignTools::ValueType::Undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
DesignTools::TreeItem *CurveEditorModel::createTopLevelItem(const QmlDesigner::QmlTimeline &timeline,
|
||||||
|
const QmlDesigner::ModelNode &node)
|
||||||
|
{
|
||||||
|
if (!node.isValid())
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
auto *nodeItem = new DesignTools::NodeTreeItem(node.id(), QIcon(":/ICON_INSTANCE"));
|
||||||
|
for (auto &&grp : timeline.keyframeGroupsForTarget(node)) {
|
||||||
|
if (grp.isValid()) {
|
||||||
|
DesignTools::AnimationCurve curve = createAnimationCurve(grp);
|
||||||
|
if (curve.isValid()) {
|
||||||
|
QString name = QString::fromUtf8(grp.propertyName());
|
||||||
|
auto propertyItem = new DesignTools::PropertyTreeItem(name, curve, typeFrom(grp));
|
||||||
|
|
||||||
|
QmlDesigner::ModelNode target = grp.modelNode();
|
||||||
|
if (target.hasAuxiliaryData("locked"))
|
||||||
|
propertyItem->setLocked(true);
|
||||||
|
|
||||||
|
if (target.hasAuxiliaryData("pinned"))
|
||||||
|
propertyItem->setPinned(true);
|
||||||
|
|
||||||
|
nodeItem->addChild(propertyItem);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!nodeItem->hasChildren()) {
|
||||||
|
delete nodeItem;
|
||||||
|
nodeItem = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
return nodeItem;
|
||||||
|
}
|
||||||
|
|
||||||
|
DesignTools::AnimationCurve CurveEditorModel::createAnimationCurve(
|
||||||
|
const QmlDesigner::QmlTimelineKeyframeGroup &group)
|
||||||
|
{
|
||||||
|
switch (typeFrom(group)) {
|
||||||
|
case DesignTools::ValueType::Bool:
|
||||||
|
return createDoubleCurve(group);
|
||||||
|
|
||||||
|
case DesignTools::ValueType::Integer:
|
||||||
|
return createDoubleCurve(group);
|
||||||
|
|
||||||
|
case DesignTools::ValueType::Double:
|
||||||
|
return createDoubleCurve(group);
|
||||||
|
|
||||||
|
default:
|
||||||
|
return DesignTools::AnimationCurve();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<DesignTools::Keyframe> createKeyframes(QList<QmlDesigner::ModelNode> nodes)
|
||||||
|
{
|
||||||
|
auto byTime = [](const auto &a, const auto &b) {
|
||||||
|
return a.variantProperty("frame").value().toDouble()
|
||||||
|
< b.variantProperty("frame").value().toDouble();
|
||||||
|
};
|
||||||
|
std::sort(nodes.begin(), nodes.end(), byTime);
|
||||||
|
|
||||||
|
std::vector<DesignTools::Keyframe> frames;
|
||||||
|
for (auto &&node : nodes) {
|
||||||
|
QVariant timeVariant = node.variantProperty("frame").value();
|
||||||
|
QVariant valueVariant = node.variantProperty("value").value();
|
||||||
|
if (!timeVariant.isValid() || !valueVariant.isValid())
|
||||||
|
continue;
|
||||||
|
|
||||||
|
QPointF position(timeVariant.toDouble(), valueVariant.toDouble());
|
||||||
|
|
||||||
|
auto keyframe = DesignTools::Keyframe(position);
|
||||||
|
|
||||||
|
if (node.hasBindingProperty("easing.bezierCurve")) {
|
||||||
|
QmlDesigner::EasingCurve ecurve;
|
||||||
|
ecurve.fromString(node.bindingProperty("easing.bezierCurve").expression());
|
||||||
|
keyframe.setData(static_cast<QEasingCurve>(ecurve));
|
||||||
|
}
|
||||||
|
frames.push_back(keyframe);
|
||||||
|
}
|
||||||
|
return frames;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<DesignTools::Keyframe> resolveSmallCurves(const std::vector<DesignTools::Keyframe> &frames)
|
||||||
|
{
|
||||||
|
std::vector<DesignTools::Keyframe> out;
|
||||||
|
for (auto &&frame : frames) {
|
||||||
|
if (frame.hasData() && !out.empty()) {
|
||||||
|
QEasingCurve curve = frame.data().toEasingCurve();
|
||||||
|
// One-segment-curve: Since (0,0) is implicit => 3
|
||||||
|
if (curve.toCubicSpline().count() == 3) {
|
||||||
|
DesignTools::Keyframe &previous = out.back();
|
||||||
|
#if 0
|
||||||
|
// Do not resolve when two adjacent keyframes have the same value.
|
||||||
|
if (qFuzzyCompare(previous.position().y(), frame.position().y())) {
|
||||||
|
out.push_back(frame);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
DesignTools::AnimationCurve acurve(curve, previous.position(), frame.position());
|
||||||
|
previous.setRightHandle(acurve.keyframeAt(0).rightHandle());
|
||||||
|
out.push_back(acurve.keyframeAt(1));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
out.push_back(frame);
|
||||||
|
}
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
DesignTools::AnimationCurve CurveEditorModel::createDoubleCurve(
|
||||||
|
const QmlDesigner::QmlTimelineKeyframeGroup &group)
|
||||||
|
{
|
||||||
|
std::vector<DesignTools::Keyframe> keyframes = createKeyframes(group.keyframePositions());
|
||||||
|
keyframes = resolveSmallCurves(keyframes);
|
||||||
|
|
||||||
|
QString str;
|
||||||
|
QmlDesigner::ModelNode target = group.modelNode();
|
||||||
|
if (target.hasAuxiliaryData("unified"))
|
||||||
|
str = target.auxiliaryData("unified").toString();
|
||||||
|
|
||||||
|
if (str.size() == static_cast<int>(keyframes.size())) {
|
||||||
|
for (int i = 0; i < str.size(); ++i) {
|
||||||
|
if (str.at(i) == '1')
|
||||||
|
keyframes[static_cast<size_t>(i)].setUnified(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return DesignTools::AnimationCurve(keyframes);
|
||||||
|
}
|
||||||
|
|
||||||
} // End namespace DesignTools.
|
} // End namespace DesignTools.
|
||||||
|
|||||||
@@ -27,6 +27,8 @@
|
|||||||
|
|
||||||
#include "detail/treemodel.h"
|
#include "detail/treemodel.h"
|
||||||
|
|
||||||
|
#include <qmltimelinekeyframegroup.h>
|
||||||
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
QT_BEGIN_NAMESPACE
|
QT_BEGIN_NAMESPACE
|
||||||
@@ -46,41 +48,46 @@ class CurveEditorModel : public TreeModel
|
|||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void currentFrameChanged(int frame);
|
void commitCurrentFrame(int frame);
|
||||||
|
|
||||||
void startFrameChanged(int frame);
|
void commitStartFrame(int frame);
|
||||||
|
|
||||||
void endFrameChanged(int frame);
|
void commitEndFrame(int frame);
|
||||||
|
|
||||||
void updateStartFrame(int frame);
|
|
||||||
|
|
||||||
void updateEndFrame(int frame);
|
|
||||||
|
|
||||||
void curveChanged(PropertyTreeItem *item);
|
void curveChanged(PropertyTreeItem *item);
|
||||||
|
|
||||||
public:
|
|
||||||
virtual double minimumTime() const = 0;
|
|
||||||
|
|
||||||
virtual double maximumTime() const = 0;
|
|
||||||
|
|
||||||
virtual CurveEditorStyle style() const = 0;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
CurveEditorModel(double minTime, double maxTime, QObject *parent = nullptr);
|
CurveEditorModel(double minTime, double maxTime, QObject *parent = nullptr);
|
||||||
|
|
||||||
~CurveEditorModel() override;
|
~CurveEditorModel() override;
|
||||||
|
|
||||||
|
double minimumTime() const;
|
||||||
|
|
||||||
|
double maximumTime() const;
|
||||||
|
|
||||||
|
DesignTools::CurveEditorStyle style() const;
|
||||||
|
|
||||||
|
public:
|
||||||
|
void setTimeline(const QmlDesigner::QmlTimeline &timeline);
|
||||||
|
|
||||||
void setCurrentFrame(int frame);
|
void setCurrentFrame(int frame);
|
||||||
|
|
||||||
void setMinimumTime(double time, bool internal);
|
void setMinimumTime(double time);
|
||||||
|
|
||||||
void setMaximumTime(double time, bool internal);
|
void setMaximumTime(double time);
|
||||||
|
|
||||||
void setCurve(unsigned int id, const AnimationCurve &curve);
|
void setCurve(unsigned int id, const AnimationCurve &curve);
|
||||||
|
|
||||||
void reset(const std::vector<TreeItem *> &items);
|
void reset(const std::vector<TreeItem *> &items);
|
||||||
|
|
||||||
protected:
|
private:
|
||||||
|
DesignTools::TreeItem *createTopLevelItem(const QmlDesigner::QmlTimeline &timeline,
|
||||||
|
const QmlDesigner::ModelNode &node);
|
||||||
|
|
||||||
|
DesignTools::AnimationCurve createAnimationCurve(const QmlDesigner::QmlTimelineKeyframeGroup &group);
|
||||||
|
|
||||||
|
DesignTools::AnimationCurve createDoubleCurve(const QmlDesigner::QmlTimelineKeyframeGroup &group);
|
||||||
|
|
||||||
double m_minTime = 0.;
|
double m_minTime = 0.;
|
||||||
|
|
||||||
double m_maxTime = 0.;
|
double m_maxTime = 0.;
|
||||||
|
|||||||
@@ -0,0 +1,375 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
**
|
||||||
|
** 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 "curveeditor.h"
|
||||||
|
#include "curveeditormodel.h"
|
||||||
|
#include "curvesegment.h"
|
||||||
|
|
||||||
|
#include <bindingproperty.h>
|
||||||
|
#include <easingcurve.h>
|
||||||
|
#include <nodeabstractproperty.h>
|
||||||
|
#include <variantproperty.h>
|
||||||
|
#include <qmlstate.h>
|
||||||
|
#include <qmltimeline.h>
|
||||||
|
|
||||||
|
#include <cmath>
|
||||||
|
|
||||||
|
namespace QmlDesigner {
|
||||||
|
|
||||||
|
CurveEditorView::CurveEditorView(QObject *parent)
|
||||||
|
: AbstractView(parent)
|
||||||
|
, m_block(false)
|
||||||
|
, m_model(new DesignTools::CurveEditorModel(0., 500.))
|
||||||
|
, m_editor(new DesignTools::CurveEditor(m_model))
|
||||||
|
{
|
||||||
|
Q_UNUSED(parent);
|
||||||
|
connect(m_model,
|
||||||
|
&DesignTools::CurveEditorModel::commitCurrentFrame,
|
||||||
|
this,
|
||||||
|
&CurveEditorView::commitCurrentFrame);
|
||||||
|
|
||||||
|
connect(m_model,
|
||||||
|
&DesignTools::CurveEditorModel::commitStartFrame,
|
||||||
|
this,
|
||||||
|
&CurveEditorView::commitStartFrame);
|
||||||
|
|
||||||
|
connect(m_model,
|
||||||
|
&DesignTools::CurveEditorModel::commitEndFrame,
|
||||||
|
this,
|
||||||
|
&CurveEditorView::commitEndFrame);
|
||||||
|
|
||||||
|
connect(m_model,
|
||||||
|
&DesignTools::CurveEditorModel::curveChanged,
|
||||||
|
this,
|
||||||
|
&CurveEditorView::commitKeyframes);
|
||||||
|
}
|
||||||
|
|
||||||
|
CurveEditorView::~CurveEditorView() {}
|
||||||
|
|
||||||
|
bool CurveEditorView::hasWidget() const
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
WidgetInfo CurveEditorView::widgetInfo()
|
||||||
|
{
|
||||||
|
return createWidgetInfo(
|
||||||
|
m_editor, nullptr, "CurveEditorId", WidgetInfo::BottomPane, 0, tr("CurveEditor"));
|
||||||
|
}
|
||||||
|
|
||||||
|
void CurveEditorView::modelAttached(Model *model)
|
||||||
|
{
|
||||||
|
AbstractView::modelAttached(model);
|
||||||
|
|
||||||
|
QmlTimeline timeline = activeTimeline();
|
||||||
|
if (timeline.isValid()) {
|
||||||
|
m_model->setTimeline(timeline);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CurveEditorView::modelAboutToBeDetached(Model *model)
|
||||||
|
{
|
||||||
|
AbstractView::modelAboutToBeDetached(model);
|
||||||
|
m_model->reset({});
|
||||||
|
}
|
||||||
|
|
||||||
|
bool dirtyfiesView(const ModelNode &node)
|
||||||
|
{
|
||||||
|
return QmlTimeline::isValidQmlTimeline(node)
|
||||||
|
|| QmlTimelineKeyframeGroup::isValidQmlTimelineKeyframeGroup(node);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CurveEditorView::nodeRemoved(const ModelNode &removedNode,
|
||||||
|
const NodeAbstractProperty &parentProperty,
|
||||||
|
PropertyChangeFlags propertyChange)
|
||||||
|
{
|
||||||
|
Q_UNUSED(removedNode);
|
||||||
|
Q_UNUSED(propertyChange);
|
||||||
|
|
||||||
|
if (!parentProperty.isValid())
|
||||||
|
return;
|
||||||
|
|
||||||
|
ModelNode parent = parentProperty.parentModelNode();
|
||||||
|
if (dirtyfiesView(parent))
|
||||||
|
updateKeyframes();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CurveEditorView::nodeReparented(const ModelNode &node,
|
||||||
|
const NodeAbstractProperty &newPropertyParent,
|
||||||
|
const NodeAbstractProperty &oldPropertyParent,
|
||||||
|
PropertyChangeFlags propertyChange)
|
||||||
|
{
|
||||||
|
Q_UNUSED(node);
|
||||||
|
Q_UNUSED(newPropertyParent);
|
||||||
|
Q_UNUSED(oldPropertyParent);
|
||||||
|
Q_UNUSED(propertyChange);
|
||||||
|
|
||||||
|
ModelNode parent = newPropertyParent.parentModelNode();
|
||||||
|
if (newPropertyParent.isValid() && dirtyfiesView(parent))
|
||||||
|
updateKeyframes();
|
||||||
|
else if (QmlTimelineKeyframeGroup::checkKeyframesType(node))
|
||||||
|
updateKeyframes();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CurveEditorView::instancePropertyChanged(const QList<QPair<ModelNode, PropertyName>> &propertyList)
|
||||||
|
{
|
||||||
|
Q_UNUSED(propertyList);
|
||||||
|
|
||||||
|
for (const auto &pair : propertyList) {
|
||||||
|
if (!QmlTimeline::isValidQmlTimeline(pair.first))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (pair.second == "startFrame")
|
||||||
|
updateStartFrame(pair.first);
|
||||||
|
else if (pair.second == "endFrame")
|
||||||
|
updateEndFrame(pair.first);
|
||||||
|
else if (pair.second == "currentFrame")
|
||||||
|
updateCurrentFrame(pair.first);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CurveEditorView::variantPropertiesChanged(const QList<VariantProperty> &propertyList,
|
||||||
|
PropertyChangeFlags propertyChange)
|
||||||
|
{
|
||||||
|
Q_UNUSED(propertyList);
|
||||||
|
Q_UNUSED(propertyChange);
|
||||||
|
|
||||||
|
for (const auto &property : propertyList) {
|
||||||
|
if ((property.name() == "frame" || property.name() == "value")
|
||||||
|
&& property.parentModelNode().type() == "QtQuick.Timeline.Keyframe"
|
||||||
|
&& property.parentModelNode().isValid()
|
||||||
|
&& property.parentModelNode().hasParentProperty()) {
|
||||||
|
const ModelNode framesNode = property.parentModelNode().parentProperty().parentModelNode();
|
||||||
|
if (QmlTimelineKeyframeGroup::isValidQmlTimelineKeyframeGroup(framesNode))
|
||||||
|
updateKeyframes();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CurveEditorView::bindingPropertiesChanged(const QList<BindingProperty> &propertyList,
|
||||||
|
PropertyChangeFlags propertyChange)
|
||||||
|
{
|
||||||
|
Q_UNUSED(propertyList);
|
||||||
|
Q_UNUSED(propertyChange);
|
||||||
|
|
||||||
|
for (const auto &property : propertyList) {
|
||||||
|
if (property.name() == "easing.bezierCurve") {
|
||||||
|
updateKeyframes();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CurveEditorView::propertiesRemoved(const QList<AbstractProperty> &propertyList)
|
||||||
|
{
|
||||||
|
Q_UNUSED(propertyList);
|
||||||
|
|
||||||
|
for (const auto &property : propertyList) {
|
||||||
|
if (property.name() == "keyframes" && property.parentModelNode().isValid()) {
|
||||||
|
ModelNode parent = property.parentModelNode();
|
||||||
|
if (dirtyfiesView(parent))
|
||||||
|
updateKeyframes();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
QmlTimeline CurveEditorView::activeTimeline() const
|
||||||
|
{
|
||||||
|
QmlModelState state = currentState();
|
||||||
|
if (state.isBaseState()) {
|
||||||
|
for (const ModelNode &node : allModelNodesOfType("QtQuick.Timeline.Timeline")) {
|
||||||
|
if (QmlTimeline::isValidQmlTimeline(node)) {
|
||||||
|
if (node.hasVariantProperty("enabled")
|
||||||
|
&& node.variantProperty("enabled").value().toBool())
|
||||||
|
return QmlTimeline(node);
|
||||||
|
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const ModelNode &node : allModelNodesOfType("QtQuick.Timeline.Timeline")) {
|
||||||
|
if (QmlTimeline::isValidQmlTimeline(node) && state.affectsModelNode(node)) {
|
||||||
|
QmlPropertyChanges propertyChanges(state.propertyChanges(node));
|
||||||
|
if (!propertyChanges.isValid())
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (node.hasVariantProperty("enabled") && node.variantProperty("enabled").value().toBool())
|
||||||
|
return QmlTimeline(node);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
void CurveEditorView::updateKeyframes()
|
||||||
|
{
|
||||||
|
if (m_block)
|
||||||
|
return;
|
||||||
|
|
||||||
|
QmlTimeline timeline = activeTimeline();
|
||||||
|
if (timeline.isValid())
|
||||||
|
m_model->setTimeline(timeline);
|
||||||
|
else
|
||||||
|
m_model->reset({});
|
||||||
|
}
|
||||||
|
|
||||||
|
void CurveEditorView::updateCurrentFrame(const ModelNode &node)
|
||||||
|
{
|
||||||
|
if (m_editor->dragging())
|
||||||
|
return;
|
||||||
|
|
||||||
|
QmlTimeline timeline(node);
|
||||||
|
if (timeline.isValid())
|
||||||
|
m_model->setCurrentFrame(static_cast<int>(std::round(timeline.currentKeyframe())));
|
||||||
|
else
|
||||||
|
m_model->setCurrentFrame(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CurveEditorView::updateStartFrame(const ModelNode &node)
|
||||||
|
{
|
||||||
|
QmlTimeline timeline(node);
|
||||||
|
if (timeline.isValid())
|
||||||
|
m_model->setMinimumTime(static_cast<int>(std::round(timeline.startKeyframe())));
|
||||||
|
}
|
||||||
|
|
||||||
|
void CurveEditorView::updateEndFrame(const ModelNode &node)
|
||||||
|
{
|
||||||
|
QmlTimeline timeline(node);
|
||||||
|
if (timeline.isValid())
|
||||||
|
m_model->setMaximumTime(static_cast<int>(std::round(timeline.endKeyframe())));
|
||||||
|
}
|
||||||
|
|
||||||
|
ModelNode getTargetNode1(DesignTools::PropertyTreeItem *item, const QmlTimeline &timeline)
|
||||||
|
{
|
||||||
|
if (const DesignTools::NodeTreeItem *nodeItem = item->parentNodeTreeItem()) {
|
||||||
|
QString targetId = nodeItem->name();
|
||||||
|
if (timeline.isValid()) {
|
||||||
|
for (auto &&target : timeline.allTargets()) {
|
||||||
|
if (target.displayName() == targetId)
|
||||||
|
return target;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ModelNode();
|
||||||
|
}
|
||||||
|
|
||||||
|
QmlTimelineKeyframeGroup timelineKeyframeGroup1(QmlTimeline &timeline,
|
||||||
|
DesignTools::PropertyTreeItem *item)
|
||||||
|
{
|
||||||
|
ModelNode node = getTargetNode1(item, timeline);
|
||||||
|
if (node.isValid())
|
||||||
|
return timeline.keyframeGroup(node, item->name().toLatin1());
|
||||||
|
|
||||||
|
return QmlTimelineKeyframeGroup();
|
||||||
|
}
|
||||||
|
|
||||||
|
void attachEasingCurve1(double frame, const QEasingCurve &curve, const QmlTimelineKeyframeGroup &group)
|
||||||
|
{
|
||||||
|
ModelNode frameNode = group.keyframe(frame);
|
||||||
|
if (frameNode.isValid()) {
|
||||||
|
auto expression = EasingCurve(curve).toString();
|
||||||
|
frameNode.bindingProperty("easing.bezierCurve").setExpression(expression);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CurveEditorView::commitKeyframes(DesignTools::PropertyTreeItem *item)
|
||||||
|
{
|
||||||
|
QmlTimeline currentTimeline = activeTimeline();
|
||||||
|
QmlTimelineKeyframeGroup group = timelineKeyframeGroup1(currentTimeline, item);
|
||||||
|
|
||||||
|
if (group.isValid()) {
|
||||||
|
ModelNode groupNode = group.modelNode();
|
||||||
|
|
||||||
|
if (groupNode.isValid()) {
|
||||||
|
if (item->locked())
|
||||||
|
groupNode.setAuxiliaryData("locked", true);
|
||||||
|
else
|
||||||
|
groupNode.removeAuxiliaryData("locked");
|
||||||
|
|
||||||
|
if (item->pinned())
|
||||||
|
groupNode.setAuxiliaryData("pinned", true);
|
||||||
|
else
|
||||||
|
groupNode.removeAuxiliaryData("pinned");
|
||||||
|
|
||||||
|
if (item->hasUnified())
|
||||||
|
groupNode.setAuxiliaryData("unified", item->unifyString());
|
||||||
|
else
|
||||||
|
groupNode.removeAuxiliaryData("unified");
|
||||||
|
}
|
||||||
|
|
||||||
|
auto replaceKeyframes = [&group, item, this]() {
|
||||||
|
m_block = true;
|
||||||
|
for (auto frame : group.keyframes())
|
||||||
|
frame.destroy();
|
||||||
|
|
||||||
|
DesignTools::Keyframe previous;
|
||||||
|
for (auto &&frame : item->curve().keyframes()) {
|
||||||
|
QPointF pos = frame.position();
|
||||||
|
group.setValue(QVariant(pos.y()), pos.x());
|
||||||
|
|
||||||
|
if (previous.isValid()) {
|
||||||
|
if (frame.interpolation() == DesignTools::Keyframe::Interpolation::Bezier) {
|
||||||
|
DesignTools::CurveSegment segment(previous, frame);
|
||||||
|
if (segment.isValid())
|
||||||
|
attachEasingCurve1(pos.x(), segment.easingCurve(), group);
|
||||||
|
} else if (frame.interpolation() == DesignTools::Keyframe::Interpolation::Easing) {
|
||||||
|
QVariant data = frame.data();
|
||||||
|
if (data.type() == static_cast<int>(QMetaType::QEasingCurve))
|
||||||
|
attachEasingCurve1(pos.x(), data.value<QEasingCurve>(), group);
|
||||||
|
} else if (frame.interpolation() == DesignTools::Keyframe::Interpolation::Step) {
|
||||||
|
// Warning: Keyframe::Interpolation::Step not yet implemented
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
previous = frame;
|
||||||
|
}
|
||||||
|
m_block = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
executeInTransaction("CurveEditor::commitKeyframes", replaceKeyframes);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CurveEditorView::commitCurrentFrame(int frame)
|
||||||
|
{
|
||||||
|
QmlTimeline timeline = activeTimeline();
|
||||||
|
timeline.modelNode().setAuxiliaryData("currentFrame@NodeInstance", frame);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CurveEditorView::commitStartFrame(int frame)
|
||||||
|
{
|
||||||
|
QmlTimeline timeline = activeTimeline();
|
||||||
|
if (timeline.isValid())
|
||||||
|
timeline.modelNode().variantProperty("startFrame").setValue(frame);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CurveEditorView::commitEndFrame(int frame)
|
||||||
|
{
|
||||||
|
QmlTimeline timeline = activeTimeline();
|
||||||
|
if (timeline.isValid())
|
||||||
|
timeline.modelNode().variantProperty("endFrame").setValue(frame);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace QmlDesigner
|
||||||
@@ -0,0 +1,91 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
**
|
||||||
|
** 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 "curveeditor.h"
|
||||||
|
#include "curveeditormodel.h"
|
||||||
|
#include <abstractview.h>
|
||||||
|
|
||||||
|
namespace QmlDesigner {
|
||||||
|
|
||||||
|
class TimelineWidget;
|
||||||
|
|
||||||
|
class CurveEditorView : public AbstractView
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit CurveEditorView(QObject *parent = nullptr);
|
||||||
|
~CurveEditorView() override;
|
||||||
|
|
||||||
|
public:
|
||||||
|
bool hasWidget() const override;
|
||||||
|
|
||||||
|
WidgetInfo widgetInfo() override;
|
||||||
|
|
||||||
|
void modelAttached(Model *model) override;
|
||||||
|
|
||||||
|
void modelAboutToBeDetached(Model *model) override;
|
||||||
|
|
||||||
|
void nodeRemoved(const ModelNode &removedNode,
|
||||||
|
const NodeAbstractProperty &parentProperty,
|
||||||
|
PropertyChangeFlags propertyChange) override;
|
||||||
|
|
||||||
|
void nodeReparented(const ModelNode &node,
|
||||||
|
const NodeAbstractProperty &newPropertyParent,
|
||||||
|
const NodeAbstractProperty &oldPropertyParent,
|
||||||
|
PropertyChangeFlags propertyChange) override;
|
||||||
|
|
||||||
|
void instancePropertyChanged(const QList<QPair<ModelNode, PropertyName>> &propertyList) override;
|
||||||
|
|
||||||
|
void variantPropertiesChanged(const QList<VariantProperty> &propertyList,
|
||||||
|
PropertyChangeFlags propertyChange) override;
|
||||||
|
|
||||||
|
void bindingPropertiesChanged(const QList<BindingProperty> &propertyList,
|
||||||
|
PropertyChangeFlags propertyChange) override;
|
||||||
|
|
||||||
|
void propertiesRemoved(const QList<AbstractProperty> &propertyList) override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
QmlTimeline activeTimeline() const;
|
||||||
|
|
||||||
|
void updateKeyframes();
|
||||||
|
void updateCurrentFrame(const ModelNode &node);
|
||||||
|
void updateStartFrame(const ModelNode &node);
|
||||||
|
void updateEndFrame(const ModelNode &node);
|
||||||
|
|
||||||
|
void commitKeyframes(DesignTools::PropertyTreeItem *item);
|
||||||
|
void commitCurrentFrame(int frame);
|
||||||
|
void commitStartFrame(int frame);
|
||||||
|
void commitEndFrame(int frame);
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool m_block;
|
||||||
|
DesignTools::CurveEditorModel *m_model;
|
||||||
|
DesignTools::CurveEditor *m_editor;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace QmlDesigner
|
||||||
@@ -43,6 +43,7 @@ namespace DesignTools {
|
|||||||
|
|
||||||
GraphicsView::GraphicsView(CurveEditorModel *model, QWidget *parent)
|
GraphicsView::GraphicsView(CurveEditorModel *model, QWidget *parent)
|
||||||
: QGraphicsView(parent)
|
: QGraphicsView(parent)
|
||||||
|
, m_dragging(false)
|
||||||
, m_zoomX(0.0)
|
, m_zoomX(0.0)
|
||||||
, m_zoomY(0.0)
|
, m_zoomY(0.0)
|
||||||
, m_transform()
|
, m_transform()
|
||||||
@@ -98,6 +99,11 @@ CurveEditorStyle GraphicsView::editorStyle() const
|
|||||||
return m_style;
|
return m_style;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool GraphicsView::dragging() const
|
||||||
|
{
|
||||||
|
return m_dragging;
|
||||||
|
}
|
||||||
|
|
||||||
double GraphicsView::minimumTime() const
|
double GraphicsView::minimumTime() const
|
||||||
{
|
{
|
||||||
bool check = m_model->minimumTime() < m_scene->minimumTime();
|
bool check = m_model->minimumTime() < m_scene->minimumTime();
|
||||||
@@ -152,9 +158,8 @@ QRectF GraphicsView::timeScaleRect() const
|
|||||||
QRectF GraphicsView::valueScaleRect() const
|
QRectF GraphicsView::valueScaleRect() const
|
||||||
{
|
{
|
||||||
QRect vp(viewport()->rect());
|
QRect vp(viewport()->rect());
|
||||||
QPoint tl = vp.topLeft() + QPoint(0, m_style.timeAxisHeight);
|
|
||||||
QPoint br = vp.bottomLeft() + QPoint(m_style.valueAxisWidth, 0);
|
QPoint br = vp.bottomLeft() + QPoint(m_style.valueAxisWidth, 0);
|
||||||
return mapToScene(QRect(tl, br)).boundingRect();
|
return mapToScene(QRect(vp.topLeft(), br)).boundingRect();
|
||||||
}
|
}
|
||||||
|
|
||||||
QRectF GraphicsView::defaultRasterRect() const
|
QRectF GraphicsView::defaultRasterRect() const
|
||||||
@@ -204,11 +209,11 @@ void GraphicsView::setZoomY(double zoom, const QPoint &pivot)
|
|||||||
void GraphicsView::setCurrentFrame(int frame, bool notify)
|
void GraphicsView::setCurrentFrame(int frame, bool notify)
|
||||||
{
|
{
|
||||||
int clampedFrame = clamp(frame, m_model->minimumTime(), m_model->maximumTime());
|
int clampedFrame = clamp(frame, m_model->minimumTime(), m_model->maximumTime());
|
||||||
|
|
||||||
m_playhead.moveToFrame(clampedFrame, this);
|
m_playhead.moveToFrame(clampedFrame, this);
|
||||||
viewport()->update();
|
viewport()->update();
|
||||||
|
|
||||||
if (notify)
|
currentFrameChanged(clampedFrame, notify);
|
||||||
notifyFrameChanged(frame);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void GraphicsView::scrollContent(double x, double y)
|
void GraphicsView::scrollContent(double x, double y)
|
||||||
@@ -276,8 +281,10 @@ void GraphicsView::keyPressEvent(QKeyEvent *event)
|
|||||||
|
|
||||||
void GraphicsView::mousePressEvent(QMouseEvent *event)
|
void GraphicsView::mousePressEvent(QMouseEvent *event)
|
||||||
{
|
{
|
||||||
if (m_playhead.mousePress(globalToScene(event->globalPos())))
|
if (m_playhead.mousePress(globalToScene(event->globalPos()))) {
|
||||||
|
m_dragging = true;
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
Shortcut shortcut(event);
|
Shortcut shortcut(event);
|
||||||
if (shortcut == m_style.shortcuts.insertKeyframe) {
|
if (shortcut == m_style.shortcuts.insertKeyframe) {
|
||||||
@@ -288,6 +295,7 @@ void GraphicsView::mousePressEvent(QMouseEvent *event)
|
|||||||
if (shortcut == Shortcut(Qt::LeftButton)) {
|
if (shortcut == Shortcut(Qt::LeftButton)) {
|
||||||
QPointF pos = mapToScene(event->pos());
|
QPointF pos = mapToScene(event->pos());
|
||||||
if (timeScaleRect().contains(pos)) {
|
if (timeScaleRect().contains(pos)) {
|
||||||
|
m_dragging = true;
|
||||||
setCurrentFrame(std::round(mapXtoTime(pos.x())));
|
setCurrentFrame(std::round(mapXtoTime(pos.x())));
|
||||||
m_playhead.setMoving(true);
|
m_playhead.setMoving(true);
|
||||||
event->accept();
|
event->accept();
|
||||||
@@ -317,6 +325,7 @@ void GraphicsView::mouseReleaseEvent(QMouseEvent *event)
|
|||||||
m_playhead.mouseRelease(this);
|
m_playhead.mouseRelease(this);
|
||||||
m_selector.mouseRelease(event, m_scene);
|
m_selector.mouseRelease(event, m_scene);
|
||||||
this->viewport()->update();
|
this->viewport()->update();
|
||||||
|
m_dragging = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void GraphicsView::wheelEvent(QWheelEvent *event)
|
void GraphicsView::wheelEvent(QWheelEvent *event)
|
||||||
@@ -364,15 +373,14 @@ void GraphicsView::drawForeground(QPainter *painter, const QRectF &rect)
|
|||||||
if (abscissa.isValid())
|
if (abscissa.isValid())
|
||||||
drawTimeScale(painter, abscissa);
|
drawTimeScale(painter, abscissa);
|
||||||
|
|
||||||
painter->fillRect(QRectF(rect.topLeft(), abscissa.bottomLeft()),
|
painter->fillRect(QRectF(rect.topLeft(), abscissa.bottomLeft()), m_style.backgroundAlternateBrush);
|
||||||
m_style.backgroundAlternateBrush);
|
|
||||||
|
m_playhead.paint(painter, this);
|
||||||
|
|
||||||
auto ordinate = valueScaleRect();
|
auto ordinate = valueScaleRect();
|
||||||
if (ordinate.isValid())
|
if (ordinate.isValid())
|
||||||
drawValueScale(painter, ordinate);
|
drawValueScale(painter, ordinate);
|
||||||
|
|
||||||
m_playhead.paint(painter, this);
|
|
||||||
|
|
||||||
m_selector.paint(painter);
|
m_selector.paint(painter);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -463,11 +471,7 @@ void GraphicsView::applyZoom(double x, double y, const QPoint &pivot)
|
|||||||
|
|
||||||
void GraphicsView::drawGrid(QPainter *painter, const QRectF &rect)
|
void GraphicsView::drawGrid(QPainter *painter, const QRectF &rect)
|
||||||
{
|
{
|
||||||
QRectF gridRect = rect.adjusted(
|
QRectF gridRect = scene()->sceneRect();
|
||||||
m_style.valueAxisWidth + m_style.canvasMargin,
|
|
||||||
m_style.timeAxisHeight + m_style.canvasMargin,
|
|
||||||
-m_style.canvasMargin,
|
|
||||||
-m_style.canvasMargin);
|
|
||||||
|
|
||||||
if (!gridRect.isValid())
|
if (!gridRect.isValid())
|
||||||
return;
|
return;
|
||||||
@@ -577,8 +581,6 @@ void GraphicsView::drawTimeScale(QPainter *painter, const QRectF &rect)
|
|||||||
for (double i = minimumTime(); i <= maximumTime(); i += timeIncrement)
|
for (double i = minimumTime(); i <= maximumTime(); i += timeIncrement)
|
||||||
paintLabeledTick(i);
|
paintLabeledTick(i);
|
||||||
|
|
||||||
drawRangeBar(painter, rect);
|
|
||||||
|
|
||||||
painter->restore();
|
painter->restore();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -47,7 +47,7 @@ class GraphicsView : public QGraphicsView
|
|||||||
friend class Playhead;
|
friend class Playhead;
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void notifyFrameChanged(int frame);
|
void currentFrameChanged(int frame, bool notify);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
GraphicsView(CurveEditorModel *model, QWidget *parent = nullptr);
|
GraphicsView(CurveEditorModel *model, QWidget *parent = nullptr);
|
||||||
@@ -58,6 +58,8 @@ public:
|
|||||||
|
|
||||||
CurveEditorStyle editorStyle() const;
|
CurveEditorStyle editorStyle() const;
|
||||||
|
|
||||||
|
bool dragging() const;
|
||||||
|
|
||||||
int mapTimeToX(double time) const;
|
int mapTimeToX(double time) const;
|
||||||
|
|
||||||
int mapValueToY(double value) const;
|
int mapValueToY(double value) const;
|
||||||
@@ -153,6 +155,8 @@ private:
|
|||||||
QRectF rangeMaxHandle(const QRectF &rect);
|
QRectF rangeMaxHandle(const QRectF &rect);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
bool m_dragging;
|
||||||
|
|
||||||
double m_zoomX;
|
double m_zoomX;
|
||||||
|
|
||||||
double m_zoomY;
|
double m_zoomY;
|
||||||
|
|||||||
@@ -102,9 +102,10 @@ bool Playhead::mouseMove(const QPointF &pos, GraphicsView *view)
|
|||||||
|
|
||||||
QRectF canvas = view->canvasRect().adjusted(0.0, -style.timeAxisHeight, 0.0, 0.0);
|
QRectF canvas = view->canvasRect().adjusted(0.0, -style.timeAxisHeight, 0.0, 0.0);
|
||||||
|
|
||||||
if (canvas.contains(pos))
|
if (canvas.contains(pos)) {
|
||||||
view->setCurrentFrame(std::round(view->mapXtoTime(pos.x())));
|
int frame = std::round(view->mapXtoTime(pos.x()));
|
||||||
else if (!m_timer.isActive())
|
view->setCurrentFrame(frame);
|
||||||
|
} else if (!m_timer.isActive())
|
||||||
m_timer.start();
|
m_timer.start();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -148,9 +149,6 @@ void Playhead::mouseMoveOutOfBounds(GraphicsView *view)
|
|||||||
|
|
||||||
void Playhead::mouseRelease(GraphicsView *view)
|
void Playhead::mouseRelease(GraphicsView *view)
|
||||||
{
|
{
|
||||||
if (m_moving)
|
|
||||||
emit view->model()->currentFrameChanged(m_frame);
|
|
||||||
|
|
||||||
m_moving = false;
|
m_moving = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,63 +0,0 @@
|
|||||||
/****************************************************************************
|
|
||||||
**
|
|
||||||
** Copyright (C) 2018 The Qt Company Ltd.
|
|
||||||
** Contact: https://www.qt.io/licensing/
|
|
||||||
**
|
|
||||||
** This file is part of Qt Creator.
|
|
||||||
**
|
|
||||||
** 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 "animationcurvedialog.h"
|
|
||||||
|
|
||||||
#include <QVBoxLayout>
|
|
||||||
|
|
||||||
namespace QmlDesigner {
|
|
||||||
|
|
||||||
AnimationCurveDialog::AnimationCurveDialog(QWidget *parent)
|
|
||||||
: QDialog(parent)
|
|
||||||
, m_editor(nullptr)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
AnimationCurveDialog::AnimationCurveDialog(DesignTools::CurveEditorModel *model, QWidget *parent)
|
|
||||||
: QDialog(parent)
|
|
||||||
, m_editor(nullptr)
|
|
||||||
{
|
|
||||||
setModel(model);
|
|
||||||
}
|
|
||||||
|
|
||||||
void AnimationCurveDialog::setModel(DesignTools::CurveEditorModel *model)
|
|
||||||
{
|
|
||||||
if (m_editor)
|
|
||||||
return;
|
|
||||||
|
|
||||||
m_editor = new DesignTools::CurveEditor(model);
|
|
||||||
|
|
||||||
auto *layout = new QVBoxLayout;
|
|
||||||
layout->addWidget(m_editor);
|
|
||||||
setLayout(layout);
|
|
||||||
}
|
|
||||||
|
|
||||||
void AnimationCurveDialog::refresh()
|
|
||||||
{
|
|
||||||
if (m_editor)
|
|
||||||
m_editor->clearCanvas();
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace QmlDesigner
|
|
||||||
@@ -1,51 +0,0 @@
|
|||||||
/****************************************************************************
|
|
||||||
**
|
|
||||||
** Copyright (C) 2018 The Qt Company Ltd.
|
|
||||||
** Contact: https://www.qt.io/licensing/
|
|
||||||
**
|
|
||||||
** This file is part of Qt Creator.
|
|
||||||
**
|
|
||||||
** 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 "curveeditor/curveeditor.h"
|
|
||||||
|
|
||||||
#include <QDialog>
|
|
||||||
|
|
||||||
namespace QmlDesigner {
|
|
||||||
|
|
||||||
class AnimationCurveDialog : public QDialog
|
|
||||||
{
|
|
||||||
Q_OBJECT
|
|
||||||
|
|
||||||
public:
|
|
||||||
AnimationCurveDialog(QWidget *parent = nullptr);
|
|
||||||
|
|
||||||
AnimationCurveDialog(DesignTools::CurveEditorModel *model, QWidget *parent = nullptr);
|
|
||||||
|
|
||||||
void setModel(DesignTools::CurveEditorModel *model);
|
|
||||||
|
|
||||||
void refresh();
|
|
||||||
|
|
||||||
private:
|
|
||||||
DesignTools::CurveEditor *m_editor;
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace QmlDesigner
|
|
||||||
@@ -1,249 +0,0 @@
|
|||||||
/****************************************************************************
|
|
||||||
**
|
|
||||||
** Copyright (C) 2018 The Qt Company Ltd.
|
|
||||||
** Contact: https://www.qt.io/licensing/
|
|
||||||
**
|
|
||||||
** This file is part of Qt Creator.
|
|
||||||
**
|
|
||||||
** 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 "animationcurveeditormodel.h"
|
|
||||||
#include "curveeditor/curveeditorstyle.h"
|
|
||||||
#include "curveeditor/treeitem.h"
|
|
||||||
#include "easingcurve.h"
|
|
||||||
#include "qmltimeline.h"
|
|
||||||
|
|
||||||
#include <bindingproperty.h>
|
|
||||||
#include <theme.h>
|
|
||||||
#include <variantproperty.h>
|
|
||||||
|
|
||||||
namespace QmlDesigner {
|
|
||||||
|
|
||||||
AnimationCurveEditorModel::AnimationCurveEditorModel(double minTime, double maxTime)
|
|
||||||
: CurveEditorModel(minTime, maxTime)
|
|
||||||
{}
|
|
||||||
|
|
||||||
AnimationCurveEditorModel::~AnimationCurveEditorModel() {}
|
|
||||||
|
|
||||||
double AnimationCurveEditorModel::minimumTime() const
|
|
||||||
{
|
|
||||||
return m_minTime;
|
|
||||||
}
|
|
||||||
|
|
||||||
double AnimationCurveEditorModel::maximumTime() const
|
|
||||||
{
|
|
||||||
return m_maxTime;
|
|
||||||
}
|
|
||||||
|
|
||||||
DesignTools::CurveEditorStyle AnimationCurveEditorModel::style() const
|
|
||||||
{
|
|
||||||
// Pseudo auto generated. See: CurveEditorStyleDialog
|
|
||||||
DesignTools::CurveEditorStyle out;
|
|
||||||
out.backgroundBrush = QBrush(QColor(21, 21, 21));
|
|
||||||
out.backgroundAlternateBrush = QBrush(QColor(32, 32, 32));
|
|
||||||
out.fontColor = QColor(255, 255, 255);
|
|
||||||
out.gridColor = QColor(114, 116, 118);
|
|
||||||
out.canvasMargin = 15;
|
|
||||||
out.zoomInWidth = 99;
|
|
||||||
out.zoomInHeight = 99;
|
|
||||||
out.timeAxisHeight = 60;
|
|
||||||
out.timeOffsetLeft = 10;
|
|
||||||
out.timeOffsetRight = 10;
|
|
||||||
out.rangeBarColor = Theme::instance()->qmlDesignerBackgroundColorDarkAlternate();
|
|
||||||
out.rangeBarCapsColor = Theme::getColor(Theme::QmlDesigner_HighlightColor);
|
|
||||||
out.valueAxisWidth = 60;
|
|
||||||
out.valueOffsetTop = 10;
|
|
||||||
out.valueOffsetBottom = 10;
|
|
||||||
out.handleStyle.size = 10;
|
|
||||||
out.handleStyle.lineWidth = 1;
|
|
||||||
out.handleStyle.color = QColor(255, 255, 255);
|
|
||||||
out.handleStyle.selectionColor = QColor(255, 255, 255);
|
|
||||||
out.keyframeStyle.size = 14;
|
|
||||||
out.keyframeStyle.color = QColor(172, 210, 255);
|
|
||||||
out.keyframeStyle.selectionColor = QColor(255, 255, 255);
|
|
||||||
out.curveStyle.width = 2;
|
|
||||||
out.curveStyle.color = QColor(0, 200, 0);
|
|
||||||
out.curveStyle.selectionColor = QColor(255, 255, 255);
|
|
||||||
out.treeItemStyle.margins = 0;
|
|
||||||
out.playhead.width = 20;
|
|
||||||
out.playhead.radius = 4;
|
|
||||||
out.playhead.color = QColor(200, 200, 0);
|
|
||||||
return out;
|
|
||||||
}
|
|
||||||
|
|
||||||
void AnimationCurveEditorModel::setTimeline(const QmlTimeline &timeline)
|
|
||||||
{
|
|
||||||
m_minTime = timeline.startKeyframe();
|
|
||||||
m_maxTime = timeline.endKeyframe();
|
|
||||||
|
|
||||||
std::vector<DesignTools::TreeItem *> items;
|
|
||||||
for (auto &&target : timeline.allTargets()) {
|
|
||||||
if (DesignTools::TreeItem *item = createTopLevelItem(timeline, target))
|
|
||||||
items.push_back(item);
|
|
||||||
}
|
|
||||||
|
|
||||||
reset(items);
|
|
||||||
}
|
|
||||||
|
|
||||||
DesignTools::ValueType typeFrom(const QmlTimelineKeyframeGroup &group)
|
|
||||||
{
|
|
||||||
if (group.valueType() == TypeName("double") || group.valueType() == TypeName("real")
|
|
||||||
|| group.valueType() == TypeName("float"))
|
|
||||||
return DesignTools::ValueType::Double;
|
|
||||||
|
|
||||||
if (group.valueType() == TypeName("boolean") || group.valueType() == TypeName("bool"))
|
|
||||||
return DesignTools::ValueType::Bool;
|
|
||||||
|
|
||||||
if (group.valueType() == TypeName("integer") || group.valueType() == TypeName("int"))
|
|
||||||
return DesignTools::ValueType::Integer;
|
|
||||||
|
|
||||||
// Ignoring: QColor / HAlignment / VAlignment
|
|
||||||
return DesignTools::ValueType::Undefined;
|
|
||||||
}
|
|
||||||
|
|
||||||
DesignTools::TreeItem *AnimationCurveEditorModel::createTopLevelItem(const QmlTimeline &timeline,
|
|
||||||
const ModelNode &node)
|
|
||||||
{
|
|
||||||
if (!node.isValid())
|
|
||||||
return nullptr;
|
|
||||||
|
|
||||||
auto *nodeItem = new DesignTools::NodeTreeItem(node.id(), QIcon(":/ICON_INSTANCE"));
|
|
||||||
for (auto &&grp : timeline.keyframeGroupsForTarget(node)) {
|
|
||||||
if (grp.isValid()) {
|
|
||||||
DesignTools::AnimationCurve curve = createAnimationCurve(grp);
|
|
||||||
if (curve.isValid()) {
|
|
||||||
QString name = QString::fromUtf8(grp.propertyName());
|
|
||||||
auto propertyItem = new DesignTools::PropertyTreeItem(name, curve, typeFrom(grp));
|
|
||||||
|
|
||||||
ModelNode target = grp.modelNode();
|
|
||||||
if (target.hasAuxiliaryData("locked"))
|
|
||||||
propertyItem->setLocked(true);
|
|
||||||
|
|
||||||
if (target.hasAuxiliaryData("pinned"))
|
|
||||||
propertyItem->setPinned(true);
|
|
||||||
|
|
||||||
nodeItem->addChild(propertyItem);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!nodeItem->hasChildren()) {
|
|
||||||
delete nodeItem;
|
|
||||||
nodeItem = nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
return nodeItem;
|
|
||||||
}
|
|
||||||
|
|
||||||
DesignTools::AnimationCurve AnimationCurveEditorModel::createAnimationCurve(
|
|
||||||
const QmlTimelineKeyframeGroup &group)
|
|
||||||
{
|
|
||||||
switch (typeFrom(group)) {
|
|
||||||
case DesignTools::ValueType::Bool:
|
|
||||||
return createDoubleCurve(group);
|
|
||||||
|
|
||||||
case DesignTools::ValueType::Integer:
|
|
||||||
return createDoubleCurve(group);
|
|
||||||
|
|
||||||
case DesignTools::ValueType::Double:
|
|
||||||
return createDoubleCurve(group);
|
|
||||||
default:
|
|
||||||
return DesignTools::AnimationCurve();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
std::vector<DesignTools::Keyframe> createKeyframes(QList<ModelNode> nodes)
|
|
||||||
{
|
|
||||||
auto byTime = [](const auto &a, const auto &b) {
|
|
||||||
return a.variantProperty("frame").value().toDouble()
|
|
||||||
< b.variantProperty("frame").value().toDouble();
|
|
||||||
};
|
|
||||||
std::sort(nodes.begin(), nodes.end(), byTime);
|
|
||||||
|
|
||||||
std::vector<DesignTools::Keyframe> frames;
|
|
||||||
for (auto &&node : nodes) {
|
|
||||||
QVariant timeVariant = node.variantProperty("frame").value();
|
|
||||||
QVariant valueVariant = node.variantProperty("value").value();
|
|
||||||
if (!timeVariant.isValid() || !valueVariant.isValid())
|
|
||||||
continue;
|
|
||||||
|
|
||||||
QPointF position(timeVariant.toDouble(), valueVariant.toDouble());
|
|
||||||
|
|
||||||
auto keyframe = DesignTools::Keyframe(position);
|
|
||||||
|
|
||||||
if (node.hasBindingProperty("easing.bezierCurve")) {
|
|
||||||
EasingCurve ecurve;
|
|
||||||
ecurve.fromString(node.bindingProperty("easing.bezierCurve").expression());
|
|
||||||
keyframe.setData(static_cast<QEasingCurve>(ecurve));
|
|
||||||
}
|
|
||||||
frames.push_back(keyframe);
|
|
||||||
}
|
|
||||||
return frames;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::vector<DesignTools::Keyframe> resolveSmallCurves(
|
|
||||||
const std::vector<DesignTools::Keyframe> &frames)
|
|
||||||
{
|
|
||||||
std::vector<DesignTools::Keyframe> out;
|
|
||||||
for (auto &&frame : frames) {
|
|
||||||
if (frame.hasData() && !out.empty()) {
|
|
||||||
QEasingCurve curve = frame.data().toEasingCurve();
|
|
||||||
// One-segment-curve: Since (0,0) is implicit => 3
|
|
||||||
if (curve.toCubicSpline().count() == 3) {
|
|
||||||
DesignTools::Keyframe &previous = out.back();
|
|
||||||
#if 0
|
|
||||||
// Do not resolve when two adjacent keyframes have the same value.
|
|
||||||
if (qFuzzyCompare(previous.position().y(), frame.position().y())) {
|
|
||||||
out.push_back(frame);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
DesignTools::AnimationCurve acurve(curve, previous.position(), frame.position());
|
|
||||||
previous.setRightHandle(acurve.keyframeAt(0).rightHandle());
|
|
||||||
out.push_back(acurve.keyframeAt(1));
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
out.push_back(frame);
|
|
||||||
}
|
|
||||||
return out;
|
|
||||||
}
|
|
||||||
|
|
||||||
DesignTools::AnimationCurve AnimationCurveEditorModel::createDoubleCurve(
|
|
||||||
const QmlTimelineKeyframeGroup &group)
|
|
||||||
{
|
|
||||||
std::vector<DesignTools::Keyframe> keyframes = createKeyframes(group.keyframePositions());
|
|
||||||
keyframes = resolveSmallCurves(keyframes);
|
|
||||||
|
|
||||||
QString str;
|
|
||||||
ModelNode target = group.modelNode();
|
|
||||||
if (target.hasAuxiliaryData("unified"))
|
|
||||||
str = target.auxiliaryData("unified").toString();
|
|
||||||
|
|
||||||
if (str.size() == static_cast<int>(keyframes.size())) {
|
|
||||||
for (int i = 0; i < str.size(); ++i) {
|
|
||||||
if (str.at(i) == '1')
|
|
||||||
keyframes[i].setUnified(true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return DesignTools::AnimationCurve(keyframes);
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace QmlDesigner
|
|
||||||
@@ -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 "curveeditor/curveeditormodel.h"
|
|
||||||
#include "curveeditor/treeitem.h"
|
|
||||||
|
|
||||||
#include <qmltimelinekeyframegroup.h>
|
|
||||||
|
|
||||||
namespace QmlDesigner {
|
|
||||||
|
|
||||||
class AnimationCurveEditorModel : public DesignTools::CurveEditorModel
|
|
||||||
{
|
|
||||||
Q_OBJECT
|
|
||||||
|
|
||||||
public:
|
|
||||||
AnimationCurveEditorModel(double minTime, double maxTime);
|
|
||||||
|
|
||||||
~AnimationCurveEditorModel() override;
|
|
||||||
|
|
||||||
double minimumTime() const override;
|
|
||||||
|
|
||||||
double maximumTime() const override;
|
|
||||||
|
|
||||||
DesignTools::CurveEditorStyle style() const override;
|
|
||||||
|
|
||||||
void setTimeline(const QmlTimeline &timeline);
|
|
||||||
|
|
||||||
private:
|
|
||||||
DesignTools::TreeItem *createTopLevelItem(const QmlTimeline &timeline, const ModelNode &node);
|
|
||||||
|
|
||||||
DesignTools::AnimationCurve createAnimationCurve(const QmlTimelineKeyframeGroup &group);
|
|
||||||
|
|
||||||
DesignTools::AnimationCurve createDoubleCurve(const QmlTimelineKeyframeGroup &group);
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace QmlDesigner
|
|
||||||
@@ -36,9 +36,7 @@ SOURCES += \
|
|||||||
easingcurve.cpp \
|
easingcurve.cpp \
|
||||||
timelinesettingsmodel.cpp \
|
timelinesettingsmodel.cpp \
|
||||||
timelinetooldelegate.cpp \
|
timelinetooldelegate.cpp \
|
||||||
timelinecontrols.cpp \
|
timelinecontrols.cpp
|
||||||
animationcurveeditormodel.cpp \
|
|
||||||
animationcurvedialog.cpp
|
|
||||||
|
|
||||||
HEADERS += \
|
HEADERS += \
|
||||||
timelineview.h \
|
timelineview.h \
|
||||||
|
|||||||
@@ -103,36 +103,7 @@ static QAction *createAction(const Utils::Id &id,
|
|||||||
TimelineToolBar::TimelineToolBar(QWidget *parent)
|
TimelineToolBar::TimelineToolBar(QWidget *parent)
|
||||||
: QToolBar(parent)
|
: QToolBar(parent)
|
||||||
, m_grp()
|
, m_grp()
|
||||||
, m_dialog(new AnimationCurveDialog(this))
|
|
||||||
, m_curveModel(new AnimationCurveEditorModel(0., 500.))
|
|
||||||
{
|
{
|
||||||
m_dialog->setModel(m_curveModel);
|
|
||||||
connect(m_curveModel,
|
|
||||||
&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,
|
|
||||||
&TimelineToolBar::curveChanged);
|
|
||||||
|
|
||||||
setContentsMargins(0, 0, 0, 0);
|
setContentsMargins(0, 0, 0, 0);
|
||||||
createLeftControls();
|
createLeftControls();
|
||||||
createCenterControls();
|
createCenterControls();
|
||||||
@@ -143,8 +114,6 @@ void TimelineToolBar::reset()
|
|||||||
{
|
{
|
||||||
if (recording())
|
if (recording())
|
||||||
m_recording->setChecked(false);
|
m_recording->setChecked(false);
|
||||||
|
|
||||||
m_curveModel->reset({});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool TimelineToolBar::recording() const
|
bool TimelineToolBar::recording() const
|
||||||
@@ -189,7 +158,6 @@ void TimelineToolBar::setCurrentTimeline(const QmlTimeline &timeline)
|
|||||||
setStartFrame(timeline.startKeyframe());
|
setStartFrame(timeline.startKeyframe());
|
||||||
setEndFrame(timeline.endKeyframe());
|
setEndFrame(timeline.endKeyframe());
|
||||||
m_timelineLabel->setText(timeline.modelNode().id());
|
m_timelineLabel->setText(timeline.modelNode().id());
|
||||||
m_curveModel->setTimeline(timeline);
|
|
||||||
} else {
|
} else {
|
||||||
m_timelineLabel->setText("");
|
m_timelineLabel->setText("");
|
||||||
}
|
}
|
||||||
@@ -197,8 +165,6 @@ void TimelineToolBar::setCurrentTimeline(const QmlTimeline &timeline)
|
|||||||
|
|
||||||
void TimelineToolBar::setStartFrame(qreal frame)
|
void TimelineToolBar::setStartFrame(qreal frame)
|
||||||
{
|
{
|
||||||
m_curveModel->setMinimumTime(frame, true);
|
|
||||||
|
|
||||||
auto text = QString::number(frame, 'f', 0);
|
auto text = QString::number(frame, 'f', 0);
|
||||||
m_firstFrame->setText(text);
|
m_firstFrame->setText(text);
|
||||||
setupCurrentFrameValidator();
|
setupCurrentFrameValidator();
|
||||||
@@ -206,16 +172,12 @@ void TimelineToolBar::setStartFrame(qreal frame)
|
|||||||
|
|
||||||
void TimelineToolBar::setCurrentFrame(qreal frame)
|
void TimelineToolBar::setCurrentFrame(qreal frame)
|
||||||
{
|
{
|
||||||
m_curveModel->setCurrentFrame(std::round(frame));
|
|
||||||
|
|
||||||
auto text = QString::number(frame, 'f', 0);
|
auto text = QString::number(frame, 'f', 0);
|
||||||
m_currentFrame->setText(text);
|
m_currentFrame->setText(text);
|
||||||
}
|
}
|
||||||
|
|
||||||
void TimelineToolBar::setEndFrame(qreal frame)
|
void TimelineToolBar::setEndFrame(qreal frame)
|
||||||
{
|
{
|
||||||
m_curveModel->setMaximumTime(frame, true);
|
|
||||||
|
|
||||||
auto text = QString::number(frame, 'f', 0);
|
auto text = QString::number(frame, 'f', 0);
|
||||||
m_lastFrame->setText(text);
|
m_lastFrame->setText(text);
|
||||||
setupCurrentFrameValidator();
|
setupCurrentFrameValidator();
|
||||||
@@ -240,19 +202,6 @@ void TimelineToolBar::removeTimeline(const QmlTimeline &timeline)
|
|||||||
setCurrentTimeline(QmlTimeline());
|
setCurrentTimeline(QmlTimeline());
|
||||||
}
|
}
|
||||||
|
|
||||||
void TimelineToolBar::openAnimationCurveEditor()
|
|
||||||
{
|
|
||||||
QmlTimeline timeline;
|
|
||||||
if (auto *tlw = qobject_cast<TimelineWidget *>(parent())) {
|
|
||||||
if (auto *tlv = tlw->timelineView())
|
|
||||||
timeline = tlv->timelineForState(tlv->currentState());
|
|
||||||
}
|
|
||||||
|
|
||||||
m_dialog->refresh();
|
|
||||||
m_curveModel->setTimeline(timeline);
|
|
||||||
m_dialog->show();
|
|
||||||
}
|
|
||||||
|
|
||||||
void TimelineToolBar::createLeftControls()
|
void TimelineToolBar::createLeftControls()
|
||||||
{
|
{
|
||||||
auto addActionToGroup = [&](QAction *action) {
|
auto addActionToGroup = [&](QAction *action) {
|
||||||
@@ -282,17 +231,6 @@ void TimelineToolBar::createLeftControls()
|
|||||||
connect(settingsAction, &QAction::triggered, this, &TimelineToolBar::settingDialogClicked);
|
connect(settingsAction, &QAction::triggered, this, &TimelineToolBar::settingDialogClicked);
|
||||||
addActionToGroup(settingsAction);
|
addActionToGroup(settingsAction);
|
||||||
|
|
||||||
auto *curveEditorAction = createAction(TimelineConstants::C_CURVE_EDITOR,
|
|
||||||
TimelineIcons::CURVE_EDITORDIALOG.icon(),
|
|
||||||
tr("Animation Curve Editor"),
|
|
||||||
QKeySequence(Qt::Key_C));
|
|
||||||
|
|
||||||
connect(curveEditorAction,
|
|
||||||
&QAction::triggered,
|
|
||||||
this,
|
|
||||||
&TimelineToolBar::openAnimationCurveEditor);
|
|
||||||
addActionToGroup(curveEditorAction);
|
|
||||||
|
|
||||||
addWidgetToGroup(createSpacer());
|
addWidgetToGroup(createSpacer());
|
||||||
|
|
||||||
m_timelineLabel = new QLabel(this);
|
m_timelineLabel = new QLabel(this);
|
||||||
|
|||||||
@@ -25,9 +25,6 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "animationcurvedialog.h"
|
|
||||||
#include "animationcurveeditormodel.h"
|
|
||||||
|
|
||||||
#include <QToolBar>
|
#include <QToolBar>
|
||||||
|
|
||||||
QT_FORWARD_DECLARE_CLASS(QLabel)
|
QT_FORWARD_DECLARE_CLASS(QLabel)
|
||||||
@@ -67,8 +64,6 @@ signals:
|
|||||||
void currentFrameChanged(int value);
|
void currentFrameChanged(int value);
|
||||||
void endFrameChanged(int value);
|
void endFrameChanged(int value);
|
||||||
|
|
||||||
void curveChanged(DesignTools::PropertyTreeItem *item);
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit TimelineToolBar(QWidget *parent = nullptr);
|
explicit TimelineToolBar(QWidget *parent = nullptr);
|
||||||
|
|
||||||
@@ -89,8 +84,6 @@ public:
|
|||||||
void setActionEnabled(const QString &name, bool enabled);
|
void setActionEnabled(const QString &name, bool enabled);
|
||||||
void removeTimeline(const QmlTimeline &timeline);
|
void removeTimeline(const QmlTimeline &timeline);
|
||||||
|
|
||||||
void openAnimationCurveEditor();
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void resizeEvent(QResizeEvent *event) override;
|
void resizeEvent(QResizeEvent *event) override;
|
||||||
|
|
||||||
@@ -103,10 +96,6 @@ private:
|
|||||||
|
|
||||||
QList<QObject *> m_grp;
|
QList<QObject *> m_grp;
|
||||||
|
|
||||||
AnimationCurveDialog *m_dialog = nullptr;
|
|
||||||
|
|
||||||
AnimationCurveEditorModel *m_curveModel = nullptr;
|
|
||||||
|
|
||||||
QLabel *m_timelineLabel = nullptr;
|
QLabel *m_timelineLabel = nullptr;
|
||||||
QLabel *m_stateLabel = nullptr;
|
QLabel *m_stateLabel = nullptr;
|
||||||
QSlider *m_scale = nullptr;
|
QSlider *m_scale = nullptr;
|
||||||
|
|||||||
@@ -25,8 +25,6 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "animationcurvedialog.h"
|
|
||||||
#include "animationcurveeditormodel.h"
|
|
||||||
#include "treeitem.h"
|
#include "treeitem.h"
|
||||||
|
|
||||||
#include <abstractview.h>
|
#include <abstractview.h>
|
||||||
|
|||||||
@@ -258,8 +258,6 @@ void TimelineWidget::connectToolbar()
|
|||||||
|
|
||||||
connect(graphicsScene(), &TimelineGraphicsScene::scroll, this, &TimelineWidget::scroll);
|
connect(graphicsScene(), &TimelineGraphicsScene::scroll, this, &TimelineWidget::scroll);
|
||||||
|
|
||||||
connect(m_toolbar, &TimelineToolBar::curveChanged, this, &TimelineWidget::updateAnimationCurve);
|
|
||||||
|
|
||||||
auto setRulerScaling = [this](int val) { m_graphicsScene->setRulerScaling(val); };
|
auto setRulerScaling = [this](int val) { m_graphicsScene->setRulerScaling(val); };
|
||||||
connect(m_toolbar, &TimelineToolBar::scaleFactorChanged, setRulerScaling);
|
connect(m_toolbar, &TimelineToolBar::scaleFactorChanged, setRulerScaling);
|
||||||
|
|
||||||
@@ -372,66 +370,6 @@ void attachEasingCurve(double frame,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void TimelineWidget::updateAnimationCurve(DesignTools::PropertyTreeItem *item)
|
|
||||||
{
|
|
||||||
QmlTimeline currentTimeline = graphicsScene()->currentTimeline();
|
|
||||||
QmlTimelineKeyframeGroup group = timelineKeyframeGroup(currentTimeline, item);
|
|
||||||
|
|
||||||
if (group.isValid()) {
|
|
||||||
ModelNode groupNode = group.modelNode();
|
|
||||||
|
|
||||||
if (groupNode.isValid()) {
|
|
||||||
if (item->locked())
|
|
||||||
groupNode.setAuxiliaryData("locked", true);
|
|
||||||
else
|
|
||||||
groupNode.removeAuxiliaryData("locked");
|
|
||||||
|
|
||||||
if (item->pinned())
|
|
||||||
groupNode.setAuxiliaryData("pinned", true);
|
|
||||||
else
|
|
||||||
groupNode.removeAuxiliaryData("pinned");
|
|
||||||
|
|
||||||
if (item->hasUnified())
|
|
||||||
groupNode.setAuxiliaryData("unified", item->unifyString());
|
|
||||||
else
|
|
||||||
groupNode.removeAuxiliaryData("unified");
|
|
||||||
}
|
|
||||||
|
|
||||||
auto replaceKeyframes = [&group, item, this]() {
|
|
||||||
m_toolbar->setBlockReflection(true);
|
|
||||||
for (auto frame : group.keyframes())
|
|
||||||
frame.destroy();
|
|
||||||
|
|
||||||
DesignTools::Keyframe previous;
|
|
||||||
for (auto &&frame : item->curve().keyframes()) {
|
|
||||||
QPointF pos = frame.position();
|
|
||||||
group.setValue(QVariant(pos.y()), pos.x());
|
|
||||||
|
|
||||||
if (previous.isValid()) {
|
|
||||||
if (frame.interpolation() == DesignTools::Keyframe::Interpolation::Bezier) {
|
|
||||||
DesignTools::CurveSegment segment(previous, frame);
|
|
||||||
if (segment.isValid())
|
|
||||||
attachEasingCurve(pos.x(), segment.easingCurve(), group);
|
|
||||||
} else if (frame.interpolation()
|
|
||||||
== DesignTools::Keyframe::Interpolation::Easing) {
|
|
||||||
QVariant data = frame.data();
|
|
||||||
if (data.type() == static_cast<int>(QMetaType::QEasingCurve))
|
|
||||||
attachEasingCurve(pos.x(), data.value<QEasingCurve>(), group);
|
|
||||||
} else if (frame.interpolation() == DesignTools::Keyframe::Interpolation::Step) {
|
|
||||||
// Warning: Keyframe::Interpolation::Step not yet implemented
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
previous = frame;
|
|
||||||
}
|
|
||||||
m_toolbar->setBlockReflection(false);
|
|
||||||
};
|
|
||||||
|
|
||||||
timelineView()->executeInTransaction("TimelineWidget::handleKeyframeReplacement",
|
|
||||||
replaceKeyframes);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void TimelineWidget::selectionChanged()
|
void TimelineWidget::selectionChanged()
|
||||||
{
|
{
|
||||||
if (graphicsScene()->hasSelection())
|
if (graphicsScene()->hasSelection())
|
||||||
|
|||||||
@@ -25,7 +25,6 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "animationcurveeditormodel.h"
|
|
||||||
#include "timelineutils.h"
|
#include "timelineutils.h"
|
||||||
#include <coreplugin/icontext.h>
|
#include <coreplugin/icontext.h>
|
||||||
|
|
||||||
@@ -79,8 +78,6 @@ public slots:
|
|||||||
void changeScaleFactor(int factor);
|
void changeScaleFactor(int factor);
|
||||||
void scroll(const TimelineUtils::Side &side);
|
void scroll(const TimelineUtils::Side &side);
|
||||||
|
|
||||||
void updateAnimationCurve(DesignTools::PropertyTreeItem *item);
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void showEvent(QShowEvent *event) override;
|
void showEvent(QShowEvent *event) override;
|
||||||
void resizeEvent(QResizeEvent *event) override;
|
void resizeEvent(QResizeEvent *event) override;
|
||||||
|
|||||||
@@ -125,11 +125,6 @@ QString TransitionEditorToolBar::currentTransitionId() const
|
|||||||
return m_transitionComboBox->currentText();
|
return m_transitionComboBox->currentText();
|
||||||
}
|
}
|
||||||
|
|
||||||
void TransitionEditorToolBar::setBlockReflection(bool block)
|
|
||||||
{
|
|
||||||
m_blockReflection = block;
|
|
||||||
}
|
|
||||||
|
|
||||||
void TransitionEditorToolBar::updateComboBox(const ModelNode &root)
|
void TransitionEditorToolBar::updateComboBox(const ModelNode &root)
|
||||||
{
|
{
|
||||||
if (root.isValid() && root.hasProperty("transitions")) {
|
if (root.isValid() && root.hasProperty("transitions")) {
|
||||||
@@ -142,9 +137,6 @@ void TransitionEditorToolBar::updateComboBox(const ModelNode &root)
|
|||||||
|
|
||||||
void TransitionEditorToolBar::setCurrentTransition(const ModelNode &transition)
|
void TransitionEditorToolBar::setCurrentTransition(const ModelNode &transition)
|
||||||
{
|
{
|
||||||
if (m_blockReflection)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (transition.isValid()) {
|
if (transition.isValid()) {
|
||||||
m_transitionComboBox->clear();
|
m_transitionComboBox->clear();
|
||||||
const ModelNode root = transition.view()->rootModelNode();
|
const ModelNode root = transition.view()->rootModelNode();
|
||||||
|
|||||||
@@ -25,9 +25,7 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "animationcurvedialog.h"
|
#include <modelnode.h>
|
||||||
#include "animationcurveeditormodel.h"
|
|
||||||
|
|
||||||
#include <QToolBar>
|
#include <QToolBar>
|
||||||
|
|
||||||
QT_FORWARD_DECLARE_CLASS(QComboBox)
|
QT_FORWARD_DECLARE_CLASS(QComboBox)
|
||||||
@@ -85,8 +83,6 @@ private:
|
|||||||
QComboBox *m_transitionComboBox = nullptr;
|
QComboBox *m_transitionComboBox = nullptr;
|
||||||
QSlider *m_scale = nullptr;
|
QSlider *m_scale = nullptr;
|
||||||
QLineEdit *m_duration = nullptr;
|
QLineEdit *m_duration = nullptr;
|
||||||
|
|
||||||
bool m_blockReflection = false;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace QmlDesigner
|
} // namespace QmlDesigner
|
||||||
|
|||||||
@@ -25,10 +25,6 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "animationcurvedialog.h"
|
|
||||||
#include "animationcurveeditormodel.h"
|
|
||||||
#include "treeitem.h"
|
|
||||||
|
|
||||||
#include <abstractview.h>
|
#include <abstractview.h>
|
||||||
|
|
||||||
#include <QPointer>
|
#include <QPointer>
|
||||||
|
|||||||
@@ -38,6 +38,7 @@
|
|||||||
#include <sourcetool/sourcetool.h>
|
#include <sourcetool/sourcetool.h>
|
||||||
#include <colortool/colortool.h>
|
#include <colortool/colortool.h>
|
||||||
#include <annotationeditor/annotationtool.h>
|
#include <annotationeditor/annotationtool.h>
|
||||||
|
#include <curveeditor/curveeditorview.h>
|
||||||
#include <formeditor/transitiontool.h>
|
#include <formeditor/transitiontool.h>
|
||||||
#include <texttool/texttool.h>
|
#include <texttool/texttool.h>
|
||||||
#include <timelineeditor/timelineview.h>
|
#include <timelineeditor/timelineview.h>
|
||||||
@@ -238,6 +239,9 @@ bool QmlDesignerPlugin::delayedInitialize()
|
|||||||
auto timelineView = new QmlDesigner::TimelineView;
|
auto timelineView = new QmlDesigner::TimelineView;
|
||||||
d->viewManager.registerViewTakingOwnership(timelineView);
|
d->viewManager.registerViewTakingOwnership(timelineView);
|
||||||
timelineView->registerActions();
|
timelineView->registerActions();
|
||||||
|
|
||||||
|
auto curveEditorView = new QmlDesigner::CurveEditorView;
|
||||||
|
d->viewManager.registerViewTakingOwnership(curveEditorView);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto transitionEditorView = new QmlDesigner::TransitionEditorView;
|
auto transitionEditorView = new QmlDesigner::TransitionEditorView;
|
||||||
|
|||||||
@@ -721,6 +721,8 @@ Project {
|
|||||||
"connectioneditor/dynamicpropertiesmodel.cpp",
|
"connectioneditor/dynamicpropertiesmodel.cpp",
|
||||||
"connectioneditor/dynamicpropertiesmodel.h",
|
"connectioneditor/dynamicpropertiesmodel.h",
|
||||||
"connectioneditor/stylesheet.css",
|
"connectioneditor/stylesheet.css",
|
||||||
|
"curveeditor/curveeditorview.cpp",
|
||||||
|
"curveeditor/curveeditorview.h",
|
||||||
"curveeditor/animationcurve.cpp",
|
"curveeditor/animationcurve.cpp",
|
||||||
"curveeditor/animationcurve.h",
|
"curveeditor/animationcurve.h",
|
||||||
"curveeditor/curveeditor.cpp",
|
"curveeditor/curveeditor.cpp",
|
||||||
@@ -796,10 +798,6 @@ Project {
|
|||||||
"texttool/textedititemwidget.h",
|
"texttool/textedititemwidget.h",
|
||||||
"texttool/texttool.cpp",
|
"texttool/texttool.cpp",
|
||||||
"texttool/texttool.h",
|
"texttool/texttool.h",
|
||||||
"timelineeditor/animationcurvedialog.cpp",
|
|
||||||
"timelineeditor/animationcurvedialog.h",
|
|
||||||
"timelineeditor/animationcurveeditormodel.cpp",
|
|
||||||
"timelineeditor/animationcurveeditormodel.h",
|
|
||||||
"timelineeditor/canvas.cpp",
|
"timelineeditor/canvas.cpp",
|
||||||
"timelineeditor/canvas.h",
|
"timelineeditor/canvas.h",
|
||||||
"timelineeditor/canvasstyledialog.cpp",
|
"timelineeditor/canvasstyledialog.cpp",
|
||||||
|
|||||||
Reference in New Issue
Block a user