forked from qt-creator/qt-creator
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:
@@ -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
|
||||||
|
@@ -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;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user