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 <mahmoud.badri@qt.io>
Reviewed-by: Qt CI Patch Build Bot <ci_patchbuild_bot@qt.io>
This commit is contained in:
Miikka Heikkinen
2024-03-21 15:14:57 +02:00
parent 5f055fed2d
commit e4429401d5
5 changed files with 99 additions and 10 deletions

View File

@@ -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
}
}

View File

@@ -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();

View File

@@ -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<Uniform *> m_uniforms;

View File

@@ -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<Uniform *> uniforms = static_cast<EffectComposerUniformsModel *>(
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;

View File

@@ -181,6 +181,7 @@ private:
QString getDesignerSpecifics() const;
void connectCompositionNode(CompositionNode *node);
void updateExtraMargin();
QList<CompositionNode *> 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+");
};