aboutsummaryrefslogtreecommitdiffstats
path: root/src/quickcontrols/material/impl/qquickmaterialripple.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/quickcontrols/material/impl/qquickmaterialripple.cpp')
-rw-r--r--src/quickcontrols/material/impl/qquickmaterialripple.cpp86
1 files changed, 63 insertions, 23 deletions
diff --git a/src/quickcontrols/material/impl/qquickmaterialripple.cpp b/src/quickcontrols/material/impl/qquickmaterialripple.cpp
index 0379d41e43..647e4ccbe3 100644
--- a/src/quickcontrols/material/impl/qquickmaterialripple.cpp
+++ b/src/quickcontrols/material/impl/qquickmaterialripple.cpp
@@ -30,12 +30,19 @@ public:
void sync(QQuickItem *item) override;
private:
+ void updateWaveNode();
+
qreal m_from = 0;
qreal m_to = 0;
qreal m_value = 0;
+ qreal m_newValue = 0;
+
WavePhase m_phase = WaveEnter;
QPointF m_anchor;
QRectF m_bounds;
+
+ qreal m_opacity = -1.0;
+ qreal m_newOpacity = 1.0;
};
QQuickMaterialRippleWaveNode::QQuickMaterialRippleWaveNode(QQuickMaterialRipple *ripple)
@@ -50,6 +57,9 @@ QQuickMaterialRippleWaveNode::QQuickMaterialRippleWaveNode(QQuickMaterialRipple
QSGInternalRectangleNode *rectNode = d->sceneGraphContext()->createInternalRectangleNode();
rectNode->setAntialiasing(true);
opacityNode->appendChildNode(rectNode);
+
+ auto window = ripple->window();
+ connect(window, &QQuickWindow::beforeFrameBegin, this, &QQuickMaterialRippleWaveNode::updateWaveNode, Qt::DirectConnection);
}
void QQuickMaterialRippleWaveNode::exit()
@@ -67,29 +77,10 @@ void QQuickMaterialRippleWaveNode::updateCurrentTime(int time)
if (duration() > 0)
p = time / static_cast<qreal>(duration());
- m_value = m_from + (m_to - m_from) * p;
- p = m_value / m_to;
-
- const qreal dx = (1.0 - p) * (m_anchor.x() - m_bounds.width() / 2);
- const qreal dy = (1.0 - p) * (m_anchor.y() - m_bounds.height() / 2);
-
- QMatrix4x4 m;
- m.translate(qRound((m_bounds.width() - m_value) / 2 + dx),
- qRound((m_bounds.height() - m_value) / 2 + dy));
- setMatrix(m);
+ m_newValue = m_from + (m_to - m_from) * p;
- QSGOpacityNode *opacityNode = static_cast<QSGOpacityNode *>(firstChild());
- Q_ASSERT(opacityNode->type() == QSGNode::OpacityNodeType);
- qreal opacity = 1.0;
if (m_phase == WaveExit)
- opacity -= static_cast<qreal>(time) / WAVE_OPACITY_DECAY_DURATION;
- opacityNode->setOpacity(opacity);
-
- QSGInternalRectangleNode *rectNode = static_cast<QSGInternalRectangleNode *>(opacityNode->firstChild());
- Q_ASSERT(rectNode->type() == QSGNode::GeometryNodeType);
- rectNode->setRect(QRectF(0, 0, m_value, m_value));
- rectNode->setRadius(m_value / 2);
- rectNode->update();
+ m_newOpacity = 1.0 - static_cast<qreal>(time) / WAVE_OPACITY_DECAY_DURATION;
}
void QQuickMaterialRippleWaveNode::sync(QQuickItem *item)
@@ -107,6 +98,37 @@ void QQuickMaterialRippleWaveNode::sync(QQuickItem *item)
rectNode->setColor(ripple->color());
}
+void QQuickMaterialRippleWaveNode::updateWaveNode()
+{
+ QSGOpacityNode *opacityNode = static_cast<QSGOpacityNode *>(firstChild());
+ Q_ASSERT(opacityNode->type() == QSGNode::OpacityNodeType);
+ if (!qFuzzyCompare(m_opacity, m_newOpacity)) {
+ m_opacity = m_newOpacity;
+ opacityNode->setOpacity(m_opacity);
+ }
+
+ if (qFuzzyCompare(m_value, m_newValue))
+ return;
+
+ m_value = m_newValue;
+
+ qreal p = m_value / m_to;
+
+ const qreal dx = (1.0 - p) * (m_anchor.x() - m_bounds.width() / 2);
+ const qreal dy = (1.0 - p) * (m_anchor.y() - m_bounds.height() / 2);
+
+ QMatrix4x4 m;
+ m.translate(qRound((m_bounds.width() - m_value) / 2 + dx),
+ qRound((m_bounds.height() - m_value) / 2 + dy));
+ setMatrix(m);
+
+ QSGInternalRectangleNode *rectNode = static_cast<QSGInternalRectangleNode *>(opacityNode->firstChild());
+ Q_ASSERT(rectNode->type() == QSGNode::GeometryNodeType);
+ rectNode->setRect(QRectF(0, 0, m_value, m_value));
+ rectNode->setRadius(m_value / 2);
+ rectNode->update();
+}
+
class QQuickMaterialRippleBackgroundNode : public QQuickAnimatedNode
{
Q_OBJECT
@@ -118,7 +140,12 @@ public:
void sync(QQuickItem *item) override;
private:
+ void updateBackgroundNode();
+
bool m_active = false;
+
+ qreal m_opacity = -1.0;
+ qreal m_newOpacity = 0.0;
};
QQuickMaterialRippleBackgroundNode::QQuickMaterialRippleBackgroundNode(QQuickMaterialRipple *ripple)
@@ -127,13 +154,15 @@ QQuickMaterialRippleBackgroundNode::QQuickMaterialRippleBackgroundNode(QQuickMat
setDuration(OPACITY_ENTER_DURATION_FAST);
QSGOpacityNode *opacityNode = new QSGOpacityNode;
- opacityNode->setOpacity(0.0);
appendChildNode(opacityNode);
QQuickItemPrivate *d = QQuickItemPrivate::get(ripple);
QSGInternalRectangleNode *rectNode = d->sceneGraphContext()->createInternalRectangleNode();
rectNode->setAntialiasing(true);
opacityNode->appendChildNode(rectNode);
+
+ auto window = ripple->window();
+ connect(window, &QQuickWindow::beforeFrameBegin, this, &QQuickMaterialRippleBackgroundNode::updateBackgroundNode, Qt::DirectConnection);
}
void QQuickMaterialRippleBackgroundNode::updateCurrentTime(int time)
@@ -144,7 +173,7 @@ void QQuickMaterialRippleBackgroundNode::updateCurrentTime(int time)
QSGOpacityNode *opacityNode = static_cast<QSGOpacityNode *>(firstChild());
Q_ASSERT(opacityNode->type() == QSGNode::OpacityNodeType);
- opacityNode->setOpacity(opacity);
+ m_newOpacity = opacity;
}
void QQuickMaterialRippleBackgroundNode::sync(QQuickItem *item)
@@ -181,6 +210,17 @@ void QQuickMaterialRippleBackgroundNode::sync(QQuickItem *item)
rectNode->update();
}
+void QQuickMaterialRippleBackgroundNode::updateBackgroundNode()
+{
+ if (m_opacity == m_newOpacity)
+ return;
+
+ m_opacity = m_newOpacity;
+ QSGOpacityNode *opacityNode = static_cast<QSGOpacityNode *>(firstChild());
+ Q_ASSERT(opacityNode->type() == QSGNode::OpacityNodeType);
+ opacityNode->setOpacity(m_opacity);
+}
+
QQuickMaterialRipple::QQuickMaterialRipple(QQuickItem *parent)
: QQuickItem(parent)
{