1// Copyright (C) 2022 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
3
4#include "uniformmodel.h"
5#include "propertyhandler.h"
6#include "effectmanager.h"
7
8UniformModel::UniformModel(QObject *parent)
9 : QAbstractListModel(parent)
10{
11
12}
13
14void UniformModel::setModelData(UniformTable *data)
15{
16 beginResetModel();
17 m_uniformTable = data;
18 endResetModel();
19 updateCanMoveStatus();
20 Q_EMIT uniformsChanged();
21}
22
23int UniformModel::rowCount(const QModelIndex &) const
24{
25 return int((m_uniformTable != nullptr) ? m_uniformTable->size() : 0);
26}
27
28QVariant UniformModel::data(const QModelIndex &index, int role) const
29{
30 if (!m_uniformTable || !index.isValid())
31 return QVariant();
32
33 if (index.row() >= m_uniformTable->size())
34 return false;
35
36 const auto &uniform = (*m_uniformTable)[index.row()];
37
38 if (role == Type) {
39 return QVariant::fromValue(value: uniform.type);
40 } else if (role == NodeId) {
41 return QVariant::fromValue(value: uniform.nodeId);
42 } else if (role == Name) {
43 return QVariant::fromValue(value: QString::fromLatin1(ba: uniform.name));
44 } else if (role == Value) {
45 switch (uniform.type) {
46 case Uniform::Type::Sampler:
47 return uniform.value.value<QString>();
48 case Uniform::Type::Bool:
49 return uniform.value.value<bool>();
50 case Uniform::Type::Int:
51 return uniform.value.value<int>();
52 case Uniform::Type::Float:
53 return uniform.value.value<double>();
54 case Uniform::Type::Vec2:
55 return uniform.value.value<QVector2D>();
56 case Uniform::Type::Vec3:
57 return uniform.value.value<QVector3D>();
58 case Uniform::Type::Vec4:
59 return uniform.value.value<QVector4D>();
60 case Uniform::Type::Color:
61 return uniform.value.value<QColor>();
62 case Uniform::Type::Define:
63 return uniform.value.value<QString>();
64 }
65 } else if (role == DefaultValue) {
66 switch (uniform.type) {
67 case Uniform::Type::Sampler:
68 return uniform.defaultValue.value<QString>();
69 case Uniform::Type::Bool:
70 return uniform.defaultValue.value<bool>();
71 case Uniform::Type::Int:
72 return uniform.defaultValue.value<int>();
73 case Uniform::Type::Float:
74 return uniform.defaultValue.value<double>();
75 case Uniform::Type::Vec2:
76 return uniform.defaultValue.value<QVector2D>();
77 case Uniform::Type::Vec3:
78 return uniform.defaultValue.value<QVector3D>();
79 case Uniform::Type::Vec4:
80 return uniform.defaultValue.value<QVector4D>();
81 case Uniform::Type::Color:
82 return uniform.defaultValue.value<QColor>();
83 case Uniform::Type::Define:
84 return uniform.defaultValue.value<QString>();
85 }
86 } else if (role == MinValue) {
87 switch (uniform.type) {
88 case Uniform::Type::Sampler:
89 return uniform.minValue.value<QString>();
90 case Uniform::Type::Bool:
91 return uniform.minValue.value<bool>();
92 case Uniform::Type::Int:
93 return uniform.minValue.value<int>();
94 case Uniform::Type::Float:
95 return uniform.minValue.value<double>();
96 case Uniform::Type::Vec2:
97 return uniform.minValue.value<QVector2D>();
98 case Uniform::Type::Vec3:
99 return uniform.minValue.value<QVector3D>();
100 case Uniform::Type::Vec4:
101 return uniform.minValue.value<QVector4D>();
102 case Uniform::Type::Color:
103 return uniform.minValue.value<QColor>();
104 case Uniform::Type::Define:
105 return uniform.minValue.value<QString>();
106 }
107 } else if (role == MaxValue) {
108 switch (uniform.type) {
109 case Uniform::Type::Sampler:
110 return uniform.maxValue.value<QString>();
111 case Uniform::Type::Bool:
112 return uniform.maxValue.value<bool>();
113 case Uniform::Type::Int:
114 return uniform.maxValue.value<int>();
115 case Uniform::Type::Float:
116 return uniform.maxValue.value<double>();
117 case Uniform::Type::Vec2:
118 return uniform.maxValue.value<QVector2D>();
119 case Uniform::Type::Vec3:
120 return uniform.maxValue.value<QVector3D>();
121 case Uniform::Type::Vec4:
122 return uniform.maxValue.value<QVector4D>();
123 case Uniform::Type::Color:
124 return uniform.maxValue.value<QColor>();
125 case Uniform::Type::Define:
126 return uniform.maxValue.value<QString>();
127 }
128 } else if (role == Description) {
129 return QVariant::fromValue(value: uniform.description);
130 } else if (role == CustomValue) {
131 return QVariant::fromValue(value: uniform.customValue);
132 } else if (role == UseCustomValue) {
133 return QVariant::fromValue(value: uniform.useCustomValue);
134 } else if (role == Visible) {
135 return QVariant::fromValue(value: uniform.visible);
136 } else if (role == ExportProperty) {
137 return QVariant::fromValue(value: uniform.exportProperty);
138 } else if (role == CanMoveUp) {
139 return QVariant::fromValue(value: uniform.canMoveUp);
140 } else if (role == CanMoveDown) {
141 return QVariant::fromValue(value: uniform.canMoveDown);
142 } else if (role == EnableMipmap) {
143 return QVariant::fromValue(value: uniform.enableMipmap);
144 } else if (role == ExportImage) {
145 return QVariant::fromValue(value: uniform.exportImage);
146 }
147
148 return QVariant();
149}
150
151QHash<int, QByteArray> UniformModel::roleNames() const
152{
153 QHash<int, QByteArray> roles;
154 roles[Type] = "type";
155 roles[Name] = "name";
156 roles[Value] = "value";
157 roles[DefaultValue] = "defaultValue";
158 roles[MinValue] = "minValue";
159 roles[MaxValue] = "maxValue";
160 roles[NodeId] = "nodeId";
161 roles[Description] = "description";
162 roles[CustomValue] = "customValue";
163 roles[UseCustomValue] = "useCustomValue";
164 roles[Visible] = "visible";
165 roles[ExportProperty] = "exportProperty";
166 roles[CanMoveUp] = "canMoveUp";
167 roles[CanMoveDown] = "canMoveDown";
168 roles[EnableMipmap] = "enableMipmap";
169 roles[ExportImage] = "exportImage";
170 return roles;
171}
172
173bool UniformModel::setData(const QModelIndex &index, const QVariant &value, int role)
174{
175 if (!index.isValid() || !m_uniformTable)
176 return false;
177
178 if (index.row() >= m_uniformTable->size())
179 return false;
180
181 auto &uniform = (*m_uniformTable)[index.row()];
182
183 bool ok = true;
184
185 if (role == Type) {
186 const auto v = value.toInt(ok: &ok);
187 if (ok)
188 uniform.type = static_cast<Uniform::Type>(v);
189 } else if (role == Name) {
190 uniform.name = value.toString().toUtf8();
191 } else if (role == Value) {
192 switch (uniform.type) {
193 case Uniform::Type::Bool:
194 case Uniform::Type::Int:
195 case Uniform::Type::Float:
196 case Uniform::Type::Vec2:
197 case Uniform::Type::Vec3:
198 case Uniform::Type::Vec4:
199 case Uniform::Type::Color:
200 case Uniform::Type::Sampler:
201 case Uniform::Type::Define:
202 uniform.value = value;
203 break;
204 }
205 } else if (role == DefaultValue) {
206 switch (uniform.type) {
207 case Uniform::Type::Bool:
208 case Uniform::Type::Int:
209 case Uniform::Type::Float:
210 case Uniform::Type::Vec2:
211 case Uniform::Type::Vec3:
212 case Uniform::Type::Vec4:
213 case Uniform::Type::Color:
214 case Uniform::Type::Sampler:
215 case Uniform::Type::Define:
216 uniform.defaultValue = value;
217 break;
218 }
219 } else if (role == MinValue) {
220 switch (uniform.type) {
221 case Uniform::Type::Bool:
222 case Uniform::Type::Int:
223 case Uniform::Type::Float:
224 case Uniform::Type::Vec2:
225 case Uniform::Type::Vec3:
226 case Uniform::Type::Vec4:
227 case Uniform::Type::Color:
228 case Uniform::Type::Sampler:
229 case Uniform::Type::Define:
230 uniform.minValue = value;
231 break;
232 }
233 } else if (role == MaxValue) {
234 switch (uniform.type) {
235 case Uniform::Type::Bool:
236 case Uniform::Type::Int:
237 case Uniform::Type::Float:
238 case Uniform::Type::Vec2:
239 case Uniform::Type::Vec3:
240 case Uniform::Type::Vec4:
241 case Uniform::Type::Color:
242 case Uniform::Type::Sampler:
243 case Uniform::Type::Define:
244 uniform.maxValue = value;
245 break;
246 }
247 } else if (role == Description) {
248 uniform.description = value.toString();
249 } else if (role == CustomValue) {
250 uniform.customValue = value.toString();
251 } else if (role == UseCustomValue) {
252 uniform.useCustomValue = value.toBool();
253 } else if (role == ExportProperty) {
254 uniform.exportProperty = value.toBool();
255 } else if (role == CanMoveUp) {
256 uniform.canMoveUp = value.toBool();
257 } else if (role == CanMoveDown) {
258 uniform.canMoveDown = value.toBool();
259 } else if (role == EnableMipmap) {
260 uniform.enableMipmap = value.toBool();
261 } else if (role == ExportImage) {
262 uniform.exportImage = value.toBool();
263 }
264
265 if (role == Value) {
266 // Don't update uniforms when value is changed, as those
267 // go through g_propertyData
268 g_propertyData.insert(key: uniform.name, value);
269 if (m_effectManager)
270 m_effectManager->setUnsavedChanges(true);
271 }
272 if (role != Value || !uniform.exportProperty) {
273 // But non-exported (const value) properties need update
274 Q_EMIT uniformsChanged();
275 }
276
277 if (ok)
278 emit dataChanged(topLeft: index, bottomRight: index, roles: {role});
279
280 return ok;
281}
282
283// Initialize the value variant with correct type
284QVariant UniformModel::getInitializedVariant(Uniform::Type type, bool maxValue)
285{
286 switch (type) {
287 case Uniform::Type::Sampler:
288 return QString();
289 case Uniform::Type::Bool:
290 return maxValue ? true : false;
291 case Uniform::Type::Int:
292 return maxValue ? 100 : 0;
293 case Uniform::Type::Float:
294 return maxValue ? 1.0 : 0.0;
295 case Uniform::Type::Vec2:
296 return maxValue ? QVector2D(1.0, 1.0) : QVector2D(0.0, 0.0);
297 case Uniform::Type::Vec3:
298 return maxValue ? QVector3D(1.0, 1.0, 1.0) : QVector3D(0.0, 0.0, 0.0);
299 case Uniform::Type::Vec4:
300 return maxValue ? QVector4D(1.0, 1.0, 1.0, 1.0) : QVector4D(0.0, 0.0, 0.0, 0.0);
301 case Uniform::Type::Color:
302 return maxValue ? QColor::fromRgbF(r: 1.0f, g: 1.0f, b: 1.0f, a: 1.0f) : QColor::fromRgbF(r: 0.0f, g: 0.0f, b: 0.0f, a: 0.0f);
303 case Uniform::Type::Define:
304 return QString();
305 }
306 return QVariant();
307}
308
309// Return name for the image property Image element
310QString UniformModel::getImageElementName(const Uniform &uniform)
311{
312 if (uniform.value.toString().isEmpty())
313 return QStringLiteral("null");
314 QString simplifiedName = uniform.name.simplified();
315 simplifiedName = simplifiedName.remove(c: ' ');
316 return QStringLiteral("imageItem") + simplifiedName;
317}
318
319// This will update the row content at rowIndex
320// When rowIndex = -1, new row will be appended
321bool UniformModel::updateRow(int nodeId, int rowIndex, int type, const QString &id,
322 const QVariant &defaultValue, const QString &description, const QString &customValue,
323 bool useCustomValue, const QVariant &minValue, const QVariant &maxValue,
324 bool enableMipmap, bool exportImage)
325{
326 if (m_uniformTable == nullptr)
327 return false;
328
329 bool addNewRow = false;
330 if (rowIndex == -1) {
331 addNewRow = true;
332 // Add new row after the last of its node so uniforms are
333 // in continuous groups per node.
334 rowIndex = m_uniformTable->size();
335 for (int i = m_uniformTable->size() - 1; i >= 0; i--) {
336 auto &uniform = (*m_uniformTable)[i];
337 if (uniform.nodeId == nodeId) {
338 rowIndex = i + 1;
339 break;
340 }
341 }
342 }
343
344 if (addNewRow && !validateUniformName(uniformName: id))
345 return false;
346
347 if (addNewRow)
348 beginInsertRows(parent: QModelIndex(), first: rowIndex, last: rowIndex);
349
350 Uniform newUniform = { };
351 auto &uniform = addNewRow ? newUniform : (*m_uniformTable)[rowIndex];
352
353 uniform.type = Uniform::Type(type);
354 uniform.name = id.toLocal8Bit();
355 uniform.description = description;
356 uniform.customValue = customValue;
357 uniform.useCustomValue = useCustomValue;
358 uniform.enableMipmap = enableMipmap;
359 uniform.exportImage = exportImage;
360 switch (uniform.type) {
361 case Uniform::Type::Bool:
362 uniform.defaultValue = defaultValue;
363 break;
364 case Uniform::Type::Int:
365 case Uniform::Type::Float:
366 case Uniform::Type::Vec2:
367 case Uniform::Type::Vec3:
368 case Uniform::Type::Vec4:
369 case Uniform::Type::Color:
370 case Uniform::Type::Define:
371 uniform.defaultValue = defaultValue;
372 uniform.minValue = minValue;
373 uniform.maxValue = maxValue;
374 break;
375 case Uniform::Type::Sampler:
376 if (defaultValue.metaType().id() == QMetaType::QUrl)
377 uniform.defaultValue = defaultValue.toString();
378 else
379 uniform.defaultValue = "";
380 // Update the mipmap property
381 QString mipmapProperty = m_effectManager->mipmapPropertyName(name: uniform.name);
382 g_propertyData[mipmapProperty] = enableMipmap;
383 break;
384 }
385
386 if (addNewRow) {
387 // When adding a property, value is default value
388 uniform.value = uniform.defaultValue;
389 g_propertyData.insert(key: uniform.name, value: uniform.value);
390 // Note: NodeId is only updated when adding new property
391 // Properties can't be moved to other nodes
392 uniform.nodeId = nodeId;
393 m_uniformTable->insert(i: rowIndex, t: uniform);
394 endInsertRows();
395 updateCanMoveStatus();
396 if (uniform.type == Uniform::Type::Sampler) {
397 QString fs = "\n";
398 fs += "// *** Autogenerated - Remove if not needed ***\n";
399 fs += "// vec4 " + uniform.name + "Tex = texture(" + uniform.name + ", texCoord);\n";
400 Q_EMIT addFSCode(code: fs);
401 }
402 } else {
403 if (!uniform.useCustomValue)
404 g_propertyData.insert(key: uniform.name, value: uniform.value);
405 Q_EMIT dataChanged(topLeft: QAbstractItemModel::createIndex(arow: rowIndex, acolumn: 0),
406 bottomRight: QAbstractItemModel::createIndex(arow: rowIndex, acolumn: 0));
407 }
408 // Update QML component as useCustomValue, customValue etc. might have changed
409 Q_EMIT qmlComponentChanged();
410 Q_EMIT uniformsChanged();
411 return true;
412}
413
414bool UniformModel::resetValue(int rowIndex)
415{
416 auto &uniform = (*m_uniformTable)[rowIndex];
417 auto index = QAbstractItemModel::createIndex(arow: rowIndex, acolumn: 0);
418 setData(index, value: uniform.defaultValue, role: Value);
419
420 g_propertyData.insert(key: uniform.name, value: uniform.defaultValue);
421
422 emit dataChanged(topLeft: index, bottomRight: index, roles: {Value});
423
424 // Image element may change, so update component
425 if (uniform.type == Uniform::Type::Sampler)
426 Q_EMIT qmlComponentChanged();
427 Q_EMIT uniformsChanged();
428
429 return true;
430}
431
432// Updates the image data at rowIndex
433bool UniformModel::setImage(int rowIndex, const QVariant &value)
434{
435 auto &uniform = (*m_uniformTable)[rowIndex];
436 uniform.value = value.toString();
437
438 g_propertyData.insert(key: uniform.name, value);
439
440 emit dataChanged(topLeft: QAbstractItemModel::createIndex(arow: 0, acolumn: 0),
441 bottomRight: QAbstractItemModel::createIndex(arow: rowIndex, acolumn: 0));
442
443 // Image element may change, so update component
444 if (uniform.type == Uniform::Type::Sampler)
445 Q_EMIT qmlComponentChanged();
446 Q_EMIT uniformsChanged();
447 return true;
448}
449
450// Move uniform up/down in the list
451void UniformModel::moveIndex(int rowIndex, int direction)
452{
453 if (m_uniformTable == nullptr)
454 return;
455
456 // Note: beginMoveRows index behaves differently than QList move index.
457 int destinationRowIndex = rowIndex + 2;
458 int destinationListIndex = rowIndex + 1;
459 if (direction == -1) {
460 destinationRowIndex = rowIndex - 1;
461 destinationListIndex = rowIndex - 1;
462 }
463
464 if (destinationListIndex >= 0 && m_uniformTable->size() > destinationListIndex) {
465 beginMoveRows(sourceParent: QModelIndex(), sourceFirst: rowIndex, sourceLast: rowIndex, destinationParent: QModelIndex(), destinationRow: destinationRowIndex);
466 m_uniformTable->move(from: rowIndex, to: destinationListIndex);
467 endMoveRows();
468 updateCanMoveStatus();
469 }
470}
471
472void UniformModel::removeRow(int rowIndex, int rows)
473{
474 if (m_uniformTable == nullptr)
475 return;
476
477 if (m_uniformTable->size() > rowIndex) {
478 rows = qBound(min: 1, val: rows, max: m_uniformTable->size());
479 beginRemoveRows(parent: QModelIndex(), first: rowIndex, last: rowIndex + rows - 1);
480 m_uniformTable->remove(i: rowIndex, n: rows);
481 endRemoveRows();
482 updateCanMoveStatus();
483
484 emit dataChanged(topLeft: QAbstractItemModel::createIndex(arow: 0, acolumn: 0),
485 bottomRight: QAbstractItemModel::createIndex(arow: rowIndex, acolumn: 0));
486 Q_EMIT uniformsChanged();
487 }
488}
489
490bool UniformModel::validateUniformName(const QString &uniformName)
491{
492 if (!m_uniformTable)
493 return false;
494
495 // must be unique
496 for (const auto &uniform : *m_uniformTable) {
497 if (uniform.name == uniformName)
498 return false;
499 }
500
501 return true;
502}
503
504QString UniformModel::typeToProperty(Uniform::Type type)
505{
506 QString property;
507 switch (type) {
508 case Uniform::Type::Bool:
509 property = "bool";
510 break;
511 case Uniform::Type::Int:
512 property = "int";
513 break;
514 case Uniform::Type::Float:
515 property = "real";
516 break;
517 case Uniform::Type::Vec2:
518 property = "point";
519 break;
520 case Uniform::Type::Vec3:
521 property = "vector3d";
522 break;
523 case Uniform::Type::Vec4:
524 property = "vector4d";
525 break;
526 case Uniform::Type::Color:
527 property = "color";
528 break;
529 case Uniform::Type::Sampler:
530 property = "var";
531 break;
532 case Uniform::Type::Define:
533 property = "var";
534 break;
535 }
536 return property;
537}
538
539QString UniformModel::typeToUniform(Uniform::Type type)
540{
541 QString property;
542 switch (type) {
543 case Uniform::Type::Bool:
544 property = "bool";
545 break;
546 case Uniform::Type::Int:
547 property = "int";
548 break;
549 case Uniform::Type::Float:
550 property = "float";
551 break;
552 case Uniform::Type::Vec2:
553 property = "vec2";
554 break;
555 case Uniform::Type::Vec3:
556 property = "vec3";
557 break;
558 case Uniform::Type::Vec4:
559 case Uniform::Type::Color:
560 property = "vec4";
561 break;
562 case Uniform::Type::Sampler:
563 property = "sampler2D";
564 break;
565 case Uniform::Type::Define:
566 property = "define";
567 break;
568 }
569 return property;
570}
571
572// Get value in QML format that used for exports
573QString UniformModel::valueAsString(const Uniform &uniform)
574{
575 QString s;
576 switch (uniform.type) {
577 case Uniform::Type::Bool:
578 s = uniform.value.toBool() ? "true" : "false";
579 break;
580 case Uniform::Type::Int:
581 s = QString::number(uniform.value.toInt());
582 break;
583 case Uniform::Type::Float:
584 s = QString::number(uniform.value.toDouble());
585 break;
586 case Uniform::Type::Vec2:
587 {
588 QVector2D v2 = uniform.value.value<QVector2D>();
589 s = QString("Qt.point(%1, %2)").arg(a: v2.x()).arg(a: v2.y());
590 break;
591 }
592 case Uniform::Type::Vec3:
593 {
594 QVector3D v3 = uniform.value.value<QVector3D>();
595 s = QString("Qt.vector3d(%1, %2, %3)").arg(a: v3.x()).arg(a: v3.y()).arg(a: v3.z());
596 break;
597 }
598 case Uniform::Type::Vec4:
599 {
600 QVector4D v4 = uniform.value.value<QVector4D>();
601 s = QString("Qt.vector4d(%1, %2, %3, %4)").arg(a: v4.x()).arg(a: v4.y()).arg(a: v4.z()).arg(a: v4.w());
602 break;
603 }
604 case Uniform::Type::Color:
605 {
606 QColor c = uniform.value.value<QColor>();
607 s = QString("Qt.rgba(%1, %2, %3, %4)").arg(a: c.redF()).arg(a: c.greenF()).arg(a: c.blueF()).arg(a: c.alphaF());
608 break;
609 }
610 case Uniform::Type::Sampler:
611 {
612 s = getImageElementName(uniform);
613 break;
614 }
615 case Uniform::Type::Define:
616 {
617 s = uniform.value.toString();
618 break;
619 }
620 }
621 return s;
622}
623
624// Get value in GLSL format that is used for non-exported const properties
625QString UniformModel::valueAsVariable(const Uniform &uniform)
626{
627 QString s;
628 switch (uniform.type) {
629 case Uniform::Type::Bool:
630 s = uniform.value.toBool() ? "true" : "false";
631 break;
632 case Uniform::Type::Int:
633 s = QString::number(uniform.value.toInt());
634 break;
635 case Uniform::Type::Float:
636 s = QString::number(uniform.value.toDouble());
637 break;
638 case Uniform::Type::Vec2:
639 {
640 QVector2D v2 = uniform.value.value<QVector2D>();
641 s = QString("vec2(%1, %2)").arg(a: v2.x()).arg(a: v2.y());
642 break;
643 }
644 case Uniform::Type::Vec3:
645 {
646 QVector3D v3 = uniform.value.value<QVector3D>();
647 s = QString("vec3(%1, %2, %3)").arg(a: v3.x()).arg(a: v3.y()).arg(a: v3.z());
648 break;
649 }
650 case Uniform::Type::Vec4:
651 {
652 QVector4D v4 = uniform.value.value<QVector4D>();
653 s = QString("vec4(%1, %2, %3, %4)").arg(a: v4.x()).arg(a: v4.y()).arg(a: v4.z()).arg(a: v4.w());
654 break;
655 }
656 case Uniform::Type::Color:
657 {
658 QColor c = uniform.value.value<QColor>();
659 s = QString("vec4(%1, %2, %3, %4)").arg(a: c.redF()).arg(a: c.greenF()).arg(a: c.blueF()).arg(a: c.alphaF());
660 break;
661 }
662 default:
663 qWarning() << QString("Unhandled const variable type: %1").arg(a: int(uniform.type)).toLatin1();
664 break;
665 }
666 return s;
667}
668
669// Get value in QML binding that used for previews
670QString UniformModel::valueAsBinding(const Uniform &uniform)
671{
672 QString s;
673 switch (uniform.type) {
674 case Uniform::Type::Bool:
675 case Uniform::Type::Int:
676 case Uniform::Type::Float:
677 case Uniform::Type::Define:
678 s = "g_propertyData." + uniform.name;
679 break;
680 case Uniform::Type::Vec2:
681 {
682 QString sx = QString("g_propertyData.%1.x").arg(a: uniform.name);
683 QString sy = QString("g_propertyData.%1.y").arg(a: uniform.name);
684 s = QString("Qt.point(%1, %2)").arg(args&: sx, args&: sy);
685 break;
686 }
687 case Uniform::Type::Vec3:
688 {
689 QString sx = QString("g_propertyData.%1.x").arg(a: uniform.name);
690 QString sy = QString("g_propertyData.%1.y").arg(a: uniform.name);
691 QString sz = QString("g_propertyData.%1.z").arg(a: uniform.name);
692 s = QString("Qt.vector3d(%1, %2, %3)").arg(args&: sx, args&: sy, args&: sz);
693 break;
694 }
695 case Uniform::Type::Vec4:
696 {
697 QString sx = QString("g_propertyData.%1.x").arg(a: uniform.name);
698 QString sy = QString("g_propertyData.%1.y").arg(a: uniform.name);
699 QString sz = QString("g_propertyData.%1.z").arg(a: uniform.name);
700 QString sw = QString("g_propertyData.%1.w").arg(a: uniform.name);
701 s = QString("Qt.vector4d(%1, %2, %3, %4)").arg(args&: sx, args&: sy, args&: sz, args&: sw);
702 break;
703 }
704 case Uniform::Type::Color:
705 {
706 QString sr = QString("g_propertyData.%1.r").arg(a: uniform.name);
707 QString sg = QString("g_propertyData.%1.g").arg(a: uniform.name);
708 QString sb = QString("g_propertyData.%1.b").arg(a: uniform.name);
709 QString sa = QString("g_propertyData.%1.a").arg(a: uniform.name);
710 s = QString("Qt.rgba(%1, %2, %3, %4)").arg(args&: sr, args&: sg, args&: sb, args&: sa);
711 break;
712 }
713 case Uniform::Type::Sampler:
714 {
715 s = getImageElementName(uniform);
716 break;
717 }
718 }
719 return s;
720}
721
722QString UniformModel::variantAsDataString(const Uniform::Type type, const QVariant &variant)
723{
724 QString s;
725 switch (type) {
726 case Uniform::Type::Bool:
727 s = variant.toBool() ? "true" : "false";
728 break;
729 case Uniform::Type::Int:
730 s = QString::number(variant.toInt());
731 break;
732 case Uniform::Type::Float:
733 s = QString::number(variant.toDouble());
734 break;
735 case Uniform::Type::Vec2:
736 {
737 QStringList list;
738 QVector2D v2 = variant.value<QVector2D>();
739 list << QString::number(v2.x());
740 list << QString::number(v2.y());
741 s = list.join(sep: ", ");
742 break;
743 }
744 case Uniform::Type::Vec3:
745 {
746 QStringList list;
747 QVector3D v3 = variant.value<QVector3D>();
748 list << QString::number(v3.x());
749 list << QString::number(v3.y());
750 list << QString::number(v3.z());
751 s = list.join(sep: ", ");
752 break;
753 }
754 case Uniform::Type::Vec4:
755 {
756 QStringList list;
757 QVector4D v4 = variant.value<QVector4D>();
758 list << QString::number(v4.x());
759 list << QString::number(v4.y());
760 list << QString::number(v4.z());
761 list << QString::number(v4.w());
762 s = list.join(sep: ", ");
763 break;
764 }
765 case Uniform::Type::Color:
766 {
767 QStringList list;
768 QColor c = variant.value<QColor>();
769 list << QString::number(c.redF(), format: 'g', precision: 3);
770 list << QString::number(c.greenF(), format: 'g', precision: 3);
771 list << QString::number(c.blueF(), format: 'g', precision: 3);
772 list << QString::number(c.alphaF(), format: 'g', precision: 3);
773 s = list.join(sep: ", ");
774 break;
775 }
776 case Uniform::Type::Sampler:
777 case Uniform::Type::Define:
778 {
779 s = variant.toString();
780 break;
781 }
782 }
783 return s;
784}
785
786void UniformModel::appendUniform(Uniform uniform)
787{
788 if (!validateUniformName(uniformName: uniform.name)) {
789 qWarning() << "Invalid uniform name, can't add it";
790 return;
791 }
792
793 int rowIndex = m_uniformTable->size();
794 beginInsertRows(parent: QModelIndex(), first: rowIndex, last: rowIndex);
795 m_uniformTable->insert(i: rowIndex, t: uniform);
796 endInsertRows();
797 updateCanMoveStatus();
798
799 emit dataChanged(topLeft: QAbstractItemModel::createIndex(arow: 0, acolumn: 0),
800 bottomRight: QAbstractItemModel::createIndex(arow: rowIndex, acolumn: 0));
801
802 Q_EMIT uniformsChanged();
803
804}
805
806void UniformModel::setUniformValueData(Uniform *uniform, const QString &value, const QString &defaultValue, const QString &minValue, const QString &maxValue)
807{
808 if (!uniform)
809 return;
810
811 uniform->value = value.isEmpty() ? getInitializedVariant(type: uniform->type, maxValue: false) : valueStringToVariant(type: uniform->type, value);
812 uniform->defaultValue = defaultValue.isEmpty() ? getInitializedVariant(type: uniform->type, maxValue: false) : valueStringToVariant(type: uniform->type, value: defaultValue);
813 uniform->minValue = minValue.isEmpty() ? getInitializedVariant(type: uniform->type, maxValue: false) : valueStringToVariant(type: uniform->type, value: minValue);
814 uniform->maxValue = maxValue.isEmpty() ? getInitializedVariant(type: uniform->type, maxValue: true) : valueStringToVariant(type: uniform->type, value: maxValue);
815
816 // Update the value data in bindings
817 g_propertyData.insert(key: uniform->name, value: uniform->value);
818}
819
820UniformModel::Uniform::Type UniformModel::typeFromString(const QString &typeString) const
821{
822 if (typeString == "bool")
823 return UniformModel::Uniform::Type::Bool;
824 else if (typeString == "int")
825 return UniformModel::Uniform::Type::Int;
826 else if (typeString == "float")
827 return UniformModel::Uniform::Type::Float;
828 else if (typeString == "vec2")
829 return UniformModel::Uniform::Type::Vec2;
830 else if (typeString == "vec3")
831 return UniformModel::Uniform::Type::Vec3;
832 else if (typeString == "vec4")
833 return UniformModel::Uniform::Type::Vec4;
834 else if (typeString == "color")
835 return UniformModel::Uniform::Type::Color;
836 else if (typeString == "image")
837 return UniformModel::Uniform::Type::Sampler;
838 else if (typeString == "define")
839 return UniformModel::Uniform::Type::Define;
840
841 qWarning() << QString("Unknown type: %1").arg(a: typeString).toLatin1();
842 return UniformModel::Uniform::Type::Float;
843}
844
845QString UniformModel::stringFromType(Uniform::Type type)
846{
847 QString property;
848 switch (type) {
849 case Uniform::Type::Bool:
850 property = "bool";
851 break;
852 case Uniform::Type::Int:
853 property = "int";
854 break;
855 case Uniform::Type::Float:
856 property = "float";
857 break;
858 case Uniform::Type::Vec2:
859 property = "vec2";
860 break;
861 case Uniform::Type::Vec3:
862 property = "vec3";
863 break;
864 case Uniform::Type::Vec4:
865 property = "vec4";
866 break;
867 case Uniform::Type::Color:
868 property = "color";
869 break;
870 case Uniform::Type::Sampler:
871 property = "image";
872 break;
873 case Uniform::Type::Define:
874 property = "define";
875 break;
876 }
877 return property;
878}
879
880QVariant UniformModel::valueStringToVariant(const Uniform::Type type, const QString &value)
881{
882 QVariant variant;
883 switch (type) {
884 case UniformModel::Uniform::Type::Bool:
885 variant = (value == "true") ? true : false;
886 break;
887 case UniformModel::Uniform::Type::Int:
888 case UniformModel::Uniform::Type::Float:
889 variant = value;
890 break;
891 case UniformModel::Uniform::Type::Vec2:
892 {
893 QStringList list = value.split(sep: QLatin1Char(','));
894 if (list.size() >= 2)
895 variant = QVector2D(list.at(i: 0).toDouble(), list.at(i: 1).toDouble());
896 }
897 break;
898 case UniformModel::Uniform::Type::Vec3:
899 {
900 QStringList list = value.split(sep: QLatin1Char(','));
901 if (list.size() >= 3)
902 variant = QVector3D(list.at(i: 0).toDouble(), list.at(i: 1).toDouble(), list.at(i: 2).toDouble());
903 }
904 break;
905 case UniformModel::Uniform::Type::Vec4:
906 {
907 QStringList list = value.split(sep: QLatin1Char(','));
908 if (list.size() >= 4)
909 variant = QVector4D(list.at(i: 0).toDouble(), list.at(i: 1).toDouble(), list.at(i: 2).toDouble(), list.at(i: 3).toDouble());
910 }
911 break;
912 case UniformModel::Uniform::Type::Color:
913 {
914 QStringList list = value.split(sep: QLatin1Char(','));
915 if (list.size() >= 4)
916 variant = QColor::fromRgbF(r: list.at(i: 0).toDouble(), g: list.at(i: 1).toDouble(), b: list.at(i: 2).toDouble(), a: list.at(i: 3).toDouble());
917 }
918 break;
919 case UniformModel::Uniform::Type::Sampler:
920 variant = value;
921 break;
922 case UniformModel::Uniform::Type::Define:
923 variant = value;
924 break;
925 }
926
927 return variant;
928}
929
930// Update canMoveUp and canMoveDown.
931// When uniform is first/last of its node it can't move up/down.
932void UniformModel::updateCanMoveStatus() {
933 if (m_uniformTable->isEmpty())
934 return;
935 QList<int> usedIds;
936 for (int i = 0; i < m_uniformTable->size() ; i++) {
937 auto &uniform = (*m_uniformTable)[i];
938 if (usedIds.contains(t: uniform.nodeId)) {
939 uniform.canMoveUp = true;
940 } else {
941 uniform.canMoveUp = false;
942 usedIds << uniform.nodeId;
943 }
944 }
945 usedIds.clear();
946 for (int i = m_uniformTable->size() - 1; i >= 0; i--) {
947 auto &uniform = (*m_uniformTable)[i];
948 if (usedIds.contains(t: uniform.nodeId)) {
949 uniform.canMoveDown = true;
950 } else {
951 uniform.canMoveDown = false;
952 usedIds << uniform.nodeId;
953 }
954 }
955 int lastRowIndex = m_uniformTable->size();
956 emit dataChanged(topLeft: QAbstractItemModel::createIndex(arow: 0, acolumn: 0),
957 bottomRight: QAbstractItemModel::createIndex(arow: lastRowIndex, acolumn: 0));
958}
959
960

source code of qtquickeffectmaker/tools/qqem/uniformmodel.cpp