aboutsummaryrefslogtreecommitdiffstats
path: root/src/plugins/effectmakernew/effectmakermodel.h
blob: 96eb0e19b462fdfbe259f8f11c0296d9430201fb (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
// Copyright (C) 2023 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0

#pragma once

#include "shaderfeatures.h"

#include <utils/filepath.h>

#include <QFileSystemWatcher>
#include <QMap>
#include <QRegularExpression>
#include <QStandardItemModel>
#include <QTemporaryFile>

namespace ProjectExplorer {
class Target;
}

namespace Utils {
class Process;
}

namespace EffectMaker {

class CompositionNode;
class Uniform;

struct EffectError {
    Q_GADGET
    Q_PROPERTY(QString message MEMBER m_message)
    Q_PROPERTY(int line MEMBER m_line)
    Q_PROPERTY(int type MEMBER m_type)

public:
    QString m_message;
    int m_line = -1;
    int m_type = -1;
};

class EffectMakerModel : public QAbstractListModel
{
    Q_OBJECT

    Q_PROPERTY(bool isEmpty MEMBER m_isEmpty NOTIFY isEmptyChanged)
    Q_PROPERTY(int selectedIndex MEMBER m_selectedIndex NOTIFY selectedIndexChanged)
    Q_PROPERTY(bool shadersUpToDate READ shadersUpToDate WRITE setShadersUpToDate NOTIFY shadersUpToDateChanged)
    Q_PROPERTY(QString qmlComponentString READ qmlComponentString)
    Q_PROPERTY(QString currentComposition READ currentComposition WRITE setCurrentComposition NOTIFY currentCompositionChanged)

public:
    EffectMakerModel(QObject *parent = nullptr);

    QHash<int, QByteArray> roleNames() const override;
    int rowCount(const QModelIndex & parent = QModelIndex()) const override;
    QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
    bool setData(const QModelIndex &index, const QVariant &value, int role) override;

    bool isEmpty() const { return m_isEmpty; }
    void setIsEmpty(bool val);

    void addNode(const QString &nodeQenPath);

    Q_INVOKABLE void moveNode(int fromIdx, int toIdx);
    Q_INVOKABLE void removeNode(int idx);

    bool shadersUpToDate() const;
    void setShadersUpToDate(bool newShadersUpToDate);

    QString fragmentShader() const;
    void setFragmentShader(const QString &newFragmentShader);

    QString vertexShader() const;
    void setVertexShader(const QString &newVertexShader);

    const QString &qmlComponentString() const;

    void clear();

    Q_INVOKABLE void updateQmlComponent();

    Q_INVOKABLE void resetEffectError(int type);
    Q_INVOKABLE void setEffectError(const QString &errorMessage, int type = -1, int lineNumber = -1);

    Q_INVOKABLE void exportComposition(const QString &name);
    Q_INVOKABLE void exportResources(const QString &name);

    void openComposition(const QString &path);

    QString currentComposition() const;
    void setCurrentComposition(const QString &newCurrentComposition);

signals:
    void isEmptyChanged();
    void selectedIndexChanged(int idx);
    void effectErrorChanged();
    void shadersUpToDateChanged();
    void shadersBaked();

    void currentCompositionChanged();

private:
    enum Roles {
        NameRole = Qt::UserRole + 1,
        EnabledRole,
        UniformsRole
    };

    enum ErrorTypes {
        ErrorCommon = -1,
        ErrorQMLParsing,
        ErrorVert,
        ErrorFrag,
        ErrorQMLRuntime,
        ErrorPreprocessor
    };

    bool isValidIndex(int idx) const;

    const QList<Uniform *> allUniforms();

    const QString getBufUniform();
    const QString getVSUniforms();
    const QString getFSUniforms();

    QString detectErrorMessage(const QString &errorMessage);
    EffectError effectError() const;

    QString valueAsString(const Uniform &uniform);
    QString valueAsBinding(const Uniform &uniform);
    QString valueAsVariable(const Uniform &uniform);
    QString getImageElementName(const Uniform &uniform);
    const QString getConstVariables();
    const QString getDefineProperties();
    int getTagIndex(const QStringList &code, const QString &tag);
    QString processVertexRootLine(const QString &line);
    QString processFragmentRootLine(const QString &line);
    QStringList getDefaultRootVertexShader();
    QStringList getDefaultRootFragmentShader();
    QStringList removeTagsFromCode(const QStringList &codeLines);
    QString removeTagsFromCode(const QString &code);
    QString getCustomShaderVaryings(bool outState);
    QString generateVertexShader(bool includeUniforms = true);
    QString generateFragmentShader(bool includeUniforms = true);
    void handleQsbProcessExit(Utils::Process *qsbProcess, const QString &shader);
    QString stripFileFromURL(const QString &urlString) const;
    QString getQmlEffectString();

    void updateCustomUniforms();
    void createFiles();
    void bakeShaders();

    QString mipmapPropertyName(const QString &name) const;
    QString getQmlImagesString(bool localFiles);
    QString getQmlComponentString(bool localFiles);

    QList<CompositionNode *> m_nodes;

    int m_selectedIndex = -1;
    bool m_isEmpty = true;
    // True when shaders haven't changed since last baking
    bool m_shadersUpToDate = true;
    int m_remainingQsbTargets = 0;
    QMap<int, EffectError> m_effectErrors;
    ShaderFeatures m_shaderFeatures;
    QStringList m_shaderVaryingVariables;
    QString m_fragmentShader;
    QString m_vertexShader;
    QStringList m_defaultRootVertexShader;
    QStringList m_defaultRootFragmentShader;
    // Temp files to store shaders sources and binary data
    QTemporaryFile m_fragmentSourceFile;
    QTemporaryFile m_vertexSourceFile;
    QString m_fragmentSourceFilename;
    QString m_vertexSourceFilename;
    QString m_fragmentShaderFilename;
    QString m_vertexShaderFilename;
    // Used in exported QML, at root of the file
    QString m_exportedRootPropertiesString;
    // Used in exported QML, at ShaderEffect component of the file
    QString m_exportedEffectPropertiesString;
    // Used in preview QML, at ShaderEffect component of the file
    QString m_previewEffectPropertiesString;
    QString m_qmlComponentString;
    bool m_loadComponentImages = true;
    QString m_currentComposition;

    const QRegularExpression m_spaceReg = QRegularExpression("\\s+");
};

} // namespace EffectMaker