QmlDesigner: Prepare the process to compile shaders externally

Also added customValue for Uniform

Task-number: QDS-10811
Change-Id: Ie47ad41d0c80da149bdab9cae542297d59abcee6
Reviewed-by: Miikka Heikkinen <miikka.heikkinen@qt.io>
This commit is contained in:
Amr Essam
2023-10-09 13:46:08 +03:00
committed by Amr Elsayed
parent 82be17c2c6
commit 93ba99f019
6 changed files with 73 additions and 33 deletions

View File

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

View File

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

View File

@@ -10,6 +10,12 @@
#include <QByteArrayView>
#include <QVector2D>
#include <projectexplorer/project.h>
#include <projectexplorer/projecttree.h>
#include <projectexplorer/target.h>
#include <qtsupport/qtkitinformation.h>
#include <utils/qtcassert.h>
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

View File

@@ -5,6 +5,8 @@
#include "shaderfeatures.h"
#include <utils/filepath.h>
#include <QMap>
#include <QRegularExpression>
#include <QStandardItemModel>
@@ -12,6 +14,10 @@
#include <QtShaderTools/private/qshaderbaker_p.h>
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

View File

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

View File

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