1 | // Copyright (C) 2022 The Qt Company Ltd. |
2 | // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only |
3 | |
4 | #include "qssgscenedesc_p.h" |
5 | |
6 | QT_BEGIN_NAMESPACE |
7 | |
8 | bool QSSGSceneDesc::PropertyCall::set(QQuick3DObject &, const char *, const void *) { return false; } |
9 | bool QSSGSceneDesc::PropertyCall::get(const QQuick3DObject &, const void *[]) const { return false; } |
10 | |
11 | static inline quint16 getNextNodeId(QSSGSceneDesc::Scene &scene) |
12 | { |
13 | /* root node uses the default value 0 */ |
14 | return ++scene.nodeId; |
15 | } |
16 | |
17 | void QSSGSceneDesc::addNode(QSSGSceneDesc::Node &parent, QSSGSceneDesc::Node &node) |
18 | { |
19 | Q_ASSERT(parent.scene); |
20 | node.scene = parent.scene; |
21 | node.id = getNextNodeId(scene&: *parent.scene); |
22 | |
23 | if (QSSGRenderGraphObject::isResource(type: node.runtimeType) || node.nodeType == Node::Type::Mesh || node.nodeType == Node::Type::Skeleton) |
24 | node.scene->resources.push_back(t: &node); |
25 | else // Here goes nothing: kick all the resources out of the tree... |
26 | parent.children.push_back(t: &node); |
27 | } |
28 | |
29 | void QSSGSceneDesc::addNode(QSSGSceneDesc::Scene &scene, QSSGSceneDesc::Node &node) |
30 | { |
31 | if (scene.root) { |
32 | addNode(parent&: *scene.root, node); |
33 | } else { |
34 | Q_ASSERT(node.id == 0); |
35 | node.scene = &scene; |
36 | scene.root = &node; |
37 | } |
38 | } |
39 | |
40 | void QSSGSceneDesc::Scene::reset() |
41 | { |
42 | id.clear(); |
43 | nodeId = 0; |
44 | root = nullptr; |
45 | resources.clear(); |
46 | meshStorage.clear(); |
47 | } |
48 | |
49 | void QSSGSceneDesc::Scene::cleanup() |
50 | { |
51 | id.clear(); |
52 | nodeId = 0; |
53 | |
54 | root->cleanupChildren(); |
55 | delete root; |
56 | root = nullptr; |
57 | |
58 | qDeleteAll(c: resources); |
59 | resources.clear(); |
60 | |
61 | for (auto *anim: animations) { |
62 | for (auto *ch: anim->channels) { |
63 | qDeleteAll(c: ch->keys); |
64 | ch->keys.clear(); |
65 | delete ch; |
66 | } |
67 | delete anim; |
68 | } |
69 | animations.clear(); |
70 | } |
71 | |
72 | QMetaType QSSGSceneDesc::listViewMetaType() |
73 | { |
74 | return QMetaType::fromType<QSSGSceneDesc::ListView *>(); |
75 | } |
76 | |
77 | void QSSGSceneDesc::destructValue(QVariant &value) |
78 | { |
79 | if (!value.isValid()) |
80 | return; |
81 | |
82 | if (value.metaType() == QMetaType::fromType<QSSGSceneDesc::NodeList *>()) |
83 | delete value.value<NodeList *>(); |
84 | else if (value.metaType() == QMetaType::fromType<QSSGSceneDesc::ListView *>()) |
85 | delete value.value<ListView *>(); |
86 | // Non-pointer types are destructed by ~QVariant |
87 | else if ((value.metaType().flags() & QMetaType::TypeFlag::IsPointer) |
88 | // Mesh node will be deleted when cleaning up resources. |
89 | && (value.metaType() != QMetaType::fromType<QSSGSceneDesc::Mesh *>()) |
90 | // Referencing nodes will not be deleted here. |
91 | // They should be deleted in the node hierarchy or resources. |
92 | && (value.metaType().id() != qMetaTypeId<QSSGSceneDesc::Node *>())) { |
93 | qWarning() << value.metaType().name() << " was not destroyed correctly." ; |
94 | } |
95 | } |
96 | |
97 | void QSSGSceneDesc::destructNode(Node &node) |
98 | { |
99 | for (auto *prop : node.properties) |
100 | delete prop; |
101 | // Not necessary to clear the list as long as we only call this from the destructor |
102 | } |
103 | |
104 | QSSGSceneDesc::Node::~Node() { destructNode(node&: *this); } |
105 | |
106 | void QSSGSceneDesc::Node::cleanupChildren() |
107 | { |
108 | auto firstIt = children.begin(); |
109 | auto lastIt = children.end(); |
110 | for (auto it = firstIt; it != lastIt; ++it) { |
111 | Node *node = *it; |
112 | node->cleanupChildren(); |
113 | delete node; |
114 | } |
115 | } |
116 | |
117 | QSSGSceneDesc::Property *QSSGSceneDesc::setProperty(Node &node, const char *name, QVariant &&value) |
118 | { |
119 | Q_ASSERT(node.scene); |
120 | QSSGSceneDesc::Property *prop = new QSSGSceneDesc::Property; |
121 | prop->name = name; |
122 | prop->call = nullptr; |
123 | prop->value = value; |
124 | node.properties.push_back(t: prop); |
125 | return prop; |
126 | } |
127 | |
128 | QSSGSceneDesc::Model::Model() : Node(Node::Type::Model, Node::RuntimeType::Model) {} |
129 | |
130 | QSSGSceneDesc::Camera::Camera(RuntimeType rt) : Node(Node::Type::Camera, rt) {} |
131 | |
132 | QSSGSceneDesc::Light::Light(RuntimeType rt) : Node(Node::Type::Light, rt) {} |
133 | |
134 | QSSGSceneDesc::Skin::Skin() : Node(Node::Type::Skin, Node::RuntimeType::Skin) {} |
135 | |
136 | QSSGSceneDesc::Skeleton::Skeleton() : Node(Node::Type::Skeleton, Node::RuntimeType::Skeleton) {} |
137 | |
138 | QSSGSceneDesc::Joint::Joint() : Node(Node::Type::Joint, Node::RuntimeType::Joint) {} |
139 | |
140 | QSSGSceneDesc::MorphTarget::MorphTarget() : Node(Node::Type::MorphTarget, Node::RuntimeType::MorphTarget) {} |
141 | |
142 | QSSGSceneDesc::Material::Material(RuntimeType rt) : Node(Node::Type::Material, rt) {} |
143 | |
144 | QSSGSceneDesc::Texture::Texture(RuntimeType rt, const QByteArray &name) |
145 | : Node(name, Node::Type::Texture, rt) |
146 | { |
147 | } |
148 | |
149 | QSSGSceneDesc::TextureData::TextureData(const QByteArray &textureData, QSize size, const QByteArray &format, quint8 flags, QByteArray name) |
150 | : Node(name, Node::Type::Texture, RuntimeType::TextureData) |
151 | , data(textureData) |
152 | , sz(size) |
153 | , fmt(format) |
154 | , flgs(flags) |
155 | {} |
156 | |
157 | QSSGSceneDesc::Mesh::Mesh(QByteArray name, qsizetype index) |
158 | : Node(name, Node::Type::Mesh, RuntimeType::Node) |
159 | , idx(index) |
160 | {} |
161 | |
162 | QT_END_NAMESPACE |
163 | |