1/****************************************************************************
2**
3** Copyright (C) 2014 Klaralvdalens Datakonsult AB (KDAB).
4** Contact: https://www.qt.io/licensing/
5**
6** This file is part of the Qt3D module of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:LGPL$
9** Commercial License Usage
10** Licensees holding valid commercial Qt licenses may use this file in
11** accordance with the commercial license agreement provided with the
12** Software or, alternatively, in accordance with the terms contained in
13** a written agreement between you and The Qt Company. For licensing terms
14** and conditions see https://www.qt.io/terms-conditions. For further
15** information use the contact form at https://www.qt.io/contact-us.
16**
17** GNU Lesser General Public License Usage
18** Alternatively, this file may be used under the terms of the GNU Lesser
19** General Public License version 3 as published by the Free Software
20** Foundation and appearing in the file LICENSE.LGPL3 included in the
21** packaging of this file. Please review the following information to
22** ensure the GNU Lesser General Public License version 3 requirements
23** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
24**
25** GNU General Public License Usage
26** Alternatively, this file may be used under the terms of the GNU
27** General Public License version 2.0 or (at your option) the GNU General
28** Public license version 3 or any later version approved by the KDE Free
29** Qt Foundation. The licenses are as published by the Free Software
30** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
31** included in the packaging of this file. Please review the following
32** information to ensure the GNU General Public License requirements will
33** be met: https://www.gnu.org/licenses/gpl-2.0.html and
34** https://www.gnu.org/licenses/gpl-3.0.html.
35**
36** $QT_END_LICENSE$
37**
38****************************************************************************/
39
40#include "qcomponent.h"
41#include "qcomponent_p.h"
42
43#include <Qt3DCore/qpropertyupdatedchange.h>
44#include <Qt3DCore/qcomponentaddedchange.h>
45#include <Qt3DCore/qcomponentremovedchange.h>
46#include <Qt3DCore/qentity.h>
47
48#include <Qt3DCore/private/qentity_p.h>
49#include <Qt3DCore/private/qscene_p.h>
50
51QT_BEGIN_NAMESPACE
52
53namespace Qt3DCore {
54
55QComponentPrivate::QComponentPrivate()
56 : QNodePrivate()
57 , m_shareable(true)
58{
59}
60
61QComponentPrivate::~QComponentPrivate()
62{
63}
64
65void QComponentPrivate::addEntity(QEntity *entity)
66{
67 Q_Q(QComponent);
68 m_entities.append(entity);
69
70 if (m_scene != nullptr && !m_scene->hasEntityForComponent(m_id, entity->id())) {
71 if (!m_shareable && !m_scene->entitiesForComponent(m_id).isEmpty())
72 qWarning() << "Trying to assign a non shareable component to more than one Entity";
73 m_scene->addEntityForComponent(m_id, entity->id());
74 }
75
76 const auto componentAddedChange = QComponentAddedChangePtr::create(q, entity);
77 notifyObservers(componentAddedChange);
78 Q_EMIT q->addedToEntity(entity);
79}
80
81void QComponentPrivate::removeEntity(QEntity *entity)
82{
83 Q_Q(QComponent);
84 if (m_scene != nullptr)
85 m_scene->removeEntityForComponent(m_id, entity->id());
86
87 m_entities.removeAll(entity);
88
89 const auto componentRemovedChange = QComponentRemovedChangePtr::create(q, entity);
90 notifyObservers(componentRemovedChange);
91 Q_EMIT q->removedFromEntity(entity);
92}
93
94/*!
95 \class Qt3DCore::QComponent
96 \inmodule Qt3DCore
97 \inherits Qt3DCore::QNode
98 \since 5.5
99
100 \brief The base class of scene nodes that can be aggregated by Qt3DCore::QEntity
101 instances as a component.
102
103 A Qt3DCore::QComponent provides a vertical slice of behavior that can be assigned to and
104 sometimes shared across Qt3DCore::QEntity instances.
105
106 Qt3DCore::QComponent subclasses are often aggregated in groups that impart useful
107 behavior to the aggregating entity. For example, to have an Entity that gets
108 drawn by the Qt3D renderer aspect, an entity would most likely aggregate
109 Qt3DCore::QTransform, Qt3DRender::QMesh, and Qt3DRender::QMaterial components.
110
111 \sa Qt3DCore::QEntity
112*/
113
114/*!
115 \fn Qt3DCore::QComponent::addedToEntity(Qt3DCore::QEntity *entity)
116
117 Indicates that a reference has been added to \a entity.
118*/
119/*!
120 \fn Qt3DCore::QComponent::removedFromEntity(Qt3DCore::QEntity *entity)
121
122 Indicates that a reference has been removed from \a entity.
123
124*/
125/*!
126 Constructs a new QComponent instance with \a parent as the parent.
127 \note a QComponent should never be instanced directly,
128 instance one of the subclasses instead.
129*/
130QComponent::QComponent(QNode *parent)
131 : QComponent(*new QComponentPrivate, parent) {}
132
133QComponent::~QComponent()
134{
135 Q_D(QComponent);
136
137 // iterate on copy since removeEntity removes from the list, invalidating the iterator
138 const auto entities = std::move(d->m_entities);
139 for (QEntity *entity : entities) {
140 QEntityPrivate *entityPimpl = static_cast<QEntityPrivate *>(QEntityPrivate::get(entity));
141 if (entityPimpl)
142 entityPimpl->m_components.removeAll(this);
143 d->removeEntity(entity);
144 }
145}
146
147/*!
148 \property Qt3DCore::QComponent::isShareable
149 Holds the shareable flag of the QComponent. The QComponent can be shared across several
150 entities if \c{true}.
151*/
152bool QComponent::isShareable() const
153{
154 Q_D(const QComponent);
155 return d->m_shareable;
156}
157
158void QComponent::setShareable(bool shareable)
159{
160 Q_D(QComponent);
161 if (d->m_shareable != shareable) {
162 d->m_shareable = shareable;
163 emit shareableChanged(shareable);
164 }
165}
166
167/*!
168 Returns a QVector containing all the entities that reference this component.
169*/
170QVector<QEntity *> QComponent::entities() const
171{
172 Q_D(const QComponent);
173 return d->m_entities;
174}
175
176/*! \internal */
177QComponent::QComponent(QComponentPrivate &dd, QNode *parent)
178 : QNode(dd, parent)
179{
180}
181
182} // namespace Qt3DCore
183
184/*!
185 \qmltype Component3D
186 \instantiates Qt3DCore::QComponent
187 \inqmlmodule Qt3D.Core
188 \inherits Node
189 \since 5.5
190 \brief Provides the base type for creating Qt 3D components.
191
192 \TODO
193*/
194
195/*!
196 \qmlproperty bool Component3D::isShareable
197*/
198
199QT_END_NAMESPACE
200