1 | // Copyright (C) 2021 The Qt Company Ltd. |
2 | // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only |
3 | |
4 | #include "uniformmodel.h" |
5 | |
6 | QT_BEGIN_NAMESPACE |
7 | |
8 | UniformModel::UniformModel(QObject *parent) |
9 | : QAbstractListModel(parent) |
10 | { |
11 | |
12 | } |
13 | |
14 | void UniformModel::setModelData(UniformTable *data) |
15 | { |
16 | beginResetModel(); |
17 | m_uniformTable = data; |
18 | endResetModel(); |
19 | } |
20 | |
21 | int UniformModel::rowCount(const QModelIndex &) const |
22 | { |
23 | return int((m_uniformTable != nullptr) ? m_uniformTable->size() : 0); |
24 | } |
25 | |
26 | QVariant UniformModel::data(const QModelIndex &index, int role) const |
27 | { |
28 | if (!m_uniformTable || !index.isValid()) |
29 | return QVariant(); |
30 | |
31 | if (index.row() >= m_uniformTable->size()) |
32 | return false; |
33 | |
34 | const auto &uniform = (*m_uniformTable)[index.row()]; |
35 | |
36 | if (role == Type) { |
37 | return QVariant::fromValue(value: uniform.type); |
38 | } else if (role == Name) { |
39 | return QVariant::fromValue(value: QString::fromLatin1(ba: uniform.name)); |
40 | } else if (role == Value) { |
41 | switch (uniform.type) { |
42 | case CustomMaterial::Uniform::Type::Sampler: |
43 | return QVariant::fromValue(value: uniform.imagePath); |
44 | case CustomMaterial::Uniform::Type::Bool: |
45 | return QVariant::fromValue(value: uniform.b); |
46 | case CustomMaterial::Uniform::Type::Int: |
47 | return QVariant::fromValue(value: uniform.i); |
48 | case CustomMaterial::Uniform::Type::Float: |
49 | return QVariant::fromValue(value: uniform.f); |
50 | case CustomMaterial::Uniform::Type::Vec2: |
51 | return QVariant::fromValue(value: uniform.vec2); |
52 | case CustomMaterial::Uniform::Type::Vec3: |
53 | return QVariant::fromValue(value: uniform.vec3); |
54 | case CustomMaterial::Uniform::Type::Vec4: |
55 | return QVariant::fromValue(value: uniform.vec4); |
56 | case CustomMaterial::Uniform::Type::Mat44: |
57 | return QVariant::fromValue(value: uniform.m44); |
58 | case CustomMaterial::Uniform::Type::Last: |
59 | break; |
60 | } |
61 | } |
62 | |
63 | return QVariant(); |
64 | } |
65 | |
66 | QHash<int, QByteArray> UniformModel::roleNames() const |
67 | { |
68 | QHash<int, QByteArray> roles; |
69 | roles[Type] = "type" ; |
70 | roles[Name] = "name" ; |
71 | roles[Value] = "value" ; |
72 | return roles; |
73 | } |
74 | |
75 | bool UniformModel::setData(const QModelIndex &index, const QVariant &value, int role) |
76 | { |
77 | if (!index.isValid() || !m_uniformTable) |
78 | return false; |
79 | |
80 | if (index.row() >= m_uniformTable->size()) |
81 | return false; |
82 | |
83 | auto &uniform = (*m_uniformTable)[index.row()]; |
84 | |
85 | bool ok = true; |
86 | |
87 | if (role == Type) { |
88 | const auto v = value.toInt(ok: &ok); |
89 | if (ok) |
90 | uniform.type = static_cast<CustomMaterial::Uniform::Type>(v); |
91 | } else if (role == Name) { |
92 | uniform.name = value.toString().toUtf8(); |
93 | } else if (role == Value) { |
94 | switch (uniform.type) { |
95 | case CustomMaterial::Uniform::Type::Bool: |
96 | uniform.b = value.toBool(); |
97 | break; |
98 | case CustomMaterial::Uniform::Type::Int: |
99 | uniform.i = value.toInt(); |
100 | break; |
101 | case CustomMaterial::Uniform::Type::Float: |
102 | uniform.f = value.toFloat(); |
103 | break; |
104 | case CustomMaterial::Uniform::Type::Vec2: |
105 | uniform.vec2 = value.value<QVector2D>(); |
106 | break; |
107 | case CustomMaterial::Uniform::Type::Vec3: |
108 | uniform.vec3 = value.value<QVector3D>(); |
109 | break; |
110 | case CustomMaterial::Uniform::Type::Vec4: |
111 | uniform.vec4 = value.value<QVector4D>(); |
112 | break; |
113 | case CustomMaterial::Uniform::Type::Mat44: |
114 | uniform.m44 = value.value<QMatrix4x4>(); |
115 | break; |
116 | case CustomMaterial::Uniform::Type::Sampler: |
117 | uniform.imagePath = value.toUrl().path(); |
118 | break; |
119 | case CustomMaterial::Uniform::Type::Last: |
120 | break; |
121 | } |
122 | } |
123 | |
124 | |
125 | if (ok) |
126 | emit dataChanged(topLeft: index, bottomRight: index, roles: {role}); |
127 | |
128 | return ok; |
129 | } |
130 | |
131 | bool UniformModel::insertRow(int rowIndex, int type, const QString &id) |
132 | { |
133 | if (m_uniformTable == nullptr) |
134 | return false; |
135 | |
136 | if (!validateUniformName(uniformName: id)) |
137 | return false; |
138 | |
139 | |
140 | beginInsertRows(parent: QModelIndex(), first: rowIndex, last: rowIndex); |
141 | |
142 | CustomMaterial::Uniform uniform = { }; |
143 | uniform.type = CustomMaterial::Uniform::Type(type); |
144 | uniform.name = id.toLocal8Bit(); |
145 | switch (uniform.type) { |
146 | case CustomMaterial::Uniform::Type::Bool: |
147 | uniform.b = false; |
148 | break; |
149 | case CustomMaterial::Uniform::Type::Int: |
150 | uniform.i = 0; |
151 | break; |
152 | case CustomMaterial::Uniform::Type::Float: |
153 | uniform.f = 0.0f; |
154 | break; |
155 | case CustomMaterial::Uniform::Type::Vec2: |
156 | uniform.vec2 = QVector2D(); |
157 | break; |
158 | case CustomMaterial::Uniform::Type::Vec3: |
159 | uniform.vec3 = QVector3D(); |
160 | break; |
161 | case CustomMaterial::Uniform::Type::Vec4: |
162 | uniform.vec4 = QVector4D(); |
163 | break; |
164 | case CustomMaterial::Uniform::Type::Mat44: |
165 | uniform.m44 = QMatrix4x4(); |
166 | break; |
167 | case CustomMaterial::Uniform::Type::Sampler: |
168 | uniform.imagePath = QString(); |
169 | break; |
170 | case CustomMaterial::Uniform::Type::Last: |
171 | Q_UNREACHABLE(); |
172 | break; |
173 | } |
174 | |
175 | m_uniformTable->insert(i: rowIndex, t: uniform); |
176 | |
177 | endInsertRows(); |
178 | |
179 | emit dataChanged(topLeft: QAbstractItemModel::createIndex(arow: 0, acolumn: 0), |
180 | bottomRight: QAbstractItemModel::createIndex(arow: rowIndex, acolumn: 0)); |
181 | return true; |
182 | } |
183 | |
184 | void UniformModel::removeRow(int rowIndex, int rows) |
185 | { |
186 | if (m_uniformTable == nullptr) |
187 | return; |
188 | |
189 | if (m_uniformTable->size() > rowIndex) { |
190 | rows = qBound(min: 1, val: rows, max: m_uniformTable->size()); |
191 | beginRemoveRows(parent: QModelIndex(), first: rowIndex, last: rowIndex + rows - 1); |
192 | m_uniformTable->remove(i: rowIndex, n: rows); |
193 | endRemoveRows(); |
194 | emit dataChanged(topLeft: QAbstractItemModel::createIndex(arow: 0, acolumn: 0), |
195 | bottomRight: QAbstractItemModel::createIndex(arow: rowIndex, acolumn: 0)); |
196 | } |
197 | } |
198 | |
199 | bool UniformModel::validateUniformName(const QString &uniformName) |
200 | { |
201 | if (!m_uniformTable) |
202 | return false; |
203 | |
204 | // must be unique |
205 | for (const auto &uniform : *m_uniformTable) |
206 | { |
207 | if (uniform.name == uniformName) |
208 | return false; |
209 | } |
210 | |
211 | // TODO: There are probably some other requirments |
212 | |
213 | return true; |
214 | } |
215 | |
216 | QT_END_NAMESPACE |
217 | |
218 | |
219 | |