forked from qt-creator/qt-creator
EffectMaker: Open saved compositions
- Also fixing issues related to image paths - Composition name is shown in save dialog when re-save - Clear current composition for reset or open a new one Task-number: QDS-11192 Change-Id: I97aad4b5216e6b116343bb274db0f9abd1275fec Reviewed-by: Mahmoud Badri <mahmoud.badri@qt.io>
This commit is contained in:
@@ -18,6 +18,7 @@ Item {
|
|||||||
|
|
||||||
SaveDialog {
|
SaveDialog {
|
||||||
id: saveDialog
|
id: saveDialog
|
||||||
|
compositionName: EffectMakerBackend.effectMakerModel.currentComposition
|
||||||
anchors.centerIn: parent
|
anchors.centerIn: parent
|
||||||
onAccepted: {
|
onAccepted: {
|
||||||
let name = saveDialog.compositionName
|
let name = saveDialog.compositionName
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ StudioControls.Dialog {
|
|||||||
property string compositionName: ""
|
property string compositionName: ""
|
||||||
|
|
||||||
onOpened: {
|
onOpened: {
|
||||||
nameText.text = "" //TODO: Generate unique name
|
nameText.text = compositionName //TODO: Generate unique name
|
||||||
emptyText.text = ""
|
emptyText.text = ""
|
||||||
nameText.forceActiveFocus()
|
nameText.forceActiveFocus()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,13 +11,36 @@
|
|||||||
#include <QFile>
|
#include <QFile>
|
||||||
#include <QJsonArray>
|
#include <QJsonArray>
|
||||||
#include <QJsonDocument>
|
#include <QJsonDocument>
|
||||||
#include <QJsonObject>
|
|
||||||
|
|
||||||
namespace EffectMaker {
|
namespace EffectMaker {
|
||||||
|
|
||||||
CompositionNode::CompositionNode(const QString &qenPath)
|
CompositionNode::CompositionNode(const QString &effectName, const QString &qenPath, const QJsonObject &jsonObject)
|
||||||
{
|
{
|
||||||
parse(qenPath);
|
QJsonObject json;
|
||||||
|
if (jsonObject.isEmpty()) {
|
||||||
|
QFile qenFile(qenPath);
|
||||||
|
if (!qenFile.open(QIODevice::ReadOnly)) {
|
||||||
|
qWarning("Couldn't open effect file.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
QByteArray loadData = qenFile.readAll();
|
||||||
|
QJsonParseError parseError;
|
||||||
|
QJsonDocument jsonDoc(QJsonDocument::fromJson(loadData, &parseError));
|
||||||
|
|
||||||
|
if (parseError.error != QJsonParseError::NoError) {
|
||||||
|
QString error = QString("Error parsing effect node");
|
||||||
|
QString errorDetails = QString("%1: %2").arg(parseError.offset).arg(parseError.errorString());
|
||||||
|
qWarning() << error;
|
||||||
|
qWarning() << errorDetails;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
json = jsonDoc.object().value("QEN").toObject();
|
||||||
|
parse(effectName, qenPath, json);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
parse(effectName, "", jsonObject);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
QString CompositionNode::fragmentCode() const
|
QString CompositionNode::fragmentCode() const
|
||||||
@@ -63,28 +86,8 @@ CompositionNode::NodeType CompositionNode::type() const
|
|||||||
return m_type;
|
return m_type;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CompositionNode::parse(const QString &qenPath)
|
void CompositionNode::parse(const QString &effectName, const QString &qenPath, const QJsonObject &json)
|
||||||
{
|
{
|
||||||
QFile qenFile(qenPath);
|
|
||||||
|
|
||||||
if (!qenFile.open(QIODevice::ReadOnly)) {
|
|
||||||
qWarning("Couldn't open effect file.");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
QByteArray loadData = qenFile.readAll();
|
|
||||||
QJsonParseError parseError;
|
|
||||||
QJsonDocument jsonDoc(QJsonDocument::fromJson(loadData, &parseError));
|
|
||||||
if (parseError.error != QJsonParseError::NoError) {
|
|
||||||
QString error = QString("Error parsing the effect node: %1:").arg(qenPath);
|
|
||||||
QString errorDetails = QString("%1: %2").arg(parseError.offset).arg(parseError.errorString());
|
|
||||||
qWarning() << qPrintable(error);
|
|
||||||
qWarning() << qPrintable(errorDetails);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
QJsonObject json = jsonDoc.object().value("QEN").toObject();
|
|
||||||
|
|
||||||
int version = -1;
|
int version = -1;
|
||||||
if (json.contains("version"))
|
if (json.contains("version"))
|
||||||
version = json["version"].toInt(-1);
|
version = json["version"].toInt(-1);
|
||||||
@@ -102,7 +105,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(), qenPath);
|
const auto uniform = new Uniform(effectName, prop.toObject(), qenPath);
|
||||||
m_unifomrsModel.addUniform(uniform);
|
m_unifomrsModel.addUniform(uniform);
|
||||||
m_uniforms.append(uniform);
|
m_uniforms.append(uniform);
|
||||||
g_propertyData.insert(uniform->name(), uniform->value());
|
g_propertyData.insert(uniform->name(), uniform->value());
|
||||||
|
|||||||
@@ -5,6 +5,7 @@
|
|||||||
|
|
||||||
#include "effectmakeruniformsmodel.h"
|
#include "effectmakeruniformsmodel.h"
|
||||||
|
|
||||||
|
#include <QJsonObject>
|
||||||
#include <QObject>
|
#include <QObject>
|
||||||
|
|
||||||
namespace EffectMaker {
|
namespace EffectMaker {
|
||||||
@@ -24,7 +25,7 @@ public:
|
|||||||
CustomNode
|
CustomNode
|
||||||
};
|
};
|
||||||
|
|
||||||
CompositionNode(const QString &qenPath);
|
CompositionNode(const QString &effectName, const QString &qenPath, const QJsonObject &json = {});
|
||||||
|
|
||||||
QString fragmentCode() const;
|
QString fragmentCode() const;
|
||||||
QString vertexCode() const;
|
QString vertexCode() const;
|
||||||
@@ -48,7 +49,7 @@ signals:
|
|||||||
void isEnabledChanged();
|
void isEnabledChanged();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void parse(const QString &qenPath);
|
void parse(const QString &effectName, const QString &qenPath, const QJsonObject &json);
|
||||||
|
|
||||||
QString m_name;
|
QString m_name;
|
||||||
NodeType m_type = CustomNode;
|
NodeType m_type = CustomNode;
|
||||||
|
|||||||
@@ -49,19 +49,6 @@ static bool writeToFile(const QByteArray &buf, const QString &filename, FileType
|
|||||||
EffectMakerModel::EffectMakerModel(QObject *parent)
|
EffectMakerModel::EffectMakerModel(QObject *parent)
|
||||||
: QAbstractListModel{parent}
|
: QAbstractListModel{parent}
|
||||||
{
|
{
|
||||||
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
|
||||||
@@ -117,7 +104,7 @@ void EffectMakerModel::setIsEmpty(bool val)
|
|||||||
void EffectMakerModel::addNode(const QString &nodeQenPath)
|
void EffectMakerModel::addNode(const QString &nodeQenPath)
|
||||||
{
|
{
|
||||||
beginInsertRows({}, m_nodes.size(), m_nodes.size());
|
beginInsertRows({}, m_nodes.size(), m_nodes.size());
|
||||||
auto *node = new CompositionNode(nodeQenPath);
|
auto *node = new CompositionNode("", nodeQenPath);
|
||||||
m_nodes.append(node);
|
m_nodes.append(node);
|
||||||
endInsertRows();
|
endInsertRows();
|
||||||
|
|
||||||
@@ -189,12 +176,17 @@ void EffectMakerModel::clear()
|
|||||||
if (m_nodes.isEmpty())
|
if (m_nodes.isEmpty())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
beginRemoveRows({}, 0, m_nodes.count());
|
||||||
|
|
||||||
for (CompositionNode *node : std::as_const(m_nodes))
|
for (CompositionNode *node : std::as_const(m_nodes))
|
||||||
delete node;
|
delete node;
|
||||||
|
|
||||||
m_nodes.clear();
|
m_nodes.clear();
|
||||||
|
|
||||||
|
endRemoveRows();
|
||||||
|
|
||||||
setIsEmpty(true);
|
setIsEmpty(true);
|
||||||
|
bakeShaders();
|
||||||
}
|
}
|
||||||
|
|
||||||
const QList<Uniform *> EffectMakerModel::allUniforms()
|
const QList<Uniform *> EffectMakerModel::allUniforms()
|
||||||
@@ -571,6 +563,69 @@ void EffectMakerModel::exportComposition(const QString &name)
|
|||||||
saveFile.close();
|
saveFile.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void EffectMakerModel::openComposition(const QString &path)
|
||||||
|
{
|
||||||
|
clear();
|
||||||
|
|
||||||
|
QFile compFile(path);
|
||||||
|
if (!compFile.open(QIODevice::ReadOnly)) {
|
||||||
|
QString error = QString("Couldn't open composition file: '%1'").arg(path);
|
||||||
|
qWarning() << qPrintable(error);
|
||||||
|
setEffectError(error);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
QByteArray data = compFile.readAll();
|
||||||
|
QJsonParseError parseError;
|
||||||
|
QJsonDocument jsonDoc(QJsonDocument::fromJson(data, &parseError));
|
||||||
|
if (parseError.error != QJsonParseError::NoError) {
|
||||||
|
QString error = QString("Error parsing the project file: %1").arg(parseError.errorString());
|
||||||
|
qWarning() << error;
|
||||||
|
setEffectError(error);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
QJsonObject rootJson = jsonDoc.object();
|
||||||
|
if (!rootJson.contains("QEP")) {
|
||||||
|
QString error = QStringLiteral("Error: Invalid project file");
|
||||||
|
qWarning() << error;
|
||||||
|
setEffectError(error);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
QJsonObject json = rootJson["QEP"].toObject();
|
||||||
|
|
||||||
|
int version = -1;
|
||||||
|
if (json.contains("version"))
|
||||||
|
version = json["version"].toInt(-1);
|
||||||
|
|
||||||
|
if (version != 1) {
|
||||||
|
QString error = QString("Error: Unknown project version (%1)").arg(version);
|
||||||
|
qWarning() << error;
|
||||||
|
setEffectError(error);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get effects dir
|
||||||
|
const QString effectName = QFileInfo(path).baseName();
|
||||||
|
const Utils::FilePath effectsResDir = QmlDesigner::ModelNodeOperations::getEffectsImportDirectory();
|
||||||
|
const QString effectsResPath = effectsResDir.pathAppended(effectName).toString();
|
||||||
|
|
||||||
|
if (json.contains("nodes") && json["nodes"].isArray()) {
|
||||||
|
const QJsonArray nodesArray = json["nodes"].toArray();
|
||||||
|
for (const auto &nodeElement : nodesArray) {
|
||||||
|
beginInsertRows({}, m_nodes.size(), m_nodes.size());
|
||||||
|
auto *node = new CompositionNode(effectName, "", nodeElement.toObject());
|
||||||
|
m_nodes.append(node);
|
||||||
|
endInsertRows();
|
||||||
|
}
|
||||||
|
|
||||||
|
setIsEmpty(m_nodes.isEmpty());
|
||||||
|
bakeShaders();
|
||||||
|
}
|
||||||
|
|
||||||
|
setCurrentComposition(effectName);
|
||||||
|
}
|
||||||
|
|
||||||
void EffectMakerModel::exportResources(const QString &name)
|
void EffectMakerModel::exportResources(const QString &name)
|
||||||
{
|
{
|
||||||
// Make sure that uniforms are up-to-date
|
// Make sure that uniforms are up-to-date
|
||||||
@@ -647,18 +702,15 @@ void EffectMakerModel::exportResources(const QString &name)
|
|||||||
QString imagePath = uniform->value().toString();
|
QString imagePath = uniform->value().toString();
|
||||||
QFileInfo fi(imagePath);
|
QFileInfo fi(imagePath);
|
||||||
QString imageFilename = fi.fileName();
|
QString imageFilename = fi.fileName();
|
||||||
sources.append(imagePath);
|
sources.append(imagePath.remove(0, 7)); // Removes "file://"
|
||||||
dests.append(imageFilename);
|
dests.append(imageFilename);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//TODO: Copy source files if requested in future versions
|
|
||||||
|
|
||||||
// Copy files
|
|
||||||
for (int i = 0; i < sources.count(); ++i) {
|
for (int i = 0; i < sources.count(); ++i) {
|
||||||
Utils::FilePath source = Utils::FilePath::fromString(sources[i]);
|
Utils::FilePath source = Utils::FilePath::fromString(sources[i]);
|
||||||
Utils::FilePath target = Utils::FilePath::fromString(effectsResPath + dests[i]);
|
Utils::FilePath target = Utils::FilePath::fromString(effectsResPath + dests[i]);
|
||||||
if (target.exists())
|
if (target.exists() && source.fileName() != target.fileName())
|
||||||
target.removeFile(); // Remove existing file for update
|
target.removeFile(); // Remove existing file for update
|
||||||
|
|
||||||
if (!source.copyFile(target))
|
if (!source.copyFile(target))
|
||||||
@@ -1254,15 +1306,16 @@ QString EffectMakerModel::getQmlImagesString(bool localFiles)
|
|||||||
if (localFiles) {
|
if (localFiles) {
|
||||||
QFileInfo fi(imagePath);
|
QFileInfo fi(imagePath);
|
||||||
imagePath = fi.fileName();
|
imagePath = fi.fileName();
|
||||||
}
|
imagesString += QString(" source: %1\n").arg(uniform->name());
|
||||||
if (m_loadComponentImages)
|
} else {
|
||||||
imagesString += QString(" source: g_propertyData.%1\n").arg(uniform->name());
|
imagesString += QString(" source: g_propertyData.%1\n").arg(uniform->name());
|
||||||
if (!localFiles) {
|
|
||||||
QString mipmapProperty = mipmapPropertyName(uniform->name());
|
if (uniform->enableMipmap())
|
||||||
imagesString += QString(" mipmap: g_propertyData.%1\n").arg(mipmapProperty);
|
|
||||||
} else if (uniform->enableMipmap()) {
|
|
||||||
imagesString += " mipmap: true\n";
|
imagesString += " mipmap: true\n";
|
||||||
|
else
|
||||||
|
QString mipmapProperty = mipmapPropertyName(uniform->name());
|
||||||
}
|
}
|
||||||
|
|
||||||
imagesString += " visible: false\n";
|
imagesString += " visible: false\n";
|
||||||
imagesString += " }\n";
|
imagesString += " }\n";
|
||||||
}
|
}
|
||||||
@@ -1336,6 +1389,19 @@ QString EffectMakerModel::getQmlComponentString(bool localFiles)
|
|||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QString EffectMakerModel::currentComposition() const
|
||||||
|
{
|
||||||
|
return m_currentComposition;
|
||||||
|
}
|
||||||
|
|
||||||
|
void EffectMakerModel::setCurrentComposition(const QString &newCurrentComposition)
|
||||||
|
{
|
||||||
|
if (m_currentComposition == newCurrentComposition)
|
||||||
|
return;
|
||||||
|
m_currentComposition = newCurrentComposition;
|
||||||
|
emit currentCompositionChanged();
|
||||||
|
}
|
||||||
|
|
||||||
void EffectMakerModel::updateQmlComponent()
|
void EffectMakerModel::updateQmlComponent()
|
||||||
{
|
{
|
||||||
// Clear possible QML runtime errors
|
// Clear possible QML runtime errors
|
||||||
@@ -1352,25 +1418,4 @@ QString EffectMakerModel::stripFileFromURL(const QString &urlString) const
|
|||||||
return filePath;
|
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,6 @@
|
|||||||
#include "shaderfeatures.h"
|
#include "shaderfeatures.h"
|
||||||
|
|
||||||
#include <utils/filepath.h>
|
#include <utils/filepath.h>
|
||||||
#include <utils/filesystemwatcher.h>
|
|
||||||
|
|
||||||
#include <QFileSystemWatcher>
|
#include <QFileSystemWatcher>
|
||||||
#include <QMap>
|
#include <QMap>
|
||||||
@@ -47,7 +46,7 @@ class EffectMakerModel : public QAbstractListModel
|
|||||||
Q_PROPERTY(int selectedIndex MEMBER m_selectedIndex NOTIFY selectedIndexChanged)
|
Q_PROPERTY(int selectedIndex MEMBER m_selectedIndex NOTIFY selectedIndexChanged)
|
||||||
Q_PROPERTY(bool shadersUpToDate READ shadersUpToDate WRITE setShadersUpToDate NOTIFY shadersUpToDateChanged)
|
Q_PROPERTY(bool shadersUpToDate READ shadersUpToDate WRITE setShadersUpToDate NOTIFY shadersUpToDateChanged)
|
||||||
Q_PROPERTY(QString qmlComponentString READ qmlComponentString)
|
Q_PROPERTY(QString qmlComponentString READ qmlComponentString)
|
||||||
|
Q_PROPERTY(QString currentComposition READ currentComposition WRITE setCurrentComposition NOTIFY currentCompositionChanged)
|
||||||
|
|
||||||
public:
|
public:
|
||||||
EffectMakerModel(QObject *parent = nullptr);
|
EffectMakerModel(QObject *parent = nullptr);
|
||||||
@@ -86,6 +85,11 @@ public:
|
|||||||
Q_INVOKABLE void exportComposition(const QString &name);
|
Q_INVOKABLE void exportComposition(const QString &name);
|
||||||
Q_INVOKABLE void exportResources(const QString &name);
|
Q_INVOKABLE void exportResources(const QString &name);
|
||||||
|
|
||||||
|
void openComposition(const QString &path);
|
||||||
|
|
||||||
|
QString currentComposition() const;
|
||||||
|
void setCurrentComposition(const QString &newCurrentComposition);
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void isEmptyChanged();
|
void isEmptyChanged();
|
||||||
void selectedIndexChanged(int idx);
|
void selectedIndexChanged(int idx);
|
||||||
@@ -93,6 +97,8 @@ signals:
|
|||||||
void shadersUpToDateChanged();
|
void shadersUpToDateChanged();
|
||||||
void shadersBaked();
|
void shadersBaked();
|
||||||
|
|
||||||
|
void currentCompositionChanged();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
enum Roles {
|
enum Roles {
|
||||||
NameRole = Qt::UserRole + 1,
|
NameRole = Qt::UserRole + 1,
|
||||||
@@ -138,8 +144,6 @@ private:
|
|||||||
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;
|
QString stripFileFromURL(const QString &urlString) const;
|
||||||
void updateImageWatchers();
|
|
||||||
void clearImageWatchers();
|
|
||||||
QString getQmlEffectString();
|
QString getQmlEffectString();
|
||||||
|
|
||||||
void updateCustomUniforms();
|
void updateCustomUniforms();
|
||||||
@@ -179,7 +183,7 @@ private:
|
|||||||
QString m_previewEffectPropertiesString;
|
QString m_previewEffectPropertiesString;
|
||||||
QString m_qmlComponentString;
|
QString m_qmlComponentString;
|
||||||
bool m_loadComponentImages = true;
|
bool m_loadComponentImages = true;
|
||||||
Utils::FileSystemWatcher m_fileWatcher;
|
QString m_currentComposition;
|
||||||
|
|
||||||
const QRegularExpression m_spaceReg = QRegularExpression("\\s+");
|
const QRegularExpression m_spaceReg = QRegularExpression("\\s+");
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -59,12 +59,15 @@ QmlDesigner::WidgetInfo EffectMakerView::widgetInfo()
|
|||||||
QmlDesigner::WidgetInfo::LeftPane, 0, tr("Effect Maker"));
|
QmlDesigner::WidgetInfo::LeftPane, 0, tr("Effect Maker"));
|
||||||
}
|
}
|
||||||
|
|
||||||
void EffectMakerView::customNotification(const AbstractView * /*view*/,
|
void EffectMakerView::customNotification([[maybe_unused]] const AbstractView *view,
|
||||||
const QString & /*identifier*/,
|
const QString &identifier,
|
||||||
const QList<QmlDesigner::ModelNode> & /*nodeList*/,
|
[[maybe_unused]] const QList<QmlDesigner::ModelNode> &nodeList,
|
||||||
const QList<QVariant> & /*data*/)
|
const QList<QVariant> &data)
|
||||||
{
|
{
|
||||||
// TODO
|
if (identifier == "open_effectmaker_composition" && data.count() > 0) {
|
||||||
|
const QString compositionPath = data[0].toString();
|
||||||
|
m_widget->effectMakerModel()->openComposition(compositionPath);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void EffectMakerView::modelAttached(QmlDesigner::Model *model)
|
void EffectMakerView::modelAttached(QmlDesigner::Model *model)
|
||||||
|
|||||||
@@ -6,13 +6,15 @@
|
|||||||
|
|
||||||
#include "propertyhandler.h"
|
#include "propertyhandler.h"
|
||||||
|
|
||||||
|
#include <modelnodeoperations.h>
|
||||||
|
|
||||||
#include <QColor>
|
#include <QColor>
|
||||||
#include <QJsonObject>
|
#include <QJsonObject>
|
||||||
#include <QVector2D>
|
#include <QVector2D>
|
||||||
|
|
||||||
namespace EffectMaker {
|
namespace EffectMaker {
|
||||||
|
|
||||||
Uniform::Uniform(const QJsonObject &propObj, const QString &qenPath)
|
Uniform::Uniform(const QString &effectName, const QJsonObject &propObj, const QString &qenPath)
|
||||||
: m_qenPath(qenPath)
|
: m_qenPath(qenPath)
|
||||||
{
|
{
|
||||||
QString value, defaultValue, minValue, maxValue;
|
QString value, defaultValue, minValue, maxValue;
|
||||||
@@ -26,9 +28,11 @@ Uniform::Uniform(const QJsonObject &propObj, const QString &qenPath)
|
|||||||
if (m_displayName.isEmpty())
|
if (m_displayName.isEmpty())
|
||||||
m_displayName = m_name;
|
m_displayName = m_name;
|
||||||
|
|
||||||
|
QString resPath;
|
||||||
if (m_type == Type::Sampler) {
|
if (m_type == Type::Sampler) {
|
||||||
|
resPath = getResourcePath(effectName, defaultValue, qenPath);
|
||||||
if (!defaultValue.isEmpty())
|
if (!defaultValue.isEmpty())
|
||||||
defaultValue = getResourcePath(defaultValue);
|
defaultValue = resPath;
|
||||||
if (propObj.contains("enableMipmap"))
|
if (propObj.contains("enableMipmap"))
|
||||||
m_enableMipmap = getBoolValue(propObj.value("enableMipmap"), false);
|
m_enableMipmap = getBoolValue(propObj.value("enableMipmap"), false);
|
||||||
// Update the mipmap property
|
// Update the mipmap property
|
||||||
@@ -39,7 +43,7 @@ Uniform::Uniform(const QJsonObject &propObj, const QString &qenPath)
|
|||||||
if (propObj.contains("value")) {
|
if (propObj.contains("value")) {
|
||||||
value = propObj.value("value").toString();
|
value = propObj.value("value").toString();
|
||||||
if (m_type == Type::Sampler)
|
if (m_type == Type::Sampler)
|
||||||
value = getResourcePath(value);
|
value = resPath;
|
||||||
} else {
|
} else {
|
||||||
// QEN files don't store the current value, so with those use default value
|
// QEN files don't store the current value, so with those use default value
|
||||||
value = defaultValue;
|
value = defaultValue;
|
||||||
@@ -166,9 +170,13 @@ bool Uniform::getBoolValue(const QJsonValue &jsonValue, bool defaultValue)
|
|||||||
|
|
||||||
// Returns the path for a shader resource
|
// Returns the path for a shader resource
|
||||||
// Used with sampler types
|
// Used with sampler types
|
||||||
QString Uniform::getResourcePath(const QString &value) const
|
QString Uniform::getResourcePath(const QString &effectName, const QString &value, const QString &qenPath) const
|
||||||
{
|
{
|
||||||
QString filePath = value;
|
QString filePath = value;
|
||||||
|
if (qenPath.isEmpty()) {
|
||||||
|
const Utils::FilePath effectsResDir = QmlDesigner::ModelNodeOperations::getEffectsImportDirectory();
|
||||||
|
return effectsResDir.pathAppended(effectName).pathAppended(value).toString();
|
||||||
|
} else {
|
||||||
QDir dir(m_qenPath);
|
QDir dir(m_qenPath);
|
||||||
dir.cdUp();
|
dir.cdUp();
|
||||||
QString absPath = dir.absoluteFilePath(filePath);
|
QString absPath = dir.absoluteFilePath(filePath);
|
||||||
@@ -176,6 +184,7 @@ QString Uniform::getResourcePath(const QString &value) const
|
|||||||
absPath = QUrl::fromLocalFile(absPath).toString();
|
absPath = QUrl::fromLocalFile(absPath).toString();
|
||||||
return absPath;
|
return absPath;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Validation and setting values
|
// Validation and setting values
|
||||||
void Uniform::setValueData(const QString &value, const QString &defaultValue,
|
void Uniform::setValueData(const QString &value, const QString &defaultValue,
|
||||||
@@ -300,7 +309,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 == "image")
|
else if (typeString == "sampler2D" || typeString == "image") //TODO: change image to sample2D in all QENs
|
||||||
return Uniform::Type::Sampler;
|
return Uniform::Type::Sampler;
|
||||||
else if (typeString == "define")
|
else if (typeString == "define")
|
||||||
return Uniform::Type::Define;
|
return Uniform::Type::Define;
|
||||||
|
|||||||
@@ -40,7 +40,7 @@ public:
|
|||||||
Define
|
Define
|
||||||
};
|
};
|
||||||
|
|
||||||
Uniform(const QJsonObject &props, const QString &qenPath);
|
Uniform(const QString &effectName, const QJsonObject &props, const QString &qenPath);
|
||||||
|
|
||||||
Type type() const;
|
Type type() const;
|
||||||
QString typeName() const;
|
QString typeName() const;
|
||||||
@@ -78,7 +78,7 @@ signals:
|
|||||||
private:
|
private:
|
||||||
QString mipmapPropertyName(const QString &name) const;
|
QString mipmapPropertyName(const QString &name) const;
|
||||||
bool getBoolValue(const QJsonValue &jsonValue, bool defaultValue);
|
bool getBoolValue(const QJsonValue &jsonValue, bool defaultValue);
|
||||||
QString getResourcePath(const QString &value) const;
|
QString getResourcePath(const QString &effectName, const QString &value, const QString &qenPath) const;
|
||||||
void setValueData(const QString &value, const QString &defaultValue,
|
void setValueData(const QString &value, const QString &defaultValue,
|
||||||
const QString &minValue, const QString &maxValue);
|
const QString &minValue, const QString &maxValue);
|
||||||
|
|
||||||
|
|||||||
@@ -13,6 +13,9 @@
|
|||||||
#include "qmldesignerplugin.h"
|
#include "qmldesignerplugin.h"
|
||||||
#include "theme.h"
|
#include "theme.h"
|
||||||
|
|
||||||
|
#include <extensionsystem/pluginmanager.h>
|
||||||
|
#include <extensionsystem/pluginspec.h>
|
||||||
|
|
||||||
#include <studioquickwidget.h>
|
#include <studioquickwidget.h>
|
||||||
|
|
||||||
#include <coreplugin/fileutils.h>
|
#include <coreplugin/fileutils.h>
|
||||||
@@ -364,8 +367,21 @@ QSet<QString> AssetsLibraryWidget::supportedAssetSuffixes(bool complex)
|
|||||||
return suffixes;
|
return suffixes;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool isEffectMakerActivated()
|
||||||
|
{
|
||||||
|
const QVector<ExtensionSystem::PluginSpec *> specs = ExtensionSystem::PluginManager::plugins();
|
||||||
|
return std::find_if(specs.begin(), specs.end(),
|
||||||
|
[](ExtensionSystem::PluginSpec *spec) {
|
||||||
|
return spec->name() == "EffectMakerNew" && spec->isEffectivelyEnabled();
|
||||||
|
})
|
||||||
|
!= specs.end();
|
||||||
|
}
|
||||||
|
|
||||||
void AssetsLibraryWidget::openEffectMaker(const QString &filePath)
|
void AssetsLibraryWidget::openEffectMaker(const QString &filePath)
|
||||||
{
|
{
|
||||||
|
if (isEffectMakerActivated())
|
||||||
|
m_assetsView->emitCustomNotification("open_effectmaker_composition", {}, {filePath});
|
||||||
|
else
|
||||||
ModelNodeOperations::openEffectMaker(filePath);
|
ModelNodeOperations::openEffectMaker(filePath);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user