From 93ba99f019cbe4e4eba1858a501b38060a651ea3 Mon Sep 17 00:00:00 2001 From: Amr Essam Date: Mon, 9 Oct 2023 13:46:08 +0300 Subject: [PATCH] QmlDesigner: Prepare the process to compile shaders externally Also added customValue for Uniform Task-number: QDS-10811 Change-Id: Ie47ad41d0c80da149bdab9cae542297d59abcee6 Reviewed-by: Miikka Heikkinen --- .../EffectMakerPreview.qml | 51 +++++++++---------- src/plugins/effectmakernew/CMakeLists.txt | 2 +- .../effectmakernew/effectmakermodel.cpp | 30 ++++++++++- src/plugins/effectmakernew/effectmakermodel.h | 18 +++++-- .../effectmakernew/effectmakerwidget.cpp | 2 + src/plugins/effectmakernew/uniform.cpp | 3 ++ 6 files changed, 73 insertions(+), 33 deletions(-) diff --git a/share/qtcreator/qmldesigner/effectMakerQmlSources/EffectMakerPreview.qml b/share/qtcreator/qmldesigner/effectMakerQmlSources/EffectMakerPreview.qml index c23e95e5628..c6ffe83a168 100644 --- a/share/qtcreator/qmldesigner/effectMakerQmlSources/EffectMakerPreview.qml +++ b/share/qtcreator/qmldesigner/effectMakerQmlSources/EffectMakerPreview.qml @@ -20,6 +20,31 @@ Column { // The delay in ms to wait until updating the effect readonly property int updateDelay: 200 + // Create a dummy parent to host the effect qml object + function createNewComponent() { + var oldComponent = componentParent.children[0]; + if (oldComponent) + oldComponent.destroy(); + try { + const newObject = Qt.createQmlObject( + effectMakerModel.qmlComponentString, + componentParent, + "" + ); + effectMakerModel.resetEffectError(0); + } catch (error) { + let errorString = "QML: ERROR: "; + let errorLine = -1; + if (error.qmlErrors.length > 0) { + // Show the first QML error + let e = error.qmlErrors[0]; + errorString += e.lineNumber + ": " + e.message; + errorLine = e.lineNumber; + } + effectMakerModel.setEffectError(errorString, 0, errorLine); + } + } + Rectangle { // toolbar width: parent.width height: StudioTheme.Values.toolbarHeight @@ -154,32 +179,6 @@ Column { layer.smooth: true } - // Create a dummy parent to host the effect qml object - function createNewComponent() { - var oldComponent = componentParent.children[0]; - if (oldComponent) - oldComponent.destroy(); - - try { - const newObject = Qt.createQmlObject( - effectMakerModel.qmlComponentString, - componentParent, - "" - ); - effectMakerModel.resetEffectError(0); - } catch (error) { - let errorString = "QML: ERROR: "; - let errorLine = -1; - if (error.qmlErrors.length > 0) { - // Show the first QML error - let e = error.qmlErrors[0]; - errorString += e.lineNumber + ": " + e.message; - errorLine = e.lineNumber; - } - effectMakerModel.setEffectError(errorString, 0, errorLine); - } - } - Connections { target: effectMakerModel function onShadersBaked() { diff --git a/src/plugins/effectmakernew/CMakeLists.txt b/src/plugins/effectmakernew/CMakeLists.txt index b8842687e5e..d01c97618c7 100644 --- a/src/plugins/effectmakernew/CMakeLists.txt +++ b/src/plugins/effectmakernew/CMakeLists.txt @@ -3,7 +3,7 @@ find_package(Qt6 OPTIONAL_COMPONENTS Gui Quick ShaderTools) add_qtc_plugin(EffectMakerNew CONDITION TARGET QmlDesigner AND TARGET Qt::ShaderTools PLUGIN_DEPENDS - QtCreator::Core QtCreator::QmlDesigner + QtCreator::Core QtCreator::QmlDesigner QtCreator::ProjectExplorer DEPENDS Qt::Core QtCreator::Utils Qt::CorePrivate Qt::Widgets Qt::Qml Qt::QmlPrivate Qt::Quick Qt::ShaderTools Qt::ShaderToolsPrivate diff --git a/src/plugins/effectmakernew/effectmakermodel.cpp b/src/plugins/effectmakernew/effectmakermodel.cpp index 9da7d97ef60..364a012fe30 100644 --- a/src/plugins/effectmakernew/effectmakermodel.cpp +++ b/src/plugins/effectmakernew/effectmakermodel.cpp @@ -10,6 +10,12 @@ #include #include +#include +#include +#include + +#include + #include namespace EffectMaker { @@ -758,7 +764,7 @@ void EffectMakerModel::updateCustomUniforms() // Custom values are not readonly, others inside the effect can be QString readOnly = uniform->useCustomValue() ? QString() : QStringLiteral("readonly "); previewEffectPropertiesString += " " + readOnly + "property " + type + " " - + propertyName + bindedValueString + '\n'; + + propertyName + valueString + '\n'; // Define type properties are not added into exports if (!isDefine) { if (uniform->useCustomValue()) { @@ -783,7 +789,9 @@ void EffectMakerModel::updateCustomUniforms() } // See if any of the properties changed - // TODO + m_exportedRootPropertiesString = exportedRootPropertiesString; + m_previewEffectPropertiesString = previewEffectPropertiesString; + m_exportedEffectPropertiesString = exportedEffectPropertiesString; } void EffectMakerModel::bakeShaders() @@ -807,6 +815,7 @@ void EffectMakerModel::bakeShaders() QString vs = m_vertexShader; m_baker.setSourceString(vs.toUtf8(), QShader::VertexStage); QShader vertShader = m_baker.bake(); + if (!vertShader.isValid()) { qWarning() << "Shader baking failed:" << qPrintable(m_baker.errorMessage()); setEffectError(m_baker.errorMessage().split('\n').first(), ErrorVert); @@ -821,6 +830,7 @@ void EffectMakerModel::bakeShaders() m_baker.setSourceString(fs.toUtf8(), QShader::FragmentStage); QShader fragShader = m_baker.bake(); + if (!fragShader.isValid()) { qWarning() << "Shader baking failed:" << qPrintable(m_baker.errorMessage()); setEffectError(m_baker.errorMessage().split('\n').first(), ErrorFrag); @@ -908,6 +918,7 @@ QString EffectMakerModel::getQmlComponentString(bool localFiles) // When used in preview component, we need property with value // and when in exported component, property with binding to root value. s += localFiles ? m_exportedEffectPropertiesString : m_previewEffectPropertiesString; + if (!customImagesString.isEmpty()) s += '\n' + customImagesString; @@ -925,6 +936,21 @@ QString EffectMakerModel::getQmlComponentString(bool localFiles) return s; } +Utils::FilePath EffectMakerModel::qsbPath() const +{ + const ProjectExplorer::Target *target = ProjectExplorer::ProjectTree::currentTarget(); + if (target) { + if (QtSupport::QtVersion *qtVer = QtSupport::QtKitAspect::qtVersion(target->kit())) { + Utils::FilePath path = qtVer->binPath().pathAppended("qsb").withExecutableSuffix(); + if (path.exists()) + return path; + } + } + + qWarning() << "Shader baking failed, QSB not found."; + return {}; +} + void EffectMakerModel::updateQmlComponent() { // Clear possible QML runtime errors diff --git a/src/plugins/effectmakernew/effectmakermodel.h b/src/plugins/effectmakernew/effectmakermodel.h index 395a9063c53..ad315a9c8d1 100644 --- a/src/plugins/effectmakernew/effectmakermodel.h +++ b/src/plugins/effectmakernew/effectmakermodel.h @@ -5,6 +5,8 @@ #include "shaderfeatures.h" +#include + #include #include #include @@ -12,6 +14,10 @@ #include +namespace Utils { +class Process; +} + namespace EffectMaker { class CompositionNode; @@ -60,14 +66,17 @@ public: QString fragmentShader() const; void setFragmentShader(const QString &newFragmentShader); + QString vertexShader() const; void setVertexShader(const QString &newVertexShader); const QString &qmlComponentString() const; - void setQmlComponentString(const QString &string); Q_INVOKABLE void updateQmlComponent(); + Q_INVOKABLE void resetEffectError(int type); + Q_INVOKABLE void setEffectError(const QString &errorMessage, int type = -1, int lineNumber = -1); + signals: void isEmptyChanged(); void selectedIndexChanged(int idx); @@ -102,8 +111,6 @@ private: void updateBakedShaderVersions(); QString detectErrorMessage(const QString &errorMessage); EffectError effectError() const; - void setEffectError(const QString &errorMessage, int type = -1, int lineNumber = -1); - void resetEffectError(int type); QString valueAsString(const Uniform &uniform); QString valueAsBinding(const Uniform &uniform); @@ -121,6 +128,9 @@ private: QString getCustomShaderVaryings(bool outState); QString generateVertexShader(bool includeUniforms = true); QString generateFragmentShader(bool includeUniforms = true); + + Utils::FilePath qsbPath() const; + void updateCustomUniforms(); void bakeShaders(); @@ -140,7 +150,7 @@ private: QString m_vertexShader; QStringList m_defaultRootVertexShader; QStringList m_defaultRootFragmentShader; - QShaderBaker m_baker; + QShaderBaker m_baker; // TODO: Remove QTemporaryFile m_fragmentShaderFile; QTemporaryFile m_vertexShaderFile; // Used in exported QML, at root of the file diff --git a/src/plugins/effectmakernew/effectmakerwidget.cpp b/src/plugins/effectmakernew/effectmakerwidget.cpp index 72d4c1b2cd6..d0114584932 100644 --- a/src/plugins/effectmakernew/effectmakerwidget.cpp +++ b/src/plugins/effectmakernew/effectmakerwidget.cpp @@ -7,6 +7,8 @@ #include "effectmakermodel.h" #include "effectmakernodesmodel.h" #include "effectmakerview.h" + +#include "nodeinstanceview.h" #include "qmldesignerconstants.h" #include "qmldesignerplugin.h" #include "qqmlcontext.h" diff --git a/src/plugins/effectmakernew/uniform.cpp b/src/plugins/effectmakernew/uniform.cpp index 5cad43e0c95..4901b6bbb6e 100644 --- a/src/plugins/effectmakernew/uniform.cpp +++ b/src/plugins/effectmakernew/uniform.cpp @@ -40,6 +40,9 @@ Uniform::Uniform(const QJsonObject &propObj) // QEN files don't store the current value, so with those use default value value = defaultValue; } + m_customValue = propObj.value("customValue").toString(); + m_useCustomValue = getBoolValue(propObj.value("useCustomValue"), false); + minValue = propObj.value("minValue").toString(); maxValue = propObj.value("maxValue").toString();