135void QQuick3DObject::setParentItem(QQuick3DObject *parentItem)
138 if (parentItem == d->parentItem)
142 QQuick3DObject *itemAncestor = parentItem;
143 while (itemAncestor !=
nullptr) {
144 if (Q_UNLIKELY(itemAncestor ==
this)) {
145 qWarning() <<
"QSSGObject::setParentItem: Parent" << parentItem <<
"is already part of the subtree of" <<
this;
148 itemAncestor = itemAncestor->parentItem();
152 d->removeFromDirtyList();
154 QQuick3DObject *oldParentItem = d->parentItem;
157 QQuick3DObjectPrivate *op = QQuick3DObjectPrivate::get(oldParentItem);
159 op->removeChild(
this);
160 }
else if (d->sceneManager) {
161 d->sceneManager->parentlessItems.remove(
this);
164 const auto parentSceneManager = parentItem ? QQuick3DObjectPrivate::get(parentItem)->sceneManager :
nullptr;
165 if (d->sceneManager == parentSceneManager) {
167 d->parentItem = parentItem;
170 QQuick3DObjectPrivate::derefSceneManager(
this);
171 d->parentItem = parentItem;
172 if (parentSceneManager)
173 QQuick3DObjectPrivate::refSceneManager(
this, *parentSceneManager);
176 d->dirty(QQuick3DObjectPrivate::ParentChanged);
179 QQuick3DObjectPrivate::get(d->parentItem)->addChild(
this);
180 else if (d->sceneManager)
181 d->sceneManager->parentlessItems.insert(
this);
183 d->itemChange(ItemParentHasChanged, d->parentItem);
185 emit parentChanged();
580void QQuick3DObjectPrivate::data_append(QQmlListProperty<QObject> *prop, QObject *o)
585 QQuick3DObject *that =
static_cast<QQuick3DObject *>(prop->object);
586 QQuick3DObjectPrivate *privateItem = QQuick3DObjectPrivate::get(that);
588 if (QQuick3DObject *item = qmlobject_cast<QQuick3DObject *>(o)) {
589 item->setParentItem(that);
592 QQuickItem *quickItem = qobject_cast<QQuickItem *>(o);
594 if (!privateItem->contentItem2d) {
595 privateItem->contentItem2d =
new QQuick3DItem2D(quickItem);
596 privateItem->contentItem2d->setParent(that);
597 privateItem->contentItem2d->setParentItem(that);
599 privateItem->contentItem2d->addChildItem(quickItem);
601 qmlobject_connect(privateItem->contentItem2d, QQuick3DItem2D, SIGNAL(allChildrenRemoved()),
602 that, QQuick3DObject, SLOT(_q_cleanupContentItem2D()));
607 resources_append(prop, o);
620QObject *QQuick3DObjectPrivate::data_at(QQmlListProperty<QObject> *property, qsizetype i)
622 QQuick3DObject *item =
static_cast<QQuick3DObject *>(property->object);
623 QQuick3DObjectPrivate *privateItem = QQuick3DObjectPrivate::get(item);
624 QQmlListProperty<QObject> resourcesProperty = privateItem->resources();
625 QQmlListProperty<QQuick3DObject> childrenProperty = privateItem->children();
627 int resourcesCount = resources_count(&resourcesProperty);
628 if (i < resourcesCount)
629 return resources_at(&resourcesProperty, i);
630 const int j = i - resourcesCount;
631 if (j < children_count(&childrenProperty))
632 return children_at(&childrenProperty, j);
653void QQuick3DObjectPrivate::resources_append(QQmlListProperty<QObject> *prop, QObject *object)
655 QQuick3DObject *quickItem =
static_cast<QQuick3DObject *>(prop->object);
656 QQuick3DObjectPrivate *quickItemPrivate = QQuick3DObjectPrivate::get(quickItem);
657 if (!quickItemPrivate->extra.value().resourcesList.contains(object)) {
658 quickItemPrivate->extra.value().resourcesList.append(object);
660 qmlobject_connect(object, QObject, SIGNAL(destroyed(QObject*)),
661 quickItem, QQuick3DObject, SLOT(_q_resourceObjectDeleted(QObject*)));
672void QQuick3DObjectPrivate::resources_clear(QQmlListProperty<QObject> *prop)
674 QQuick3DObject *quickItem =
static_cast<QQuick3DObject *>(prop->object);
675 QQuick3DObjectPrivate *quickItemPrivate = QQuick3DObjectPrivate::get(quickItem);
676 if (quickItemPrivate->extra.isAllocated()) {
677 for (QObject *object : std::as_const(quickItemPrivate->extra->resourcesList)) {
679 qmlobject_disconnect(object, QObject, SIGNAL(destroyed(QObject*)),
680 quickItem, QQuick3DObject, SLOT(_q_resourceObjectDeleted(QObject*)));
683 quickItemPrivate->extra->resourcesList.clear();
825void QQuick3DObjectPrivate::addToDirtyList()
829 Q_ASSERT(sceneManager);
830 if (!prevDirtyItem) {
831 Q_ASSERT(!nextDirtyItem);
833 if (QSSGRenderGraphObject::isNodeType(type)) {
836 const bool hasInstanceRoot = (type == Type::Model &&
static_cast<QQuick3DModel *>(q)->instanceRoot() &&
static_cast<QQuick3DModel *>(q)->instanceRoot() != q);
837 const auto dirtyListIdx = !hasInstanceRoot ? QQuick3DSceneManager::nodeListIndex(type)
838 : size_t(QQuick3DSceneManager::NodePriority::ModelWithInstanceRoot);
839 nextDirtyItem = sceneManager->dirtyNodes[dirtyListIdx];
841 QQuick3DObjectPrivate::get(nextDirtyItem)->prevDirtyItem = &nextDirtyItem;
842 prevDirtyItem = &sceneManager->dirtyNodes[dirtyListIdx];
843 sceneManager->dirtyNodes[dirtyListIdx] = q;
844 }
else if (QSSGRenderGraphObject::isExtension(type)) {
845 const auto dirtyListIdx = QQuick3DSceneManager::extensionListIndex(type);
846 nextDirtyItem = sceneManager->dirtyExtensions[dirtyListIdx];
848 QQuick3DObjectPrivate::get(nextDirtyItem)->prevDirtyItem = &nextDirtyItem;
849 prevDirtyItem = &sceneManager->dirtyExtensions[dirtyListIdx];
850 sceneManager->dirtyExtensions[dirtyListIdx] = q;
852 const auto dirtyListIdx = QQuick3DSceneManager::resourceListIndex(type);
853 nextDirtyItem = sceneManager->dirtyResources[dirtyListIdx];
855 QQuick3DObjectPrivate::get(nextDirtyItem)->prevDirtyItem = &nextDirtyItem;
856 prevDirtyItem = &sceneManager->dirtyResources[dirtyListIdx];
857 sceneManager->dirtyResources[dirtyListIdx] = q;
860 sceneManager->dirtyItem(q);
861 Q_ASSERT(prevDirtyItem);
931void QQuick3DObjectPrivate::refSceneManager(QQuick3DSceneManager &c)
945 if (sceneManager.isNull() && sceneRefCount == 1)
948 Q_ASSERT((sceneManager !=
nullptr) == (sceneRefCount > 0));
949 if (++sceneRefCount > 1) {
951 if (c.window() != sceneManager->window()) {
952 qWarning(
"QSSGObject: Cannot use same item on different windows at the same time.");
957 if (&c != sceneManager) {
958 sharedResource =
true;
959 for (
int ii = 0; ii < childItems.size(); ++ii) {
960 QQuick3DObject *child = childItems.at(ii);
961 QQuick3DObjectPrivate::get(child)->sharedResource = sharedResource;
962 QQuick3DObjectPrivate::refSceneManager(child, c);
969 Q_ASSERT(sceneManager ==
nullptr);
976 sceneManager->parentlessItems.insert(q);
978 sharedResource = QQuick3DObjectPrivate::get(parentItem)->sharedResource;
980 for (
int ii = 0; ii < childItems.size(); ++ii) {
981 QQuick3DObject *child = childItems.at(ii);
982 QQuick3DObjectPrivate::get(child)->sharedResource = sharedResource;
983 QQuick3DObjectPrivate::refSceneManager(child, c);
988 itemChange(QQuick3DObject::ItemSceneChange, &c);
991void QQuick3DObjectPrivate::derefSceneManager()
998 if (--sceneRefCount > 0)
1001 removeFromDirtyList();
1003 sceneManager->dirtyBoundingBoxList.removeAll(q);
1005 for (
int ii = 0; ii < childItems.size(); ++ii) {
1006 QQuick3DObject *child = childItems.at(ii);
1007 QQuick3DObjectPrivate::derefSceneManager(child);
1011 sceneManager->parentlessItems.remove(q);
1014 sceneManager->cleanup(spatialNode);
1015 spatialNode =
nullptr;
1018 sceneManager =
nullptr;
1022 itemChange(QQuick3DObject::ItemSceneChange, sceneManager.data());
1025void QQuick3DObjectPrivate::updateSubFocusItem(QQuick3DObject *scope,
bool focus)
1027 Q_Q(QQuick3DObject);
1030 QQuick3DObjectPrivate *scopePrivate = QQuick3DObjectPrivate::get(scope);
1032 QQuick3DObject *oldSubFocusItem = scopePrivate->subFocusItem;
1034 if (oldSubFocusItem) {
1035 QQuick3DObject *sfi = scopePrivate->subFocusItem->parentItem();
1036 while (sfi && sfi != scope) {
1037 QQuick3DObjectPrivate::get(sfi)->subFocusItem =
nullptr;
1038 sfi = sfi->parentItem();
1043 scopePrivate->subFocusItem = q;
1044 QQuick3DObject *sfi = scopePrivate->subFocusItem->parentItem();
1045 while (sfi && sfi != scope) {
1046 QQuick3DObjectPrivate::get(sfi)->subFocusItem = q;
1047 sfi = sfi->parentItem();
1050 scopePrivate->subFocusItem =
nullptr;
1054void QQuick3DObjectPrivate::itemChange(QQuick3DObject::ItemChange change,
const QQuick3DObject::ItemChangeData &data)
1056 Q_Q(QQuick3DObject);
1058 case QQuick3DObject::ItemRotationHasChanged:
1060 qWarning(
"ItemRoationHasChange is unhandled!!!!");
1062 case QQuick3DObject::ItemChildAddedChange: {
1063 q->itemChange(change, data);
1064 if (!changeListeners.isEmpty()) {
1065 const auto listeners = changeListeners;
1066 for (
const QQuick3DObjectPrivate::ChangeListener &change : listeners) {
1067 if (change.types & QQuick3DObjectPrivate::Children) {
1068 change.listener->itemChildAdded(q, data.item);
1074 case QQuick3DObject::ItemChildRemovedChange: {
1075 q->itemChange(change, data);
1076 if (!changeListeners.isEmpty()) {
1077 const auto listeners = changeListeners;
1078 for (
const QQuick3DObjectPrivate::ChangeListener &change : listeners) {
1079 if (change.types & QQuick3DObjectPrivate::Children) {
1080 change.listener->itemChildRemoved(q, data.item);
1086 case QQuick3DObject::ItemSceneChange:
1087 q->itemChange(change, data);
1089 case QQuick3DObject::ItemVisibleHasChanged: {
1090 q->itemChange(change, data);
1091 if (!changeListeners.isEmpty()) {
1092 const auto listeners = changeListeners;
1093 for (
const QQuick3DObjectPrivate::ChangeListener &change : listeners) {
1094 if (change.types & QQuick3DObjectPrivate::Visibility) {
1095 change.listener->itemVisibilityChanged(q);
1101 case QQuick3DObject::ItemEnabledHasChanged: {
1102 q->itemChange(change, data);
1103 if (!changeListeners.isEmpty()) {
1104 const auto listeners = changeListeners;
1105 for (
const QQuick3DObjectPrivate::ChangeListener &change : listeners) {
1106 if (change.types & QQuick3DObjectPrivate::Enabled) {
1107 change.listener->itemEnabledChanged(q);
1113 case QQuick3DObject::ItemParentHasChanged: {
1114 q->itemChange(change, data);
1115 if (!changeListeners.isEmpty()) {
1116 const auto listeners = changeListeners;
1117 for (
const QQuick3DObjectPrivate::ChangeListener &change : listeners) {
1118 if (change.types & QQuick3DObjectPrivate::Parent) {
1119 change.listener->itemParentChanged(q, data.item);
1125 case QQuick3DObject::ItemOpacityHasChanged: {
1126 q->itemChange(change, data);
1127 if (!changeListeners.isEmpty()) {
1128 const auto listeners = changeListeners;
1129 for (
const QQuick3DObjectPrivate::ChangeListener &change : listeners) {
1130 if (change.types & QQuick3DObjectPrivate::Opacity) {
1131 change.listener->itemOpacityChanged(q);
1137 case QQuick3DObject::ItemActiveFocusHasChanged:
1138 q->itemChange(change, data);
1140 case QQuick3DObject::ItemAntialiasingHasChanged:
1142 case QQuick3DObject::ItemDevicePixelRatioHasChanged:
1143 q->itemChange(change, data);