QmlDesigner: Add Effect Maker shader error propagation

In case of manual edit of shaders, this simple system detects common
errors that might be found in a shader.

Task-number: QDS-10499
Change-Id: I0c70ac85ef519880dcd98642c5927f037f113f94
Reviewed-by: Miikka Heikkinen <miikka.heikkinen@qt.io>
Reviewed-by: Mahmoud Badri <mahmoud.badri@qt.io>
This commit is contained in:
Amr Essam
2023-09-01 10:59:02 +03:00
committed by Amr Elsayed
parent 8ae76adbf5
commit cec9e6493e
2 changed files with 94 additions and 0 deletions

View File

@@ -6,6 +6,8 @@
#include "compositionnode.h" #include "compositionnode.h"
#include "uniform.h" #include "uniform.h"
#include <QRegularExpression>
#include <utils/qtcassert.h> #include <utils/qtcassert.h>
namespace QmlDesigner { namespace QmlDesigner {
@@ -152,4 +154,77 @@ const QString EffectMakerModel::getFSUniforms()
return s; return s;
} }
// Detects common GLSL error messages and returns potential
// additional error information related to them.
QString EffectMakerModel::detectErrorMessage(const QString &errorMessage)
{
static QHash<QString, QString> nodeErrors {
{ "'BLUR_HELPER_MAX_LEVEL' : undeclared identifier", "BlurHelper"},
{ "'iSourceBlur1' : undeclared identifier", "BlurHelper"},
{ "'hash23' : no matching overloaded function found", "NoiseHelper" },
{ "'HASH_BOX_SIZE' : undeclared identifier", "NoiseHelper" },
{ "'pseudo3dNoise' : no matching overloaded function found", "NoiseHelper" }
};
QString missingNodeError = QStringLiteral("Are you missing a %1 node?\n");
QHash<QString, QString>::const_iterator i = nodeErrors.constBegin();
while (i != nodeErrors.constEnd()) {
if (errorMessage.contains(i.key()))
return missingNodeError.arg(i.value());
++i;
}
return QString();
}
// Return first error message (if any)
EffectError EffectMakerModel::effectError() const
{
for (const EffectError &e : std::as_const(m_effectErrors)) {
if (!e.m_message.isEmpty())
return e;
}
return {};
}
// Set the effect error message with optional type and lineNumber.
// Type comes from ErrorTypes, defaulting to common errors (-1).
// Note that type must match with UI editor tab index.
void EffectMakerModel::setEffectError(const QString &errorMessage, int type, int lineNumber)
{
EffectError error;
error.m_type = type;
if (type == 1 || type == 2) {
// For shaders, get the line number from baker output.
// Which is something like "ERROR: :15: message"
int glslErrorLineNumber = -1;
static QRegularExpression spaceReg("\\s+");
QStringList errorStringList = errorMessage.split(spaceReg, Qt::SkipEmptyParts);
if (errorStringList.size() >= 2) {
QString lineString = errorStringList.at(1).trimmed();
if (lineString.size() >= 3) {
// String is ":[linenumber]:", get only the number.
glslErrorLineNumber = lineString.sliced(1, lineString.size() - 2).toInt();
}
}
error.m_line = glslErrorLineNumber;
} else {
// For QML (and others) use given linenumber
error.m_line = lineNumber;
}
QString additionalErrorInfo = detectErrorMessage(errorMessage);
error.m_message = additionalErrorInfo + errorMessage;
m_effectErrors.insert(type, error);
Q_EMIT effectErrorChanged();
}
void EffectMakerModel::resetEffectError(int type)
{
if (m_effectErrors.contains(type)) {
m_effectErrors.remove(type);
Q_EMIT effectErrorChanged();
}
}
} // namespace QmlDesigner } // namespace QmlDesigner

View File

@@ -13,6 +13,17 @@ namespace QmlDesigner {
class CompositionNode; class CompositionNode;
class Uniform; class Uniform;
struct EffectError {
Q_GADGET
Q_PROPERTY(QString message MEMBER m_message)
Q_PROPERTY(int line MEMBER m_line)
Q_PROPERTY(int type MEMBER m_type)
public:
QString m_message;
int m_line = -1;
int m_type = -1;
};
class EffectMakerModel : public QAbstractListModel class EffectMakerModel : public QAbstractListModel
{ {
Q_OBJECT Q_OBJECT
@@ -36,6 +47,7 @@ public:
signals: signals:
void isEmptyChanged(); void isEmptyChanged();
void selectedIndexChanged(int idx); void selectedIndexChanged(int idx);
void effectErrorChanged();
private: private:
enum Roles { enum Roles {
@@ -51,11 +63,18 @@ private:
const QString getVSUniforms(); const QString getVSUniforms();
const QString getFSUniforms(); const QString getFSUniforms();
QString detectErrorMessage(const QString &errorMessage);
EffectError effectError() const;
void setEffectError(const QString &errorMessage, int type, int lineNumber);
void resetEffectError(int type);
QList<CompositionNode *> m_nodes; QList<CompositionNode *> m_nodes;
int m_selectedIndex = -1; int m_selectedIndex = -1;
bool m_isEmpty = true; bool m_isEmpty = true;
QMap<int, EffectError> m_effectErrors;
ShaderFeatures m_shaderFeatures; ShaderFeatures m_shaderFeatures;
}; };