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 {
|
EffectMakerPreview {
|
||||||
mainRoot: root
|
mainRoot: root
|
||||||
|
|
||||||
|
FrameAnimation {
|
||||||
|
id: previewFrameTimer
|
||||||
|
running: true
|
||||||
|
paused: false // TODO: from the toolbar
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Rectangle {
|
Rectangle {
|
||||||
|
|||||||
@@ -12,6 +12,9 @@ import EffectMakerBackend
|
|||||||
Column {
|
Column {
|
||||||
id: root
|
id: root
|
||||||
|
|
||||||
|
property real animatedTime: 0 //TODO get from animator
|
||||||
|
property int animatedFrame: 0 //TODO get from animator
|
||||||
|
|
||||||
width: parent.width
|
width: parent.width
|
||||||
|
|
||||||
required property Item mainRoot
|
required property Item mainRoot
|
||||||
|
|||||||
@@ -102,7 +102,7 @@ void CompositionNode::parse(const QString &qenPath)
|
|||||||
// parse properties
|
// parse properties
|
||||||
QJsonArray jsonProps = json.value("properties").toArray();
|
QJsonArray jsonProps = json.value("properties").toArray();
|
||||||
for (const auto /*QJsonValueRef*/ &prop : jsonProps) {
|
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);
|
m_unifomrsModel.addUniform(uniform);
|
||||||
g_propertyData.insert(uniform->name(), uniform->value());
|
g_propertyData.insert(uniform->name(), uniform->value());
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -60,6 +60,20 @@ EffectMakerModel::EffectMakerModel(QObject *parent)
|
|||||||
m_vertexShaderFilename = m_vertexShaderFile.fileName();
|
m_vertexShaderFilename = m_vertexShaderFile.fileName();
|
||||||
m_fragmentShaderFilename = m_fragmentShaderFile.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
|
QHash<int, QByteArray> EffectMakerModel::roleNames() const
|
||||||
@@ -734,6 +748,7 @@ void EffectMakerModel::handleQsbProcessExit(Utils::Process *qsbProcess, const QS
|
|||||||
--m_remainingQsbTargets;
|
--m_remainingQsbTargets;
|
||||||
|
|
||||||
const QString errStr = qsbProcess->errorString();
|
const QString errStr = qsbProcess->errorString();
|
||||||
|
auto std = qsbProcess->stdErr();
|
||||||
if (!errStr.isEmpty())
|
if (!errStr.isEmpty())
|
||||||
qWarning() << QString("Failed to generate QSB file for: %1 %2").arg(shader, errStr);
|
qWarning() << QString("Failed to generate QSB file for: %1 %2").arg(shader, errStr);
|
||||||
|
|
||||||
@@ -891,12 +906,47 @@ void EffectMakerModel::setShadersUpToDate(bool UpToDate)
|
|||||||
emit shadersUpToDateChanged();
|
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)
|
QString EffectMakerModel::getQmlImagesString(bool localFiles)
|
||||||
{
|
{
|
||||||
Q_UNUSED(localFiles)
|
QString imagesString;
|
||||||
|
const QList<Uniform *> uniforms = allUniforms();
|
||||||
// TODO
|
for (Uniform *uniform : uniforms) {
|
||||||
return QString();
|
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)
|
QString EffectMakerModel::getQmlComponentString(bool localFiles)
|
||||||
@@ -971,5 +1021,35 @@ void EffectMakerModel::updateQmlComponent()
|
|||||||
m_qmlComponentString = getQmlComponentString(false);
|
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
|
} // namespace EffectMaker
|
||||||
|
|
||||||
|
|||||||
@@ -6,7 +6,9 @@
|
|||||||
#include "shaderfeatures.h"
|
#include "shaderfeatures.h"
|
||||||
|
|
||||||
#include <utils/filepath.h>
|
#include <utils/filepath.h>
|
||||||
|
#include <utils/filesystemwatcher.h>
|
||||||
|
|
||||||
|
#include <QFileSystemWatcher>
|
||||||
#include <QMap>
|
#include <QMap>
|
||||||
#include <QRegularExpression>
|
#include <QRegularExpression>
|
||||||
#include <QStandardItemModel>
|
#include <QStandardItemModel>
|
||||||
@@ -132,10 +134,14 @@ private:
|
|||||||
QString generateVertexShader(bool includeUniforms = true);
|
QString generateVertexShader(bool includeUniforms = true);
|
||||||
QString generateFragmentShader(bool includeUniforms = true);
|
QString generateFragmentShader(bool includeUniforms = true);
|
||||||
void handleQsbProcessExit(Utils::Process *qsbProcess, const QString &shader);
|
void handleQsbProcessExit(Utils::Process *qsbProcess, const QString &shader);
|
||||||
|
QString stripFileFromURL(const QString &urlString) const;
|
||||||
|
void updateImageWatchers();
|
||||||
|
void clearImageWatchers();
|
||||||
|
|
||||||
void updateCustomUniforms();
|
void updateCustomUniforms();
|
||||||
void bakeShaders();
|
void bakeShaders();
|
||||||
|
|
||||||
|
QString mipmapPropertyName(const QString &name) const;
|
||||||
QString getQmlImagesString(bool localFiles);
|
QString getQmlImagesString(bool localFiles);
|
||||||
QString getQmlComponentString(bool localFiles);
|
QString getQmlComponentString(bool localFiles);
|
||||||
|
|
||||||
@@ -169,6 +175,8 @@ private:
|
|||||||
// Used in preview QML, at ShaderEffect component of the file
|
// Used in preview QML, at ShaderEffect component of the file
|
||||||
QString m_previewEffectPropertiesString;
|
QString m_previewEffectPropertiesString;
|
||||||
QString m_qmlComponentString;
|
QString m_qmlComponentString;
|
||||||
|
bool m_loadComponentImages = true;
|
||||||
|
Utils::FileSystemWatcher m_fileWatcher;
|
||||||
|
|
||||||
const QRegularExpression m_spaceReg = QRegularExpression("\\s+");
|
const QRegularExpression m_spaceReg = QRegularExpression("\\s+");
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
#include "uniform.h"
|
#include "uniform.h"
|
||||||
#include <qmldesignerplugin.h>
|
#include <qmldesignerplugin.h>
|
||||||
|
|
||||||
|
#include "propertyhandler.h"
|
||||||
|
|
||||||
#include <QColor>
|
#include <QColor>
|
||||||
#include <QJsonObject>
|
#include <QJsonObject>
|
||||||
@@ -11,7 +12,8 @@
|
|||||||
|
|
||||||
namespace EffectMaker {
|
namespace EffectMaker {
|
||||||
|
|
||||||
Uniform::Uniform(const QJsonObject &propObj)
|
Uniform::Uniform(const QJsonObject &propObj, const QString &qenPath) :
|
||||||
|
m_qenPath(qenPath)
|
||||||
{
|
{
|
||||||
QString value, defaultValue, minValue, maxValue;
|
QString value, defaultValue, minValue, maxValue;
|
||||||
|
|
||||||
@@ -31,6 +33,7 @@ Uniform::Uniform(const QJsonObject &propObj)
|
|||||||
m_enableMipmap = getBoolValue(propObj.value("enableMipmap"), false);
|
m_enableMipmap = getBoolValue(propObj.value("enableMipmap"), false);
|
||||||
// Update the mipmap property
|
// Update the mipmap property
|
||||||
QString mipmapProperty = mipmapPropertyName(m_name);
|
QString mipmapProperty = mipmapPropertyName(m_name);
|
||||||
|
g_propertyData[mipmapProperty] = m_enableMipmap;
|
||||||
}
|
}
|
||||||
if (propObj.contains("value")) {
|
if (propObj.contains("value")) {
|
||||||
value = propObj.value("value").toString();
|
value = propObj.value("value").toString();
|
||||||
@@ -164,9 +167,13 @@ bool Uniform::getBoolValue(const QJsonValue &jsonValue, bool defaultValue)
|
|||||||
// Used with sampler types
|
// Used with sampler types
|
||||||
QString Uniform::getResourcePath(const QString &value) const
|
QString Uniform::getResourcePath(const QString &value) const
|
||||||
{
|
{
|
||||||
Q_UNUSED(value)
|
QString filePath = value;
|
||||||
//TODO
|
QDir dir(m_qenPath);
|
||||||
return {};
|
dir.cdUp();
|
||||||
|
QString absPath = dir.absoluteFilePath(filePath);
|
||||||
|
absPath = QDir::cleanPath(absPath);
|
||||||
|
absPath = QUrl::fromLocalFile(absPath).toString();
|
||||||
|
return absPath;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Validation and setting values
|
// Validation and setting values
|
||||||
@@ -263,10 +270,8 @@ QString Uniform::stringFromType(Uniform::Type type)
|
|||||||
return "vec2";
|
return "vec2";
|
||||||
else if (type == Type::Vec3)
|
else if (type == Type::Vec3)
|
||||||
return "vec3";
|
return "vec3";
|
||||||
else if (type == Type::Vec4)
|
else if (type == Type::Vec4 || type == Type::Color)
|
||||||
return "vec4";
|
return "vec4";
|
||||||
else if (type == Type::Color)
|
|
||||||
return "color";
|
|
||||||
else if (type == Type::Sampler)
|
else if (type == Type::Sampler)
|
||||||
return "sampler2D";
|
return "sampler2D";
|
||||||
else if (type == Type::Define)
|
else if (type == Type::Define)
|
||||||
@@ -292,7 +297,7 @@ Uniform::Type Uniform::typeFromString(const QString &typeString)
|
|||||||
return Uniform::Type::Vec4;
|
return Uniform::Type::Vec4;
|
||||||
else if (typeString == "color")
|
else if (typeString == "color")
|
||||||
return Uniform::Type::Color;
|
return Uniform::Type::Color;
|
||||||
else if (typeString == "sampler2D")
|
else if (typeString == "image")
|
||||||
return Uniform::Type::Sampler;
|
return Uniform::Type::Sampler;
|
||||||
else if (typeString == "define")
|
else if (typeString == "define")
|
||||||
return Uniform::Type::Define;
|
return Uniform::Type::Define;
|
||||||
|
|||||||
@@ -42,7 +42,7 @@ public:
|
|||||||
Define
|
Define
|
||||||
};
|
};
|
||||||
|
|
||||||
Uniform(const QJsonObject &props);
|
Uniform(const QJsonObject &props, const QString &qenPath);
|
||||||
|
|
||||||
Type type() const;
|
Type type() const;
|
||||||
QString typeName() const;
|
QString typeName() const;
|
||||||
@@ -87,6 +87,7 @@ private:
|
|||||||
QVariant getInitializedVariant(bool maxValue);
|
QVariant getInitializedVariant(bool maxValue);
|
||||||
QVariant valueStringToVariant(const QString &value);
|
QVariant valueStringToVariant(const QString &value);
|
||||||
|
|
||||||
|
QString m_qenPath;
|
||||||
Type m_type;
|
Type m_type;
|
||||||
QVariant m_value;
|
QVariant m_value;
|
||||||
QVariant m_defaultValue;
|
QVariant m_defaultValue;
|
||||||
|
|||||||
Reference in New Issue
Block a user