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)
902 Q_ASSERT(sceneManager ==
nullptr || sceneRefCount > 0);
903 if (++sceneRefCount > 1 && sceneManager !=
nullptr) {
905 if (c.window() != sceneManager->window()) {
906 qWarning(
"QSSGObject: Cannot use same item on different windows at the same time.");
911 if (&c != sceneManager) {
912 sharedResource =
true;
913 for (
int ii = 0; ii < childItems.size(); ++ii) {
914 QQuick3DObject *child = childItems.at(ii);
915 QQuick3DObjectPrivate::get(child)->sharedResource = sharedResource;
916 QQuick3DObjectPrivate::refSceneManager(child, c);
923 Q_ASSERT(sceneManager ==
nullptr);
927 sceneManager->parentlessItems.insert(q);
929 sharedResource = QQuick3DObjectPrivate::get(parentItem)->sharedResource;
931 for (
int ii = 0; ii < childItems.size(); ++ii) {
932 QQuick3DObject *child = childItems.at(ii);
933 QQuick3DObjectPrivate::get(child)->sharedResource = sharedResource;
934 QQuick3DObjectPrivate::refSceneManager(child, c);
939 itemChange(QQuick3DObject::ItemSceneChange, &c);
942void QQuick3DObjectPrivate::derefSceneManager()
949 if (--sceneRefCount > 0)
952 removeFromDirtyList();
954 sceneManager->dirtyBoundingBoxList.removeAll(q);
956 for (
int ii = 0; ii < childItems.size(); ++ii) {
957 QQuick3DObject *child = childItems.at(ii);
958 QQuick3DObjectPrivate::derefSceneManager(child);
962 sceneManager->parentlessItems.remove(q);
965 sceneManager->cleanup(spatialNode);
966 spatialNode =
nullptr;
969 sceneManager =
nullptr;
973 itemChange(QQuick3DObject::ItemSceneChange, sceneManager.data());
976void QQuick3DObjectPrivate::updateSubFocusItem(QQuick3DObject *scope,
bool focus)
981 QQuick3DObjectPrivate *scopePrivate = QQuick3DObjectPrivate::get(scope);
983 QQuick3DObject *oldSubFocusItem = scopePrivate->subFocusItem;
985 if (oldSubFocusItem) {
986 QQuick3DObject *sfi = scopePrivate->subFocusItem->parentItem();
987 while (sfi && sfi != scope) {
988 QQuick3DObjectPrivate::get(sfi)->subFocusItem =
nullptr;
989 sfi = sfi->parentItem();
994 scopePrivate->subFocusItem = q;
995 QQuick3DObject *sfi = scopePrivate->subFocusItem->parentItem();
996 while (sfi && sfi != scope) {
997 QQuick3DObjectPrivate::get(sfi)->subFocusItem = q;
998 sfi = sfi->parentItem();
1001 scopePrivate->subFocusItem =
nullptr;
1005void QQuick3DObjectPrivate::itemChange(QQuick3DObject::ItemChange change,
const QQuick3DObject::ItemChangeData &data)
1007 Q_Q(QQuick3DObject);
1009 case QQuick3DObject::ItemRotationHasChanged:
1011 qWarning(
"ItemRoationHasChange is unhandled!!!!");
1013 case QQuick3DObject::ItemChildAddedChange: {
1014 q->itemChange(change, data);
1015 if (!changeListeners.isEmpty()) {
1016 const auto listeners = changeListeners;
1017 for (
const QQuick3DObjectPrivate::ChangeListener &change : listeners) {
1018 if (change.types & QQuick3DObjectPrivate::Children) {
1019 change.listener->itemChildAdded(q, data.item);
1025 case QQuick3DObject::ItemChildRemovedChange: {
1026 q->itemChange(change, data);
1027 if (!changeListeners.isEmpty()) {
1028 const auto listeners = changeListeners;
1029 for (
const QQuick3DObjectPrivate::ChangeListener &change : listeners) {
1030 if (change.types & QQuick3DObjectPrivate::Children) {
1031 change.listener->itemChildRemoved(q, data.item);
1037 case QQuick3DObject::ItemSceneChange:
1038 q->itemChange(change, data);
1040 case QQuick3DObject::ItemVisibleHasChanged: {
1041 q->itemChange(change, data);
1042 if (!changeListeners.isEmpty()) {
1043 const auto listeners = changeListeners;
1044 for (
const QQuick3DObjectPrivate::ChangeListener &change : listeners) {
1045 if (change.types & QQuick3DObjectPrivate::Visibility) {
1046 change.listener->itemVisibilityChanged(q);
1052 case QQuick3DObject::ItemEnabledHasChanged: {
1053 q->itemChange(change, data);
1054 if (!changeListeners.isEmpty()) {
1055 const auto listeners = changeListeners;
1056 for (
const QQuick3DObjectPrivate::ChangeListener &change : listeners) {
1057 if (change.types & QQuick3DObjectPrivate::Enabled) {
1058 change.listener->itemEnabledChanged(q);
1064 case QQuick3DObject::ItemParentHasChanged: {
1065 q->itemChange(change, data);
1066 if (!changeListeners.isEmpty()) {
1067 const auto listeners = changeListeners;
1068 for (
const QQuick3DObjectPrivate::ChangeListener &change : listeners) {
1069 if (change.types & QQuick3DObjectPrivate::Parent) {
1070 change.listener->itemParentChanged(q, data.item);
1076 case QQuick3DObject::ItemOpacityHasChanged: {
1077 q->itemChange(change, data);
1078 if (!changeListeners.isEmpty()) {
1079 const auto listeners = changeListeners;
1080 for (
const QQuick3DObjectPrivate::ChangeListener &change : listeners) {
1081 if (change.types & QQuick3DObjectPrivate::Opacity) {
1082 change.listener->itemOpacityChanged(q);
1088 case QQuick3DObject::ItemActiveFocusHasChanged:
1089 q->itemChange(change, data);
1091 case QQuick3DObject::ItemAntialiasingHasChanged:
1093 case QQuick3DObject::ItemDevicePixelRatioHasChanged:
1094 q->itemChange(change, data);