forked from qt-creator/qt-creator
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:
@@ -32,6 +32,12 @@ Item {
|
||||
|
||||
EffectMakerPreview {
|
||||
mainRoot: root
|
||||
|
||||
FrameAnimation {
|
||||
id: previewFrameTimer
|
||||
running: true
|
||||
paused: false // TODO: from the toolbar
|
||||
}
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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());
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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+");
|
||||
};
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user