137void QQuick3DObject::setParentItem(QQuick3DObject *parentItem)
140 if (parentItem == d->parentItem)
144 QQuick3DObject *itemAncestor = parentItem;
145 while (itemAncestor !=
nullptr) {
146 if (Q_UNLIKELY(itemAncestor ==
this)) {
147 qWarning() <<
"QSSGObject::setParentItem: Parent" << parentItem <<
"is already part of the subtree of" <<
this;
150 itemAncestor = itemAncestor->parentItem();
154 d->removeFromDirtyList();
156 QQuick3DObject *oldParentItem = d->parentItem;
159 QQuick3DObjectPrivate *op = QQuick3DObjectPrivate::get(oldParentItem);
161 op->removeChild(
this);
162 }
else if (d->sceneManager) {
163 d->sceneManager->parentlessItems.remove(
this);
166 const auto parentSceneManager = parentItem ? QQuick3DObjectPrivate::get(parentItem)->sceneManager :
nullptr;
167 if (d->sceneManager == parentSceneManager) {
169 d->parentItem = parentItem;
172 QQuick3DObjectPrivate::derefSceneManager(
this);
173 d->parentItem = parentItem;
174 if (parentSceneManager)
175 QQuick3DObjectPrivate::refSceneManager(
this, *parentSceneManager);
178 d->dirty(QQuick3DObjectPrivate::ParentChanged);
181 QQuick3DObjectPrivate::get(d->parentItem)->addChild(
this);
182 else if (d->sceneManager)
183 d->sceneManager->parentlessItems.insert(
this);
185 d->itemChange(ItemParentHasChanged, d->parentItem);
187 emit parentChanged();
524void QQuick3DObjectPrivate::data_append(QQmlListProperty<QObject> *prop, QObject *o)
529 QQuick3DObject *that =
static_cast<QQuick3DObject *>(prop->object);
530 QQuick3DObjectPrivate *privateItem = QQuick3DObjectPrivate::get(that);
532 if (QQuick3DObject *item = qmlobject_cast<QQuick3DObject *>(o)) {
533 item->setParentItem(that);
536 QQuickItem *quickItem = qobject_cast<QQuickItem *>(o);
538 if (!privateItem->contentItem2d) {
539 privateItem->contentItem2d =
new QQuick3DItem2D(quickItem);
540 privateItem->contentItem2d->setParent(that);
541 privateItem->contentItem2d->setParentItem(that);
543 privateItem->contentItem2d->addChildItem(quickItem);
545 qmlobject_connect(privateItem->contentItem2d, QQuick3DItem2D, SIGNAL(allChildrenRemoved()),
546 that, QQuick3DObject, SLOT(_q_cleanupContentItem2D()));
551 resources_append(prop, o);
564QObject *QQuick3DObjectPrivate::data_at(QQmlListProperty<QObject> *property, qsizetype i)
566 QQuick3DObject *item =
static_cast<QQuick3DObject *>(property->object);
567 QQuick3DObjectPrivate *privateItem = QQuick3DObjectPrivate::get(item);
568 QQmlListProperty<QObject> resourcesProperty = privateItem->resources();
569 QQmlListProperty<QQuick3DObject> childrenProperty = privateItem->children();
571 int resourcesCount = resources_count(&resourcesProperty);
572 if (i < resourcesCount)
573 return resources_at(&resourcesProperty, i);
574 const int j = i - resourcesCount;
575 if (j < children_count(&childrenProperty))
576 return children_at(&childrenProperty, j);
597void QQuick3DObjectPrivate::resources_append(QQmlListProperty<QObject> *prop, QObject *object)
599 QQuick3DObject *quickItem =
static_cast<QQuick3DObject *>(prop->object);
600 QQuick3DObjectPrivate *quickItemPrivate = QQuick3DObjectPrivate::get(quickItem);
601 if (!quickItemPrivate->extra.value().resourcesList.contains(object)) {
602 quickItemPrivate->extra.value().resourcesList.append(object);
604 qmlobject_connect(object, QObject, SIGNAL(destroyed(QObject*)),
605 quickItem, QQuick3DObject, SLOT(_q_resourceObjectDeleted(QObject*)));
616void QQuick3DObjectPrivate::resources_clear(QQmlListProperty<QObject> *prop)
618 QQuick3DObject *quickItem =
static_cast<QQuick3DObject *>(prop->object);
619 QQuick3DObjectPrivate *quickItemPrivate = QQuick3DObjectPrivate::get(quickItem);
620 if (quickItemPrivate->extra.isAllocated()) {
621 for (QObject *object : std::as_const(quickItemPrivate->extra->resourcesList)) {
623 qmlobject_disconnect(object, QObject, SIGNAL(destroyed(QObject*)),
624 quickItem, QQuick3DObject, SLOT(_q_resourceObjectDeleted(QObject*)));
627 quickItemPrivate->extra->resourcesList.clear();
769void QQuick3DObjectPrivate::addToDirtyList()
773 Q_ASSERT(sceneManager);
774 if (!prevDirtyItem) {
775 Q_ASSERT(!nextDirtyItem);
777 if (QSSGRenderGraphObject::isNodeType(type)) {
780 const bool hasInstanceRoot = (type == Type::Model &&
static_cast<QQuick3DModel *>(q)->instanceRoot() &&
static_cast<QQuick3DModel *>(q)->instanceRoot() != q);
781 const auto dirtyListIdx = !hasInstanceRoot ? QQuick3DSceneManager::nodeListIndex(type)
782 : size_t(QQuick3DSceneManager::NodePriority::ModelWithInstanceRoot);
783 nextDirtyItem = sceneManager->dirtyNodes[dirtyListIdx];
785 QQuick3DObjectPrivate::get(nextDirtyItem)->prevDirtyItem = &nextDirtyItem;
786 prevDirtyItem = &sceneManager->dirtyNodes[dirtyListIdx];
787 sceneManager->dirtyNodes[dirtyListIdx] = q;
788 }
else if (QSSGRenderGraphObject::isExtension(type)) {
789 const auto dirtyListIdx = QQuick3DSceneManager::extensionListIndex(type);
790 nextDirtyItem = sceneManager->dirtyExtensions[dirtyListIdx];
792 QQuick3DObjectPrivate::get(nextDirtyItem)->prevDirtyItem = &nextDirtyItem;
793 prevDirtyItem = &sceneManager->dirtyExtensions[dirtyListIdx];
794 sceneManager->dirtyExtensions[dirtyListIdx] = q;
796 const auto dirtyListIdx = QQuick3DSceneManager::resourceListIndex(type);
797 nextDirtyItem = sceneManager->dirtyResources[dirtyListIdx];
799 QQuick3DObjectPrivate::get(nextDirtyItem)->prevDirtyItem = &nextDirtyItem;
800 prevDirtyItem = &sceneManager->dirtyResources[dirtyListIdx];
801 sceneManager->dirtyResources[dirtyListIdx] = q;
804 sceneManager->dirtyItem(q);
805 Q_ASSERT(prevDirtyItem);
875void QQuick3DObjectPrivate::refSceneManager(QQuick3DSceneManager &c)
889 if (sceneManager.isNull() && sceneRefCount == 1)
892 Q_ASSERT((sceneManager !=
nullptr) == (sceneRefCount > 0));
893 if (++sceneRefCount > 1) {
895 if (c.window() != sceneManager->window()) {
896 qWarning(
"QSSGObject: Cannot use same item on different windows at the same time.");
901 if (&c != sceneManager) {
902 sharedResource =
true;
903 for (
int ii = 0; ii < childItems.size(); ++ii) {
904 QQuick3DObject *child = childItems.at(ii);
905 QQuick3DObjectPrivate::get(child)->sharedResource = sharedResource;
906 QQuick3DObjectPrivate::refSceneManager(child, c);
913 Q_ASSERT(sceneManager ==
nullptr);
920 sceneManager->parentlessItems.insert(q);
922 sharedResource = QQuick3DObjectPrivate::get(parentItem)->sharedResource;
924 for (
int ii = 0; ii < childItems.size(); ++ii) {
925 QQuick3DObject *child = childItems.at(ii);
926 QQuick3DObjectPrivate::get(child)->sharedResource = sharedResource;
927 QQuick3DObjectPrivate::refSceneManager(child, c);
932 itemChange(QQuick3DObject::ItemSceneChange, &c);
935void QQuick3DObjectPrivate::derefSceneManager()
942 if (--sceneRefCount > 0)
945 removeFromDirtyList();
947 sceneManager->dirtyBoundingBoxList.removeAll(q);
949 for (
int ii = 0; ii < childItems.size(); ++ii) {
950 QQuick3DObject *child = childItems.at(ii);
951 QQuick3DObjectPrivate::derefSceneManager(child);
955 sceneManager->parentlessItems.remove(q);
958 sceneManager->cleanup(spatialNode);
959 spatialNode =
nullptr;
962 sceneManager =
nullptr;
966 itemChange(QQuick3DObject::ItemSceneChange, sceneManager.data());
969void QQuick3DObjectPrivate::updateSubFocusItem(QQuick3DObject *scope,
bool focus)
974 QQuick3DObjectPrivate *scopePrivate = QQuick3DObjectPrivate::get(scope);
976 QQuick3DObject *oldSubFocusItem = scopePrivate->subFocusItem;
978 if (oldSubFocusItem) {
979 QQuick3DObject *sfi = scopePrivate->subFocusItem->parentItem();
980 while (sfi && sfi != scope) {
981 QQuick3DObjectPrivate::get(sfi)->subFocusItem =
nullptr;
982 sfi = sfi->parentItem();
987 scopePrivate->subFocusItem = q;
988 QQuick3DObject *sfi = scopePrivate->subFocusItem->parentItem();
989 while (sfi && sfi != scope) {
990 QQuick3DObjectPrivate::get(sfi)->subFocusItem = q;
991 sfi = sfi->parentItem();
994 scopePrivate->subFocusItem =
nullptr;
998void QQuick3DObjectPrivate::itemChange(QQuick3DObject::ItemChange change,
const QQuick3DObject::ItemChangeData &data)
1000 Q_Q(QQuick3DObject);
1002 case QQuick3DObject::ItemRotationHasChanged:
1004 qWarning(
"ItemRoationHasChange is unhandled!!!!");
1006 case QQuick3DObject::ItemChildAddedChange: {
1007 q->itemChange(change, data);
1008 if (!changeListeners.isEmpty()) {
1009 const auto listeners = changeListeners;
1010 for (
const QQuick3DObjectPrivate::ChangeListener &change : listeners) {
1011 if (change.types & QQuick3DObjectPrivate::Children) {
1012 change.listener->itemChildAdded(q, data.item);
1018 case QQuick3DObject::ItemChildRemovedChange: {
1019 q->itemChange(change, data);
1020 if (!changeListeners.isEmpty()) {
1021 const auto listeners = changeListeners;
1022 for (
const QQuick3DObjectPrivate::ChangeListener &change : listeners) {
1023 if (change.types & QQuick3DObjectPrivate::Children) {
1024 change.listener->itemChildRemoved(q, data.item);
1030 case QQuick3DObject::ItemSceneChange:
1031 q->itemChange(change, data);
1033 case QQuick3DObject::ItemVisibleHasChanged: {
1034 q->itemChange(change, data);
1035 if (!changeListeners.isEmpty()) {
1036 const auto listeners = changeListeners;
1037 for (
const QQuick3DObjectPrivate::ChangeListener &change : listeners) {
1038 if (change.types & QQuick3DObjectPrivate::Visibility) {
1039 change.listener->itemVisibilityChanged(q);
1045 case QQuick3DObject::ItemEnabledHasChanged: {
1046 q->itemChange(change, data);
1047 if (!changeListeners.isEmpty()) {
1048 const auto listeners = changeListeners;
1049 for (
const QQuick3DObjectPrivate::ChangeListener &change : listeners) {
1050 if (change.types & QQuick3DObjectPrivate::Enabled) {
1051 change.listener->itemEnabledChanged(q);
1057 case QQuick3DObject::ItemParentHasChanged: {
1058 q->itemChange(change, data);
1059 if (!changeListeners.isEmpty()) {
1060 const auto listeners = changeListeners;
1061 for (
const QQuick3DObjectPrivate::ChangeListener &change : listeners) {
1062 if (change.types & QQuick3DObjectPrivate::Parent) {
1063 change.listener->itemParentChanged(q, data.item);
1069 case QQuick3DObject::ItemOpacityHasChanged: {
1070 q->itemChange(change, data);
1071 if (!changeListeners.isEmpty()) {
1072 const auto listeners = changeListeners;
1073 for (
const QQuick3DObjectPrivate::ChangeListener &change : listeners) {
1074 if (change.types & QQuick3DObjectPrivate::Opacity) {
1075 change.listener->itemOpacityChanged(q);
1081 case QQuick3DObject::ItemActiveFocusHasChanged:
1082 q->itemChange(change, data);
1084 case QQuick3DObject::ItemAntialiasingHasChanged:
1086 case QQuick3DObject::ItemDevicePixelRatioHasChanged:
1087 q->itemChange(change, data);