QmlDesigner: Fix some parsing issues in effect maker

Task-number: QDS-10987
Change-Id: Ifeb42f9e04ba39ddaa45a03b60eb12ce1652c61a
Reviewed-by: Mahmoud Badri <mahmoud.badri@qt.io>
Reviewed-by: Miikka Heikkinen <miikka.heikkinen@qt.io>
This commit is contained in:
Amr Essam
2023-10-19 16:39:21 +03:00
committed by Amr Elsayed
parent 1d04d50c78
commit 96dfdfc0b7
7 changed files with 117 additions and 14 deletions

View File

@@ -32,6 +32,12 @@ Item {
EffectMakerPreview {
mainRoot: root
FrameAnimation {
id: previewFrameTimer
running: true
paused: false // TODO: from the toolbar
}
}
Rectangle {

View File

@@ -12,6 +12,9 @@ import EffectMakerBackend
Column {
id: root
property real animatedTime: 0 //TODO get from animator
property int animatedFrame: 0 //TODO get from animator
width: parent.width
required property Item mainRoot

View File

@@ -102,7 +102,7 @@ void CompositionNode::parse(const QString &qenPath)
// parse properties
QJsonArray jsonProps = json.value("properties").toArray();
for (const auto /*QJsonValueRef*/ &prop : jsonProps) {
const auto uniform = new Uniform(prop.toObject());
const auto uniform = new Uniform(prop.toObject(), qenPath);
m_unifomrsModel.addUniform(uniform);
g_propertyData.insert(uniform->name(), uniform->value());
}

View File

@@ -60,6 +60,20 @@ EffectMakerModel::EffectMakerModel(QObject *parent)
m_vertexShaderFilename = m_vertexShaderFile.fileName();
m_fragmentShaderFilename = m_fragmentShaderFile.fileName();
}
connect(&m_fileWatcher, &Utils::FileSystemWatcher::fileChanged, this, [this]() {
// Update component with images not set.
m_loadComponentImages = false;
updateQmlComponent();
// Then enable component images with a longer delay than
// the component updating delay. This way Image elements
// will reload the changed image files.
const int enableImagesDelay = 200;
QTimer::singleShot(enableImagesDelay, this, [this]() {
m_loadComponentImages = true;
updateQmlComponent();
} );
});
}
QHash<int, QByteArray> EffectMakerModel::roleNames() const
@@ -734,6 +748,7 @@ void EffectMakerModel::handleQsbProcessExit(Utils::Process *qsbProcess, const QS
--m_remainingQsbTargets;
const QString errStr = qsbProcess->errorString();
auto std = qsbProcess->stdErr();
if (!errStr.isEmpty())
qWarning() << QString("Failed to generate QSB file for: %1 %2").arg(shader, errStr);
@@ -891,12 +906,47 @@ void EffectMakerModel::setShadersUpToDate(bool UpToDate)
emit shadersUpToDateChanged();
}
// Returns name for image mipmap property.
// e.g. "myImage" -> "myImageMipmap".
QString EffectMakerModel::mipmapPropertyName(const QString &name) const
{
QString simplifiedName = name.simplified();
simplifiedName = simplifiedName.remove(' ');
simplifiedName += "Mipmap";
return simplifiedName;
}
QString EffectMakerModel::getQmlImagesString(bool localFiles)
{
Q_UNUSED(localFiles)
// TODO
return QString();
QString imagesString;
const QList<Uniform *> uniforms = allUniforms();
for (Uniform *uniform : uniforms) {
if (uniform->type() == Uniform::Type::Sampler) {
QString imagePath = uniform->value().toString();
if (imagePath.isEmpty())
continue;
imagesString += " Image {\n";
QString simplifiedName = getImageElementName(*uniform);
imagesString += QString(" id: %1\n").arg(simplifiedName);
imagesString += " anchors.fill: parent\n";
// File paths are absolute, return as local when requested
if (localFiles) {
QFileInfo fi(imagePath);
imagePath = fi.fileName();
}
if (m_loadComponentImages)
imagesString += QString(" source: \"%1\"\n").arg(imagePath);
if (!localFiles) {
QString mipmapProperty = mipmapPropertyName(uniform->name());
imagesString += QString(" mipmap: g_propertyData.%1\n").arg(mipmapProperty);
} else if (uniform->enableMipmap()) {
imagesString += " mipmap: true\n";
}
imagesString += " visible: false\n";
imagesString += " }\n";
}
}
return imagesString;
}
QString EffectMakerModel::getQmlComponentString(bool localFiles)
@@ -971,5 +1021,35 @@ void EffectMakerModel::updateQmlComponent()
m_qmlComponentString = getQmlComponentString(false);
}
// Removes "file:" from the URL path.
// So e.g. "file:///C:/myimages/steel1.jpg" -> "C:/myimages/steel1.jpg"
QString EffectMakerModel::stripFileFromURL(const QString &urlString) const
{
QUrl url(urlString);
QString filePath = (url.scheme() == QStringLiteral("file")) ? url.toLocalFile() : url.toString();
return filePath;
}
void EffectMakerModel::updateImageWatchers()
{
const QList<Uniform *> uniforms = allUniforms();
for (Uniform *uniform : uniforms) {
if (uniform->type() == Uniform::Type::Sampler) {
// Watch all image properties files
QString imagePath = stripFileFromURL(uniform->value().toString());
if (imagePath.isEmpty())
continue;
m_fileWatcher.addFile(imagePath, Utils::FileSystemWatcher::WatchAllChanges);
}
}
}
void EffectMakerModel::clearImageWatchers()
{
const auto watchedFiles = m_fileWatcher.files();
if (!watchedFiles.isEmpty())
m_fileWatcher.removeFiles(watchedFiles);
}
} // namespace EffectMaker

