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
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
|
// Copyright (C) 2022 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#ifndef QSSGSCENEDESCRIPTION_P_H
#define QSSGSCENEDESCRIPTION_P_H
#include <QtQuick3DAssetUtils/private/qtquick3dassetutilsglobal_p.h>
#include <QtQuick3DRuntimeRender/private/qssgrendergraphobject_p.h>
#include <QtQuick3DRuntimeRender/private/qssgperframeallocator_p.h>
#include <QtQuick3DUtils/private/qssgmesh_p.h>
#include <QtCore/qlist.h>
#include <QtCore/qhash.h>
#include <QtCore/qvariant.h>
#include <QtCore/qflags.h>
#include <QtQml/qqmllist.h>
// QtQuick3D
#include <QtQuick3D/private/qquick3dobject_p.h>
// Materials
#include <QtQuick3D/private/qquick3dcustommaterial_p.h>
#include <QtQuick3D/private/qquick3ddefaultmaterial_p.h>
#include <QtQuick3D/private/qquick3dprincipledmaterial_p.h>
#include <QtQuick3D/private/qquick3dspecularglossymaterial_p.h>
#include <QtQuick3D/private/qquick3dmodel_p.h>
// cameras
#include <QtQuick3D/private/qquick3dorthographiccamera_p.h>
#include <QtQuick3D/private/qquick3dperspectivecamera_p.h>
#include <QtQuick3D/private/qquick3dcustomcamera_p.h>
// Lights
#include <QtQuick3D/private/qquick3ddirectionallight_p.h>
#include <QtQuick3D/private/qquick3dpointlight_p.h>
#include <QtQuick3D/private/qquick3dspotlight_p.h>
// Texture
#include <QtQuick3D/private/qquick3dtexture_p.h>
#include <QtQuick3D/private/qquick3dcubemaptexture_p.h>
#include <QtQuick3D/private/qquick3dtexturedata_p.h>
//
#include <QtQuick3D/private/qquick3dskeleton_p.h>
#include <QtQuick3D/private/qquick3djoint_p.h>
#include <qmetatype.h>
#include <QtQuick3DUtils/private/qssginvasivelinkedlist_p.h>
QT_BEGIN_NAMESPACE
//
// W A R N I N G
// -------------
//
// This file is not part of the Qt API. It exists purely as an
// implementation detail. This header file may change from version to
// version without notice, or even be removed.
//
// We mean it.
//
namespace QSSGSceneDesc
{
struct Node;
struct Animation;
template<typename T>
using rm_cvref_t = std::remove_cv_t<std::remove_reference_t<T>>;
struct Q_QUICK3DASSETUTILS_EXPORT Scene
{
using ResourceNodes = QVarLengthArray<Node *>;
using MeshStorage = QVector<QSSGMesh::Mesh>;
using Animations = QVector<Animation *>;
// Root node, usually an empty 'transform' node.
Node *root = nullptr;
QString id; // Don't make any assumption about the content of this id...
ResourceNodes resources;
MeshStorage meshStorage;
Animations animations;
QString sourceDir;
mutable quint16 nodeId = 0;
void reset();
void cleanup();
};
struct Q_QUICK3DASSETUTILS_EXPORT PropertyCall
{
virtual ~PropertyCall() = default;
virtual bool set(QQuick3DObject &, const char *, const void *) = 0;
virtual bool set(QQuick3DObject &, const char *, const QVariant &) = 0;
virtual bool get(const QQuick3DObject &, const void *[]) const = 0;
};
Q_QUICK3DASSETUTILS_EXPORT void destructValue(QVariant &value);
struct Flag
{
QMetaEnum me;
int value;
};
struct Property
{
~Property();
enum class Type { Static, Dynamic };
QVariant value;
QByteArray name;
QSSGSceneDesc::PropertyCall *call = nullptr;
Type type = Type::Static;
};
inline Property::~Property()
{
delete call;
destructValue(value);
}
Q_QUICK3DASSETUTILS_EXPORT void destructNode(QSSGSceneDesc::Node &node);
struct NodeList
{
NodeList(void * const *data, qsizetype n)
{
const auto size = sizeof(Node *) * n;
head = reinterpret_cast<Node **>(malloc(size));
memcpy(head, data, size);
count = n;
}
~NodeList() { if (head) free(head); }
Node **head = nullptr;
qsizetype count = -1;
};
struct Q_QUICK3DASSETUTILS_EXPORT Node
{
// Node type
enum class Type : quint8
{
Transform,
Camera,
Model,
Texture,
Material,
Light,
Mesh,
Skin,
Skeleton,
Joint,
MorphTarget
};
using type = QQuick3DNode;
// Runtime type type mapping between this type and the QtQuick3D type
using RuntimeType = QSSGRenderGraphObject::Type;
explicit Node(QByteArray name, Node::Type type, Node::RuntimeType rt)
: name(name)
, runtimeType(rt)
, nodeType(type) {}
explicit Node(Node::Type type, Node::RuntimeType rt)
: Node(nullptr, type, rt) {}
virtual ~Node();
void cleanupChildren();
QByteArray name;
Scene *scene = nullptr;
QObject *obj = nullptr;
using ChildList = QList<Node *>;
using PropertyList = QList<Property *>;
ChildList children;
PropertyList properties;
quint16 id = 0;
RuntimeType runtimeType;
Type nodeType;
};
template<typename T>
static constexpr bool is_node_v = std::is_base_of_v<Node, T>;
// Set up type mapping from a QQuick3D type to a SceneDesc type
template <typename T> struct TypeMap {};
#define QSSG_DECLARE_NODE(NODE) \
static_assert(is_node_v<NODE>, #NODE " - does not inherit from Node!"); \
template <> struct TypeMap<NODE::type> { using type = QSSGSceneDesc::NODE; };
template<typename T>
using as_scene_type_t = typename T::type;
template<typename T>
using as_node_type_t = typename TypeMap<T>::type;
QSSG_DECLARE_NODE(Node)
struct Q_QUICK3DASSETUTILS_EXPORT Texture : Node
{
using type = QQuick3DTexture;
explicit Texture(Node::RuntimeType rt, const QByteArray &name = {});
};
QSSG_DECLARE_NODE(Texture)
struct Q_QUICK3DASSETUTILS_EXPORT TextureData : Node
{
using type = QQuick3DTextureData;
enum class Flags : quint8
{
Compressed = 0x1
};
explicit TextureData(const QByteArray &textureData, QSize size, const QByteArray &format, quint8 flags = 0, QByteArray name = {});
QByteArray data;
QSize sz;
QByteArray fmt;
quint8 flgs;
};
QSSG_DECLARE_NODE(TextureData)
struct Q_QUICK3DASSETUTILS_EXPORT Material : Node
{
using type = QQuick3DMaterial;
explicit Material(Node::RuntimeType rt);
};
QSSG_DECLARE_NODE(Material)
// The mesh is a special node, as it's not really a node type but
// a handle to a mesh that will be turned into a source URL...
struct Q_QUICK3DASSETUTILS_EXPORT Mesh : Node
{
explicit Mesh(QByteArray name, qsizetype index);
qsizetype idx; // idx to the mesh data in the mesh data storage (see Scene).
};
struct Q_QUICK3DASSETUTILS_EXPORT Model : Node
{
using type = QQuick3DModel;
Model();
};
QSSG_DECLARE_NODE(Model)
struct Q_QUICK3DASSETUTILS_EXPORT Camera : Node
{
using type = QQuick3DCamera;
explicit Camera(RuntimeType rt);
};
QSSG_DECLARE_NODE(Camera)
struct Q_QUICK3DASSETUTILS_EXPORT Light : Node
{
using type = QQuick3DAbstractLight;
explicit Light(RuntimeType rt);
};
QSSG_DECLARE_NODE(Light)
struct Q_QUICK3DASSETUTILS_EXPORT Skin : Node
{
using type = QQuick3DSkin;
Skin();
};
QSSG_DECLARE_NODE(Skin)
struct Q_QUICK3DASSETUTILS_EXPORT Skeleton : Node
{
using type = QQuick3DSkeleton;
Skeleton();
// Skeleton is a virtual node, which is added for the start of the joint heirarchy.
// parent - joint 1 -> parent - skeleton - joint 1
// - joint 2 - joint 2
// - model 1 - model 1
// - camera 1 - camera 1
size_t maxIndex = 0;
};
QSSG_DECLARE_NODE(Skeleton)
struct Q_QUICK3DASSETUTILS_EXPORT Joint : Node
{
using type = QQuick3DJoint;
Joint();
};
QSSG_DECLARE_NODE(Joint)
struct Q_QUICK3DASSETUTILS_EXPORT MorphTarget : Node
{
using type = QQuick3DMorphTarget;
MorphTarget();
};
QSSG_DECLARE_NODE(MorphTarget)
// We keep our own list data structure, since Qt does not have a variant list where all the
// elements have the same type, and using a list of QVariant is very inefficient
struct ListView
{
~ListView() { if (data) free(data); }
QMetaType mt;
void *data = nullptr;
qsizetype count = -1;
};
Q_QUICK3DASSETUTILS_EXPORT QMetaType listViewMetaType();
struct Animation
{
struct KeyPosition
{
enum class KeyType : quint16
{
Frame = 0x100,
Time = 0x200
};
enum class ValueType : quint8
{
Number,
Vec2,
Vec3,
Vec4,
Quaternion
};
ValueType getValueType() const { return ValueType(0xf & flag); }
KeyType getKeyType() const { return KeyType(0xf00 & flag); }
QVariant getValue() const {
switch (getValueType()) {
case ValueType::Number:
return value.x();
case ValueType::Vec2:
return value.toVector2D();
case ValueType::Vec3:
return value.toVector3D();
case ValueType::Vec4:
return value;
case ValueType::Quaternion:
return QQuaternion(value);
}
return value;
}
QMetaType::Type getValueQMetaType() const {
switch (getValueType()) {
case ValueType::Number:
return QMetaType::Float;
case ValueType::Vec2:
return QMetaType::QVector2D;
case ValueType::Vec3:
return QMetaType::QVector3D;
case ValueType::Vec4:
return QMetaType::QVector4D;
case ValueType::Quaternion:
return QMetaType::QQuaternion;
}
return QMetaType::QVector4D;
}
QVector4D value;
float time = 0.0f;
quint16 flag = 0;
};
using Keys = QList<Animation::KeyPosition *>;
struct Channel
{
enum class TargetType : quint8
{
Property
};
// This is a bit simplistic, but is all we support so let's keep simple.
enum class TargetProperty : quint8
{
Unknown,
Position,
Rotation,
Scale,
Weight // for MorphMesh
};
Node *target = nullptr;
Keys keys;
TargetType targetType = TargetType::Property;
TargetProperty targetProperty = TargetProperty::Unknown;
};
using Channels = QList<Animation::Channel *>;
Channels channels;
// It stores the length of this Animation, every keys in every channels in
// an animation will have the same KeyType and it will be a type of
// the length
float length = 0.0f;
float framesPerSecond = 0.0f; // for translation back to frames
QByteArray name;
};
// Add a child node to parent node.
Q_QUICK3DASSETUTILS_EXPORT void addNode(Node &parent, Node &node);
// Add node to the scene, if a node is already set the new node will
// become a child of the root node.
Q_QUICK3DASSETUTILS_EXPORT void addNode(Scene &scene, Node &node);
template<typename> struct ListParam { enum { value = 0 }; };
template<typename T> struct ListParam<QList<T>>
{
using type = T;
enum { value = 1 };
};
template <typename T>
using listParam_t = typename ListParam<rm_cvref_t<T>>::type;
template <typename T>
struct FuncType
{
enum { value = 0 };
};
template <typename R, typename... A>
struct FuncType<R (*)(A...)>
{
enum { value = sizeof...(A) == 3 };
using Ret = R;
using Arg0 = std::tuple_element_t<0, std::tuple<A...>>;
using Arg1 = std::tuple_element_t<1, std::tuple<A...>>;
using Arg2 = std::tuple_element_t<2, std::tuple<A...>>;
using Arg2Base = rm_cvref_t<Arg2>;
};
template <typename R, typename C, typename... A>
struct FuncType<R (C::*)(A...)>
{
enum { value = sizeof... (A) == 1 };
using Ret = R;
using Class = C;
// For now we only care about single argument functions
using Arg0 = std::tuple_element_t<0, std::tuple<A...>>;
using Arg0Base = rm_cvref_t<Arg0>;
};
template <typename T, typename C>
struct FuncType<QQmlListProperty<T> (C::*)()>
{
enum { value = 2 };
using Ret = QQmlListProperty<T>;
using Class = C;
using Arg0 = void;
using Arg0Base = Arg0;
};
template <typename Ret, typename Arg>
struct PropertyProxySetter : PropertyCall
{
using Setter = Ret (*)(QQuick3DObject &, const char *, Arg);
constexpr explicit PropertyProxySetter(Setter fn) : call(fn) {}
Setter call = nullptr;
bool get(const QQuick3DObject &, const void *[]) const override { return false; }
bool set(QQuick3DObject &that, const char *name, const void *value) override
{
if constexpr (std::is_pointer_v<typename FuncType<Setter>::Arg2>)
call(that, name, reinterpret_cast<typename FuncType<Setter>::Arg2>(const_cast<void *>(value)));
else
call(that, name, *reinterpret_cast<typename FuncType<Setter>::Arg2Base *>(const_cast<void *>(value)));
return true;
}
bool set(QQuick3DObject &that, const char *name, const QVariant &var) override
{
call(that, name, qvariant_cast<typename FuncType<Setter>::Arg2Base>(var));
return true;
}
};
template <typename Ret, typename Class, typename Arg>
struct PropertySetter : PropertyCall
{
using Setter = Ret (Class::*)(Arg);
constexpr explicit PropertySetter(Setter fn) : call(fn) {}
Setter call = nullptr;
bool get(const QQuick3DObject &, const void *[]) const override { return false; }
bool set(QQuick3DObject &that, const char *, const void *value) override
{
if constexpr (std::is_pointer_v<typename FuncType<Setter>::Arg0>)
(qobject_cast<Class *>(&that)->*call)(reinterpret_cast<typename FuncType<Setter>::Arg0>(const_cast<void *>(value)));
else {
(qobject_cast<Class *>(&that)->*call)(*reinterpret_cast<typename FuncType<Setter>::Arg0Base *>(const_cast<void *>(value)));
}
return true;
}
bool set(QQuick3DObject &that, const char *, const QVariant &var) override
{
(qobject_cast<Class *>(&that)->*call)(qvariant_cast<typename FuncType<Setter>::Arg0Base>(var));
return true;
}
};
template <typename Ret, typename Class, typename Arg>
struct PropertyListSetter : PropertyCall
{
using Setter = Ret (Class::*)(Arg);
using ListT = typename FuncType<Setter>::Arg0Base;
using It = listParam_t<ListT>;
constexpr explicit PropertyListSetter(Setter fn) : call(fn) {}
Setter call = nullptr;
bool get(const QQuick3DObject &, const void *[]) const override { return false; }
bool set(QQuick3DObject &that, const char *, const void *value) override
{
if (const auto listView = reinterpret_cast<const ListView *>(value)) {
if (listView->count > 0) {
const auto begin = reinterpret_cast<It *>(listView->data);
const auto end = reinterpret_cast<It *>(listView->data) + listView->count;
(qobject_cast<Class *>(&that)->*call)(ListT{begin, end});
} else {
(qobject_cast<Class *>(&that)->*call)(ListT{});
}
return true;
}
return false;
}
bool set(QQuick3DObject &that, const char *, const QVariant &var) override
{
if (const auto listView = qvariant_cast<const ListView *>(var)) {
if (listView->count > 0) {
const auto begin = reinterpret_cast<It *>(listView->data);
const auto end = reinterpret_cast<It *>(listView->data) + listView->count;
(qobject_cast<Class *>(&that)->*call)(ListT{begin, end});
} else {
(qobject_cast<Class *>(&that)->*call)(ListT{});
}
}
return false;
}
};
template <typename Class, typename T, template <typename> typename List>
struct PropertyList : PropertyCall
{
using ListType = List<T>;
using ListFunc = ListType (Class::*)();
constexpr explicit PropertyList(ListFunc fn) : listfn(fn) {}
ListFunc listfn = nullptr;
static_assert(std::is_same_v<ListType, QQmlListProperty<T>>, "Expected QQmlListProperty!");
bool get(const QQuick3DObject &, const void *[]) const override { return false; }
void doSet(QQuick3DObject &that, const QSSGSceneDesc::NodeList &nodeList)
{
ListType list = (qobject_cast<Class *>(&that)->*listfn)();
auto head = reinterpret_cast<as_node_type_t<T> **>(nodeList.head);
for (int i = 0, end = nodeList.count; i != end; ++i)
list.append(&list, qobject_cast<T *>((*(head + i))->obj));
}
bool set(QQuick3DObject &that, const char *, const void *value) override
{
if (value) {
const auto &nodeList = *reinterpret_cast<const QSSGSceneDesc::NodeList *>(value);
doSet(that, nodeList);
return true;
}
return false;
}
bool set(QQuick3DObject &that, const char *, const QVariant &var) override
{
const auto *nodeList = qvariant_cast<const QSSGSceneDesc::NodeList *>(var);
if (nodeList) {
doSet(that, *nodeList);
return true;
}
return false;
}
};
template <typename NodeT>
using if_node = typename std::enable_if_t<is_node_v<NodeT>, bool>;
template <typename Setter, typename Value>
using if_compatible_t = typename std::enable_if_t<std::is_same_v<typename FuncType<Setter>::Arg0Base, rm_cvref_t<Value>>, bool>;
template <typename Setter, typename T>
using if_compatible_node_list_t = typename std::enable_if_t<std::is_same_v<typename FuncType<Setter>::Ret, QQmlListProperty<as_scene_type_t<T>>>, bool>;
template <typename Setter, typename Value>
using if_compatible_proxy_t = typename std::enable_if_t<std::is_same_v<typename FuncType<Setter>::Arg2Base, rm_cvref_t<Value>>, bool>;
// Sets a property on a node, the property is a name map to struct containing a pointer to the value and a function
// to set the value on an runtime object (QtQuick3DObject). The type is verified at compile-time, so we can assume
// the value is of the right type when setting it at run-time.
template<typename Setter, typename T, if_compatible_t<Setter, T> = false>
static void setProperty(QSSGSceneDesc::Node &node, const char *name, Setter setter, T &&value)
{
Q_ASSERT(node.scene);
auto prop = new Property;
prop->name = name;
prop->call = new PropertySetter(setter);
prop->value = QVariant::fromValue(std::forward<T>(value));
node.properties.push_back(prop);
}
template<typename Setter, typename T, if_compatible_t<Setter, QFlags<T>> = false>
static void setProperty(QSSGSceneDesc::Node &node, const char *name, Setter setter, QFlags<T> value)
{
Q_ASSERT(node.scene);
auto prop = new Property;
prop->name = name;
prop->call = new PropertySetter(setter);
prop->value = QVariant::fromValue(Flag{ QMetaEnum::fromType<rm_cvref_t<T>>(), value.toInt() });
node.properties.push_back(prop);
}
template<typename Setter, typename T, if_compatible_t<Setter, QList<T>> = false>
static void setProperty(QSSGSceneDesc::Node &node, const char *name, Setter setter, QList<T> value)
{
Q_ASSERT(node.scene);
static_assert(!std::is_pointer_v<T>, "Type cannot be a pointer!");
static_assert(std::is_trivially_destructible_v<T> && std::is_trivially_copy_constructible_v<T>,
"List parameter type needs to be trivially constructable and trivially destructible!");
const auto count = value.size();
void *data = nullptr;
if (count) {
const auto asize = count * sizeof(T);
data = malloc(asize); // is freed in ~ListView
memcpy(data, value.constData(), asize);
}
auto prop = new Property;
prop->name = name;
prop->call = new PropertyListSetter(setter);
prop->value = QVariant::fromValue(new ListView{ QMetaType::fromType<rm_cvref_t<T>>(), data, count });
node.properties.push_back(prop);
}
Q_QUICK3DASSETUTILS_EXPORT QSSGSceneDesc::Property *setProperty(QSSGSceneDesc::Node &node, const char *name, QVariant &&value);
// Calling this will omit any type checking, so make sure the type is handled correctly
// when it gets used later!
template<typename Setter>
static void setProperty(QSSGSceneDesc::Node &node, const char *name, Setter setter, QVariant &&value)
{
Q_ASSERT(node.scene);
Property *prop = new Property;
prop->name = name;
prop->call = new PropertySetter(setter);
prop->value = value;
node.properties.push_back(prop);
}
template<typename Setter, typename Value, if_compatible_proxy_t<Setter, Value> = true>
static void setProperty(QSSGSceneDesc::Node &node, const char *name, Setter setter, Value &&value, QSSGSceneDesc::Property::Type type = QSSGSceneDesc::Property::Type::Static)
{
Q_ASSERT(node.scene);
static_assert(std::is_trivially_destructible_v<rm_cvref_t<Value>>, "Value needs to be trivially destructible!");
Property *prop = new Property;
prop->name = name;
prop->call = new PropertyProxySetter(setter);
prop->value = QVariant::fromValue(value);
prop->type = type;
node.properties.push_back(prop);
}
template<typename Setter, typename ViewValue, if_compatible_t<Setter, typename ViewValue::type> = false>
static void setProperty(QSSGSceneDesc::Node &node, const char *name, Setter setter, ViewValue view)
{
Q_ASSERT(node.scene);
static_assert(std::is_same_v<typename ViewValue::type, typename FuncType<Setter>::Arg0Base>, "Type cannot be mapped to slot argument");
Property *prop = new Property;
prop->name = name;
prop->call = new PropertySetter(setter);
prop->value = QVariant::fromValue(view);
node.properties.push_back(prop);
}
template<typename Setter, typename Value, if_compatible_t<Setter, as_scene_type_t<Value> *> = true>
static void setProperty(QSSGSceneDesc::Node &node, const char *name, Setter setter, Value *value)
{
Q_ASSERT(node.scene);
Property *prop = new Property;
prop->name = name;
prop->call = new PropertySetter(setter);
// Always 'Node', the Node class itself contains more fine grain type information.
prop->value = QVariant::fromValue(static_cast<Node *>(value));
node.properties.push_back(prop);
}
// Overloaded function for setting a type to a property that's a QQmlListProperty.
template<typename Setter, typename NodeT, qsizetype Prealloc, if_compatible_node_list_t<Setter, NodeT> = true>
static void setProperty(QSSGSceneDesc::Node &node, const char *name, Setter setter, const QVarLengthArray<NodeT *, Prealloc> &list)
{
Q_ASSERT(node.scene);
if (!list.isEmpty()) {
NodeList *l = new NodeList(reinterpret_cast<void * const*>(list.constData()), list.count());
Property *prop = new Property;
prop->name = name;
prop->call = new PropertyList(setter);
prop->value = QVariant::fromValue(l);
node.properties.push_back(prop);
}
}
} // QSSGSceneDesc
QT_END_NAMESPACE
Q_DECLARE_METATYPE(QSSGSceneDesc::Node)
Q_DECLARE_METATYPE(QSSGSceneDesc::Texture)
Q_DECLARE_METATYPE(QSSGSceneDesc::Material)
Q_DECLARE_METATYPE(QSSGSceneDesc::Mesh)
Q_DECLARE_METATYPE(QSSGSceneDesc::Model)
Q_DECLARE_METATYPE(QSSGSceneDesc::Camera)
Q_DECLARE_METATYPE(QSSGSceneDesc::Light)
Q_DECLARE_METATYPE(QSSGSceneDesc::Skin)
Q_DECLARE_METATYPE(QSSGSceneDesc::Skeleton)
Q_DECLARE_METATYPE(QSSGSceneDesc::Joint)
Q_DECLARE_METATYPE(QSSGSceneDesc::MorphTarget)
Q_DECLARE_METATYPE(QSSGSceneDesc::NodeList)
Q_DECLARE_METATYPE(QSSGSceneDesc::Animation)
Q_DECLARE_METATYPE(QSSGSceneDesc::ListView)
Q_DECLARE_METATYPE(QSSGSceneDesc::Flag)
#endif // QSSGSCENEDESCRIPTION_P_H
|