I have a Scene3D
where I dynamically add an entity which has an ObjectPicker
, via this helper class' Scene3DViewHelper::addCuboid()
slot:
scene3dviewhelper.h:
#ifndef SCENE3DVIEWHELPER_H
#define SCENE3DVIEWHELPER_H
#include <Qt3DCore/QEntity>
class Scene3DViewHelper : public QObject
{
Q_OBJECT
public:
Q_PROPERTY(Qt3DCore::QEntity * rootEntity READ rootEntity WRITE setRootEntity NOTIFY rootEntityChanged)
explicit Scene3DViewHelper(QObject *parent = nullptr);
Qt3DCore::QEntity * rootEntity() const;
public slots:
void setRootEntity(Qt3DCore::QEntity *rootEntity);
void addCuboid();
signals:
void rootEntityChanged(Qt3DCore::QEntity *rootEntity);
private:
Qt3DCore::QEntity *rootEntity_;
};
#endif // SCENE3DVIEWHELPER_H
scene3dviewhelper.cpp:
#include "scene3dviewhelper.h"
#include <Qt3DCore>
#include <Qt3DRender>
#include <Qt3DExtras>
Scene3DViewHelper::Scene3DViewHelper(QObject *parent) : QObject(parent) {}
Qt3DCore::QEntity * Scene3DViewHelper::rootEntity() const { return rootEntity_; }
void Scene3DViewHelper::setRootEntity(Qt3DCore::QEntity *rootEntity)
{
auto old = rootEntity_;
rootEntity_ = rootEntity;
if(rootEntity_ != old) emit rootEntityChanged(rootEntity);
}
void Scene3DViewHelper::addCuboid()
{
if(!rootEntity_) return;
auto cuboidEntity = new Qt3DCore::QEntity(rootEntity_);
auto mat = new Qt3DExtras::QPhongMaterial(cuboidEntity);
mat->setDiffuse(QColor(217, 217, 255));
auto t = new Qt3DCore::QTransform(cuboidEntity);
auto mesh = new Qt3DExtras::QCuboidMesh(cuboidEntity);
auto picker = new Qt3DRender::QObjectPicker(cuboidEntity);
connect(picker, &Qt3DRender::QObjectPicker::clicked, [=] {
qDebug() << "clicked entity" << cuboidEntity;
});
mesh->setXExtent(1);
mesh->setYExtent(1);
mesh->setZExtent(1);
cuboidEntity->addComponent(mat);
cuboidEntity->addComponent(t);
cuboidEntity->addComponent(mesh);
cuboidEntity->addComponent(picker);
}
Scene3DView.qml:
import QtQuick.Scene3D 2.0
import Qt3D.Core 2.0
import Qt3D.Render 2.14
import Qt3D.Input 2.0
import Qt3D.Logic 2.0
import Qt3D.Extras 2.0
import Qt3DUtils 1.0
Scene3D {
id: scene3d
aspects: ["render", "logic", "input"]
hoverEnabled: true // needed for ObjectPickers to handle hover events
property alias helper: helper
data: Scene3DViewHelper {
id: helper
rootEntity: rootEntity
}
entity: Entity {
id: rootEntity
components: [
RenderSettings {
ForwardRenderer {
id: forwardRenderer
camera: mainCamera
}
pickingSettings.pickMethod: PickingSettings.TrianglePicking
pickingSettings.pickResultMode: PickingSettings.AllPicks
pickingSettings.faceOrientationPickingMode: PickingSettings.FrontAndBackFace
},
InputSettings {}
]
Camera {
id: mainCamera
projectionType: CameraLens.PerspectiveProjection
fieldOfView: 45
aspectRatio: 16/9
nearPlane : 0.1
farPlane : 1000.0
position: Qt.vector3d(0.0, 0.0, -4.0)
upVector: Qt.vector3d(0.0, 1.0, 0.0)
viewCenter: Qt.vector3d(0.0, 0.5, 0.0)
}
/*Entity {
id: cuboid0
components: [
CuboidMesh {
xExtent: 1
yExtent: 1
zExtent: 1
},
Transform {
translation.x: -1.5
},
PhongMaterial {
diffuse: Qt.rgba(0.85, 0.85, 1, 1)
},
ObjectPicker {
onClicked: console.log("clicked entity", cuboid0)
}
]
}*/
}
}
main.qml:
import QtQuick.Window 2.13 as QtQuick
ApplicationWindow {
id: mainWindow
visible: true
width: 1000
height: 700
MainMenu {
onAddCuboid: scene3d.helper.addCuboid()
}
Scene3DView {
id: scene3d
anchors.fill: parent
}
}
main.cpp:
#include <QApplication>
#include <QQmlApplicationEngine>
#include "scene3dviewhelper.h"
int main(int argc, char *argv[])
{
QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
QApplication app(argc, argv);
qmlRegisterType<Scene3DViewHelper>("Qt3DUtils", 1, 0, "Scene3DViewHelper");
const QUrl mainUrl(QStringLiteral("qrc:/main.qml"));
QQmlApplicationEngine engine;
QObject::connect(&engine, &QQmlApplicationEngine::objectCreated,
&app, [&](QObject *obj, const QUrl &objUrl) {
if(!obj && mainUrl == objUrl)
QCoreApplication::exit(-1);
}, Qt::QueuedConnection);
engine.load(mainUrl);
return app.exec();
}
The problem is that the ObjectPicker
doesn't work: I'm supposed to see the "clicked entity Qt3DCore::QEntity(0x7fa19f005300)" message on the console when I click the cuboid, but I don't see it.
If I uncomment the cuboid0
entity, then picking works both for the cuboid0
entity and for the dynamically created cuboid:
qml: clicked entity Qt3DCore::Quick::Quick3DEntity(0x7fa0d7c025e0)
clicked entity Qt3DCore::QEntity(0x7fa0d6527f10)
What does creating the Entity in QML do that I don't do in void Scene3DViewHelper::addCuboid()
?
pressed
signal too? Usingconnect(picker, &Qt3DRender::QObjectPicker::pressed, ...);
– Autolycuspressed
is not received if the static (cuboid0) entity is not present. Strangely, if cuboid0 is present,pressed
is received twice on the dynamically created entity. – Willifordenabled: false
, and picking will work on the dynamically created entity. – Williford5.12.7
and see if behavior is the same. – AutolycushoverEnabled: true
makes the issue go away – Williford