View File

@@ -6,7 +6,9 @@
#include "shaderfeatures.h"
#include <utils/filepath.h>
#include <utils/filesystemwatcher.h>
#include <QFileSystemWatcher>
#include <QMap>
#include <QRegularExpression>
#include <QStandardItemModel>
@@ -132,10 +134,14 @@ private:
QString generateVertexShader(bool includeUniforms = true);
QString generateFragmentShader(bool includeUniforms = true);
void handleQsbProcessExit(Utils::Process *qsbProcess, const QString &shader);
QString stripFileFromURL(const QString &urlString) const;
void updateImageWatchers();
void clearImageWatchers();
void updateCustomUniforms();
void bakeShaders();
QString mipmapPropertyName(const QString &name) const;
QString getQmlImagesString(bool localFiles);
QString getQmlComponentString(bool localFiles);
@@ -169,6 +175,8 @@ private:
// Used in preview QML, at ShaderEffect component of the file
QString m_previewEffectPropertiesString;
QString m_qmlComponentString;
bool m_loadComponentImages = true;
Utils::FileSystemWatcher m_fileWatcher;
const QRegularExpression m_spaceReg = QRegularExpression("\\s+");
};

View File

@@ -4,6 +4,7 @@
#include "uniform.h"
#include <qmldesignerplugin.h>
#include "propertyhandler.h"
#include <QColor>
#include <QJsonObject>
@@ -11,7 +12,8 @@
namespace EffectMaker {
Uniform::Uniform(const QJsonObject &propObj)
Uniform::Uniform(const QJsonObject &propObj, const QString &qenPath) :
m_qenPath(qenPath)
{
QString value, defaultValue, minValue, maxValue;
@@ -31,6 +33,7 @@ Uniform::Uniform(const QJsonObject &propObj)
m_enableMipmap = getBoolValue(propObj.value("enableMipmap"), false);
// Update the mipmap property
QString mipmapProperty = mipmapPropertyName(m_name);
g_propertyData[mipmapProperty] = m_enableMipmap;
}
if (propObj.contains("value")) {
value = propObj.value("value").toString();
@@ -164,9 +167,13 @@ bool Uniform::getBoolValue(const QJsonValue &jsonValue, bool defaultValue)
// Used with sampler types
QString Uniform::getResourcePath(const QString &value) const
{
Q_UNUSED(value)
//TODO
return {};
QString filePath = value;
QDir dir(m_qenPath);
dir.cdUp();
QString absPath = dir.absoluteFilePath(filePath);
absPath = QDir::cleanPath(absPath);
absPath = QUrl::fromLocalFile(absPath).toString();
return absPath;
}
// Validation and setting values
@@ -263,10 +270,8 @@ QString Uniform::stringFromType(Uniform::Type type)
return "vec2";
else if (type == Type::Vec3)
return "vec3";
else if (type == Type::Vec4)
else if (type == Type::Vec4 || type == Type::Color)
return "vec4";
else if (type == Type::Color)
return "color";
else if (type == Type::Sampler)
return "sampler2D";
else if (type == Type::Define)
@@ -292,7 +297,7 @@ Uniform::Type Uniform::typeFromString(const QString &typeString)
return Uniform::Type::Vec4;
else if (typeString == "color")
return Uniform::Type::Color;
else if (typeString == "sampler2D")
else if (typeString == "image")
return Uniform::Type::Sampler;
else if (typeString == "define")
return Uniform::Type::Define;

View File

@@ -42,7 +42,7 @@ public:
Define
};
Uniform(const QJsonObject &props);
Uniform(const QJsonObject &props, const QString &qenPath);
Type type() const;
QString typeName() const;
@@ -87,6 +87,7 @@ private:
QVariant getInitializedVariant(bool maxValue);
QVariant valueStringToVariant(const QString &value);
QString m_qenPath;
Type m_type;
QVariant m_value;
QVariant m_defaultValue;