aboutsummaryrefslogtreecommitdiffstats
path: root/src/assetutils/qssgscenedesc.cpp
blob: de4b747ca0b18f55990d7c3196ff0fa841aa84d9 (plain)
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
// Copyright (C) 2022 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only

#include "qssgscenedesc_p.h"

QT_BEGIN_NAMESPACE

bool QSSGSceneDesc::PropertyCall::set(QQuick3DObject &, const char *, const void *) { return false; }
bool QSSGSceneDesc::PropertyCall::get(const QQuick3DObject &, const void *[]) const { return false; }

static inline quint16 getNextNodeId(QSSGSceneDesc::Scene &scene)
{
    /* root node uses the default value 0 */
    return ++scene.nodeId;
}

void QSSGSceneDesc::addNode(QSSGSceneDesc::Node &parent, QSSGSceneDesc::Node &node)
{
    Q_ASSERT(parent.scene);
    node.scene = parent.scene;
    node.id = getNextNodeId(*parent.scene);

    if (QSSGRenderGraphObject::isResource(node.runtimeType) || node.nodeType == Node::Type::Mesh || node.nodeType == Node::Type::Skeleton)
        node.scene->resources.push_back(&node);
    else // Here goes nothing: kick all the resources out of the tree...
        parent.children.push_back(&node);
}

void QSSGSceneDesc::addNode(QSSGSceneDesc::Scene &scene, QSSGSceneDesc::Node &node)
{
    if (scene.root) {
        addNode(*scene.root, node);
    } else {
        Q_ASSERT(node.id == 0);
        node.scene = &scene;
        scene.root = &node;
    }
}

void QSSGSceneDesc::Scene::reset()
{
    id.clear();
    nodeId = 0;
    root = nullptr;
    resources.clear();
    meshStorage.clear();
}

void QSSGSceneDesc::Scene::cleanup()
{
    id.clear();
    nodeId = 0;

    root->cleanupChildren();
    delete root;
    root = nullptr;

    qDeleteAll(resources);
    resources.clear();

    for (auto *anim: animations) {
        for (auto *ch: anim->channels) {
            qDeleteAll(ch->keys);
            ch->keys.clear();
            delete ch;
        }
        delete anim;
    }
    animations.clear();
}

QMetaType QSSGSceneDesc::listViewMetaType()
{
    return QMetaType::fromType<QSSGSceneDesc::ListView *>();
}

void QSSGSceneDesc::destructValue(QVariant &value)
{
    if (!value.isValid())
        return;

    if (value.metaType() == QMetaType::fromType<QSSGSceneDesc::NodeList *>())
        delete value.value<NodeList *>();
    else if (value.metaType() == QMetaType::fromType<QSSGSceneDesc::ListView *>())
        delete value.value<ListView *>();
    // Non-pointer types are destructed by ~QVariant
    else if ((value.metaType().flags() & QMetaType::TypeFlag::IsPointer)
            // Mesh node will be deleted when cleaning up resources.
            && (value.metaType() != QMetaType::fromType<QSSGSceneDesc::Mesh *>())
            // Referencing nodes will not be deleted here.
            // They should be deleted in the node hierarchy or resources.
            && (value.metaType().id() != qMetaTypeId<QSSGSceneDesc::Node *>())) {
        qWarning() << value.metaType().name() << " was not destroyed correctly.";
    }
}

void QSSGSceneDesc::destructNode(Node &node)
{
    for (auto *prop : node.properties)
        delete prop;
    // Not necessary to clear the list as long as we only call this from the destructor
}

QSSGSceneDesc::Node::~Node() { destructNode(*this); }

void QSSGSceneDesc::Node::cleanupChildren()
{
    auto firstIt = children.begin();
    auto lastIt = children.end();
    for (auto it = firstIt; it != lastIt; ++it) {
        Node *node = *it;
        node->cleanupChildren();
        delete node;
    }
}

QSSGSceneDesc::Property *QSSGSceneDesc::setProperty(Node &node, const char *name, QVariant &&value)
{
    Q_ASSERT(node.scene);
    QSSGSceneDesc::Property *prop = new QSSGSceneDesc::Property;
    prop->name = name;
    prop->call = nullptr;
    prop->value = value;
    node.properties.push_back(prop);
    return prop;
}

QSSGSceneDesc::Model::Model() : Node(Node::Type::Model, Node::RuntimeType::Model) {}

QSSGSceneDesc::Camera::Camera(RuntimeType rt) : Node(Node::Type::Camera, rt) {}

QSSGSceneDesc::Light::Light(RuntimeType rt) : Node(Node::Type::Light, rt) {}

QSSGSceneDesc::Skin::Skin() : Node(Node::Type::Skin, Node::RuntimeType::Skin) {}

QSSGSceneDesc::Skeleton::Skeleton() : Node(Node::Type::Skeleton, Node::RuntimeType::Skeleton) {}

QSSGSceneDesc::Joint::Joint() : Node(Node::Type::Joint, Node::RuntimeType::Joint) {}

QSSGSceneDesc::MorphTarget::MorphTarget() : Node(Node::Type::MorphTarget, Node::RuntimeType::MorphTarget) {}

QSSGSceneDesc::Material::Material(RuntimeType rt) : Node(Node::Type::Material, rt) {}

QSSGSceneDesc::Texture::Texture(RuntimeType rt, const QByteArray &name)
    : Node(name, Node::Type::Texture, rt)
{
}

QSSGSceneDesc::TextureData::TextureData(const QByteArray &textureData, QSize size, const QByteArray &format, quint8 flags, QByteArray name)
    : Node(name, Node::Type::Texture, RuntimeType::TextureData)
    , data(textureData)
    , sz(size)
    , fmt(format)
    , flgs(flags)
{}

QSSGSceneDesc::Mesh::Mesh(QByteArray name, qsizetype index)
    : Node(name, Node::Type::Mesh, RuntimeType::Node)
    , idx(index)
{}

QT_END_NAMESPACE