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);
917 sceneManager->parentlessItems.insert(q);
919 sharedResource = QQuick3DObjectPrivate::get(parentItem)->sharedResource;
921 for (
int ii = 0; ii < childItems.size(); ++ii) {
922 QQuick3DObject *child = childItems.at(ii);
923 QQuick3DObjectPrivate::get(child)->sharedResource = sharedResource;
924 QQuick3DObjectPrivate::refSceneManager(child, c);
929 itemChange(QQuick3DObject::ItemSceneChange, &c);
932void QQuick3DObjectPrivate::derefSceneManager()
939 if (--sceneRefCount > 0)
942 removeFromDirtyList();
944 sceneManager->dirtyBoundingBoxList.removeAll(q);
946 for (
int ii = 0; ii < childItems.size(); ++ii) {
947 QQuick3DObject *child = childItems.at(ii);
948 QQuick3DObjectPrivate::derefSceneManager(child);
952 sceneManager->parentlessItems.remove(q);
955 sceneManager->cleanup(spatialNode);
956 spatialNode =
nullptr;
959 sceneManager =
nullptr;
963 itemChange(QQuick3DObject::ItemSceneChange, sceneManager.data());
966void QQuick3DObjectPrivate::updateSubFocusItem(QQuick3DObject *scope,
bool focus)
971 QQuick3DObjectPrivate *scopePrivate = QQuick3DObjectPrivate::get(scope);
973 QQuick3DObject *oldSubFocusItem = scopePrivate->subFocusItem;
975 if (oldSubFocusItem) {
976 QQuick3DObject *sfi = scopePrivate->subFocusItem->parentItem();
977 while (sfi && sfi != scope) {
978 QQuick3DObjectPrivate::get(sfi)->subFocusItem =
nullptr;
979 sfi = sfi->parentItem();
984 scopePrivate->subFocusItem = q;
985 QQuick3DObject *sfi = scopePrivate->subFocusItem->parentItem();
986 while (sfi && sfi != scope) {
987 QQuick3DObjectPrivate::get(sfi)->subFocusItem = q;
988 sfi = sfi->parentItem();
991 scopePrivate->subFocusItem =
nullptr;
995void QQuick3DObjectPrivate::itemChange(QQuick3DObject::ItemChange change,
const QQuick3DObject::ItemChangeData &data)
999 case QQuick3DObject::ItemRotationHasChanged:
1001 qWarning(
"ItemRoationHasChange is unhandled!!!!");
1003 case QQuick3DObject::ItemChildAddedChange: {
1004 q->itemChange(change, data);
1005 if (!changeListeners.isEmpty()) {
1006 const auto listeners = changeListeners;
1007 for (
const QQuick3DObjectPrivate::ChangeListener &change : listeners) {
1008 if (change.types & QQuick3DObjectPrivate::Children) {
1009 change.listener->itemChildAdded(q, data.item);
1015 case QQuick3DObject::ItemChildRemovedChange: {
1016 q->itemChange(change, data);
1017 if (!changeListeners.isEmpty()) {
1018 const auto listeners = changeListeners;
1019 for (
const QQuick3DObjectPrivate::ChangeListener &change : listeners) {
1020 if (change.types & QQuick3DObjectPrivate::Children) {
1021 change.listener->itemChildRemoved(q, data.item);
1027 case QQuick3DObject::ItemSceneChange:
1028 q->itemChange(change, data);
1030 case QQuick3DObject::ItemVisibleHasChanged: {
1031 q->itemChange(change, data);
1032 if (!changeListeners.isEmpty()) {
1033 const auto listeners = changeListeners;
1034 for (
const QQuick3DObjectPrivate::ChangeListener &change : listeners) {
1035 if (change.types & QQuick3DObjectPrivate::Visibility) {
1036 change.listener->itemVisibilityChanged(q);
1042 case QQuick3DObject::ItemEnabledHasChanged: {
1043 q->itemChange(change, data);
1044 if (!changeListeners.isEmpty()) {
1045 const auto listeners = changeListeners;
1046 for (
const QQuick3DObjectPrivate::ChangeListener &change : listeners) {
1047 if (change.types & QQuick3DObjectPrivate::Enabled) {
1048 change.listener->itemEnabledChanged(q);
1054 case QQuick3DObject::ItemParentHasChanged: {
1055 q->itemChange(change, data);
1056 if (!changeListeners.isEmpty()) {
1057 const auto listeners = changeListeners;
1058 for (
const QQuick3DObjectPrivate::ChangeListener &change : listeners) {
1059 if (change.types & QQuick3DObjectPrivate::Parent) {
1060 change.listener->itemParentChanged(q, data.item);
1066 case QQuick3DObject::ItemOpacityHasChanged: {
1067 q->itemChange(change, data);
1068 if (!changeListeners.isEmpty()) {
1069 const auto listeners = changeListeners;
1070 for (
const QQuick3DObjectPrivate::ChangeListener &change : listeners) {
1071 if (change.types & QQuick3DObjectPrivate::Opacity) {
1072 change.listener->itemOpacityChanged(q);
1078 case QQuick3DObject::ItemActiveFocusHasChanged:
1079 q->itemChange(change, data);
1081 case QQuick3DObject::ItemAntialiasingHasChanged:
1083 case QQuick3DObject::ItemDevicePixelRatioHasChanged:
1084 q->itemChange(change, data);