summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorSean Harmer <sean.harmer@kdab.com>2015-02-15 19:47:25 +0000
committerSean Harmer <sean.harmer@kdab.com>2015-02-28 16:28:39 +0000
commit7ccaf0f9a917f49e1cde551c2a4f4dcff575406c (patch)
tree3dd47490fce2cf99f783b0bad608cf97d84fd6ab /src
parent66b26f86856ff57713ffab35fb689d087aa91ecc (diff)
Added NodeInstantiator
Hopefully in the long term we can make the renderer smart enough that it can automatically use instancing to render such things. Change-Id: I9f5cfabeea11f5e6b925d5ad2466afa8e601e6f8 Reviewed-by: Sean Harmer <sean.harmer@kdab.com> Reviewed-by: Paul Lemire <paul.lemire@kdab.com>
Diffstat (limited to 'src')
-rw-r--r--src/quick3d/imports/core/importscore.pro2
-rw-r--r--src/quick3d/imports/core/qt3dquick3dcoreplugin.cpp2
-rw-r--r--src/quick3d/quick3d/items/items.pri7
-rw-r--r--src/quick3d/quick3d/items/quick3dnodeinstantiator.cpp492
-rw-r--r--src/quick3d/quick3d/items/quick3dnodeinstantiator_p.h118
-rw-r--r--src/quick3d/quick3d/items/quick3dnodeinstantiator_p_p.h83
6 files changed, 701 insertions, 3 deletions
diff --git a/src/quick3d/imports/core/importscore.pro b/src/quick3d/imports/core/importscore.pro
index 887a72147..7cfc2534a 100644
--- a/src/quick3d/imports/core/importscore.pro
+++ b/src/quick3d/imports/core/importscore.pro
@@ -2,7 +2,7 @@ CXX_MODULE = qml
TARGET = quick3dcoreplugin
TARGETPATH = Qt3D
-QT += qml 3dcore 3dquick 3dquick-private
+QT += qml 3dcore 3dcore-private 3dquick 3dquick-private
HEADERS += \
qt3dquick3dcoreplugin.h
diff --git a/src/quick3d/imports/core/qt3dquick3dcoreplugin.cpp b/src/quick3d/imports/core/qt3dquick3dcoreplugin.cpp
index 77eb505de..986431b4a 100644
--- a/src/quick3d/imports/core/qt3dquick3dcoreplugin.cpp
+++ b/src/quick3d/imports/core/qt3dquick3dcoreplugin.cpp
@@ -47,6 +47,7 @@
#include <Qt3DQuick/quick3dentityloader.h>
#include <Qt3DQuick/quick3dtransform.h>
#include <Qt3DQuick/quick3dconfiguration.h>
+#include <private/quick3dnodeinstantiator_p.h>
#include <private/qt3dquick_global_p.h>
QT_BEGIN_NAMESPACE
@@ -61,6 +62,7 @@ void Qt3DQuick3DCorePlugin::registerTypes(const char *uri)
qmlRegisterType<Qt3D::Quick::Quick3DConfiguration>(uri, 2, 0, "Configuration");
qmlRegisterExtendedType<Qt3D::QEntity, Qt3D::Quick::Quick3DEntity>(uri, 2, 0, "Entity");
qmlRegisterType<Qt3D::Quick::Quick3DEntityLoader>(uri, 2, 0, "EntityLoader");
+ qmlRegisterType<Qt3D::Quick::Quick3DNodeInstantiator>(uri, 2, 0, "NodeInstantiator");
qmlRegisterExtendedType<Qt3D::QTransform, Qt3D::Quick::Quick3DTransform>(uri, 2, 0, "Transform");
// Ideally we want to make Node an uncreatable type
// We would need qmlRegisterUncreatableExtendedType for that
diff --git a/src/quick3d/quick3d/items/items.pri b/src/quick3d/quick3d/items/items.pri
index edf00bd5e..0c01fe46f 100644
--- a/src/quick3d/quick3d/items/items.pri
+++ b/src/quick3d/quick3d/items/items.pri
@@ -4,13 +4,16 @@ HEADERS += \
$$PWD/quick3dentityloader.h \
$$PWD/quick3dentityloader_p.h \
$$PWD/quick3dtransform.h \
- $$PWD/quick3dconfiguration.h
+ $$PWD/quick3dconfiguration.h \
+ $$PWD/quick3dnodeinstantiator_p_p.h \
+ $$PWD/quick3dnodeinstantiator_p.h
SOURCES += \
$$PWD/quick3dnode.cpp \
$$PWD/quick3dentity.cpp \
$$PWD/quick3dentityloader.cpp \
$$PWD/quick3dtransform.cpp \
- $$PWD/quick3dconfiguration.cpp
+ $$PWD/quick3dconfiguration.cpp \
+ $$PWD/quick3dnodeinstantiator.cpp
INCLUDEPATH += $$PWD
diff --git a/src/quick3d/quick3d/items/quick3dnodeinstantiator.cpp b/src/quick3d/quick3d/items/quick3dnodeinstantiator.cpp
new file mode 100644
index 000000000..4684bd212
--- /dev/null
+++ b/src/quick3d/quick3d/items/quick3dnodeinstantiator.cpp
@@ -0,0 +1,492 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Research In Motion.
+** Copyright (C) 2015 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later as published by the Free
+** Software Foundation and appearing in the file LICENSE.GPL included in
+** the packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "quick3dnodeinstantiator_p.h"
+#include "quick3dnodeinstantiator_p_p.h"
+
+#include <QtQml/QQmlContext>
+#include <QtQml/QQmlComponent>
+#include <QtQml/QQmlInfo>
+#include <QtQml/QQmlError>
+#include <QtQml/private/qqmlobjectmodel_p.h>
+#include <QtQml/private/qqmldelegatemodel_p.h>
+
+QT_BEGIN_NAMESPACE
+
+namespace Qt3D {
+namespace Quick {
+
+Quick3DNodeInstantiatorPrivate::Quick3DNodeInstantiatorPrivate(QNode *qq)
+ : QNodePrivate(qq)
+ , m_componentComplete(true)
+ , m_effectiveReset(false)
+ , m_active(true)
+ , m_async(false)
+ , m_ownModel(false)
+ , m_model(QVariant(1))
+ , m_instanceModel(0)
+ , m_delegate(0)
+{
+}
+
+Quick3DNodeInstantiatorPrivate::~Quick3DNodeInstantiatorPrivate()
+{
+ qDeleteAll(m_objects);
+}
+
+void Quick3DNodeInstantiatorPrivate::clear()
+{
+ Q_Q(Quick3DNodeInstantiator);
+ if (!m_instanceModel)
+ return;
+ if (!m_objects.count())
+ return;
+
+ for (int i = 0; i < m_objects.count(); i++) {
+ q->objectRemoved(i, m_objects[i]);
+ m_instanceModel->release(m_objects[i]);
+ }
+ m_objects.clear();
+ q->objectChanged();
+}
+
+void Quick3DNodeInstantiatorPrivate::regenerate()
+{
+ Q_Q(Quick3DNodeInstantiator);
+ if (!m_componentComplete)
+ return;
+
+ int prevCount = q->count();
+
+ clear();
+
+ if (!m_active || !m_instanceModel || !m_instanceModel->count() || !m_instanceModel->isValid()) {
+ if (prevCount)
+ q->countChanged();
+ return;
+ }
+
+ for (int i = 0; i < m_instanceModel->count(); i++) {
+ QObject *object = m_instanceModel->object(i, m_async);
+ // If the item was already created we won't get a createdItem
+ if (object)
+ _q_createdItem(i, object);
+ }
+ if (q->count() != prevCount)
+ q->countChanged();
+}
+
+void Quick3DNodeInstantiatorPrivate::_q_createdItem(int idx, QObject *item)
+{
+ Q_Q(Quick3DNodeInstantiator);
+ if (m_objects.contains(item)) //Case when it was created synchronously in regenerate
+ return;
+ item->setParent(q);
+ m_objects.insert(idx, item);
+ if (m_objects.count() == 1)
+ q->objectChanged();
+ q->objectAdded(idx, item);
+}
+
+void Quick3DNodeInstantiatorPrivate::_q_modelUpdated(const QQmlChangeSet &changeSet, bool reset)
+{
+ Q_Q(Quick3DNodeInstantiator);
+
+ if (!m_componentComplete || m_effectiveReset)
+ return;
+
+ if (reset) {
+ regenerate();
+ if (changeSet.difference() != 0)
+ q->countChanged();
+ return;
+ }
+
+ int difference = 0;
+ QHash<int, QVector<QPointer<QObject> > > moved;
+ Q_FOREACH (const QQmlChangeSet::Change &remove, changeSet.removes()) {
+ int index = qMin(remove.index, m_objects.count());
+ int count = qMin(remove.index + remove.count, m_objects.count()) - index;
+ if (remove.isMove()) {
+ moved.insert(remove.moveId, m_objects.mid(index, count));
+ m_objects.erase(
+ m_objects.begin() + index,
+ m_objects.begin() + index + count);
+ } else {
+ while (count--) {
+ QObject *obj = m_objects.at(index);
+ m_objects.remove(index);
+ q->objectRemoved(index, obj);
+ if (obj)
+ m_instanceModel->release(obj);
+ }
+ }
+
+ difference -= remove.count;
+ }
+
+ Q_FOREACH (const QQmlChangeSet::Change &insert, changeSet.inserts()) {
+ int index = qMin(insert.index, m_objects.count());
+ if (insert.isMove()) {
+ QVector<QPointer<QObject> > movedObjects = moved.value(insert.moveId);
+ m_objects = m_objects.mid(0, index) + movedObjects + m_objects.mid(index);
+ } else for (int i = 0; i < insert.count; ++i) {
+ int modelIndex = index + i;
+ QObject *obj = m_instanceModel->object(modelIndex, m_async);
+ if (obj)
+ _q_createdItem(modelIndex, obj);
+ }
+ difference += insert.count;
+ }
+
+ if (difference != 0)
+ q->countChanged();
+}
+
+void Quick3DNodeInstantiatorPrivate::makeModel()
+{
+ Q_Q(Quick3DNodeInstantiator);
+ QQmlDelegateModel* delegateModel = new QQmlDelegateModel(qmlContext(q));
+ m_instanceModel = delegateModel;
+ m_ownModel = true;
+ delegateModel->setDelegate(m_delegate);
+ delegateModel->classBegin(); //Pretend it was made in QML
+ if (m_componentComplete)
+ delegateModel->componentComplete();
+}
+
+/*!
+ \qmltype NodeInstantiator
+ \instantiates Quick3DNodeInstantiator
+ \inqmlmodule Quick3D
+ \brief Dynamically creates nodes
+ \since 5.5
+
+ A NodeInstantiator can be used to control the dynamic creation of nodes, or to dynamically
+ create multiple objects from a template.
+
+ The NodeInstantiator element will manage the objects it creates. Those
+ objects are parented to the Instantiator and can also be deleted by the
+ NodeInstantiator if the NodeInstantiator's properties change. Nodes can
+ also be destroyed dynamically through other means, and the NodeInstantiator
+ will not recreate them unless the properties of the NodeInstantiator
+ change.
+
+*/
+Quick3DNodeInstantiator::Quick3DNodeInstantiator(QNode *parent)
+ : QNode(*(new Quick3DNodeInstantiatorPrivate(this)), parent)
+{
+}
+
+Quick3DNodeInstantiator::~Quick3DNodeInstantiator()
+{
+}
+
+/*!
+ \qmlsignal Quick3D::NodeInstantiator::objectAdded(int index, QtObject node)
+
+ This signal is emitted when a node is added to the NodeInstantiator. The \a index
+ parameter holds the index which the node has been given, and the \a node
+ parameter holds the \l Node that has been added.
+
+ The corresponding handler is \c onNodeAdded.
+*/
+
+/*!
+ \qmlsignal Quick3D::NodeInstantiator::objectRemoved(int index, QtObject object)
+
+ This signal is emitted when an object is removed from the Instantiator. The \a index
+ parameter holds the index which the object had been given, and the \a object
+ parameter holds the \l QtObject that has been removed.
+
+ Do not keep a reference to \a object if it was created by this Instantiator, as
+ in these cases it will be deleted shortly after the signal is handled.
+
+ The corresponding handler is \c onObjectRemoved.
+*/
+/*!
+ \qmlproperty bool Quick3D::NodeInstantiator::active
+
+ When active is true, and the delegate component is ready, the Instantiator will
+ create objects according to the model. When active is false, no objects
+ will be created and any previously created objects will be destroyed.
+
+ Default is true.
+*/
+bool Quick3DNodeInstantiator::isActive() const
+{
+ Q_D(const Quick3DNodeInstantiator);
+ return d->m_active;
+}
+
+void Quick3DNodeInstantiator::setActive(bool newVal)
+{
+ Q_D(Quick3DNodeInstantiator);
+ if (newVal == d->m_active)
+ return;
+ d->m_active = newVal;
+ emit activeChanged();
+ d->regenerate();
+}
+
+/*!
+ \qmlproperty bool Quick3D::NodeInstantiator::asynchronous
+
+ When asynchronous is true the Instantiator will attempt to create objects
+ asynchronously. This means that objects may not be available immediately,
+ even if active is set to true.
+
+ You can use the objectAdded signal to respond to items being created.
+
+ Default is false.
+*/
+bool Quick3DNodeInstantiator::isAsync() const
+{
+ Q_D(const Quick3DNodeInstantiator);
+ return d->m_async;
+}
+
+void Quick3DNodeInstantiator::setAsync(bool newVal)
+{
+ Q_D(Quick3DNodeInstantiator);
+ if (newVal == d->m_async)
+ return;
+ d->m_async = newVal;
+ emit asynchronousChanged();
+}
+
+
+/*!
+ \qmlproperty int Quick3D::NodeInstantiator::count
+
+ The number of objects the Instantiator is currently managing.
+*/
+
+int Quick3DNodeInstantiator::count() const
+{
+ Q_D(const Quick3DNodeInstantiator);
+ return d->m_objects.count();
+}
+
+/*!
+ \qmlproperty QtQml::Component Quick3D::NodeInstantiator::delegate
+ \default
+
+ The component used to create all objects.
+
+ Note that an extra variable, index, will be available inside instances of the
+ delegate. This variable refers to the index of the instance inside the Instantiator,
+ and can be used to obtain the object through the itemAt method of the Instantiator.
+
+ If this property is changed, all instances using the old delegate will be destroyed
+ and new instances will be created using the new delegate.
+*/
+QQmlComponent *Quick3DNodeInstantiator::delegate()
+{
+ Q_D(Quick3DNodeInstantiator);
+ return d->m_delegate;
+}
+
+void Quick3DNodeInstantiator::setDelegate(QQmlComponent *c)
+{
+ Q_D(Quick3DNodeInstantiator);
+ if (c == d->m_delegate)
+ return;
+
+ d->m_delegate = c;
+ emit delegateChanged();
+
+ if (!d->m_ownModel)
+ return;
+
+ if (QQmlDelegateModel *dModel = qobject_cast<QQmlDelegateModel*>(d->m_instanceModel))
+ dModel->setDelegate(c);
+ if (d->m_componentComplete)
+ d->regenerate();
+}
+
+/*!
+ \qmlproperty variant Quick3D::NodeInstantiator::model
+
+ This property can be set to any of the supported \l {qml-data-models}{data models}:
+
+ \list
+ \li A number that indicates the number of delegates to be created by the repeater
+ \li A model (e.g. a ListModel item, or a QAbstractItemModel subclass)
+ \li A string list
+ \li An object list
+ \endlist
+
+ The type of model affects the properties that are exposed to the \l delegate.
+
+ Default value is 1, which creates a single delegate instance.
+
+ \sa {qml-data-models}{Data Models}
+*/
+
+QVariant Quick3DNodeInstantiator::model() const
+{
+ Q_D(const Quick3DNodeInstantiator);
+ return d->m_model;
+}
+
+void Quick3DNodeInstantiator::setModel(const QVariant &v)
+{
+ Q_D(Quick3DNodeInstantiator);
+ if (d->m_model == v)
+ return;
+
+ d->m_model = v;
+ //Don't actually set model until componentComplete in case it wants to create its delegates immediately
+ if (!d->m_componentComplete)
+ return;
+
+ QQmlInstanceModel *prevModel = d->m_instanceModel;
+ QObject *object = qvariant_cast<QObject*>(v);
+ QQmlInstanceModel *vim = 0;
+ if (object && (vim = qobject_cast<QQmlInstanceModel *>(object))) {
+ if (d->m_ownModel) {
+ delete d->m_instanceModel;
+ prevModel = 0;
+ d->m_ownModel = false;
+ }
+ d->m_instanceModel = vim;
+ } else if (v != QVariant(0)){
+ if (!d->m_ownModel)
+ d->makeModel();
+
+ if (QQmlDelegateModel *dataModel = qobject_cast<QQmlDelegateModel *>(d->m_instanceModel)) {
+ d->m_effectiveReset = true;
+ dataModel->setModel(v);
+ d->m_effectiveReset = false;
+ }
+ }
+
+ if (d->m_instanceModel != prevModel) {
+ if (prevModel) {
+ disconnect(prevModel, SIGNAL(modelUpdated(QQmlChangeSet,bool)),
+ this, SLOT(_q_modelUpdated(QQmlChangeSet,bool)));
+ disconnect(prevModel, SIGNAL(createdItem(int,QObject*)), this, SLOT(_q_createdItem(int,QObject*)));
+ //disconnect(prevModel, SIGNAL(initItem(int,QObject*)), this, SLOT(initItem(int,QObject*)));
+ }
+
+ connect(d->m_instanceModel, SIGNAL(modelUpdated(QQmlChangeSet,bool)),
+ this, SLOT(_q_modelUpdated(QQmlChangeSet,bool)));
+ connect(d->m_instanceModel, SIGNAL(createdItem(int,QObject*)), this, SLOT(_q_createdItem(int,QObject*)));
+ //connect(d->m_instanceModel, SIGNAL(initItem(int,QObject*)), this, SLOT(initItem(int,QObject*)));
+ }
+
+ d->regenerate();
+ emit modelChanged();
+}
+
+/*!
+ \qmlproperty QtQml::QtObject Quick3D::NodeInstantiator::object
+
+ This is a reference to the first created object, intended as a convenience
+ for the case where only one object has been created.
+*/
+QObject *Quick3DNodeInstantiator::object() const
+{
+ Q_D(const Quick3DNodeInstantiator);
+ if (d->m_objects.count())
+ return d->m_objects[0];
+ return 0;
+}
+
+/*!
+ \qmlmethod QtQml::QtObject Quick3D::NodeInstantiator::objectAt
+
+ Returns a reference to the object with the given \a index.
+*/
+QObject *Quick3DNodeInstantiator::objectAt(int index) const
+{
+ Q_D(const Quick3DNodeInstantiator);
+ if (index >= 0 && index < d->m_objects.count())
+ return d->m_objects[index];
+ return 0;
+}
+
+/*!
+ \internal
+*/
+void Quick3DNodeInstantiator::classBegin()
+{
+ Q_D(Quick3DNodeInstantiator);
+ d->m_componentComplete = false;
+}
+
+/*!
+ \internal
+*/
+void Quick3DNodeInstantiator::componentComplete()
+{
+ Q_D(Quick3DNodeInstantiator);
+ d->m_componentComplete = true;
+ if (d->m_ownModel) {
+ static_cast<QQmlDelegateModel *>(d->m_instanceModel)->componentComplete();
+ d->regenerate();
+ } else {
+ QVariant realModel = d->m_model;
+ d->m_model = QVariant(0);
+ setModel(realModel); //If realModel == d->m_model this won't do anything, but that's fine since the model's 0
+ //setModel calls regenerate
+ }
+}
+
+void Quick3DNodeInstantiator::copy(const QNode *ref)
+{
+ QNode::copy(ref);
+ const Quick3DNodeInstantiator *instantiator = static_cast<const Quick3DNodeInstantiator*>(ref);
+ // We only need to clone the children as the instantiator itself has no
+ // corresponding backend node type.
+ for (int i = 0; i < instantiator->d_func()->m_objects.size(); ++i) {
+ QNode *n = qobject_cast<QNode *>(instantiator->d_func()->m_objects.at(i));
+ if (!n)
+ continue;
+ QNode *clonedNode = QNode::clone(n);
+ clonedNode->setParent(this);
+ d_func()->m_objects.append(clonedNode);
+ }
+}
+
+} // namespace Quick
+} // namespace Qt3D
+
+QT_END_NAMESPACE
+
+#include "moc_quick3dnodeinstantiator_p.cpp"
diff --git a/src/quick3d/quick3d/items/quick3dnodeinstantiator_p.h b/src/quick3d/quick3d/items/quick3dnodeinstantiator_p.h
new file mode 100644
index 000000000..e4171b303
--- /dev/null
+++ b/src/quick3d/quick3d/items/quick3dnodeinstantiator_p.h
@@ -0,0 +1,118 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Research In Motion.
+** Copyright (C) 2015 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later as published by the Free
+** Software Foundation and appearing in the file LICENSE.GPL included in
+** the packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QT3D_QUICK_NODEINSTANTIATOR_H
+#define QT3D_QUICK_NODEINSTANTIATOR_H
+
+#include <Qt3DQuick/qt3dquick_global.h>
+#include <Qt3DCore/qnode.h>
+#include <QtQml/qqmlcomponent.h>
+#include <QtQml/qqmlparserstatus.h>
+
+QT_BEGIN_NAMESPACE
+
+namespace Qt3D {
+namespace Quick {
+
+class Quick3DNodeInstantiatorPrivate;
+
+class QT3DQUICKSHARED_EXPORT Quick3DNodeInstantiator : public QNode, public QQmlParserStatus
+{
+ Q_OBJECT
+
+ Q_INTERFACES(QQmlParserStatus)
+
+ Q_PROPERTY(bool active READ isActive WRITE setActive NOTIFY activeChanged)
+ Q_PROPERTY(bool asynchronous READ isAsync WRITE setAsync NOTIFY asynchronousChanged)
+ Q_PROPERTY(QVariant model READ model WRITE setModel NOTIFY modelChanged)
+ Q_PROPERTY(int count READ count NOTIFY countChanged)
+ Q_PROPERTY(QQmlComponent *delegate READ delegate WRITE setDelegate NOTIFY delegateChanged)
+ Q_PROPERTY(QObject *object READ object NOTIFY objectChanged)
+ Q_CLASSINFO("DefaultProperty", "delegate")
+
+public:
+ Quick3DNodeInstantiator(QNode *parent = 0);
+ ~Quick3DNodeInstantiator();
+
+ bool isActive() const;
+ void setActive(bool newVal);
+
+ bool isAsync() const;
+ void setAsync(bool newVal);
+
+ int count() const;
+
+ QQmlComponent *delegate();
+ void setDelegate(QQmlComponent *c);
+
+ QVariant model() const;
+ void setModel(const QVariant &v);
+
+ QObject *object() const;
+ Q_INVOKABLE QObject *objectAt(int index) const;
+
+ void classBegin();
+ void componentComplete();
+
+Q_SIGNALS:
+ void modelChanged();
+ void delegateChanged();
+ void countChanged();
+ void objectChanged();
+ void activeChanged();
+ void asynchronousChanged();
+
+ void objectAdded(int index, QObject *object);
+ void objectRemoved(int index, QObject *object);
+
+protected:
+ void copy(const QNode *ref) Q_DECL_OVERRIDE;
+
+private:
+ QT3D_CLONEABLE(Quick3DNodeInstantiator)
+ Q_DISABLE_COPY(Quick3DNodeInstantiator)
+ Q_DECLARE_PRIVATE(Quick3DNodeInstantiator)
+ Q_PRIVATE_SLOT(d_func(), void _q_createdItem(int, QObject *))
+ Q_PRIVATE_SLOT(d_func(), void _q_modelUpdated(const QQmlChangeSet &, bool))
+};
+
+} // namespace Quick
+} // namespace Qt3D
+
+QT_END_NAMESPACE
+
+#endif // QT3D_QUICK_NODEINSTANTIATOR_H
diff --git a/src/quick3d/quick3d/items/quick3dnodeinstantiator_p_p.h b/src/quick3d/quick3d/items/quick3dnodeinstantiator_p_p.h
new file mode 100644
index 000000000..274fa752d
--- /dev/null
+++ b/src/quick3d/quick3d/items/quick3dnodeinstantiator_p_p.h
@@ -0,0 +1,83 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Research In Motion.
+** Copyright (C) 2015 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later as published by the Free
+** Software Foundation and appearing in the file LICENSE.GPL included in
+** the packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QT3D_QUICK_QUICK3DNODEINSTANTIATOR_P_P_H
+#define QT3D_QUICK_QUICK3DNODEINSTANTIATOR_P_P_H
+
+#include <private/qnode_p.h>
+#include <private/qqmlchangeset_p.h>
+#include <private/qqmlobjectmodel_p.h>
+
+QT_BEGIN_NAMESPACE
+
+class QQmlComponent;
+
+namespace Qt3D {
+namespace Quick {
+
+class Quick3DNodeInstantiatorPrivate : public QNodePrivate
+{
+ Q_DECLARE_PUBLIC(Quick3DNodeInstantiator)
+
+public:
+ Quick3DNodeInstantiatorPrivate(QNode *qq);
+ ~Quick3DNodeInstantiatorPrivate();
+
+ void clear();
+ void regenerate();
+ void makeModel();
+ void _q_createdItem(int, QObject *);
+ void _q_modelUpdated(const QQmlChangeSet &, bool);
+
+ bool m_componentComplete:1;
+ bool m_effectiveReset:1;
+ bool m_active:1;
+ bool m_async:1;
+ bool m_ownModel:1;
+ QVariant m_model;
+ QQmlInstanceModel *m_instanceModel;
+ QQmlComponent *m_delegate;
+ QVector<QPointer<QObject> > m_objects;
+};
+
+} // namespace Quick
+} // namespace Qt3D
+
+QT_END_NAMESPACE
+
+#endif // QT3D_QUICK_QUICK3DNODEINSTANTIATOR_P_P_H
+