1// Copyright (C) 2022 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
3
4#ifndef EFFECTMANAGER_H
5#define EFFECTMANAGER_H
6
7#include <QObject>
8#include <QTemporaryFile>
9#include <QTimer>
10#include <QQmlPropertyMap>
11#include <QFileSystemWatcher>
12#include "uniformmodel.h"
13#include "nodeview.h"
14#include "shaderfeatures.h"
15#include <rhi/qshaderbaker.h>
16#include <QtQuick/private/qquicktextedit_p_p.h>
17#include "addnodemodel.h"
18#include "applicationsettings.h"
19#include "codehelper.h"
20
21// The delay in ms to wait until updating the effect
22const int EFFECT_UPDATE_DELAY = 200;
23
24// This will be used for commandline arguments.
25extern QQmlPropertyMap g_argData;
26
27struct EffectError {
28 Q_GADGET
29 Q_PROPERTY(QString message MEMBER m_message)
30 Q_PROPERTY(int line MEMBER m_line)
31 Q_PROPERTY(int type MEMBER m_type)
32public:
33 QString m_message;
34 int m_line = -1;
35 int m_type = -1;
36};
37
38class EffectManager : public QObject
39{
40 Q_OBJECT
41 Q_PROPERTY(UniformModel *uniformModel READ uniformModel WRITE setUniformModel NOTIFY uniformModelChanged)
42 Q_PROPERTY(NodeView *nodeView READ nodeView WRITE setNodeView NOTIFY nodeViewChanged)
43 Q_PROPERTY(CodeHelper *codeHelper READ codeHelper CONSTANT)
44 Q_PROPERTY(QString fragmentShader READ fragmentShader WRITE setFragmentShader NOTIFY fragmentShaderChanged)
45 Q_PROPERTY(QString vertexShader READ vertexShader WRITE setVertexShader NOTIFY vertexShaderChanged)
46 Q_PROPERTY(QString fragmentShaderFilename READ fragmentShaderFilename WRITE setFragmentShaderFilename NOTIFY fragmentShaderFilenameChanged)
47 Q_PROPERTY(QString vertexShaderFilename READ vertexShaderFilename WRITE setVertexShaderFilename NOTIFY vertexShaderFilenameChanged)
48 Q_PROPERTY(QString qmlComponentString READ qmlComponentString WRITE setQmlComponentString NOTIFY qmlComponentStringChanged)
49
50 Q_PROPERTY(EffectError effectError READ effectError NOTIFY effectErrorChanged)
51 Q_PROPERTY(bool unsavedChanges READ unsavedChanges WRITE setUnsavedChanges NOTIFY unsavedChangesChanged)
52 Q_PROPERTY(bool hasProjectFilename READ hasProjectFilename NOTIFY hasProjectFilenameChanged)
53 Q_PROPERTY(QString projectName READ projectName NOTIFY projectNameChanged)
54 Q_PROPERTY(QString projectFilename READ projectFilename NOTIFY projectFilenameChanged)
55 Q_PROPERTY(QString projectDirectory READ projectDirectory NOTIFY projectDirectoryChanged)
56 Q_PROPERTY(QString exportFilename READ exportFilename NOTIFY exportFilenameChanged)
57 Q_PROPERTY(QString exportDirectory READ exportDirectory NOTIFY exportDirectoryChanged)
58 Q_PROPERTY(int exportFlags READ exportFlags NOTIFY exportFlagsChanged)
59 Q_PROPERTY(bool shadersUpToDate READ shadersUpToDate WRITE setShadersUpToDate NOTIFY shadersUpToDateChanged)
60 Q_PROPERTY(bool autoPlayEffect READ autoPlayEffect WRITE setAutoPlayEffect NOTIFY autoPlayEffectChanged)
61 Q_PROPERTY(AddNodeModel *addNodeModel READ addNodeModel NOTIFY addNodeModelChanged)
62 Q_PROPERTY(QRect effectPadding READ effectPadding WRITE setEffectPadding NOTIFY effectPaddingChanged)
63 Q_PROPERTY(QString effectHeadings READ effectHeadings WRITE setEffectHeadings NOTIFY effectHeadingsChanged)
64 Q_PROPERTY(ApplicationSettings * settings READ settings NOTIFY settingsChanged)
65 QML_ELEMENT
66
67public:
68 explicit EffectManager(QObject *parent = nullptr);
69
70 UniformModel *uniformModel() const;
71 void setUniformModel(UniformModel *newUniformModel);
72
73 CodeHelper *codeHelper() const;
74
75 QString fragmentShader() const;
76 void setFragmentShader(const QString &newFragmentShader);
77
78 QString vertexShader() const;
79 void setVertexShader(const QString &newVertexShader);
80
81 bool unsavedChanges() const;
82 void setUnsavedChanges(bool newUnsavedChanges);
83
84 bool hasProjectFilename() const;
85 QString projectFilename() const;
86 QString projectName() const;
87 void setProjectName(const QString &name);
88 QString projectDirectory() const;
89 QString exportFilename() const;
90 QString exportDirectory() const;
91 int exportFlags() const;
92
93 NodeView *nodeView() const;
94 void setNodeView(NodeView *newNodeView);
95
96 EffectError effectError() const;
97
98 const QString &fragmentShaderFilename() const;
99 void setFragmentShaderFilename(const QString &newFragmentShaderFilename);
100
101 const QString &vertexShaderFilename() const;
102 void setVertexShaderFilename(const QString &newVertexShaderFilename);
103
104 const QString &qmlComponentString() const;
105 void setQmlComponentString(const QString &string);
106
107 bool shadersUpToDate() const;
108 void setShadersUpToDate(bool upToDate);
109
110 bool autoPlayEffect() const;
111 void setAutoPlayEffect(bool autoPlay);
112
113 AddNodeModel *addNodeModel() const;
114
115 const QRect &effectPadding() const;
116 QString effectHeadings() const;
117
118 ApplicationSettings *settings() const {
119 return m_settings;
120 }
121
122 Q_INVOKABLE QString mipmapPropertyName(const QString &name) const;
123 Q_INVOKABLE QString getSupportedImageFormatsFilter() const;
124
125 Q_INVOKABLE int effectUpdateDelay() const {
126 return EFFECT_UPDATE_DELAY;
127 }
128
129public Q_SLOTS:
130 QString generateVertexShader(bool includeUniforms = true);
131 QString generateFragmentShader(bool includeUniforms = true);
132 void updateQmlComponent();
133 void initialize();
134 NodesModel::Node loadEffectNode(const QString &filename);
135 bool addEffectNode(const QString &filename, int startNodeId = -1, int endNodeId = -1);
136 bool deleteEffectNodes(QList<int> nodeIds);
137 bool loadProject(const QUrl &filename);
138 bool saveProject(const QUrl &filename = QString());
139 bool newProject(const QString &filepath, const QString &filename, bool clearNodeView, bool createProjectDir = false);
140 void closeProject();
141 bool exportEffect(const QString &dirPath, const QString &filename, int exportFlags, int qsbVersionIndex);
142 void cleanupProject();
143 void cleanupNodeView(bool initialize = true);
144 bool saveSelectedNode(const QUrl &filename);
145 void updateBakedShaderVersions();
146 void bakeShaders(bool forced = false);
147
148 QString getHelpTextString();
149 void updateAddNodeData();
150 void showHideAddNodeGroup(const QString &groupName, bool show);
151 void refreshAddNodesList();
152 void setEffectPadding(const QRect &newEffectPadding);
153 void setEffectHeadings(const QString &newEffectHeadings);
154 QString stripFileFromURL(const QString &urlString) const;
155 QString addFileToURL(const QString &urlString) const;
156 QString getDirectory(const QString &path, bool useFileScheme = true) const;
157 QString getDefaultImagesDirectory(bool useFileScheme = true) const;
158 void autoIndentCurrentCode(int codeTab, const QString &code);
159 bool processKey(int codeTab, int keyCode, int modifiers, QQuickTextEdit *textEdit);
160 void setEffectError(const QString &errorMessage, int type = -1, int lineNumber = -1);
161 void resetEffectError(int type = -1);
162
163signals:
164 void uniformModelChanged();
165 void fragmentShaderChanged();
166 void vertexShaderChanged();
167 void unsavedChangesChanged();
168 void hasProjectFilenameChanged();
169 void projectFilenameChanged();
170 void projectNameChanged();
171 void projectDirectoryChanged();
172 void exportFilenameChanged();
173 void exportDirectoryChanged();
174 void exportFlagsChanged();
175 void shadersBaked();
176
177 void nodeViewChanged();
178 void effectErrorChanged();
179
180 void fragmentShaderFilenameChanged();
181 void vertexShaderFilenameChanged();
182 void qmlComponentStringChanged();
183 void shadersUpToDateChanged();
184 void autoPlayEffectChanged();
185 void addNodeModelChanged();
186
187 void effectPaddingChanged();
188 void effectHeadingsChanged();
189 void settingsChanged();
190
191private:
192 friend class AddNodeModel;
193 friend class ApplicationSettings;
194
195 enum ExportFlags {
196 QMLComponent = 1,
197 QSBShaders = 2,
198 TextShaders = 4,
199 Images = 8,
200 QRCFile = 16
201 };
202
203 enum ErrorTypes {
204 ErrorCommon = -1,
205 ErrorQMLParsing,
206 ErrorVert,
207 ErrorFrag,
208 ErrorQMLRuntime,
209 ErrorPreprocessor
210 };
211
212 const QString getBufUniform();
213 const QString getFSUniforms();
214 const QString getVSUniforms();
215 const QString getDefineProperties();
216 const QString getConstVariables();
217 void updateCustomUniforms();
218 QString getQmlImagesString(bool localFiles);
219 QString getQmlComponentString(bool localFiles);
220 QString getQmlEffectString();
221 QStringList getDefaultRootVertexShader();
222 QStringList getDefaultRootFragmentShader();
223 QString processVertexRootLine(const QString &line);
224 QString processFragmentRootLine(const QString &line);
225 QString getCustomShaderVaryings(bool outState);
226 QStringList removeTagsFromCode(const QStringList &codeLines);
227 QString removeTagsFromCode(const QString &code);
228 QString replaceOldTagsWithNew(const QString &code);
229 QString detectErrorMessage(const QString &errorMessage);
230
231 void doBakeShaders();
232 QFile resolveFileFromUrl(const QUrl &fileUrl);
233 bool createNodeFromJson(const QJsonObject &rootJson, NodesModel::Node &node, bool fullNode, const QString &nodePath);
234 bool addNodeIntoView(NodesModel::Node &node, int startNodeId = -1, int endNodeId = -1);
235 bool addNodeConnection(int startNodeId, int endNodeId);
236 int getTagIndex(const QStringList &code, const QString &tag);
237 QJsonObject nodeToJson(const NodesModel::Node &node, bool simplified, const QString &nodePath);
238 QString codeFromJsonArray(const QJsonArray &codeArray);
239 QString absoluteToRelativePath(const QString &path, const QString &toPath = QString());
240 QString relativeToAbsolutePath(const QString &path, const QString &toPath = QString());
241 void updateImageWatchers();
242 void clearImageWatchers();
243
244 UniformModel *m_uniformModel = nullptr;
245 UniformModel::UniformTable m_uniformTable;
246 CodeHelper *m_codeHelper = nullptr;
247 QString m_fragmentShader;
248 QString m_vertexShader;
249 QString m_qmlCode;
250 // Used in exported QML, at root of the file
251 QString m_exportedRootPropertiesString;
252 // Used in exported QML, at ShaderEffect component of the file
253 QString m_exportedEffectPropertiesString;
254 // Used in preview QML, at ShaderEffect component of the file
255 QString m_previewEffectPropertiesString;
256 bool m_unsavedChanges = false;
257 bool m_firstBake = true;
258 // Full path of the project file
259 QUrl m_projectFilename;
260 // Path to where project file is located
261 QString m_projectDirectory;
262 // Exported effect name, without the prefixes
263 QString m_exportFilename;
264 // Path to where effect is exported
265 QString m_exportDirectory;
266 // Name of the project
267 // E.g. "MyEffect"
268 QString m_projectName;
269 int m_exportFlags = QMLComponent | QSBShaders | Images;
270
271 QTemporaryFile m_fragmentShaderFile;
272 QTemporaryFile m_vertexShaderFile;
273
274 ApplicationSettings *m_settings = nullptr;
275 QShaderBaker m_baker;
276 NodeView *m_nodeView = nullptr;
277 QMap<int, EffectError> m_effectErrors;
278 QString m_fragmentShaderFilename;
279 QString m_vertexShaderFilename;
280 QString m_qmlComponentString;
281 QStringList m_defaultRootVertexShader;
282 QStringList m_defaultRootFragmentShader;
283 QTimer m_shaderBakerTimer;
284 // True when shaders haven't changed since last baking
285 bool m_shadersUpToDate = true;
286 // When true, shaders are baked automatically after a
287 // short delay when they change.
288 bool m_autoPlayEffect = true;
289 bool m_loadComponentImages = true;
290
291 ShaderFeatures m_shaderFeatures;
292 AddNodeModel *m_addNodeModel = nullptr;
293 QStringList m_shaderVaryingVariables;
294 QRect m_effectPadding;
295 QString m_effectHeadings;
296 QFileSystemWatcher m_fileWatcher;
297};
298
299#endif // EFFECTMANAGER_H
300

source code of qtquickeffectmaker/tools/qqem/effectmanager.h