| 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 | |