Qt 6.x
The Qt SDK
Loading...
Searching...
No Matches
qquick3dviewport.cpp
Go to the documentation of this file.
1// Copyright (C) 2019 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
3
7#include "qquick3dtexture_p.h"
10#include "qquick3dcamera_p.h"
11#include "qquick3dmodel_p.h"
13#include "qquick3ditem2d_p.h"
18
19#include <QtQuick3DRuntimeRender/private/qssgrenderlayer_p.h>
20#include <QtQuick3DRuntimeRender/private/qssglayerrenderdata_p.h>
21
22#include <QtQuick3DUtils/private/qssgassert_p.h>
23
24#include <qsgtextureprovider.h>
25#include <QSGSimpleTextureNode>
26#include <QSGRendererInterface>
27#include <QQuickWindow>
28#include <QtQuick/private/qquickitem_p.h>
29#include <QtQuick/private/qquickpointerhandler_p.h>
30
31#include <QtQml>
32
33#include <QtGui/private/qeventpoint_p.h>
34
35#include <QtCore/private/qnumeric_p.h>
36
37#include <optional>
38
40
41Q_LOGGING_CATEGORY(lcEv, "qt.quick3d.event")
42Q_LOGGING_CATEGORY(lcPick, "qt.quick3d.pick")
43Q_LOGGING_CATEGORY(lcHover, "qt.quick3d.hover")
44
46{
47 static const bool v = (qEnvironmentVariableIntValue("QT_QUICK3D_FORCE_INPUT_HANDLING") > 0);
48 return v;
49}
50
52{
53 static void removeAll() {
54 for (auto o : owners) {
55 if (!o.isNull())
56 o->setSceneTransform(nullptr);
57 }
58 owners.clear();
59 }
60
62 da->setSceneTransform(this);
63 owners.append(da);
64 }
65
66 /*
67 Transforms viewport coordinates to 2D scene coordinates.
68 Returns the point in targetItem corresponding to \a viewportPoint,
69 assuming that targetItem is mapped onto sceneParentNode.
70 If it's no longer a "hit" on sceneParentNode, returns the last-good point.
71 */
72 QPointF map(const QPointF &viewportPoint) override {
73 std::optional<QSSGRenderRay> rayResult = renderer->getRayFromViewportPos(viewportPoint * dpr);
74 if (rayResult.has_value()) {
75 auto pickResult = renderer->syncPickOne(rayResult.value(), sceneParentNode);
76 auto ret = pickResult.m_localUVCoords.toPointF();
77 if (!uvCoordsArePixels) {
78 ret = QPointF(targetItem->x() + ret.x() * targetItem->width(),
79 targetItem->y() - ret.y() * targetItem->height() + targetItem->height());
80 }
81 const bool outOfModel = pickResult.m_localUVCoords.isNull();
82 qCDebug(lcEv) << viewportPoint << "->" << (outOfModel ? "OOM" : "") << ret << "@" << pickResult.m_scenePosition
83 << "UV" << pickResult.m_localUVCoords << "dist" << qSqrt(pickResult.m_distanceSq);
84 if (outOfModel) {
85 return lastGoodMapping;
86 } else {
88 return ret;
89 }
90 }
91 return QPointF();
92 }
93
98 bool uvCoordsArePixels = false; // if false, they are in the range 0..1
100
102};
103
105
107{
108 Q_DISABLE_COPY_MOVE(QQuick3DExtensionListHelper);
109public:
111 {
112 QSSG_ASSERT(list && extension, return);
113
114 if (QQuick3DViewport *that = qobject_cast<QQuick3DViewport *>(list->object)) {
115 if (const auto idx = that->m_extensions.indexOf(extension); idx == -1) {
116 if (!extension->parentItem())
117 extension->setParentItem(that->m_sceneRoot);
118 that->m_extensions.push_back(extension);
119 that->m_extensionListDirty = true;
120 }
121 }
122 }
124 {
125 QQuick3DObject *ret = nullptr;
126 QSSG_ASSERT(list, return ret);
127
128 if (QQuick3DViewport *that = qobject_cast<QQuick3DViewport *>(list->object)) {
129 if (that->m_extensions.size() > index)
130 ret = that->m_extensions.at(index);
131 }
132
133 return ret;
134 }
136 {
137 qsizetype ret = -1;
138 QSSG_ASSERT(list, return ret);
139
140 if (QQuick3DViewport *that = qobject_cast<QQuick3DViewport *>(list->object))
141 ret = that->m_extensions.size();
142
143 return ret;
144 }
146 {
147 QSSG_ASSERT(list, return);
148
149 if (QQuick3DViewport *that = qobject_cast<QQuick3DViewport *>(list->object)) {
150 that->m_extensions.clear();
151 that->m_extensionListDirty = true;
152 }
153 }
155 {
156 QSSG_ASSERT(list, return);
157
158 if (QQuick3DViewport *that = qobject_cast<QQuick3DViewport *>(list->object)) {
159 if (that->m_extensions.size() > idx && idx > -1) {
160 that->m_extensions.replace(idx, o);
161 that->m_extensionListDirty = true;
162 }
163 }
164 }
166 {
167 QSSG_ASSERT(list, return);
168
169 if (QQuick3DViewport *that = qobject_cast<QQuick3DViewport *>(list->object)) {
170 that->m_extensions.removeLast();
171 that->m_extensionListDirty = true;
172 }
173 }
174};
175
232{
234 m_camera = nullptr;
235 m_sceneRoot = new QQuick3DSceneRootNode(this);
236 m_environment = new QQuick3DSceneEnvironment(m_sceneRoot);
237 m_renderStats = new QQuick3DRenderStats();
238 QQuick3DSceneManager *sceneManager = new QQuick3DSceneManager();
239 QQuick3DObjectPrivate::get(m_sceneRoot)->refSceneManager(*sceneManager);
240 Q_ASSERT(sceneManager == QQuick3DObjectPrivate::get(m_sceneRoot)->sceneManager);
242 this, &QQuickItem::update);
243
244 // Overrides the internal input handling to always be true
245 // instead of potentially updated after a sync (see updatePaintNode)
247 m_enableInputProcessing = true;
248 updateInputProcessing();
250 }
251}
252
254{
255 // If the quick window still exists, make sure to disconnect any of the direct
256 // connections to this View3D
257 if (auto qw = window())
258 disconnect(qw, nullptr, this, nullptr);
259
260 auto sceneManager = QQuick3DObjectPrivate::get(m_sceneRoot)->sceneManager;
261 if (sceneManager) {
262 sceneManager->setParent(nullptr);
263 if (auto wa = sceneManager->wattached)
264 wa->queueForCleanup(sceneManager);
265 }
266
267 delete m_sceneRoot;
268 m_sceneRoot = nullptr;
269
270 // m_renderStats is tightly coupled with the render thread, so can't delete while we
271 // might still be rendering.
272 m_renderStats->deleteLater();
273
274 // m_directRenderer must be destroyed on the render thread at the proper time, not here.
275 // That's handled in releaseResources() + upon sceneGraphInvalidated
276}
277
279{
280 if (!obj)
281 return;
282 QQuick3DViewport *view3d = static_cast<QQuick3DViewport *>(property->object);
283
284 if (QQuick3DObject *sceneObject = qmlobject_cast<QQuick3DObject *>(obj)) {
286 itemProperty.append(&itemProperty, sceneObject);
287 } else {
289 }
290}
291
293{
294 QQuick3DViewport *view3d = static_cast<QQuick3DViewport *>(property->object);
295 if (!view3d || !view3d->scene() || !QQuick3DObjectPrivate::get(view3d->scene())->data().count)
296 return 0;
298 return itemProperty.count(&itemProperty);
299}
300
302{
303 QQuick3DViewport *view3d = static_cast<QQuick3DViewport *>(property->object);
305 return itemProperty.at(&itemProperty, i);
306}
307
309{
310 QQuick3DViewport *view3d = static_cast<QQuick3DViewport *>(property->object);
312 return itemProperty.clear(&itemProperty);
313}
314
315
317{
318 return QQmlListProperty<QObject>(this,
319 nullptr,
322 ssgn_at,
323 ssgn_clear);
324}
325
338{
339 return m_camera;
340}
341
350{
351 return m_environment;
352}
353
363{
364 return m_sceneRoot;
365}
366
380{
381 return m_importScene;
382}
383
428{
429 return m_renderMode;
430}
431
454{
455 return m_renderFormat;
456}
457
468{
469 return m_renderStats;
470}
471
473{
475
476 if (QQuickWindow *qw = window()) {
478 auto rci = wa->rci();
479 if (!rci) {
480 QSGRendererInterface *rif = qw->rendererInterface();
482 QRhi *rhi = static_cast<QRhi *>(rif->getResource(qw, QSGRendererInterface::RhiResource));
483 QSSG_CHECK_X(rhi != nullptr, "No QRhi from QQuickWindow, this cannot happen");
484 // The RenderContextInterface, and the objects owned by it (such
485 // as, the BufferManager) are always per-QQuickWindow, and so per
486 // scenegraph render thread. Hence the association with window.
487 // Multiple View3Ds in the same window can use the same rendering
488 // infrastructure (so e.g. the same QSSGBufferManager), but two
489 // View3D objects in different windows must not, except for certain
490 // components that do not work with and own native graphics
491 // resources (most notably, QSSGShaderLibraryManager - but this
492 // distinction is handled internally by QSSGRenderContextInterface).
493 rci = std::make_shared<QSSGRenderContextInterface>(rhi);
494 wa->setRci(rci);
495
496 // Use DirectConnection to stay on the render thread, if there is one.
498 &QQuick3DViewport::onReleaseCachedResources, Qt::DirectConnection);
499
500 } else {
501 qWarning("The Qt Quick scene is using a rendering method that is not based on QRhi and a 3D graphics API. "
502 "Qt Quick 3D is not functional in such an environment. The View3D item is not going to display anything.");
503 }
504 }
505
506 if (rci)
508 }
509
510 return renderer;
511}
512
514{
515 // We can only be a texture provider if we are rendering to a texture first
516 if (m_renderMode == QQuick3DViewport::Offscreen)
517 return true;
518
519 return false;
520}
521
523{
524 // When Item::layer::enabled == true, QQuickItem will be a texture
525 // provider. In this case we should prefer to return the layer rather
526 // than the fbo texture.
529
530 // We can only be a texture provider if we are rendering to a texture first
531 if (m_renderMode != QQuick3DViewport::Offscreen)
532 return nullptr;
533
534 QQuickWindow *w = window();
535 if (!w) {
536 qWarning("QSSGView3D::textureProvider: can only be queried on the rendering thread of an exposed window");
537 return nullptr;
538 }
539
540 if (!m_node)
541 m_node = new SGFramebufferObjectNode;
542 return m_node;
543}
544
545class CleanupJob : public QRunnable
546{
547public:
549 void run() override { delete m_renderer; }
550private:
551 QQuick3DSGDirectRenderer *m_renderer;
552};
553
555{
556 if (m_directRenderer) {
557 window()->scheduleRenderJob(new CleanupJob(m_directRenderer), QQuickWindow::BeforeSynchronizingStage);
558 m_directRenderer = nullptr;
559 }
560
561 m_node = nullptr;
562}
563
565{
566 delete m_directRenderer;
567 m_directRenderer = nullptr;
568}
569
570void QQuick3DViewport::geometryChange(const QRectF &newGeometry, const QRectF &oldGeometry)
571{
572 QQuickItem::geometryChange(newGeometry, oldGeometry);
573
574 if (newGeometry.size() != oldGeometry.size())
575 update();
576}
577
579{
580 // When changing render modes
581 if (m_renderModeDirty) {
582 if (node) {
583 delete node;
584 node = nullptr;
585 m_node = nullptr;
586 m_renderNode = nullptr;
587 }
588 if (m_directRenderer) {
589 delete m_directRenderer;
590 m_directRenderer = nullptr;
591 }
592 }
593
594 m_renderModeDirty = false;
595
596 switch (m_renderMode) {
597 // Direct rendering
598 case Underlay:
600 case Overlay:
601 setupDirectRenderer(m_renderMode);
602 node = nullptr;
603 break;
604 case Offscreen:
605 node = setupOffscreenRenderer(node);
606 break;
607 case Inline:
608 // QSGRenderNode-based rendering
609 node = setupInlineRenderer(node);
610 break;
611 }
612
614 // Implicitly enable internal input processing if any item2ds are present.
615 const auto inputHandlingEnabled =
617 const auto enable = inputHandlingEnabled > 0;
618 if (m_enableInputProcessing != enable) {
619 m_enableInputProcessing = enable;
620 QMetaObject::invokeMethod(this, "updateInputProcessing", Qt::QueuedConnection);
621 }
622 }
623
624 return node;
625}
626
628{
629 if (change == ItemSceneChange) {
630 if (value.window) {
631 // TODO: if we want to support multiple windows, there has to be a scene manager for
632 // every window.
634 if (m_importScene)
636 m_renderStats->setWindow(value.window);
637 }
638 } else if (change == ItemVisibleHasChanged && isVisible()) {
639 update();
640 }
641}
642
644{
645 if (m_enableInputProcessing && event->isPointerEvent())
646 return internalPick(static_cast<QPointerEvent *>(event));
647 else
648 return QQuickItem::event(event);
649}
650
652{
655}
656
658{
659 if (m_camera == camera)
660 return;
661
662 if (camera && !camera->parentItem())
663 camera->setParentItem(m_sceneRoot);
664 if (camera)
666
668
669 m_camera = camera;
671 update();
672}
673
675{
676 if (m_environment == environment)
677 return;
678
679 m_environment = environment;
680 if (m_environment && !m_environment->parentItem())
681 m_environment->setParentItem(m_sceneRoot);
683 update();
684}
685
687{
688 // ### We may need consider the case where there is
689 // already a scene tree here
690 // FIXME : Only the first importScene is an effective one
691 if (m_importScene)
692 return;
693
694 // FIXME : Check self-import or cross-import
695 // Currently it does not work since importScene qml parsed in a reverse order.
696 QQuick3DNode *scene = inScene;
697 while (scene) {
698 if (m_sceneRoot == scene) {
699 qmlWarning(this) << "Cannot allow self-import or cross-import!";
700 return;
701 }
702
703 QQuick3DSceneRootNode *rn = qobject_cast<QQuick3DSceneRootNode *>(scene);
704 scene = rn ? rn->view3D()->importScene() : nullptr;
705 }
706
707 m_importScene = inScene;
708 if (m_importScene) {
709 auto privateObject = QQuick3DObjectPrivate::get(m_importScene);
710 if (!privateObject->sceneManager) {
711 // If object doesn't already have scene manager, check from its children
712 QQuick3DSceneManager *manager = findChildSceneManager(m_importScene);
713 // If still not found, use the one from the scene root (scenes defined outside of an view3d)
714 if (!manager)
716 if (manager) {
717 manager->setWindow(window());
718 privateObject->refSceneManager(*manager);
719 }
720 // At this point some manager will exist
721 Q_ASSERT(privateObject->sceneManager);
722 }
723
724 connect(privateObject->sceneManager, &QQuick3DSceneManager::needsUpdate,
725 this, &QQuickItem::update);
726
727 QQuick3DNode *scene = inScene;
728 while (scene) {
729 QQuick3DSceneRootNode *rn = qobject_cast<QQuick3DSceneRootNode *>(scene);
730 scene = rn ? rn->view3D()->importScene() : nullptr;
731
732 if (scene) {
735 this, &QQuickItem::update);
736 }
737 }
738 }
739
741 update();
742}
743
745{
746 if (m_renderMode == renderMode)
747 return;
748
749 m_renderMode = renderMode;
750 m_renderModeDirty = true;
752 update();
753}
754
755void QQuick3DViewport::setRenderFormat(QQuickShaderEffectSource::Format format)
756{
757 if (m_renderFormat == format)
758 return;
759
760 m_renderFormat = format;
761 m_renderModeDirty = true;
762 emit renderFormatChanged();
763 update();
764}
765
766
784{
785 if (!m_camera) {
786 qmlWarning(this) << "Cannot resolve view position without a camera assigned!";
787 return QVector3D(0, 0, 0);
788 }
789
790 qreal _width = width();
791 qreal _height = height();
792 if (_width == 0 || _height == 0)
793 return QVector3D(0, 0, 0);
794
795 const QVector3D normalizedPos = m_camera->mapToViewport(scenePos, _width, _height);
796 return normalizedPos * QVector3D(float(_width), float(_height), 1);
797}
798
817{
818 if (!m_camera) {
819 qmlWarning(this) << "Cannot resolve scene position without a camera assigned!";
820 return QVector3D(0, 0, 0);
821 }
822
823 qreal _width = width();
824 qreal _height = height();
825 if (_width == 0 || _height == 0)
826 return QVector3D(0, 0, 0);
827
828 const QVector3D normalizedPos = viewPos / QVector3D(float(_width), float(_height), 1);
829 return m_camera->mapFromViewport(normalizedPos, _width, _height);
830}
831
841{
842 QQuick3DSceneRenderer *renderer = getRenderer();
843 if (!renderer)
844 return QQuick3DPickResult();
845
846 const QPointF position(qreal(x) * window()->effectiveDevicePixelRatio(),
847 qreal(y) * window()->effectiveDevicePixelRatio());
848 std::optional<QSSGRenderRay> rayResult = renderer->getRayFromViewportPos(position);
849 if (!rayResult.has_value())
850 return QQuick3DPickResult();
851
852 return processPickResult(renderer->syncPick(rayResult.value()));
853
854}
855
868QList<QQuick3DPickResult> QQuick3DViewport::pickAll(float x, float y) const
869{
870 QQuick3DSceneRenderer *renderer = getRenderer();
871 if (!renderer)
873
874 const QPointF position(qreal(x) * window()->effectiveDevicePixelRatio(),
875 qreal(y) * window()->effectiveDevicePixelRatio());
876 std::optional<QSSGRenderRay> rayResult = renderer->getRayFromViewportPos(position);
877 if (!rayResult.has_value())
879
880 const auto resultList = renderer->syncPickAll(rayResult.value());
881 QList<QQuick3DPickResult> processedResultList;
882 processedResultList.reserve(resultList.size());
883 for (const auto &result : resultList)
884 processedResultList.append(processPickResult(result));
885
886 return processedResultList;
887}
888
902QQuick3DPickResult QQuick3DViewport::rayPick(const QVector3D &origin, const QVector3D &direction) const
903{
904 QQuick3DSceneRenderer *renderer = getRenderer();
905 if (!renderer)
906 return QQuick3DPickResult();
907
908 const QSSGRenderRay ray(origin, direction);
909
910 return processPickResult(renderer->syncPick(ray));
911}
912
929QList<QQuick3DPickResult> QQuick3DViewport::rayPickAll(const QVector3D &origin, const QVector3D &direction) const
930{
931 QQuick3DSceneRenderer *renderer = getRenderer();
932 if (!renderer)
934
935 const QSSGRenderRay ray(origin, direction);
936
937 const auto resultList = renderer->syncPickAll(ray);
938 QList<QQuick3DPickResult> processedResultList;
939 processedResultList.reserve(resultList.size());
940 for (const auto &result : resultList)
941 processedResultList.append(processPickResult(result));
942
943 return processedResultList;
944}
945
947{
948 internalPick(event, origin, direction);
949}
950
952{
953 return m_lightmapBaker;
954}
955
957{
958 if (!m_lightmapBaker)
959 m_lightmapBaker= new QQuick3DLightmapBaker(this);
960
961 return m_lightmapBaker;
962}
963
968{
969 lightmapBaker()->bake();
970}
971
973{
974 QQuick3DSceneRenderer *renderer = getRenderer();
975 if (!renderer)
976 return;
977
978 renderer->setGlobalPickingEnabled(isEnabled);
979}
980
981void QQuick3DViewport::invalidateSceneGraph()
982{
983 m_node = nullptr;
984}
985
986QQuick3DSceneRenderer *QQuick3DViewport::getRenderer() const
987{
989 if (m_node) {
990 renderer = m_node->renderer;
991 } else if (m_renderNode) {
992 renderer = m_renderNode->renderer;
993 } else if (m_directRenderer) {
994 renderer = m_directRenderer->renderer();
995 }
996 return renderer;
997}
998
999void QQuick3DViewport::updateDynamicTextures()
1000{
1001 // Update QSGDynamicTextures that are used for source textures and Quick items
1002 // Must be called on the render thread.
1003
1004 const auto &sceneManager = QQuick3DObjectPrivate::get(m_sceneRoot)->sceneManager;
1005 for (auto *texture : std::as_const(sceneManager->qsgDynamicTextures))
1006 texture->updateTexture();
1007
1008 QQuick3DNode *scene = m_importScene;
1009 while (scene) {
1010 const auto &importSm = QQuick3DObjectPrivate::get(scene)->sceneManager;
1011 if (importSm != sceneManager) {
1012 for (auto *texture : std::as_const(importSm->qsgDynamicTextures))
1013 texture->updateTexture();
1014 }
1015
1016 // if importScene has another import
1017 QQuick3DSceneRootNode *rn = qobject_cast<QQuick3DSceneRootNode *>(scene);
1018 scene = rn ? rn->view3D()->importScene() : nullptr;
1019 }
1020}
1021
1022QSGNode *QQuick3DViewport::setupOffscreenRenderer(QSGNode *node)
1023{
1024 SGFramebufferObjectNode *n = static_cast<SGFramebufferObjectNode *>(node);
1025
1026 if (!n) {
1027 if (!m_node)
1028 m_node = new SGFramebufferObjectNode;
1029 n = m_node;
1030 }
1031
1032 if (!n->renderer) {
1033 n->window = window();
1034 n->renderer = createRenderer();
1035 if (!n->renderer)
1036 return nullptr;
1037 n->renderer->fboNode = n;
1038 n->quickFbo = this;
1039 connect(window(), SIGNAL(screenChanged(QScreen*)), n, SLOT(handleScreenChange()));
1040 }
1042 QSize desiredFboSize(qMax<int>(minFboSize.width(), width()),
1043 qMax<int>(minFboSize.height(), height()));
1044
1045 n->devicePixelRatio = window()->effectiveDevicePixelRatio();
1046 desiredFboSize *= n->devicePixelRatio;
1047
1048 n->setFiltering(smooth() ? QSGTexture::Linear : QSGTexture::Nearest);
1049 n->setRect(0, 0, width(), height());
1050 if (checkIsVisible() && isComponentComplete()) {
1051 n->renderer->synchronize(this, desiredFboSize, n->devicePixelRatio);
1052 if (n->renderer->m_textureNeedsFlip)
1053 n->setTextureCoordinatesTransform(QSGSimpleTextureNode::MirrorVertically);
1054 updateDynamicTextures();
1055 n->scheduleRender();
1056 }
1057
1058 return n;
1059}
1060
1061QSGNode *QQuick3DViewport::setupInlineRenderer(QSGNode *node)
1062{
1063 QQuick3DSGRenderNode *n = static_cast<QQuick3DSGRenderNode *>(node);
1064 if (!n) {
1065 if (!m_renderNode)
1066 m_renderNode = new QQuick3DSGRenderNode;
1067 n = m_renderNode;
1068 }
1069
1070 if (!n->renderer) {
1071 n->window = window();
1072 n->renderer = createRenderer();
1073 if (!n->renderer)
1074 return nullptr;
1075 }
1076
1077 const QSize targetSize = window()->effectiveDevicePixelRatio() * QSize(width(), height());
1078
1079 // checkIsVisible, not isVisible, because, for example, a
1080 // { visible: false; layer.enabled: true } item still needs
1081 // to function normally.
1082 if (checkIsVisible() && isComponentComplete()) {
1083 n->renderer->synchronize(this, targetSize, window()->effectiveDevicePixelRatio());
1084 updateDynamicTextures();
1085 n->markDirty(QSGNode::DirtyMaterial);
1086 }
1087
1088 return n;
1089}
1090
1091
1092void QQuick3DViewport::setupDirectRenderer(RenderMode mode)
1093{
1096 if (!m_directRenderer) {
1097 QQuick3DSceneRenderer *sceneRenderer = createRenderer();
1098 if (!sceneRenderer)
1099 return;
1100 m_directRenderer = new QQuick3DSGDirectRenderer(sceneRenderer, window(), renderMode);
1102 }
1103
1104 const QSizeF targetSize = window()->effectiveDevicePixelRatio() * QSizeF(width(), height());
1105 m_directRenderer->setViewport(QRectF(window()->effectiveDevicePixelRatio() * mapToScene(QPointF(0, 0)), targetSize));
1106 m_directRenderer->setVisibility(isVisible());
1107 if (isVisible()) {
1108 m_directRenderer->renderer()->synchronize(this, targetSize.toSize(), window()->effectiveDevicePixelRatio());
1109 updateDynamicTextures();
1110 m_directRenderer->requestRender();
1111 }
1112}
1113
1114// This is used for offscreen mode since we need to check if
1115// this item is used by an effect but hidden
1116bool QQuick3DViewport::checkIsVisible() const
1117{
1118 auto childPrivate = QQuickItemPrivate::get(this);
1119 return (childPrivate->explicitVisible ||
1120 (childPrivate->extra.isAllocated() && childPrivate->extra->effectRefCount));
1121
1122}
1123
1133void QQuick3DViewport::processPickedObject(const QSSGRenderGraphObject *backendObject,
1134 const QSSGRenderPickResult &pickResult,
1135 int pointIndex,
1137 QFlatMap<QQuickItem *, SubsceneInfo> &visitedSubscenes) const
1138{
1139 QQuickItem *subsceneRootItem = nullptr;
1140 QPointF subscenePosition;
1141 const auto frontendObject = findFrontendNode(backendObject);
1142 if (!frontendObject)
1143 return;
1144
1145 // Figure out if there are any QQuickItem based scenes we need to forward
1146 // the event to, and if the are found, determine how to translate the UV Coords
1147 // in the pickResult based on what type the object containing the scene is.
1148 auto frontendObjectPrivate = QQuick3DObjectPrivate::get(frontendObject);
1149 if (frontendObjectPrivate->type == QQuick3DObjectPrivate::Type::Item2D) {
1150 // Item2D, this is the case where there is just an embedded Qt Quick 2D Item
1151 // rendered directly to the scene.
1152 auto item2D = qobject_cast<QQuick3DItem2D *>(frontendObject);
1153 if (item2D)
1154 subsceneRootItem = item2D->contentItem();
1155 if (!subsceneRootItem || subsceneRootItem->childItems().isEmpty())
1156 return; // ignore empty 2D subscenes
1157
1158 // In this case the "UV" coordinates are in pixels in the subscene root item, so we can just use them.
1159 subscenePosition = pickResult.m_localUVCoords.toPointF();
1160 // Even though an Item2D is an "infinite plane" for rendering purposes,
1161 // avoid delivering events outside the rectangular area that is occupied by child items,
1162 // so that events can "fall through" to other interactive content in the scene or behind it.
1163 if (!subsceneRootItem->childrenRect().contains(subscenePosition))
1164 return;
1165 } else if (frontendObjectPrivate->type == QQuick3DObjectPrivate::Type::Model) {
1166 // Model
1167 int materialSubset = pickResult.m_subset;
1168 const auto backendModel = static_cast<const QSSGRenderModel *>(backendObject);
1169 // Get material
1170 if (backendModel->materials.size() < (pickResult.m_subset + 1))
1171 materialSubset = backendModel->materials.size() - 1;
1172 if (materialSubset < 0)
1173 return;
1174 const auto backendMaterial = backendModel->materials.at(materialSubset);
1175 const auto frontendMaterial = static_cast<QQuick3DMaterial*>(findFrontendNode(backendMaterial));
1176 subsceneRootItem = getSubSceneRootItem(frontendMaterial);
1177
1178 if (subsceneRootItem) {
1179 // In this case the pick result really is using UV coordinates.
1180 subscenePosition = QPointF(subsceneRootItem->x() + pickResult.m_localUVCoords.x() * subsceneRootItem->width(),
1181 subsceneRootItem->y() - pickResult.m_localUVCoords.y() * subsceneRootItem->height() + subsceneRootItem->height());
1182 }
1183 }
1184
1185 // Add the new event (item and position) to the visitedSubscene map.
1186 if (subsceneRootItem) {
1187 SubsceneInfo &subscene = visitedSubscenes[subsceneRootItem]; // create if not found
1188 subscene.obj = frontendObject;
1189 if (subscene.eventPointScenePositions.size() != event->pointCount()) {
1190 // ensure capacity, and use an out-of-scene position rather than 0,0 by default
1191 constexpr QPointF inf(-qt_inf(), -qt_inf());
1192 subscene.eventPointScenePositions.resize(event->pointCount(), inf);
1193 }
1194 subscene.eventPointScenePositions[pointIndex] = subscenePosition;
1195 }
1196}
1197
1208QQuickItem *QQuick3DViewport::getSubSceneRootItem(QQuick3DMaterial *material) const
1209{
1210 if (!material)
1211 return nullptr;
1212
1213 QQuickItem *subsceneRootItem = nullptr;
1214 const auto frontendMaterialPrivate = QQuick3DObjectPrivate::get(material);
1215
1216 if (frontendMaterialPrivate->type == QQuick3DObjectPrivate::Type::DefaultMaterial) {
1217 // Default Material
1218 const auto defaultMaterial = qobject_cast<QQuick3DDefaultMaterial *>(material);
1219 if (defaultMaterial) {
1220 // Just check for a diffuseMap for now
1221 if (defaultMaterial->diffuseMap() && defaultMaterial->diffuseMap()->sourceItem())
1222 subsceneRootItem = defaultMaterial->diffuseMap()->sourceItem();
1223 }
1224
1225 } else if (frontendMaterialPrivate->type == QQuick3DObjectPrivate::Type::PrincipledMaterial) {
1226 // Principled Material
1227 const auto principledMaterial = qobject_cast<QQuick3DPrincipledMaterial *>(material);
1228 if (principledMaterial) {
1229 // Just check for a baseColorMap for now
1230 if (principledMaterial->baseColorMap() && principledMaterial->baseColorMap()->sourceItem())
1231 subsceneRootItem = principledMaterial->baseColorMap()->sourceItem();
1232 }
1233 } else if (frontendMaterialPrivate->type == QQuick3DObjectPrivate::Type::SpecularGlossyMaterial) {
1234 // SpecularGlossy Material
1235 const auto specularGlossyMaterial = qobject_cast<QQuick3DSpecularGlossyMaterial *>(material);
1236 if (specularGlossyMaterial) {
1237 // Just check for a albedoMap for now
1238 if (specularGlossyMaterial->albedoMap() && specularGlossyMaterial->albedoMap()->sourceItem())
1239 subsceneRootItem = specularGlossyMaterial->albedoMap()->sourceItem();
1240 }
1241 } else if (frontendMaterialPrivate->type == QQuick3DObjectPrivate::Type::CustomMaterial) {
1242 // Custom Material
1243 const auto customMaterial = qobject_cast<QQuick3DCustomMaterial *>(material);
1244 if (customMaterial) {
1245 // This case is a bit harder because we can not know how the textures will be used
1246 const auto &texturesInputs = customMaterial->m_dynamicTextureMaps;
1247 for (const auto &textureInput : texturesInputs) {
1248 if (auto texture = textureInput->texture()) {
1249 if (texture->sourceItem()) {
1250 subsceneRootItem = texture->sourceItem();
1251 break;
1252 }
1253 }
1254 }
1255 }
1256 }
1257 return subsceneRootItem;
1258}
1259
1266bool QQuick3DViewport::forwardEventToSubscenes(QPointerEvent *event,
1267 bool useRayPicking,
1269 const QFlatMap<QQuickItem *, SubsceneInfo> &visitedSubscenes) const
1270{
1271 // Now deliver the entire event (all points) to each relevant subscene.
1272 // Maybe only some points fall inside, but QQuickDeliveryAgentPrivate::deliverMatchingPointsToItem()
1273 // makes reduced-subset touch events that contain only the relevant points, when necessary.
1274 bool ret = false;
1275
1276 QVarLengthArray<QPointF, 16> originalScenePositions;
1277 originalScenePositions.resize(event->pointCount());
1278 for (int pointIndex = 0; pointIndex < event->pointCount(); ++pointIndex)
1279 originalScenePositions[pointIndex] = event->point(pointIndex).scenePosition();
1280 for (auto subscene : visitedSubscenes) {
1281 QQuickItem *subsceneRoot = subscene.first;
1282 auto &subsceneInfo = subscene.second;
1283 Q_ASSERT(subsceneInfo.eventPointScenePositions.size() == event->pointCount());
1284 auto da = QQuickItemPrivate::get(subsceneRoot)->deliveryAgent();
1285 for (int pointIndex = 0; pointIndex < event->pointCount(); ++pointIndex) {
1286 const auto &pt = subsceneInfo.eventPointScenePositions.at(pointIndex);
1287 // By tradition, QGuiApplicationPrivate::processTouchEvent() has set the local position to the scene position,
1288 // and Qt Quick expects it to arrive that way: then QQuickDeliveryAgentPrivate::translateTouchEvent()
1289 // copies it into the scene position before localizing.
1290 // That might be silly, we might change it eventually, but gotta stay consistent for now.
1291 QEventPoint &ep = event->point(pointIndex);
1292 QMutableEventPoint::setPosition(ep, pt);
1293 QMutableEventPoint::setScenePosition(ep, pt);
1294 }
1295
1296 if (event->isBeginEvent())
1297 da->setSceneTransform(nullptr);
1298 if (da->event(event)) {
1299 ret = true;
1300 if (QQuickDeliveryAgentPrivate::anyPointGrabbed(event) && !useRayPicking) {
1301 // In case any QEventPoint was grabbed, the relevant QQuickDeliveryAgent needs to know
1302 // how to repeat the picking/coordinate transformation for each update,
1303 // because delivery will bypass internalPick() due to the grab, and it's
1304 // more efficient to avoid whole-scene picking each time anyway.
1305 auto frontendObjectPrivate = QQuick3DObjectPrivate::get(subsceneInfo.obj);
1306 const bool item2Dcase = (frontendObjectPrivate->type == QQuick3DObjectPrivate::Type::Item2D);
1309 transform->sceneParentNode = static_cast<QSSGRenderNode*>(frontendObjectPrivate->spatialNode);
1310 transform->targetItem = subsceneRoot;
1311 transform->dpr = window()->effectiveDevicePixelRatio();
1312 transform->uvCoordsArePixels = item2Dcase;
1313 transform->setOnDeliveryAgent(da);
1314 qCDebug(lcPick) << event->type() << "created ViewportTransformHelper on" << da;
1315 }
1316 } else if (event->type() != QEvent::HoverMove) {
1317 qCDebug(lcPick) << subsceneRoot << "didn't want" << event;
1318 }
1319 event->setAccepted(false); // reject implicit grab and let it keep propagating
1320 }
1321 if (visitedSubscenes.isEmpty()) {
1322 event->setAccepted(false);
1323 } else {
1324 for (int pointIndex = 0; pointIndex < event->pointCount(); ++pointIndex)
1325 QMutableEventPoint::setScenePosition(event->point(pointIndex), originalScenePositions.at(pointIndex));
1326 }
1327 return ret;
1328}
1329
1330
1331bool QQuick3DViewport::internalPick(QPointerEvent *event, const QVector3D &origin, const QVector3D &direction) const
1332{
1333 QQuick3DSceneRenderer *renderer = getRenderer();
1334 if (!renderer || !event)
1335 return false;
1336
1337 QFlatMap<QQuickItem*, SubsceneInfo> visitedSubscenes;
1338 const bool useRayPicking = !direction.isNull();
1339
1340 for (int pointIndex = 0; pointIndex < event->pointCount(); ++pointIndex) {
1341 auto &eventPoint = event->point(pointIndex);
1343 if (Q_UNLIKELY(useRayPicking))
1344 pickResults = getPickResults(renderer, origin, direction);
1345 else
1346 pickResults = getPickResults(renderer, eventPoint);
1347
1348 if (!pickResults.isEmpty())
1349 for (const auto &pickResult : pickResults)
1350 processPickedObject(pickResult.m_hitObject, pickResult, pointIndex, event, visitedSubscenes);
1351 else
1352 eventPoint.setAccepted(false); // let it fall through the viewport to Items underneath
1353 }
1354
1355 return forwardEventToSubscenes(event, useRayPicking, renderer, visitedSubscenes);
1356}
1357
1359 const QVector3D &origin,
1360 const QVector3D &direction) const
1361{
1362 const QSSGRenderRay ray(origin, direction);
1363 return renderer->syncPickAll(ray);
1364}
1365
1366QVarLengthArray<QSSGRenderPickResult, 20> QQuick3DViewport::getPickResults(QQuick3DSceneRenderer *renderer, const QEventPoint &eventPoint) const
1367{
1369 const QPointF realPosition = eventPoint.position() * window()->effectiveDevicePixelRatio();
1370 std::optional<QSSGRenderRay> rayResult = renderer->getRayFromViewportPos(realPosition);
1371 if (rayResult.has_value())
1372 pickResults = renderer->syncPickAll(rayResult.value());
1373 return pickResults;
1374}
1375
1382QQuick3DObject *QQuick3DViewport::findFrontendNode(const QSSGRenderGraphObject *backendObject) const
1383{
1384 if (!backendObject)
1385 return nullptr;
1386
1387 const auto sceneManager = QQuick3DObjectPrivate::get(m_sceneRoot)->sceneManager;
1388 QQuick3DObject *frontendObject = sceneManager->lookUpNode(backendObject);
1389 if (!frontendObject && m_importScene) {
1390 const auto importSceneManager = QQuick3DObjectPrivate::get(m_importScene)->sceneManager;
1391 frontendObject = importSceneManager->lookUpNode(backendObject);
1392 }
1393 return frontendObject;
1394}
1395
1396QQuick3DPickResult QQuick3DViewport::processPickResult(const QSSGRenderPickResult &pickResult) const
1397{
1398 if (!pickResult.m_hitObject)
1399 return QQuick3DPickResult();
1400
1401 QQuick3DObject *frontendObject = findFrontendNode(pickResult.m_hitObject);
1402
1403 QQuick3DModel *model = qobject_cast<QQuick3DModel *>(frontendObject);
1404 if (!model)
1405 return QQuick3DPickResult();
1406
1408 ::sqrtf(pickResult.m_distanceSq),
1409 pickResult.m_localUVCoords,
1410 pickResult.m_scenePosition,
1411 pickResult.m_localPosition,
1412 pickResult.m_faceNormal,
1413 pickResult.m_instanceIndex);
1414}
1415
1416// Returns the first found scene manager of objects children
1417QQuick3DSceneManager *QQuick3DViewport::findChildSceneManager(QQuick3DObject *inObject, QQuick3DSceneManager *manager)
1418{
1419 if (manager)
1420 return manager;
1421
1423 for (auto child : children) {
1424 if (auto m = QQuick3DObjectPrivate::get(child)->sceneManager) {
1425 manager = m;
1426 break;
1427 }
1428 manager = findChildSceneManager(child, manager);
1429 }
1430 return manager;
1431}
1432
1433void QQuick3DViewport::updateInputProcessing()
1434{
1435 // This should be called from the gui thread.
1436 setAcceptTouchEvents(m_enableInputProcessing);
1437 setAcceptHoverEvents(m_enableInputProcessing);
1438 setAcceptedMouseButtons(m_enableInputProcessing ? Qt::AllButtons : Qt::NoButton);
1439}
1440
1441void QQuick3DViewport::onReleaseCachedResources()
1442{
1443 if (auto renderer = getRenderer())
1444 renderer->releaseCachedResources();
1445}
1446
1451{
1453 &m_extensionListDirty,
1460}
1461
void run() override
Implement this pure virtual function in your subclass.
CleanupJob(QQuick3DSGDirectRenderer *renderer)
The QEventPoint class provides information about a point in a QPointerEvent.
Definition qeventpoint.h:20
QPointF position
the position of this point.
Definition qeventpoint.h:36
\inmodule QtCore
Definition qcoreevent.h:45
@ HoverMove
Definition qcoreevent.h:177
bool isEmpty() const noexcept
Definition qflatmap_p.h:579
Definition qlist.h:74
bool isEmpty() const noexcept
Definition qlist.h:390
void reserve(qsizetype size)
Definition qlist.h:746
void append(parameter_type t)
Definition qlist.h:441
void clear()
Definition qlist.h:417
\inmodule QtCore
Definition qobject.h:90
const QObjectList & children() const
Returns a list of child objects.
Definition qobject.h:171
static QMetaObject::Connection connect(const QObject *sender, const char *signal, const QObject *receiver, const char *member, Qt::ConnectionType=Qt::AutoConnection)
\threadsafe
Definition qobject.cpp:2823
void setParent(QObject *parent)
Makes the object a child of parent.
Definition qobject.cpp:2142
void deleteLater()
\threadsafe
Definition qobject.cpp:2352
\inmodule QtCore\reentrant
Definition qpoint.h:214
A base class for pointer events.
Definition qevent.h:73
The QQmlListProperty class allows applications to expose list-like properties of QObject-derived clas...
Definition qqmllist.h:24
ClearFunction clear
Definition qqmllist.h:87
AtFunction at
Definition qqmllist.h:86
CountFunction count
Definition qqmllist.h:85
AppendFunction append
Definition qqmllist.h:84
Q_INVOKABLE QVector3D mapFromViewport(const QVector3D &viewportPos) const
\qmlmethod vector3d Camera::mapFromViewport(vector3d viewportPos)
void updateGlobalVariables(const QRectF &inViewport)
Q_INVOKABLE QVector3D mapToViewport(const QVector3D &scenePos) const
\qmlmethod vector3d Camera::mapToViewport(vector3d scenePos)
static void extensionClear(QQmlListProperty< QQuick3DObject > *list)
static void extensionReplace(QQmlListProperty< QQuick3DObject > *list, qsizetype idx, QQuick3DObject *o)
static void extensionAppend(QQmlListProperty< QQuick3DObject > *list, QQuick3DObject *extension)
static QQuick3DObject * extensionAt(QQmlListProperty< QQuick3DObject > *list, qsizetype index)
static void extensionRemoveLast(QQmlListProperty< QQuick3DObject > *list)
static qsizetype extensionCount(QQmlListProperty< QQuick3DObject > *list)
void bake(Callback callback)
Triggers a new frame where lightmap baking will take place.
QList< QQuick3DObject * > childItems
QPointer< QQuick3DSceneManager > sceneManager
void refSceneManager(QQuick3DSceneManager &)
static void attachWatcherPriv(SceneContext *sceneContext, CallContext *callContext, Setter setter, QQuick3DObject *newO, QObject *oldO)
static QQuick3DObjectPrivate * get(QQuick3DObject *item)
QQmlListProperty< QObject > data()
\qmltype Object3D \inqmlmodule QtQuick3D \instantiates QQuick3DObject \inherits QtObject
void setParentItem(QQuick3DObject *parentItem)
void setWindow(QQuickWindow *window)
QQuick3DSceneRenderer * renderer()
void setViewport(const QRectF &viewport)
QQuick3DSceneRenderer * renderer
void setWindow(QQuickWindow *window)
static QQuick3DWindowAttachment * getOrSetWindowAttachment(QQuickWindow &window)
QSSGRenderPickResult syncPickOne(const QSSGRenderRay &ray, QSSGRenderNode *node)
void synchronize(QQuick3DViewport *view3D, const QSize &size, float dpr)
std::optional< QSSGRenderRay > getRayFromViewportPos(const QPointF &pos)
QQuick3DViewport * view3D()
void renderModeChanged()
QQuick3DNode * importScene
bool isTextureProvider() const override
Returns true if this item is a texture provider.
QQmlListProperty< QObject > data
void geometryChange(const QRectF &newGeometry, const QRectF &oldGeometry) override
void releaseResources() override
This function is called when an item should release graphics resources which are not already managed ...
QQuick3DLightmapBaker * lightmapBaker()
void processPointerEventFromRay(const QVector3D &origin, const QVector3D &direction, QPointerEvent *event)
void setGlobalPickingEnabled(bool isEnabled)
void setCamera(QQuick3DCamera *camera)
QQuickShaderEffectSource::Format renderFormat
\qmlproperty enumeration QtQuick3D::View3D::renderFormat
void environmentChanged()
void setImportScene(QQuick3DNode *inScene)
void componentComplete() override
Invoked after the root component that caused this instantiation has completed construction.
void setEnvironment(QQuick3DSceneEnvironment *environment)
void itemChange(QQuickItem::ItemChange change, const QQuickItem::ItemChangeData &value) override
Called when change occurs for this item.
Q_INVOKABLE QQuick3DPickResult pick(float x, float y) const
\qmlmethod PickResult View3D::pick(float x, float y)
bool event(QEvent *) override
This virtual function receives events to an object and should return true if the event e was recogniz...
Q_INVOKABLE QVector3D mapTo3DScene(const QVector3D &viewPos) const
\qmlmethod vector3d View3D::mapTo3DScene(vector3d viewPos)
QQuick3DSceneRenderer * createRenderer() const
QSGNode * updatePaintNode(QSGNode *, UpdatePaintNodeData *) override
Called on the render thread when it is time to sync the state of the item with the scene graph.
QSGTextureProvider * textureProvider() const override
Returns the texture provider for an item.
void importSceneChanged()
QQuick3DViewport(QQuickItem *parent=nullptr)
\qmltype View3D \inherits QQuickItem \inqmlmodule QtQuick3D
QQuick3DLightmapBaker * maybeLightmapBaker()
Q_INVOKABLE QVector3D mapFrom3DScene(const QVector3D &scenePos) const
\qmlmethod vector3d View3D::mapFrom3DScene(vector3d scenePos)
void setRenderMode(QQuick3DViewport::RenderMode renderMode)
Q_INVOKABLE void bakeLightmap()
QQuick3DRenderStats * renderStats
QQuick3DNode * scene
QQmlListProperty< QQuick3DObject > extensions
QQuick3DSceneEnvironment * environment
QQuick3DCamera * camera
Q_REVISION(6, 4) void setRenderFormat(QQuickShaderEffectSource void cleanupDirectRenderer()
static bool anyPointGrabbed(const QPointerEvent *ev)
void setSceneTransform(Transform *transform)
QQuickDeliveryAgent * deliveryAgent()
QSGContext * sceneGraphContext() const
static void data_append(QQmlListProperty< QObject > *, QObject *)
static QQuickItemPrivate * get(QQuickItem *item)
The QQuickItem class provides the most basic of all visual items in \l {Qt Quick}.
Definition qquickitem.h:64
QPointF mapToScene(const QPointF &point) const
Maps the given point in this item's coordinate system to the equivalent point within the scene's coor...
bool event(QEvent *) override
\reimp
QList< QQuickItem * > childItems() const
Returns the children of this item.
void setFlag(Flag flag, bool enabled=true)
Enables the specified flag for this item if enabled is true; if enabled is false, the flag is disable...
virtual void geometryChange(const QRectF &newGeometry, const QRectF &oldGeometry)
qreal x
\qmlproperty real QtQuick::Item::x \qmlproperty real QtQuick::Item::y \qmlproperty real QtQuick::Item...
Definition qquickitem.h:73
void componentComplete() override
\reimp Derived classes should call the base class method before adding their own actions to perform a...
void setAcceptHoverEvents(bool enabled)
If enabled is true, this sets the item to accept hover events; otherwise, hover events are not accept...
qreal y
Defines the item's y position relative to its parent.
Definition qquickitem.h:74
void setAcceptTouchEvents(bool accept)
If enabled is true, this sets the item to accept touch events; otherwise, touch events are not accept...
bool isVisible() const
virtual QSGTextureProvider * textureProvider() const
Returns the texture provider for an item.
QRectF childrenRect()
\qmlpropertygroup QtQuick::Item::childrenRect \qmlproperty real QtQuick::Item::childrenRect....
void setAcceptedMouseButtons(Qt::MouseButtons buttons)
Sets the mouse buttons accepted by this item to buttons.
QQuickWindow * window() const
Returns the window in which this item is rendered.
qreal width
This property holds the width of this item.
Definition qquickitem.h:76
bool isComponentComplete() const
Returns true if construction of the QML component is complete; otherwise returns false.
QPointF position() const
bool isEnabled() const
Q_INVOKABLE void forceActiveFocus()
\qmlmethod point QtQuick::Item::mapToItem(Item item, real x, real y) \qmlmethod point QtQuick::Item::...
const QSize & targetSize
Definition qquickitem.h:302
bool smooth
\qmlproperty bool QtQuick::Item::smooth
Definition qquickitem.h:111
qreal height
This property holds the height of this item.
Definition qquickitem.h:77
ItemChange
Used in conjunction with QQuickItem::itemChange() to notify the item about certain types of changes.
Definition qquickitem.h:143
@ ItemVisibleHasChanged
Definition qquickitem.h:147
void update()
Schedules a call to updatePaintNode() for this item.
virtual bool isTextureProvider() const
Returns true if this item is a texture provider.
\qmltype Window \instantiates QQuickWindow \inqmlmodule QtQuick
void sceneGraphInvalidated()
\qmlsignal QtQuick::Window::sceneGraphInitialized()
\inmodule QtCore\reentrant
Definition qrect.h:483
bool contains(const QRectF &r) const noexcept
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition qrect.cpp:1985
constexpr QSizeF size() const noexcept
Returns the size of the rectangle.
Definition qrect.h:721
\inmodule QtCore\reentrant
Definition qrect.h:30
\inmodule QtGui
Definition qrhi.h:1767
\inmodule QtCore
Definition qrunnable.h:18
virtual QSize minimumFBOSize() const
\group qtquick-scenegraph-nodes \title Qt Quick Scene Graph Node classes
Definition qsgnode.h:37
@ DirtyMaterial
Definition qsgnode.h:75
An interface providing access to some of the graphics API specific internals of the scenegraph.
static bool isApiRhiBased(GraphicsApi api)
virtual GraphicsApi graphicsApi() const =0
Returns the graphics API that is in use by the Qt Quick scenegraph.
virtual void * getResource(QQuickWindow *window, Resource resource) const
Queries a graphics resource in window.
The QSGTextureProvider class encapsulates texture based entities in QML.
\inmodule QtQuick
Definition qsgtexture.h:20
The QScreen class is used to query screen properties. \inmodule QtGui.
Definition qscreen.h:32
\inmodule QtCore
Definition qsize.h:207
\inmodule QtCore
Definition qsize.h:25
constexpr int height() const noexcept
Returns the height.
Definition qsize.h:132
constexpr int width() const noexcept
Returns the width.
Definition qsize.h:129
bool isEmpty() const
const T & at(qsizetype idx) const
void resize(qsizetype sz)
constexpr float y() const noexcept
Returns the y coordinate of this point.
Definition qvectornd.h:502
constexpr float x() const noexcept
Returns the x coordinate of this point.
Definition qvectornd.h:501
constexpr QPointF toPointF() const noexcept
Returns the QPointF form of this 2D vector.
Definition qvectornd.h:628
The QVector3D class represents a vector or vertex in 3D space.
Definition qvectornd.h:171
QQuick3DSceneRenderer * renderer
void extension()
[6]
Definition dialogs.cpp:230
QCamera * camera
Definition camera.cpp:19
list append(new Employee("Blackpool", "Stephen"))
direction
Combined button and popup list for selecting options.
@ AllButtons
Definition qnamespace.h:89
@ NoButton
Definition qnamespace.h:56
@ QueuedConnection
@ DirectConnection
#define Q_FALLTHROUGH()
#define Q_UNLIKELY(x)
static int pick(bool vertical, const QSize &size)
EGLOutputLayerEXT EGLint EGLAttrib value
[5]
qfloat16 qSqrt(qfloat16 f)
Definition qfloat16.h:243
#define qWarning
Definition qlogging.h:162
#define Q_LOGGING_CATEGORY(name,...)
#define qCDebug(category,...)
return ret
constexpr static Q_DECL_CONST_FUNCTION double qt_inf() noexcept
Definition qnumeric_p.h:77
#define SLOT(a)
Definition qobjectdefs.h:51
#define SIGNAL(a)
Definition qobjectdefs.h:52
GLsizei const GLfloat * v
[13]
GLint GLint GLint GLint GLint x
[0]
GLenum mode
const GLfloat * m
GLfloat GLfloat GLfloat w
[0]
GLint GLsizei GLsizei height
GLuint index
[2]
GLint GLsizei width
GLboolean enable
GLenum GLuint texture
GLfloat n
GLint GLsizei GLsizei GLenum format
GLint y
struct _cl_event * event
GLuint GLenum GLenum transform
GLhandleARB obj
[2]
GLuint64EXT * result
[6]
Q_QML_EXPORT QQmlInfo qmlWarning(const QObject *me)
#define Q_QUICK3D_PROFILE_REGISTER(obj)
static QT_BEGIN_NAMESPACE bool isforceInputHandlingSet()
static qsizetype ssgn_count(QQmlListProperty< QObject > *property)
static QObject * ssgn_at(QQmlListProperty< QObject > *property, qsizetype i)
static void ssgn_append(QQmlListProperty< QObject > *property, QObject *obj)
static void ssgn_clear(QQmlListProperty< QObject > *property)
#define Q_ASSERT(cond)
Definition qrandom.cpp:47
#define QSSG_CHECK_X(cond, msg)
#define QSSG_ASSERT(cond, action)
#define QSSG_GUARD(cond)
Q_CORE_EXPORT int qEnvironmentVariableIntValue(const char *varName, bool *ok=nullptr) noexcept
#define emit
ptrdiff_t qsizetype
Definition qtypes.h:70
double qreal
Definition qtypes.h:92
const char property[13]
Definition qwizard.cpp:101
QSqlQueryModel * model
[16]
QList< int > list
[14]
myObject disconnect()
[26]
QLayoutItem * child
[0]
QNetworkAccessManager manager
QSvgRenderer * renderer
[0]
static bool invokeMethod(QObject *obj, const char *member, Qt::ConnectionType, QGenericReturnArgument ret, QGenericArgument val0=QGenericArgument(nullptr), QGenericArgument val1=QGenericArgument(), QGenericArgument val2=QGenericArgument(), QGenericArgument val3=QGenericArgument(), QGenericArgument val4=QGenericArgument(), QGenericArgument val5=QGenericArgument(), QGenericArgument val6=QGenericArgument(), QGenericArgument val7=QGenericArgument(), QGenericArgument val8=QGenericArgument(), QGenericArgument val9=QGenericArgument())
\threadsafe This is an overloaded member function, provided for convenience. It differs from the abov...
QVector< QSSGRenderGraphObject * > materials
const QSSGRenderGraphObject * m_hitObject
QPointF map(const QPointF &viewportPoint) override
void setOnDeliveryAgent(QQuickDeliveryAgent *da)
static QList< QPointer< QQuickDeliveryAgent > > owners
QSSGRenderNode * sceneParentNode
QQuick3DSceneRenderer * renderer
IUIAutomationTreeWalker __RPC__deref_out_opt IUIAutomationElement ** parent
\inmodule QtQuick
Definition qquickitem.h:158