From e4429401d51d0476fb5361f88245d43424f9702f Mon Sep 17 00:00:00 2001 From: Miikka Heikkinen Date: Thu, 21 Mar 2024 15:14:57 +0200 Subject: [PATCH] EffectComposer: Add extraMargin property for generated effects Extra margin property is added to effects that can spill outside the source item. This property specifies the amount of space outside the item that the effect is allowed to use for rendering. Fixes: QDS-11607 Change-Id: I36d7392593faa6deb99726eaa02184aa87aa3571 Reviewed-by: Mahmoud Badri Reviewed-by: Qt CI Patch Build Bot --- .../EffectComposerPreview.qml | 7 +- .../effectcomposer/compositionnode.cpp | 3 + src/plugins/effectcomposer/compositionnode.h | 3 + .../effectcomposer/effectcomposermodel.cpp | 94 +++++++++++++++++-- .../effectcomposer/effectcomposermodel.h | 2 + 5 files changed, 99 insertions(+), 10 deletions(-) diff --git a/share/qtcreator/qmldesigner/effectComposerQmlSources/EffectComposerPreview.qml b/share/qtcreator/qmldesigner/effectComposerQmlSources/EffectComposerPreview.qml index c832b2f3708..aefffcc6bcc 100644 --- a/share/qtcreator/qmldesigner/effectComposerQmlSources/EffectComposerPreview.qml +++ b/share/qtcreator/qmldesigner/effectComposerQmlSources/EffectComposerPreview.qml @@ -21,6 +21,7 @@ Column { readonly property int updateDelay: 100 readonly property int previewMargin: 5 + readonly property int extraMargin: 200 property real previewScale: 1 @@ -246,6 +247,8 @@ Column { layer.enabled: true layer.mipmap: true layer.smooth: true + layer.sourceRect: Qt.rect(-root.extraMargin, -root.extraMargin, + width + root.extraMargin * 2, height + root.extraMargin * 2) visible: false Image { @@ -347,10 +350,6 @@ Column { width: source.width height: source.height anchors.centerIn: parent - // Cache the layer. This way heavy shaders rendering doesn't - // slow down code editing & rest of the UI. - layer.enabled: true - layer.smooth: true } } diff --git a/src/plugins/effectcomposer/compositionnode.cpp b/src/plugins/effectcomposer/compositionnode.cpp index 108eb5801d8..d939e2283af 100644 --- a/src/plugins/effectcomposer/compositionnode.cpp +++ b/src/plugins/effectcomposer/compositionnode.cpp @@ -113,6 +113,9 @@ void CompositionNode::parse(const QString &effectName, const QString &qenPath, c m_fragmentCode = EffectUtils::codeFromJsonArray(json.value("fragmentCode").toArray()); m_vertexCode = EffectUtils::codeFromJsonArray(json.value("vertexCode").toArray()); + if (json.contains("extraMargin")) + m_extraMargin = json.value("extraMargin").toInt(); + if (json.contains("enabled")) m_isEnabled = json["enabled"].toBool(); diff --git a/src/plugins/effectcomposer/compositionnode.h b/src/plugins/effectcomposer/compositionnode.h index b3348bb38fc..433468688a2 100644 --- a/src/plugins/effectcomposer/compositionnode.h +++ b/src/plugins/effectcomposer/compositionnode.h @@ -52,6 +52,8 @@ public: int decRefCount(); void setRefCount(int count); + int extraMargin() const { return m_extraMargin; } + signals: void uniformsModelChanged(); void isEnabledChanged(); @@ -70,6 +72,7 @@ private: QString m_id; bool m_isEnabled = true; int m_refCount = 0; + int m_extraMargin = 0; QList m_uniforms; diff --git a/src/plugins/effectcomposer/effectcomposermodel.cpp b/src/plugins/effectcomposer/effectcomposermodel.cpp index 092df2b3e4a..394b85aa552 100644 --- a/src/plugins/effectcomposer/effectcomposermodel.cpp +++ b/src/plugins/effectcomposer/effectcomposermodel.cpp @@ -490,6 +490,8 @@ QJsonObject nodeToJson(const CompositionNode &node) nodeObject.insert("enabled", node.isEnabled()); nodeObject.insert("version", 1); nodeObject.insert("id", node.id()); + if (node.extraMargin()) + nodeObject.insert("extraMargin", node.extraMargin()); // Add properties QJsonArray propertiesArray; @@ -676,10 +678,44 @@ R"( )"; s += frameProp.arg(tr("Frame"), tr("This property allows explicit control of current animation frame.")); } + s += " }\n"; s += " }\n"; } + if (m_shaderFeatures.enabled(ShaderFeatures::Source) && m_extraMargin) { + QString generalSection = + R"( + Section { + caption: "%1" + width: parent.width + + SectionLayout { + PropertyLabel { + text: "%2" + tooltip: "%3" + } + + SecondColumnLayout { + SpinBox { + minimumValue: 0 + maximumValue: 1000 + decimals: 0 + stepSize: 1 + sliderIndicatorVisible: true + backendValue: backendValues.extraMargin + implicitWidth: StudioTheme.Values.singleControlColumnWidth + + StudioTheme.Values.actionIndicatorWidth + } + ExpandingSpacer {} + } + } + } +)"; + s += generalSection.arg(tr("General"), tr("Extra Margin"), + tr("This property specifies how much of extra space is reserved for the effect outside the parent geometry.")); + } + for (const auto &node : std::as_const(m_nodes)) { const QList uniforms = static_cast( node->uniformsModel())->uniforms(); @@ -739,8 +775,34 @@ Item { s += header; if (m_shaderFeatures.enabled(ShaderFeatures::Source)) { - s += " // This is the main source for the effect. Set internally to the current parent item. Do not modify.\n"; - s += " property Item source: null\n"; + QString sourceStr{ +R"( + // This is the main source for the effect. Set internally to the current parent item. Do not modify. + property Item source: null +)" + }; + + QString extraMarginStr{ +R"( + // This property specifies how much of extra space is reserved for the effect outside the parent geometry. + // It should be sufficient for most use cases but if the application uses extreme values it may be necessary to + // increase this value. + property int extraMargin: %1 + + onExtraMarginChanged: setupSourceRect() + + function setupSourceRect() { + if (rootItem.source) { + var width = source.width + extraMargin * 2 + var height = source.height + extraMargin * 2 + source.layer.sourceRect = Qt.rect(-extraMargin, -extraMargin, width, height) + } + } +)" + }; + s += sourceStr; + if (m_extraMargin) + s += extraMarginStr.arg(m_extraMargin); } if (m_shaderFeatures.enabled(ShaderFeatures::Time) || m_shaderFeatures.enabled(ShaderFeatures::Frame)) { @@ -773,6 +835,7 @@ R"( parent.layer.effect = effectComponent } %1 + %3 } } @@ -781,6 +844,7 @@ R"( parent.layer.enabled = true parent.layer.effect = effectComponent source = parent + %3 } else { parent.layer.enabled = false parent.layer.effect = null @@ -805,10 +869,13 @@ R"( parentChanged = parentChanged.arg(mipmap1, mipmap2); } - parentChanged = parentChanged.arg(m_shaderFeatures.enabled(ShaderFeatures::Source) - ? QString("source = parent") : QString(), - m_shaderFeatures.enabled(ShaderFeatures::Source) - ? QString("source = null") : QString()); + if (m_shaderFeatures.enabled(ShaderFeatures::Source)) { + parentChanged = parentChanged.arg(QString("source = parent"), + QString("source = null"), + m_extraMargin ? QString("setupSourceRect()") : QString()); + } else { + parentChanged = parentChanged.arg(QString(), QString(), QString()); + } s += parentChanged; // Custom properties @@ -854,6 +921,8 @@ void EffectComposerModel::saveComposition(const QString &name) return; } + updateExtraMargin(); + QJsonObject json; // File format version json.insert("version", 1); @@ -1844,6 +1913,12 @@ QString EffectComposerModel::getQmlComponentString(bool localFiles) s += l2 + "vertexShader: 'file:///" + vertFile + "'\n"; s += l2 + "fragmentShader: 'file:///" + fragFile + "'\n"; s += l2 + "anchors.fill: " + (localFiles ? "rootItem.source" : "parent") + "\n"; + if (localFiles) { + if (m_extraMargin) + s += l2 + "anchors.margins: -rootItem.extraMargin\n"; + } else { + s += l2 + "anchors.margins: -root.extraMargin\n"; + } if (m_shaderFeatures.enabled(ShaderFeatures::GridMesh)) { QString gridSize = QString("%1, %2").arg(m_shaderFeatures.gridMeshWidth()) .arg(m_shaderFeatures.gridMeshHeight()); @@ -1879,6 +1954,13 @@ void EffectComposerModel::connectCompositionNode(CompositionNode *node) }); } +void EffectComposerModel::updateExtraMargin() +{ + m_extraMargin = 0; + for (CompositionNode *node : std::as_const(m_nodes)) + m_extraMargin = qMax(node->extraMargin(), m_extraMargin); +} + QString EffectComposerModel::currentComposition() const { return m_currentComposition; diff --git a/src/plugins/effectcomposer/effectcomposermodel.h b/src/plugins/effectcomposer/effectcomposermodel.h index 3dca41abf9e..e92213d12a5 100644 --- a/src/plugins/effectcomposer/effectcomposermodel.h +++ b/src/plugins/effectcomposer/effectcomposermodel.h @@ -181,6 +181,7 @@ private: QString getDesignerSpecifics() const; void connectCompositionNode(CompositionNode *node); + void updateExtraMargin(); QList m_nodes; @@ -218,6 +219,7 @@ private: bool m_hasValidTarget = false; QString m_currentComposition; QTimer m_rebakeTimer; + int m_extraMargin = 0; const QRegularExpression m_spaceReg = QRegularExpression("\\s+"); };